diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 |
commit | 5ca98fd98791947eba83a1ed3f2c8191ef7afa6c (patch) | |
tree | f5944309621cee4fe0976be6f9ac619b7ebfc4c2 /include | |
parent | 68bcb7db193e4bc81430063148253d30a791023e (diff) | |
download | src-5ca98fd98791947eba83a1ed3f2c8191ef7afa6c.tar.gz src-5ca98fd98791947eba83a1ed3f2c8191ef7afa6c.zip |
Vendor import of llvm RELEASE_350/final tag r216957 (effectively, 3.5.0 release):vendor/llvm/llvm-release_350-r216957
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=274955
svn path=/vendor/llvm/llvm-release_35-r216957/; revision=274956; tag=vendor/llvm/llvm-release_350-r216957
Diffstat (limited to 'include')
521 files changed, 33594 insertions, 16668 deletions
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 9953d52edd62..fdff77bc5e51 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -15,7 +15,7 @@ #ifndef LLVM_C_CORE_H #define LLVM_C_CORE_H -#include "llvm/Support/DataTypes.h" +#include "llvm-c/Support.h" #ifdef __cplusplus extern "C" { @@ -62,8 +62,6 @@ extern "C" { * @{ */ -typedef int LLVMBool; - /* Opaque types. */ /** @@ -114,13 +112,6 @@ typedef struct LLVMOpaqueBuilder *LLVMBuilderRef; */ typedef struct LLVMOpaqueModuleProvider *LLVMModuleProviderRef; -/** - * Used to provide a module to JIT or interpreter. - * - * @see llvm::MemoryBuffer - */ -typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; - /** @see llvm::PassManagerBase */ typedef struct LLVMOpaquePassManager *LLVMPassManagerRef; @@ -133,6 +124,12 @@ typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef; * @see llvm::Use */ typedef struct LLVMOpaqueUse *LLVMUseRef; + +/** + * @see llvm::DiagnosticInfo + */ +typedef struct LLVMOpaqueDiagnosticInfo *LLVMDiagnosticInfoRef; + typedef enum { LLVMZExtAttribute = 1<<0, LLVMSExtAttribute = 1<<1, @@ -167,7 +164,11 @@ typedef enum { LLVMAddressSafety = 1ULL << 32, LLVMStackProtectStrongAttribute = 1ULL<<33, LLVMCold = 1ULL << 34, - LLVMOptimizeNone = 1ULL << 35 + LLVMOptimizeNone = 1ULL << 35, + LLVMInAllocaAttribute = 1ULL << 36, + LLVMNonNullAttribute = 1ULL << 37, + LLVMJumpTableAttribute = 1ULL << 38, + LLVMDereferenceableAttribute = 1ULL << 39, */ } LLVMAttribute; @@ -283,8 +284,8 @@ typedef enum { LLVMInternalLinkage, /**< Rename collisions when linking (static functions) */ LLVMPrivateLinkage, /**< Like Internal, but omit from symbol table */ - LLVMDLLImportLinkage, /**< Function to be imported from DLL */ - LLVMDLLExportLinkage, /**< Function to be accessible from DLL */ + LLVMDLLImportLinkage, /**< Obsolete */ + LLVMDLLExportLinkage, /**< Obsolete */ LLVMExternalWeakLinkage,/**< ExternalWeak linkage description */ LLVMGhostLinkage, /**< Obsolete */ LLVMCommonLinkage, /**< Tentative definitions */ @@ -299,6 +300,12 @@ typedef enum { } LLVMVisibility; typedef enum { + LLVMDefaultStorageClass = 0, + LLVMDLLImportStorageClass = 1, /**< Function to be imported from DLL. */ + LLVMDLLExportStorageClass = 2 /**< Function to be accessible from DLL. */ +} LLVMDLLStorageClass; + +typedef enum { LLVMCCallConv = 0, LLVMFastCallConv = 8, LLVMColdCallConv = 9, @@ -402,6 +409,13 @@ typedef enum { the old one */ } LLVMAtomicRMWBinOp; +typedef enum { + LLVMDSError, + LLVMDSWarning, + LLVMDSRemark, + LLVMDSNote +} LLVMDiagnosticSeverity; + /** * @} */ @@ -455,6 +469,9 @@ void LLVMEnablePrettyStackTrace(void); * @{ */ +typedef void (*LLVMDiagnosticHandler)(LLVMDiagnosticInfoRef, void *); +typedef void (*LLVMYieldCallback)(LLVMContextRef, void *); + /** * Create a new context. * @@ -469,6 +486,21 @@ LLVMContextRef LLVMContextCreate(void); LLVMContextRef LLVMGetGlobalContext(void); /** + * Set the diagnostic handler for this context. + */ +void LLVMContextSetDiagnosticHandler(LLVMContextRef C, + LLVMDiagnosticHandler Handler, + void *DiagnosticContext); + +/** + * Set the yield callback function for this context. + * + * @see LLVMContext::setYieldCallback() + */ +void LLVMContextSetYieldCallback(LLVMContextRef C, LLVMYieldCallback Callback, + void *OpaqueHandle); + +/** * Destroy a context instance. * * This should be called for every call to LLVMContextCreate() or memory @@ -476,6 +508,21 @@ LLVMContextRef LLVMGetGlobalContext(void); */ void LLVMContextDispose(LLVMContextRef C); +/** + * Return a string representation of the DiagnosticInfo. Use + * LLVMDisposeMessage to free the string. + * + * @see DiagnosticInfo::print() + */ +char *LLVMGetDiagInfoDescription(LLVMDiagnosticInfoRef DI); + +/** + * Return an enum LLVMDiagnosticSeverity. + * + * @see DiagnosticInfo::getSeverity() + */ +LLVMDiagnosticSeverity LLVMGetDiagInfoSeverity(LLVMDiagnosticInfoRef DI); + unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char* Name, unsigned SLen); unsigned LLVMGetMDKindID(const char* Name, unsigned SLen); @@ -1123,9 +1170,10 @@ LLVMTypeRef LLVMX86MMXType(void); macro(ConstantStruct) \ macro(ConstantVector) \ macro(GlobalValue) \ - macro(Function) \ macro(GlobalAlias) \ - macro(GlobalVariable) \ + macro(GlobalObject) \ + macro(Function) \ + macro(GlobalVariable) \ macro(UndefValue) \ macro(Instruction) \ macro(BinaryOperator) \ @@ -1688,6 +1736,10 @@ const char *LLVMGetSection(LLVMValueRef Global); void LLVMSetSection(LLVMValueRef Global, const char *Section); LLVMVisibility LLVMGetVisibility(LLVMValueRef Global); void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz); +LLVMDLLStorageClass LLVMGetDLLStorageClass(LLVMValueRef Global); +void LLVMSetDLLStorageClass(LLVMValueRef Global, LLVMDLLStorageClass Class); +LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global); +void LLVMSetUnnamedAddr(LLVMValueRef Global, LLVMBool HasUnnamedAddr); /** * @defgroup LLVMCCoreValueWithAlignment Values with alignment @@ -1698,6 +1750,7 @@ void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz); /** * Obtain the preferred alignment of the value. + * @see llvm::AllocaInst::getAlignment() * @see llvm::LoadInst::getAlignment() * @see llvm::StoreInst::getAlignment() * @see llvm::GlobalValue::getAlignment() @@ -1706,6 +1759,7 @@ unsigned LLVMGetAlignment(LLVMValueRef V); /** * Set the preferred alignment of the value. + * @see llvm::AllocaInst::setAlignment() * @see llvm::LoadInst::setAlignment() * @see llvm::StoreInst::setAlignment() * @see llvm::GlobalValue::setAlignment() @@ -2663,7 +2717,9 @@ LLVMValueRef LLVMBuildIsNotNull(LLVMBuilderRef, LLVMValueRef Val, const char *Name); LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); -LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op, +LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering ordering, + LLVMBool singleThread, const char *Name); +LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, LLVMAtomicRMWBinOp op, LLVMValueRef PTR, LLVMValueRef Val, LLVMAtomicOrdering ordering, LLVMBool singleThread); @@ -2793,16 +2849,13 @@ void LLVMDisposePassManager(LLVMPassManagerRef PM); * @{ */ -/** Allocate and initialize structures needed to make LLVM safe for - multithreading. The return value indicates whether multithreaded - initialization succeeded. Must be executed in isolation from all - other LLVM api calls. - @see llvm::llvm_start_multithreaded */ +/** Deprecated: Multi-threading can only be enabled/disabled with the compile + time define LLVM_ENABLE_THREADS. This function always returns + LLVMIsMultithreaded(). */ LLVMBool LLVMStartMultithreaded(void); -/** Deallocate structures necessary to make LLVM safe for multithreading. - Must be executed in isolation from all other LLVM api calls. - @see llvm::llvm_stop_multithreaded */ +/** Deprecated: Multi-threading can only be enabled/disabled with the compile + time define LLVM_ENABLE_THREADS. */ void LLVMStopMultithreaded(void); /** Check whether LLVM is executing in thread-safe mode or not. diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h index 79bcfcdab9e8..8f31150ad91d 100644 --- a/include/llvm-c/Disassembler.h +++ b/include/llvm-c/Disassembler.h @@ -96,6 +96,16 @@ struct LLVMOpInfo1 { #define LLVMDisassembler_VariantKind_ARM_LO16 2 /* :lower16: */ /** + * The ARM64 target VariantKinds. + */ +#define LLVMDisassembler_VariantKind_ARM64_PAGE 1 /* @page */ +#define LLVMDisassembler_VariantKind_ARM64_PAGEOFF 2 /* @pageoff */ +#define LLVMDisassembler_VariantKind_ARM64_GOTPAGE 3 /* @gotpage */ +#define LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF 4 /* @gotpageoff */ +#define LLVMDisassembler_VariantKind_ARM64_TLVP 5 /* @tvlppage */ +#define LLVMDisassembler_VariantKind_ARM64_TLVOFF 6 /* @tvlppageoff */ + +/** * The type for the symbol lookup function. This may be called by the * disassembler for things like adding a comment for a PC plus a constant * offset load instruction to use a symbol name instead of a load address value. @@ -123,6 +133,17 @@ typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, /* The input reference is from a PC relative load instruction. */ #define LLVMDisassembler_ReferenceType_In_PCrel_Load 2 +/* The input reference is from an ARM64::ADRP instruction. */ +#define LLVMDisassembler_ReferenceType_In_ARM64_ADRP 0x100000001 +/* The input reference is from an ARM64::ADDXri instruction. */ +#define LLVMDisassembler_ReferenceType_In_ARM64_ADDXri 0x100000002 +/* The input reference is from an ARM64::LDRXui instruction. */ +#define LLVMDisassembler_ReferenceType_In_ARM64_LDRXui 0x100000003 +/* The input reference is from an ARM64::LDRXl instruction. */ +#define LLVMDisassembler_ReferenceType_In_ARM64_LDRXl 0x100000004 +/* The input reference is from an ARM64::ADR instruction. */ +#define LLVMDisassembler_ReferenceType_In_ARM64_ADR 0x100000005 + /* The output reference is to as symbol stub. */ #define LLVMDisassembler_ReferenceType_Out_SymbolStub 1 /* The output reference is to a symbol address in a literal pool. */ @@ -141,6 +162,9 @@ typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, /* The output reference is to a Objective-C class ref. */ #define LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref 8 +/* The output reference is to a C++ symbol name. */ +#define LLVMDisassembler_ReferenceType_DeMangled_Name 9 + #ifdef __cplusplus extern "C" { #endif /* !defined(__cplusplus) */ diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index 35643122003a..7cdf0d78d5b6 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -163,6 +163,8 @@ void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, LLVMValueRef Fn); LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE); +LLVMTargetMachineRef +LLVMGetExecutionEngineTargetMachine(LLVMExecutionEngineRef EE); void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void* Addr); diff --git a/include/llvm-c/IRReader.h b/include/llvm-c/IRReader.h index d0a23be0abf5..5001afb7ed7d 100644 --- a/include/llvm-c/IRReader.h +++ b/include/llvm-c/IRReader.h @@ -24,7 +24,7 @@ extern "C" { * Read LLVM IR from a memory buffer and convert it into an in-memory Module * object. Returns 0 on success. * Optionally returns a human-readable description of any errors that - * occured during parsing IR. OutMessage must be disposed with + * occurred during parsing IR. OutMessage must be disposed with * LLVMDisposeMessage. * * @see llvm::ParseIR() diff --git a/include/llvm-c/Object.h b/include/llvm-c/Object.h index c271552482e0..447fcea7bc24 100644 --- a/include/llvm-c/Object.h +++ b/include/llvm-c/Object.h @@ -78,7 +78,6 @@ void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef RI); // SymbolRef accessors const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI); uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI); -uint64_t LLVMGetSymbolFileOffset(LLVMSymbolIteratorRef SI); uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI); // RelocationRef accessors diff --git a/include/llvm-c/Support.h b/include/llvm-c/Support.h index 7f03ede604a2..4e6ff220b100 100644 --- a/include/llvm-c/Support.h +++ b/include/llvm-c/Support.h @@ -14,13 +14,32 @@ #ifndef LLVM_C_SUPPORT_H #define LLVM_C_SUPPORT_H -#include "llvm-c/Core.h" +#include "llvm/Support/DataTypes.h" #ifdef __cplusplus extern "C" { #endif /** + * @defgroup LLVMCSupportTypes Types and Enumerations + * + * @{ + */ + +typedef int LLVMBool; + +/** + * Used to pass regions of memory through LLVM interfaces. + * + * @see llvm::MemoryBuffer + */ +typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; + +/** + * @} + */ + +/** * This function permanently loads the dynamic library at the given path. * It is safe to call this function multiple times for the same library. * diff --git a/include/llvm-c/TargetMachine.h b/include/llvm-c/TargetMachine.h index e1594113949c..d4993e7e6da1 100644 --- a/include/llvm-c/TargetMachine.h +++ b/include/llvm-c/TargetMachine.h @@ -62,7 +62,7 @@ LLVMTargetRef LLVMGetFirstTarget(void); LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T); /*===-- Target ------------------------------------------------------------===*/ -/** Finds the target corresponding to the given name and stores it in \p T. +/** Finds the target corresponding to the given name and stores it in \p T. Returns 0 on success. */ LLVMTargetRef LLVMGetTargetFromName(const char *Name); @@ -137,6 +137,9 @@ LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleR disposed with LLVMDisposeMessage. */ char* LLVMGetDefaultTargetTriple(void); +/** Adds the target-specific analysis passes to the pass manager. */ +void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM); + #ifdef __cplusplus } #endif diff --git a/include/llvm-c/Transforms/PassManagerBuilder.h b/include/llvm-c/Transforms/PassManagerBuilder.h index 545f8aae8ca2..3d7a9d677eab 100644 --- a/include/llvm-c/Transforms/PassManagerBuilder.h +++ b/include/llvm-c/Transforms/PassManagerBuilder.h @@ -19,7 +19,6 @@ typedef struct LLVMOpaquePassManagerBuilder *LLVMPassManagerBuilderRef; #ifdef __cplusplus -#include "llvm/Transforms/IPO/PassManagerBuilder.h" extern "C" { #endif diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h index 355e8dc299fb..0ca72cec0cd2 100644 --- a/include/llvm-c/Transforms/Scalar.h +++ b/include/llvm-c/Transforms/Scalar.h @@ -41,6 +41,12 @@ void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM); /** See llvm::createDeadStoreEliminationPass function. */ void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM); +/** See llvm::createScalarizerPass function. */ +void LLVMAddScalarizerPass(LLVMPassManagerRef PM); + +/** See llvm::createMergedLoadStoreMotionPass function. */ +void LLVMAddMergedLoadStoreMotionPass(LLVMPassManagerRef PM); + /** See llvm::createGVNPass function. */ void LLVMAddGVNPass(LLVMPassManagerRef PM); diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index 89f54b7a7b74..c525710ae1a1 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -40,8 +40,11 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 5 +#define LTO_API_VERSION 10 +/** + * \since prior to LTO_API_VERSION=3 + */ typedef enum { LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */ LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0, @@ -62,23 +65,29 @@ typedef enum { LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800 } lto_symbol_attributes; +/** + * \since prior to LTO_API_VERSION=3 + */ typedef enum { LTO_DEBUG_MODEL_NONE = 0, LTO_DEBUG_MODEL_DWARF = 1 } lto_debug_model; +/** + * \since prior to LTO_API_VERSION=3 + */ typedef enum { LTO_CODEGEN_PIC_MODEL_STATIC = 0, LTO_CODEGEN_PIC_MODEL_DYNAMIC = 1, - LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC = 2 + LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC = 2, + LTO_CODEGEN_PIC_MODEL_DEFAULT = 3 } lto_codegen_model; - /** opaque reference to a loaded object module */ -typedef struct LTOModule* lto_module_t; +typedef struct LLVMOpaqueLTOModule *lto_module_t; /** opaque reference to a code generator */ -typedef struct LTOCodeGenerator* lto_code_gen_t; +typedef struct LLVMOpaqueLTOCodeGenerator *lto_code_gen_t; #ifdef __cplusplus extern "C" { @@ -86,6 +95,8 @@ extern "C" { /** * Returns a printable string. + * + * \since prior to LTO_API_VERSION=3 */ extern const char* lto_get_version(void); @@ -93,12 +104,16 @@ lto_get_version(void); /** * Returns the last error string or NULL if last operation was successful. + * + * \since prior to LTO_API_VERSION=3 */ extern const char* lto_get_error_message(void); /** * Checks if a file is a loadable object file. + * + * \since prior to LTO_API_VERSION=3 */ extern lto_bool_t lto_module_is_object_file(const char* path); @@ -106,6 +121,8 @@ lto_module_is_object_file(const char* path); /** * Checks if a file is a loadable object compiled for requested target. + * + * \since prior to LTO_API_VERSION=3 */ extern lto_bool_t lto_module_is_object_file_for_target(const char* path, @@ -114,6 +131,8 @@ lto_module_is_object_file_for_target(const char* path, /** * Checks if a buffer is a loadable object file. + * + * \since prior to LTO_API_VERSION=3 */ extern lto_bool_t lto_module_is_object_file_in_memory(const void* mem, size_t length); @@ -121,6 +140,8 @@ lto_module_is_object_file_in_memory(const void* mem, size_t length); /** * Checks if a buffer is a loadable object compiled for requested target. + * + * \since prior to LTO_API_VERSION=3 */ extern lto_bool_t lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length, @@ -130,6 +151,8 @@ lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length, /** * Loads an object file from disk. * Returns NULL on error (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 */ extern lto_module_t lto_module_create(const char* path); @@ -138,13 +161,27 @@ lto_module_create(const char* path); /** * Loads an object file from memory. * Returns NULL on error (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 */ extern lto_module_t lto_module_create_from_memory(const void* mem, size_t length); /** + * Loads an object file from memory with an extra path argument. + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=9 + */ +extern lto_module_t +lto_module_create_from_memory_with_path(const void* mem, size_t length, + const char *path); + +/** * 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). + * + * \since LTO_API_VERSION=5 */ extern lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t file_size); @@ -152,28 +189,34 @@ lto_module_create_from_fd(int fd, const char *path, size_t file_size); /** * 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). + * + * \since LTO_API_VERSION=5 */ extern lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path, size_t file_size, size_t map_size, off_t offset); - /** * Frees all memory internally allocated by the module. * Upon return the lto_module_t is no longer valid. + * + * \since prior to LTO_API_VERSION=3 */ extern void lto_module_dispose(lto_module_t mod); - /** * Returns triple string which the object module was compiled under. + * + * \since prior to LTO_API_VERSION=3 */ extern const char* lto_module_get_target_triple(lto_module_t mod); /** * Sets triple string with which the object will be codegened. + * + * \since LTO_API_VERSION=4 */ extern void lto_module_set_target_triple(lto_module_t mod, const char *triple); @@ -181,6 +224,8 @@ lto_module_set_target_triple(lto_module_t mod, const char *triple); /** * Returns the number of symbols in the object module. + * + * \since prior to LTO_API_VERSION=3 */ extern unsigned int lto_module_get_num_symbols(lto_module_t mod); @@ -188,6 +233,8 @@ lto_module_get_num_symbols(lto_module_t mod); /** * Returns the name of the ith symbol in the object module. + * + * \since prior to LTO_API_VERSION=3 */ extern const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index); @@ -195,40 +242,116 @@ lto_module_get_symbol_name(lto_module_t mod, unsigned int index); /** * Returns the attributes of the ith symbol in the object module. + * + * \since prior to LTO_API_VERSION=3 */ extern lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index); /** + * Returns the number of dependent libraries in the object module. + * + * \since LTO_API_VERSION=8 + */ +extern unsigned int +lto_module_get_num_deplibs(lto_module_t mod); + + +/** + * Returns the ith dependent library in the module. + * + * \since LTO_API_VERSION=8 + */ +extern const char* +lto_module_get_deplib(lto_module_t mod, unsigned int index); + + +/** + * Returns the number of linker options in the object module. + * + * \since LTO_API_VERSION=8 + */ +extern unsigned int +lto_module_get_num_linkeropts(lto_module_t mod); + + +/** + * Returns the ith linker option in the module. + * + * \since LTO_API_VERSION=8 + */ +extern const char* +lto_module_get_linkeropt(lto_module_t mod, unsigned int index); + + +/** + * Diagnostic severity. + * + * \since LTO_API_VERSION=7 + */ +typedef enum { + LTO_DS_ERROR = 0, + LTO_DS_WARNING = 1, + LTO_DS_REMARK = 3, // Added in LTO_API_VERSION=10. + LTO_DS_NOTE = 2 +} lto_codegen_diagnostic_severity_t; + +/** + * Diagnostic handler type. + * \p severity defines the severity. + * \p diag is the actual diagnostic. + * The diagnostic is not prefixed by any of severity keyword, e.g., 'error: '. + * \p ctxt is used to pass the context set with the diagnostic handler. + * + * \since LTO_API_VERSION=7 + */ +typedef void (*lto_diagnostic_handler_t)( + lto_codegen_diagnostic_severity_t severity, const char *diag, void *ctxt); + +/** + * Set a diagnostic handler and the related context (void *). + * This is more general than lto_get_error_message, as the diagnostic handler + * can be called at anytime within lto. + * + * \since LTO_API_VERSION=7 + */ +extern void lto_codegen_set_diagnostic_handler(lto_code_gen_t, + lto_diagnostic_handler_t, + void *); + +/** * Instantiates a code generator. * Returns NULL on error (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 */ extern lto_code_gen_t lto_codegen_create(void); - /** * Frees all code generator and all memory it internally allocated. * Upon return the lto_code_gen_t is no longer valid. + * + * \since prior to LTO_API_VERSION=3 */ extern void 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). + * + * \since prior to LTO_API_VERSION=3 */ extern lto_bool_t lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); - - /** * Sets if debug info should be generated. * Returns true on error (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 */ extern lto_bool_t lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model); @@ -237,6 +360,8 @@ lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model); /** * Sets which PIC code model to generated. * Returns true on error (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 */ extern lto_bool_t lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model); @@ -244,6 +369,8 @@ lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model); /** * Sets the cpu to generate code for. + * + * \since LTO_API_VERSION=4 */ extern void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu); @@ -252,20 +379,27 @@ lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu); /** * Sets the location of the assembler tool to run. If not set, libLTO * will use gcc to invoke the assembler. + * + * \since LTO_API_VERSION=3 */ extern void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path); /** * Sets extra arguments that libLTO should pass to the assembler. + * + * \since LTO_API_VERSION=4 */ extern void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, int nargs); /** - * Tells LTO optimization passes that this symbol must be preserved - * because it is referenced by native code or a command line option. + * Adds to a list of all global symbols that must exist in the final generated + * code. If a function is not listed there, it might be inlined into every usage + * and optimized away. + * + * \since prior to LTO_API_VERSION=3 */ extern void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); @@ -274,6 +408,8 @@ lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol); * Writes a new object file at the specified path that contains the * merged contents of all modules added so far. * Returns true on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=5 */ extern lto_bool_t lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); @@ -285,6 +421,8 @@ lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path); * lto_code_gen_t and will be freed when lto_codegen_dispose() * is called, or lto_codegen_compile() is called again. * On failure, returns NULL (check lto_get_error_message() for details). + * + * \since prior to LTO_API_VERSION=3 */ extern const void* lto_codegen_compile(lto_code_gen_t cg, size_t* length); @@ -292,6 +430,8 @@ lto_codegen_compile(lto_code_gen_t cg, size_t* length); /** * Generates code for all added modules into one native object file. * The name of the file is written to name. Returns true on error. + * + * \since LTO_API_VERSION=5 */ extern lto_bool_t lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); @@ -299,6 +439,8 @@ lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name); /** * Sets options to help debug codegen bugs. + * + * \since prior to LTO_API_VERSION=3 */ extern void lto_codegen_debug_options(lto_code_gen_t cg, const char *); @@ -306,6 +448,8 @@ lto_codegen_debug_options(lto_code_gen_t cg, const char *); /** * Initializes LLVM disassemblers. * FIXME: This doesn't really belong here. + * + * \since LTO_API_VERSION=5 */ extern void lto_initialize_disassembler(void); diff --git a/include/llvm-c/module.modulemap b/include/llvm-c/module.modulemap new file mode 100644 index 000000000000..a456119595c9 --- /dev/null +++ b/include/llvm-c/module.modulemap @@ -0,0 +1,4 @@ +module LLVM_C { + umbrella "." + module * { export * } +} diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 43a78660bf18..50f1463d7eaa 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -1,4 +1,4 @@ -//== llvm/Support/APFloat.h - Arbitrary Precision Floating Point -*- C++ -*-==// +//===- llvm/ADT/APFloat.h - Arbitrary Precision Floating Point ---*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -196,6 +196,7 @@ public: explicit APFloat(double d); explicit APFloat(float f); APFloat(const APFloat &); + APFloat(APFloat &&); ~APFloat(); /// @} @@ -235,19 +236,19 @@ public: APInt fill(64, type); return getQNaN(Sem, Negative, &fill); } else { - return getQNaN(Sem, Negative, 0); + return getQNaN(Sem, Negative, nullptr); } } /// Factory for QNaN values. static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false, - const APInt *payload = 0) { + const APInt *payload = nullptr) { return makeNaN(Sem, false, Negative, payload); } /// Factory for SNaN values. static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false, - const APInt *payload = 0) { + const APInt *payload = nullptr) { return makeNaN(Sem, true, Negative, payload); } @@ -411,6 +412,7 @@ public: /// @} APFloat &operator=(const APFloat &); + APFloat &operator=(APFloat &&); /// \brief Overload to compute a hash code for an APFloat value. /// @@ -498,7 +500,8 @@ private: void makeLargest(bool Neg = false); void makeSmallest(bool Neg = false); - void makeNaN(bool SNaN = false, bool Neg = false, const APInt *fill = 0); + void makeNaN(bool SNaN = false, bool Neg = false, + const APInt *fill = nullptr); static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, const APInt *fill); void makeInf(bool Neg = false); diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index d494ad25351b..aa3c3f67ec10 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -284,12 +284,10 @@ public: initSlowCase(that); } -#if LLVM_HAS_RVALUE_REFERENCES /// \brief Move Constructor. APInt(APInt &&that) : BitWidth(that.BitWidth), VAL(that.VAL) { that.BitWidth = 0; } -#endif /// \brief Destructor. ~APInt() { @@ -656,7 +654,6 @@ public: return AssignSlowCase(RHS); } -#if LLVM_HAS_RVALUE_REFERENCES /// @brief Move assignment operator. APInt &operator=(APInt &&that) { if (!isSingleWord()) @@ -669,7 +666,6 @@ public: return *this; } -#endif /// \brief Assignment operator. /// @@ -1265,7 +1261,7 @@ public: /// \returns the number of words to hold the integer value with a given bit /// width. static unsigned getNumWords(unsigned BitWidth) { - return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + return ((uint64_t)BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; } /// \brief Compute the number of active bits in the value @@ -1504,6 +1500,35 @@ public: return BitWidth - (*this - 1).countLeadingZeros(); } + /// \returns the nearest log base 2 of this APInt. Ties round up. + /// + /// NOTE: When we have a BitWidth of 1, we define: + /// + /// log2(0) = UINT32_MAX + /// log2(1) = 0 + /// + /// to get around any mathematical concerns resulting from + /// referencing 2 in a space where 2 does no exist. + unsigned nearestLogBase2() const { + // Special case when we have a bitwidth of 1. If VAL is 1, then we + // get 0. If VAL is 0, we get UINT64_MAX which gets truncated to + // UINT32_MAX. + if (BitWidth == 1) + return VAL - 1; + + // Handle the zero case. + if (!getBoolValue()) + return UINT32_MAX; + + // The non-zero case is handled by computing: + // + // nearestLogBase2(x) = logBase2(x) + x[logBase2(x)-1]. + // + // where x[i] is referring to the value of the ith bit of x. + unsigned lg = logBase2(); + return lg + unsigned((*this)[lg - 1]); + } + /// \returns the log base 2 of this APInt if its an exact power of two, -1 /// otherwise int32_t exactLogBase2() const { diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index ad035a7c30df..ee34e9b53088 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -30,18 +30,12 @@ public: explicit APSInt(uint32_t BitWidth, bool isUnsigned = true) : APInt(BitWidth, 0), IsUnsigned(isUnsigned) {} - explicit APSInt(const APInt &I, bool isUnsigned = true) - : APInt(I), IsUnsigned(isUnsigned) {} + explicit APSInt(APInt I, bool isUnsigned = true) + : APInt(std::move(I)), IsUnsigned(isUnsigned) {} - APSInt &operator=(const APSInt &RHS) { - APInt::operator=(RHS); - IsUnsigned = RHS.IsUnsigned; - return *this; - } - - APSInt &operator=(const APInt &RHS) { + APSInt &operator=(APInt RHS) { // Retain our current sign. - APInt::operator=(RHS); + APInt::operator=(std::move(RHS)); return *this; } @@ -62,7 +56,7 @@ public: APInt::toString(Str, Radix, isSigned()); } /// toString - Converts an APInt to a std::string. This is an inefficient - /// method, your should prefer passing in a SmallString instead. + /// method; you should prefer passing in a SmallString instead. std::string toString(unsigned Radix) const { return APInt::toString(Radix, isSigned()); } diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index e5562c368309..0fff505d8d01 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -48,10 +48,10 @@ namespace llvm { /// @{ /// Construct an empty ArrayRef. - /*implicit*/ ArrayRef() : Data(0), Length(0) {} + /*implicit*/ ArrayRef() : Data(nullptr), Length(0) {} /// Construct an empty ArrayRef from None. - /*implicit*/ ArrayRef(NoneType) : Data(0), Length(0) {} + /*implicit*/ ArrayRef(NoneType) : Data(nullptr), Length(0) {} /// Construct an ArrayRef from a single element. /*implicit*/ ArrayRef(const T &OneElt) @@ -76,7 +76,7 @@ namespace llvm { /// Construct an ArrayRef from a std::vector. template<typename A> /*implicit*/ ArrayRef(const std::vector<T, A> &Vec) - : Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {} + : Data(Vec.data()), Length(Vec.size()) {} /// Construct an ArrayRef from a C array. template <size_t N> @@ -120,14 +120,18 @@ namespace llvm { return Data[Length-1]; } + // copy - Allocate copy in Allocator and return ArrayRef<T> to it. + template <typename Allocator> ArrayRef<T> copy(Allocator &A) { + T *Buff = A.template Allocate<T>(Length); + std::copy(begin(), end(), Buff); + return ArrayRef<T>(Buff, Length); + } + /// equals - Check for element-wise equality. bool equals(ArrayRef RHS) const { if (Length != RHS.Length) return false; - for (size_type i = 0; i != Length; i++) - if (Data[i] != RHS.Data[i]) - return false; - return true; + return std::equal(begin(), end(), RHS.begin()); } /// slice(n) - Chop off the first N elements of the array. @@ -143,6 +147,12 @@ namespace llvm { return ArrayRef<T>(data()+N, M); } + // \brief Drop the last \p N elements of the array. + ArrayRef<T> drop_back(unsigned N = 1) const { + assert(size() >= N && "Dropping more elements than exist"); + return slice(0, size() - N); + } + /// @} /// @name Operator Overloads /// @{ @@ -213,7 +223,7 @@ namespace llvm { /// Construct an MutableArrayRef from a C array. template <size_t N> - /*implicit*/ MutableArrayRef(T (&Arr)[N]) + /*implicit*/ LLVM_CONSTEXPR MutableArrayRef(T (&Arr)[N]) : ArrayRef<T>(Arr) {} T *data() const { return const_cast<T*>(ArrayRef<T>::data()); } diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 8fb538f68fcf..34e2284311b3 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -34,6 +34,7 @@ class BitVector { unsigned Capacity; // Size of allocated memory in BitWord. public: + typedef unsigned size_type; // Encapsulation of a single bit. class reference { friend class BitVector; @@ -58,21 +59,21 @@ public: reference& operator=(bool t) { if (t) - *WordRef |= 1L << BitPos; + *WordRef |= BitWord(1) << BitPos; else - *WordRef &= ~(1L << BitPos); + *WordRef &= ~(BitWord(1) << BitPos); return *this; } operator bool() const { - return ((*WordRef) & (1L << BitPos)) ? true : false; + return ((*WordRef) & (BitWord(1) << BitPos)) ? true : false; } }; /// BitVector default ctor - Creates an empty bitvector. BitVector() : Size(0), Capacity(0) { - Bits = 0; + Bits = nullptr; } /// BitVector ctor - Creates a bitvector of specified number of bits. All @@ -88,7 +89,7 @@ public: /// BitVector copy ctor. BitVector(const BitVector &RHS) : Size(RHS.size()) { if (Size == 0) { - Bits = 0; + Bits = nullptr; Capacity = 0; return; } @@ -98,12 +99,10 @@ public: std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord)); } -#if LLVM_HAS_RVALUE_REFERENCES BitVector(BitVector &&RHS) : Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) { - RHS.Bits = 0; + RHS.Bits = nullptr; } -#endif ~BitVector() { std::free(Bits); @@ -113,10 +112,10 @@ public: bool empty() const { return Size == 0; } /// size - Returns the number of bits in this bitvector. - unsigned size() const { return Size; } + size_type size() const { return Size; } /// count - Returns the number of bits which are set. - unsigned count() const { + size_type count() const { unsigned NumBits = 0; for (unsigned i = 0; i < NumBitWords(size()); ++i) if (sizeof(BitWord) == 4) @@ -240,7 +239,7 @@ public: } BitVector &set(unsigned Idx) { - Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE); + Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE); return *this; } @@ -267,7 +266,8 @@ public: Bits[I / BITWORD_SIZE] = ~0UL; BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1; - Bits[I / BITWORD_SIZE] |= PostfixMask; + if (I < E) + Bits[I / BITWORD_SIZE] |= PostfixMask; return *this; } @@ -278,7 +278,7 @@ public: } BitVector &reset(unsigned Idx) { - Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE)); + Bits[Idx / BITWORD_SIZE] &= ~(BitWord(1) << (Idx % BITWORD_SIZE)); return *this; } @@ -305,7 +305,8 @@ public: Bits[I / BITWORD_SIZE] = 0UL; BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1; - Bits[I / BITWORD_SIZE] &= ~PostfixMask; + if (I < E) + Bits[I / BITWORD_SIZE] &= ~PostfixMask; return *this; } @@ -318,7 +319,7 @@ public: } BitVector &flip(unsigned Idx) { - Bits[Idx / BITWORD_SIZE] ^= 1L << (Idx % BITWORD_SIZE); + Bits[Idx / BITWORD_SIZE] ^= BitWord(1) << (Idx % BITWORD_SIZE); return *this; } @@ -330,7 +331,7 @@ public: bool operator[](unsigned Idx) const { assert (Idx < Size && "Out-of-bounds Bit access."); - BitWord Mask = 1L << (Idx % BITWORD_SIZE); + BitWord Mask = BitWord(1) << (Idx % BITWORD_SIZE); return (Bits[Idx / BITWORD_SIZE] & Mask) != 0; } @@ -459,7 +460,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES const BitVector &operator=(BitVector &&RHS) { if (this == &RHS) return *this; @@ -468,11 +468,10 @@ public: Size = RHS.Size; Capacity = RHS.Capacity; - RHS.Bits = 0; + RHS.Bits = nullptr; return *this; } -#endif void swap(BitVector &RHS) { std::swap(Bits, RHS.Bits); diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index ce322cce4e0b..85f37b9051b1 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -43,6 +43,7 @@ protected: typedef std::pair<KeyT, ValueT> BucketT; public: + typedef unsigned size_type; typedef KeyT key_type; typedef ValueT mapped_type; typedef BucketT value_type; @@ -70,7 +71,7 @@ public: unsigned size() const { return getNumEntries(); } /// Grow the densemap so that it has at least Size buckets. Does not shrink - void resize(size_t Size) { + void resize(size_type Size) { if (Size > getNumBuckets()) grow(Size); } @@ -99,10 +100,10 @@ public: setNumTombstones(0); } - /// count - Return true if the specified key is in the map. - bool count(const KeyT &Val) const { + /// Return 1 if the specified key is in the map, 0 otherwise. + size_type count(const KeyT &Val) const { const BucketT *TheBucket; - return LookupBucketFor(Val, TheBucket); + return LookupBucketFor(Val, TheBucket) ? 1 : 0; } iterator find(const KeyT &Val) { @@ -161,7 +162,6 @@ public: return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); } -#if LLVM_HAS_RVALUE_REFERENCES // Inserts key,value pair into the map if the key isn't already in the map. // If the key is already in the map, it returns false and doesn't update the // value. @@ -177,8 +177,7 @@ public: TheBucket); return std::make_pair(iterator(TheBucket, getBucketsEnd(), true), true); } -#endif - + /// insert - Range insertion of pairs. template<typename InputIt> void insert(InputIt I, InputIt E) { @@ -218,7 +217,6 @@ public: return FindAndConstruct(Key).second; } -#if LLVM_HAS_RVALUE_REFERENCES value_type& FindAndConstruct(KeyT &&Key) { BucketT *TheBucket; if (LookupBucketFor(Key, TheBucket)) @@ -230,7 +228,6 @@ public: ValueT &operator[](KeyT &&Key) { return FindAndConstruct(std::move(Key)).second; } -#endif /// isPointerIntoBucketsArray - Return true if the specified pointer points /// somewhere into the DenseMap's array of buckets (i.e. either to a key or @@ -289,8 +286,8 @@ protected: bool FoundVal = LookupBucketFor(B->first, DestBucket); (void)FoundVal; // silence warning. assert(!FoundVal && "Key already in new map?"); - DestBucket->first = llvm_move(B->first); - new (&DestBucket->second) ValueT(llvm_move(B->second)); + DestBucket->first = std::move(B->first); + new (&DestBucket->second) ValueT(std::move(B->second)); incrementNumEntries(); // Free the value. @@ -403,7 +400,6 @@ private: return TheBucket; } -#if LLVM_HAS_RVALUE_REFERENCES BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value, BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); @@ -420,7 +416,6 @@ private: new (&TheBucket->second) ValueT(std::move(Value)); return TheBucket; } -#endif BucketT *InsertIntoBucketImpl(const KeyT &Key, BucketT *TheBucket) { // If the load of the hash table is more than 3/4, or if fewer than 1/8 of @@ -467,12 +462,12 @@ private: const unsigned NumBuckets = getNumBuckets(); if (NumBuckets == 0) { - FoundBucket = 0; + FoundBucket = nullptr; return false; } // FoundTombstone - Keep track of whether we find a tombstone while probing. - const BucketT *FoundTombstone = 0; + const BucketT *FoundTombstone = nullptr; const KeyT EmptyKey = getEmptyKey(); const KeyT TombstoneKey = getTombstoneKey(); assert(!KeyInfoT::isEqual(Val, EmptyKey) && @@ -555,12 +550,10 @@ public: copyFrom(other); } -#if LLVM_HAS_RVALUE_REFERENCES DenseMap(DenseMap &&other) : BaseT() { init(0); swap(other); } -#endif template<typename InputIt> DenseMap(const InputIt &I, const InputIt &E) { @@ -585,7 +578,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES DenseMap& operator=(DenseMap &&other) { this->destroyAll(); operator delete(Buckets); @@ -593,7 +585,6 @@ public: swap(other); return *this; } -#endif void copyFrom(const DenseMap& other) { this->destroyAll(); @@ -675,7 +666,7 @@ private: bool allocateBuckets(unsigned Num) { NumBuckets = Num; if (NumBuckets == 0) { - Buckets = 0; + Buckets = nullptr; return false; } @@ -719,12 +710,10 @@ public: copyFrom(other); } -#if LLVM_HAS_RVALUE_REFERENCES SmallDenseMap(SmallDenseMap &&other) : BaseT() { init(0); swap(other); } -#endif template<typename InputIt> SmallDenseMap(const InputIt &I, const InputIt &E) { @@ -765,10 +754,10 @@ public: // Swap separately and handle any assymetry. std::swap(LHSB->first, RHSB->first); if (hasLHSValue) { - new (&RHSB->second) ValueT(llvm_move(LHSB->second)); + new (&RHSB->second) ValueT(std::move(LHSB->second)); LHSB->second.~ValueT(); } else if (hasRHSValue) { - new (&LHSB->second) ValueT(llvm_move(RHSB->second)); + new (&LHSB->second) ValueT(std::move(RHSB->second)); RHSB->second.~ValueT(); } } @@ -784,7 +773,7 @@ public: SmallDenseMap &LargeSide = Small ? RHS : *this; // First stash the large side's rep and move the small side across. - LargeRep TmpRep = llvm_move(*LargeSide.getLargeRep()); + LargeRep TmpRep = std::move(*LargeSide.getLargeRep()); LargeSide.getLargeRep()->~LargeRep(); LargeSide.Small = true; // This is similar to the standard move-from-old-buckets, but the bucket @@ -794,11 +783,11 @@ public: for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { BucketT *NewB = &LargeSide.getInlineBuckets()[i], *OldB = &SmallSide.getInlineBuckets()[i]; - new (&NewB->first) KeyT(llvm_move(OldB->first)); + 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(llvm_move(OldB->second)); + new (&NewB->second) ValueT(std::move(OldB->second)); OldB->second.~ValueT(); } } @@ -806,7 +795,7 @@ public: // The hard part of moving the small buckets across is done, just move // the TmpRep into its new home. SmallSide.Small = false; - new (SmallSide.getLargeRep()) LargeRep(llvm_move(TmpRep)); + new (SmallSide.getLargeRep()) LargeRep(std::move(TmpRep)); } SmallDenseMap& operator=(const SmallDenseMap& other) { @@ -814,7 +803,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES SmallDenseMap& operator=(SmallDenseMap &&other) { this->destroyAll(); deallocateBuckets(); @@ -822,7 +810,6 @@ public: swap(other); return *this; } -#endif void copyFrom(const SmallDenseMap& other) { this->destroyAll(); @@ -830,7 +817,7 @@ public: Small = true; if (other.getNumBuckets() > InlineBuckets) { Small = false; - allocateBuckets(other.getNumBuckets()); + new (getLargeRep()) LargeRep(allocateBuckets(other.getNumBuckets())); } this->BaseT::copyFrom(other); } @@ -866,8 +853,8 @@ public: !KeyInfoT::isEqual(P->first, TombstoneKey)) { assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && "Too many inline buckets!"); - new (&TmpEnd->first) KeyT(llvm_move(P->first)); - new (&TmpEnd->second) ValueT(llvm_move(P->second)); + new (&TmpEnd->first) KeyT(std::move(P->first)); + new (&TmpEnd->second) ValueT(std::move(P->second)); ++TmpEnd; P->second.~ValueT(); } @@ -882,7 +869,7 @@ public: return; } - LargeRep OldRep = llvm_move(*getLargeRep()); + LargeRep OldRep = std::move(*getLargeRep()); getLargeRep()->~LargeRep(); if (AtLeast <= InlineBuckets) { Small = true; @@ -991,14 +978,15 @@ class DenseMapIterator { friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, true>; public: typedef ptrdiff_t difference_type; - typedef typename conditional<IsConst, const Bucket, Bucket>::type value_type; + typedef typename std::conditional<IsConst, const Bucket, Bucket>::type + value_type; typedef value_type *pointer; typedef value_type &reference; typedef std::forward_iterator_tag iterator_category; private: pointer Ptr, End; public: - DenseMapIterator() : Ptr(0), End(0) {} + DenseMapIterator() : Ptr(nullptr), End(nullptr) {} DenseMapIterator(pointer Pos, pointer E, bool NoAdvance = false) : Ptr(Pos), End(E) { diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index d699ad51ada4..37a81b0c7ee2 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -27,11 +27,14 @@ class DenseSet { typedef DenseMap<ValueT, char, ValueInfoT> MapTy; MapTy TheMap; public: - DenseSet(const DenseSet &Other) : TheMap(Other.TheMap) {} + typedef ValueT key_type; + typedef ValueT value_type; + typedef unsigned size_type;
+ explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {} bool empty() const { return TheMap.empty(); } - unsigned size() const { return TheMap.size(); } + size_type size() const { return TheMap.size(); } size_t getMemorySize() const { return TheMap.getMemorySize(); } /// Grow the DenseSet so that it has at least Size buckets. Will not shrink @@ -42,7 +45,8 @@ public: TheMap.clear(); } - bool count(const ValueT &V) const { + /// Return 1 if the specified key is in the set, 0 otherwise.
+ size_type count(const ValueT &V) const { return TheMap.count(V); } @@ -54,11 +58,6 @@ public: TheMap.swap(RHS.TheMap); } - DenseSet &operator=(const DenseSet &RHS) { - TheMap = RHS.TheMap; - return *this; - } - // Iterators. class Iterator { diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index 644544253ab7..dfba43f3ac85 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -33,6 +33,7 @@ #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" @@ -207,6 +208,12 @@ df_iterator<T> df_end(const T& G) { return df_iterator<T>::end(G); } +// Provide an accessor method to use them in range-based patterns. +template <class T> +iterator_range<df_iterator<T>> depth_first(const T& G) { + return iterator_range<df_iterator<T>>(df_begin(G), df_end(G)); +} + // Provide global definitions of external depth first iterators... template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> > struct df_ext_iterator : public df_iterator<T, SetTy, true> { @@ -244,6 +251,12 @@ idf_iterator<T> idf_end(const T& G){ return idf_iterator<T>::end(Inverse<T>(G)); } +// Provide an accessor method to use them in range-based patterns. +template <class T> +iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) { + return iterator_range<idf_iterator<T>>(idf_begin(G), idf_end(G)); +} + // Provide global definitions of external inverse depth first iterators... template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> > struct idf_ext_iterator : public idf_iterator<T, SetTy, true> { diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index 1d81772ee8ae..e0396c7e7914 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -86,14 +86,14 @@ class EquivalenceClasses { } void setNext(const ECValue *NewNext) const { - assert(getNext() == 0 && "Already has a next pointer!"); + assert(getNext() == nullptr && "Already has a next pointer!"); Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader()); } public: ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1), Data(RHS.Data) { // Only support copying of singleton nodes. - assert(RHS.isLeader() && RHS.getNext() == 0 && "Not a singleton!"); + assert(RHS.isLeader() && RHS.getNext() == nullptr && "Not a singleton!"); } bool operator<(const ECValue &UFN) const { return Data < UFN.Data; } @@ -147,10 +147,10 @@ public: class member_iterator; member_iterator member_begin(iterator I) const { // Only leaders provide anything to iterate over. - return member_iterator(I->isLeader() ? &*I : 0); + return member_iterator(I->isLeader() ? &*I : nullptr); } member_iterator member_end() const { - return member_iterator(0); + return member_iterator(nullptr); } /// findValue - Return an iterator to the specified value. If it does not @@ -249,16 +249,15 @@ public: explicit member_iterator() {} explicit member_iterator(const ECValue *N) : Node(N) {} - member_iterator(const member_iterator &I) : Node(I.Node) {} reference operator*() const { - assert(Node != 0 && "Dereferencing end()!"); + assert(Node != nullptr && "Dereferencing end()!"); return Node->getData(); } reference operator->() const { return operator*(); } member_iterator &operator++() { - assert(Node != 0 && "++'d off the end of the list!"); + assert(Node != nullptr && "++'d off the end of the list!"); Node = Node->getNext(); return *this; } diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 1b2c94c35f84..14c5933d388a 100644 --- a/include/llvm/ADT/FoldingSet.h +++ b/include/llvm/ADT/FoldingSet.h @@ -18,12 +18,12 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" namespace llvm { class APFloat; class APInt; - class BumpPtrAllocator; /// This folding set used for two purposes: /// 1. Given information about a node we want to create, look up the unique @@ -137,7 +137,7 @@ public: public: - Node() : NextInFoldingSetBucket(0) {} + Node() : NextInFoldingSetBucket(nullptr) {} // Accessors void *getNextInBucket() const { return NextInFoldingSetBucket; } @@ -269,7 +269,7 @@ class FoldingSetNodeIDRef { const unsigned *Data; size_t Size; public: - FoldingSetNodeIDRef() : Data(0), Size(0) {} + FoldingSetNodeIDRef() : Data(nullptr), Size(0) {} FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {} /// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef, @@ -278,6 +278,8 @@ public: bool operator==(FoldingSetNodeIDRef) const; + bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); } + /// Used to compare the "ordering" of two nodes as defined by the /// profiled bits and their ordering defined by memcmp(). bool operator<(FoldingSetNodeIDRef) const; @@ -331,6 +333,9 @@ public: bool operator==(const FoldingSetNodeID &RHS) const; bool operator==(const FoldingSetNodeIDRef RHS) const; + bool operator!=(const FoldingSetNodeID &RHS) const { return !(*this == RHS); } + bool operator!=(const FoldingSetNodeIDRef RHS) const { return !(*this ==RHS);} + /// Used to compare the "ordering" of two nodes as defined by the /// profiled bits and their ordering defined by memcmp(). bool operator<(const FoldingSetNodeID &RHS) const; @@ -391,20 +396,20 @@ template<class T> class FoldingSet : public FoldingSetImpl { private: /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a /// way to convert nodes into a unique specifier. - virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const { + void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override { T *TN = static_cast<T *>(N); FoldingSetTrait<T>::Profile(*TN, ID); } /// NodeEquals - Instantiations may optionally provide a way to compare a /// node with a specified ID. - virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash, - FoldingSetNodeID &TempID) const { + bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash, + FoldingSetNodeID &TempID) const override { T *TN = static_cast<T *>(N); return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID); } /// ComputeNodeHash - Instantiations may optionally provide a way to compute a /// hash value directly from a node. - virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const { + unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override { T *TN = static_cast<T *>(N); return FoldingSetTrait<T>::ComputeHash(*TN, TempID); } @@ -468,20 +473,19 @@ private: /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a /// way to convert nodes into a unique specifier. - virtual void GetNodeProfile(FoldingSetImpl::Node *N, - FoldingSetNodeID &ID) const { + void GetNodeProfile(FoldingSetImpl::Node *N, + FoldingSetNodeID &ID) const override { T *TN = static_cast<T *>(N); ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context); } - virtual bool NodeEquals(FoldingSetImpl::Node *N, - const FoldingSetNodeID &ID, unsigned IDHash, - FoldingSetNodeID &TempID) const { + bool NodeEquals(FoldingSetImpl::Node *N, const FoldingSetNodeID &ID, + unsigned IDHash, FoldingSetNodeID &TempID) const override { T *TN = static_cast<T *>(N); return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID, Context); } - virtual unsigned ComputeNodeHash(FoldingSetImpl::Node *N, - FoldingSetNodeID &TempID) const { + unsigned ComputeNodeHash(FoldingSetImpl::Node *N, + FoldingSetNodeID &TempID) const override { T *TN = static_cast<T *>(N); return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context); } @@ -790,6 +794,14 @@ template<typename T> struct FoldingSetTrait<T*> { ID.AddPointer(X); } }; +template <typename T1, typename T2> +struct FoldingSetTrait<std::pair<T1, T2>> { + static inline void Profile(const std::pair<T1, T2> &P, + llvm::FoldingSetNodeID &ID) { + ID.Add(P.first); + ID.Add(P.second); + } +}; } // End of namespace llvm. #endif diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index e434417da7c5..abf02b8cc9d5 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -45,7 +45,6 @@ #ifndef LLVM_ADT_HASHING_H #define LLVM_ADT_HASHING_H -#include "llvm/ADT/STLExtras.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Host.h" #include "llvm/Support/SwapByteOrder.h" @@ -109,7 +108,8 @@ public: /// differing argument types even if they would implicit promote to a common /// type without changing the value. template <typename T> -typename enable_if<is_integral_or_enum<T>, hash_code>::type hash_value(T value); +typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type +hash_value(T value); /// \brief Compute a hash_code for a pointer's address. /// @@ -152,7 +152,7 @@ inline uint64_t fetch64(const char *p) { uint64_t result; memcpy(&result, p, sizeof(result)); if (sys::IsBigEndianHost) - return sys::SwapByteOrder(result); + sys::swapByteOrder(result); return result; } @@ -160,7 +160,7 @@ inline uint32_t fetch32(const char *p) { uint32_t result; memcpy(&result, p, sizeof(result)); if (sys::IsBigEndianHost) - return sys::SwapByteOrder(result); + sys::swapByteOrder(result); return result; } @@ -265,7 +265,6 @@ inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) { /// keeps 56 bytes of arbitrary state. struct hash_state { uint64_t h0, h1, h2, h3, h4, h5, h6; - uint64_t seed; /// \brief Create a new hash_state structure and initialize it based on the /// seed and the first 64-byte chunk. @@ -273,7 +272,7 @@ struct hash_state { static hash_state create(const char *s, uint64_t seed) { hash_state state = { 0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49), - seed * k1, shift_mix(seed), 0, seed }; + seed * k1, shift_mix(seed), 0 }; state.h6 = hash_16_bytes(state.h4, state.h5); state.mix(s); return state; @@ -352,24 +351,24 @@ inline size_t get_execution_seed() { // and pointers, but there are platforms where it doesn't and we would like to // support user-defined types which happen to satisfy this property. template <typename T> struct is_hashable_data - : integral_constant<bool, ((is_integral_or_enum<T>::value || - is_pointer<T>::value) && - 64 % sizeof(T) == 0)> {}; + : std::integral_constant<bool, ((is_integral_or_enum<T>::value || + std::is_pointer<T>::value) && + 64 % sizeof(T) == 0)> {}; // Special case std::pair to detect when both types are viable and when there // is no alignment-derived padding in the pair. This is a bit of a lie because // std::pair isn't truly POD, but it's close enough in all reasonable // implementations for our use case of hashing the underlying data. template <typename T, typename U> struct is_hashable_data<std::pair<T, U> > - : integral_constant<bool, (is_hashable_data<T>::value && - is_hashable_data<U>::value && - (sizeof(T) + sizeof(U)) == - sizeof(std::pair<T, U>))> {}; + : std::integral_constant<bool, (is_hashable_data<T>::value && + is_hashable_data<U>::value && + (sizeof(T) + sizeof(U)) == + sizeof(std::pair<T, U>))> {}; /// \brief Helper to get the hashable data representation for a type. /// This variant is enabled when the type itself can be used. template <typename T> -typename enable_if<is_hashable_data<T>, T>::type +typename std::enable_if<is_hashable_data<T>::value, T>::type get_hashable_data(const T &value) { return value; } @@ -377,7 +376,7 @@ get_hashable_data(const T &value) { /// This variant is enabled when we must first call hash_value and use the /// result as our data. template <typename T> -typename enable_if_c<!is_hashable_data<T>::value, size_t>::type +typename std::enable_if<!is_hashable_data<T>::value, size_t>::type get_hashable_data(const T &value) { using ::llvm::hash_value; return hash_value(value); @@ -411,7 +410,7 @@ template <typename InputIteratorT> hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { const size_t seed = get_execution_seed(); char buffer[64], *buffer_ptr = buffer; - char *const buffer_end = buffer_ptr + array_lengthof(buffer); + char *const buffer_end = std::end(buffer); while (first != last && store_and_advance(buffer_ptr, buffer_end, get_hashable_data(*first))) ++first; @@ -451,7 +450,7 @@ hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { /// are stored in contiguous memory, this routine avoids copying each value /// and directly reads from the underlying memory. template <typename ValueT> -typename enable_if<is_hashable_data<ValueT>, hash_code>::type +typename std::enable_if<is_hashable_data<ValueT>::value, hash_code>::type hash_combine_range_impl(ValueT *first, ValueT *last) { const size_t seed = get_execution_seed(); const char *s_begin = reinterpret_cast<const char *>(first); @@ -734,7 +733,7 @@ inline hash_code hash_integer_value(uint64_t value) { // Declared and documented above, but defined here so that any of the hashing // infrastructure is available. template <typename T> -typename enable_if<is_integral_or_enum<T>, hash_code>::type +typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type hash_value(T value) { return ::llvm::hashing::detail::hash_integer_value(value); } diff --git a/include/llvm/ADT/ImmutableIntervalMap.h b/include/llvm/ADT/ImmutableIntervalMap.h deleted file mode 100644 index 6793c6b9c205..000000000000 --- a/include/llvm/ADT/ImmutableIntervalMap.h +++ /dev/null @@ -1,248 +0,0 @@ -//===--- ImmutableIntervalMap.h - Immutable (functional) map ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the ImmutableIntervalMap class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_IMMUTABLEINTERVALMAP_H -#define LLVM_ADT_IMMUTABLEINTERVALMAP_H - -#include "llvm/ADT/ImmutableMap.h" - -namespace llvm { - -class Interval { -private: - int64_t Start; - int64_t End; - -public: - Interval(int64_t S, int64_t E) : Start(S), End(E) {} - - int64_t getStart() const { return Start; } - int64_t getEnd() const { return End; } -}; - -template <typename T> -struct ImutIntervalInfo { - typedef const std::pair<Interval, T> value_type; - typedef const value_type &value_type_ref; - typedef const Interval key_type; - typedef const Interval &key_type_ref; - typedef const T data_type; - typedef const T &data_type_ref; - - static key_type_ref KeyOfValue(value_type_ref V) { - return V.first; - } - - static data_type_ref DataOfValue(value_type_ref V) { - return V.second; - } - - static bool isEqual(key_type_ref L, key_type_ref R) { - return L.getStart() == R.getStart() && L.getEnd() == R.getEnd(); - } - - static bool isDataEqual(data_type_ref L, data_type_ref R) { - return ImutContainerInfo<T>::isEqual(L,R); - } - - static bool isLess(key_type_ref L, key_type_ref R) { - // Assume L and R does not overlap. - if (L.getStart() < R.getStart()) { - assert(L.getEnd() < R.getStart()); - return true; - } else if (L.getStart() == R.getStart()) { - assert(L.getEnd() == R.getEnd()); - return false; - } else { - assert(L.getStart() > R.getEnd()); - return false; - } - } - - static bool isContainedIn(key_type_ref K, key_type_ref L) { - if (K.getStart() >= L.getStart() && K.getEnd() <= L.getEnd()) - return true; - else - return false; - } - - static void Profile(FoldingSetNodeID &ID, value_type_ref V) { - ID.AddInteger(V.first.getStart()); - ID.AddInteger(V.first.getEnd()); - ImutProfileInfo<T>::Profile(ID, V.second); - } -}; - -template <typename ImutInfo> -class ImutIntervalAVLFactory : public ImutAVLFactory<ImutInfo> { - typedef ImutAVLTree<ImutInfo> TreeTy; - typedef typename ImutInfo::value_type value_type; - typedef typename ImutInfo::value_type_ref value_type_ref; - typedef typename ImutInfo::key_type key_type; - typedef typename ImutInfo::key_type_ref key_type_ref; - typedef typename ImutInfo::data_type data_type; - typedef typename ImutInfo::data_type_ref data_type_ref; - -public: - ImutIntervalAVLFactory(BumpPtrAllocator &Alloc) - : ImutAVLFactory<ImutInfo>(Alloc) {} - - TreeTy *Add(TreeTy *T, value_type_ref V) { - T = add_internal(V,T); - this->MarkImmutable(T); - return T; - } - - TreeTy *Find(TreeTy *T, key_type_ref K) { - if (!T) - return NULL; - - key_type_ref CurrentKey = ImutInfo::KeyOfValue(this->getValue(T)); - - if (ImutInfo::isContainedIn(K, CurrentKey)) - return T; - else if (ImutInfo::isLess(K, CurrentKey)) - return Find(this->getLeft(T), K); - else - return Find(this->getRight(T), K); - } - -private: - TreeTy *add_internal(value_type_ref V, TreeTy *T) { - key_type_ref K = ImutInfo::KeyOfValue(V); - T = removeAllOverlaps(T, K); - if (this->isEmpty(T)) - return this->CreateNode(NULL, V, NULL); - - assert(!T->isMutable()); - - key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T)); - - if (ImutInfo::isLess(K, KCurrent)) - return this->Balance(add_internal(V, this->Left(T)), this->Value(T), - this->Right(T)); - else - return this->Balance(this->Left(T), this->Value(T), - add_internal(V, this->Right(T))); - } - - // Remove all overlaps from T. - TreeTy *removeAllOverlaps(TreeTy *T, key_type_ref K) { - bool Changed; - do { - Changed = false; - T = removeOverlap(T, K, Changed); - this->markImmutable(T); - } while (Changed); - - return T; - } - - // Remove one overlap from T. - TreeTy *removeOverlap(TreeTy *T, key_type_ref K, bool &Changed) { - if (!T) - return NULL; - Interval CurrentK = ImutInfo::KeyOfValue(this->Value(T)); - - // If current key does not overlap the inserted key. - if (CurrentK.getStart() > K.getEnd()) - return this->Balance(removeOverlap(this->Left(T), K, Changed), - this->Value(T), this->Right(T)); - else if (CurrentK.getEnd() < K.getStart()) - return this->Balance(this->Left(T), this->Value(T), - removeOverlap(this->Right(T), K, Changed)); - - // Current key overlaps with the inserted key. - // Remove the current key. - Changed = true; - data_type_ref OldData = ImutInfo::DataOfValue(this->Value(T)); - T = this->Remove_internal(CurrentK, T); - // Add back the unoverlapped part of the current key. - if (CurrentK.getStart() < K.getStart()) { - if (CurrentK.getEnd() <= K.getEnd()) { - Interval NewK(CurrentK.getStart(), K.getStart()-1); - return add_internal(std::make_pair(NewK, OldData), T); - } else { - Interval NewK1(CurrentK.getStart(), K.getStart()-1); - T = add_internal(std::make_pair(NewK1, OldData), T); - - Interval NewK2(K.getEnd()+1, CurrentK.getEnd()); - return add_internal(std::make_pair(NewK2, OldData), T); - } - } else { - if (CurrentK.getEnd() > K.getEnd()) { - Interval NewK(K.getEnd()+1, CurrentK.getEnd()); - return add_internal(std::make_pair(NewK, OldData), T); - } else - return T; - } - } -}; - -/// ImmutableIntervalMap maps an interval [start, end] to a value. The intervals -/// in the map are guaranteed to be disjoint. -template <typename ValT> -class ImmutableIntervalMap - : public ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> > { - - typedef typename ImutIntervalInfo<ValT>::value_type value_type; - typedef typename ImutIntervalInfo<ValT>::value_type_ref value_type_ref; - typedef typename ImutIntervalInfo<ValT>::key_type key_type; - typedef typename ImutIntervalInfo<ValT>::key_type_ref key_type_ref; - typedef typename ImutIntervalInfo<ValT>::data_type data_type; - typedef typename ImutIntervalInfo<ValT>::data_type_ref data_type_ref; - typedef ImutAVLTree<ImutIntervalInfo<ValT> > TreeTy; - -public: - explicit ImmutableIntervalMap(TreeTy *R) - : ImmutableMap<Interval, ValT, ImutIntervalInfo<ValT> >(R) {} - - class Factory { - ImutIntervalAVLFactory<ImutIntervalInfo<ValT> > F; - - public: - Factory(BumpPtrAllocator& Alloc) : F(Alloc) {} - - ImmutableIntervalMap getEmptyMap() { - return ImmutableIntervalMap(F.getEmptyTree()); - } - - ImmutableIntervalMap add(ImmutableIntervalMap Old, - key_type_ref K, data_type_ref D) { - TreeTy *T = F.add(Old.Root, std::pair<key_type, data_type>(K, D)); - return ImmutableIntervalMap(F.getCanonicalTree(T)); - } - - ImmutableIntervalMap remove(ImmutableIntervalMap Old, key_type_ref K) { - TreeTy *T = F.remove(Old.Root, K); - return ImmutableIntervalMap(F.getCanonicalTree(T)); - } - - data_type *lookup(ImmutableIntervalMap M, key_type_ref K) { - TreeTy *T = F.Find(M.getRoot(), K); - if (T) - return &T->getValue().second; - else - return 0; - } - }; - -private: - // For ImmutableIntervalMap, the lookup operation has to be done by the - // factory. - data_type* lookup(key_type_ref K) const; -}; - -} // end namespace llvm - -#endif diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h index 8f8fb9877040..11f281be3d23 100644 --- a/include/llvm/ADT/ImmutableMap.h +++ b/include/llvm/ADT/ImmutableMap.h @@ -241,14 +241,14 @@ public: if (T) return &T->getValue().second; } - return 0; + return nullptr; } /// getMaxElement - Returns the <key,value> pair in the ImmutableMap for /// which key is the highest in the ordering of keys in the map. This /// method returns NULL if the map is empty. value_type* getMaxElement() const { - return Root ? &(Root->getMaxElement()->getValue()) : 0; + return Root ? &(Root->getMaxElement()->getValue()) : nullptr; } //===--------------------------------------------------===// diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h index ad349699e2a1..5a3d8ad21f92 100644 --- a/include/llvm/ADT/ImmutableSet.h +++ b/include/llvm/ADT/ImmutableSet.h @@ -81,7 +81,7 @@ public: else T = T->getRight(); } - return NULL; + return nullptr; } /// getMaxElement - Find the subtree associated with the highest ranged @@ -242,9 +242,9 @@ private: /// ImutAVLFactory. ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v, unsigned height) - : factory(f), left(l), right(r), prev(0), next(0), height(height), - IsMutable(true), IsDigestCached(false), IsCanonicalized(0), - value(v), digest(0), refCount(0) + : factory(f), left(l), right(r), prev(nullptr), next(nullptr), + height(height), IsMutable(true), IsDigestCached(false), + IsCanonicalized(0), value(v), digest(0), refCount(0) { if (left) left->retain(); if (right) right->retain(); @@ -411,7 +411,7 @@ public: return T; } - TreeTy* getEmptyTree() const { return NULL; } + TreeTy* getEmptyTree() const { return nullptr; } protected: @@ -607,7 +607,7 @@ protected: public: TreeTy *getCanonicalTree(TreeTy *TNew) { if (!TNew) - return 0; + return nullptr; if (TNew->IsCanonicalized) return TNew; @@ -619,7 +619,7 @@ public: do { if (!entry) break; - for (TreeTy *T = entry ; T != 0; T = T->next) { + for (TreeTy *T = entry ; T != nullptr; T = T->next) { // Compare the Contents('T') with Contents('TNew') typename TreeTy::iterator TI = T->begin(), TE = T->end(); if (!compareTreeWithSection(TNew, TI, TE)) @@ -696,12 +696,7 @@ public: } inline bool operator==(const _Self& x) const { - if (stack.size() != x.stack.size()) - return false; - for (unsigned i = 0 ; i < stack.size(); i++) - if (stack[i] != x.stack[i]) - return false; - return true; + return stack == x.stack; } inline bool operator!=(const _Self& x) const { return !operator==(x); } diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index 1ca3288a350a..46549eed9939 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -1177,7 +1177,7 @@ branchRoot(unsigned Position) { if (Nodes == 1) size[0] = rootSize; else - NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, NULL, size, + NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, nullptr, size, Position, true); // Allocate new nodes. @@ -1218,7 +1218,7 @@ splitRoot(unsigned Position) { if (Nodes == 1) Size[0] = rootSize; else - NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, NULL, Size, + NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, nullptr, Size, Position, true); // Allocate new nodes. @@ -1346,7 +1346,7 @@ protected: public: /// const_iterator - Create an iterator that isn't pointing anywhere. - const_iterator() : map(0) {} + const_iterator() : map(nullptr) {} /// setMap - Change the map iterated over. This call must be followed by a /// call to goToBegin(), goToEnd(), or find() diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index b8b88619957e..f9df3781257e 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -23,6 +23,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include <atomic> #include <memory> namespace llvm { @@ -88,6 +89,31 @@ namespace llvm { static void retain(T *obj) { obj->Retain(); } static void release(T *obj) { obj->Release(); } }; + +/// \brief A thread-safe version of \c llvm::RefCountedBase. +/// +/// A generic base class for objects that wish to have their lifetimes managed +/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to +/// obtain such functionality, and are typically handled with +/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the +/// management of reference counts. +template <class Derived> +class ThreadSafeRefCountedBase { + mutable std::atomic<int> RefCount; + +protected: + ThreadSafeRefCountedBase() : RefCount(0) {} + +public: + void Retain() const { ++RefCount; } + + void Release() const { + int NewRefCount = --RefCount; + assert(NewRefCount >= 0 && "Reference count was already zero."); + if (NewRefCount == 0) + delete static_cast<const Derived*>(this); + } +}; //===----------------------------------------------------------------------===// /// IntrusiveRefCntPtr - A template class that implements a "smart pointer" @@ -109,11 +135,11 @@ namespace llvm { template <typename T> class IntrusiveRefCntPtr { T* Obj; - typedef IntrusiveRefCntPtr this_type; + public: typedef T element_type; - explicit IntrusiveRefCntPtr() : Obj(0) {} + explicit IntrusiveRefCntPtr() : Obj(nullptr) {} IntrusiveRefCntPtr(T* obj) : Obj(obj) { retain(); @@ -123,20 +149,18 @@ namespace llvm { retain(); } -#if LLVM_HAS_RVALUE_REFERENCES IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { - S.Obj = 0; + S.Obj = nullptr; } template <class X> - IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) { + IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) { S.Obj = 0; } -#endif template <class X> IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) - : Obj(S.getPtr()) { + : Obj(S.get()) { retain(); } @@ -151,12 +175,9 @@ namespace llvm { T* operator->() const { return Obj; } - T* getPtr() const { return Obj; } + T* get() const { return Obj; } - typedef T* (IntrusiveRefCntPtr::*unspecified_bool_type) () const; - operator unspecified_bool_type() const { - return Obj == 0 ? 0 : &IntrusiveRefCntPtr::getPtr; - } + LLVM_EXPLICIT operator bool() const { return Obj; } void swap(IntrusiveRefCntPtr& other) { T* tmp = other.Obj; @@ -166,7 +187,7 @@ namespace llvm { void reset() { release(); - Obj = 0; + Obj = nullptr; } void resetWithoutRelease() { @@ -182,42 +203,62 @@ namespace llvm { inline bool operator==(const IntrusiveRefCntPtr<T>& A, const IntrusiveRefCntPtr<U>& B) { - return A.getPtr() == B.getPtr(); + return A.get() == B.get(); } template<class T, class U> inline bool operator!=(const IntrusiveRefCntPtr<T>& A, const IntrusiveRefCntPtr<U>& B) { - return A.getPtr() != B.getPtr(); + return A.get() != B.get(); } template<class T, class U> inline bool operator==(const IntrusiveRefCntPtr<T>& A, U* B) { - return A.getPtr() == B; + return A.get() == B; } template<class T, class U> inline bool operator!=(const IntrusiveRefCntPtr<T>& A, U* B) { - return A.getPtr() != B; + return A.get() != B; } template<class T, class U> inline bool operator==(T* A, const IntrusiveRefCntPtr<U>& B) { - return A == B.getPtr(); + return A == B.get(); } template<class T, class U> inline bool operator!=(T* A, const IntrusiveRefCntPtr<U>& B) { - return A != B.getPtr(); + return A != B.get(); + } + + template <class T> + bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { + return !B; + } + + template <class T> + bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { + return B == A; + } + + template <class T> + bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { + return !(A == B); + } + + template <class T> + bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { + return !(A == B); } //===----------------------------------------------------------------------===// @@ -227,14 +268,14 @@ namespace llvm { template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { typedef T* SimpleType; static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) { - return Val.getPtr(); + return Val.get(); } }; template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { typedef /*const*/ T* SimpleType; static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { - return Val.getPtr(); + return Val.get(); } }; diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index f6fcb0888de3..4e1fc1527270 100644 --- a/include/llvm/ADT/MapVector.h +++ b/include/llvm/ADT/MapVector.h @@ -1,4 +1,4 @@ -//===- llvm/ADT/MapVector.h - Map with deterministic value order *- C++ -*-===// +//===- llvm/ADT/MapVector.h - Map w/ deterministic value order --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,9 +17,7 @@ #ifndef LLVM_ADT_MAPVECTOR_H #define LLVM_ADT_MAPVECTOR_H -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" #include <vector> namespace llvm { @@ -31,7 +29,7 @@ template<typename KeyT, typename ValueT, typename MapType = llvm::DenseMap<KeyT, unsigned>, typename VectorType = std::vector<std::pair<KeyT, ValueT> > > class MapVector { - typedef typename VectorType::size_type SizeType; + typedef typename VectorType::size_type size_type; MapType Map; VectorType Vector; @@ -40,7 +38,7 @@ public: typedef typename VectorType::iterator iterator; typedef typename VectorType::const_iterator const_iterator; - SizeType size() const { + size_type size() const { return Vector.size(); } @@ -97,12 +95,12 @@ public: if (Result.second) { Vector.push_back(std::make_pair(KV.first, KV.second)); I = Vector.size() - 1; - return std::make_pair(llvm::prior(end()), true); + return std::make_pair(std::prev(end()), true); } return std::make_pair(begin() + I, false); } - unsigned count(const KeyT &Key) const { + size_type count(const KeyT &Key) const { typename MapType::const_iterator Pos = Map.find(Key); return Pos == Map.end()? 0 : 1; } @@ -125,8 +123,59 @@ public: Map.erase(Pos); Vector.pop_back(); } + + /// \brief Remove the element given by Iterator. + /// + /// Returns an iterator to the element following the one which was removed, + /// which may be end(). + /// + /// \note This is a deceivingly expensive operation (linear time). It's + /// usually better to use \a remove_if() if possible. + typename VectorType::iterator erase(typename VectorType::iterator Iterator) { + Map.erase(Iterator->first); + auto Next = Vector.erase(Iterator); + if (Next == Vector.end()) + return Next; + + // Update indices in the map. + size_t Index = Next - Vector.begin(); + for (auto &I : Map) { + assert(I.second != Index && "Index was already erased!"); + if (I.second > Index) + --I.second; + } + return Next; + } + + /// \brief Remove the elements that match the predicate. + /// + /// Erase all elements that match \c Pred in a single pass. Takes linear + /// time. + template <class Predicate> void remove_if(Predicate Pred); }; +template <typename KeyT, typename ValueT, typename MapType, typename VectorType> +template <class Function> +void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) { + auto O = Vector.begin(); + for (auto I = O, E = Vector.end(); I != E; ++I) { + if (Pred(*I)) { + // Erase from the map. + Map.erase(I->first); + continue; + } + + if (I != O) { + // Move the value and update the index in the map. + *O = std::move(*I); + Map[O->first] = O - Vector.begin(); + } + ++O; + } + // Erase trailing entries in the vector. + Vector.erase(O, Vector.end()); } +} // end namespace llvm + #endif diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 194e53fac213..ae8344da76a6 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -17,13 +17,10 @@ #define LLVM_ADT_OPTIONAL_H #include "llvm/ADT/None.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/AlignOf.h" +#include "llvm/Support/Compiler.h" #include <cassert> - -#if LLVM_HAS_RVALUE_REFERENCES #include <utility> -#endif namespace llvm { @@ -42,7 +39,6 @@ public: new (storage.buffer) T(*O); } -#if LLVM_HAS_RVALUE_REFERENCES Optional(T &&y) : hasVal(true) { new (storage.buffer) T(std::forward<T>(y)); } @@ -70,7 +66,6 @@ public: } return *this; } -#endif static inline Optional create(const T* y) { return y ? Optional(*y) : Optional(); diff --git a/include/llvm/ADT/OwningPtr.h b/include/llvm/ADT/OwningPtr.h deleted file mode 100644 index 6b9e42eaec0f..000000000000 --- a/include/llvm/ADT/OwningPtr.h +++ /dev/null @@ -1,153 +0,0 @@ -//===- llvm/ADT/OwningPtr.h - Smart ptr that owns the pointee ---*- 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 and implements the OwningPtr class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_OWNINGPTR_H -#define LLVM_ADT_OWNINGPTR_H - -#include "llvm/Support/Compiler.h" -#include <cassert> -#include <cstddef> - -namespace llvm { - -/// OwningPtr smart pointer - OwningPtr mimics a built-in pointer except that it -/// guarantees deletion of the object pointed to, either on destruction of the -/// OwningPtr or via an explicit reset(). Once created, ownership of the -/// pointee object can be taken away from OwningPtr by using the take method. -template<class T> -class OwningPtr { - OwningPtr(OwningPtr const &) LLVM_DELETED_FUNCTION; - OwningPtr &operator=(OwningPtr const &) LLVM_DELETED_FUNCTION; - T *Ptr; -public: - explicit OwningPtr(T *P = 0) : Ptr(P) {} - -#if LLVM_HAS_RVALUE_REFERENCES - OwningPtr(OwningPtr &&Other) : Ptr(Other.take()) {} - - OwningPtr &operator=(OwningPtr &&Other) { - reset(Other.take()); - return *this; - } -#endif - - ~OwningPtr() { - delete Ptr; - } - - /// reset - Change the current pointee to the specified pointer. Note that - /// calling this with any pointer (including a null pointer) deletes the - /// current pointer. - void reset(T *P = 0) { - if (P == Ptr) return; - T *Tmp = Ptr; - Ptr = P; - delete Tmp; - } - - /// take - Reset the owning pointer to null and return its pointer. This does - /// not delete the pointer before returning it. - T *take() { - T *Tmp = Ptr; - Ptr = 0; - return Tmp; - } - - T &operator*() const { - assert(Ptr && "Cannot dereference null pointer"); - return *Ptr; - } - - T *operator->() const { return Ptr; } - T *get() const { return Ptr; } - LLVM_EXPLICIT operator bool() const { return Ptr != 0; } - bool operator!() const { return Ptr == 0; } - bool isValid() const { return Ptr != 0; } - - void swap(OwningPtr &RHS) { - T *Tmp = RHS.Ptr; - RHS.Ptr = Ptr; - Ptr = Tmp; - } -}; - -template<class T> -inline void swap(OwningPtr<T> &a, OwningPtr<T> &b) { - a.swap(b); -} - -/// OwningArrayPtr smart pointer - OwningArrayPtr provides the same -/// functionality as OwningPtr, except that it works for array types. -template<class T> -class OwningArrayPtr { - OwningArrayPtr(OwningArrayPtr const &) LLVM_DELETED_FUNCTION; - OwningArrayPtr &operator=(OwningArrayPtr const &) LLVM_DELETED_FUNCTION; - T *Ptr; -public: - explicit OwningArrayPtr(T *P = 0) : Ptr(P) {} - -#if LLVM_HAS_RVALUE_REFERENCES - OwningArrayPtr(OwningArrayPtr &&Other) : Ptr(Other.take()) {} - - OwningArrayPtr &operator=(OwningArrayPtr &&Other) { - reset(Other.take()); - return *this; - } -#endif - - ~OwningArrayPtr() { - delete [] Ptr; - } - - /// reset - Change the current pointee to the specified pointer. Note that - /// calling this with any pointer (including a null pointer) deletes the - /// current pointer. - void reset(T *P = 0) { - if (P == Ptr) return; - T *Tmp = Ptr; - Ptr = P; - delete [] Tmp; - } - - /// take - Reset the owning pointer to null and return its pointer. This does - /// not delete the pointer before returning it. - T *take() { - T *Tmp = Ptr; - Ptr = 0; - return Tmp; - } - - T &operator[](std::ptrdiff_t i) const { - assert(Ptr && "Cannot dereference null pointer"); - return Ptr[i]; - } - - T *get() const { return Ptr; } - LLVM_EXPLICIT operator bool() const { return Ptr != 0; } - bool operator!() const { return Ptr == 0; } - - void swap(OwningArrayPtr &RHS) { - T *Tmp = RHS.Ptr; - RHS.Ptr = Ptr; - Ptr = Tmp; - } -}; - -template<class T> -inline void swap(OwningArrayPtr<T> &a, OwningArrayPtr<T> &b) { - a.swap(b); -} - -} // end namespace llvm - -#endif diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 0cfd470003af..45a40db85c04 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -17,6 +17,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> +#include <limits> namespace llvm { @@ -41,7 +42,12 @@ template <typename PointerTy, unsigned IntBits, typename IntType=unsigned, typename PtrTraits = PointerLikeTypeTraits<PointerTy> > class PointerIntPair { intptr_t Value; - enum LLVM_ENUM_INT_TYPE(uintptr_t) { + static_assert(PtrTraits::NumLowBitsAvailable < + std::numeric_limits<uintptr_t>::digits, + "cannot use a pointer type that has all bits free"); + static_assert(IntBits <= PtrTraits::NumLowBitsAvailable, + "PointerIntPair with integer size too large for pointer"); + enum : uintptr_t { /// PointerBitMask - The bits that come from the pointer. PointerBitMask = ~(uintptr_t)(((intptr_t)1 << PtrTraits::NumLowBitsAvailable)-1), @@ -59,8 +65,6 @@ class PointerIntPair { public: PointerIntPair() : Value(0) {} PointerIntPair(PointerTy PtrVal, IntType IntVal) { - assert(IntBits <= PtrTraits::NumLowBitsAvailable && - "PointerIntPair formed with integer size too large for pointer"); setPointerAndInt(PtrVal, IntVal); } explicit PointerIntPair(PointerTy PtrVal) { @@ -79,7 +83,7 @@ public: void setPointer(PointerTy PtrVal) { intptr_t PtrWord = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal)); - assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + assert((PtrWord & ~PointerBitMask) == 0 && "Pointer is not sufficiently aligned"); // Preserve all low bits, just update the pointer. Value = PtrWord | (Value & ~PointerBitMask); @@ -87,7 +91,7 @@ public: void setInt(IntType IntVal) { intptr_t IntWord = static_cast<intptr_t>(IntVal); - assert(IntWord < (1 << IntBits) && "Integer too large for field"); + assert((IntWord & ~IntMask) == 0 && "Integer too large for field"); // Preserve all bits other than the ones we are updating. Value &= ~ShiftedIntMask; // Remove integer field. @@ -97,7 +101,7 @@ public: void initWithPointer(PointerTy PtrVal) { intptr_t PtrWord = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal)); - assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + assert((PtrWord & ~PointerBitMask) == 0 && "Pointer is not sufficiently aligned"); Value = PtrWord; } @@ -105,10 +109,10 @@ public: void setPointerAndInt(PointerTy PtrVal, IntType IntVal) { intptr_t PtrWord = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal)); - assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + assert((PtrWord & ~PointerBitMask) == 0 && "Pointer is not sufficiently aligned"); intptr_t IntWord = static_cast<intptr_t>(IntVal); - assert(IntWord < (1 << IntBits) && "Integer too large for field"); + assert((IntWord & ~IntMask) == 0 && "Integer too large for field"); Value = PtrWord | (IntWord << IntShift); } @@ -158,13 +162,13 @@ struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType> > { typedef PointerIntPair<PointerTy, IntBits, IntType> Ty; static Ty getEmptyKey() { uintptr_t Val = static_cast<uintptr_t>(-1); - Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable; - return Ty(reinterpret_cast<PointerTy>(Val), IntType((1 << IntBits)-1)); + Val <<= PointerLikeTypeTraits<Ty>::NumLowBitsAvailable; + return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val)); } static Ty getTombstoneKey() { uintptr_t Val = static_cast<uintptr_t>(-2); Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable; - return Ty(reinterpret_cast<PointerTy>(Val), IntType(0)); + return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val)); } static unsigned getHashValue(Ty V) { uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue()); diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h index 05d362feab22..a6dddd277621 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -15,8 +15,9 @@ #ifndef LLVM_ADT_POINTERUNION_H #define LLVM_ADT_POINTERUNION_H -#include "llvm/Support/Compiler.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Compiler.h" namespace llvm { @@ -153,6 +154,12 @@ namespace llvm { "Can't get the address because PointerLikeTypeTraits changes the ptr"); return (PT1 *)Val.getAddrOfPointer(); } + + /// \brief Assignment from nullptr which just clears the union. + const PointerUnion &operator=(std::nullptr_t) { + Val.initWithPointer(nullptr); + return *this; + } /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. @@ -297,6 +304,12 @@ namespace llvm { if (is<T>()) return get<T>(); return T(); } + + /// \brief Assignment from nullptr which just clears the union. + const PointerUnion3 &operator=(std::nullptr_t) { + Val = nullptr; + return *this; + } /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. @@ -406,6 +419,12 @@ namespace llvm { if (is<T>()) return get<T>(); return T(); } + + /// \brief Assignment from nullptr which just clears the union. + const PointerUnion4 &operator=(std::nullptr_t) { + Val = nullptr; + return *this; + } /// Assignment operators - Allow assigning into this union from either /// pointer type, setting the discriminator to remember what it came from. @@ -455,6 +474,33 @@ namespace llvm { ::NumLowBitsAvailable }; }; + + // Teach DenseMap how to use PointerUnions as keys. + template<typename T, typename U> + struct DenseMapInfo<PointerUnion<T, U> > { + typedef PointerUnion<T, U> Pair; + typedef DenseMapInfo<T> FirstInfo; + typedef DenseMapInfo<U> SecondInfo; + + static inline Pair getEmptyKey() { + return Pair(FirstInfo::getEmptyKey()); + } + static inline Pair getTombstoneKey() { + return Pair(FirstInfo::getTombstoneKey()); + } + static unsigned getHashValue(const Pair &PairVal) { + intptr_t key = (intptr_t)PairVal.getOpaqueValue(); + return DenseMapInfo<intptr_t>::getHashValue(key); + } + static bool isEqual(const Pair &LHS, const Pair &RHS) { + return LHS.template is<T>() == RHS.template is<T>() && + (LHS.template is<T>() ? + FirstInfo::isEqual(LHS.template get<T>(), + RHS.template get<T>()) : + SecondInfo::isEqual(LHS.template get<U>(), + RHS.template get<U>())); + } + }; } #endif diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index 59fa3f39c91e..dd8cc74b714e 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -111,7 +111,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag, } inline po_iterator(NodeType *BB) { - this->insertEdge((NodeType*)0, BB); + this->insertEdge((NodeType*)nullptr, BB); VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); traverseChild(); } @@ -119,7 +119,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag, inline po_iterator(NodeType *BB, SetType &S) : po_iterator_storage<SetType, ExtStorage>(S) { - if (this->insertEdge((NodeType*)0, BB)) { + if (this->insertEdge((NodeType*)nullptr, BB)) { VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB))); traverseChild(); } diff --git a/include/llvm/ADT/SCCIterator.h b/include/llvm/ADT/SCCIterator.h index 8ce4fd53bacd..bc74416ac88b 100644 --- a/include/llvm/ADT/SCCIterator.h +++ b/include/llvm/ADT/SCCIterator.h @@ -6,16 +6,18 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected -// components (SCCs) of a graph in O(N+E) time using Tarjan's DFS algorithm. -// -// The SCC iterator has the important property that if a node in SCC S1 has an -// edge to a node in SCC S2, then it visits S1 *after* S2. -// -// To visit S1 *before* S2, use the scc_iterator on the Inverse graph. -// (NOTE: This requires some simple wrappers and is not supported yet.) -// +/// \file +/// +/// This builds on the llvm/ADT/GraphTraits.h file to find the strongly +/// connected components (SCCs) of a graph in O(N+E) time using Tarjan's DFS +/// algorithm. +/// +/// The SCC iterator has the important property that if a node in SCC S1 has an +/// edge to a node in SCC S2, then it visits S1 *after* S2. +/// +/// To visit S1 *before* S2, use the scc_iterator on the Inverse graph. (NOTE: +/// This requires some simple wrappers and is not supported yet.) +/// //===----------------------------------------------------------------------===// #ifndef LLVM_ADT_SCCITERATOR_H @@ -23,169 +25,112 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator.h" #include <vector> namespace llvm { -//===----------------------------------------------------------------------===// -/// -/// scc_iterator - Enumerate the SCCs of a directed graph, in -/// reverse topological order of the SCC DAG. +/// \brief Enumerate the SCCs of a directed graph in reverse topological order +/// of the SCC DAG. /// -template<class GraphT, class GT = GraphTraits<GraphT> > +/// This is implemented using Tarjan's DFS algorithm using an internal stack to +/// build up a vector of nodes in a particular SCC. Note that it is a forward +/// iterator and thus you cannot backtrack or re-visit nodes. +template <class GraphT, class GT = GraphTraits<GraphT>> class scc_iterator - : public std::iterator<std::forward_iterator_tag, - std::vector<typename GT::NodeType>, ptrdiff_t> { - typedef typename GT::NodeType NodeType; + : public iterator_facade_base< + scc_iterator<GraphT, GT>, std::forward_iterator_tag, + const std::vector<typename GT::NodeType *>, ptrdiff_t> { + typedef typename GT::NodeType NodeType; typedef typename GT::ChildIteratorType ChildItTy; - typedef std::vector<NodeType*> SccTy; - typedef std::iterator<std::forward_iterator_tag, - std::vector<typename GT::NodeType>, ptrdiff_t> super; - typedef typename super::reference reference; - typedef typename super::pointer pointer; - - // The visit counters used to detect when a complete SCC is on the stack. - // visitNum is the global counter. - // nodeVisitNumbers are per-node visit numbers, also used as DFS flags. + typedef std::vector<NodeType *> SccTy; + typedef typename scc_iterator::reference reference; + + /// Element of VisitStack during DFS. + struct StackElement { + NodeType *Node; ///< The current node pointer. + ChildItTy NextChild; ///< The next child, modified inplace during DFS. + unsigned MinVisited; ///< Minimum uplink value of all children of Node. + + StackElement(NodeType *Node, const ChildItTy &Child, unsigned Min) + : Node(Node), NextChild(Child), MinVisited(Min) {} + + bool operator==(const StackElement &Other) const { + return Node == Other.Node && + NextChild == Other.NextChild && + MinVisited == Other.MinVisited; + } + }; + + /// The visit counters used to detect when a complete SCC is on the stack. + /// visitNum is the global counter. + /// + /// nodeVisitNumbers are per-node visit numbers, also used as DFS flags. unsigned visitNum; DenseMap<NodeType *, unsigned> nodeVisitNumbers; - // SCCNodeStack - Stack holding nodes of the SCC. + /// Stack holding nodes of the SCC. std::vector<NodeType *> SCCNodeStack; - // CurrentSCC - The current SCC, retrieved using operator*(). + /// The current SCC, retrieved using operator*(). SccTy CurrentSCC; - // VisitStack - Used to maintain the ordering. Top = current block - // First element is basic block pointer, second is the 'next child' to visit - std::vector<std::pair<NodeType *, ChildItTy> > VisitStack; - - // MinVisitNumStack - Stack holding the "min" values for each node in the DFS. - // This is used to track the minimum uplink values for all children of - // the corresponding node on the VisitStack. - std::vector<unsigned> MinVisitNumStack; - - // A single "visit" within the non-recursive DFS traversal. - void DFSVisitOne(NodeType *N) { - ++visitNum; // Global counter for the visit order - nodeVisitNumbers[N] = visitNum; - SCCNodeStack.push_back(N); - MinVisitNumStack.push_back(visitNum); - VisitStack.push_back(std::make_pair(N, GT::child_begin(N))); - //dbgs() << "TarjanSCC: Node " << N << - // " : visitNum = " << visitNum << "\n"; - } + /// DFS stack, Used to maintain the ordering. The top contains the current + /// node, the next child to visit, and the minimum uplink value of all child + std::vector<StackElement> VisitStack; - // The stack-based DFS traversal; defined below. - void DFSVisitChildren() { - assert(!VisitStack.empty()); - while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { - // TOS has at least one more child so continue DFS - NodeType *childN = *VisitStack.back().second++; - if (!nodeVisitNumbers.count(childN)) { - // this node has never been seen. - DFSVisitOne(childN); - continue; - } - - unsigned childNum = nodeVisitNumbers[childN]; - if (MinVisitNumStack.back() > childNum) - MinVisitNumStack.back() = childNum; - } - } + /// A single "visit" within the non-recursive DFS traversal. + void DFSVisitOne(NodeType *N); - // Compute the next SCC using the DFS traversal. - void GetNextSCC() { - assert(VisitStack.size() == MinVisitNumStack.size()); - CurrentSCC.clear(); // Prepare to compute the next SCC - while (!VisitStack.empty()) { - DFSVisitChildren(); - assert(VisitStack.back().second ==GT::child_end(VisitStack.back().first)); - NodeType *visitingN = VisitStack.back().first; - unsigned minVisitNum = MinVisitNumStack.back(); - VisitStack.pop_back(); - MinVisitNumStack.pop_back(); - if (!MinVisitNumStack.empty() && MinVisitNumStack.back() > minVisitNum) - MinVisitNumStack.back() = minVisitNum; - - //dbgs() << "TarjanSCC: Popped node " << visitingN << - // " : minVisitNum = " << minVisitNum << "; Node visit num = " << - // nodeVisitNumbers[visitingN] << "\n"; - - if (minVisitNum != nodeVisitNumbers[visitingN]) - continue; - - // A full SCC is on the SCCNodeStack! It includes all nodes below - // visitingN on the stack. Copy those nodes to CurrentSCC, - // reset their minVisit values, and return (this suspends - // the DFS traversal till the next ++). - do { - CurrentSCC.push_back(SCCNodeStack.back()); - SCCNodeStack.pop_back(); - nodeVisitNumbers[CurrentSCC.back()] = ~0U; - } while (CurrentSCC.back() != visitingN); - return; - } - } + /// The stack-based DFS traversal; defined below. + void DFSVisitChildren(); + + /// Compute the next SCC using the DFS traversal. + void GetNextSCC(); - inline scc_iterator(NodeType *entryN) : visitNum(0) { + scc_iterator(NodeType *entryN) : visitNum(0) { DFSVisitOne(entryN); GetNextSCC(); } - inline scc_iterator() { /* End is when DFS stack is empty */ } -public: - typedef scc_iterator<GraphT, GT> _Self; + /// End is when the DFS stack is empty. + scc_iterator() {} - // Provide static "constructors"... - static inline _Self begin(const GraphT &G){return _Self(GT::getEntryNode(G));} - static inline _Self end (const GraphT &) { return _Self(); } +public: + static scc_iterator begin(const GraphT &G) { + return scc_iterator(GT::getEntryNode(G)); + } + static scc_iterator end(const GraphT &) { return scc_iterator(); } - // Direct loop termination test: I.isAtEnd() is more efficient than I == end() - inline bool isAtEnd() const { + /// \brief Direct loop termination test which is more efficient than + /// comparison with \c end(). + bool isAtEnd() const { assert(!CurrentSCC.empty() || VisitStack.empty()); return CurrentSCC.empty(); } - inline bool operator==(const _Self& x) const { + bool operator==(const scc_iterator &x) const { return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC; } - inline bool operator!=(const _Self& x) const { return !operator==(x); } - // Iterator traversal: forward iteration only - inline _Self& operator++() { // Preincrement + scc_iterator &operator++() { GetNextSCC(); return *this; } - inline _Self operator++(int) { // Postincrement - _Self tmp = *this; ++*this; return tmp; - } - // Retrieve a reference to the current SCC - inline const SccTy &operator*() const { - assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); - return CurrentSCC; - } - inline SccTy &operator*() { + reference operator*() const { assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); return CurrentSCC; } - // hasLoop() -- Test if the current SCC has a loop. If it has more than one - // node, this is trivially true. If not, it may still contain a loop if the - // node has an edge back to itself. - bool hasLoop() const { - assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); - if (CurrentSCC.size() > 1) return true; - NodeType *N = CurrentSCC.front(); - for (ChildItTy CI = GT::child_begin(N), CE=GT::child_end(N); CI != CE; ++CI) - if (*CI == N) - return true; - return false; - } + /// \brief Test if the current SCC has a loop. + /// + /// If the SCC has more than one node, this is trivially true. If not, it may + /// still contain a loop if the node has an edge back to itself. + bool hasLoop() const; - /// ReplaceNode - This informs the scc_iterator that the specified Old node - /// has been deleted, and New is to be used in its place. + /// This informs the \c scc_iterator that the specified \c Old node + /// has been deleted, and \c New is to be used in its place. void ReplaceNode(NodeType *Old, NodeType *New) { assert(nodeVisitNumbers.count(Old) && "Old not in scc_iterator?"); nodeVisitNumbers[New] = nodeVisitNumbers[Old]; @@ -193,25 +138,105 @@ public: } }; +template <class GraphT, class GT> +void scc_iterator<GraphT, GT>::DFSVisitOne(NodeType *N) { + ++visitNum; + nodeVisitNumbers[N] = visitNum; + SCCNodeStack.push_back(N); + VisitStack.push_back(StackElement(N, GT::child_begin(N), visitNum)); +#if 0 // Enable if needed when debugging. + dbgs() << "TarjanSCC: Node " << N << + " : visitNum = " << visitNum << "\n"; +#endif +} + +template <class GraphT, class GT> +void scc_iterator<GraphT, GT>::DFSVisitChildren() { + assert(!VisitStack.empty()); + while (VisitStack.back().NextChild != GT::child_end(VisitStack.back().Node)) { + // TOS has at least one more child so continue DFS + NodeType *childN = *VisitStack.back().NextChild++; + typename DenseMap<NodeType *, unsigned>::iterator Visited = + nodeVisitNumbers.find(childN); + if (Visited == nodeVisitNumbers.end()) { + // this node has never been seen. + DFSVisitOne(childN); + continue; + } + + unsigned childNum = Visited->second; + if (VisitStack.back().MinVisited > childNum) + VisitStack.back().MinVisited = childNum; + } +} + +template <class GraphT, class GT> void scc_iterator<GraphT, GT>::GetNextSCC() { + CurrentSCC.clear(); // Prepare to compute the next SCC + while (!VisitStack.empty()) { + DFSVisitChildren(); + + // Pop the leaf on top of the VisitStack. + NodeType *visitingN = VisitStack.back().Node; + unsigned minVisitNum = VisitStack.back().MinVisited; + assert(VisitStack.back().NextChild == GT::child_end(visitingN)); + VisitStack.pop_back(); + + // Propagate MinVisitNum to parent so we can detect the SCC starting node. + if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum) + VisitStack.back().MinVisited = minVisitNum; + +#if 0 // Enable if needed when debugging. + dbgs() << "TarjanSCC: Popped node " << visitingN << + " : minVisitNum = " << minVisitNum << "; Node visit num = " << + nodeVisitNumbers[visitingN] << "\n"; +#endif + + if (minVisitNum != nodeVisitNumbers[visitingN]) + continue; + + // A full SCC is on the SCCNodeStack! It includes all nodes below + // visitingN on the stack. Copy those nodes to CurrentSCC, + // reset their minVisit values, and return (this suspends + // the DFS traversal till the next ++). + do { + CurrentSCC.push_back(SCCNodeStack.back()); + SCCNodeStack.pop_back(); + nodeVisitNumbers[CurrentSCC.back()] = ~0U; + } while (CurrentSCC.back() != visitingN); + return; + } +} + +template <class GraphT, class GT> +bool scc_iterator<GraphT, GT>::hasLoop() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + if (CurrentSCC.size() > 1) + return true; + NodeType *N = CurrentSCC.front(); + for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE; + ++CI) + if (*CI == N) + return true; + return false; + } -// Global constructor for the SCC iterator. -template <class T> -scc_iterator<T> scc_begin(const T &G) { +/// \brief Construct the begin iterator for a deduced graph type T. +template <class T> scc_iterator<T> scc_begin(const T &G) { return scc_iterator<T>::begin(G); } -template <class T> -scc_iterator<T> scc_end(const T &G) { +/// \brief Construct the end iterator for a deduced graph type T. +template <class T> scc_iterator<T> scc_end(const T &G) { return scc_iterator<T>::end(G); } -template <class T> -scc_iterator<Inverse<T> > scc_begin(const Inverse<T> &G) { +/// \brief Construct the begin iterator for a deduced graph type T's Inverse<T>. +template <class T> scc_iterator<Inverse<T> > scc_begin(const Inverse<T> &G) { return scc_iterator<Inverse<T> >::begin(G); } -template <class T> -scc_iterator<Inverse<T> > scc_end(const Inverse<T> &G) { +/// \brief Construct the end iterator for a deduced graph type T's Inverse<T>. +template <class T> scc_iterator<Inverse<T> > scc_end(const Inverse<T> &G) { return scc_iterator<Inverse<T> >::end(G); } diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 3aa818335321..1cef3933b5d6 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -17,10 +17,12 @@ #ifndef LLVM_ADT_STLEXTRAS_H #define LLVM_ADT_STLEXTRAS_H +#include "llvm/Support/Compiler.h" #include <cstddef> // for std::size_t #include <cstdlib> // for qsort #include <functional> #include <iterator> +#include <memory> #include <utility> // for std::pair namespace llvm { @@ -53,6 +55,131 @@ struct greater_ptr : public std::binary_function<Ty, Ty, bool> { } }; +/// An efficient, type-erasing, non-owning reference to a callable. This is +/// intended for use as the type of a function parameter that is not used +/// after the function in question returns. +/// +/// This class does not own the callable, so it is not in general safe to store +/// a function_ref. +template<typename Fn> class function_ref; + +#if LLVM_HAS_VARIADIC_TEMPLATES + +template<typename Ret, typename ...Params> +class function_ref<Ret(Params...)> { + Ret (*callback)(intptr_t callable, Params ...params); + intptr_t callable; + + template<typename Callable> + static Ret callback_fn(intptr_t callable, Params ...params) { + return (*reinterpret_cast<Callable*>(callable))( + std::forward<Params>(params)...); + } + +public: + template<typename Callable> + function_ref(Callable &&callable) + : callback(callback_fn<typename std::remove_reference<Callable>::type>), + callable(reinterpret_cast<intptr_t>(&callable)) {} + Ret operator()(Params ...params) const { + return callback(callable, std::forward<Params>(params)...); + } +}; + +#else + +template<typename Ret> +class function_ref<Ret()> { + Ret (*callback)(intptr_t callable); + intptr_t callable; + + template<typename Callable> + static Ret callback_fn(intptr_t callable) { + return (*reinterpret_cast<Callable*>(callable))(); + } + +public: + template<typename Callable> + function_ref(Callable &&callable) + : callback(callback_fn<typename std::remove_reference<Callable>::type>), + callable(reinterpret_cast<intptr_t>(&callable)) {} + Ret operator()() const { return callback(callable); } +}; + +template<typename Ret, typename Param1> +class function_ref<Ret(Param1)> { + Ret (*callback)(intptr_t callable, Param1 param1); + intptr_t callable; + + template<typename Callable> + static Ret callback_fn(intptr_t callable, Param1 param1) { + return (*reinterpret_cast<Callable*>(callable))( + std::forward<Param1>(param1)); + } + +public: + template<typename Callable> + function_ref(Callable &&callable) + : callback(callback_fn<typename std::remove_reference<Callable>::type>), + callable(reinterpret_cast<intptr_t>(&callable)) {} + Ret operator()(Param1 param1) { + return callback(callable, std::forward<Param1>(param1)); + } +}; + +template<typename Ret, typename Param1, typename Param2> +class function_ref<Ret(Param1, Param2)> { + Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2); + intptr_t callable; + + template<typename Callable> + static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2) { + return (*reinterpret_cast<Callable*>(callable))( + std::forward<Param1>(param1), + std::forward<Param2>(param2)); + } + +public: + template<typename Callable> + function_ref(Callable &&callable) + : callback(callback_fn<typename std::remove_reference<Callable>::type>), + callable(reinterpret_cast<intptr_t>(&callable)) {} + Ret operator()(Param1 param1, Param2 param2) { + return callback(callable, + std::forward<Param1>(param1), + std::forward<Param2>(param2)); + } +}; + +template<typename Ret, typename Param1, typename Param2, typename Param3> +class function_ref<Ret(Param1, Param2, Param3)> { + Ret (*callback)(intptr_t callable, Param1 param1, Param2 param2, Param3 param3); + intptr_t callable; + + template<typename Callable> + static Ret callback_fn(intptr_t callable, Param1 param1, Param2 param2, + Param3 param3) { + return (*reinterpret_cast<Callable*>(callable))( + std::forward<Param1>(param1), + std::forward<Param2>(param2), + std::forward<Param3>(param3)); + } + +public: + template<typename Callable> + function_ref(Callable &&callable) + : callback(callback_fn<typename std::remove_reference<Callable>::type>), + callable(reinterpret_cast<intptr_t>(&callable)) {} + Ret operator()(Param1 param1, Param2 param2, Param3 param3) { + return callback(callable, + std::forward<Param1>(param1), + std::forward<Param2>(param2), + std::forward<Param3>(param3)); + } +}; + +#endif + // deleter - Very very very simple method that is used to invoke operator // delete on something. It is used like this: // @@ -95,8 +222,6 @@ public: inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) : current(I), Fn(F) {} - inline mapped_iterator(const mapped_iterator &It) - : current(It.current), Fn(It.Fn) {} inline value_type operator*() const { // All this work to do this return Fn(*current); // little change @@ -141,82 +266,10 @@ inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) { return mapped_iterator<ItTy, FuncTy>(I, F); } - -// next/prior - These functions unlike std::advance do not modify the -// passed iterator but return a copy. -// -// next(myIt) returns copy of myIt incremented once -// next(myIt, n) returns copy of myIt incremented n times -// prior(myIt) returns copy of myIt decremented once -// prior(myIt, n) returns copy of myIt decremented n times - -template <typename ItTy, typename Dist> -inline ItTy next(ItTy it, Dist n) -{ - std::advance(it, n); - return it; -} - -template <typename ItTy> -inline ItTy next(ItTy it) -{ - return ++it; -} - -template <typename ItTy, typename Dist> -inline ItTy prior(ItTy it, Dist n) -{ - std::advance(it, -n); - return it; -} - -template <typename ItTy> -inline ItTy prior(ItTy it) -{ - return --it; -} - //===----------------------------------------------------------------------===// // Extra additions to <utility> //===----------------------------------------------------------------------===// -// tie - this function ties two objects and returns a temporary object -// that is assignable from a std::pair. This can be used to make code -// more readable when using values returned from functions bundled in -// a std::pair. Since an example is worth 1000 words: -// -// typedef std::map<int, int> Int2IntMap; -// -// Int2IntMap myMap; -// Int2IntMap::iterator where; -// bool inserted; -// tie(where, inserted) = myMap.insert(std::make_pair(123,456)); -// -// if (inserted) -// // do stuff -// else -// // do other stuff -template <typename T1, typename T2> -struct tier { - typedef T1 &first_type; - typedef T2 &second_type; - - first_type first; - second_type second; - - tier(first_type f, second_type s) : first(f), second(s) { } - tier& operator=(const std::pair<T1, T2>& p) { - first = p.first; - second = p.second; - return *this; - } -}; - -template <typename T1, typename T2> -inline tier<T1, T2> tie(T1& f, T2& s) { - return tier<T1, T2>(f, s); -} - /// \brief Function object to check whether the first component of a std::pair /// compares less than the first component of another std::pair. struct less_first { @@ -237,27 +290,20 @@ struct less_second { // Extra additions for arrays //===----------------------------------------------------------------------===// -/// Find where an array ends (for ending iterators) -/// This returns a pointer to the byte immediately -/// after the end of an array. -template<class T, std::size_t N> -inline T *array_endof(T (&x)[N]) { - return x+N; -} - /// Find the length of an array. -template<class T, std::size_t N> -inline size_t array_lengthof(T (&)[N]) { +template <class T, std::size_t N> +LLVM_CONSTEXPR inline size_t array_lengthof(T (&)[N]) { return N; } -/// array_pod_sort_comparator - This is helper function for array_pod_sort, -/// which just uses operator< on T. +/// Adapt std::less<T> for array_pod_sort. template<typename T> inline int array_pod_sort_comparator(const void *P1, const void *P2) { - if (*reinterpret_cast<const T*>(P1) < *reinterpret_cast<const T*>(P2)) + if (std::less<T>()(*reinterpret_cast<const T*>(P1), + *reinterpret_cast<const T*>(P2))) return -1; - if (*reinterpret_cast<const T*>(P2) < *reinterpret_cast<const T*>(P1)) + if (std::less<T>()(*reinterpret_cast<const T*>(P2), + *reinterpret_cast<const T*>(P1))) return 1; return 0; } @@ -280,7 +326,7 @@ inline int (*get_array_pod_sort_comparator(const T &)) /// possible. /// /// This function assumes that you have simple POD-like types that can be -/// compared with operator< and can be moved with memcpy. If this isn't true, +/// compared with std::less and can be moved with memcpy. If this isn't true, /// you should use std::sort. /// /// NOTE: If qsort_r were portable, we could allow a custom comparator and @@ -327,6 +373,170 @@ void DeleteContainerSeconds(Container &C) { C.clear(); } +//===----------------------------------------------------------------------===// +// Extra additions to <memory> +//===----------------------------------------------------------------------===// + +#if LLVM_HAS_VARIADIC_TEMPLATES + +// Implement make_unique according to N3656. + +/// \brief Constructs a `new T()` with the given args and returns a +/// `unique_ptr<T>` which owns the object. +/// +/// Example: +/// +/// auto p = make_unique<int>(); +/// auto p = make_unique<std::tuple<int, int>>(0, 1); +template <class T, class... Args> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Args &&... args) { + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} + +/// \brief Constructs a `new T[n]` with the given args and returns a +/// `unique_ptr<T[]>` which owns the object. +/// +/// \param n size of the new array. +/// +/// Example: +/// +/// auto p = make_unique<int[]>(2); // value-initializes the array with 0's. +template <class T> +typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0, + std::unique_ptr<T>>::type +make_unique(size_t n) { + return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); +} + +/// This function isn't used and is only here to provide better compile errors. +template <class T, class... Args> +typename std::enable_if<std::extent<T>::value != 0>::type +make_unique(Args &&...) LLVM_DELETED_FUNCTION; + +#else + +template <class T> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique() { + return std::unique_ptr<T>(new T()); +} + +template <class T, class Arg1> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1) { + return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1))); +} + +template <class T, class Arg1, class Arg2> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2))); +} + +template <class T, class Arg1, class Arg2, class Arg3> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3) { + return std::unique_ptr<T>(new T(std::forward<Arg1>(arg1), + std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, + class Arg6> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, + Arg6 &&arg6) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5), std::forward<Arg6>(arg6))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, + class Arg6, class Arg7> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, + Arg6 &&arg6, Arg7 &&arg7) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), + std::forward<Arg7>(arg7))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, + class Arg6, class Arg7, class Arg8> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, + Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), + std::forward<Arg7>(arg7), std::forward<Arg8>(arg8))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, + class Arg6, class Arg7, class Arg8, class Arg9> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, + Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), + std::forward<Arg7>(arg7), std::forward<Arg8>(arg8), + std::forward<Arg9>(arg9))); +} + +template <class T, class Arg1, class Arg2, class Arg3, class Arg4, class Arg5, + class Arg6, class Arg7, class Arg8, class Arg9, class Arg10> +typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type +make_unique(Arg1 &&arg1, Arg2 &&arg2, Arg3 &&arg3, Arg4 &&arg4, Arg5 &&arg5, + Arg6 &&arg6, Arg7 &&arg7, Arg8 &&arg8, Arg9 &&arg9, Arg10 &&arg10) { + return std::unique_ptr<T>( + new T(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), + std::forward<Arg3>(arg3), std::forward<Arg4>(arg4), + std::forward<Arg5>(arg5), std::forward<Arg6>(arg6), + std::forward<Arg7>(arg7), std::forward<Arg8>(arg8), + std::forward<Arg9>(arg9), std::forward<Arg10>(arg10))); +} + +template <class T> +typename std::enable_if<std::is_array<T>::value &&std::extent<T>::value == 0, + std::unique_ptr<T>>::type +make_unique(size_t n) { + return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); +} + +#endif + +template<typename First, typename Second> +struct pair_hash { + size_t operator()(const std::pair<First, Second> &P) const { + return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second); + } +}; + } // End llvm namespace #endif diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index efddd9f9b857..02a6ea345834 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -148,6 +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;
private: typedef ScopedHashTableVal<K, V> ValTy; DenseMap<K, ValTy*, KInfo> TopLevelMap; @@ -159,20 +160,19 @@ private: void operator=(const ScopedHashTable&); // NOT YET IMPLEMENTED friend class ScopedHashTableScope<K, V, KInfo, AllocatorTy>; public: - ScopedHashTable() : CurScope(0) {} + ScopedHashTable() : CurScope(nullptr) {} ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {} ~ScopedHashTable() { - assert(CurScope == 0 && TopLevelMap.empty() && "Scope imbalance!"); + assert(!CurScope && TopLevelMap.empty() && "Scope imbalance!"); } /// Access to the allocator. - typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy; - typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy; - AllocatorRefTy getAllocator() { return Allocator; } - AllocatorCRefTy getAllocator() const { return Allocator; } + AllocatorTy &getAllocator() { return Allocator; } + const AllocatorTy &getAllocator() const { return Allocator; } - bool count(const K &Key) const { + /// Return 1 if the specified key is in the table, 0 otherwise.
+ size_type count(const K &Key) const { return TopLevelMap.count(Key); } @@ -222,7 +222,7 @@ ScopedHashTableScope<K, V, KInfo, Allocator>:: ScopedHashTableScope(ScopedHashTable<K, V, KInfo, Allocator> &ht) : HT(ht) { PrevScope = HT.CurScope; HT.CurScope = this; - LastValInScope = 0; + LastValInScope = nullptr; } template <typename K, typename V, typename KInfo, typename Allocator> @@ -233,7 +233,7 @@ ScopedHashTableScope<K, V, KInfo, Allocator>::~ScopedHashTableScope() { // Pop and delete all values corresponding to this scope. while (ScopedHashTableVal<K, V> *ThisEntry = LastValInScope) { // Pop this value out of the TopLevelMap. - if (ThisEntry->getNextForKey() == 0) { + if (!ThisEntry->getNextForKey()) { assert(HT.TopLevelMap[ThisEntry->getKey()] == ThisEntry && "Scope imbalance!"); HT.TopLevelMap.erase(ThisEntry->getKey()); diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h index 5eda37c675fe..1e7d237045aa 100644 --- a/include/llvm/ADT/SetVector.h +++ b/include/llvm/ADT/SetVector.h @@ -195,11 +195,10 @@ private: set_type &set_; public: - typedef typename UnaryPredicate::argument_type argument_type; - TestAndEraseFromSet(UnaryPredicate P, set_type &set_) : P(P), set_(set_) {} - bool operator()(argument_type Arg) { + template <typename ArgumentT> + bool operator()(const ArgumentT &Arg) { if (P(Arg)) { set_.erase(Arg); return true; diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index 86949b2ae342..0922017ea61a 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -54,6 +54,7 @@ class SmallBitVector { }; public: + typedef unsigned size_type;
// Encapsulation of a single bit. class reference { SmallBitVector &TheVector; @@ -153,11 +154,9 @@ public: switchToLarge(new BitVector(*RHS.getPointer())); } -#if LLVM_HAS_RVALUE_REFERENCES SmallBitVector(SmallBitVector &&RHS) : X(RHS.X) { RHS.X = 1; } -#endif ~SmallBitVector() { if (!isSmall()) @@ -175,7 +174,7 @@ public: } /// count - Returns the number of bits which are set. - unsigned count() const { + size_type count() const { if (isSmall()) { uintptr_t Bits = getSmallBits(); if (NumBaseBits == 32) @@ -506,7 +505,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES const SmallBitVector &operator=(SmallBitVector &&RHS) { if (this != &RHS) { clear(); @@ -514,7 +512,6 @@ public: } return *this; } -#endif void swap(SmallBitVector &RHS) { std::swap(X, RHS.X); diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index bd0d8838ef02..74f3fd43cec4 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file defines the SmallPtrSet class. See the doxygen comment for -// SmallPtrSetImpl for more details on the algorithm used. +// SmallPtrSetImplBase for more details on the algorithm used. // //===----------------------------------------------------------------------===// @@ -27,7 +27,7 @@ namespace llvm { class SmallPtrSetIteratorImpl; -/// SmallPtrSetImpl - This is the common code shared among all the +/// SmallPtrSetImplBase - This is the common code shared among all the /// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one /// for small and one for large sets. /// @@ -45,7 +45,7 @@ class SmallPtrSetIteratorImpl; /// (-2), to allow deletion. The hash table is resized when the table is 3/4 or /// more. When this happens, the table is doubled in size. /// -class SmallPtrSetImpl { +class SmallPtrSetImplBase { friend class SmallPtrSetIteratorImpl; protected: /// SmallArray - Points to a fixed size set of buckets, used in 'small mode'. @@ -60,19 +60,22 @@ protected: unsigned NumElements; unsigned NumTombstones; - // Helper to copy construct a SmallPtrSet. - SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl& that); - explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) : + // Helpers to copy and move construct a SmallPtrSet. + SmallPtrSetImplBase(const void **SmallStorage, const SmallPtrSetImplBase &that); + SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize, + SmallPtrSetImplBase &&that); + explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize) : SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) { assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 && "Initial size must be a power of two!"); clear(); } - ~SmallPtrSetImpl(); + ~SmallPtrSetImplBase(); public: + typedef unsigned size_type; bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; } - unsigned size() const { return NumElements; } + size_type size() const { return NumElements; } void clear() { // If the capacity of the array is huge, and the # elements used is small, @@ -128,13 +131,14 @@ private: /// Grow - Allocate a larger backing store for the buckets and move it over. void Grow(unsigned NewSize); - void operator=(const SmallPtrSetImpl &RHS) LLVM_DELETED_FUNCTION; + void operator=(const SmallPtrSetImplBase &RHS) LLVM_DELETED_FUNCTION; protected: /// swap - Swaps the elements of two sets. /// Note: This method assumes that both sets have the same small size. - void swap(SmallPtrSetImpl &RHS); + void swap(SmallPtrSetImplBase &RHS); - void CopyFrom(const SmallPtrSetImpl &RHS); + void CopyFrom(const SmallPtrSetImplBase &RHS); + void MoveFrom(unsigned SmallSize, SmallPtrSetImplBase &&RHS); }; /// SmallPtrSetIteratorImpl - This is the common base class shared between all @@ -163,8 +167,8 @@ protected: void AdvanceIfNotValid() { assert(Bucket <= End); while (Bucket != End && - (*Bucket == SmallPtrSetImpl::getEmptyMarker() || - *Bucket == SmallPtrSetImpl::getTombstoneMarker())) + (*Bucket == SmallPtrSetImplBase::getEmptyMarker() || + *Bucket == SmallPtrSetImplBase::getTombstoneMarker())) ++Bucket; } }; @@ -228,26 +232,25 @@ struct RoundUpToPowerOfTwo { }; -/// SmallPtrSet - This class implements a set which is optimized for holding -/// SmallSize or less elements. This internally rounds up SmallSize to the next -/// power of two if it is not already a power of two. See the comments above -/// SmallPtrSetImpl for details of the algorithm. -template<class PtrType, unsigned SmallSize> -class SmallPtrSet : public SmallPtrSetImpl { - // Make sure that SmallSize is a power of two, round up if not. - enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val }; - /// SmallStorage - Fixed size storage used in 'small mode'. - const void *SmallStorage[SmallSizePowTwo]; +/// \brief A templated base class for \c SmallPtrSet which provides the +/// typesafe interface that is common across all small sizes. +/// +/// This is particularly useful for passing around between interface boundaries +/// to avoid encoding a particular small size in the interface boundary. +template <typename PtrType> +class SmallPtrSetImpl : public SmallPtrSetImplBase { typedef PointerLikeTypeTraits<PtrType> PtrTraits; -public: - SmallPtrSet() : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {} - SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(SmallStorage, that) {} - - template<typename It> - SmallPtrSet(It I, It E) : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) { - insert(I, E); - } +protected: + // Constructors that forward to the base. + SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) + : SmallPtrSetImplBase(SmallStorage, that) {} + SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize, + SmallPtrSetImpl &&that) + : SmallPtrSetImplBase(SmallStorage, SmallSize, std::move(that)) {} + explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) + : 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) { @@ -260,9 +263,9 @@ public: return erase_imp(PtrTraits::getAsVoidPointer(Ptr)); } - /// count - Return true if the specified pointer is in the set. - bool count(PtrType Ptr) const { - return count_imp(PtrTraits::getAsVoidPointer(Ptr)); + /// count - Return 1 if the specified pointer is in the set, 0 otherwise. + size_type count(PtrType Ptr) const { + return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0; } template <typename IterT> @@ -279,18 +282,48 @@ public: inline iterator end() const { return iterator(CurArray+CurArraySize, CurArray+CurArraySize); } +}; - // Allow assignment from any smallptrset with the same element type even if it - // doesn't have the same smallsize. - const SmallPtrSet<PtrType, SmallSize>& +/// SmallPtrSet - This class implements a set which is optimized for holding +/// SmallSize or less elements. This internally rounds up SmallSize to the next +/// power of two if it is not already a power of two. See the comments above +/// SmallPtrSetImplBase for details of the algorithm. +template<class PtrType, unsigned SmallSize> +class SmallPtrSet : public SmallPtrSetImpl<PtrType> { + typedef SmallPtrSetImpl<PtrType> BaseT; + + // Make sure that SmallSize is a power of two, round up if not. + enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val }; + /// SmallStorage - Fixed size storage used in 'small mode'. + const void *SmallStorage[SmallSizePowTwo]; +public: + SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {} + SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {} + SmallPtrSet(SmallPtrSet &&that) + : BaseT(SmallStorage, SmallSizePowTwo, std::move(that)) {} + + template<typename It> + SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) { + this->insert(I, E); + } + + SmallPtrSet<PtrType, SmallSize> & operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) { - CopyFrom(RHS); + if (&RHS != this) + this->CopyFrom(RHS); + return *this; + } + + SmallPtrSet<PtrType, SmallSize>& + operator=(SmallPtrSet<PtrType, SmallSize> &&RHS) { + if (&RHS != this) + this->MoveFrom(SmallSizePowTwo, std::move(RHS)); return *this; } /// swap - Swaps the elements of two sets. void swap(SmallPtrSet<PtrType, SmallSize> &RHS) { - SmallPtrSetImpl::swap(RHS); + SmallPtrSetImplBase::swap(RHS); } }; diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h index 5dfe924f6d78..bb1971eb7c5d 100644 --- a/include/llvm/ADT/SmallSet.h +++ b/include/llvm/ADT/SmallSet.h @@ -37,18 +37,22 @@ class SmallSet { typedef typename SmallVector<T, N>::const_iterator VIterator; typedef typename SmallVector<T, N>::iterator mutable_iterator; public: + typedef size_t size_type; SmallSet() {} - bool empty() const { return Vector.empty() && Set.empty(); } - unsigned size() const { + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { + return Vector.empty() && Set.empty(); + } + + size_type size() const { return isSmall() ? Vector.size() : Set.size(); } - /// count - Return true if the element is in the set. - bool count(const T &V) const { + /// count - Return 1 if the element is in the set, 0 otherwise. + size_type count(const T &V) const { if (isSmall()) { // Since the collection is small, just do a linear search. - return vfind(V) != Vector.end(); + return vfind(V) == Vector.end() ? 0 : 1; } else { return Set.count(V); } diff --git a/include/llvm/ADT/SmallString.h b/include/llvm/ADT/SmallString.h index 2cfb5b9f2a9d..e569f54481a2 100644 --- a/include/llvm/ADT/SmallString.h +++ b/include/llvm/ADT/SmallString.h @@ -34,9 +34,6 @@ public: template<typename ItTy> SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {} - /// Copy ctor. - SmallString(const SmallString &RHS) : SmallVector<char, InternalLen>(RHS) {} - // Note that in order to add new overloads for append & assign, we have to // duplicate the inherited versions so as not to inadvertently hide them. diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 505aa8d8ae61..82538e9bd108 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_SMALLVECTOR_H #define LLVM_ADT_SMALLVECTOR_H +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" @@ -183,13 +184,9 @@ protected: /// std::move, but not all stdlibs actually provide that. template<typename It1, typename It2> static It2 move(It1 I, It1 E, It2 Dest) { -#if LLVM_HAS_RVALUE_REFERENCES for (; I != E; ++I, ++Dest) *Dest = ::std::move(*I); return Dest; -#else - return ::std::copy(I, E, Dest); -#endif } /// move_backward - Use move-assignment to move the range @@ -198,25 +195,17 @@ protected: /// std::move_backward, but not all stdlibs actually provide that. template<typename It1, typename It2> static It2 move_backward(It1 I, It1 E, It2 Dest) { -#if LLVM_HAS_RVALUE_REFERENCES while (I != E) *--Dest = ::std::move(*--E); return Dest; -#else - return ::std::copy_backward(I, E, Dest); -#endif } /// uninitialized_move - 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) { -#if LLVM_HAS_RVALUE_REFERENCES for (; I != E; ++I, ++Dest) ::new ((void*) &*Dest) T(::std::move(*I)); -#else - ::std::uninitialized_copy(I, E, Dest); -#endif } /// uninitialized_copy - Copy the range [I, E) onto the uninitialized @@ -231,32 +220,22 @@ protected: /// Guarantees space for at least one more element, or MinSize more /// elements if specified. void grow(size_t MinSize = 0); - + public: void push_back(const T &Elt) { - if (this->EndX < this->CapacityX) { - Retry: - ::new ((void*) this->end()) T(Elt); - this->setEnd(this->end()+1); - return; - } - this->grow(); - goto Retry; + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void*) this->end()) T(Elt); + this->setEnd(this->end()+1); } -#if LLVM_HAS_RVALUE_REFERENCES void push_back(T &&Elt) { - if (this->EndX < this->CapacityX) { - Retry: - ::new ((void*) this->end()) T(::std::move(Elt)); - this->setEnd(this->end()+1); - return; - } - this->grow(); - goto Retry; + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void*) this->end()) T(::std::move(Elt)); + this->setEnd(this->end()+1); } -#endif - + void pop_back() { this->setEnd(this->end()-1); this->end()->~T(); @@ -268,7 +247,7 @@ template <typename T, bool isPodLike> void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { size_t CurCapacity = this->capacity(); size_t CurSize = this->size(); - // Always grow, even from zero. + // Always grow, even from zero. size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2)); if (NewCapacity < MinSize) NewCapacity = MinSize; @@ -348,16 +327,12 @@ protected: } public: void push_back(const T &Elt) { - if (this->EndX < this->CapacityX) { - Retry: - memcpy(this->end(), &Elt, sizeof(T)); - this->setEnd(this->end()+1); - return; - } - this->grow(); - goto Retry; + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + memcpy(this->end(), &Elt, sizeof(T)); + this->setEnd(this->end()+1); } - + void pop_back() { this->setEnd(this->end()-1); } @@ -405,7 +380,8 @@ public: } else if (N > this->size()) { if (this->capacity() < N) this->grow(N); - std::uninitialized_fill(this->end(), this->begin()+N, T()); + for (auto I = this->end(), E = this->begin() + N; I != E; ++I) + new (&*I) T(); this->setEnd(this->begin()+N); } } @@ -428,11 +404,7 @@ public: } T LLVM_ATTRIBUTE_UNUSED_RESULT pop_back_val() { -#if LLVM_HAS_RVALUE_REFERENCES T Result = ::std::move(this->back()); -#else - T Result = this->back(); -#endif this->pop_back(); return Result; } @@ -501,7 +473,6 @@ public: return(N); } -#if LLVM_HAS_RVALUE_REFERENCES iterator insert(iterator I, T &&Elt) { if (I == this->end()) { // Important special case for empty vector. this->push_back(::std::move(Elt)); @@ -511,28 +482,26 @@ public: assert(I >= this->begin() && "Insertion iterator is out of bounds."); assert(I <= this->end() && "Inserting past the end of the vector."); - if (this->EndX < this->CapacityX) { - Retry: - ::new ((void*) this->end()) T(::std::move(this->back())); - this->setEnd(this->end()+1); - // Push everything else over. - this->move_backward(I, this->end()-1, this->end()); + if (this->EndX >= this->CapacityX) { + size_t EltNo = I-this->begin(); + this->grow(); + I = this->begin()+EltNo; + } - // If we just moved the element we're inserting, be sure to update - // the reference. - T *EltPtr = &Elt; - if (I <= EltPtr && EltPtr < this->EndX) - ++EltPtr; + ::new ((void*) this->end()) T(::std::move(this->back())); + // Push everything else over. + this->move_backward(I, this->end()-1, this->end()); + this->setEnd(this->end()+1); - *I = ::std::move(*EltPtr); - return I; - } - size_t EltNo = I-this->begin(); - this->grow(); - I = this->begin()+EltNo; - goto Retry; + // If we just moved the element we're inserting, be sure to update + // the reference. + T *EltPtr = &Elt; + if (I <= EltPtr && EltPtr < this->EndX) + ++EltPtr; + + *I = ::std::move(*EltPtr); + return I; } -#endif iterator insert(iterator I, const T &Elt) { if (I == this->end()) { // Important special case for empty vector. @@ -543,26 +512,24 @@ public: assert(I >= this->begin() && "Insertion iterator is out of bounds."); assert(I <= this->end() && "Inserting past the end of the vector."); - if (this->EndX < this->CapacityX) { - Retry: - ::new ((void*) this->end()) T(this->back()); - this->setEnd(this->end()+1); - // Push everything else over. - this->move_backward(I, this->end()-1, this->end()); - - // If we just moved the element we're inserting, be sure to update - // the reference. - const T *EltPtr = &Elt; - if (I <= EltPtr && EltPtr < this->EndX) - ++EltPtr; - - *I = *EltPtr; - return I; + if (this->EndX >= this->CapacityX) { + size_t EltNo = I-this->begin(); + this->grow(); + I = this->begin()+EltNo; } - size_t EltNo = I-this->begin(); - this->grow(); - I = this->begin()+EltNo; - goto Retry; + ::new ((void*) this->end()) T(std::move(this->back())); + // Push everything else over. + this->move_backward(I, this->end()-1, this->end()); + this->setEnd(this->end()+1); + + // If we just moved the element we're inserting, be sure to update + // the reference. + const T *EltPtr = &Elt; + if (I <= EltPtr && EltPtr < this->EndX) + ++EltPtr; + + *I = *EltPtr; + return I; } iterator insert(iterator I, size_type NumToInsert, const T &Elt) { @@ -589,7 +556,8 @@ public: // reallocate the vector. if (size_t(this->end()-I) >= NumToInsert) { T *OldEnd = this->end(); - append(this->end()-NumToInsert, this->end()); + append(std::move_iterator<iterator>(this->end() - NumToInsert), + std::move_iterator<iterator>(this->end())); // Copy the existing elements that get replaced. this->move_backward(I, OldEnd-NumToInsert, OldEnd); @@ -642,7 +610,8 @@ public: // reallocate the vector. if (size_t(this->end()-I) >= NumToInsert) { T *OldEnd = this->end(); - append(this->end()-NumToInsert, this->end()); + append(std::move_iterator<iterator>(this->end() - NumToInsert), + std::move_iterator<iterator>(this->end())); // Copy the existing elements that get replaced. this->move_backward(I, OldEnd-NumToInsert, OldEnd); @@ -673,9 +642,7 @@ public: SmallVectorImpl &operator=(const SmallVectorImpl &RHS); -#if LLVM_HAS_RVALUE_REFERENCES SmallVectorImpl &operator=(SmallVectorImpl &&RHS); -#endif bool operator==(const SmallVectorImpl &RHS) const { if (this->size() != RHS.size()) return false; @@ -793,7 +760,6 @@ SmallVectorImpl<T> &SmallVectorImpl<T>:: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES template <typename T> SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { // Avoid self-assignment. @@ -842,7 +808,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { this->grow(RHSSize); } else if (CurSize) { // Otherwise, use assignment for the already-constructed elements. - this->move(RHS.begin(), RHS.end(), this->begin()); + this->move(RHS.begin(), RHS.begin()+CurSize, this->begin()); } // Move-construct the new elements in place. @@ -855,7 +821,6 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { RHS.clear(); return *this; } -#endif /// Storage for the SmallVector elements which aren't contained in /// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1' @@ -894,6 +859,12 @@ public: this->append(S, E); } + template <typename RangeTy> + explicit SmallVector(const llvm::iterator_range<RangeTy> R) + : SmallVectorImpl<T>(N) { + this->append(R.begin(), R.end()); + } + SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) { if (!RHS.empty()) SmallVectorImpl<T>::operator=(RHS); @@ -904,7 +875,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) { if (!RHS.empty()) SmallVectorImpl<T>::operator=(::std::move(RHS)); @@ -914,8 +884,6 @@ public: SmallVectorImpl<T>::operator=(::std::move(RHS)); return *this; } -#endif - }; template<typename T, unsigned N> diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 7a10f857044d..36754d682355 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -45,6 +45,7 @@ struct SparseBitVectorElement : public ilist_node<SparseBitVectorElement<ElementSize> > { public: typedef unsigned long BitWord; + typedef unsigned size_type;
enum { BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT, BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE, @@ -120,7 +121,7 @@ public: return Bits[Idx / BITWORD_SIZE] & (1L << (Idx % BITWORD_SIZE)); } - unsigned count() const { + size_type count() const { unsigned NumBits = 0; for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) if (sizeof(BitWord) == 4) @@ -382,7 +383,7 @@ class SparseBitVector { AtEnd = true; return; } - // Set up for next non zero word in bitmap. + // Set up for next non-zero word in bitmap. BitNumber = Iter->index() * ElementSize; NextSetBitNumber = Iter->find_first(); BitNumber += NextSetBitNumber; diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h index 7f2a6f7d0bac..dc1273eb7ff6 100644 --- a/include/llvm/ADT/SparseMultiSet.h +++ b/include/llvm/ADT/SparseMultiSet.h @@ -76,6 +76,10 @@ template<typename ValueT, typename KeyFunctorT = llvm::identity<unsigned>, typename SparseT = uint8_t> class SparseMultiSet { + static_assert(std::numeric_limits<SparseT>::is_integer && + !std::numeric_limits<SparseT>::is_signed, + "SparseT must be an unsigned integer type"); + /// The actual data that's stored, as a doubly-linked list implemented via /// indices into the DenseVector. The doubly linked list is implemented /// circular in Prev indices, and INVALID-terminated in Next indices. This @@ -181,9 +185,10 @@ public: typedef const ValueT &const_reference; typedef ValueT *pointer; typedef const ValueT *const_pointer; + typedef unsigned size_type;
SparseMultiSet() - : Sparse(0), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) { } + : Sparse(nullptr), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) {} ~SparseMultiSet() { free(Sparse); } @@ -245,16 +250,6 @@ public: typedef typename super::pointer pointer; typedef typename super::reference reference; - iterator_base(const iterator_base &RHS) - : SMS(RHS.SMS), Idx(RHS.Idx), SparseIdx(RHS.SparseIdx) { } - - const iterator_base &operator=(const iterator_base &RHS) { - SMS = RHS.SMS; - Idx = RHS.Idx; - SparseIdx = RHS.SparseIdx; - return *this; - } - reference operator*() const { assert(isKeyed() && SMS->sparseIndex(SMS->Dense[Idx].Data) == SparseIdx && "Dereferencing iterator of invalid key or index"); @@ -333,7 +328,7 @@ public: /// This is not the same as BitVector::size() which returns the size of the /// universe. /// - unsigned size() const { + size_type size() const { assert(NumFree <= Dense.size() && "Out-of-bounds free entries"); return Dense.size() - NumFree; } @@ -354,9 +349,6 @@ public: /// iterator findIndex(unsigned Idx) { assert(Idx < Universe && "Key out of range"); - assert(std::numeric_limits<SparseT>::is_integer && - !std::numeric_limits<SparseT>::is_signed && - "SparseT must be an unsigned integer type"); const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u; for (unsigned i = Sparse[Idx], e = Dense.size(); i < e; i += Stride) { const unsigned FoundIdx = sparseIndex(Dense[i]); @@ -387,7 +379,7 @@ public: /// Returns the number of elements identified by Key. This will be linear in /// the number of elements of that key. - unsigned count(const KeyT &Key) const { + size_type count(const KeyT &Key) const { unsigned Ret = 0; for (const_iterator It = find(Key); It != end(); ++It) ++Ret; diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index 267a340a7581..632d52ad9d82 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -118,8 +118,13 @@ template<typename ValueT, typename KeyFunctorT = llvm::identity<unsigned>, typename SparseT = uint8_t> class SparseSet { + static_assert(std::numeric_limits<SparseT>::is_integer && + !std::numeric_limits<SparseT>::is_signed, + "SparseT must be an unsigned integer type"); + typedef typename KeyFunctorT::argument_type KeyT; typedef SmallVector<ValueT, 8> DenseT; + typedef unsigned size_type;
DenseT Dense; SparseT *Sparse; unsigned Universe; @@ -138,7 +143,7 @@ public: typedef ValueT *pointer; typedef const ValueT *const_pointer; - SparseSet() : Sparse(0), Universe(0) {} + SparseSet() : Sparse(nullptr), Universe(0) {} ~SparseSet() { free(Sparse); } /// setUniverse - Set the universe size which determines the largest key the @@ -182,7 +187,7 @@ public: /// This is not the same as BitVector::size() which returns the size of the /// universe. /// - unsigned size() const { return Dense.size(); } + size_type size() const { return Dense.size(); } /// clear - Clears the set. This is a very fast constant time operation. /// @@ -198,9 +203,6 @@ public: /// iterator findIndex(unsigned Idx) { assert(Idx < Universe && "Key out of range"); - assert(std::numeric_limits<SparseT>::is_integer && - !std::numeric_limits<SparseT>::is_signed && - "SparseT must be an unsigned integer type"); const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u; for (unsigned i = Sparse[Idx], e = size(); i < e; i += Stride) { const unsigned FoundIdx = ValIndexOf(Dense[i]); @@ -227,10 +229,11 @@ public: return const_cast<SparseSet*>(this)->findIndex(KeyIndexOf(Key)); } - /// count - Returns true if this set contains an element identified by Key. + /// count - Returns 1 if this set contains an element identified by Key, + /// 0 otherwise. /// - bool count(const KeyT &Key) const { - return find(Key) != end(); + size_type count(const KeyT &Key) const { + return find(Key) == end() ? 0 : 1; } /// insert - Attempts to insert a new element. diff --git a/include/llvm/ADT/Statistic.h b/include/llvm/ADT/Statistic.h index 26aac7bea627..d98abc375e8a 100644 --- a/include/llvm/ADT/Statistic.h +++ b/include/llvm/ADT/Statistic.h @@ -46,7 +46,7 @@ public: /// construct - This should only be called for non-global statistics. void construct(const char *name, const char *desc) { Name = name; Desc = desc; - Value = 0; Initialized = 0; + Value = 0; Initialized = false; } // Allow use of this class as the value itself. diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index 56dbb5b80689..0992f5d4a549 100644 --- a/include/llvm/ADT/StringExtras.h +++ b/include/llvm/ADT/StringExtras.h @@ -14,9 +14,9 @@ #ifndef LLVM_ADT_STRINGEXTRAS_H #define LLVM_ADT_STRINGEXTRAS_H -#include <iterator> #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" +#include <iterator> namespace llvm { template<typename T> class SmallVectorImpl; @@ -28,6 +28,11 @@ static inline char hexdigit(unsigned X, bool LowerCase = false) { return X < 10 ? '0' + X : HexChar + X - 10; } +/// Construct a string ref from a boolean. +static inline StringRef toStringRef(bool B) { + return StringRef(B ? "true" : "false"); +} + /// Interpret the given character \p C as a hexadecimal digit and return its /// value. /// @@ -48,7 +53,7 @@ static inline unsigned hexDigitValue(char C) { /// This should only be used with unsigned types. /// template<typename IntTy> -static inline char *utohex_buffer(IntTy X, char *BufferEnd) { +static inline char *utohex_buffer(IntTy X, char *BufferEnd, bool LowerCase = false) { char *BufPtr = BufferEnd; *--BufPtr = 0; // Null terminate buffer. if (X == 0) { @@ -58,15 +63,15 @@ static inline char *utohex_buffer(IntTy X, char *BufferEnd) { while (X) { unsigned char Mod = static_cast<unsigned char>(X) & 15; - *--BufPtr = hexdigit(Mod); + *--BufPtr = hexdigit(Mod, LowerCase); X >>= 4; } return BufPtr; } -static inline std::string utohexstr(uint64_t X) { +static inline std::string utohexstr(uint64_t X, bool LowerCase = false) { char Buffer[17]; - return utohex_buffer(X, Buffer+17); + return utohex_buffer(X, Buffer+17, LowerCase); } static inline std::string utostr_32(uint32_t X, bool isNeg = false) { @@ -136,7 +141,7 @@ void SplitString(StringRef Source, // better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx // X*33+c -> X*33^c static inline unsigned HashString(StringRef Str, unsigned Result = 0) { - for (unsigned i = 0, e = Str.size(); i != e; ++i) + for (StringRef::size_type i = 0, e = Str.size(); i != e; ++i) Result = Result * 33 + (unsigned char)Str[i]; return Result; } diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index 0838ebe91f1b..c40e5e2b3d87 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -17,6 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include <cstring> +#include <utility> namespace llvm { template<typename ValueT> @@ -26,19 +27,6 @@ namespace llvm { template<typename ValueTy> class StringMapEntry; -/// StringMapEntryInitializer - This datatype can be partially specialized for -/// various datatypes in a stringmap to allow them to be initialized when an -/// entry is default constructed for the map. -template<typename ValueTy> -class StringMapEntryInitializer { -public: - template <typename InitTy> - static void Initialize(StringMapEntry<ValueTy> &T, InitTy InitVal) { - T.second = InitVal; - } -}; - - /// StringMapEntryBase - Shared base class of StringMapEntry instances. class StringMapEntryBase { unsigned StrLen; @@ -61,15 +49,22 @@ protected: unsigned NumTombstones; unsigned ItemSize; protected: - explicit StringMapImpl(unsigned itemSize) : ItemSize(itemSize) { - // Initialize the map with zero buckets to allocation. - TheTable = 0; - NumBuckets = 0; - NumItems = 0; - NumTombstones = 0; + explicit StringMapImpl(unsigned itemSize) + : TheTable(nullptr), + // Initialize the map with zero buckets to allocation. + NumBuckets(0), NumItems(0), NumTombstones(0), ItemSize(itemSize) {} + StringMapImpl(StringMapImpl &&RHS) + : TheTable(RHS.TheTable), NumBuckets(RHS.NumBuckets), + NumItems(RHS.NumItems), NumTombstones(RHS.NumTombstones), + ItemSize(RHS.ItemSize) { + RHS.TheTable = nullptr; + RHS.NumBuckets = 0; + RHS.NumItems = 0; + RHS.NumTombstones = 0; } + StringMapImpl(unsigned InitSize, unsigned ItemSize); - void RehashTable(); + unsigned RehashTable(unsigned BucketNo = 0); /// LookupBucketFor - Look up the bucket that the specified string should end /// up in. If it already exists as a key in the map, the Item pointer for the @@ -122,8 +117,8 @@ public: explicit StringMapEntry(unsigned strLen) : StringMapEntryBase(strLen), second() {} - StringMapEntry(unsigned strLen, const ValueTy &V) - : StringMapEntryBase(strLen), second(V) {} + StringMapEntry(unsigned strLen, ValueTy V) + : StringMapEntryBase(strLen), second(std::move(V)) {} StringRef getKey() const { return StringRef(getKeyData(), getKeyLength()); @@ -144,15 +139,13 @@ public: /// Create - Create a StringMapEntry for the specified key and default /// construct the value. template<typename AllocatorTy, typename InitType> - static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, InitType InitVal) { - unsigned KeyLength = static_cast<unsigned>(KeyEnd-KeyStart); + unsigned KeyLength = Key.size(); - // Okay, the item doesn't already exist, and 'Bucket' is the bucket to fill - // in. Allocate a new item with space for the string at the end and a null + // Allocate a new item with space for the string at the end and a null // terminator. - unsigned AllocSize = static_cast<unsigned>(sizeof(StringMapEntry))+ KeyLength+1; unsigned Alignment = alignOf<StringMapEntry>(); @@ -161,34 +154,29 @@ public: static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); // Default construct the value. - new (NewItem) StringMapEntry(KeyLength); + new (NewItem) StringMapEntry(KeyLength, std::move(InitVal)); // Copy the string information. char *StrBuffer = const_cast<char*>(NewItem->getKeyData()); - memcpy(StrBuffer, KeyStart, KeyLength); + memcpy(StrBuffer, Key.data(), KeyLength); StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. - - // Initialize the value if the client wants to. - StringMapEntryInitializer<ValueTy>::Initialize(*NewItem, InitVal); return NewItem; } template<typename AllocatorTy> - static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, - AllocatorTy &Allocator) { - return Create(KeyStart, KeyEnd, Allocator, 0); + static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator) { + return Create(Key, Allocator, ValueTy()); } /// Create - Create a StringMapEntry with normal malloc/free. template<typename InitType> - static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, - InitType InitVal) { + static StringMapEntry *Create(StringRef Key, InitType InitVal) { MallocAllocator A; - return Create(KeyStart, KeyEnd, A, InitVal); + return Create(Key, A, std::move(InitVal)); } - static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd) { - return Create(KeyStart, KeyEnd, ValueTy()); + static StringMapEntry *Create(StringRef Key) { + return Create(Key, ValueTy()); } /// GetStringMapEntryFromValue - Given a value that is known to be embedded @@ -216,8 +204,10 @@ public: template<typename AllocatorTy> void Destroy(AllocatorTy &Allocator) { // Free memory referenced by the item. + unsigned AllocSize = + static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1; this->~StringMapEntry(); - Allocator.Deallocate(this); + Allocator.Deallocate(static_cast<void *>(this), AllocSize); } /// Destroy this object, releasing memory back to the malloc allocator. @@ -249,23 +239,19 @@ public: : StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))), Allocator(A) {} - StringMap(const StringMap &RHS) - : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) { - assert(RHS.empty() && - "Copy ctor from non-empty stringmap not implemented yet!"); - (void)RHS; - } - void operator=(const StringMap &RHS) { - assert(RHS.empty() && - "assignment from non-empty stringmap not implemented yet!"); - (void)RHS; - clear(); + StringMap(StringMap &&RHS) + : StringMapImpl(std::move(RHS)), Allocator(std::move(RHS.Allocator)) {} + + StringMap &operator=(StringMap RHS) { + StringMapImpl::swap(RHS); + std::swap(Allocator, RHS.Allocator); + return *this; } - typedef typename ReferenceAdder<AllocatorTy>::result AllocatorRefTy; - typedef typename ReferenceAdder<const AllocatorTy>::result AllocatorCRefTy; - AllocatorRefTy getAllocator() { return Allocator; } - AllocatorCRefTy getAllocator() const { return Allocator; } + // FIXME: Implement copy operations if/when they're needed. + + AllocatorTy &getAllocator() { return Allocator; } + const AllocatorTy &getAllocator() const { return Allocator; } typedef const char* key_type; typedef ValueTy mapped_type; @@ -313,6 +299,7 @@ public: return GetOrCreateValue(Key).getValue(); } + /// count - Return 1 if the element is in the map, 0 otherwise. size_type count(StringRef Key) const { return find(Key) == end() ? 0 : 1; } @@ -336,6 +323,28 @@ public: return true; } + /// insert - Inserts the specified key/value pair into the map if the key + /// isn't already in the map. 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 with key equivalent to the key of the pair. + std::pair<iterator, bool> insert(std::pair<StringRef, ValueTy> KV) { + unsigned BucketNo = LookupBucketFor(KV.first); + StringMapEntryBase *&Bucket = TheTable[BucketNo]; + if (Bucket && Bucket != getTombstoneVal()) + return std::make_pair(iterator(TheTable + BucketNo, false), + false); // Already exists in map. + + if (Bucket == getTombstoneVal()) + --NumTombstones; + Bucket = + MapEntryTy::Create(KV.first, Allocator, std::move(KV.second)); + ++NumItems; + assert(NumItems + NumTombstones <= NumBuckets); + + BucketNo = RehashTable(BucketNo); + return std::make_pair(iterator(TheTable + BucketNo, false), true); + } + // clear - Empties out the StringMap void clear() { if (empty()) return; @@ -347,7 +356,7 @@ public: if (Bucket && Bucket != getTombstoneVal()) { static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); } - Bucket = 0; + Bucket = nullptr; } NumItems = 0; @@ -359,25 +368,7 @@ public: /// return. template <typename InitTy> MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) { - unsigned BucketNo = LookupBucketFor(Key); - StringMapEntryBase *&Bucket = TheTable[BucketNo]; - if (Bucket && Bucket != getTombstoneVal()) - return *static_cast<MapEntryTy*>(Bucket); - - MapEntryTy *NewItem = - MapEntryTy::Create(Key.begin(), Key.end(), Allocator, Val); - - if (Bucket == getTombstoneVal()) - --NumTombstones; - ++NumItems; - assert(NumItems + NumTombstones <= NumBuckets); - - // Fill in the bucket for the hash table. The FullHashValue was already - // filled in by LookupBucketFor. - Bucket = NewItem; - - RehashTable(); - return *NewItem; + return *insert(std::make_pair(Key, std::move(Val))).first; } MapEntryTy &GetOrCreateValue(StringRef Key) { @@ -404,7 +395,17 @@ public: } ~StringMap() { - clear(); + // Delete all the elements in the map, but don't reset the elements + // to default values. This is a copy of clear(), but avoids unnecessary + // work not required in the destructor. + if (!empty()) { + for (unsigned I = 0, E = NumBuckets; I != E; ++I) { + StringMapEntryBase *Bucket = TheTable[I]; + if (Bucket && Bucket != getTombstoneVal()) { + static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator); + } + } + } free(TheTable); } }; @@ -417,7 +418,7 @@ protected: public: typedef StringMapEntry<ValueTy> value_type; - StringMapConstIterator() : Ptr(0) { } + StringMapConstIterator() : Ptr(nullptr) { } explicit StringMapConstIterator(StringMapEntryBase **Bucket, bool NoAdvance = false) @@ -450,7 +451,7 @@ public: private: void AdvancePastEmptyBuckets() { - while (*Ptr == 0 || *Ptr == StringMapImpl::getTombstoneVal()) + while (*Ptr == nullptr || *Ptr == StringMapImpl::getTombstoneVal()) ++Ptr; } }; diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index ec0c2849f37e..1f413e80553f 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -10,7 +10,6 @@ #ifndef LLVM_ADT_STRINGREF_H #define LLVM_ADT_STRINGREF_H -#include "llvm/Support/type_traits.h" #include <algorithm> #include <cassert> #include <cstring> @@ -70,7 +69,7 @@ namespace llvm { /// @{ /// Construct an empty string ref. - /*implicit*/ StringRef() : Data(0), Length(0) {} + /*implicit*/ StringRef() : Data(nullptr), Length(0) {} /// Construct a string ref from a cstring. /*implicit*/ StringRef(const char *Str) @@ -124,6 +123,13 @@ namespace llvm { return Data[Length-1]; } + // copy - Allocate copy in Allocator and return StringRef to it. + template <typename Allocator> StringRef copy(Allocator &A) { + char *S = A.template Allocate<char>(Length); + std::copy(begin(), end(), S); + return StringRef(S, Length); + } + /// equals - Check for string equality, this is more efficient than /// compare() when the relative ordering of inequal strings isn't needed. bool equals(StringRef RHS) const { @@ -179,7 +185,7 @@ namespace llvm { /// str - Get the contents as an std::string. std::string str() const { - if (Data == 0) return std::string(); + if (!Data) return std::string(); return std::string(Data, Length); } @@ -333,7 +339,7 @@ namespace llvm { /// this returns true to signify the error. The string is considered /// erroneous if empty or if it overflows T. template <typename T> - typename enable_if_c<std::numeric_limits<T>::is_signed, bool>::type + typename std::enable_if<std::numeric_limits<T>::is_signed, bool>::type getAsInteger(unsigned Radix, T &Result) const { long long LLVal; if (getAsSignedInteger(*this, Radix, LLVal) || @@ -344,7 +350,7 @@ namespace llvm { } template <typename T> - typename enable_if_c<!std::numeric_limits<T>::is_signed, bool>::type + typename std::enable_if<!std::numeric_limits<T>::is_signed, bool>::type getAsInteger(unsigned Radix, T &Result) const { unsigned long long ULLVal; if (getAsUnsignedInteger(*this, Radix, ULLVal) || @@ -553,11 +559,6 @@ namespace llvm { // StringRefs can be treated like a POD type. template <typename T> struct isPodLike; template <> struct isPodLike<StringRef> { static const bool value = true; }; - - /// Construct a string ref from a boolean. - inline StringRef toStringRef(bool B) { - return StringRef(B ? "true" : "false"); - } } #endif diff --git a/include/llvm/ADT/StringSwitch.h b/include/llvm/ADT/StringSwitch.h index 7fd6e2796032..0393a0c373ef 100644 --- a/include/llvm/ADT/StringSwitch.h +++ b/include/llvm/ADT/StringSwitch.h @@ -49,7 +49,7 @@ class StringSwitch { public: explicit StringSwitch(StringRef S) - : Str(S), Result(0) { } + : Str(S), Result(nullptr) { } template<unsigned N> StringSwitch& Case(const char (&S)[N], const T& Value) { diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index cc0e7b63819c..5669b2a81a40 100644 --- a/include/llvm/ADT/TinyPtrVector.h +++ b/include/llvm/ADT/TinyPtrVector.h @@ -12,9 +12,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerUnion.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Compiler.h" namespace llvm { @@ -70,9 +68,8 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) { - RHS.Val = (EltTy)0; + RHS.Val = (EltTy)nullptr; } TinyPtrVector &operator=(TinyPtrVector &&RHS) { if (this == &RHS) @@ -95,10 +92,9 @@ public: } Val = RHS.Val; - RHS.Val = (EltTy)0; + RHS.Val = (EltTy)nullptr; return *this; } -#endif // implicit conversion operator to ArrayRef. operator ArrayRef<EltTy>() const { @@ -178,7 +174,7 @@ public: } void push_back(EltTy NewVal) { - assert(NewVal != 0 && "Can't add a null value"); + assert(NewVal && "Can't add a null value"); // If we have nothing, add something. if (Val.isNull()) { @@ -199,7 +195,7 @@ public: void pop_back() { // If we have a single value, convert to empty. if (Val.template is<EltTy>()) - Val = (EltTy)0; + Val = (EltTy)nullptr; else if (VecTy *Vec = Val.template get<VecTy*>()) Vec->pop_back(); } @@ -207,7 +203,7 @@ public: void clear() { // If we have a single value, convert to empty. if (Val.template is<EltTy>()) { - Val = (EltTy)0; + Val = (EltTy)nullptr; } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { // If we have a vector form, just clear it. Vec->clear(); @@ -222,7 +218,7 @@ public: // If we have a single value, convert to empty. if (Val.template is<EltTy>()) { if (I == begin()) - Val = (EltTy)0; + Val = (EltTy)nullptr; } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { // multiple items in a vector; just do the erase, there is no // benefit to collapsing back to a pointer @@ -238,7 +234,7 @@ public: if (Val.template is<EltTy>()) { if (S == begin() && S != E) - Val = (EltTy)0; + Val = (EltTy)nullptr; } else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) { return Vec->erase(S, E); } @@ -250,7 +246,7 @@ public: assert(I <= this->end() && "Inserting past the end of the vector."); if (I == end()) { push_back(Elt); - return llvm::prior(end()); + return std::prev(end()); } assert(!Val.isNull() && "Null value with non-end insert iterator."); if (EltTy V = Val.template dyn_cast<EltTy>()) { @@ -273,7 +269,7 @@ public: // If we have a single value, convert to a vector. ptrdiff_t Offset = I - begin(); if (Val.isNull()) { - if (llvm::next(From) == To) { + if (std::next(From) == To) { Val = *From; return begin(); } diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 84e0b29d1fe0..b96f11435520 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -46,32 +46,53 @@ public: enum ArchType { UnknownArch, - arm, // ARM: arm, armv.*, xscale - aarch64, // AArch64: aarch64 - hexagon, // Hexagon: hexagon - mips, // MIPS: mips, mipsallegrex - mipsel, // MIPSEL: mipsel, mipsallegrexel - mips64, // MIPS64: mips64 - mips64el,// MIPS64EL: mips64el - msp430, // MSP430: msp430 - ppc, // PPC: powerpc - ppc64, // PPC64: powerpc64, ppu - ppc64le, // PPC64LE: powerpc64le - r600, // R600: AMD GPUs HD2XXX - HD6XXX - sparc, // Sparc: sparc - sparcv9, // Sparcv9: Sparcv9 - systemz, // SystemZ: s390x - tce, // TCE (http://tce.cs.tut.fi/): tce - thumb, // Thumb: thumb, thumbv.* - x86, // X86: i[3-9]86 - x86_64, // X86-64: amd64, x86_64 - xcore, // XCore: xcore - nvptx, // NVPTX: 32-bit - nvptx64, // NVPTX: 64-bit - le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) - amdil, // amdil: amd IL - spir, // SPIR: standard portable IR for OpenCL 32-bit version - spir64 // SPIR: standard portable IR for OpenCL 64-bit version + 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 + mips, // MIPS: mips, mipsallegrex + mipsel, // MIPSEL: mipsel, mipsallegrexel + mips64, // MIPS64: mips64 + mips64el, // MIPS64EL: mips64el + msp430, // MSP430: msp430 + ppc, // PPC: powerpc + ppc64, // PPC64: powerpc64, ppu + ppc64le, // PPC64LE: powerpc64le + r600, // R600: AMD GPUs HD2XXX - HD6XXX + sparc, // Sparc: sparc + sparcv9, // Sparcv9: Sparcv9 + systemz, // SystemZ: s390x + tce, // TCE (http://tce.cs.tut.fi/): tce + thumb, // Thumb (little endian): thumb, thumbv.* + thumbeb, // Thumb (big endian): thumbeb + x86, // X86: i[3-9]86 + x86_64, // X86-64: amd64, x86_64 + xcore, // XCore: xcore + nvptx, // NVPTX: 32-bit + nvptx64, // NVPTX: 64-bit + le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) + amdil, // amdil: amd IL + spir, // SPIR: standard portable IR for OpenCL 32-bit version + spir64, // SPIR: standard portable IR for OpenCL 64-bit version + kalimba // Kalimba: generic kalimba + }; + enum SubArchType { + NoSubArch, + + ARMSubArch_v8, + ARMSubArch_v7, + ARMSubArch_v7em, + ARMSubArch_v7m, + ARMSubArch_v7s, + ARMSubArch_v6, + ARMSubArch_v6m, + ARMSubArch_v6t2, + ARMSubArch_v5, + ARMSubArch_v5te, + ARMSubArch_v4t }; enum VendorType { UnknownVendor, @@ -83,7 +104,10 @@ public: BGQ, Freescale, IBM, - NVIDIA + ImaginationTechnologies, + MipsTechnologies, + NVIDIA, + CSR }; enum OSType { UnknownOS, @@ -120,10 +144,21 @@ public: GNUEABI, GNUEABIHF, GNUX32, + CODE16, EABI, - MachO, + EABIHF, Android, - ELF + + MSVC, + Itanium, + Cygnus, + }; + enum ObjectFormatType { + UnknownObjectFormat, + + COFF, + ELF, + MachO, }; private: @@ -132,6 +167,9 @@ private: /// The parsed arch type. ArchType Arch; + /// The parsed subarchitecture type. + SubArchType SubArch; + /// The parsed vendor type. VendorType Vendor; @@ -141,13 +179,16 @@ private: /// The parsed Environment type. EnvironmentType Environment; + /// The object format type. + ObjectFormatType ObjectFormat; + public: /// @name Constructors /// @{ /// \brief Default constructor is the same as an empty string and leaves all /// triple fields unknown. - Triple() : Data(), Arch(), Vendor(), OS(), Environment() {} + Triple() : Data(), Arch(), Vendor(), OS(), Environment(), ObjectFormat() {} explicit Triple(const Twine &Str); Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr); @@ -171,6 +212,9 @@ public: /// getArch - Get the parsed architecture type of this triple. ArchType getArch() const { return Arch; } + /// getSubArch - get the parsed subarchitecture type for this triple. + SubArchType getSubArch() const { return SubArch; } + /// getVendor - Get the parsed vendor type of this triple. VendorType getVendor() const { return Vendor; } @@ -186,6 +230,9 @@ public: /// getEnvironment - Get the parsed environment type of this triple. EnvironmentType getEnvironment() const { return Environment; } + /// getFormat - Get the object format for this triple. + ObjectFormatType getObjectFormat() const { return ObjectFormat; } + /// getOSVersion - Parse the version number from the OS name component of the /// triple, if present. /// @@ -314,14 +361,42 @@ public: return isMacOSX() || isiOS(); } + bool isOSFreeBSD() const { + return getOS() == Triple::FreeBSD; + } + + bool isWindowsMSVCEnvironment() const { + return getOS() == Triple::Win32 && + (getEnvironment() == Triple::UnknownEnvironment || + getEnvironment() == Triple::MSVC); + } + + bool isKnownWindowsMSVCEnvironment() const { + return getOS() == Triple::Win32 && getEnvironment() == Triple::MSVC; + } + + bool isWindowsItaniumEnvironment() const { + return getOS() == Triple::Win32 && getEnvironment() == Triple::Itanium; + } + + bool isWindowsCygwinEnvironment() const { + return getOS() == Triple::Cygwin || + (getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus); + } + + bool isWindowsGNUEnvironment() const { + return getOS() == Triple::MinGW32 || + (getOS() == Triple::Win32 && getEnvironment() == Triple::GNU); + } + /// \brief Tests for either Cygwin or MinGW OS bool isOSCygMing() const { - return getOS() == Triple::Cygwin || getOS() == Triple::MinGW32; + return isWindowsCygwinEnvironment() || isWindowsGNUEnvironment(); } /// \brief Is this a "Windows" OS targeting a "MSVCRT.dll" environment. bool isOSMSVCRT() const { - return getOS() == Triple::Win32 || getOS() == Triple::MinGW32; + return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment(); } /// \brief Tests whether the OS is Windows. @@ -341,18 +416,17 @@ public: /// \brief Tests whether the OS uses the ELF binary format. bool isOSBinFormatELF() const { - return !isOSDarwin() && !isOSWindows(); + return getObjectFormat() == Triple::ELF; } /// \brief Tests whether the OS uses the COFF binary format. bool isOSBinFormatCOFF() const { - return isOSWindows(); + return getObjectFormat() == Triple::COFF; } /// \brief Tests whether the environment is MachO. - // FIXME: Should this be an OSBinFormat predicate? - bool isEnvironmentMachO() const { - return getEnvironment() == Triple::MachO || isOSDarwin(); + bool isOSBinFormatMachO() const { + return getObjectFormat() == Triple::MachO; } /// @} @@ -375,6 +449,9 @@ public: /// to a known type. void setEnvironment(EnvironmentType Kind); + /// setObjectFormat - Set the object file format + void setObjectFormat(ObjectFormatType Kind); + /// setTriple - Set all components to the new triple \p Str. void setTriple(const Twine &Str); @@ -422,6 +499,12 @@ public: /// architecture if no such variant can be found. llvm::Triple get64BitArchVariant() const; + /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. + /// + /// \param Arch the architecture name (e.g., "armv7s"). If it is an empty + /// string then the triple's arch name is used. + const char* getARMCPUForArch(StringRef Arch = StringRef()) const; + /// @} /// @name Static helpers for IDs. /// @{ diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index e16c6b491386..4be3ee6f82db 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -182,6 +182,10 @@ namespace llvm { assert(isValid() && "Invalid twine!"); } + /// Since the intended use of twines is as temporary objects, assignments + /// when concatenating might cause undefined behavior or stack corruptions + Twine &operator=(const Twine &Other) LLVM_DELETED_FUNCTION; + /// isNull - Check for the null twine. bool isNull() const { return getLHSKind() == NullKind; @@ -374,7 +378,7 @@ namespace llvm { static Twine utohexstr(const uint64_t &Val) { Child LHS, RHS; LHS.uHex = &Val; - RHS.twine = 0; + RHS.twine = nullptr; return Twine(LHS, UHexKind, RHS, EmptyKind); } diff --git a/include/llvm/ADT/UniqueVector.h b/include/llvm/ADT/UniqueVector.h index 2d02d1ce166f..a9cb2f5709eb 100644 --- a/include/llvm/ADT/UniqueVector.h +++ b/include/llvm/ADT/UniqueVector.h @@ -22,13 +22,18 @@ namespace llvm { /// class should have an implementation of operator== and of operator<. /// Entries can be fetched using operator[] with the entry ID. template<class T> class UniqueVector { +public: + typedef typename std::vector<T> VectorType; + typedef typename VectorType::iterator iterator; + typedef typename VectorType::const_iterator const_iterator; + private: // Map - Used to handle the correspondence of entry to ID. std::map<T, unsigned> Map; // Vector - ID ordered vector of entries. Entries can be indexed by ID - 1. // - std::vector<T> Vector; + VectorType Vector; public: /// insert - Append entry to the vector if it doesn't already exist. Returns @@ -68,6 +73,18 @@ public: return Vector[ID - 1]; } + /// \brief Return an iterator to the start of the vector. + iterator begin() { return Vector.begin(); } + + /// \brief Return an iterator to the start of the vector. + const_iterator begin() const { return Vector.begin(); } + + /// \brief Return an iterator to the end of the vector. + iterator end() { return Vector.end(); } + + /// \brief Return an iterator to the end of the vector. + const_iterator end() const { return Vector.end(); } + /// size - Returns the number of entries in the vector. /// size_t size() const { return Vector.size(); } diff --git a/include/llvm/ADT/edit_distance.h b/include/llvm/ADT/edit_distance.h index f77ef13fef2b..9ee1edc54e05 100644 --- a/include/llvm/ADT/edit_distance.h +++ b/include/llvm/ADT/edit_distance.h @@ -17,8 +17,8 @@ #define LLVM_ADT_EDIT_DISTANCE_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/OwningPtr.h" #include <algorithm> +#include <memory> namespace llvm { @@ -57,7 +57,7 @@ unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray, const unsigned SmallBufferSize = 64; unsigned SmallBuffer[SmallBufferSize]; - llvm::OwningArrayPtr<unsigned> Allocated; + std::unique_ptr<unsigned[]> Allocated; unsigned *Previous = SmallBuffer; if (2*(n + 1) > SmallBufferSize) { Previous = new unsigned [2*(n+1)]; diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 6aeaa91f1b16..bc148452f217 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -83,7 +83,7 @@ struct ilist_sentinel_traits { /// provideInitialHead - when constructing an ilist, provide a starting /// value for its Head /// @return null node to indicate that it needs to be allocated later - static NodeTy *provideInitialHead() { return 0; } + static NodeTy *provideInitialHead() { return nullptr; } /// ensureHead - make sure that Head is either already /// initialized or assigned a fresh sentinel @@ -92,7 +92,7 @@ struct ilist_sentinel_traits { if (!Head) { Head = ilist_traits<NodeTy>::createSentinel(); ilist_traits<NodeTy>::noteHead(Head, Head); - ilist_traits<NodeTy>::setNext(Head, 0); + ilist_traits<NodeTy>::setNext(Head, nullptr); return Head; } return ilist_traits<NodeTy>::getPrev(Head); @@ -175,7 +175,7 @@ public: ilist_iterator(pointer NP) : NodePtr(NP) {} ilist_iterator(reference NR) : NodePtr(&NR) {} - ilist_iterator() : NodePtr(0) {} + ilist_iterator() : NodePtr(nullptr) {} // This is templated so that we can allow constructing a const iterator from // a nonconst iterator... @@ -383,7 +383,7 @@ public: // Miscellaneous inspection routines. size_type max_size() const { return size_type(-1); } bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { - return Head == 0 || Head == getTail(); + return !Head || Head == getTail(); } // Front and back accessor functions... @@ -451,8 +451,8 @@ public: // an ilist (and potentially deleted) with iterators still pointing at it. // When those iterators are incremented or decremented, they will assert on // the null next/prev pointer instead of "usually working". - this->setNext(Node, 0); - this->setPrev(Node, 0); + this->setNext(Node, nullptr); + this->setPrev(Node, nullptr); return Node; } @@ -494,9 +494,9 @@ private: // Note: we have to be careful about the case when we move the first node // in the list. This node is the list sentinel node and we can't move it. NodeTy *ThisSentinel = getTail(); - setTail(0); + setTail(nullptr); NodeTy *L2Sentinel = L2.getTail(); - L2.setTail(0); + L2.setTail(nullptr); // Remove [first, last) from its old position. NodeTy *First = &*first, *Prev = this->getPrev(First); @@ -537,7 +537,7 @@ public: // size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const { - if (Head == 0) return 0; // Don't require construction of sentinel if empty. + if (!Head) return 0; // Don't require construction of sentinel if empty. return std::distance(begin(), end()); } diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h index 03612440e7ac..85aa7a4b1f7f 100644 --- a/include/llvm/ADT/ilist_node.h +++ b/include/llvm/ADT/ilist_node.h @@ -30,7 +30,7 @@ protected: NodeTy *getPrev() { return Prev; } const NodeTy *getPrev() const { return Prev; } void setPrev(NodeTy *P) { Prev = P; } - ilist_half_node() : Prev(0) {} + ilist_half_node() : Prev(nullptr) {} }; template<typename NodeTy> @@ -48,7 +48,7 @@ class ilist_node : private ilist_half_node<NodeTy> { const NodeTy *getNext() const { return Next; } void setNext(NodeTy *N) { Next = N; } protected: - ilist_node() : Next(0) {} + ilist_node() : Next(nullptr) {} public: /// @name Adjacent Node Accessors @@ -60,7 +60,7 @@ public: // Check for sentinel. if (!Prev->getNext()) - return 0; + return nullptr; return Prev; } @@ -71,7 +71,7 @@ public: // Check for sentinel. if (!Prev->getNext()) - return 0; + return nullptr; return Prev; } @@ -82,7 +82,7 @@ public: // Check for sentinel. if (!Next->getNext()) - return 0; + return nullptr; return Next; } @@ -93,7 +93,7 @@ public: // Check for sentinel. if (!Next->getNext()) - return 0; + return nullptr; return Next; } diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h new file mode 100644 index 000000000000..56041dbb106c --- /dev/null +++ b/include/llvm/ADT/iterator.h @@ -0,0 +1,244 @@ +//===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERATOR_H +#define LLVM_ADT_ITERATOR_H + +#include <iterator> +#include <cstddef> + +namespace llvm { + +/// \brief CRTP base class which implements the entire standard iterator facade +/// in terms of a minimal subset of the interface. +/// +/// Use this when it is reasonable to implement most of the iterator +/// functionality in terms of a core subset. If you need special behavior or +/// there are performance implications for this, you may want to override the +/// relevant members instead. +/// +/// Note, one abstraction that this does *not* provide is implementing +/// subtraction in terms of addition by negating the difference. Negation isn't +/// always information preserving, and I can see very reasonable iterator +/// designs where this doesn't work well. It doesn't really force much added +/// boilerplate anyways. +/// +/// Another abstraction that this doesn't provide is implementing increment in +/// terms of addition of one. These aren't equivalent for all iterator +/// categories, and respecting that adds a lot of complexity for little gain. +template <typename DerivedT, typename IteratorCategoryT, typename T, + typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *, + typename ReferenceT = T &> +class iterator_facade_base + : public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT, + ReferenceT> { +protected: + enum { + IsRandomAccess = + std::is_base_of<std::random_access_iterator_tag, IteratorCategoryT>::value, + IsBidirectional = + std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value, + }; + +public: + DerivedT operator+(DifferenceTypeT n) const { + static_assert( + IsRandomAccess, + "The '+' operator is only defined for random access iterators."); + DerivedT tmp = *static_cast<const DerivedT *>(this); + tmp += n; + return tmp; + } + friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) { + static_assert( + IsRandomAccess, + "The '+' operator is only defined for random access iterators."); + return i + n; + } + DerivedT operator-(DifferenceTypeT n) const { + static_assert( + IsRandomAccess, + "The '-' operator is only defined for random access iterators."); + DerivedT tmp = *static_cast<const DerivedT *>(this); + tmp -= n; + return tmp; + } + + DerivedT &operator++() { + return static_cast<DerivedT *>(this)->operator+=(1); + } + DerivedT operator++(int) { + DerivedT tmp = *static_cast<DerivedT *>(this); + ++*static_cast<DerivedT *>(this); + return tmp; + } + DerivedT &operator--() { + static_assert( + IsBidirectional, + "The decrement operator is only defined for bidirectional iterators."); + return static_cast<DerivedT *>(this)->operator-=(1); + } + DerivedT operator--(int) { + static_assert( + IsBidirectional, + "The decrement operator is only defined for bidirectional iterators."); + DerivedT tmp = *static_cast<DerivedT *>(this); + --*static_cast<DerivedT *>(this); + return tmp; + } + + bool operator!=(const DerivedT &RHS) const { + return !static_cast<const DerivedT *>(this)->operator==(RHS); + } + + bool operator>(const DerivedT &RHS) const { + static_assert( + IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return !static_cast<const DerivedT *>(this)->operator<(RHS) && + !static_cast<const DerivedT *>(this)->operator==(RHS); + } + bool operator<=(const DerivedT &RHS) const { + static_assert( + IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return !static_cast<const DerivedT *>(this)->operator>(RHS); + } + bool operator>=(const DerivedT &RHS) const { + static_assert( + IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return !static_cast<const DerivedT *>(this)->operator<(RHS); + } + + PointerT operator->() const { + return &static_cast<const DerivedT *>(this)->operator*(); + } + ReferenceT operator[](DifferenceTypeT n) const { + static_assert(IsRandomAccess, + "Subscripting is only defined for random access iterators."); + return *static_cast<const DerivedT *>(this)->operator+(n); + } +}; + +/// \brief CRTP base class for adapting an iterator to a different type. +/// +/// This class can be used through CRTP to adapt one iterator into another. +/// Typically this is done through providing in the derived class a custom \c +/// operator* implementation. Other methods can be overridden as well. +template < + typename DerivedT, typename WrappedIteratorT, + typename IteratorCategoryT = + typename std::iterator_traits<WrappedIteratorT>::iterator_category, + typename T = typename std::iterator_traits<WrappedIteratorT>::value_type, + typename DifferenceTypeT = + typename std::iterator_traits<WrappedIteratorT>::difference_type, + typename PointerT = T *, typename ReferenceT = T &, + // Don't provide these, they are mostly to act as aliases below. + typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>> +class iterator_adaptor_base + : public iterator_facade_base<DerivedT, IteratorCategoryT, T, + DifferenceTypeT, PointerT, ReferenceT> { + typedef typename iterator_adaptor_base::iterator_facade_base BaseT; + +protected: + WrappedIteratorT I; + + iterator_adaptor_base() {} + + template <typename U> + explicit iterator_adaptor_base( + U &&u, + typename std::enable_if< + !std::is_base_of<typename std::remove_cv< + typename std::remove_reference<U>::type>::type, + DerivedT>::value, + int>::type = 0) + : I(std::forward<U &&>(u)) {} + +public: + typedef DifferenceTypeT difference_type; + + DerivedT &operator+=(difference_type n) { + static_assert( + BaseT::IsRandomAccess, + "The '+=' operator is only defined for random access iterators."); + I += n; + return *static_cast<DerivedT *>(this); + } + DerivedT &operator-=(difference_type n) { + static_assert( + BaseT::IsRandomAccess, + "The '-=' operator is only defined for random access iterators."); + I -= n; + return *static_cast<DerivedT *>(this); + } + using BaseT::operator-; + difference_type operator-(const DerivedT &RHS) const { + static_assert( + BaseT::IsRandomAccess, + "The '-' operator is only defined for random access iterators."); + return I - RHS.I; + } + + // We have to explicitly provide ++ and -- rather than letting the facade + // forward to += because WrappedIteratorT might not support +=. + using BaseT::operator++; + DerivedT &operator++() { + ++I; + return *static_cast<DerivedT *>(this); + } + using BaseT::operator--; + DerivedT &operator--() { + static_assert( + BaseT::IsBidirectional, + "The decrement operator is only defined for bidirectional iterators."); + --I; + return *static_cast<DerivedT *>(this); + } + + bool operator==(const DerivedT &RHS) const { return I == RHS.I; } + bool operator<(const DerivedT &RHS) const { + static_assert( + BaseT::IsRandomAccess, + "Relational operators are only defined for random access iterators."); + return I < RHS.I; + } + + ReferenceT operator*() const { return *I; } +}; + +/// \brief An iterator type that allows iterating over the pointees via some +/// other iterator. +/// +/// The typical usage of this is to expose a type that iterates over Ts, but +/// which is implemented with some iterator over T*s: +/// +/// \code +/// typedef pointee_iterator<SmallVectorImpl<T *>::iterator> iterator; +/// \endcode +template <typename WrappedIteratorT, + typename T = typename std::remove_reference< + decltype(**std::declval<WrappedIteratorT>())>::type> +struct pointee_iterator + : iterator_adaptor_base< + pointee_iterator<WrappedIteratorT>, WrappedIteratorT, + typename std::iterator_traits<WrappedIteratorT>::iterator_category, + T> { + pointee_iterator() {} + template <typename U> + pointee_iterator(U &&u) + : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {} + + T &operator*() const { return **this->I; } +}; + +} + +#endif diff --git a/include/llvm/ADT/iterator_range.h b/include/llvm/ADT/iterator_range.h new file mode 100644 index 000000000000..dd17d6c8f7b4 --- /dev/null +++ b/include/llvm/ADT/iterator_range.h @@ -0,0 +1,53 @@ +//===- iterator_range.h - A range adaptor for iterators ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This provides a very simple, boring adaptor for a begin and end iterator +/// into a range type. This should be used to build range views that work well +/// with range based for loops and range based constructors. +/// +/// Note that code here follows more standards-based coding conventions as it +/// is mirroring proposed interfaces for standardization. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERATOR_RANGE_H +#define LLVM_ADT_ITERATOR_RANGE_H + +#include <utility> + +namespace llvm { + +/// \brief A range adaptor for a pair of iterators. +/// +/// This just wraps two iterators into a range-compatible interface. Nothing +/// fancy at all. +template <typename IteratorT> +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)) {} + + IteratorT begin() const { return begin_iterator; } + IteratorT end() const { return end_iterator; } +}; + +/// \brief Convenience function for iterating over sub-ranges. +/// +/// This provides a bit of syntactic sugar to make using sub-ranges +/// in for loops a bit easier. Analogous to std::make_pair(). +template <class T> iterator_range<T> make_range(T x, T y) { + return iterator_range<T>(std::move(x), std::move(y)); +} +} + +#endif diff --git a/include/llvm/ADT/polymorphic_ptr.h b/include/llvm/ADT/polymorphic_ptr.h deleted file mode 100644 index b8d8d71238e3..000000000000 --- a/include/llvm/ADT/polymorphic_ptr.h +++ /dev/null @@ -1,117 +0,0 @@ -//===- llvm/ADT/polymorphic_ptr.h - Smart copyable owned ptr ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// This file provides a polymorphic_ptr class template. See the class comments -/// for details about this API, its intended use cases, etc. -/// -/// The primary motivation here is to work around the necessity of copy -/// semantics in C++98. This is typically used where any actual copies are -/// incidental or unnecessary. As a consequence, it is expected to cease to be -/// useful and be removed when we can directly rely on move-only types. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_POLYMORPHIC_PTR_H -#define LLVM_ADT_POLYMORPHIC_PTR_H - -#include "llvm/Support/Compiler.h" - -namespace llvm { - -/// \brief An owning, copyable polymorphic smart pointer. -/// -/// This pointer exists to provide copyable owned smart pointer. Rather than -/// shared ownership semantics, it has unique ownership semantics and deep copy -/// semantics. It is copyable by requiring that the underlying type exposes -/// a method which can produce a (heap allocated) clone. -/// -/// Note that in almost all scenarios use of this could be avoided if we could -/// build move-only containers of a std::unique_ptr, but until then this -/// provides an effective way to place polymorphic objects in a container. -template <typename T> class polymorphic_ptr { - T *ptr; - -public: - polymorphic_ptr(T *ptr = 0) : ptr(ptr) {} - polymorphic_ptr(const polymorphic_ptr &arg) : ptr(arg ? arg->clone() : 0) {} -#if LLVM_HAS_RVALUE_REFERENCES - polymorphic_ptr(polymorphic_ptr &&arg) : ptr(arg.take()) {} -#endif - ~polymorphic_ptr() { delete ptr; } - - polymorphic_ptr &operator=(polymorphic_ptr arg) { - swap(arg); - return *this; - } - polymorphic_ptr &operator=(T *arg) { - if (arg != ptr) { - delete ptr; - ptr = arg; - } - return *this; - } - - T &operator*() const { return *ptr; } - T *operator->() const { return ptr; } - LLVM_EXPLICIT operator bool() const { return ptr != 0; } - bool operator!() const { return ptr == 0; } - - T *get() const { return ptr; } - - T *take() { - T *tmp = ptr; - ptr = 0; - return tmp; - } - - void swap(polymorphic_ptr &arg) { - T *tmp = ptr; - ptr = arg.ptr; - arg.ptr = tmp; - } -}; - -template <typename T> -void swap(polymorphic_ptr<T> &lhs, polymorphic_ptr<T> &rhs) { - lhs.swap(rhs); -} - -template <typename T, typename U> -bool operator==(const polymorphic_ptr<T> &lhs, const polymorphic_ptr<U> &rhs) { - return lhs.get() == rhs.get(); -} - -template <typename T, typename U> -bool operator!=(const polymorphic_ptr<T> &lhs, const polymorphic_ptr<U> &rhs) { - return lhs.get() != rhs.get(); -} - -template <typename T, typename U> -bool operator==(const polymorphic_ptr<T> &lhs, U *rhs) { - return lhs.get() == rhs; -} - -template <typename T, typename U> -bool operator!=(const polymorphic_ptr<T> &lhs, U *rhs) { - return lhs.get() != rhs; -} - -template <typename T, typename U> -bool operator==(T *lhs, const polymorphic_ptr<U> &rhs) { - return lhs == rhs.get(); -} - -template <typename T, typename U> -bool operator!=(T *lhs, const polymorphic_ptr<U> &rhs) { - return lhs != rhs.get(); -} - -} - -#endif diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index efafbbdb7761..689766446445 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -38,7 +38,7 @@ #define LLVM_ANALYSIS_ALIASANALYSIS_H #include "llvm/ADT/DenseMap.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" namespace llvm { @@ -55,7 +55,7 @@ class DominatorTree; class AliasAnalysis { protected: - const DataLayout *TD; + const DataLayout *DL; const TargetLibraryInfo *TLI; private: @@ -75,7 +75,7 @@ protected: public: static char ID; // Class identification, replacement for typeinfo - AliasAnalysis() : TD(0), TLI(0), AA(0) {} + AliasAnalysis() : DL(nullptr), TLI(nullptr), AA(nullptr) {} virtual ~AliasAnalysis(); // We want to be subclassed /// UnknownSize - This is a special value which can be used with the @@ -86,7 +86,7 @@ public: /// getDataLayout - Return a pointer to the current DataLayout object, or /// null if no DataLayout object is available. /// - const DataLayout *getDataLayout() const { return TD; } + const DataLayout *getDataLayout() const { return DL; } /// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo /// object, or null if no TargetLibraryInfo object is available. @@ -116,8 +116,8 @@ public: /// the location, or null if there is no known unique tag. const MDNode *TBAATag; - explicit Location(const Value *P = 0, uint64_t S = UnknownSize, - const MDNode *N = 0) + explicit Location(const Value *P = nullptr, uint64_t S = UnknownSize, + const MDNode *N = nullptr) : Ptr(P), Size(S), TBAATag(N) {} Location getWithNewPtr(const Value *NewPtr) const { @@ -134,7 +134,7 @@ public: Location getWithoutTBAATag() const { Location Copy(*this); - Copy.TBAATag = 0; + Copy.TBAATag = nullptr; return Copy; } }; @@ -274,6 +274,14 @@ public: UnknownModRefBehavior = Anywhere | ModRef }; + /// Get the location associated with a pointer argument of a callsite. + /// The mask bits are set to indicate the allowed aliasing ModRef kinds. + /// Note that these mask bits do not necessarily account for the overall + /// behavior of the function, but rather only provide additional + /// per-argument information. + virtual Location getArgLocation(ImmutableCallSite CS, unsigned ArgIdx, + ModRefResult &Mask); + /// getModRefBehavior - Return the behavior when calling the given call site. virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS); @@ -560,12 +568,12 @@ struct DenseMapInfo<AliasAnalysis::Location> { static inline AliasAnalysis::Location getEmptyKey() { return AliasAnalysis::Location(DenseMapInfo<const Value *>::getEmptyKey(), - 0, 0); + 0, nullptr); } static inline AliasAnalysis::Location getTombstoneKey() { return AliasAnalysis::Location(DenseMapInfo<const Value *>::getTombstoneKey(), - 0, 0); + 0, nullptr); } static unsigned getHashValue(const AliasAnalysis::Location &Val) { return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^ @@ -597,6 +605,13 @@ bool isNoAliasArgument(const Value *V); /// bool isIdentifiedObject(const Value *V); +/// isIdentifiedFunctionLocal - Return true if V is umabigously identified +/// at the function-level. Different IdentifiedFunctionLocals can't alias. +/// Further, an IdentifiedFunctionLocal can not alias with any function +/// arguments other than itself, which is not necessarily true for +/// IdentifiedObjects. +bool isIdentifiedFunctionLocal(const Value *V); + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index da007072e559..6117d91ec651 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -20,7 +20,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include <vector> namespace llvm { @@ -43,13 +43,13 @@ class AliasSet : public ilist_node<AliasSet> { const MDNode *TBAAInfo; public: PointerRec(Value *V) - : Val(V), PrevInList(0), NextInList(0), AS(0), Size(0), + : Val(V), PrevInList(nullptr), NextInList(nullptr), AS(nullptr), Size(0), TBAAInfo(DenseMapInfo<const MDNode *>::getEmptyKey()) {} Value *getValue() const { return Val; } PointerRec *getNext() const { return NextInList; } - bool hasAliasSet() const { return AS != 0; } + bool hasAliasSet() const { return AS != nullptr; } PointerRec** setPrevInList(PointerRec **PIL) { PrevInList = PIL; @@ -75,7 +75,7 @@ class AliasSet : public ilist_node<AliasSet> { // If we have missing or conflicting TBAAInfo, return null. if (TBAAInfo == DenseMapInfo<const MDNode *>::getEmptyKey() || TBAAInfo == DenseMapInfo<const MDNode *>::getTombstoneKey()) - return 0; + return nullptr; return TBAAInfo; } @@ -91,7 +91,7 @@ class AliasSet : public ilist_node<AliasSet> { } void setAliasSet(AliasSet *as) { - assert(AS == 0 && "Already have an alias set!"); + assert(!AS && "Already have an alias set!"); AS = as; } @@ -100,7 +100,7 @@ class AliasSet : public ilist_node<AliasSet> { *PrevInList = NextInList; if (AS->PtrListEnd == &NextInList) { AS->PtrListEnd = PrevInList; - assert(*AS->PtrListEnd == 0 && "List not terminated right!"); + assert(*AS->PtrListEnd == nullptr && "List not terminated right!"); } delete this; } @@ -174,7 +174,7 @@ public: class iterator; iterator begin() const { return iterator(PtrList); } iterator end() const { return iterator(); } - bool empty() const { return PtrList == 0; } + bool empty() const { return PtrList == nullptr; } void print(raw_ostream &OS) const; void dump() const; @@ -184,7 +184,7 @@ public: PointerRec, ptrdiff_t> { PointerRec *CurNode; public: - explicit iterator(PointerRec *CN = 0) : CurNode(CN) {} + explicit iterator(PointerRec *CN = nullptr) : CurNode(CN) {} bool operator==(const iterator& x) const { return CurNode == x.CurNode; @@ -220,8 +220,9 @@ private: // Can only be created by AliasSetTracker. Also, ilist creates one // to serve as a sentinel. friend struct ilist_sentinel_traits<AliasSet>; - AliasSet() : PtrList(0), PtrListEnd(&PtrList), Forward(0), RefCount(0), - AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { + AliasSet() + : PtrList(nullptr), PtrListEnd(&PtrList), Forward(nullptr), RefCount(0), + AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { } AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION; @@ -282,10 +283,10 @@ class AliasSetTracker { /// notified whenever a Value is deleted. class ASTCallbackVH : public CallbackVH { AliasSetTracker *AST; - virtual void deleted(); - virtual void allUsesReplacedWith(Value *); + void deleted() override; + void allUsesReplacedWith(Value *) override; public: - ASTCallbackVH(Value *V, AliasSetTracker *AST = 0); + ASTCallbackVH(Value *V, AliasSetTracker *AST = nullptr); ASTCallbackVH &operator=(Value *V); }; /// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that tell us how to @@ -354,7 +355,7 @@ public: /// pointer didn't alias anything). AliasSet &getAliasSetForPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo, - bool *New = 0); + bool *New = nullptr); /// getAliasSetForPointerIfExists - Return the alias set containing the /// location specified if one exists, otherwise return null. @@ -408,7 +409,7 @@ private: // entry for the pointer if it doesn't already exist. AliasSet::PointerRec &getEntryFor(Value *V) { AliasSet::PointerRec *&Entry = PointerMap[ASTCallbackVH(V, this)]; - if (Entry == 0) + if (!Entry) Entry = new AliasSet::PointerRec(V); return *Entry; } diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h deleted file mode 100644 index 817a44188b89..000000000000 --- a/include/llvm/Analysis/BlockFrequencyImpl.h +++ /dev/null @@ -1,347 +0,0 @@ -//===-- BlockFrequencyImpl.h - Block Frequency Implementation --*- C++ -*--===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Shared implementation of BlockFrequency for IR and Machine Instructions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H -#define LLVM_ANALYSIS_BLOCKFREQUENCYIMPL_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/PostOrderIterator.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/Support/BlockFrequency.h" -#include "llvm/Support/BranchProbability.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include <string> -#include <vector> - -namespace llvm { - - -class BlockFrequencyInfo; -class MachineBlockFrequencyInfo; - -/// BlockFrequencyImpl implements block frequency algorithm for IR and -/// Machine Instructions. Algorithm starts with value ENTRY_FREQ -/// for the entry block and then propagates frequencies using branch weights -/// from (Machine)BranchProbabilityInfo. LoopInfo is not required because -/// algorithm can find "backedges" by itself. -template<class BlockT, class FunctionT, class BlockProbInfoT> -class BlockFrequencyImpl { - - DenseMap<const BlockT *, BlockFrequency> Freqs; - - BlockProbInfoT *BPI; - - FunctionT *Fn; - - typedef GraphTraits< Inverse<BlockT *> > GT; - - const uint32_t EntryFreq; - - std::string getBlockName(BasicBlock *BB) const { - return BB->getName().str(); - } - - std::string getBlockName(MachineBasicBlock *MBB) const { - std::string str; - raw_string_ostream ss(str); - ss << "BB#" << MBB->getNumber(); - - if (const BasicBlock *BB = MBB->getBasicBlock()) - ss << " derived from LLVM BB " << BB->getName(); - - return ss.str(); - } - - void setBlockFreq(BlockT *BB, BlockFrequency Freq) { - Freqs[BB] = Freq; - DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = " << Freq << "\n"); - } - - /// getEdgeFreq - Return edge frequency based on SRC frequency and Src -> Dst - /// edge probability. - BlockFrequency getEdgeFreq(BlockT *Src, BlockT *Dst) const { - BranchProbability Prob = BPI->getEdgeProbability(Src, Dst); - return getBlockFreq(Src) * Prob; - } - - /// incBlockFreq - Increase BB block frequency by FREQ. - /// - void incBlockFreq(BlockT *BB, BlockFrequency Freq) { - Freqs[BB] += Freq; - DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += " << Freq - << " --> " << Freqs[BB] << "\n"); - } - - // All blocks in postorder. - std::vector<BlockT *> POT; - - // Map Block -> Position in reverse-postorder list. - DenseMap<BlockT *, unsigned> RPO; - - // For each loop header, record the per-iteration probability of exiting the - // loop. This is the reciprocal of the expected number of loop iterations. - typedef DenseMap<BlockT*, BranchProbability> LoopExitProbMap; - LoopExitProbMap LoopExitProb; - - // (reverse-)postorder traversal iterators. - typedef typename std::vector<BlockT *>::iterator pot_iterator; - typedef typename std::vector<BlockT *>::reverse_iterator rpot_iterator; - - pot_iterator pot_begin() { return POT.begin(); } - pot_iterator pot_end() { return POT.end(); } - - rpot_iterator rpot_begin() { return POT.rbegin(); } - rpot_iterator rpot_end() { return POT.rend(); } - - rpot_iterator rpot_at(BlockT *BB) { - rpot_iterator I = rpot_begin(); - unsigned idx = RPO.lookup(BB); - assert(idx); - std::advance(I, idx - 1); - - assert(*I == BB); - return I; - } - - /// isBackedge - Return if edge Src -> Dst is a reachable backedge. - /// - bool isBackedge(BlockT *Src, BlockT *Dst) const { - unsigned a = RPO.lookup(Src); - if (!a) - return false; - unsigned b = RPO.lookup(Dst); - assert(b && "Destination block should be reachable"); - return a >= b; - } - - /// getSingleBlockPred - return single BB block predecessor or NULL if - /// BB has none or more predecessors. - BlockT *getSingleBlockPred(BlockT *BB) { - typename GT::ChildIteratorType - PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB), - PE = GraphTraits< Inverse<BlockT *> >::child_end(BB); - - if (PI == PE) - return 0; - - BlockT *Pred = *PI; - - ++PI; - if (PI != PE) - return 0; - - return Pred; - } - - void doBlock(BlockT *BB, BlockT *LoopHead, - SmallPtrSet<BlockT *, 8> &BlocksInLoop) { - - DEBUG(dbgs() << "doBlock(" << getBlockName(BB) << ")\n"); - setBlockFreq(BB, 0); - - if (BB == LoopHead) { - setBlockFreq(BB, EntryFreq); - return; - } - - if(BlockT *Pred = getSingleBlockPred(BB)) { - if (BlocksInLoop.count(Pred)) - setBlockFreq(BB, getEdgeFreq(Pred, BB)); - // TODO: else? irreducible, ignore it for now. - return; - } - - bool isInLoop = false; - bool isLoopHead = false; - - for (typename GT::ChildIteratorType - PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB), - PE = GraphTraits< Inverse<BlockT *> >::child_end(BB); - PI != PE; ++PI) { - BlockT *Pred = *PI; - - if (isBackedge(Pred, BB)) { - isLoopHead = true; - } else if (BlocksInLoop.count(Pred)) { - incBlockFreq(BB, getEdgeFreq(Pred, BB)); - isInLoop = true; - } - // TODO: else? irreducible. - } - - if (!isInLoop) - return; - - if (!isLoopHead) - return; - - // This block is a loop header, so boost its frequency by the expected - // number of loop iterations. The loop blocks will be revisited so they all - // get this boost. - typename LoopExitProbMap::const_iterator I = LoopExitProb.find(BB); - assert(I != LoopExitProb.end() && "Loop header missing from table"); - Freqs[BB] /= I->second; - DEBUG(dbgs() << "Loop header scaled to " << Freqs[BB] << ".\n"); - } - - /// doLoop - Propagate block frequency down through the loop. - void doLoop(BlockT *Head, BlockT *Tail) { - DEBUG(dbgs() << "doLoop(" << getBlockName(Head) << ", " - << getBlockName(Tail) << ")\n"); - - SmallPtrSet<BlockT *, 8> BlocksInLoop; - - for (rpot_iterator I = rpot_at(Head), E = rpot_at(Tail); ; ++I) { - BlockT *BB = *I; - doBlock(BB, Head, BlocksInLoop); - - BlocksInLoop.insert(BB); - if (I == E) - break; - } - - // Compute loop's cyclic probability using backedges probabilities. - BlockFrequency BackFreq; - for (typename GT::ChildIteratorType - PI = GraphTraits< Inverse<BlockT *> >::child_begin(Head), - PE = GraphTraits< Inverse<BlockT *> >::child_end(Head); - PI != PE; ++PI) { - BlockT *Pred = *PI; - assert(Pred); - if (isBackedge(Pred, Head)) - BackFreq += getEdgeFreq(Pred, Head); - } - - // The cyclic probability is freq(BackEdges) / freq(Head), where freq(Head) - // only counts edges entering the loop, not the loop backedges. - // The probability of leaving the loop on each iteration is: - // - // ExitProb = 1 - CyclicProb - // - // The Expected number of loop iterations is: - // - // Iterations = 1 / ExitProb - // - uint64_t D = std::max(getBlockFreq(Head).getFrequency(), UINT64_C(1)); - uint64_t N = std::max(BackFreq.getFrequency(), UINT64_C(1)); - if (N < D) - N = D - N; - else - // We'd expect N < D, but rounding and saturation means that can't be - // guaranteed. - N = 1; - - // Now ExitProb = N / D, make sure it fits in an i32/i32 fraction. - assert(N <= D); - if (D > UINT32_MAX) { - unsigned Shift = 32 - countLeadingZeros(D); - D >>= Shift; - N >>= Shift; - if (N == 0) - N = 1; - } - BranchProbability LEP = BranchProbability(N, D); - LoopExitProb.insert(std::make_pair(Head, LEP)); - DEBUG(dbgs() << "LoopExitProb[" << getBlockName(Head) << "] = " << LEP - << " from 1 - " << BackFreq << " / " << getBlockFreq(Head) - << ".\n"); - } - - friend class BlockFrequencyInfo; - friend class MachineBlockFrequencyInfo; - - BlockFrequencyImpl() : EntryFreq(BlockFrequency::getEntryFrequency()) { } - - void doFunction(FunctionT *fn, BlockProbInfoT *bpi) { - Fn = fn; - BPI = bpi; - - // Clear everything. - RPO.clear(); - POT.clear(); - LoopExitProb.clear(); - Freqs.clear(); - - BlockT *EntryBlock = fn->begin(); - - std::copy(po_begin(EntryBlock), po_end(EntryBlock), std::back_inserter(POT)); - - unsigned RPOidx = 0; - for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) { - BlockT *BB = *I; - RPO[BB] = ++RPOidx; - DEBUG(dbgs() << "RPO[" << getBlockName(BB) << "] = " << RPO[BB] << "\n"); - } - - // Travel over all blocks in postorder. - for (pot_iterator I = pot_begin(), E = pot_end(); I != E; ++I) { - BlockT *BB = *I; - BlockT *LastTail = 0; - DEBUG(dbgs() << "POT: " << getBlockName(BB) << "\n"); - - for (typename GT::ChildIteratorType - PI = GraphTraits< Inverse<BlockT *> >::child_begin(BB), - PE = GraphTraits< Inverse<BlockT *> >::child_end(BB); - PI != PE; ++PI) { - - BlockT *Pred = *PI; - if (isBackedge(Pred, BB) && (!LastTail || RPO[Pred] > RPO[LastTail])) - LastTail = Pred; - } - - if (LastTail) - doLoop(BB, LastTail); - } - - // At the end assume the whole function as a loop, and travel over it once - // again. - doLoop(*(rpot_begin()), *(pot_begin())); - } - -public: - /// getBlockFreq - Return block frequency. Return 0 if we don't have it. - BlockFrequency getBlockFreq(const BlockT *BB) const { - typename DenseMap<const BlockT *, BlockFrequency>::const_iterator - I = Freqs.find(BB); - if (I != Freqs.end()) - return I->second; - return 0; - } - - void print(raw_ostream &OS) const { - OS << "\n\n---- Block Freqs ----\n"; - for (typename FunctionT::iterator I = Fn->begin(), E = Fn->end(); I != E;) { - BlockT *BB = I++; - OS << " " << getBlockName(BB) << " = " << getBlockFreq(BB) << "\n"; - - for (typename GraphTraits<BlockT *>::ChildIteratorType - SI = GraphTraits<BlockT *>::child_begin(BB), - SE = GraphTraits<BlockT *>::child_end(BB); SI != SE; ++SI) { - BlockT *Succ = *SI; - OS << " " << getBlockName(BB) << " -> " << getBlockName(Succ) - << " = " << getEdgeFreq(BB, Succ) << "\n"; - } - } - } - - void dump() const { - print(dbgs()); - } -}; - -} - -#endif diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h index a123d0b8c136..3289a2823c0c 100644 --- a/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/include/llvm/Analysis/BlockFrequencyInfo.h @@ -1,4 +1,4 @@ -//===------- BlockFrequencyInfo.h - Block Frequency Analysis --*- C++ -*---===// +//===- BlockFrequencyInfo.h - Block Frequency Analysis ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,14 +21,13 @@ namespace llvm { class BranchProbabilityInfo; -template<class BlockT, class FunctionT, class BranchProbInfoT> -class BlockFrequencyImpl; +template <class BlockT> class BlockFrequencyInfoImpl; -/// BlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate -/// IR basic block frequencies. +/// BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to +/// estimate IR basic block frequencies. class BlockFrequencyInfo : public FunctionPass { - - BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> *BFI; + typedef BlockFrequencyInfoImpl<BasicBlock> ImplType; + std::unique_ptr<ImplType> BFI; public: static char ID; @@ -37,10 +36,11 @@ public: ~BlockFrequencyInfo(); - void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnFunction(Function &F); - void print(raw_ostream &O, const Module *M) const; + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void print(raw_ostream &O, const Module *M) const override; const Function *getFunction() const; void view() const; @@ -50,6 +50,17 @@ public: /// comparison to the other block frequencies. We do this to avoid using of /// floating points. BlockFrequency getBlockFreq(const BasicBlock *BB) const; + + // Print the block frequency Freq to OS using the current functions entry + // frequency to convert freq into a relative decimal form. + raw_ostream &printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const; + + // Convenience method that attempts to look up the frequency associated with + // BB and print it to OS. + raw_ostream &printBlockFreq(raw_ostream &OS, const BasicBlock *BB) const; + + uint64_t getEntryFreq() const; + }; } diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h new file mode 100644 index 000000000000..bb256c7bbcc8 --- /dev/null +++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -0,0 +1,1181 @@ +//==- BlockFrequencyInfoImpl.h - Block Frequency Implementation -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Shared implementation of BlockFrequency for IR and Machine Instructions. +// See the documentation below for BlockFrequencyInfoImpl for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H +#define LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/Support/BlockFrequency.h" +#include "llvm/Support/BranchProbability.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ScaledNumber.h" +#include "llvm/Support/raw_ostream.h" +#include <deque> +#include <list> +#include <string> +#include <vector> + +#define DEBUG_TYPE "block-freq" + +namespace llvm { + +class BasicBlock; +class BranchProbabilityInfo; +class Function; +class Loop; +class LoopInfo; +class MachineBasicBlock; +class MachineBranchProbabilityInfo; +class MachineFunction; +class MachineLoop; +class MachineLoopInfo; + +namespace bfi_detail { + +struct IrreducibleGraph; + +// This is part of a workaround for a GCC 4.7 crash on lambdas. +template <class BT> struct BlockEdgesAdder; + +/// \brief Mass of a block. +/// +/// This class implements a sort of fixed-point fraction always between 0.0 and +/// 1.0. getMass() == UINT64_MAX indicates a value of 1.0. +/// +/// Masses can be added and subtracted. Simple saturation arithmetic is used, +/// so arithmetic operations never overflow or underflow. +/// +/// Masses can be multiplied. Multiplication treats full mass as 1.0 and uses +/// an inexpensive floating-point algorithm that's off-by-one (almost, but not +/// quite, maximum precision). +/// +/// Masses can be scaled by \a BranchProbability at maximum precision. +class BlockMass { + uint64_t Mass; + +public: + BlockMass() : Mass(0) {} + explicit BlockMass(uint64_t Mass) : Mass(Mass) {} + + static BlockMass getEmpty() { return BlockMass(); } + static BlockMass getFull() { return BlockMass(UINT64_MAX); } + + uint64_t getMass() const { return Mass; } + + bool isFull() const { return Mass == UINT64_MAX; } + bool isEmpty() const { return !Mass; } + + bool operator!() const { return isEmpty(); } + + /// \brief Add another mass. + /// + /// Adds another mass, saturating at \a isFull() rather than overflowing. + BlockMass &operator+=(const BlockMass &X) { + uint64_t Sum = Mass + X.Mass; + Mass = Sum < Mass ? UINT64_MAX : Sum; + return *this; + } + + /// \brief Subtract another mass. + /// + /// Subtracts another mass, saturating at \a isEmpty() rather than + /// undeflowing. + BlockMass &operator-=(const BlockMass &X) { + uint64_t Diff = Mass - X.Mass; + Mass = Diff > Mass ? 0 : Diff; + return *this; + } + + BlockMass &operator*=(const BranchProbability &P) { + Mass = P.scale(Mass); + return *this; + } + + bool operator==(const BlockMass &X) const { return Mass == X.Mass; } + bool operator!=(const BlockMass &X) const { return Mass != X.Mass; } + bool operator<=(const BlockMass &X) const { return Mass <= X.Mass; } + bool operator>=(const BlockMass &X) const { return Mass >= X.Mass; } + bool operator<(const BlockMass &X) const { return Mass < X.Mass; } + bool operator>(const BlockMass &X) const { return Mass > X.Mass; } + + /// \brief Convert to scaled number. + /// + /// Convert to \a ScaledNumber. \a isFull() gives 1.0, while \a isEmpty() + /// gives slightly above 0.0. + ScaledNumber<uint64_t> toScaled() const; + + void dump() const; + raw_ostream &print(raw_ostream &OS) const; +}; + +inline BlockMass operator+(const BlockMass &L, const BlockMass &R) { + return BlockMass(L) += R; +} +inline BlockMass operator-(const BlockMass &L, const BlockMass &R) { + return BlockMass(L) -= R; +} +inline BlockMass operator*(const BlockMass &L, const BranchProbability &R) { + return BlockMass(L) *= R; +} +inline BlockMass operator*(const BranchProbability &L, const BlockMass &R) { + return BlockMass(R) *= L; +} + +inline raw_ostream &operator<<(raw_ostream &OS, const BlockMass &X) { + return X.print(OS); +} + +} // end namespace bfi_detail + +template <> struct isPodLike<bfi_detail::BlockMass> { + static const bool value = true; +}; + +/// \brief Base class for BlockFrequencyInfoImpl +/// +/// BlockFrequencyInfoImplBase has supporting data structures and some +/// algorithms for BlockFrequencyInfoImplBase. Only algorithms that depend on +/// the block type (or that call such algorithms) are skipped here. +/// +/// Nevertheless, the majority of the overall algorithm documention lives with +/// BlockFrequencyInfoImpl. See there for details. +class BlockFrequencyInfoImplBase { +public: + typedef ScaledNumber<uint64_t> Scaled64; + typedef bfi_detail::BlockMass BlockMass; + + /// \brief Representative of a block. + /// + /// This is a simple wrapper around an index into the reverse-post-order + /// traversal of the blocks. + /// + /// Unlike a block pointer, its order has meaning (location in the + /// topological sort) and it's class is the same regardless of block type. + struct BlockNode { + typedef uint32_t IndexType; + IndexType Index; + + bool operator==(const BlockNode &X) const { return Index == X.Index; } + bool operator!=(const BlockNode &X) const { return Index != X.Index; } + bool operator<=(const BlockNode &X) const { return Index <= X.Index; } + bool operator>=(const BlockNode &X) const { return Index >= X.Index; } + bool operator<(const BlockNode &X) const { return Index < X.Index; } + bool operator>(const BlockNode &X) const { return Index > X.Index; } + + BlockNode() : Index(UINT32_MAX) {} + BlockNode(IndexType Index) : Index(Index) {} + + bool isValid() const { return Index <= getMaxIndex(); } + static size_t getMaxIndex() { return UINT32_MAX - 1; } + }; + + /// \brief Stats about a block itself. + struct FrequencyData { + Scaled64 Scaled; + uint64_t Integer; + }; + + /// \brief Data about a loop. + /// + /// Contains the data necessary to represent represent a loop as a + /// pseudo-node once it's packaged. + struct LoopData { + typedef SmallVector<std::pair<BlockNode, BlockMass>, 4> ExitMap; + typedef SmallVector<BlockNode, 4> NodeList; + LoopData *Parent; ///< The parent loop. + bool IsPackaged; ///< Whether this has been packaged. + uint32_t NumHeaders; ///< Number of headers. + ExitMap Exits; ///< Successor edges (and weights). + NodeList Nodes; ///< Header and the members of the loop. + BlockMass BackedgeMass; ///< Mass returned to loop header. + BlockMass Mass; + Scaled64 Scale; + + LoopData(LoopData *Parent, const BlockNode &Header) + : Parent(Parent), IsPackaged(false), NumHeaders(1), Nodes(1, Header) {} + template <class It1, class It2> + LoopData(LoopData *Parent, It1 FirstHeader, It1 LastHeader, It2 FirstOther, + It2 LastOther) + : Parent(Parent), IsPackaged(false), Nodes(FirstHeader, LastHeader) { + NumHeaders = Nodes.size(); + Nodes.insert(Nodes.end(), FirstOther, LastOther); + } + bool isHeader(const BlockNode &Node) const { + if (isIrreducible()) + return std::binary_search(Nodes.begin(), Nodes.begin() + NumHeaders, + Node); + return Node == Nodes[0]; + } + BlockNode getHeader() const { return Nodes[0]; } + bool isIrreducible() const { return NumHeaders > 1; } + + NodeList::const_iterator members_begin() const { + return Nodes.begin() + NumHeaders; + } + NodeList::const_iterator members_end() const { return Nodes.end(); } + iterator_range<NodeList::const_iterator> members() const { + return make_range(members_begin(), members_end()); + } + }; + + /// \brief Index of loop information. + struct WorkingData { + BlockNode Node; ///< This node. + LoopData *Loop; ///< The loop this block is inside. + BlockMass Mass; ///< Mass distribution from the entry block. + + WorkingData(const BlockNode &Node) : Node(Node), Loop(nullptr) {} + + bool isLoopHeader() const { return Loop && Loop->isHeader(Node); } + bool isDoubleLoopHeader() const { + return isLoopHeader() && Loop->Parent && Loop->Parent->isIrreducible() && + Loop->Parent->isHeader(Node); + } + + LoopData *getContainingLoop() const { + if (!isLoopHeader()) + return Loop; + if (!isDoubleLoopHeader()) + return Loop->Parent; + return Loop->Parent->Parent; + } + + /// \brief Resolve a node to its representative. + /// + /// Get the node currently representing Node, which could be a containing + /// 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 + /// O(1) in this context. + /// + /// In general, the complexity is O(L), where L is the number of loop + /// headers Node has been packaged into. Since this method is called in + /// the context of distributing mass, L will be the number of loop headers + /// an early exit edge jumps out of. + BlockNode getResolvedNode() const { + auto L = getPackagedLoop(); + return L ? L->getHeader() : Node; + } + LoopData *getPackagedLoop() const { + if (!Loop || !Loop->IsPackaged) + return nullptr; + auto L = Loop; + while (L->Parent && L->Parent->IsPackaged) + L = L->Parent; + return L; + } + + /// \brief Get the appropriate mass for a node. + /// + /// Get appropriate mass for Node. If Node is a loop-header (whose loop + /// has been packaged), returns the mass of its pseudo-node. If it's a + /// node inside a packaged loop, it returns the loop's mass. + BlockMass &getMass() { + if (!isAPackage()) + return Mass; + if (!isADoublePackage()) + return Loop->Mass; + return Loop->Parent->Mass; + } + + /// \brief Has ContainingLoop been packaged up? + bool isPackaged() const { return getResolvedNode() != Node; } + /// \brief Has Loop been packaged up? + bool isAPackage() const { return isLoopHeader() && Loop->IsPackaged; } + /// \brief Has Loop been packaged up twice? + bool isADoublePackage() const { + return isDoubleLoopHeader() && Loop->Parent->IsPackaged; + } + }; + + /// \brief Unscaled probability weight. + /// + /// Probability weight for an edge in the graph (including the + /// successor/target node). + /// + /// All edges in the original function are 32-bit. However, exit edges from + /// loop packages are taken from 64-bit exit masses, so we need 64-bits of + /// space in general. + /// + /// In addition to the raw weight amount, Weight stores the type of the edge + /// in the current context (i.e., the context of the loop being processed). + /// Is this a local edge within the loop, an exit from the loop, or a + /// backedge to the loop header? + struct Weight { + enum DistType { Local, Exit, Backedge }; + DistType Type; + BlockNode TargetNode; + uint64_t Amount; + Weight() : Type(Local), Amount(0) {} + Weight(DistType Type, BlockNode TargetNode, uint64_t Amount) + : Type(Type), TargetNode(TargetNode), Amount(Amount) {} + }; + + /// \brief Distribution of unscaled probability weight. + /// + /// Distribution of unscaled probability weight to a set of successors. + /// + /// This class collates the successor edge weights for later processing. + /// + /// \a DidOverflow indicates whether \a Total did overflow while adding to + /// the distribution. It should never overflow twice. + struct Distribution { + typedef SmallVector<Weight, 4> WeightList; + WeightList Weights; ///< Individual successor weights. + uint64_t Total; ///< Sum of all weights. + bool DidOverflow; ///< Whether \a Total did overflow. + + Distribution() : Total(0), DidOverflow(false) {} + void addLocal(const BlockNode &Node, uint64_t Amount) { + add(Node, Amount, Weight::Local); + } + void addExit(const BlockNode &Node, uint64_t Amount) { + add(Node, Amount, Weight::Exit); + } + void addBackedge(const BlockNode &Node, uint64_t Amount) { + add(Node, Amount, Weight::Backedge); + } + + /// \brief Normalize the distribution. + /// + /// Combines multiple edges to the same \a Weight::TargetNode and scales + /// down so that \a Total fits into 32-bits. + /// + /// This is linear in the size of \a Weights. For the vast majority of + /// cases, adjacent edge weights are combined by sorting WeightList and + /// combining adjacent weights. However, for very large edge lists an + /// auxiliary hash table is used. + void normalize(); + + private: + void add(const BlockNode &Node, uint64_t Amount, Weight::DistType Type); + }; + + /// \brief Data about each block. This is used downstream. + std::vector<FrequencyData> Freqs; + + /// \brief Loop data: see initializeLoops(). + std::vector<WorkingData> Working; + + /// \brief Indexed information about loops. + std::list<LoopData> Loops; + + /// \brief Add all edges out of a packaged loop to the distribution. + /// + /// Adds all edges from LocalLoopHead to Dist. Calls addToDist() to add each + /// successor edge. + /// + /// \return \c true unless there's an irreducible backedge. + bool addLoopSuccessorsToDist(const LoopData *OuterLoop, LoopData &Loop, + Distribution &Dist); + + /// \brief Add an edge to the distribution. + /// + /// Adds an edge to Succ to Dist. If \c LoopHead.isValid(), then whether the + /// edge is local/exit/backedge is in the context of LoopHead. Otherwise, + /// every edge should be a local edge (since all the loops are packaged up). + /// + /// \return \c true unless aborted due to an irreducible backedge. + bool addToDist(Distribution &Dist, const LoopData *OuterLoop, + const BlockNode &Pred, const BlockNode &Succ, uint64_t Weight); + + LoopData &getLoopPackage(const BlockNode &Head) { + assert(Head.Index < Working.size()); + assert(Working[Head.Index].isLoopHeader()); + return *Working[Head.Index].Loop; + } + + /// \brief Analyze irreducible SCCs. + /// + /// Separate irreducible SCCs from \c G, which is an explict graph of \c + /// OuterLoop (or the top-level function, if \c OuterLoop is \c nullptr). + /// Insert them into \a Loops before \c Insert. + /// + /// \return the \c LoopData nodes representing the irreducible SCCs. + iterator_range<std::list<LoopData>::iterator> + analyzeIrreducible(const bfi_detail::IrreducibleGraph &G, LoopData *OuterLoop, + std::list<LoopData>::iterator Insert); + + /// \brief Update a loop after packaging irreducible SCCs inside of it. + /// + /// Update \c OuterLoop. Before finding irreducible control flow, it was + /// partway through \a computeMassInLoop(), so \a LoopData::Exits and \a + /// LoopData::BackedgeMass need to be reset. Also, nodes that were packaged + /// up need to be removed from \a OuterLoop::Nodes. + void updateLoopWithIrreducible(LoopData &OuterLoop); + + /// \brief Distribute mass according to a distribution. + /// + /// Distributes the mass in Source according to Dist. If LoopHead.isValid(), + /// backedges and exits are stored in its entry in Loops. + /// + /// Mass is distributed in parallel from two copies of the source mass. + void distributeMass(const BlockNode &Source, LoopData *OuterLoop, + Distribution &Dist); + + /// \brief Compute the loop scale for a loop. + void computeLoopScale(LoopData &Loop); + + /// \brief Package up a loop. + void packageLoop(LoopData &Loop); + + /// \brief Unwrap loops. + void unwrapLoops(); + + /// \brief Finalize frequency metrics. + /// + /// Calculates final frequencies and cleans up no-longer-needed data + /// structures. + void finalizeMetrics(); + + /// \brief Clear all memory. + void clear(); + + virtual std::string getBlockName(const BlockNode &Node) const; + std::string getLoopName(const LoopData &Loop) const; + + virtual raw_ostream &print(raw_ostream &OS) const { return OS; } + void dump() const { print(dbgs()); } + + Scaled64 getFloatingBlockFreq(const BlockNode &Node) const; + + BlockFrequency getBlockFreq(const BlockNode &Node) const; + + raw_ostream &printBlockFreq(raw_ostream &OS, const BlockNode &Node) const; + raw_ostream &printBlockFreq(raw_ostream &OS, + const BlockFrequency &Freq) const; + + uint64_t getEntryFreq() const { + assert(!Freqs.empty()); + return Freqs[0].Integer; + } + /// \brief Virtual destructor. + /// + /// Need a virtual destructor to mask the compiler warning about + /// getBlockName(). + virtual ~BlockFrequencyInfoImplBase() {} +}; + +namespace bfi_detail { +template <class BlockT> struct TypeMap {}; +template <> struct TypeMap<BasicBlock> { + typedef BasicBlock BlockT; + typedef Function FunctionT; + typedef BranchProbabilityInfo BranchProbabilityInfoT; + typedef Loop LoopT; + typedef LoopInfo LoopInfoT; +}; +template <> struct TypeMap<MachineBasicBlock> { + typedef MachineBasicBlock BlockT; + typedef MachineFunction FunctionT; + typedef MachineBranchProbabilityInfo BranchProbabilityInfoT; + typedef MachineLoop LoopT; + typedef MachineLoopInfo LoopInfoT; +}; + +/// \brief Get the name of a MachineBasicBlock. +/// +/// Get the name of a MachineBasicBlock. It's templated so that including from +/// CodeGen is unnecessary (that would be a layering issue). +/// +/// This is used mainly for debug output. The name is similar to +/// MachineBasicBlock::getFullName(), but skips the name of the function. +template <class BlockT> std::string getBlockName(const BlockT *BB) { + assert(BB && "Unexpected nullptr"); + auto MachineName = "BB" + Twine(BB->getNumber()); + if (BB->getBasicBlock()) + return (MachineName + "[" + BB->getName() + "]").str(); + return MachineName.str(); +} +/// \brief Get the name of a BasicBlock. +template <> inline std::string getBlockName(const BasicBlock *BB) { + assert(BB && "Unexpected nullptr"); + return BB->getName().str(); +} + +/// \brief Graph of irreducible control flow. +/// +/// This graph is used for determining the SCCs in a loop (or top-level +/// function) that has irreducible control flow. +/// +/// During the block frequency algorithm, the local graphs are defined in a +/// light-weight way, deferring to the \a BasicBlock or \a MachineBasicBlock +/// graphs for most edges, but getting others from \a LoopData::ExitMap. The +/// latter only has successor information. +/// +/// \a IrreducibleGraph makes this graph explicit. It's in a form that can use +/// \a GraphTraits (so that \a analyzeIrreducible() can use \a scc_iterator), +/// and it explicitly lists predecessors and successors. The initialization +/// that relies on \c MachineBasicBlock is defined in the header. +struct IrreducibleGraph { + typedef BlockFrequencyInfoImplBase BFIBase; + + BFIBase &BFI; + + typedef BFIBase::BlockNode BlockNode; + struct IrrNode { + BlockNode Node; + unsigned NumIn; + std::deque<const IrrNode *> Edges; + IrrNode(const BlockNode &Node) : Node(Node), NumIn(0) {} + + typedef std::deque<const IrrNode *>::const_iterator iterator; + iterator pred_begin() const { return Edges.begin(); } + iterator succ_begin() const { return Edges.begin() + NumIn; } + iterator pred_end() const { return succ_begin(); } + iterator succ_end() const { return Edges.end(); } + }; + BlockNode Start; + const IrrNode *StartIrr; + std::vector<IrrNode> Nodes; + SmallDenseMap<uint32_t, IrrNode *, 4> Lookup; + + /// \brief Construct an explicit graph containing irreducible control flow. + /// + /// Construct an explicit graph of the control flow in \c OuterLoop (or the + /// top-level function, if \c OuterLoop is \c nullptr). Uses \c + /// addBlockEdges to add block successors that have not been packaged into + /// loops. + /// + /// \a BlockFrequencyInfoImpl::computeIrreducibleMass() is the only expected + /// user of this. + template <class BlockEdgesAdder> + IrreducibleGraph(BFIBase &BFI, const BFIBase::LoopData *OuterLoop, + BlockEdgesAdder addBlockEdges) + : BFI(BFI), StartIrr(nullptr) { + initialize(OuterLoop, addBlockEdges); + } + + template <class BlockEdgesAdder> + void initialize(const BFIBase::LoopData *OuterLoop, + BlockEdgesAdder addBlockEdges); + void addNodesInLoop(const BFIBase::LoopData &OuterLoop); + void addNodesInFunction(); + void addNode(const BlockNode &Node) { + Nodes.emplace_back(Node); + BFI.Working[Node.Index].getMass() = BlockMass::getEmpty(); + } + void indexNodes(); + template <class BlockEdgesAdder> + void addEdges(const BlockNode &Node, const BFIBase::LoopData *OuterLoop, + BlockEdgesAdder addBlockEdges); + void addEdge(IrrNode &Irr, const BlockNode &Succ, + const BFIBase::LoopData *OuterLoop); +}; +template <class BlockEdgesAdder> +void IrreducibleGraph::initialize(const BFIBase::LoopData *OuterLoop, + BlockEdgesAdder addBlockEdges) { + if (OuterLoop) { + addNodesInLoop(*OuterLoop); + for (auto N : OuterLoop->Nodes) + addEdges(N, OuterLoop, addBlockEdges); + } else { + addNodesInFunction(); + for (uint32_t Index = 0; Index < BFI.Working.size(); ++Index) + addEdges(Index, OuterLoop, addBlockEdges); + } + StartIrr = Lookup[Start.Index]; +} +template <class BlockEdgesAdder> +void IrreducibleGraph::addEdges(const BlockNode &Node, + const BFIBase::LoopData *OuterLoop, + BlockEdgesAdder addBlockEdges) { + auto L = Lookup.find(Node.Index); + if (L == Lookup.end()) + return; + IrrNode &Irr = *L->second; + const auto &Working = BFI.Working[Node.Index]; + + if (Working.isAPackage()) + for (const auto &I : Working.Loop->Exits) + addEdge(Irr, I.first, OuterLoop); + else + addBlockEdges(*this, Irr, OuterLoop); +} +} + +/// \brief Shared implementation for block frequency analysis. +/// +/// This is a shared implementation of BlockFrequencyInfo and +/// MachineBlockFrequencyInfo, and calculates the relative frequencies of +/// blocks. +/// +/// LoopInfo defines a loop as a "non-trivial" SCC dominated by a single block, +/// which is called the header. A given loop, L, can have sub-loops, which are +/// loops within the subgraph of L that exclude its header. (A "trivial" SCC +/// consists of a single block that does not have a self-edge.) +/// +/// In addition to loops, this algorithm has limited support for irreducible +/// SCCs, which are SCCs with multiple entry blocks. Irreducible SCCs are +/// discovered on they fly, and modelled as loops with multiple headers. +/// +/// The headers of irreducible sub-SCCs consist of its entry blocks and all +/// nodes that are targets of a backedge within it (excluding backedges within +/// true sub-loops). Block frequency calculations act as if a block is +/// inserted that intercepts all the edges to the headers. All backedges and +/// entries point to this block. Its successors are the headers, which split +/// the frequency evenly. +/// +/// This algorithm leverages BlockMass and ScaledNumber to maintain precision, +/// separates mass distribution from loop scaling, and dithers to eliminate +/// probability mass loss. +/// +/// The implementation is split between BlockFrequencyInfoImpl, which knows the +/// type of graph being modelled (BasicBlock vs. MachineBasicBlock), and +/// BlockFrequencyInfoImplBase, which doesn't. The base class uses \a +/// BlockNode, a wrapper around a uint32_t. BlockNode is numbered from 0 in +/// reverse-post order. This gives two advantages: it's easy to compare the +/// relative ordering of two nodes, and maps keyed on BlockT can be represented +/// by vectors. +/// +/// This algorithm is O(V+E), unless there is irreducible control flow, in +/// which case it's O(V*E) in the worst case. +/// +/// These are the main stages: +/// +/// 0. Reverse post-order traversal (\a initializeRPOT()). +/// +/// Run a single post-order traversal and save it (in reverse) in RPOT. +/// All other stages make use of this ordering. Save a lookup from BlockT +/// to BlockNode (the index into RPOT) in Nodes. +/// +/// 1. Loop initialization (\a initializeLoops()). +/// +/// Translate LoopInfo/MachineLoopInfo into a form suitable for the rest of +/// the algorithm. In particular, store the immediate members of each loop +/// in reverse post-order. +/// +/// 2. Calculate mass and scale in loops (\a computeMassInLoops()). +/// +/// For each loop (bottom-up), distribute mass through the DAG resulting +/// from ignoring backedges and treating sub-loops as a single pseudo-node. +/// Track the backedge mass distributed to the loop header, and use it to +/// calculate the loop scale (number of loop iterations). Immediate +/// members that represent sub-loops will already have been visited and +/// packaged into a pseudo-node. +/// +/// Distributing mass in a loop is a reverse-post-order traversal through +/// the loop. Start by assigning full mass to the Loop header. For each +/// node in the loop: +/// +/// - Fetch and categorize the weight distribution for its successors. +/// If this is a packaged-subloop, the weight distribution is stored +/// in \a LoopData::Exits. Otherwise, fetch it from +/// BranchProbabilityInfo. +/// +/// - Each successor is categorized as \a Weight::Local, a local edge +/// within the current loop, \a Weight::Backedge, a backedge to the +/// loop header, or \a Weight::Exit, any successor outside the loop. +/// The weight, the successor, and its category are stored in \a +/// Distribution. There can be multiple edges to each successor. +/// +/// - If there's a backedge to a non-header, there's an irreducible SCC. +/// The usual flow is temporarily aborted. \a +/// computeIrreducibleMass() finds the irreducible SCCs within the +/// loop, packages them up, and restarts the flow. +/// +/// - Normalize the distribution: scale weights down so that their sum +/// is 32-bits, and coalesce multiple edges to the same node. +/// +/// - Distribute the mass accordingly, dithering to minimize mass loss, +/// as described in \a distributeMass(). +/// +/// Finally, calculate the loop scale from the accumulated backedge mass. +/// +/// 3. Distribute mass in the function (\a computeMassInFunction()). +/// +/// Finally, distribute mass through the DAG resulting from packaging all +/// loops in the function. This uses the same algorithm as distributing +/// mass in a loop, except that there are no exit or backedge edges. +/// +/// 4. Unpackage loops (\a unwrapLoops()). +/// +/// Initialize each block's frequency to a floating point representation of +/// its mass. +/// +/// Visit loops top-down, scaling the frequencies of its immediate members +/// by the loop's pseudo-node's frequency. +/// +/// 5. Convert frequencies to a 64-bit range (\a finalizeMetrics()). +/// +/// Using the min and max frequencies as a guide, translate floating point +/// frequencies to an appropriate range in uint64_t. +/// +/// It has some known flaws. +/// +/// - Loop scale is limited to 4096 per loop (2^12) to avoid exhausting +/// BlockFrequency's 64-bit integer precision. +/// +/// - The model of irreducible control flow is a rough approximation. +/// +/// Modelling irreducible control flow exactly involves setting up and +/// solving a group of infinite geometric series. Such precision is +/// unlikely to be worthwhile, since most of our algorithms give up on +/// irreducible control flow anyway. +/// +/// Nevertheless, we might find that we need to get closer. Here's a sort +/// of TODO list for the model with diminishing returns, to be completed as +/// necessary. +/// +/// - The headers for the \a LoopData representing an irreducible SCC +/// include non-entry blocks. When these extra blocks exist, they +/// indicate a self-contained irreducible sub-SCC. We could treat them +/// as sub-loops, rather than arbitrarily shoving the problematic +/// blocks into the headers of the main irreducible SCC. +/// +/// - Backedge frequencies are assumed to be evenly split between the +/// headers of a given irreducible SCC. Instead, we could track the +/// backedge mass separately for each header, and adjust their relative +/// frequencies. +/// +/// - Entry frequencies are assumed to be evenly split between the +/// headers of a given irreducible SCC, which is the only option if we +/// need to compute mass in the SCC before its parent loop. Instead, +/// we could partially compute mass in the parent loop, and stop when +/// we get to the SCC. Here, we have the correct ratio of entry +/// masses, which we can use to adjust their relative frequencies. +/// Compute mass in the SCC, and then continue propagation in the +/// parent. +/// +/// - We can propagate mass iteratively through the SCC, for some fixed +/// number of iterations. Each iteration starts by assigning the entry +/// blocks their backedge mass from the prior iteration. The final +/// mass for each block (and each exit, and the total backedge mass +/// used for computing loop scale) is the sum of all iterations. +/// (Running this until fixed point would "solve" the geometric +/// series by simulation.) +template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { + typedef typename bfi_detail::TypeMap<BT>::BlockT BlockT; + typedef typename bfi_detail::TypeMap<BT>::FunctionT FunctionT; + typedef typename bfi_detail::TypeMap<BT>::BranchProbabilityInfoT + BranchProbabilityInfoT; + typedef typename bfi_detail::TypeMap<BT>::LoopT LoopT; + typedef typename bfi_detail::TypeMap<BT>::LoopInfoT LoopInfoT; + + // This is part of a workaround for a GCC 4.7 crash on lambdas. + friend struct bfi_detail::BlockEdgesAdder<BT>; + + typedef GraphTraits<const BlockT *> Successor; + typedef GraphTraits<Inverse<const BlockT *>> Predecessor; + + const BranchProbabilityInfoT *BPI; + const LoopInfoT *LI; + const FunctionT *F; + + // All blocks in reverse postorder. + std::vector<const BlockT *> RPOT; + DenseMap<const BlockT *, BlockNode> Nodes; + + typedef typename std::vector<const BlockT *>::const_iterator rpot_iterator; + + rpot_iterator rpot_begin() const { return RPOT.begin(); } + rpot_iterator rpot_end() const { return RPOT.end(); } + + size_t getIndex(const rpot_iterator &I) const { return I - rpot_begin(); } + + BlockNode getNode(const rpot_iterator &I) const { + return BlockNode(getIndex(I)); + } + BlockNode getNode(const BlockT *BB) const { return Nodes.lookup(BB); } + + const BlockT *getBlock(const BlockNode &Node) const { + assert(Node.Index < RPOT.size()); + return RPOT[Node.Index]; + } + + /// \brief Run (and save) a post-order traversal. + /// + /// Saves a reverse post-order traversal of all the nodes in \a F. + void initializeRPOT(); + + /// \brief Initialize loop data. + /// + /// Build up \a Loops using \a LoopInfo. \a LoopInfo gives us a mapping from + /// each block to the deepest loop it's in, but we need the inverse. For each + /// loop, we store in reverse post-order its "immediate" members, defined as + /// the header, the headers of immediate sub-loops, and all other blocks in + /// the loop that are not in sub-loops. + void initializeLoops(); + + /// \brief Propagate to a block's successors. + /// + /// In the context of distributing mass through \c OuterLoop, divide the mass + /// currently assigned to \c Node between its successors. + /// + /// \return \c true unless there's an irreducible backedge. + bool propagateMassToSuccessors(LoopData *OuterLoop, const BlockNode &Node); + + /// \brief Compute mass in a particular loop. + /// + /// Assign mass to \c Loop's header, and then for each block in \c Loop in + /// reverse post-order, distribute mass to its successors. Only visits nodes + /// that have not been packaged into sub-loops. + /// + /// \pre \a computeMassInLoop() has been called for each subloop of \c Loop. + /// \return \c true unless there's an irreducible backedge. + bool computeMassInLoop(LoopData &Loop); + + /// \brief Try to compute mass in the top-level function. + /// + /// Assign mass to the entry block, and then for each block in reverse + /// post-order, distribute mass to its successors. Skips nodes that have + /// been packaged into loops. + /// + /// \pre \a computeMassInLoops() has been called. + /// \return \c true unless there's an irreducible backedge. + bool tryToComputeMassInFunction(); + + /// \brief Compute mass in (and package up) irreducible SCCs. + /// + /// Find the irreducible SCCs in \c OuterLoop, add them to \a Loops (in front + /// of \c Insert), and call \a computeMassInLoop() on each of them. + /// + /// If \c OuterLoop is \c nullptr, it refers to the top-level function. + /// + /// \pre \a computeMassInLoop() has been called for each subloop of \c + /// OuterLoop. + /// \pre \c Insert points at the the last loop successfully processed by \a + /// computeMassInLoop(). + /// \pre \c OuterLoop has irreducible SCCs. + void computeIrreducibleMass(LoopData *OuterLoop, + std::list<LoopData>::iterator Insert); + + /// \brief Compute mass in all loops. + /// + /// For each loop bottom-up, call \a computeMassInLoop(). + /// + /// \a computeMassInLoop() aborts (and returns \c false) on loops that + /// contain a irreducible sub-SCCs. Use \a computeIrreducibleMass() and then + /// re-enter \a computeMassInLoop(). + /// + /// \post \a computeMassInLoop() has returned \c true for every loop. + void computeMassInLoops(); + + /// \brief Compute mass in the top-level function. + /// + /// Uses \a tryToComputeMassInFunction() and \a computeIrreducibleMass() to + /// compute mass in the top-level function. + /// + /// \post \a tryToComputeMassInFunction() has returned \c true. + void computeMassInFunction(); + + std::string getBlockName(const BlockNode &Node) const override { + return bfi_detail::getBlockName(getBlock(Node)); + } + +public: + const FunctionT *getFunction() const { return F; } + + void doFunction(const FunctionT *F, const BranchProbabilityInfoT *BPI, + const LoopInfoT *LI); + BlockFrequencyInfoImpl() : BPI(nullptr), LI(nullptr), F(nullptr) {} + + using BlockFrequencyInfoImplBase::getEntryFreq; + BlockFrequency getBlockFreq(const BlockT *BB) const { + return BlockFrequencyInfoImplBase::getBlockFreq(getNode(BB)); + } + Scaled64 getFloatingBlockFreq(const BlockT *BB) const { + return BlockFrequencyInfoImplBase::getFloatingBlockFreq(getNode(BB)); + } + + /// \brief Print the frequencies for the current function. + /// + /// Prints the frequencies for the blocks in the current function. + /// + /// Blocks are printed in the natural iteration order of the function, rather + /// than reverse post-order. This provides two advantages: writing -analyze + /// tests is easier (since blocks come out in source order), and even + /// unreachable blocks are printed. + /// + /// \a BlockFrequencyInfoImplBase::print() only knows reverse post-order, so + /// we need to override it here. + raw_ostream &print(raw_ostream &OS) const override; + using BlockFrequencyInfoImplBase::dump; + + using BlockFrequencyInfoImplBase::printBlockFreq; + raw_ostream &printBlockFreq(raw_ostream &OS, const BlockT *BB) const { + return BlockFrequencyInfoImplBase::printBlockFreq(OS, getNode(BB)); + } +}; + +template <class BT> +void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F, + const BranchProbabilityInfoT *BPI, + const LoopInfoT *LI) { + // Save the parameters. + this->BPI = BPI; + this->LI = LI; + this->F = F; + + // Clean up left-over data structures. + BlockFrequencyInfoImplBase::clear(); + RPOT.clear(); + Nodes.clear(); + + // Initialize. + DEBUG(dbgs() << "\nblock-frequency: " << F->getName() << "\n=================" + << std::string(F->getName().size(), '=') << "\n"); + initializeRPOT(); + initializeLoops(); + + // Visit loops in post-order to find thelocal mass distribution, and then do + // the full function. + computeMassInLoops(); + computeMassInFunction(); + unwrapLoops(); + finalizeMetrics(); +} + +template <class BT> void BlockFrequencyInfoImpl<BT>::initializeRPOT() { + const BlockT *Entry = F->begin(); + RPOT.reserve(F->size()); + std::copy(po_begin(Entry), po_end(Entry), std::back_inserter(RPOT)); + std::reverse(RPOT.begin(), RPOT.end()); + + assert(RPOT.size() - 1 <= BlockNode::getMaxIndex() && + "More nodes in function than Block Frequency Info supports"); + + DEBUG(dbgs() << "reverse-post-order-traversal\n"); + for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) { + BlockNode Node = getNode(I); + DEBUG(dbgs() << " - " << getIndex(I) << ": " << getBlockName(Node) << "\n"); + Nodes[*I] = Node; + } + + Working.reserve(RPOT.size()); + for (size_t Index = 0; Index < RPOT.size(); ++Index) + Working.emplace_back(Index); + Freqs.resize(RPOT.size()); +} + +template <class BT> void BlockFrequencyInfoImpl<BT>::initializeLoops() { + DEBUG(dbgs() << "loop-detection\n"); + if (LI->empty()) + return; + + // Visit loops top down and assign them an index. + std::deque<std::pair<const LoopT *, LoopData *>> Q; + for (const LoopT *L : *LI) + Q.emplace_back(L, nullptr); + while (!Q.empty()) { + const LoopT *Loop = Q.front().first; + LoopData *Parent = Q.front().second; + Q.pop_front(); + + BlockNode Header = getNode(Loop->getHeader()); + assert(Header.isValid()); + + Loops.emplace_back(Parent, Header); + Working[Header.Index].Loop = &Loops.back(); + DEBUG(dbgs() << " - loop = " << getBlockName(Header) << "\n"); + + for (const LoopT *L : *Loop) + Q.emplace_back(L, &Loops.back()); + } + + // Visit nodes in reverse post-order and add them to their deepest containing + // loop. + for (size_t Index = 0; Index < RPOT.size(); ++Index) { + // Loop headers have already been mostly mapped. + if (Working[Index].isLoopHeader()) { + LoopData *ContainingLoop = Working[Index].getContainingLoop(); + if (ContainingLoop) + ContainingLoop->Nodes.push_back(Index); + continue; + } + + const LoopT *Loop = LI->getLoopFor(RPOT[Index]); + if (!Loop) + continue; + + // Add this node to its containing loop's member list. + BlockNode Header = getNode(Loop->getHeader()); + assert(Header.isValid()); + const auto &HeaderData = Working[Header.Index]; + assert(HeaderData.isLoopHeader()); + + Working[Index].Loop = HeaderData.Loop; + HeaderData.Loop->Nodes.push_back(Index); + DEBUG(dbgs() << " - loop = " << getBlockName(Header) + << ": member = " << getBlockName(Index) << "\n"); + } +} + +template <class BT> void BlockFrequencyInfoImpl<BT>::computeMassInLoops() { + // Visit loops with the deepest first, and the top-level loops last. + for (auto L = Loops.rbegin(), E = Loops.rend(); L != E; ++L) { + if (computeMassInLoop(*L)) + continue; + auto Next = std::next(L); + computeIrreducibleMass(&*L, L.base()); + L = std::prev(Next); + if (computeMassInLoop(*L)) + continue; + llvm_unreachable("unhandled irreducible control flow"); + } +} + +template <class BT> +bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) { + // Compute mass in loop. + DEBUG(dbgs() << "compute-mass-in-loop: " << getLoopName(Loop) << "\n"); + + if (Loop.isIrreducible()) { + BlockMass Remaining = BlockMass::getFull(); + for (uint32_t H = 0; H < Loop.NumHeaders; ++H) { + auto &Mass = Working[Loop.Nodes[H].Index].getMass(); + Mass = Remaining * BranchProbability(1, Loop.NumHeaders - H); + Remaining -= Mass; + } + for (const BlockNode &M : Loop.Nodes) + if (!propagateMassToSuccessors(&Loop, M)) + llvm_unreachable("unhandled irreducible control flow"); + } else { + Working[Loop.getHeader().Index].getMass() = BlockMass::getFull(); + if (!propagateMassToSuccessors(&Loop, Loop.getHeader())) + llvm_unreachable("irreducible control flow to loop header!?"); + for (const BlockNode &M : Loop.members()) + if (!propagateMassToSuccessors(&Loop, M)) + // Irreducible backedge. + return false; + } + + computeLoopScale(Loop); + packageLoop(Loop); + return true; +} + +template <class BT> +bool BlockFrequencyInfoImpl<BT>::tryToComputeMassInFunction() { + // Compute mass in function. + DEBUG(dbgs() << "compute-mass-in-function\n"); + assert(!Working.empty() && "no blocks in function"); + assert(!Working[0].isLoopHeader() && "entry block is a loop header"); + + Working[0].getMass() = BlockMass::getFull(); + for (rpot_iterator I = rpot_begin(), IE = rpot_end(); I != IE; ++I) { + // Check for nodes that have been packaged. + BlockNode Node = getNode(I); + if (Working[Node.Index].isPackaged()) + continue; + + if (!propagateMassToSuccessors(nullptr, Node)) + return false; + } + return true; +} + +template <class BT> void BlockFrequencyInfoImpl<BT>::computeMassInFunction() { + if (tryToComputeMassInFunction()) + return; + computeIrreducibleMass(nullptr, Loops.begin()); + if (tryToComputeMassInFunction()) + return; + llvm_unreachable("unhandled irreducible control flow"); +} + +/// \note This should be a lambda, but that crashes GCC 4.7. +namespace bfi_detail { +template <class BT> struct BlockEdgesAdder { + typedef BT BlockT; + typedef BlockFrequencyInfoImplBase::LoopData LoopData; + typedef GraphTraits<const BlockT *> Successor; + + const BlockFrequencyInfoImpl<BT> &BFI; + explicit BlockEdgesAdder(const BlockFrequencyInfoImpl<BT> &BFI) + : BFI(BFI) {} + void operator()(IrreducibleGraph &G, IrreducibleGraph::IrrNode &Irr, + const LoopData *OuterLoop) { + const BlockT *BB = BFI.RPOT[Irr.Node.Index]; + for (auto I = Successor::child_begin(BB), E = Successor::child_end(BB); + I != E; ++I) + G.addEdge(Irr, BFI.getNode(*I), OuterLoop); + } +}; +} +template <class BT> +void BlockFrequencyInfoImpl<BT>::computeIrreducibleMass( + LoopData *OuterLoop, std::list<LoopData>::iterator Insert) { + DEBUG(dbgs() << "analyze-irreducible-in-"; + if (OuterLoop) dbgs() << "loop: " << getLoopName(*OuterLoop) << "\n"; + else dbgs() << "function\n"); + + using namespace bfi_detail; + // Ideally, addBlockEdges() would be declared here as a lambda, but that + // crashes GCC 4.7. + BlockEdgesAdder<BT> addBlockEdges(*this); + IrreducibleGraph G(*this, OuterLoop, addBlockEdges); + + for (auto &L : analyzeIrreducible(G, OuterLoop, Insert)) + computeMassInLoop(L); + + if (!OuterLoop) + return; + updateLoopWithIrreducible(*OuterLoop); +} + +template <class BT> +bool +BlockFrequencyInfoImpl<BT>::propagateMassToSuccessors(LoopData *OuterLoop, + const BlockNode &Node) { + DEBUG(dbgs() << " - node: " << getBlockName(Node) << "\n"); + // Calculate probability for successors. + Distribution Dist; + if (auto *Loop = Working[Node.Index].getPackagedLoop()) { + assert(Loop != OuterLoop && "Cannot propagate mass in a packaged loop"); + if (!addLoopSuccessorsToDist(OuterLoop, *Loop, Dist)) + // Irreducible backedge. + return false; + } else { + const BlockT *BB = getBlock(Node); + for (auto SI = Successor::child_begin(BB), SE = Successor::child_end(BB); + SI != SE; ++SI) + // Do not dereference SI, or getEdgeWeight() is linear in the number of + // successors. + if (!addToDist(Dist, OuterLoop, Node, getNode(*SI), + BPI->getEdgeWeight(BB, SI))) + // Irreducible backedge. + return false; + } + + // Distribute mass to successors, saving exit and backedge data in the + // loop header. + distributeMass(Node, OuterLoop, Dist); + return true; +} + +template <class BT> +raw_ostream &BlockFrequencyInfoImpl<BT>::print(raw_ostream &OS) const { + if (!F) + return OS; + OS << "block-frequency-info: " << F->getName() << "\n"; + for (const BlockT &BB : *F) + OS << " - " << bfi_detail::getBlockName(&BB) + << ": float = " << getFloatingBlockFreq(&BB) + << ", int = " << getBlockFreq(&BB).getFrequency() << "\n"; + + // Add an extra newline for readability. + OS << "\n"; + return OS; +} + +} // end namespace llvm + +#undef DEBUG_TYPE + +#endif diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 4ff7121728ec..4414c84f6b7a 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -16,6 +16,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/IR/CFG.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/BranchProbability.h" @@ -44,9 +45,9 @@ public: initializeBranchProbabilityInfoPass(*PassRegistry::getPassRegistry()); } - void getAnalysisUsage(AnalysisUsage &AU) const; - bool runOnFunction(Function &F); - void print(raw_ostream &OS, const Module *M = 0) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; + bool runOnFunction(Function &F) override; + void print(raw_ostream &OS, const Module *M = nullptr) const override; /// \brief Get an edge's probability, relative to other out-edges of the Src. /// @@ -98,6 +99,9 @@ public: /// It is guaranteed to fall between 1 and UINT32_MAX. uint32_t getEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst) const; + uint32_t getEdgeWeight(const BasicBlock *Src, + succ_const_iterator Dst) const; + /// \brief Set the raw edge weight for a given edge. /// /// This allows a pass to explicitly set the edge weight for an edge. It can diff --git a/include/llvm/Analysis/CFG.h b/include/llvm/Analysis/CFG.h index e5683c8e5953..7f92eda8cb20 100644 --- a/include/llvm/Analysis/CFG.h +++ b/include/llvm/Analysis/CFG.h @@ -16,7 +16,7 @@ #define LLVM_ANALYSIS_CFG_H #include "llvm/IR/BasicBlock.h" -#include "llvm/Support/CFG.h" +#include "llvm/IR/CFG.h" namespace llvm { @@ -65,8 +65,8 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, /// on branchy code but not loops, and LI is most useful on code with loops but /// does not help on branchy code outside loops. bool isPotentiallyReachable(const Instruction *From, const Instruction *To, - const DominatorTree *DT = 0, - const LoopInfo *LI = 0); + const DominatorTree *DT = nullptr, + const LoopInfo *LI = nullptr); /// \brief Determine whether block 'To' is reachable from 'From', returning /// true if uncertain. @@ -75,8 +75,8 @@ bool isPotentiallyReachable(const Instruction *From, const Instruction *To, /// Returns false only if we can prove that once 'From' has been reached then /// 'To' can not be executed. Conservatively returns true. bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To, - const DominatorTree *DT = 0, - const LoopInfo *LI = 0); + const DominatorTree *DT = nullptr, + const LoopInfo *LI = nullptr); } // End llvm namespace diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h index 39e90eb96a0f..e6d2ed1a6864 100644 --- a/include/llvm/Analysis/CFGPrinter.h +++ b/include/llvm/Analysis/CFGPrinter.h @@ -15,11 +15,10 @@ #ifndef LLVM_ANALYSIS_CFGPRINTER_H #define LLVM_ANALYSIS_CFGPRINTER_H -#include "llvm/Assembly/Writer.h" +#include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" -#include "llvm/Support/CFG.h" #include "llvm/Support/GraphWriter.h" namespace llvm { @@ -40,7 +39,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { std::string Str; raw_string_ostream OS(Str); - WriteAsOperand(OS, Node, false); + Node->printAsOperand(OS, false); return OS.str(); } @@ -51,7 +50,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits { raw_string_ostream OS(Str); if (Node->getName().empty()) { - WriteAsOperand(OS, Node, false); + Node->printAsOperand(OS, false); OS << ":"; } diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h new file mode 100644 index 000000000000..09101ae6d0d1 --- /dev/null +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -0,0 +1,591 @@ +//===- CGSCCPassManager.h - Call graph pass management ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header provides classes for managing passes over SCCs of the call +/// graph. These passes form an important component of LLVM's interprocedural +/// optimizations. Because they operate on the SCCs of the call graph, and they +/// wtraverse the graph in post order, they can effectively do pair-wise +/// interprocedural optimizations for all call edges in the program. At each +/// call site edge, the callee has already been optimized as much as is +/// possible. This in turn allows very accurate analysis of it for IPO. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H +#define LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H + +#include "llvm/IR/PassManager.h" +#include "llvm/Analysis/LazyCallGraph.h" + +namespace llvm { + +class CGSCCAnalysisManager; + +class CGSCCPassManager { +public: + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + CGSCCPassManager() {} + CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {} + CGSCCPassManager &operator=(CGSCCPassManager &&RHS) { + Passes = std::move(RHS.Passes); + return *this; + } + + /// \brief Run all of the CGSCC passes in this pass manager over a SCC. + PreservedAnalyses run(LazyCallGraph::SCC *C, + CGSCCAnalysisManager *AM = nullptr); + + template <typename CGSCCPassT> void addPass(CGSCCPassT Pass) { + Passes.emplace_back(new CGSCCPassModel<CGSCCPassT>(std::move(Pass))); + } + + static StringRef name() { return "CGSCCPassManager"; } + +private: + // Pull in the concept type and model template specialized for SCCs. + typedef detail::PassConcept<LazyCallGraph::SCC *, CGSCCAnalysisManager> + CGSCCPassConcept; + template <typename PassT> + struct CGSCCPassModel + : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT> { + CGSCCPassModel(PassT Pass) + : detail::PassModel<LazyCallGraph::SCC *, CGSCCAnalysisManager, PassT>( + std::move(Pass)) {} + }; + + CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; + CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; + + std::vector<std::unique_ptr<CGSCCPassConcept>> Passes; +}; + +/// \brief A function analysis manager to coordinate and cache analyses run over +/// a module. +class CGSCCAnalysisManager : public detail::AnalysisManagerBase< + CGSCCAnalysisManager, LazyCallGraph::SCC *> { + friend class detail::AnalysisManagerBase<CGSCCAnalysisManager, + LazyCallGraph::SCC *>; + typedef detail::AnalysisManagerBase<CGSCCAnalysisManager, + LazyCallGraph::SCC *> BaseT; + typedef BaseT::ResultConceptT ResultConceptT; + typedef BaseT::PassConceptT PassConceptT; + +public: + // Most public APIs are inherited from the CRTP base class. + + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + CGSCCAnalysisManager() {} + CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg) + : BaseT(std::move(static_cast<BaseT &>(Arg))), + CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {} + CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) { + BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); + CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults); + return *this; + } + + /// \brief Returns true if the analysis manager has an empty results cache. + bool empty() const; + + /// \brief Clear the function analysis result cache. + /// + /// This routine allows cleaning up when the set of functions itself has + /// potentially changed, and thus we can't even look up a a result and + /// invalidate it directly. Notably, this does *not* call invalidate + /// functions as there is nothing to be done for them. + void clear(); + +private: + CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; + CGSCCAnalysisManager & + operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; + + /// \brief Get a function pass result, running the pass if necessary. + ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C); + + /// \brief Get a cached function pass result or return null. + ResultConceptT *getCachedResultImpl(void *PassID, + LazyCallGraph::SCC *C) const; + + /// \brief Invalidate a function pass result. + void invalidateImpl(void *PassID, LazyCallGraph::SCC *C); + + /// \brief Invalidate the results for a function.. + void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); + + /// \brief 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 A module analysis which acts as a proxy for a CGSCC analysis +/// manager. +/// +/// This primarily proxies invalidation information from the module analysis +/// manager and module pass manager to a CGSCC analysis manager. You should +/// never use a CGSCC analysis manager from within (transitively) a module +/// pass manager unless your parent module pass has received a proxy result +/// object for it. +class CGSCCAnalysisManagerModuleProxy { +public: + class Result { + public: + explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} + // We have to explicitly define all the special member functions because + // MSVC refuses to generate them. + Result(const Result &Arg) : CGAM(Arg.CGAM) {} + Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {} + Result &operator=(Result RHS) { + std::swap(CGAM, RHS.CGAM); + return *this; + } + ~Result(); + + /// \brief Accessor for the \c CGSCCAnalysisManager. + CGSCCAnalysisManager &getManager() { return *CGAM; } + + /// \brief Handler for invalidation of the module. + /// + /// If this analysis itself is preserved, then we assume that the call + /// graph of the module hasn't changed and thus we don't need to invalidate + /// *all* cached data associated with a \c SCC* in the \c + /// CGSCCAnalysisManager. + /// + /// 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); + + private: + CGSCCAnalysisManager *CGAM; + }; + + static void *ID() { return (void *)&PassID; } + + 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) + : CGAM(Arg.CGAM) {} + CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg) + : CGAM(std::move(Arg.CGAM)) {} + CGSCCAnalysisManagerModuleProxy & + operator=(CGSCCAnalysisManagerModuleProxy RHS) { + std::swap(CGAM, RHS.CGAM); + return *this; + } + + /// \brief Run the analysis pass and create our proxy result object. + /// + /// This doesn't do any interesting work, it is primarily used to insert our + /// proxy result object into the module analysis cache so that we can proxy + /// invalidation to the CGSCC analysis manager. + /// + /// 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); + +private: + static char PassID; + + CGSCCAnalysisManager *CGAM; +}; + +/// \brief A CGSCC analysis which acts as a proxy for a module analysis +/// manager. +/// +/// This primarily provides an accessor to a parent module analysis manager to +/// CGSCC passes. Only the const interface of the module analysis manager is +/// provided to indicate that once inside of a CGSCC analysis pass you +/// cannot request a module analysis to actually run. Instead, the user must +/// rely on the \c getCachedResult API. +/// +/// This proxy *doesn't* manage the invalidation in any way. That is handled by +/// the recursive return path of each layer of the pass manager and the +/// returned PreservedAnalysis set. +class ModuleAnalysisManagerCGSCCProxy { +public: + /// \brief Result proxy object for \c ModuleAnalysisManagerCGSCCProxy. + class Result { + public: + explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} + // We have to explicitly define all the special member functions because + // MSVC refuses to generate them. + Result(const Result &Arg) : MAM(Arg.MAM) {} + Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {} + Result &operator=(Result RHS) { + std::swap(MAM, RHS.MAM); + return *this; + } + + const ModuleAnalysisManager &getManager() const { return *MAM; } + + /// \brief Handle invalidation by ignoring it, this pass is immutable. + bool invalidate(LazyCallGraph::SCC *) { return false; } + + private: + const ModuleAnalysisManager *MAM; + }; + + static void *ID() { return (void *)&PassID; } + + 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) + : MAM(Arg.MAM) {} + ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg) + : MAM(std::move(Arg.MAM)) {} + ModuleAnalysisManagerCGSCCProxy & + operator=(ModuleAnalysisManagerCGSCCProxy RHS) { + std::swap(MAM, RHS.MAM); + return *this; + } + + /// \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); } + +private: + static char PassID; + + const ModuleAnalysisManager *MAM; +}; + +/// \brief The core module pass which does a post-order walk of the SCCs and +/// runs a CGSCC pass over each one. +/// +/// Designed to allow composition of a CGSCCPass(Manager) and +/// a ModulePassManager. Note that this pass must be run with a module analysis +/// manager as it uses the LazyCallGraph analysis. It will also run the +/// \c CGSCCAnalysisManagerModuleProxy analysis prior to running the CGSCC +/// pass over the module to enable a \c FunctionAnalysisManager to be used +/// within this run safely. +template <typename CGSCCPassT> class ModuleToPostOrderCGSCCPassAdaptor { +public: + explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) + : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + ModuleToPostOrderCGSCCPassAdaptor( + const ModuleToPostOrderCGSCCPassAdaptor &Arg) + : Pass(Arg.Pass) {} + ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg) + : Pass(std::move(Arg.Pass)) {} + friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS, + ModuleToPostOrderCGSCCPassAdaptor &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + ModuleToPostOrderCGSCCPassAdaptor & + operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief Runs the CGSCC pass across every SCC in the module. + PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + assert(AM && "We need analyses to compute the call graph!"); + + // Setup the CGSCC analysis manager from its proxy. + CGSCCAnalysisManager &CGAM = + AM->getResult<CGSCCAnalysisManagerModuleProxy>(M).getManager(); + + // Get the call graph for this module. + LazyCallGraph &CG = AM->getResult<LazyCallGraphAnalysis>(M); + + PreservedAnalyses PA = PreservedAnalyses::all(); + for (LazyCallGraph::SCC &C : CG.postorder_sccs()) { + 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. + // 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); + + // Then intersect the preserved set so that invalidation of module + // analyses will eventually occur when the module pass completes. + PA.intersect(std::move(PassPA)); + } + + // By definition we preserve the proxy. This precludes *any* invalidation + // of CGSCC analyses by the proxy, but that's OK because we've taken + // care to invalidate analyses in the CGSCC analysis manager + // incrementally above. + PA.preserve<CGSCCAnalysisManagerModuleProxy>(); + return PA; + } + + static StringRef name() { return "ModuleToPostOrderCGSCCPassAdaptor"; } + +private: + CGSCCPassT Pass; +}; + +/// \brief A function to deduce a function pass type and wrap it in the +/// templated adaptor. +template <typename CGSCCPassT> +ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT> +createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) { + return std::move( + ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass))); +} + +/// \brief A CGSCC analysis which acts as a proxy for a function analysis +/// manager. +/// +/// This primarily proxies invalidation information from the CGSCC analysis +/// manager and CGSCC pass manager to a function analysis manager. You should +/// never use a function analysis manager from within (transitively) a CGSCC +/// pass manager unless your parent CGSCC pass has received a proxy result +/// object for it. +class FunctionAnalysisManagerCGSCCProxy { +public: + class Result { + public: + explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} + // We have to explicitly define all the special member functions because + // MSVC refuses to generate them. + Result(const Result &Arg) : FAM(Arg.FAM) {} + Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {} + Result &operator=(Result RHS) { + std::swap(FAM, RHS.FAM); + return *this; + } + ~Result(); + + /// \brief Accessor for the \c FunctionAnalysisManager. + FunctionAnalysisManager &getManager() { return *FAM; } + + /// \brief Handler for invalidation of the SCC. + /// + /// If this analysis itself is preserved, then we assume that the set of \c + /// Function objects in the \c SCC hasn't changed and thus we don't need + /// to invalidate *all* cached data associated with a \c Function* in the \c + /// FunctionAnalysisManager. + /// + /// 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); + + private: + FunctionAnalysisManager *FAM; + }; + + static void *ID() { return (void *)&PassID; } + + explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM) + : FAM(&FAM) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + FunctionAnalysisManagerCGSCCProxy( + const FunctionAnalysisManagerCGSCCProxy &Arg) + : FAM(Arg.FAM) {} + FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManagerCGSCCProxy &&Arg) + : FAM(std::move(Arg.FAM)) {} + FunctionAnalysisManagerCGSCCProxy & + operator=(FunctionAnalysisManagerCGSCCProxy RHS) { + std::swap(FAM, RHS.FAM); + return *this; + } + + /// \brief Run the analysis pass and create our proxy result object. + /// + /// This doesn't do any interesting work, it is primarily used to insert our + /// proxy result object into the module analysis cache so that we can proxy + /// invalidation to the function analysis manager. + /// + /// 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); + +private: + static char PassID; + + FunctionAnalysisManager *FAM; +}; + +/// \brief A function analysis which acts as a proxy for a CGSCC analysis +/// manager. +/// +/// This primarily provides an accessor to a parent CGSCC analysis manager to +/// function passes. Only the const interface of the CGSCC analysis manager is +/// provided to indicate that once inside of a function analysis pass you +/// cannot request a CGSCC analysis to actually run. Instead, the user must +/// rely on the \c getCachedResult API. +/// +/// This proxy *doesn't* manage the invalidation in any way. That is handled by +/// the recursive return path of each layer of the pass manager and the +/// returned PreservedAnalysis set. +class CGSCCAnalysisManagerFunctionProxy { +public: + /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy. + class Result { + public: + explicit Result(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} + // We have to explicitly define all the special member functions because + // MSVC refuses to generate them. + Result(const Result &Arg) : CGAM(Arg.CGAM) {} + Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {} + Result &operator=(Result RHS) { + std::swap(CGAM, RHS.CGAM); + return *this; + } + + const CGSCCAnalysisManager &getManager() const { return *CGAM; } + + /// \brief Handle invalidation by ignoring it, this pass is immutable. + bool invalidate(Function *) { return false; } + + private: + const CGSCCAnalysisManager *CGAM; + }; + + static void *ID() { return (void *)&PassID; } + + CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM) + : CGAM(&CGAM) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + CGSCCAnalysisManagerFunctionProxy( + const CGSCCAnalysisManagerFunctionProxy &Arg) + : CGAM(Arg.CGAM) {} + CGSCCAnalysisManagerFunctionProxy(CGSCCAnalysisManagerFunctionProxy &&Arg) + : CGAM(std::move(Arg.CGAM)) {} + CGSCCAnalysisManagerFunctionProxy & + operator=(CGSCCAnalysisManagerFunctionProxy RHS) { + std::swap(CGAM, RHS.CGAM); + return *this; + } + + /// \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); } + +private: + static char PassID; + + const CGSCCAnalysisManager *CGAM; +}; + +/// \brief Adaptor that maps from a SCC to its functions. +/// +/// Designed to allow composition of a FunctionPass(Manager) and +/// a CGSCCPassManager. Note that if this pass is constructed with a pointer +/// to a \c CGSCCAnalysisManager it will run the +/// \c FunctionAnalysisManagerCGSCCProxy analysis prior to running the function +/// pass over the SCC to enable a \c FunctionAnalysisManager to be used +/// within this run safely. +template <typename FunctionPassT> class CGSCCToFunctionPassAdaptor { +public: + explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass) + : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg) + : Pass(Arg.Pass) {} + CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg) + : Pass(std::move(Arg.Pass)) {} + friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief Runs the function pass across every function in the module. + 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); + + // 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. + if (FAM) + FAM->invalidate(&N->getFunction(), PassPA); + + // Then intersect the preserved set so that invalidation of module + // analyses will eventually occur when the module pass completes. + PA.intersect(std::move(PassPA)); + } + + // By definition we preserve the proxy. This precludes *any* invalidation + // of function analyses by the proxy, but that's OK because we've taken + // care to invalidate analyses in the function analysis manager + // incrementally above. + // FIXME: We need to update the call graph here to account for any deleted + // edges! + PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); + return PA; + } + + static StringRef name() { return "CGSCCToFunctionPassAdaptor"; } + +private: + FunctionPassT Pass; +}; + +/// \brief A function to deduce a function pass type and wrap it in the +/// templated adaptor. +template <typename FunctionPassT> +CGSCCToFunctionPassAdaptor<FunctionPassT> +createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { + return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); +} + +} + +#endif diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index d00c2ed327c5..9a6a4a76eb73 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -6,46 +6,47 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This interface is used to build and manipulate a call graph, which is a very -// useful tool for interprocedural optimization. -// -// Every function in a module is represented as a node in the call graph. The -// callgraph node keeps track of which functions the are called by the function -// corresponding to the node. -// -// A call graph may contain nodes where the function that they correspond to is -// null. These 'external' nodes are used to represent control flow that is not -// represented (or analyzable) in the module. In particular, this analysis -// builds one external node such that: -// 1. All functions in the module without internal linkage will have edges -// from this external node, indicating that they could be called by -// functions outside of the module. -// 2. All functions whose address is used for something more than a direct -// call, for example being stored into a memory location will also have an -// edge from this external node. Since they may be called by an unknown -// caller later, they must be tracked as such. -// -// There is a second external node added for calls that leave this module. -// Functions have a call edge to the external node iff: -// 1. The function is external, reflecting the fact that they could call -// anything without internal linkage or that has its address taken. -// 2. The function contains an indirect function call. -// -// As an extension in the future, there may be multiple nodes with a null -// function. These will be used when we can prove (through pointer analysis) -// that an indirect call site can call only a specific set of functions. -// -// Because of these properties, the CallGraph captures a conservative superset -// of all of the caller-callee relationships, which is useful for -// transformations. -// -// The CallGraph class also attempts to figure out what the root of the -// CallGraph is, which it currently does by looking for a function named 'main'. -// If no function named 'main' is found, the external node is used as the entry -// node, reflecting the fact that any function without internal linkage could -// be called into (which is common for libraries). -// +/// \file +/// +/// This file provides interfaces used to build and manipulate a call graph, +/// which is a very useful tool for interprocedural optimization. +/// +/// Every function in a module is represented as a node in the call graph. The +/// callgraph node keeps track of which functions are called by the function +/// corresponding to the node. +/// +/// A call graph may contain nodes where the function that they correspond to +/// is null. These 'external' nodes are used to represent control flow that is +/// not represented (or analyzable) in the module. In particular, this +/// analysis builds one external node such that: +/// 1. All functions in the module without internal linkage will have edges +/// from this external node, indicating that they could be called by +/// functions outside of the module. +/// 2. All functions whose address is used for something more than a direct +/// call, for example being stored into a memory location will also have +/// an edge from this external node. Since they may be called by an +/// unknown caller later, they must be tracked as such. +/// +/// There is a second external node added for calls that leave this module. +/// Functions have a call edge to the external node iff: +/// 1. The function is external, reflecting the fact that they could call +/// anything without internal linkage or that has its address taken. +/// 2. The function contains an indirect function call. +/// +/// As an extension in the future, there may be multiple nodes with a null +/// function. These will be used when we can prove (through pointer analysis) +/// that an indirect call site can call only a specific set of functions. +/// +/// Because of these properties, the CallGraph captures a conservative superset +/// of all of the caller-callee relationships, which is useful for +/// transformations. +/// +/// The CallGraph class also attempts to figure out what the root of the +/// CallGraph is, which it currently does by looking for a function named +/// 'main'. If no function named 'main' is found, the external node is used as +/// the entry node, reflecting the fact that any function without internal +/// linkage could be called into (which is common for libraries). +/// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_CALLGRAPH_H @@ -53,11 +54,11 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/Function.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" -#include "llvm/Support/CallSite.h" #include "llvm/Support/IncludeFile.h" -#include "llvm/Support/ValueHandle.h" #include <map> namespace llvm { @@ -66,171 +67,142 @@ class Function; class Module; class CallGraphNode; -//===----------------------------------------------------------------------===// -// CallGraph class definition -// -class CallGraph : public ModulePass { - Module *Mod; // The module this call graph represents +/// \brief The basic data container for the call graph of a \c Module of IR. +/// +/// This class exposes both the interface to the call graph for a module of IR. +/// +/// The core call graph itself can also be updated to reflect changes to the IR. +class CallGraph { + Module &M; typedef std::map<const Function *, CallGraphNode *> FunctionMapTy; - FunctionMapTy FunctionMap; // Map from a function to its node - // Root is root of the call graph, or the external node if a 'main' function - // couldn't be found. - // + /// \brief A map from \c Function* to \c CallGraphNode*. + FunctionMapTy FunctionMap; + + /// \brief Root is root of the call graph, or the external node if a 'main' + /// function couldn't be found. CallGraphNode *Root; - // ExternalCallingNode - This node has edges to all external functions and - // those internal functions that have their address taken. + /// \brief This node has edges to all external functions and those internal + /// functions that have their address taken. CallGraphNode *ExternalCallingNode; - // CallsExternalNode - This node has edges to it from all functions making - // indirect calls or calling an external function. + /// \brief This node has edges to it from all functions making indirect calls + /// or calling an external function. CallGraphNode *CallsExternalNode; - /// Replace the function represented by this node by another. + /// \brief Replace the function represented by this node by another. + /// /// This does not rescan the body of the function, so it is suitable when /// splicing the body of one function to another while also updating all /// callers from the old function to the new. - /// void spliceFunction(const Function *From, const Function *To); - // Add a function to the call graph, and link the node to all of the functions - // that it calls. + /// \brief Add a function to the call graph, and link the node to all of the + /// functions that it calls. void addToCallGraph(Function *F); public: - static char ID; // Class identification, replacement for typeinfo - //===--------------------------------------------------------------------- - // Accessors. - // + CallGraph(Module &M); + ~CallGraph(); + + void print(raw_ostream &OS) const; + void dump() const; + typedef FunctionMapTy::iterator iterator; typedef FunctionMapTy::const_iterator const_iterator; - /// getModule - Return the module the call graph corresponds to. - /// - Module &getModule() const { return *Mod; } + /// \brief Returns the module the call graph corresponds to. + Module &getModule() const { return M; } - inline iterator begin() { return FunctionMap.begin(); } - inline iterator end() { return FunctionMap.end(); } + inline iterator begin() { return FunctionMap.begin(); } + inline iterator end() { return FunctionMap.end(); } inline const_iterator begin() const { return FunctionMap.begin(); } - inline const_iterator end() const { return FunctionMap.end(); } + inline const_iterator end() const { return FunctionMap.end(); } - // Subscripting operators, return the call graph node for the provided - // function + /// \brief Returns the call graph node for the provided function. inline const CallGraphNode *operator[](const Function *F) const { const_iterator I = FunctionMap.find(F); assert(I != FunctionMap.end() && "Function not in callgraph!"); return I->second; } + + /// \brief Returns the call graph node for the provided function. inline CallGraphNode *operator[](const Function *F) { const_iterator I = FunctionMap.find(F); assert(I != FunctionMap.end() && "Function not in callgraph!"); return I->second; } - /// Returns the CallGraphNode which is used to represent undetermined calls - /// into the callgraph. + /// \brief Returns the \c CallGraphNode which is used to represent + /// undetermined calls into the callgraph. CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; } - CallGraphNode *getCallsExternalNode() const { return CallsExternalNode; } - /// Return the root/main method in the module, or some other root node, such - /// as the externalcallingnode. - CallGraphNode *getRoot() { return Root; } - const CallGraphNode *getRoot() const { return Root; } + CallGraphNode *getCallsExternalNode() const { return CallsExternalNode; } //===--------------------------------------------------------------------- // Functions to keep a call graph up to date with a function that has been // modified. // - /// removeFunctionFromModule - Unlink the function from this module, returning - /// it. Because this removes the function from the module, the call graph - /// node is destroyed. This is only valid if the function does not call any - /// other functions (ie, there are no edges in it's CGN). The easiest way to - /// do this is to dropAllReferences before calling this. + /// \brief Unlink the function from this module, returning it. /// + /// Because this removes the function from the module, the call graph node is + /// destroyed. This is only valid if the function does not call any other + /// functions (ie, there are no edges in it's CGN). The easiest way to do + /// this is to dropAllReferences before calling this. Function *removeFunctionFromModule(CallGraphNode *CGN); - /// getOrInsertFunction - This method is identical to calling operator[], but - /// it will insert a new CallGraphNode for the specified function if one does - /// not already exist. + /// \brief Similar to operator[], but this will insert a new CallGraphNode for + /// \c F if one does not already exist. CallGraphNode *getOrInsertFunction(const Function *F); - - CallGraph(); - virtual ~CallGraph() { releaseMemory(); } - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual bool runOnModule(Module &M); - virtual void releaseMemory(); - - void print(raw_ostream &o, const Module *) const; - void dump() const; }; -//===----------------------------------------------------------------------===// -// CallGraphNode class definition. -// +/// \brief A node in the call graph for a module. +/// +/// Typically represents a function in the call graph. There are also special +/// "null" nodes used to represent theoretical entries in the call graph. class CallGraphNode { - friend class CallGraph; - - AssertingVH<Function> F; - - // CallRecord - This is a pair of the calling instruction (a call or invoke) - // and the callgraph node being called. public: - typedef std::pair<WeakVH, CallGraphNode*> CallRecord; -private: - std::vector<CallRecord> CalledFunctions; - - /// NumReferences - This is the number of times that this CallGraphNode occurs - /// in the CalledFunctions array of this or other CallGraphNodes. - unsigned NumReferences; + /// \brief A pair of the calling instruction (a call or invoke) + /// and the call graph node being called. + typedef std::pair<WeakVH, CallGraphNode *> CallRecord; - CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION; - void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION; - - void DropRef() { --NumReferences; } - void AddRef() { ++NumReferences; } public: typedef std::vector<CallRecord> CalledFunctionsVector; - - // CallGraphNode ctor - Create a node for the specified function. - inline CallGraphNode(Function *f) : F(f), NumReferences(0) {} + /// \brief Creates a node for the specified function. + inline CallGraphNode(Function *F) : F(F), NumReferences(0) {} + ~CallGraphNode() { assert(NumReferences == 0 && "Node deleted while references remain"); } - - //===--------------------------------------------------------------------- - // Accessor methods. - // typedef std::vector<CallRecord>::iterator iterator; typedef std::vector<CallRecord>::const_iterator const_iterator; - // getFunction - Return the function that this call graph node represents. + /// \brief Returns the function that this call graph node represents. Function *getFunction() const { return F; } inline iterator begin() { return CalledFunctions.begin(); } - inline iterator end() { return CalledFunctions.end(); } + inline iterator end() { return CalledFunctions.end(); } inline const_iterator begin() const { return CalledFunctions.begin(); } - inline const_iterator end() const { return CalledFunctions.end(); } + inline const_iterator end() const { return CalledFunctions.end(); } inline bool empty() const { return CalledFunctions.empty(); } inline unsigned size() const { return (unsigned)CalledFunctions.size(); } - /// getNumReferences - Return the number of other CallGraphNodes in this - /// CallGraph that reference this node in their callee list. + /// \brief Returns the number of other CallGraphNodes in this CallGraph that + /// reference this node in their callee list. unsigned getNumReferences() const { return NumReferences; } - - // Subscripting operator - Return the i'th called function. - // + + /// \brief Returns the i'th called function. CallGraphNode *operator[](unsigned i) const { assert(i < CalledFunctions.size() && "Invalid index"); return CalledFunctions[i].second; } - /// dump - Print out this call graph node. - /// + /// \brief Print out this call graph node. void dump() const; void print(raw_ostream &OS) const; @@ -239,29 +211,25 @@ public: // modified // - /// removeAllCalledFunctions - As the name implies, this removes all edges - /// from this CallGraphNode to any functions it calls. + /// \brief Removes all edges from this CallGraphNode to any functions it + /// calls. void removeAllCalledFunctions() { while (!CalledFunctions.empty()) { CalledFunctions.back().second->DropRef(); CalledFunctions.pop_back(); } } - - /// stealCalledFunctionsFrom - Move all the callee information from N to this - /// node. + + /// \brief Moves all the callee information from N to this node. void stealCalledFunctionsFrom(CallGraphNode *N) { assert(CalledFunctions.empty() && "Cannot steal callsite information if I already have some"); std::swap(CalledFunctions, N->CalledFunctions); } - - /// addCalledFunction - Add a function to the list of functions called by this - /// one. + /// \brief Adds a function to the list of functions called by this one. void addCalledFunction(CallSite CS, CallGraphNode *M) { - assert(!CS.getInstruction() || - !CS.getCalledFunction() || + assert(!CS.getInstruction() || !CS.getCalledFunction() || !CS.getCalledFunction()->isIntrinsic()); CalledFunctions.push_back(std::make_pair(CS.getInstruction(), M)); M->AddRef(); @@ -272,32 +240,152 @@ public: *I = CalledFunctions.back(); CalledFunctions.pop_back(); } - - - /// removeCallEdgeFor - This method removes the edge in the node for the - /// specified call site. Note that this method takes linear time, so it - /// should be used sparingly. + + /// \brief Removes the edge in the node for the specified call site. + /// + /// Note that this method takes linear time, so it should be used sparingly. void removeCallEdgeFor(CallSite CS); - /// removeAnyCallEdgeTo - This method removes all call edges from this node - /// to the specified callee function. This takes more time to execute than - /// removeCallEdgeTo, so it should not be used unless necessary. + /// \brief Removes all call edges from this node to the specified callee + /// function. + /// + /// This takes more time to execute than removeCallEdgeTo, so it should not + /// be used unless necessary. void removeAnyCallEdgeTo(CallGraphNode *Callee); - /// removeOneAbstractEdgeTo - Remove one edge associated with a null callsite - /// from this node to the specified callee function. + /// \brief Removes one edge associated with a null callsite from this node to + /// the specified callee function. void removeOneAbstractEdgeTo(CallGraphNode *Callee); - - /// replaceCallEdge - This method replaces the edge in the node for the - /// specified call site with a new one. Note that this method takes linear - /// time, so it should be used sparingly. + + /// \brief Replaces the edge in the node for the specified call site with a + /// new one. + /// + /// Note that this method takes linear time, so it should be used sparingly. void replaceCallEdge(CallSite CS, CallSite NewCS, CallGraphNode *NewNode); - - /// allReferencesDropped - This is a special function that should only be - /// used by the CallGraph class. - void allReferencesDropped() { - NumReferences = 0; + +private: + friend class CallGraph; + + AssertingVH<Function> F; + + std::vector<CallRecord> CalledFunctions; + + /// \brief The number of times that this CallGraphNode occurs in the + /// CalledFunctions array of this or other CallGraphNodes. + unsigned NumReferences; + + CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION; + void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION; + + void DropRef() { --NumReferences; } + void AddRef() { ++NumReferences; } + + /// \brief A special function that should only be used by the CallGraph class. + void allReferencesDropped() { NumReferences = 0; } +}; + +/// \brief An analysis pass to compute the \c CallGraph for a \c Module. +/// +/// This class implements the concept of an analysis pass used by the \c +/// ModuleAnalysisManager to run an analysis over a module and cache the +/// resulting data. +class CallGraphAnalysis { +public: + /// \brief A formulaic typedef to inform clients of the result type. + typedef CallGraph Result; + + static void *ID() { return (void *)&PassID; } + + /// \brief Compute the \c CallGraph for the module \c M. + /// + /// The real work here is done in the \c CallGraph constructor. + CallGraph run(Module *M) { return CallGraph(*M); } + +private: + static char PassID; +}; + +/// \brief The \c ModulePass which wraps up a \c CallGraph and the logic to +/// build it. +/// +/// This class exposes both the interface to the call graph container and the +/// module pass which runs over a module of IR and produces the call graph. The +/// call graph interface is entirelly a wrapper around a \c CallGraph object +/// which is stored internally for each module. +class CallGraphWrapperPass : public ModulePass { + std::unique_ptr<CallGraph> G; + +public: + static char ID; // Class identification, replacement for typeinfo + + CallGraphWrapperPass(); + virtual ~CallGraphWrapperPass(); + + /// \brief The internal \c CallGraph around which the rest of this interface + /// is wrapped. + const CallGraph &getCallGraph() const { return *G; } + CallGraph &getCallGraph() { return *G; } + + typedef CallGraph::iterator iterator; + typedef CallGraph::const_iterator const_iterator; + + /// \brief Returns the module the call graph corresponds to. + Module &getModule() const { return G->getModule(); } + + inline iterator begin() { return G->begin(); } + inline iterator end() { return G->end(); } + inline const_iterator begin() const { return G->begin(); } + inline const_iterator end() const { return G->end(); } + + /// \brief Returns the call graph node for the provided function. + inline const CallGraphNode *operator[](const Function *F) const { + return (*G)[F]; + } + + /// \brief Returns the call graph node for the provided function. + inline CallGraphNode *operator[](const Function *F) { return (*G)[F]; } + + /// \brief Returns the \c CallGraphNode which is used to represent + /// undetermined calls into the callgraph. + CallGraphNode *getExternalCallingNode() const { + return G->getExternalCallingNode(); + } + + CallGraphNode *getCallsExternalNode() const { + return G->getCallsExternalNode(); + } + + //===--------------------------------------------------------------------- + // Functions to keep a call graph up to date with a function that has been + // modified. + // + + /// \brief Unlink the function from this module, returning it. + /// + /// Because this removes the function from the module, the call graph node is + /// destroyed. This is only valid if the function does not call any other + /// functions (ie, there are no edges in it's CGN). The easiest way to do + /// this is to dropAllReferences before calling this. + Function *removeFunctionFromModule(CallGraphNode *CGN) { + return G->removeFunctionFromModule(CGN); + } + + /// \brief Similar to operator[], but this will insert a new CallGraphNode for + /// \c F if one does not already exist. + CallGraphNode *getOrInsertFunction(const Function *F) { + return G->getOrInsertFunction(F); } + + //===--------------------------------------------------------------------- + // Implementation of the ModulePass interface needed here. + // + + void getAnalysisUsage(AnalysisUsage &AU) const override; + bool runOnModule(Module &M) override; + void releaseMemory() override; + + void print(raw_ostream &o, const Module *) const override; + void dump() const; }; //===----------------------------------------------------------------------===// @@ -307,11 +395,12 @@ public: // Provide graph traits for tranversing call graphs using standard graph // traversals. -template <> struct GraphTraits<CallGraphNode*> { +template <> struct GraphTraits<CallGraphNode *> { typedef CallGraphNode NodeType; typedef CallGraphNode::CallRecord CGNPairTy; - typedef std::pointer_to_unary_function<CGNPairTy, CallGraphNode*> CGNDerefFun; + typedef std::pointer_to_unary_function<CGNPairTy, CallGraphNode *> + CGNDerefFun; static NodeType *getEntryNode(CallGraphNode *CGN) { return CGN; } @@ -320,55 +409,54 @@ template <> struct GraphTraits<CallGraphNode*> { static inline ChildIteratorType child_begin(NodeType *N) { return map_iterator(N->begin(), CGNDerefFun(CGNDeref)); } - static inline ChildIteratorType child_end (NodeType *N) { + static inline ChildIteratorType child_end(NodeType *N) { return map_iterator(N->end(), CGNDerefFun(CGNDeref)); } - static CallGraphNode *CGNDeref(CGNPairTy P) { - return P.second; - } - + static CallGraphNode *CGNDeref(CGNPairTy P) { return P.second; } }; -template <> struct GraphTraits<const CallGraphNode*> { +template <> struct GraphTraits<const CallGraphNode *> { typedef const CallGraphNode NodeType; typedef NodeType::const_iterator ChildIteratorType; static NodeType *getEntryNode(const CallGraphNode *CGN) { return CGN; } - static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();} - static inline ChildIteratorType child_end (NodeType *N) { return N->end(); } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } }; -template<> struct GraphTraits<CallGraph*> : public GraphTraits<CallGraphNode*> { +template <> +struct GraphTraits<CallGraph *> : public GraphTraits<CallGraphNode *> { static NodeType *getEntryNode(CallGraph *CGN) { - return CGN->getExternalCallingNode(); // Start at the external node! + return CGN->getExternalCallingNode(); // Start at the external node! } - typedef std::pair<const Function*, CallGraphNode*> PairTy; - typedef std::pointer_to_unary_function<PairTy, CallGraphNode&> DerefFun; + typedef std::pair<const Function *, CallGraphNode *> PairTy; + typedef std::pointer_to_unary_function<PairTy, CallGraphNode &> DerefFun; // nodes_iterator/begin/end - Allow iteration over all nodes in the graph typedef mapped_iterator<CallGraph::iterator, DerefFun> nodes_iterator; static nodes_iterator nodes_begin(CallGraph *CG) { return map_iterator(CG->begin(), DerefFun(CGdereference)); } - static nodes_iterator nodes_end (CallGraph *CG) { + static nodes_iterator nodes_end(CallGraph *CG) { return map_iterator(CG->end(), DerefFun(CGdereference)); } - static CallGraphNode &CGdereference(PairTy P) { - return *P.second; - } + static CallGraphNode &CGdereference(PairTy P) { return *P.second; } }; -template<> struct GraphTraits<const CallGraph*> : - public GraphTraits<const CallGraphNode*> { +template <> +struct GraphTraits<const CallGraph *> : public GraphTraits< + const CallGraphNode *> { static NodeType *getEntryNode(const CallGraph *CGN) { return CGN->getExternalCallingNode(); } // 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(); } + static nodes_iterator nodes_end(const CallGraph *CG) { return CG->end(); } }; } // End llvm namespace diff --git a/include/llvm/Analysis/CallGraphSCCPass.h b/include/llvm/Analysis/CallGraphSCCPass.h index e609dac11891..667e1715775f 100644 --- a/include/llvm/Analysis/CallGraphSCCPass.h +++ b/include/llvm/Analysis/CallGraphSCCPass.h @@ -37,7 +37,8 @@ public: /// createPrinterPass - Get a pass that prints the Module /// corresponding to a CallGraph. - Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const override; using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; @@ -65,18 +66,17 @@ public: } /// Assign pass manager to manager this pass - virtual void assignPassManager(PMStack &PMS, - PassManagerType PMT); + void assignPassManager(PMStack &PMS, PassManagerType PMT) override; /// Return what kind of Pass Manager can manage this pass. - virtual PassManagerType getPotentialPassManagerType() const { + PassManagerType getPotentialPassManagerType() const override { return PMT_CallGraphPassManager; } /// getAnalysisUsage - For this class, we declare that we require and preserve /// the call graph. If the derived class implements this method, it should /// always explicitly call the implementation here. - virtual void getAnalysisUsage(AnalysisUsage &Info) const; + void getAnalysisUsage(AnalysisUsage &Info) const override; }; /// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on. diff --git a/include/llvm/Analysis/CaptureTracking.h b/include/llvm/Analysis/CaptureTracking.h index 8edabfe860a1..8b7c7a90f7c0 100644 --- a/include/llvm/Analysis/CaptureTracking.h +++ b/include/llvm/Analysis/CaptureTracking.h @@ -18,6 +18,8 @@ namespace llvm { class Value; class Use; + class Instruction; + class DominatorTree; /// PointerMayBeCaptured - Return true if this pointer value may be captured /// by the enclosing function (which is required to exist). This routine can @@ -30,6 +32,20 @@ namespace llvm { bool ReturnCaptures, bool StoreCaptures); + /// PointerMayBeCapturedBefore - Return true if this pointer value may be + /// captured by the enclosing function (which is required to exist). If a + /// DominatorTree is provided, only captures which happen before the given + /// instruction are considered. This routine can be expensive, so consider + /// caching the results. The boolean ReturnCaptures specifies whether + /// returning the value (or part of it) from the function counts as capturing + /// it or not. The boolean StoreCaptures specified whether storing the value + /// (or part of it) into memory anywhere automatically counts as capturing it + /// or not. Captures by the provided instruction are considered if the + /// final parameter is true. + bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, + bool StoreCaptures, const Instruction *I, + DominatorTree *DT, bool IncludeI = false); + /// This callback is used in conjunction with PointerMayBeCaptured. In /// addition to the interface here, you'll need to provide your own getters /// to see whether anything was captured. @@ -45,12 +61,12 @@ namespace llvm { /// capture) return false. To search it, return true. /// /// U->getUser() is always an Instruction. - virtual bool shouldExplore(Use *U); + virtual bool shouldExplore(const Use *U); /// captured - Information about the pointer was captured by the user of /// use U. Return true to stop the traversal or false to continue looking /// for more capturing instructions. - virtual bool captured(Use *U) = 0; + virtual bool captured(const Use *U) = 0; }; /// PointerMayBeCaptured - Visit the value and the values derived from it and diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 086934d0e69b..04b39c176946 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -16,7 +16,7 @@ #define LLVM_ANALYSIS_CODEMETRICS_H #include "llvm/ADT/DenseMap.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/CallSite.h" namespace llvm { class BasicBlock; diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index 0018a567967a..09d45ca2b486 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -36,15 +36,16 @@ namespace llvm { /// Note that this fails if not all of the operands are constant. Otherwise, /// this function can only fail when attempting to fold instructions like loads /// and stores, which have no constant expression form. -Constant *ConstantFoldInstruction(Instruction *I, const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0); +Constant *ConstantFoldInstruction(Instruction *I, + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldConstantExpression - Attempt to fold the constant expression /// using the specified DataLayout. If successful, the constant result is /// result is returned, if not, null is returned. Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, - const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI =nullptr); /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the /// specified operands. If successful, the constant result is returned, if not, @@ -54,8 +55,8 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, /// Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, ArrayRef<Constant *> Ops, - const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldCompareInstOperands - Attempt to constant fold a compare /// instruction (icmp/fcmp) with the specified operands. If it fails, it @@ -63,8 +64,8 @@ Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, /// Constant *ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, - const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI=nullptr); /// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue /// instruction with the specified operands and indices. The constant result is @@ -75,7 +76,8 @@ Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, /// ConstantFoldLoadFromConstPtr - Return the value that a load from C would /// produce if it is constant and determinable. If this is not determinable, /// return null. -Constant *ConstantFoldLoadFromConstPtr(Constant *C, const DataLayout *TD = 0); +Constant *ConstantFoldLoadFromConstPtr(Constant *C, + const DataLayout *TD = nullptr); /// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a /// getelementptr constantexpr, return the constant value being addressed by the @@ -96,7 +98,7 @@ bool canConstantFoldCallTo(const Function *F); /// ConstantFoldCall - Attempt to constant fold a call to the specified function /// with the specified arguments, returning null if unsuccessful. Constant *ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands, - const TargetLibraryInfo *TLI = 0); + const TargetLibraryInfo *TLI = nullptr); } #endif diff --git a/include/llvm/Analysis/ConstantsScanner.h b/include/llvm/Analysis/ConstantsScanner.h index cdaf68d75a63..d3d0a44bd6d4 100644 --- a/include/llvm/Analysis/ConstantsScanner.h +++ b/include/llvm/Analysis/ConstantsScanner.h @@ -16,7 +16,7 @@ #ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H #define LLVM_ANALYSIS_CONSTANTSSCANNER_H -#include "llvm/Support/InstIterator.h" +#include "llvm/IR/InstIterator.h" namespace llvm { diff --git a/include/llvm/Analysis/DOTGraphTraitsPass.h b/include/llvm/Analysis/DOTGraphTraitsPass.h index 0fc1c2dc360d..53c832cbebee 100644 --- a/include/llvm/Analysis/DOTGraphTraitsPass.h +++ b/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -16,53 +16,66 @@ #include "llvm/Analysis/CFGPrinter.h" #include "llvm/Pass.h" +#include "llvm/Support/FileSystem.h" namespace llvm { -template <class Analysis, bool Simple> +/// \brief Default traits class for extracting a graph from an analysis pass. +/// +/// This assumes that 'GraphT' is 'AnalysisT *' and so just passes it through. +template <typename AnalysisT, typename GraphT = AnalysisT *> +struct DefaultAnalysisGraphTraits { + static GraphT getGraph(AnalysisT *A) { return A; } +}; + +template < + typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, + typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> > class DOTGraphTraitsViewer : public FunctionPass { public: DOTGraphTraitsViewer(StringRef GraphName, char &ID) - : FunctionPass(ID), Name(GraphName) {} + : FunctionPass(ID), Name(GraphName) {} - virtual bool runOnFunction(Function &F) { - Analysis *Graph = &getAnalysis<Analysis>(); - std::string GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); + bool runOnFunction(Function &F) override { + GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>()); + std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph); std::string Title = GraphName + " for '" + F.getName().str() + "' function"; - ViewGraph(Graph, Name, Simple, Title); + ViewGraph(Graph, Name, IsSimple, Title); return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); - AU.addRequired<Analysis>(); + AU.addRequired<AnalysisT>(); } private: std::string Name; }; -template <class Analysis, bool Simple> +template < + typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, + typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> > class DOTGraphTraitsPrinter : public FunctionPass { public: DOTGraphTraitsPrinter(StringRef GraphName, char &ID) - : FunctionPass(ID), Name(GraphName) {} + : FunctionPass(ID), Name(GraphName) {} - virtual bool runOnFunction(Function &F) { - Analysis *Graph = &getAnalysis<Analysis>(); + bool runOnFunction(Function &F) override { + GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>()); std::string Filename = Name + "." + F.getName().str() + ".dot"; std::string ErrorInfo; errs() << "Writing '" << Filename << "'..."; - raw_fd_ostream File(Filename.c_str(), ErrorInfo); - std::string GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph); + raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text); + std::string GraphName = DOTGraphTraits<GraphT>::getGraphName(Graph); std::string Title = GraphName + " for '" + F.getName().str() + "' function"; if (ErrorInfo.empty()) - WriteGraph(File, Graph, Simple, Title); + WriteGraph(File, Graph, IsSimple, Title); else errs() << " error opening file for writing!"; errs() << "\n"; @@ -70,57 +83,61 @@ public: return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); - AU.addRequired<Analysis>(); + AU.addRequired<AnalysisT>(); } private: std::string Name; }; -template <class Analysis, bool Simple> +template < + typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, + typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> > class DOTGraphTraitsModuleViewer : public ModulePass { public: DOTGraphTraitsModuleViewer(StringRef GraphName, char &ID) - : ModulePass(ID), Name(GraphName) {} + : ModulePass(ID), Name(GraphName) {} - virtual bool runOnModule(Module &M) { - Analysis *Graph = &getAnalysis<Analysis>(); - std::string Title = DOTGraphTraits<Analysis*>::getGraphName(Graph); + bool runOnModule(Module &M) override { + GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>()); + std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph); - ViewGraph(Graph, Name, Simple, Title); + ViewGraph(Graph, Name, IsSimple, Title); return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); - AU.addRequired<Analysis>(); + AU.addRequired<AnalysisT>(); } private: std::string Name; }; -template <class Analysis, bool Simple> +template < + typename AnalysisT, bool IsSimple, typename GraphT = AnalysisT *, + typename AnalysisGraphTraitsT = DefaultAnalysisGraphTraits<AnalysisT> > class DOTGraphTraitsModulePrinter : public ModulePass { public: DOTGraphTraitsModulePrinter(StringRef GraphName, char &ID) - : ModulePass(ID), Name(GraphName) {} + : ModulePass(ID), Name(GraphName) {} - virtual bool runOnModule(Module &M) { - Analysis *Graph = &getAnalysis<Analysis>(); + bool runOnModule(Module &M) override { + GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis<AnalysisT>()); std::string Filename = Name + ".dot"; std::string ErrorInfo; errs() << "Writing '" << Filename << "'..."; - raw_fd_ostream File(Filename.c_str(), ErrorInfo); - std::string Title = DOTGraphTraits<Analysis*>::getGraphName(Graph); + raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text); + std::string Title = DOTGraphTraits<GraphT>::getGraphName(Graph); if (ErrorInfo.empty()) - WriteGraph(File, Graph, Simple, Title); + WriteGraph(File, Graph, IsSimple, Title); else errs() << " error opening file for writing!"; errs() << "\n"; @@ -128,9 +145,9 @@ public: return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); - AU.addRequired<Analysis>(); + AU.addRequired<AnalysisT>(); } private: diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index ea8cecf97e67..279755e47622 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -73,8 +73,8 @@ namespace llvm { Instruction *Destination) : Src(Source), Dst(Destination), - NextPredecessor(NULL), - NextSuccessor(NULL) {} + NextPredecessor(nullptr), + NextSuccessor(nullptr) {} virtual ~Dependence() {} /// Dependence::DVEntry - Each level in the distance/direction vector @@ -96,7 +96,7 @@ namespace llvm { bool Splitable : 1; // Splitting the loop will break dependence. const SCEV *Distance; // NULL implies no distance available. DVEntry() : Direction(ALL), Scalar(true), PeelFirst(false), - PeelLast(false), Splitable(false), Distance(NULL) { } + PeelLast(false), Splitable(false), Distance(nullptr) { } }; /// getSrc - Returns the source instruction for this dependence. @@ -154,7 +154,7 @@ namespace llvm { /// getDistance - Returns the distance (or NULL) associated with a /// particular level. - virtual const SCEV *getDistance(unsigned Level) const { return NULL; } + virtual const SCEV *getDistance(unsigned Level) const { return nullptr; } /// isPeelFirst - Returns true if peeling the first iteration from /// this loop will break this dependence. @@ -227,45 +227,45 @@ namespace llvm { /// isLoopIndependent - Returns true if this is a loop-independent /// dependence. - bool isLoopIndependent() const { return LoopIndependent; } + bool isLoopIndependent() const override { return LoopIndependent; } /// isConfused - Returns true if this dependence is confused /// (the compiler understands nothing and makes worst-case /// assumptions). - bool isConfused() const { return false; } + bool isConfused() const override { return false; } /// isConsistent - Returns true if this dependence is consistent /// (occurs every time the source and destination are executed). - bool isConsistent() const { return Consistent; } + bool isConsistent() const override { return Consistent; } /// getLevels - Returns the number of common loops surrounding the /// source and destination of the dependence. - unsigned getLevels() const { return Levels; } + unsigned getLevels() const override { return Levels; } /// getDirection - Returns the direction associated with a particular /// level. - unsigned getDirection(unsigned Level) const; + unsigned getDirection(unsigned Level) const override; /// getDistance - Returns the distance (or NULL) associated with a /// particular level. - const SCEV *getDistance(unsigned Level) const; + const SCEV *getDistance(unsigned Level) const override; /// isPeelFirst - Returns true if peeling the first iteration from /// this loop will break this dependence. - bool isPeelFirst(unsigned Level) const; + bool isPeelFirst(unsigned Level) const override; /// isPeelLast - Returns true if peeling the last iteration from /// this loop will break this dependence. - bool isPeelLast(unsigned Level) const; + bool isPeelLast(unsigned Level) const override; /// isSplitable - Returns true if splitting the loop will break /// the dependence. - bool isSplitable(unsigned Level) const; + bool isSplitable(unsigned Level) const override; /// isScalar - Returns true if a particular level is scalar; that is, /// if no subscript in the source or destination mention the induction /// variable associated with the loop at this level. - bool isScalar(unsigned Level) const; + bool isScalar(unsigned Level) const override; private: unsigned short Levels; bool LoopIndependent; @@ -910,7 +910,8 @@ namespace llvm { const Constraint &CurConstraint) const; bool tryDelinearize(const SCEV *SrcSCEV, const SCEV *DstSCEV, - SmallVectorImpl<Subscript> &Pair) const; + SmallVectorImpl<Subscript> &Pair, + const SCEV *ElementSize) const; public: static char ID; // Class identification, replacement for typeinfo @@ -918,10 +919,10 @@ namespace llvm { initializeDependenceAnalysisPass(*PassRegistry::getPassRegistry()); } - bool runOnFunction(Function &F); - void releaseMemory(); - void getAnalysisUsage(AnalysisUsage &) const; - void print(raw_ostream &, const Module * = 0) const; + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void getAnalysisUsage(AnalysisUsage &) const override; + void print(raw_ostream &, const Module * = nullptr) const override; }; // class DependenceAnalysis /// createDependenceAnalysisPass - This creates an instance of the diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h index a2e0675e92b7..f42b9cbbfedd 100644 --- a/include/llvm/Analysis/DominanceFrontier.h +++ b/include/llvm/Analysis/DominanceFrontier.h @@ -18,173 +18,191 @@ #ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H #define LLVM_ANALYSIS_DOMINANCEFRONTIER_H -#include "llvm/Analysis/Dominators.h" +#include "llvm/IR/Dominators.h" #include <map> #include <set> namespace llvm { - + //===----------------------------------------------------------------------===// /// DominanceFrontierBase - Common base class for computing forward and inverse /// dominance frontiers for a function. /// -class DominanceFrontierBase : public FunctionPass { +template <class BlockT> +class DominanceFrontierBase { public: - typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb - typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map + typedef std::set<BlockT *> DomSetType; // Dom set for a bb + typedef std::map<BlockT *, DomSetType> DomSetMapType; // Dom set map + protected: + typedef GraphTraits<BlockT *> BlockTraits; + DomSetMapType Frontiers; - std::vector<BasicBlock*> Roots; + std::vector<BlockT *> Roots; const bool IsPostDominators; public: - DominanceFrontierBase(char &ID, bool isPostDom) - : FunctionPass(ID), IsPostDominators(isPostDom) {} + DominanceFrontierBase(bool isPostDom) : IsPostDominators(isPostDom) {} /// getRoots - Return the root blocks of the current CFG. This may include /// multiple blocks if we are computing post dominators. For forward /// dominators, this will always be a single block (the entry node). /// - inline const std::vector<BasicBlock*> &getRoots() const { return Roots; } + inline const std::vector<BlockT *> &getRoots() const { + return Roots; + } + + BlockT *getRoot() const { + assert(Roots.size() == 1 && "Should always have entry node!"); + return Roots[0]; + } /// isPostDominator - Returns true if analysis based of postdoms /// - bool isPostDominator() const { return IsPostDominators; } + bool isPostDominator() const { + return IsPostDominators; + } - virtual void releaseMemory() { Frontiers.clear(); } + void releaseMemory() { + Frontiers.clear(); + } // Accessor interface: - typedef DomSetMapType::iterator iterator; - typedef DomSetMapType::const_iterator const_iterator; - iterator begin() { return Frontiers.begin(); } + typedef typename DomSetMapType::iterator iterator; + typedef typename DomSetMapType::const_iterator const_iterator; + iterator begin() { return Frontiers.begin(); } const_iterator begin() const { return Frontiers.begin(); } - iterator end() { return Frontiers.end(); } - const_iterator end() const { return Frontiers.end(); } - iterator find(BasicBlock *B) { return Frontiers.find(B); } - const_iterator find(BasicBlock *B) const { return Frontiers.find(B); } + iterator end() { return Frontiers.end(); } + const_iterator end() const { return Frontiers.end(); } + iterator find(BlockT *B) { return Frontiers.find(B); } + const_iterator find(BlockT *B) const { return Frontiers.find(B); } - iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) { + iterator addBasicBlock(BlockT *BB, const DomSetType &frontier) { assert(find(BB) == end() && "Block already in DominanceFrontier!"); return Frontiers.insert(std::make_pair(BB, frontier)).first; } /// removeBlock - Remove basic block BB's frontier. - void removeBlock(BasicBlock *BB) { - assert(find(BB) != end() && "Block is not in DominanceFrontier!"); - for (iterator I = begin(), E = end(); I != E; ++I) - I->second.erase(BB); - Frontiers.erase(BB); - } + void removeBlock(BlockT *BB); - void addToFrontier(iterator I, BasicBlock *Node) { - assert(I != end() && "BB is not in DominanceFrontier!"); - I->second.insert(Node); - } + void addToFrontier(iterator I, BlockT *Node); - void removeFromFrontier(iterator I, BasicBlock *Node) { - assert(I != end() && "BB is not in DominanceFrontier!"); - assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); - I->second.erase(Node); - } + void removeFromFrontier(iterator I, BlockT *Node); /// compareDomSet - Return false if two domsets match. Otherwise /// return true; - bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const { - std::set<BasicBlock *> tmpSet; - for (DomSetType::const_iterator I = DS2.begin(), - E = DS2.end(); I != E; ++I) - tmpSet.insert(*I); - - for (DomSetType::const_iterator I = DS1.begin(), - E = DS1.end(); I != E; ) { - BasicBlock *Node = *I++; - - if (tmpSet.erase(Node) == 0) - // Node is in DS1 but not in DS2. - return true; - } - - if (!tmpSet.empty()) - // There are nodes that are in DS2 but not in DS1. - return true; - - // DS1 and DS2 matches. - return false; - } + bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const; /// compare - Return true if the other dominance frontier base matches /// this dominance frontier base. Otherwise return false. - bool compare(DominanceFrontierBase &Other) const { - DomSetMapType tmpFrontiers; - for (DomSetMapType::const_iterator I = Other.begin(), - E = Other.end(); I != E; ++I) - tmpFrontiers.insert(std::make_pair(I->first, I->second)); - - for (DomSetMapType::iterator I = tmpFrontiers.begin(), - E = tmpFrontiers.end(); I != E; ) { - BasicBlock *Node = I->first; - const_iterator DFI = find(Node); - if (DFI == end()) - return true; - - if (compareDomSet(I->second, DFI->second)) - return true; - - ++I; - tmpFrontiers.erase(Node); - } - - if (!tmpFrontiers.empty()) - return true; - - return false; - } + bool compare(DominanceFrontierBase<BlockT> &Other) const; /// print - Convert to human readable form /// - virtual void print(raw_ostream &OS, const Module* = 0) const; + void print(raw_ostream &OS) const; /// dump - Dump the dominance frontier to dbgs(). void dump() const; }; - //===------------------------------------- /// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is /// used to compute a forward dominator frontiers. /// -class DominanceFrontier : public DominanceFrontierBase { - virtual void anchor(); +template <class BlockT> +class ForwardDominanceFrontierBase : public DominanceFrontierBase<BlockT> { +private: + typedef GraphTraits<BlockT *> BlockTraits; + public: + typedef DominatorTreeBase<BlockT> DomTreeT; + typedef DomTreeNodeBase<BlockT> DomTreeNodeT; + typedef typename DominanceFrontierBase<BlockT>::DomSetType DomSetType; + + ForwardDominanceFrontierBase() : DominanceFrontierBase<BlockT>(false) {} + + void analyze(DomTreeT &DT) { + this->Roots = DT.getRoots(); + assert(this->Roots.size() == 1 && + "Only one entry block for forward domfronts!"); + calculate(DT, DT[this->Roots[0]]); + } + + const DomSetType &calculate(const DomTreeT &DT, const DomTreeNodeT *Node); +}; + +class DominanceFrontier : public FunctionPass { + ForwardDominanceFrontierBase<BasicBlock> Base; + +public: + typedef DominatorTreeBase<BasicBlock> DomTreeT; + typedef DomTreeNodeBase<BasicBlock> DomTreeNodeT; + typedef DominanceFrontierBase<BasicBlock>::DomSetType DomSetType; + typedef DominanceFrontierBase<BasicBlock>::iterator iterator; + typedef DominanceFrontierBase<BasicBlock>::const_iterator const_iterator; + static char ID; // Pass ID, replacement for typeid - DominanceFrontier() : - DominanceFrontierBase(ID, false) { - initializeDominanceFrontierPass(*PassRegistry::getPassRegistry()); - } - BasicBlock *getRoot() const { - assert(Roots.size() == 1 && "Should always have entry node!"); - return Roots[0]; + DominanceFrontier(); + + ForwardDominanceFrontierBase<BasicBlock> &getBase() { return Base; } + + inline const std::vector<BasicBlock *> &getRoots() const { + return Base.getRoots(); } - virtual bool runOnFunction(Function &) { - Frontiers.clear(); - DominatorTree &DT = getAnalysis<DominatorTree>(); - Roots = DT.getRoots(); - assert(Roots.size() == 1 && "Only one entry block for forward domfronts!"); - calculate(DT, DT[Roots[0]]); - return false; + BasicBlock *getRoot() const { return Base.getRoot(); } + + bool isPostDominator() const { return Base.isPostDominator(); } + + iterator begin() { return Base.begin(); } + + const_iterator begin() const { return Base.begin(); } + + iterator end() { return Base.end(); } + + const_iterator end() const { return Base.end(); } + + iterator find(BasicBlock *B) { return Base.find(B); } + + const_iterator find(BasicBlock *B) const { return Base.find(B); } + + iterator addBasicBlock(BasicBlock *BB, const DomSetType &frontier) { + return Base.addBasicBlock(BB, frontier); + } + + void removeBlock(BasicBlock *BB) { return Base.removeBlock(BB); } + + void addToFrontier(iterator I, BasicBlock *Node) { + return Base.addToFrontier(I, Node); + } + + void removeFromFrontier(iterator I, BasicBlock *Node) { + return Base.removeFromFrontier(I, Node); } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<DominatorTree>(); + bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const { + return Base.compareDomSet(DS1, DS2); } - const DomSetType &calculate(const DominatorTree &DT, - const DomTreeNode *Node); + bool compare(DominanceFrontierBase<BasicBlock> &Other) const { + return Base.compare(Other); + } + + void releaseMemory() override; + + bool runOnFunction(Function &) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + void print(raw_ostream &OS, const Module * = nullptr) const override; + + void dump() const; }; +EXTERN_TEMPLATE_INSTANTIATION(class DominanceFrontierBase<BasicBlock>); +EXTERN_TEMPLATE_INSTANTIATION(class ForwardDominanceFrontierBase<BasicBlock>); + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/DominanceFrontierImpl.h b/include/llvm/Analysis/DominanceFrontierImpl.h new file mode 100644 index 000000000000..04df2cc35d46 --- /dev/null +++ b/include/llvm/Analysis/DominanceFrontierImpl.h @@ -0,0 +1,228 @@ +//===- llvm/Analysis/DominanceFrontier.h - Dominator Frontiers --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This is the generic implementation of the DominanceFrontier class, which +// calculate and holds the dominance frontier for a function for. +// +// This should be considered deprecated, don't add any more uses of this data +// structure. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_IMPL_H +#define LLVM_ANALYSIS_DOMINANCEFRONTIER_IMPL_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Debug.h" + +namespace llvm { + +namespace { +template <class BlockT> +class DFCalculateWorkObject { +public: + typedef DomTreeNodeBase<BlockT> DomTreeNodeT; + + DFCalculateWorkObject(BlockT *B, BlockT *P, const DomTreeNodeT *N, + const DomTreeNodeT *PN) + : currentBB(B), parentBB(P), Node(N), parentNode(PN) {} + BlockT *currentBB; + BlockT *parentBB; + const DomTreeNodeT *Node; + const DomTreeNodeT *parentNode; +}; +} + +template <class BlockT> +void DominanceFrontierBase<BlockT>::removeBlock(BlockT *BB) { + assert(find(BB) != end() && "Block is not in DominanceFrontier!"); + for (iterator I = begin(), E = end(); I != E; ++I) + I->second.erase(BB); + Frontiers.erase(BB); +} + +template <class BlockT> +void DominanceFrontierBase<BlockT>::addToFrontier(iterator I, + BlockT *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); + I->second.erase(Node); +} + +template <class BlockT> +void DominanceFrontierBase<BlockT>::removeFromFrontier(iterator I, + BlockT *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); + I->second.erase(Node); +} + +template <class BlockT> +bool DominanceFrontierBase<BlockT>::compareDomSet(DomSetType &DS1, + const DomSetType &DS2) const { + std::set<BlockT *> tmpSet; + for (BlockT *BB : DS2) + tmpSet.insert(BB); + + for (typename DomSetType::const_iterator I = DS1.begin(), E = DS1.end(); + I != E;) { + BlockT *Node = *I++; + + if (tmpSet.erase(Node) == 0) + // Node is in DS1 but tnot in DS2. + return true; + } + + if (!tmpSet.empty()) { + // There are nodes that are in DS2 but not in DS1. + return true; + } + + // DS1 and DS2 matches. + return false; +} + +template <class BlockT> +bool DominanceFrontierBase<BlockT>::compare( + DominanceFrontierBase<BlockT> &Other) const { + DomSetMapType tmpFrontiers; + for (typename DomSetMapType::const_iterator I = Other.begin(), + E = Other.end(); + I != E; ++I) + tmpFrontiers.insert(std::make_pair(I->first, I->second)); + + for (typename DomSetMapType::iterator I = tmpFrontiers.begin(), + E = tmpFrontiers.end(); + I != E;) { + BlockT *Node = I->first; + const_iterator DFI = find(Node); + if (DFI == end()) + return true; + + if (compareDomSet(I->second, DFI->second)) + return true; + + ++I; + tmpFrontiers.erase(Node); + } + + if (!tmpFrontiers.empty()) + return true; + + return false; +} + +template <class BlockT> +void DominanceFrontierBase<BlockT>::print(raw_ostream &OS) const { + for (const_iterator I = begin(), E = end(); I != E; ++I) { + OS << " DomFrontier for BB "; + if (I->first) + I->first->printAsOperand(OS, false); + else + OS << " <<exit node>>"; + OS << " is:\t"; + + const std::set<BlockT *> &BBs = I->second; + + for (const BlockT *BB : BBs) { + OS << ' '; + if (BB) + BB->printAsOperand(OS, false); + else + OS << "<<exit node>>"; + } + OS << '\n'; + } +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +template <class BlockT> +void DominanceFrontierBase<BlockT>::dump() const { + print(dbgs()); +} +#endif + +template <class BlockT> +const typename ForwardDominanceFrontierBase<BlockT>::DomSetType & +ForwardDominanceFrontierBase<BlockT>::calculate(const DomTreeT &DT, + const DomTreeNodeT *Node) { + BlockT *BB = Node->getBlock(); + DomSetType *Result = nullptr; + + std::vector<DFCalculateWorkObject<BlockT>> workList; + SmallPtrSet<BlockT *, 32> visited; + + workList.push_back(DFCalculateWorkObject<BlockT>(BB, nullptr, Node, nullptr)); + do { + DFCalculateWorkObject<BlockT> *currentW = &workList.back(); + assert(currentW && "Missing work object."); + + BlockT *currentBB = currentW->currentBB; + BlockT *parentBB = currentW->parentBB; + const DomTreeNodeT *currentNode = currentW->Node; + const DomTreeNodeT *parentNode = currentW->parentNode; + assert(currentBB && "Invalid work object. Missing current Basic Block"); + assert(currentNode && "Invalid work object. Missing current Node"); + DomSetType &S = this->Frontiers[currentBB]; + + // Visit each block only once. + if (visited.count(currentBB) == 0) { + visited.insert(currentBB); + + // Loop over CFG successors to calculate DFlocal[currentNode] + for (auto SI = BlockTraits::child_begin(currentBB), + SE = BlockTraits::child_end(currentBB); + SI != SE; ++SI) { + // Does Node immediately dominate this successor? + if (DT[*SI]->getIDom() != currentNode) + S.insert(*SI); + } + } + + // At this point, S is DFlocal. Now we union in DFup's of our children... + // Loop through and visit the nodes that Node immediately dominates (Node's + // children in the IDomTree) + bool visitChild = false; + for (typename DomTreeNodeT::const_iterator NI = currentNode->begin(), + NE = currentNode->end(); + NI != NE; ++NI) { + DomTreeNodeT *IDominee = *NI; + BlockT *childBB = IDominee->getBlock(); + if (visited.count(childBB) == 0) { + workList.push_back(DFCalculateWorkObject<BlockT>( + childBB, currentBB, IDominee, currentNode)); + visitChild = true; + } + } + + // If all children are visited or there is any child then pop this block + // from the workList. + if (!visitChild) { + if (!parentBB) { + Result = &S; + break; + } + + typename DomSetType::const_iterator CDFI = S.begin(), CDFE = S.end(); + DomSetType &parentSet = this->Frontiers[parentBB]; + for (; CDFI != CDFE; ++CDFI) { + if (!DT.properlyDominates(parentNode, DT[*CDFI])) + parentSet.insert(*CDFI); + } + workList.pop_back(); + } + + } while (!workList.empty()); + + return *Result; +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/FindUsedTypes.h b/include/llvm/Analysis/FindUsedTypes.h index b22cb8813513..574c947f4ebb 100644 --- a/include/llvm/Analysis/FindUsedTypes.h +++ b/include/llvm/Analysis/FindUsedTypes.h @@ -39,7 +39,7 @@ public: /// 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; + void print(raw_ostream &o, const Module *M) const override; private: /// IncorporateType - Incorporate one type and all of its subtypes into the @@ -53,10 +53,10 @@ private: public: /// run - This incorporates all types used by the specified module - bool runOnModule(Module &M); + bool runOnModule(Module &M) override; /// getAnalysisUsage - We do not modify anything. - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } }; diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index c9828015be29..6038872207c3 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -17,7 +17,7 @@ #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/ScalarEvolutionNormalization.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" namespace llvm { @@ -86,7 +86,7 @@ private: /// Deleted - Implementation of CallbackVH virtual function to /// receive notification when the User is deleted. - virtual void deleted(); + void deleted() override; }; template<> struct ilist_traits<IVStrideUse> @@ -122,18 +122,18 @@ class IVUsers : public LoopPass { LoopInfo *LI; DominatorTree *DT; ScalarEvolution *SE; - DataLayout *TD; + const DataLayout *DL; SmallPtrSet<Instruction*,16> Processed; /// IVUses - A list of all tracked IV uses of induction variable expressions /// we are interested in. ilist<IVStrideUse> IVUses; - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; - virtual bool runOnLoop(Loop *L, LPPassManager &LPM); + bool runOnLoop(Loop *L, LPPassManager &LPM) override; - virtual void releaseMemory(); + void releaseMemory() override; public: static char ID; // Pass ID, replacement for typeid @@ -169,7 +169,7 @@ public: return Processed.count(Inst); } - void print(raw_ostream &OS, const Module* = 0) const; + void print(raw_ostream &OS, const Module* = nullptr) const override; /// dump - This method is used for debugging. void dump() const; diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index 383f69713ad2..aaed716b6a11 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -99,7 +99,6 @@ public: /// \brief Cost analyzer used by inliner. class InlineCostAnalysis : public CallGraphSCCPass { - const DataLayout *TD; const TargetTransformInfo *TTI; public: @@ -109,8 +108,8 @@ public: ~InlineCostAnalysis(); // Pass interface implementation. - void getAnalysisUsage(AnalysisUsage &AU) const; - bool runOnSCC(CallGraphSCC &SCC); + void getAnalysisUsage(AnalysisUsage &AU) const override; + bool runOnSCC(CallGraphSCC &SCC) override; /// \brief Get an InlineCost object representing the cost of inlining this /// callsite. diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 775d0df46c67..2367c0bf77aa 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -48,160 +48,166 @@ namespace llvm { /// SimplifyAddInst - Given operands for an Add, see if we can /// fold the result. If not, this returns null. Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, - const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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, - const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifySDivInst(Value *LHS, Value *RHS, + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyUDivInst(Value *LHS, Value *RHS, + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyFDivInst(Value *LHS, Value *RHS, + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifySRemInst(Value *LHS, Value *RHS, + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyURemInst(Value *LHS, Value *RHS, + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyFRemInst(Value *LHS, Value *RHS, + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr); /// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we /// can fold the result. If not, this returns null. Value *SimplifyInsertValueInst(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, - const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr); //=== Helper functions for higher up the class hierarchy. @@ -209,40 +215,40 @@ namespace llvm { /// SimplifyCmpInst - Given operands for a CmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr); /// \brief Given a function and iterators over arguments, see if we can fold /// the result. /// /// If this call could not be simplified returns null. Value *SimplifyCall(Value *V, User::op_iterator ArgBegin, - User::op_iterator ArgEnd, const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + User::op_iterator ArgEnd, const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr); /// \brief Given a function and set of arguments, see if we can fold the /// result. /// /// If this call could not be simplified returns null. Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, - const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = 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 = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr); /// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses @@ -254,9 +260,9 @@ namespace llvm { /// /// The function returns true if any simplifications were performed. bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, - const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr); /// \brief Recursively attempt to simplify an instruction. /// @@ -265,9 +271,9 @@ namespace llvm { /// of the users impacted. It returns true if any simplifications were /// performed. bool recursivelySimplifyInstruction(Instruction *I, - const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0, - const DominatorTree *DT = 0); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr); } // end namespace llvm #endif diff --git a/include/llvm/Analysis/Interval.h b/include/llvm/Analysis/Interval.h index 5ce1260eca1f..01eba3f16c01 100644 --- a/include/llvm/Analysis/Interval.h +++ b/include/llvm/Analysis/Interval.h @@ -48,9 +48,6 @@ public: Nodes.push_back(Header); } - inline Interval(const Interval &I) // copy ctor - : HeaderNode(I.HeaderNode), Nodes(I.Nodes), Successors(I.Successors) {} - inline BasicBlock *getHeaderNode() const { return HeaderNode; } /// Nodes - The basic blocks in this interval. diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h index 22067c4f3c82..73aff76efe83 100644 --- a/include/llvm/Analysis/IntervalIterator.h +++ b/include/llvm/Analysis/IntervalIterator.h @@ -34,8 +34,8 @@ #define LLVM_ANALYSIS_INTERVALITERATOR_H #include "llvm/Analysis/IntervalPartition.h" +#include "llvm/IR/CFG.h" #include "llvm/IR/Function.h" -#include "llvm/Support/CFG.h" #include <algorithm> #include <set> #include <vector> diff --git a/include/llvm/Analysis/IntervalPartition.h b/include/llvm/Analysis/IntervalPartition.h index 8cade58cd324..274be2bdcfa9 100644 --- a/include/llvm/Analysis/IntervalPartition.h +++ b/include/llvm/Analysis/IntervalPartition.h @@ -34,7 +34,7 @@ namespace llvm { // IntervalPartition - This class builds and holds an "interval partition" for // a function. This partition divides the control flow graph into a set of // maximal intervals, as defined with the properties above. Intuitively, an -// interval is a (possibly nonexistent) loop with a "tail" of non looping +// interval is a (possibly nonexistent) loop with a "tail" of non-looping // nodes following it. // class IntervalPartition : public FunctionPass { @@ -48,12 +48,12 @@ class IntervalPartition : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid - IntervalPartition() : FunctionPass(ID), RootInterval(0) { + IntervalPartition() : FunctionPass(ID), RootInterval(nullptr) { initializeIntervalPartitionPass(*PassRegistry::getPassRegistry()); } // run - Calculate the interval partition for this function - virtual bool runOnFunction(Function &F); + bool runOnFunction(Function &F) override; // IntervalPartition ctor - Build a reduced interval partition from an // existing interval graph. This takes an additional boolean parameter to @@ -62,7 +62,7 @@ public: IntervalPartition(IntervalPartition &I, bool); // print - Show contents in human readable format... - virtual void print(raw_ostream &O, const Module* = 0) const; + void print(raw_ostream &O, const Module* = nullptr) const override; // getRootInterval() - Return the root interval that contains the starting // block of the function. @@ -77,11 +77,11 @@ public: // getBlockInterval - Return the interval that a basic block exists in. inline Interval *getBlockInterval(BasicBlock *BB) { IntervalMapTy::iterator I = IntervalMap.find(BB); - return I != IntervalMap.end() ? I->second : 0; + return I != IntervalMap.end() ? I->second : nullptr; } // getAnalysisUsage - Implement the Pass API - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } @@ -89,7 +89,7 @@ public: const std::vector<Interval*> &getIntervals() const { return Intervals; } // releaseMemory - Reset state back to before function was analyzed - void releaseMemory(); + void releaseMemory() override; private: // addIntervalToPartition - Add an interval to the internal list of intervals, diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h new file mode 100644 index 000000000000..54760aa02466 --- /dev/null +++ b/include/llvm/Analysis/JumpInstrTableInfo.h @@ -0,0 +1,60 @@ +//===-- JumpInstrTableInfo.h: Info for Jump-Instruction Tables --*- C++ -*-===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Information about jump-instruction tables that have been created by +/// JumpInstrTables pass. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H +#define LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Pass.h" + +#include <vector> + +namespace llvm { +class Function; +class FunctionType; + +/// This class stores information about jump-instruction tables created by the +/// JumpInstrTables pass (in lib/CodeGen/JumpInstrTables.cpp). Each table is a +/// map from a function type to a vector of pairs. The first element of each +/// pair is the function that has the jumptable annotation. The second element +/// is a function that was declared by JumpInstrTables and used to replace all +/// address-taking sites for the original function. +/// +/// The information in this pass is used in AsmPrinter +/// (lib/CodeGen/AsmPrinter/AsmPrinter.cpp) to generate the required assembly +/// for the jump-instruction tables. +class JumpInstrTableInfo : public ImmutablePass { +public: + static char ID; + + JumpInstrTableInfo(); + virtual ~JumpInstrTableInfo(); + const char *getPassName() const override { + return "Jump-Instruction Table Info"; + } + + typedef std::pair<Function *, Function *> JumpPair; + typedef DenseMap<FunctionType *, std::vector<JumpPair> > JumpTables; + + /// Inserts an entry in a table, adding the table if it doesn't exist. + void insertEntry(FunctionType *TableFunTy, Function *Target, Function *Jump); + + /// Gets the tables. + const JumpTables &getTables() const { return Tables; } + +private: + JumpTables Tables; +}; +} + +#endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */ diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h new file mode 100644 index 000000000000..70a4df51c1ed --- /dev/null +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -0,0 +1,566 @@ +//===- LazyCallGraph.h - Analysis of a Module's call graph ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Implements a lazy call graph analysis and related passes for the new pass +/// manager. +/// +/// NB: This is *not* a traditional call graph! It is a graph which models both +/// the current calls and potential calls. As a consequence there are many +/// edges in this call graph that do not correspond to a 'call' or 'invoke' +/// instruction. +/// +/// The primary use cases of this graph analysis is to facilitate iterating +/// across the functions of a module in ways that ensure all callees are +/// visited prior to a caller (given any SCC constraints), or vice versa. As +/// such is it particularly well suited to organizing CGSCC optimizations such +/// as inlining, outlining, argument promotion, etc. That is its primary use +/// case and motivates the design. It may not be appropriate for other +/// purposes. The use graph of functions or some other conservative analysis of +/// call instructions may be interesting for optimizations and subsequent +/// analyses which don't work in the context of an overly specified +/// potential-call-edge graph. +/// +/// To understand the specific rules and nature of this call graph analysis, +/// see the documentation of the \c LazyCallGraph below. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LAZY_CALL_GRAPH +#define LLVM_ANALYSIS_LAZY_CALL_GRAPH + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Allocator.h" +#include <iterator> + +namespace llvm { +class ModuleAnalysisManager; +class PreservedAnalyses; +class raw_ostream; + +/// \brief A lazily constructed view of the call graph of a module. +/// +/// With the edges of this graph, the motivating constraint that we are +/// attempting to maintain is that function-local optimization, CGSCC-local +/// optimizations, and optimizations transforming a pair of functions connected +/// by an edge in the graph, do not invalidate a bottom-up traversal of the SCC +/// DAG. That is, no optimizations will delete, remove, or add an edge such +/// that functions already visited in a bottom-up order of the SCC DAG are no +/// longer valid to have visited, or such that functions not yet visited in +/// a bottom-up order of the SCC DAG are not required to have already been +/// visited. +/// +/// Within this constraint, the desire is to minimize the merge points of the +/// SCC DAG. The greater the fanout of the SCC DAG and the fewer merge points +/// in the SCC DAG, the more independence there is in optimizing within it. +/// There is a strong desire to enable parallelization of optimizations over +/// the call graph, and both limited fanout and merge points will (artificially +/// in some cases) limit the scaling of such an effort. +/// +/// To this end, graph represents both direct and any potential resolution to +/// an indirect call edge. Another way to think about it is that it represents +/// both the direct call edges and any direct call edges that might be formed +/// through static optimizations. Specifically, it considers taking the address +/// of a function to be an edge in the call graph because this might be +/// forwarded to become a direct call by some subsequent function-local +/// optimization. The result is that the graph closely follows the use-def +/// edges for functions. Walking "up" the graph can be done by looking at all +/// of the uses of a function. +/// +/// The roots of the call graph are the external functions and functions +/// escaped into global variables. Those functions can be called from outside +/// of the module or via unknowable means in the IR -- we may not be able to +/// form even a potential call edge from a function body which may dynamically +/// load the function and call it. +/// +/// This analysis still requires updates to remain valid after optimizations +/// which could potentially change the set of potential callees. The +/// constraints it operates under only make the traversal order remain valid. +/// +/// The entire analysis must be re-computed if full interprocedural +/// optimizations run at any point. For example, globalopt completely +/// invalidates the information in this analysis. +/// +/// FIXME: This class is named LazyCallGraph in a lame attempt to distinguish +/// it from the existing CallGraph. At some point, it is expected that this +/// will be the only call graph and it will be renamed accordingly. +class LazyCallGraph { +public: + class Node; + class SCC; + typedef SmallVector<PointerUnion<Function *, Node *>, 4> NodeVectorT; + typedef SmallVectorImpl<PointerUnion<Function *, Node *>> NodeVectorImplT; + + /// \brief A lazy iterator used for both the entry nodes and child nodes. + /// + /// When this iterator is dereferenced, if not yet available, a function will + /// be scanned for "calls" or uses of functions and its child information + /// will be constructed. All of these results are accumulated and cached in + /// the graph. + class iterator + : public iterator_adaptor_base<iterator, NodeVectorImplT::iterator, + std::forward_iterator_tag, Node> { + friend class LazyCallGraph; + friend class LazyCallGraph::Node; + + LazyCallGraph *G; + NodeVectorImplT::iterator E; + + // Build the iterator for a specific position in a node list. + iterator(LazyCallGraph &G, NodeVectorImplT::iterator NI, + NodeVectorImplT::iterator E) + : iterator_adaptor_base(NI), G(&G), E(E) { + while (I != E && I->isNull()) + ++I; + } + + public: + iterator() {} + + using iterator_adaptor_base::operator++; + iterator &operator++() { + do { + ++I; + } while (I != E && I->isNull()); + return *this; + } + + reference operator*() const { + if (I->is<Node *>()) + return *I->get<Node *>(); + + Function *F = I->get<Function *>(); + Node &ChildN = G->get(*F); + *I = &ChildN; + return ChildN; + } + }; + + /// \brief A node in the call graph. + /// + /// This represents a single node. It's primary roles are to cache the list of + /// callees, de-duplicate and provide fast testing of whether a function is + /// a callee, and facilitate iteration of child nodes in the graph. + class Node { + friend class LazyCallGraph; + friend class LazyCallGraph::SCC; + + LazyCallGraph *G; + Function &F; + + // We provide for the DFS numbering and Tarjan walk lowlink numbers to be + // stored directly within the node. + int DFSNumber; + int LowLink; + + mutable NodeVectorT Callees; + DenseMap<Function *, size_t> CalleeIndexMap; + + /// \brief Basic constructor implements the scanning of F into Callees and + /// CalleeIndexMap. + Node(LazyCallGraph &G, Function &F); + + /// \brief Internal helper to insert a callee. + void insertEdgeInternal(Function &Callee); + + /// \brief Internal helper to insert a callee. + void insertEdgeInternal(Node &CalleeN); + + /// \brief Internal helper to remove a callee from this node. + void removeEdgeInternal(Function &Callee); + + public: + typedef LazyCallGraph::iterator iterator; + + Function &getFunction() const { + return F; + }; + + iterator begin() const { + return iterator(*G, Callees.begin(), Callees.end()); + } + iterator end() const { return iterator(*G, Callees.end(), Callees.end()); } + + /// Equality is defined as address equality. + bool operator==(const Node &N) const { return this == &N; } + bool operator!=(const Node &N) const { return !operator==(N); } + }; + + /// \brief An SCC of the call graph. + /// + /// This represents a Strongly Connected Component of the call graph as + /// a collection of call graph nodes. While the order of nodes in the SCC is + /// stable, it is not any particular order. + class SCC { + friend class LazyCallGraph; + friend class LazyCallGraph::Node; + + LazyCallGraph *G; + SmallPtrSet<SCC *, 1> ParentSCCs; + SmallVector<Node *, 1> Nodes; + + SCC(LazyCallGraph &G) : G(&G) {} + + void insert(Node &N); + + void + internalDFS(SmallVectorImpl<std::pair<Node *, Node::iterator>> &DFSStack, + SmallVectorImpl<Node *> &PendingSCCStack, Node *N, + SmallVectorImpl<SCC *> &ResultSCCs); + + public: + typedef SmallVectorImpl<Node *>::const_iterator iterator; + typedef pointee_iterator<SmallPtrSet<SCC *, 1>::const_iterator> parent_iterator; + + iterator begin() const { return Nodes.begin(); } + iterator end() const { return Nodes.end(); } + + parent_iterator parent_begin() const { return ParentSCCs.begin(); } + parent_iterator parent_end() const { return ParentSCCs.end(); } + + iterator_range<parent_iterator> parents() const { + return iterator_range<parent_iterator>(parent_begin(), parent_end()); + } + + /// \brief Test if this SCC is a parent of \a C. + bool isParentOf(const SCC &C) const { return C.isChildOf(*this); } + + /// \brief Test if this SCC is an ancestor of \a C. + bool isAncestorOf(const SCC &C) const { return C.isDescendantOf(*this); } + + /// \brief Test if this SCC is a child of \a C. + bool isChildOf(const SCC &C) const { + return ParentSCCs.count(const_cast<SCC *>(&C)); + } + + /// \brief Test if this SCC is a descendant of \a C. + bool isDescendantOf(const SCC &C) const; + + ///@{ + /// \name Mutation API + /// + /// These methods provide the core API for updating the call graph in the + /// presence of a (potentially still in-flight) DFS-found SCCs. + /// + /// Note that these methods sometimes have complex runtimes, so be careful + /// how you call them. + + /// \brief Insert an edge from one node in this SCC to another in this SCC. + /// + /// By the definition of an SCC, this does not change the nature or make-up + /// of any SCCs. + void insertIntraSCCEdge(Node &CallerN, Node &CalleeN); + + /// \brief Insert an edge whose tail is in this SCC and head is in some + /// child SCC. + /// + /// There must be an existing path from the caller to the callee. This + /// operation is inexpensive and does not change the set of SCCs in the + /// graph. + void insertOutgoingEdge(Node &CallerN, Node &CalleeN); + + /// \brief Insert an edge whose tail is in a descendant SCC and head is in + /// this SCC. + /// + /// There must be an existing path from the callee to the caller in this + /// case. NB! This is has the potential to be a very expensive function. It + /// inherently forms a cycle in the prior SCC DAG and we have to merge SCCs + /// to resolve that cycle. But finding all of the SCCs which participate in + /// the cycle can in the worst case require traversing every SCC in the + /// graph. Every attempt is made to avoid that, but passes must still + /// exercise caution calling this routine repeatedly. + /// + /// FIXME: We could possibly optimize this quite a bit for cases where the + /// caller and callee are very nearby in the graph. See comments in the + /// implementation for details, but that use case might impact users. + SmallVector<SCC *, 1> insertIncomingEdge(Node &CallerN, Node &CalleeN); + + /// \brief Remove an edge whose source is in this SCC and target is *not*. + /// + /// This removes an inter-SCC edge. All inter-SCC edges originating from + /// this SCC have been fully explored by any in-flight DFS SCC formation, + /// so this is always safe to call once you have the source SCC. + /// + /// This operation does not change the set of SCCs or the members of the + /// SCCs and so is very inexpensive. It may change the connectivity graph + /// of the SCCs though, so be careful calling this while iterating over + /// them. + void removeInterSCCEdge(Node &CallerN, Node &CalleeN); + + /// \brief Remove an edge which is entirely within this SCC. + /// + /// Both the \a Caller and the \a Callee must be within this SCC. Removing + /// such an edge make break cycles that form this SCC and thus this + /// operation may change the SCC graph significantly. In particular, this + /// operation will re-form new SCCs based on the remaining connectivity of + /// the graph. The following invariants are guaranteed to hold after + /// calling this method: + /// + /// 1) This SCC is still an SCC in the graph. + /// 2) This SCC will be the parent of any new SCCs. Thus, this SCC is + /// preserved as the root of any new SCC directed graph formed. + /// 3) No SCC other than this SCC has its member set changed (this is + /// inherent in the definition of removing such an edge). + /// 4) All of the parent links of the SCC graph will be updated to reflect + /// the new SCC structure. + /// 5) All SCCs formed out of this SCC, excluding this SCC, will be + /// returned in a vector. + /// 6) The order of the SCCs in the vector will be a valid postorder + /// traversal of the new SCCs. + /// + /// These invariants are very important to ensure that we can build + /// optimization pipeliens on top of the CGSCC pass manager which + /// intelligently update the SCC graph without invalidating other parts of + /// the SCC graph. + /// + /// The runtime complexity of this method is, in the worst case, O(V+E) + /// where V is the number of nodes in this SCC and E is the number of edges + /// leaving the nodes in this SCC. Note that E includes both edges within + /// this SCC and edges from this SCC to child SCCs. Some effort has been + /// made to minimize the overhead of common cases such as self-edges and + /// edge removals which result in a spanning tree with no more cycles. + SmallVector<SCC *, 1> removeIntraSCCEdge(Node &CallerN, Node &CalleeN); + + ///@} + }; + + /// \brief A post-order depth-first SCC iterator over the call graph. + /// + /// This iterator triggers the Tarjan DFS-based formation of the SCC DAG for + /// the call graph, walking it lazily in depth-first post-order. That is, it + /// always visits SCCs for a callee prior to visiting the SCC for a caller + /// (when they are in different SCCs). + class postorder_scc_iterator + : public iterator_facade_base<postorder_scc_iterator, + std::forward_iterator_tag, SCC> { + friend class LazyCallGraph; + friend class LazyCallGraph::Node; + + /// \brief Nonce type to select the constructor for the end iterator. + struct IsAtEndT {}; + + LazyCallGraph *G; + SCC *C; + + // Build the begin iterator for a node. + postorder_scc_iterator(LazyCallGraph &G) : G(&G) { + C = G.getNextSCCInPostOrder(); + } + + // Build the end iterator for a node. This is selected purely by overload. + postorder_scc_iterator(LazyCallGraph &G, IsAtEndT /*Nonce*/) + : G(&G), C(nullptr) {} + + public: + bool operator==(const postorder_scc_iterator &Arg) const { + return G == Arg.G && C == Arg.C; + } + + reference operator*() const { return *C; } + + using iterator_facade_base::operator++; + postorder_scc_iterator &operator++() { + C = G->getNextSCCInPostOrder(); + return *this; + } + }; + + /// \brief Construct a graph for the given module. + /// + /// This sets up the graph and computes all of the entry points of the graph. + /// No function definitions are scanned until their nodes in the graph are + /// requested during traversal. + LazyCallGraph(Module &M); + + LazyCallGraph(LazyCallGraph &&G); + LazyCallGraph &operator=(LazyCallGraph &&RHS); + + iterator begin() { + return iterator(*this, EntryNodes.begin(), EntryNodes.end()); + } + iterator end() { return iterator(*this, EntryNodes.end(), EntryNodes.end()); } + + postorder_scc_iterator postorder_scc_begin() { + return postorder_scc_iterator(*this); + } + postorder_scc_iterator postorder_scc_end() { + return postorder_scc_iterator(*this, postorder_scc_iterator::IsAtEndT()); + } + + iterator_range<postorder_scc_iterator> postorder_sccs() { + return iterator_range<postorder_scc_iterator>(postorder_scc_begin(), + postorder_scc_end()); + } + + /// \brief Lookup a function in the graph which has already been scanned and + /// added. + Node *lookup(const Function &F) const { return NodeMap.lookup(&F); } + + /// \brief Lookup a function's SCC in the graph. + /// + /// \returns null if the function hasn't been assigned an SCC via the SCC + /// iterator walk. + SCC *lookupSCC(Node &N) const { return SCCMap.lookup(&N); } + + /// \brief Get a graph node for a given function, scanning it to populate the + /// graph data as necessary. + Node &get(Function &F) { + Node *&N = NodeMap[&F]; + if (N) + return *N; + + return insertInto(F, N); + } + + ///@{ + /// \name Pre-SCC Mutation API + /// + /// These methods are only valid to call prior to forming any SCCs for this + /// call graph. They can be used to update the core node-graph during + /// a node-based inorder traversal that precedes any SCC-based traversal. + /// + /// Once you begin manipulating a call graph's SCCs, you must perform all + /// mutation of the graph via the SCC methods. + + /// \brief Update the call graph after inserting a new edge. + void insertEdge(Node &Caller, Function &Callee); + + /// \brief Update the call graph after inserting a new edge. + void insertEdge(Function &Caller, Function &Callee) { + return insertEdge(get(Caller), Callee); + } + + /// \brief Update the call graph after deleting an edge. + void removeEdge(Node &Caller, Function &Callee); + + /// \brief Update the call graph after deleting an edge. + void removeEdge(Function &Caller, Function &Callee) { + return removeEdge(get(Caller), Callee); + } + + ///@} + +private: + /// \brief Allocator that holds all the call graph nodes. + SpecificBumpPtrAllocator<Node> BPA; + + /// \brief Maps function->node for fast lookup. + DenseMap<const Function *, Node *> NodeMap; + + /// \brief The entry nodes to the graph. + /// + /// These nodes are reachable through "external" means. Put another way, they + /// escape at the module scope. + NodeVectorT EntryNodes; + + /// \brief Map of the entry nodes in the graph to their indices in + /// \c EntryNodes. + DenseMap<Function *, size_t> EntryIndexMap; + + /// \brief Allocator that holds all the call graph SCCs. + SpecificBumpPtrAllocator<SCC> SCCBPA; + + /// \brief Maps Function -> SCC for fast lookup. + DenseMap<Node *, SCC *> SCCMap; + + /// \brief The leaf SCCs of the graph. + /// + /// These are all of the SCCs which have no children. + SmallVector<SCC *, 4> LeafSCCs; + + /// \brief Stack of nodes in the DFS walk. + SmallVector<std::pair<Node *, iterator>, 4> DFSStack; + + /// \brief Set of entry nodes not-yet-processed into SCCs. + SmallVector<Function *, 4> SCCEntryNodes; + + /// \brief Stack of nodes the DFS has walked but not yet put into a SCC. + SmallVector<Node *, 4> PendingSCCStack; + + /// \brief Counter for the next DFS number to assign. + int NextDFSNumber; + + /// \brief Helper to insert a new function, with an already looked-up entry in + /// the NodeMap. + Node &insertInto(Function &F, Node *&MappedN); + + /// \brief Helper to update pointers back to the graph object during moves. + void updateGraphPtrs(); + + /// \brief Helper to form a new SCC out of the top of a DFSStack-like + /// structure. + SCC *formSCC(Node *RootN, SmallVectorImpl<Node *> &NodeStack); + + /// \brief Retrieve the next node in the post-order SCC walk of the call graph. + SCC *getNextSCCInPostOrder(); +}; + +// Provide GraphTraits specializations for call graphs. +template <> struct GraphTraits<LazyCallGraph::Node *> { + typedef LazyCallGraph::Node NodeType; + typedef LazyCallGraph::iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { return N; } + static ChildIteratorType child_begin(NodeType *N) { return N->begin(); } + static ChildIteratorType child_end(NodeType *N) { return N->end(); } +}; +template <> struct GraphTraits<LazyCallGraph *> { + typedef LazyCallGraph::Node NodeType; + typedef LazyCallGraph::iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { return N; } + static ChildIteratorType child_begin(NodeType *N) { return N->begin(); } + static ChildIteratorType child_end(NodeType *N) { return N->end(); } +}; + +/// \brief An analysis pass which computes the call graph for a module. +class LazyCallGraphAnalysis { +public: + /// \brief Inform generic clients of the result type. + typedef LazyCallGraph Result; + + static void *ID() { return (void *)&PassID; } + + /// \brief Compute the \c LazyCallGraph for a 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); } + +private: + static char PassID; +}; + +/// \brief A pass which prints the call graph to a \c raw_ostream. +/// +/// This is primarily useful for testing the analysis. +class LazyCallGraphPrinterPass { + raw_ostream &OS; + +public: + explicit LazyCallGraphPrinterPass(raw_ostream &OS); + + PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM); + + static StringRef name() { return "LazyCallGraphPrinterPass"; } +}; + +} + +#endif diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 197e94e5fd32..2fe7386e7302 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -26,17 +26,17 @@ namespace llvm { /// LazyValueInfo - This pass computes, caches, and vends lazy value constraint /// information. class LazyValueInfo : public FunctionPass { - class DataLayout *TD; + const DataLayout *DL; class TargetLibraryInfo *TLI; void *PImpl; LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION; void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION; public: static char ID; - LazyValueInfo() : FunctionPass(ID), PImpl(0) { + LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) { initializeLazyValueInfoPass(*PassRegistry::getPassRegistry()); } - ~LazyValueInfo() { assert(PImpl == 0 && "releaseMemory not called"); } + ~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); } /// Tristate - This is used to return true/false/dunno results. enum Tristate { @@ -69,10 +69,10 @@ public: void eraseBlock(BasicBlock *BB); // Implementation boilerplate. - - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); - virtual bool runOnFunction(Function &F); + + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() override; + bool runOnFunction(Function &F) override; }; } // end namespace llvm diff --git a/include/llvm/Analysis/LibCallAliasAnalysis.h b/include/llvm/Analysis/LibCallAliasAnalysis.h index c01b210acf4b..4c03c922447c 100644 --- a/include/llvm/Analysis/LibCallAliasAnalysis.h +++ b/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -27,7 +27,7 @@ namespace llvm { LibCallInfo *LCI; - explicit LibCallAliasAnalysis(LibCallInfo *LC = 0) + explicit LibCallAliasAnalysis(LibCallInfo *LC = nullptr) : FunctionPass(ID), LCI(LC) { initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry()); } @@ -38,17 +38,17 @@ namespace llvm { ~LibCallAliasAnalysis(); ModRefResult getModRefInfo(ImmutableCallSite CS, - const Location &Loc); - + const Location &Loc) override; + ModRefResult getModRefInfo(ImmutableCallSite CS1, - ImmutableCallSite CS2) { + ImmutableCallSite CS2) override { // TODO: Could compare two direct calls against each other if we cared to. return AliasAnalysis::getModRefInfo(CS1, CS2); } - - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - - virtual bool runOnFunction(Function &F) { + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnFunction(Function &F) override { InitializeAliasAnalysis(this); // set up super class return false; } @@ -57,7 +57,7 @@ namespace llvm { /// an analysis interface through multiple inheritance. If needed, it /// should override this to adjust the this pointer as needed for the /// specified pass info. - virtual void *getAdjustedAnalysisPointer(const void *PI) { + void *getAdjustedAnalysisPointer(const void *PI) override { if (PI == &AliasAnalysis::ID) return (AliasAnalysis*)this; return this; diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h index f5a9e96cbdd0..8bd747f03970 100644 --- a/include/llvm/Analysis/LibCallSemantics.h +++ b/include/llvm/Analysis/LibCallSemantics.h @@ -27,7 +27,7 @@ namespace llvm { /// standard libm functions. The location that they may be interested in is /// an abstract location that represents errno for the current target. In /// this case, a location for errno is anything such that the predicate - /// returns true. On Mac OS/X, this predicate would return true if the + /// returns true. On Mac OS X, this predicate would return true if the /// pointer is the result of a call to "__error()". /// /// Locations can also be defined in a constant-sensitive way. For example, @@ -130,7 +130,7 @@ namespace llvm { mutable const LibCallLocationInfo *Locations; mutable unsigned NumLocations; public: - LibCallInfo() : Impl(0), Locations(0), NumLocations(0) {} + LibCallInfo() : Impl(nullptr), Locations(nullptr), NumLocations(0) {} virtual ~LibCallInfo(); //===------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h index ebcb76254111..25c59288f34b 100644 --- a/include/llvm/Analysis/Loads.h +++ b/include/llvm/Analysis/Loads.h @@ -27,7 +27,8 @@ class MDNode; /// specified pointer, we do a quick local scan of the basic block containing /// ScanFrom, to determine if the address is already accessed. bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, - unsigned Align, const DataLayout *TD = 0); + unsigned Align, + const DataLayout *TD = nullptr); /// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at /// the instruction before ScanFrom) checking to see if we have the value at @@ -49,8 +50,8 @@ bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan = 6, - AliasAnalysis *AA = 0, - MDNode **TBAATag = 0); + AliasAnalysis *AA = nullptr, + MDNode **TBAATag = nullptr); } diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 62f5acad5668..bef03e91bbbd 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -33,8 +33,10 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/Dominators.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/Instruction.h" #include "llvm/Pass.h" #include <algorithm> @@ -53,6 +55,7 @@ class Loop; class MDNode; class PHINode; class raw_ostream; +template<class N> class DominatorTreeBase; template<class N, class M> class LoopInfoBase; template<class N, class M> class LoopBase; @@ -76,7 +79,7 @@ class LoopBase { operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION; public: /// Loop ctor - This creates an empty loop. - LoopBase() : ParentLoop(0) {} + LoopBase() : ParentLoop(nullptr) {} ~LoopBase() { for (size_t i = 0, e = SubLoops.size(); i != e; ++i) delete SubLoops[i]; @@ -103,7 +106,7 @@ public: /// bool contains(const LoopT *L) const { if (L == this) return true; - if (L == 0) return false; + if (!L) return false; return contains(L->getParentLoop()); } @@ -228,6 +231,18 @@ public: /// A latch block is a block that contains a branch back to the header. BlockT *getLoopLatch() const; + /// getLoopLatches - Return all loop latch blocks of this loop. A latch block + /// is a block that contains a branch back to the header. + void getLoopLatches(SmallVectorImpl<BlockT *> &LoopLatches) const { + BlockT *H = getHeader(); + typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; + for (typename InvBlockTraits::ChildIteratorType I = + InvBlockTraits::child_begin(H), + E = InvBlockTraits::child_end(H); I != E; ++I) + if (contains(*I)) + LoopLatches.push_back(*I); + } + //===--------------------------------------------------------------------===// // APIs for updating loop information after changing the CFG // @@ -250,7 +265,7 @@ public: /// updates the loop depth of the new child. /// void addChildLoop(LoopT *NewChild) { - assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!"); + assert(!NewChild->ParentLoop && "NewChild already has a parent!"); NewChild->ParentLoop = static_cast<LoopT *>(this); SubLoops.push_back(NewChild); } @@ -263,7 +278,7 @@ public: LoopT *Child = *I; assert(Child->ParentLoop == this && "Child is not a child of this loop!"); SubLoops.erase(SubLoops.begin()+(I-begin())); - Child->ParentLoop = 0; + Child->ParentLoop = nullptr; return Child; } @@ -318,7 +333,7 @@ public: protected: friend class LoopInfoBase<BlockT, LoopT>; - explicit LoopBase(BlockT *BB) : ParentLoop(0) { + explicit LoopBase(BlockT *BB) : ParentLoop(nullptr) { Blocks.push_back(BB); DenseBlockSet.insert(BB); } @@ -357,7 +372,7 @@ public: /// If null, the terminator of the loop preheader is used. /// bool makeLoopInvariant(Value *V, bool &Changed, - Instruction *InsertPt = 0) const; + Instruction *InsertPt = nullptr) const; /// makeLoopInvariant - If the given instruction is inside of the /// loop and it can be hoisted, do so to make it trivially loop-invariant. @@ -369,7 +384,7 @@ public: /// If null, the terminator of the loop preheader is used. /// bool makeLoopInvariant(Instruction *I, bool &Changed, - Instruction *InsertPt = 0) const; + Instruction *InsertPt = nullptr) const; /// getCanonicalInductionVariable - Check to see if the loop has a canonical /// induction variable: an integer recurrence that starts at 0 and increments @@ -438,6 +453,31 @@ public: void dump() const; + /// \brief Return the debug location of the start of this loop. + /// This looks for a BB terminating instruction with a known debug + /// location by looking at the preheader and header blocks. If it + /// cannot find a terminating instruction with location information, + /// it returns an unknown location. + DebugLoc getStartLoc() const { + DebugLoc StartLoc; + BasicBlock *HeadBB; + + // Try the pre-header first. + if ((HeadBB = getLoopPreheader()) != nullptr) { + StartLoc = HeadBB->getTerminator()->getDebugLoc(); + if (!StartLoc.isUnknown()) + return StartLoc; + } + + // If we have no pre-header or there are no instructions with debug + // info in it, try the header. + HeadBB = getHeader(); + if (HeadBB) + StartLoc = HeadBB->getTerminator()->getDebugLoc(); + + return StartLoc; + } + private: friend class LoopInfoBase<BasicBlock, Loop>; explicit Loop(BasicBlock *BB) : LoopBase<BasicBlock, Loop>(BB) {} @@ -516,7 +556,7 @@ public: LoopT *removeLoop(iterator I) { assert(I != end() && "Cannot remove end iterator!"); LoopT *L = *I; - assert(L->getParentLoop() == 0 && "Not a top-level loop!"); + assert(!L->getParentLoop() && "Not a top-level loop!"); TopLevelLoops.erase(TopLevelLoops.begin() + (I-begin())); return L; } @@ -540,14 +580,14 @@ public: std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); assert(I != TopLevelLoops.end() && "Old loop not at top level!"); *I = NewLoop; - assert(NewLoop->ParentLoop == 0 && OldLoop->ParentLoop == 0 && + assert(!NewLoop->ParentLoop && !OldLoop->ParentLoop && "Loops already embedded into a subloop!"); } /// addTopLevelLoop - This adds the specified loop to the collection of /// top-level loops. void addTopLevelLoop(LoopT *New) { - assert(New->getParentLoop() == 0 && "Loop already in subloop!"); + assert(!New->getParentLoop() && "Loop already in subloop!"); TopLevelLoops.push_back(New); } @@ -568,7 +608,7 @@ public: static bool isNotAlreadyContainedIn(const LoopT *SubLoop, const LoopT *ParentLoop) { - if (SubLoop == 0) return true; + if (!SubLoop) return true; if (SubLoop == ParentLoop) return false; return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop); } @@ -639,15 +679,15 @@ public: /// runOnFunction - Calculate the natural loop information. /// - virtual bool runOnFunction(Function &F); + bool runOnFunction(Function &F) override; - virtual void verifyAnalysis() const; + void verifyAnalysis() const override; - virtual void releaseMemory() { LI.releaseMemory(); } + void releaseMemory() override { LI.releaseMemory(); } - virtual void print(raw_ostream &O, const Module* M = 0) const; + void print(raw_ostream &O, const Module* M = nullptr) const override; - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; /// removeLoop - This removes the specified top-level loop from this loop info /// object. The loop is not deleted, as it will presumably be inserted into diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index c98cb589108b..948be0f5ee1e 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -15,9 +15,11 @@ #ifndef LLVM_ANALYSIS_LOOPINFOIMPL_H #define LLVM_ANALYSIS_LOOPINFOIMPL_H +#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/Dominators.h" namespace llvm { @@ -51,7 +53,7 @@ BlockT *LoopBase<BlockT, LoopT>::getExitingBlock() const { getExitingBlocks(ExitingBlocks); if (ExitingBlocks.size() == 1) return ExitingBlocks[0]; - return 0; + return nullptr; } /// getExitBlocks - Return all of the successor blocks of this loop. These @@ -78,7 +80,7 @@ BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const { getExitBlocks(ExitBlocks); if (ExitBlocks.size() == 1) return ExitBlocks[0]; - return 0; + return nullptr; } /// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). @@ -106,14 +108,14 @@ template<class BlockT, class LoopT> BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const { // Keep track of nodes outside the loop branching to the header... BlockT *Out = getLoopPredecessor(); - if (!Out) return 0; + if (!Out) return nullptr; // Make sure there is only one exit out of the preheader. typedef GraphTraits<BlockT*> BlockTraits; typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out); ++SI; if (SI != BlockTraits::child_end(Out)) - return 0; // Multiple exits from the block, must not be a preheader. + return nullptr; // Multiple exits from the block, must not be a preheader. // The predecessor has exactly one successor, so it is a preheader. return Out; @@ -127,7 +129,7 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const { template<class BlockT, class LoopT> BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const { // Keep track of nodes outside the loop branching to the header... - BlockT *Out = 0; + BlockT *Out = nullptr; // Loop over the predecessors of the header node... BlockT *Header = getHeader(); @@ -138,7 +140,7 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const { typename InvBlockTraits::NodeType *N = *PI; if (!contains(N)) { // If the block is not in the loop... if (Out && Out != N) - return 0; // Multiple predecessors outside the loop + return nullptr; // Multiple predecessors outside the loop Out = N; } } @@ -158,11 +160,11 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopLatch() const { InvBlockTraits::child_begin(Header); typename InvBlockTraits::ChildIteratorType PE = InvBlockTraits::child_end(Header); - BlockT *Latch = 0; + BlockT *Latch = nullptr; for (; PI != PE; ++PI) { typename InvBlockTraits::NodeType *N = *PI; if (contains(N)) { - if (Latch) return 0; + if (Latch) return nullptr; Latch = N; } } @@ -186,7 +188,7 @@ addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LIB) { assert((Blocks.empty() || LIB[getHeader()] == this) && "Incorrect LI specified for this loop!"); assert(NewBB && "Cannot add a null basic block to the loop!"); - assert(LIB[NewBB] == 0 && "BasicBlock already in the loop!"); + assert(!LIB[NewBB] && "BasicBlock already in the loop!"); LoopT *L = static_cast<LoopT *>(this); @@ -208,12 +210,12 @@ template<class BlockT, class LoopT> void LoopBase<BlockT, LoopT>:: replaceChildLoopWith(LoopT *OldChild, LoopT *NewChild) { assert(OldChild->ParentLoop == this && "This loop is already broken!"); - assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!"); + assert(!NewChild->ParentLoop && "NewChild already has a parent!"); typename std::vector<LoopT *>::iterator I = std::find(SubLoops.begin(), SubLoops.end(), OldChild); assert(I != SubLoops.end() && "OldChild not in loop!"); *I = NewChild; - OldChild->ParentLoop = 0; + OldChild->ParentLoop = nullptr; NewChild->ParentLoop = static_cast<LoopT *>(this); } @@ -268,11 +270,10 @@ void LoopBase<BlockT, LoopT>::verifyLoop() const { // though it is permitted if the predecessor is not itself actually // reachable. BlockT *EntryBB = BB->getParent()->begin(); - for (df_iterator<BlockT *> NI = df_begin(EntryBB), - NE = df_end(EntryBB); NI != NE; ++NI) - for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i) - assert(*NI != OutsideLoopPreds[i] && - "Loop has multiple entry points!"); + for (BlockT *CB : depth_first(EntryBB)) + for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i) + assert(CB != OutsideLoopPreds[i] && + "Loop has multiple entry points!"); } assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!"); assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!"); @@ -322,7 +323,7 @@ void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, unsigned Depth) const { for (unsigned i = 0; i < getBlocks().size(); ++i) { if (i) OS << ","; BlockT *BB = getBlocks()[i]; - WriteAsOperand(OS, BB, false); + BB->printAsOperand(OS, false); if (BB == getHeader()) OS << "<header>"; if (BB == getLoopLatch()) OS << "<latch>"; if (isLoopExiting(BB)) OS << "<exiting>"; diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h index 5926610d1aa6..726e28636ac6 100644 --- a/include/llvm/Analysis/LoopPass.h +++ b/include/llvm/Analysis/LoopPass.h @@ -32,7 +32,8 @@ public: /// getPrinterPass - Get a pass to print the function corresponding /// to a Loop. - Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const override; // runOnLoop - This method should be implemented by the subclass to perform // whatever action is necessary for the specified Loop. @@ -56,14 +57,13 @@ public: // LPPassManager passes. In such case, pop LPPassManager from the // stack. This will force assignPassManager() to create new // LPPassManger as expected. - void preparePassManager(PMStack &PMS); + void preparePassManager(PMStack &PMS) override; /// Assign pass manager to manage this pass - virtual void assignPassManager(PMStack &PMS, - PassManagerType PMT); + void assignPassManager(PMStack &PMS, PassManagerType PMT) override; /// Return what kind of Pass Manager can manage this pass. - virtual PassManagerType getPotentialPassManagerType() const { + PassManagerType getPotentialPassManagerType() const override { return PMT_LoopPassManager; } @@ -81,6 +81,11 @@ public: /// deleteAnalysisValue - Delete analysis info associated with value V. virtual void deleteAnalysisValue(Value *V, Loop *L) {} + +protected: + /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone + /// and most transformation passes should skip it. + bool skipOptnoneFunction(const Loop *L) const; }; class LPPassManager : public FunctionPass, public PMDataManager { @@ -90,21 +95,21 @@ public: /// run - Execute all of the passes scheduled for execution. Keep track of /// whether any of the passes modifies the module, and if so, return true. - bool runOnFunction(Function &F); + bool runOnFunction(Function &F) override; /// Pass Manager itself does not invalidate any analysis info. // LPPassManager needs LoopInfo. - void getAnalysisUsage(AnalysisUsage &Info) const; + void getAnalysisUsage(AnalysisUsage &Info) const override; - virtual const char *getPassName() const { + const char *getPassName() const override { return "Loop Pass Manager"; } - virtual PMDataManager *getAsPMDataManager() { return this; } - virtual Pass *getAsPass() { return this; } + PMDataManager *getAsPMDataManager() override { return this; } + Pass *getAsPass() override { return this; } /// Print passes managed by this manager - void dumpPassStructure(unsigned Offset); + void dumpPassStructure(unsigned Offset) override; LoopPass *getContainedPass(unsigned N) { assert(N < PassVector.size() && "Pass number out of range!"); @@ -112,7 +117,7 @@ public: return LP; } - virtual PassManagerType getPassManagerType() const { + PassManagerType getPassManagerType() const override { return PMT_LoopPassManager; } diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index 91224ad94ac2..d414680b519d 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -17,12 +17,12 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/TargetFolder.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/IR/Operator.h" -#include "llvm/InstVisitor.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/TargetFolder.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { class CallInst; @@ -190,6 +190,8 @@ public: return knownSize(SizeOffset) && knownOffset(SizeOffset); } + // These are "private", except they can't actually be made private. Only + // compute() should be used by external users. SizeOffsetType visitAllocaInst(AllocaInst &I); SizeOffsetType visitArgument(Argument &A); SizeOffsetType visitCallSite(CallSite CS); @@ -231,7 +233,7 @@ class ObjectSizeOffsetEvaluator bool RoundToAlign; SizeOffsetEvalType unknown() { - return std::make_pair((Value*)0, (Value*)0); + return std::make_pair(nullptr, nullptr); } SizeOffsetEvalType compute_(Value *V); @@ -256,6 +258,7 @@ public: return knownSize(SizeOffset) && knownOffset(SizeOffset); } + // The individual instruction visitors should be treated as private. SizeOffsetEvalType visitAllocaInst(AllocaInst &I); SizeOffsetEvalType visitCallSite(CallSite CS); SizeOffsetEvalType visitExtractElementInst(ExtractElementInst &I); diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 47afd1b77b0e..1c4441bea670 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -15,13 +15,12 @@ #define LLVM_ANALYSIS_MEMORYDEPENDENCEANALYSIS_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { class Function; @@ -98,7 +97,7 @@ namespace llvm { PairTy Value; explicit MemDepResult(PairTy V) : Value(V) {} public: - MemDepResult() : Value(0, Invalid) {} + MemDepResult() : Value(nullptr, Invalid) {} /// get methods: These are static ctor methods for creating various /// MemDepResult kinds. @@ -156,7 +155,7 @@ namespace llvm { /// getInst() - If this is a normal dependency, return the instruction that /// is depended on. Otherwise, return null. Instruction *getInst() const { - if (Value.getInt() == Other) return NULL; + if (Value.getInt() == Other) return nullptr; return Value.getPointer(); } @@ -286,7 +285,8 @@ namespace llvm { /// pointer. May be null if there are no tags or conflicting tags. const MDNode *TBAATag; - NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize), TBAATag(0) {} + NonLocalPointerInfo() + : Size(AliasAnalysis::UnknownSize), TBAATag(nullptr) {} }; /// CachedNonLocalPointerInfo - This map stores the cached results of doing @@ -323,24 +323,25 @@ namespace llvm { /// Current AA implementation, just a cache. AliasAnalysis *AA; - DataLayout *TD; + const DataLayout *DL; DominatorTree *DT; - OwningPtr<PredIteratorCache> PredCache; + std::unique_ptr<PredIteratorCache> PredCache; + public: MemoryDependenceAnalysis(); ~MemoryDependenceAnalysis(); static char ID; /// Pass Implementation stuff. This doesn't do any analysis eagerly. - bool runOnFunction(Function &); + bool runOnFunction(Function &) override; /// Clean up memory in between runs - void releaseMemory(); + void releaseMemory() override; /// getAnalysisUsage - Does not modify anything. It uses Value Numbering /// and Alias Analysis. /// - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; /// getDependency - Return the instruction on which a memory operation /// depends. See the class comment for more details. It is illegal to call @@ -401,7 +402,7 @@ namespace llvm { bool isLoad, BasicBlock::iterator ScanIt, BasicBlock *BB, - Instruction *QueryInst = 0); + Instruction *QueryInst = nullptr); /// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that @@ -415,7 +416,7 @@ namespace llvm { int64_t MemLocOffs, unsigned MemLocSize, const LoadInst *LI, - const DataLayout &TD); + const DataLayout &DL); private: MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index d7a3dd889a1b..69f59071f94f 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -36,8 +36,8 @@ class PHITransAddr { /// Addr - The actual address we're analyzing. Value *Addr; - /// TD - The target data we are playing with if known, otherwise null. - const DataLayout *TD; + /// The DataLayout we are playing with if known, otherwise null. + const DataLayout *DL; /// TLI - The target library info if known, otherwise null. const TargetLibraryInfo *TLI; @@ -45,7 +45,8 @@ class PHITransAddr { /// InstInputs - The inputs for our symbolic address. SmallVector<Instruction*, 4> InstInputs; public: - PHITransAddr(Value *addr, const DataLayout *td) : Addr(addr), TD(td), TLI(0) { + PHITransAddr(Value *addr, const DataLayout *DL) + : Addr(addr), DL(DL), TLI(nullptr) { // If the address is an instruction, the whole thing is considered an input. if (Instruction *I = dyn_cast<Instruction>(Addr)) InstInputs.push_back(I); diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index a5d098eb0d9c..fd65ae5ca5b2 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -95,27 +95,6 @@ namespace llvm { //===--------------------------------------------------------------------===// // - // createDSAAPass - This pass implements simple context sensitive alias - // analysis. - // - ModulePass *createDSAAPass(); - - //===--------------------------------------------------------------------===// - // - // createDSOptPass - This pass uses DSA to do a series of simple - // optimizations. - // - ModulePass *createDSOptPass(); - - //===--------------------------------------------------------------------===// - // - // createSteensgaardPass - This pass uses the data structure graphs to do a - // simple context insensitive alias analysis. - // - ModulePass *createSteensgaardPass(); - - //===--------------------------------------------------------------------===// - // /// createLazyValueInfoPass - This creates an instance of the LazyValueInfo /// pass. FunctionPass *createLazyValueInfoPass(); @@ -163,6 +142,10 @@ namespace llvm { // information and prints it with -analyze. // FunctionPass *createMemDepPrinter(); + + // createJumpInstrTableInfoPass - This creates a pass that stores information + // about the jump tables created by JumpInstrTables + ImmutablePass *createJumpInstrTableInfoPass(); } #endif diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index 88ebab4edecf..d330755a0871 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -14,7 +14,7 @@ #ifndef LLVM_ANALYSIS_POSTDOMINATORS_H #define LLVM_ANALYSIS_POSTDOMINATORS_H -#include "llvm/Analysis/Dominators.h" +#include "llvm/IR/Dominators.h" namespace llvm { @@ -32,9 +32,9 @@ struct PostDominatorTree : public FunctionPass { ~PostDominatorTree(); - virtual bool runOnFunction(Function &F); + bool runOnFunction(Function &F) override; - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } @@ -79,11 +79,17 @@ struct PostDominatorTree : public FunctionPass { return DT->findNearestCommonDominator(A, B); } - virtual void releaseMemory() { + /// Get all nodes post-dominated by R, including R itself. + void getDescendants(BasicBlock *R, + SmallVectorImpl<BasicBlock *> &Result) const { + DT->getDescendants(R, Result); + } + + void releaseMemory() override { DT->releaseMemory(); } - virtual void print(raw_ostream &OS, const Module*) const; + void print(raw_ostream &OS, const Module*) const override; }; FunctionPass* createPostDomTree(); diff --git a/include/llvm/Analysis/PtrUseVisitor.h b/include/llvm/Analysis/PtrUseVisitor.h index 1802fe88e356..6e61fc3be384 100644 --- a/include/llvm/Analysis/PtrUseVisitor.h +++ b/include/llvm/Analysis/PtrUseVisitor.h @@ -26,8 +26,8 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/InstVisitor.h" #include "llvm/IR/IntrinsicInst.h" -#include "llvm/InstVisitor.h" #include "llvm/Support/Compiler.h" namespace llvm { @@ -48,13 +48,13 @@ public: /// analysis and whether the visit completed or aborted early. class PtrInfo { public: - PtrInfo() : AbortedInfo(0, false), EscapedInfo(0, false) {} + PtrInfo() : AbortedInfo(nullptr, false), EscapedInfo(nullptr, false) {} /// \brief Reset the pointer info, clearing all state. void reset() { - AbortedInfo.setPointer(0); + AbortedInfo.setPointer(nullptr); AbortedInfo.setInt(false); - EscapedInfo.setPointer(0); + EscapedInfo.setPointer(nullptr); EscapedInfo.setInt(false); } @@ -76,14 +76,14 @@ public: /// \brief Mark the visit as aborted. Intended for use in a void return. /// \param I The instruction which caused the visit to abort, if available. - void setAborted(Instruction *I = 0) { + void setAborted(Instruction *I = nullptr) { AbortedInfo.setInt(true); AbortedInfo.setPointer(I); } /// \brief Mark the pointer as escaped. Intended for use in a void return. /// \param I The instruction which escapes the pointer, if available. - void setEscaped(Instruction *I = 0) { + void setEscaped(Instruction *I = nullptr) { EscapedInfo.setInt(true); EscapedInfo.setPointer(I); } @@ -92,7 +92,7 @@ public: /// for use in a void return. /// \param I The instruction which both escapes the pointer and aborts the /// visit, if available. - void setEscapedAndAborted(Instruction *I = 0) { + void setEscapedAndAborted(Instruction *I = nullptr) { setEscaped(I); setAborted(I); } @@ -219,7 +219,7 @@ public: U = ToVisit.UseAndIsOffsetKnown.getPointer(); IsOffsetKnown = ToVisit.UseAndIsOffsetKnown.getInt(); if (IsOffsetKnown) - Offset = llvm_move(ToVisit.Offset); + Offset = std::move(ToVisit.Offset); Instruction *I = cast<Instruction>(U->getUser()); static_cast<DerivedT*>(this)->visit(I); diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index e87319516cd1..49c88fd5caeb 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -22,24 +22,77 @@ // itself is not, but in practice runtime seems to be in the order of magnitude // of dominance tree calculation. // +// WARNING: LLVM is generally very concerned about compile time such that +// the use of additional analysis passes in the default +// optimization sequence is avoided as much as possible. +// Specifically, if you do not need the RegionInfo, but dominance +// information could be sufficient please base your work only on +// the dominator tree. Most passes maintain it, such that using +// it has often near zero cost. In contrast RegionInfo is by +// default not available, is not maintained by existing +// transformations and there is no intention to do so. +// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_REGIONINFO_H #define LLVM_ANALYSIS_REGIONINFO_H +#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/Analysis/DominanceFrontier.h" -#include "llvm/Analysis/PostDominators.h" -#include "llvm/Support/Allocator.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/Dominators.h" #include <map> +#include <memory> +#include <set> namespace llvm { -class Region; -class RegionInfo; -class raw_ostream; +// RegionTraits - Class to be specialized for different users of RegionInfo +// (i.e. BasicBlocks or MachineBasicBlocks). This is only to avoid needing to +// pass around an unreasonable number of template parameters. +template <class FuncT_> +struct RegionTraits { + // FuncT + // BlockT + // RegionT + // RegionNodeT + // RegionInfoT + typedef typename FuncT_::UnknownRegionTypeError BrokenT; +}; + +class DominatorTree; +class DominanceFrontier; class Loop; class LoopInfo; +struct PostDominatorTree; +class raw_ostream; +class Region; +template <class RegionTr> +class RegionBase; +class RegionNode; +class RegionInfo; +template <class RegionTr> +class RegionInfoBase; + +template <> +struct RegionTraits<Function> { + typedef Function FuncT; + typedef BasicBlock BlockT; + typedef Region RegionT; + typedef RegionNode RegionNodeT; + typedef RegionInfo RegionInfoT; + typedef DominatorTree DomTreeT; + typedef DomTreeNode DomTreeNodeT; + typedef DominanceFrontier DomFrontierT; + typedef PostDominatorTree PostDomTreeT; + typedef Instruction InstT; + typedef Loop LoopT; + typedef LoopInfo LoopInfoT; + + static unsigned getNumSuccessors(BasicBlock *BB) { + return BB->getTerminator()->getNumSuccessors(); + } +}; /// @brief Marker class to iterate over the elements of a Region in flat mode. /// @@ -53,11 +106,18 @@ class FlatIt {}; /// @brief A RegionNode represents a subregion or a BasicBlock that is part of a /// Region. -class RegionNode { - RegionNode(const RegionNode &) LLVM_DELETED_FUNCTION; - const RegionNode &operator=(const RegionNode &) LLVM_DELETED_FUNCTION; +template <class Tr> +class RegionNodeBase { + friend class RegionBase<Tr>; + +public: + typedef typename Tr::BlockT BlockT; + typedef typename Tr::RegionT RegionT; + +private: + RegionNodeBase(const RegionNodeBase &) LLVM_DELETED_FUNCTION; + const RegionNodeBase &operator=(const RegionNodeBase &) LLVM_DELETED_FUNCTION; -protected: /// This is the entry basic block that starts this region node. If this is a /// BasicBlock RegionNode, then entry is just the basic block, that this /// RegionNode represents. Otherwise it is the entry of this (Sub)RegionNode. @@ -68,13 +128,13 @@ protected: /// The node can hold either a Region or a BasicBlock. /// Use one bit to save, if this RegionNode is a subregion or BasicBlock /// RegionNode. - PointerIntPair<BasicBlock*, 1, bool> entry; + PointerIntPair<BlockT *, 1, bool> entry; /// @brief The parent Region of this RegionNode. /// @see getParent() - Region* parent; + RegionT *parent; -public: +protected: /// @brief Create a RegionNode. /// /// @param Parent The parent of this RegionNode. @@ -83,9 +143,11 @@ public: /// BasicBlock itself. If it represents a subregion, this /// is the entry BasicBlock of the subregion. /// @param isSubRegion If this RegionNode represents a SubRegion. - inline RegionNode(Region* Parent, BasicBlock* Entry, bool isSubRegion = 0) - : entry(Entry, isSubRegion), parent(Parent) {} + inline RegionNodeBase(RegionT *Parent, BlockT *Entry, + bool isSubRegion = false) + : entry(Entry, isSubRegion), parent(Parent) {} +public: /// @brief Get the parent Region of this RegionNode. /// /// The parent Region is the Region this RegionNode belongs to. If for @@ -94,7 +156,7 @@ public: /// pointing to the Region this RegionNode belongs to. /// /// @return Get the parent Region of this RegionNode. - inline Region* getParent() const { return parent; } + inline RegionT *getParent() const { return parent; } /// @brief Get the entry BasicBlock of this RegionNode. /// @@ -102,7 +164,7 @@ public: /// itself, otherwise we return the entry BasicBlock of the Subregion /// /// @return The entry BasicBlock of this RegionNode. - inline BasicBlock* getEntry() const { return entry.getPointer(); } + inline BlockT *getEntry() const { return entry.getPointer(); } /// @brief Get the content of this RegionNode. /// @@ -110,33 +172,15 @@ public: /// check the type of the content with the isSubRegion() function call. /// /// @return The content of this RegionNode. - template<class T> - inline T* getNodeAs() const; + template <class T> inline T *getNodeAs() const; /// @brief Is this RegionNode a subregion? /// /// @return True if it contains a subregion. False if it contains a /// BasicBlock. - inline bool isSubRegion() const { - return entry.getInt(); - } + inline bool isSubRegion() const { return entry.getInt(); } }; -/// Print a RegionNode. -inline raw_ostream &operator<<(raw_ostream &OS, const RegionNode &Node); - -template<> -inline BasicBlock* RegionNode::getNodeAs<BasicBlock>() const { - assert(!isSubRegion() && "This is not a BasicBlock RegionNode!"); - return getEntry(); -} - -template<> -inline Region* RegionNode::getNodeAs<Region>() const { - assert(isSubRegion() && "This is not a subregion RegionNode!"); - return reinterpret_cast<Region*>(const_cast<RegionNode*>(this)); -} - //===----------------------------------------------------------------------===// /// @brief A single entry single exit Region. /// @@ -199,37 +243,53 @@ inline Region* RegionNode::getNodeAs<Region>() const { /// /// The first call returns a textual representation of the program structure /// tree, the second one creates a graphical representation using graphviz. -class Region : public RegionNode { - friend class RegionInfo; - Region(const Region &) LLVM_DELETED_FUNCTION; - const Region &operator=(const Region &) LLVM_DELETED_FUNCTION; +template <class Tr> +class RegionBase : public RegionNodeBase<Tr> { + typedef typename Tr::FuncT FuncT; + typedef typename Tr::BlockT BlockT; + typedef typename Tr::RegionInfoT RegionInfoT; + typedef typename Tr::RegionT RegionT; + typedef typename Tr::RegionNodeT RegionNodeT; + typedef typename Tr::DomTreeT DomTreeT; + typedef typename Tr::LoopT LoopT; + typedef typename Tr::LoopInfoT LoopInfoT; + typedef typename Tr::InstT InstT; + + typedef GraphTraits<BlockT *> BlockTraits; + typedef GraphTraits<Inverse<BlockT *>> InvBlockTraits; + typedef typename BlockTraits::ChildIteratorType SuccIterTy; + typedef typename InvBlockTraits::ChildIteratorType PredIterTy; + + friend class RegionInfoBase<Tr>; + RegionBase(const RegionBase &) LLVM_DELETED_FUNCTION; + const RegionBase &operator=(const RegionBase &) LLVM_DELETED_FUNCTION; // Information necessary to manage this Region. - RegionInfo* RI; - DominatorTree *DT; + RegionInfoT *RI; + DomTreeT *DT; // The exit BasicBlock of this region. // (The entry BasicBlock is part of RegionNode) - BasicBlock *exit; + BlockT *exit; - typedef std::vector<Region*> RegionSet; + typedef std::vector<std::unique_ptr<RegionT>> RegionSet; // The subregions of this region. RegionSet children; - typedef std::map<BasicBlock*, RegionNode*> BBNodeMapT; + typedef std::map<BlockT *, RegionNodeT *> BBNodeMapT; // Save the BasicBlock RegionNodes that are element of this Region. mutable BBNodeMapT BBNodeMap; /// verifyBBInRegion - Check if a BB is in this Region. This check also works /// if the region is incorrectly built. (EXPENSIVE!) - void verifyBBInRegion(BasicBlock* BB) const; + void verifyBBInRegion(BlockT *BB) const; /// verifyWalk - Walk over all the BBs of the region starting from BB and /// verify that all reachable basic blocks are elements of the region. /// (EXPENSIVE!) - void verifyWalk(BasicBlock* BB, std::set<BasicBlock*>* visitedBB) const; + void verifyWalk(BlockT *BB, std::set<BlockT *> *visitedBB) const; /// verifyRegionNest - Verify if the region and its children are valid /// regions (EXPENSIVE!) @@ -244,27 +304,29 @@ public: /// @param DT The dominator tree of the current function. /// @param Parent The surrounding region or NULL if this is a top level /// region. - Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo* RI, - DominatorTree *DT, Region *Parent = 0); + RegionBase(BlockT *Entry, BlockT *Exit, RegionInfoT *RI, DomTreeT *DT, + RegionT *Parent = nullptr); /// Delete the Region and all its subregions. - ~Region(); + ~RegionBase(); /// @brief Get the entry BasicBlock of the Region. /// @return The entry BasicBlock of the region. - BasicBlock *getEntry() const { return RegionNode::getEntry(); } + BlockT *getEntry() const { + return RegionNodeBase<Tr>::getEntry(); + } /// @brief Replace the entry basic block of the region with the new basic /// block. /// /// @param BB The new entry basic block of the region. - void replaceEntry(BasicBlock *BB); + void replaceEntry(BlockT *BB); /// @brief Replace the exit basic block of the region with the new basic /// block. /// /// @param BB The new exit basic block of the region. - void replaceExit(BasicBlock *BB); + void replaceExit(BlockT *BB); /// @brief Recursively replace the entry basic block of the region. /// @@ -273,7 +335,7 @@ public: /// this region. /// /// @param NewEntry The new entry basic block. - void replaceEntryRecursive(BasicBlock *NewEntry); + void replaceEntryRecursive(BlockT *NewEntry); /// @brief Recursively replace the exit basic block of the region. /// @@ -282,22 +344,25 @@ public: /// this region. /// /// @param NewExit The new exit basic block. - void replaceExitRecursive(BasicBlock *NewExit); + void replaceExitRecursive(BlockT *NewExit); /// @brief Get the exit BasicBlock of the Region. /// @return The exit BasicBlock of the Region, NULL if this is the TopLevel /// Region. - BasicBlock *getExit() const { return exit; } + BlockT *getExit() const { return exit; } /// @brief Get the parent of the Region. /// @return The parent of the Region or NULL if this is a top level /// Region. - Region *getParent() const { return RegionNode::getParent(); } + RegionT *getParent() const { + return RegionNodeBase<Tr>::getParent(); + } /// @brief Get the RegionNode representing the current Region. /// @return The RegionNode representing the current Region. - RegionNode* getNode() const { - return const_cast<RegionNode*>(reinterpret_cast<const RegionNode*>(this)); + RegionNodeT *getNode() const { + return const_cast<RegionNodeT *>( + reinterpret_cast<const RegionNodeT *>(this)); } /// @brief Get the nesting level of this Region. @@ -310,29 +375,29 @@ public: /// @brief Check if a Region is the TopLevel region. /// /// The toplevel region represents the whole function. - bool isTopLevelRegion() const { return exit == NULL; } + bool isTopLevelRegion() const { return exit == nullptr; } - /// @brief Return a new (non canonical) region, that is obtained by joining + /// @brief Return a new (non-canonical) region, that is obtained by joining /// this region with its predecessors. /// /// @return A region also starting at getEntry(), but reaching to the next - /// basic block that forms with getEntry() a (non canonical) region. + /// basic block that forms with getEntry() a (non-canonical) region. /// NULL if such a basic block does not exist. - Region *getExpandedRegion() const; + RegionT *getExpandedRegion() const; /// @brief Return the first block of this region's single entry edge, /// if existing. /// /// @return The BasicBlock starting this region's single entry edge, /// else NULL. - BasicBlock *getEnteringBlock() const; + BlockT *getEnteringBlock() const; /// @brief Return the first block of this region's single exit edge, /// if existing. /// /// @return The BasicBlock starting this region's single exit edge, /// else NULL. - BasicBlock *getExitingBlock() const; + BlockT *getExitingBlock() const; /// @brief Is this a simple region? /// @@ -346,20 +411,18 @@ public: std::string getNameStr() const; /// @brief Return the RegionInfo object, that belongs to this Region. - RegionInfo *getRegionInfo() const { - return RI; - } + RegionInfoT *getRegionInfo() const { return RI; } /// PrintStyle - Print region in difference ways. - enum PrintStyle { PrintNone, PrintBB, PrintRN }; + enum PrintStyle { PrintNone, PrintBB, PrintRN }; /// @brief Print the region. /// /// @param OS The output stream the Region is printed to. /// @param printTree Print also the tree of subregions. /// @param level The indentation level used for printing. - void print(raw_ostream& OS, bool printTree = true, unsigned level = 0, - enum PrintStyle Style = PrintNone) const; + void print(raw_ostream &OS, bool printTree = true, unsigned level = 0, + PrintStyle Style = PrintNone) const; /// @brief Print the region to stderr. void dump() const; @@ -368,28 +431,28 @@ public: /// /// @param BB The BasicBlock that might be contained in this Region. /// @return True if the block is contained in the region otherwise false. - bool contains(const BasicBlock *BB) const; + bool contains(const BlockT *BB) const; /// @brief Check if the region contains another region. /// /// @param SubRegion The region that might be contained in this Region. /// @return True if SubRegion is contained in the region otherwise false. - bool contains(const Region *SubRegion) const { + bool contains(const RegionT *SubRegion) const { // Toplevel Region. if (!getExit()) return true; - return contains(SubRegion->getEntry()) - && (contains(SubRegion->getExit()) || SubRegion->getExit() == getExit()); + return contains(SubRegion->getEntry()) && + (contains(SubRegion->getExit()) || + SubRegion->getExit() == getExit()); } /// @brief Check if the region contains an Instruction. /// /// @param Inst The Instruction that might be contained in this region. - /// @return True if the Instruction is contained in the region otherwise false. - bool contains(const Instruction *Inst) const { - return contains(Inst->getParent()); - } + /// @return True if the Instruction is contained in the region otherwise + /// false. + bool contains(const InstT *Inst) const { return contains(Inst->getParent()); } /// @brief Check if the region contains a loop. /// @@ -398,7 +461,7 @@ public: /// In case a NULL pointer is passed to this function the result /// is false, except for the region that describes the whole function. /// In that case true is returned. - bool contains(const Loop *L) const; + bool contains(const LoopT *L) const; /// @brief Get the outermost loop in the region that contains a loop. /// @@ -408,7 +471,7 @@ public: /// @param L The loop the lookup is started. /// @return The outermost loop in the region, NULL if such a loop does not /// exist or if the region describes the whole function. - Loop *outermostLoopInRegion(Loop *L) const; + LoopT *outermostLoopInRegion(LoopT *L) const; /// @brief Get the outermost loop in the region that contains a basic block. /// @@ -419,13 +482,13 @@ public: /// @param BB The basic block surrounded by the loop. /// @return The outermost loop in the region, NULL if such a loop does not /// exist or if the region describes the whole function. - Loop *outermostLoopInRegion(LoopInfo *LI, BasicBlock* BB) const; + LoopT *outermostLoopInRegion(LoopInfoT *LI, BlockT *BB) const; /// @brief Get the subregion that starts at a BasicBlock /// /// @param BB The BasicBlock the subregion should start. /// @return The Subregion if available, otherwise NULL. - Region* getSubRegionNode(BasicBlock *BB) const; + RegionT *getSubRegionNode(BlockT *BB) const; /// @brief Get the RegionNode for a BasicBlock /// @@ -433,32 +496,32 @@ public: /// @return If available, the RegionNode that represents the subregion /// starting at BB. If no subregion starts at BB, the RegionNode /// representing BB. - RegionNode* getNode(BasicBlock *BB) const; + RegionNodeT *getNode(BlockT *BB) const; /// @brief Get the BasicBlock RegionNode for a BasicBlock /// /// @param BB The BasicBlock for which the RegionNode is requested. /// @return The RegionNode representing the BB. - RegionNode* getBBNode(BasicBlock *BB) const; + RegionNodeT *getBBNode(BlockT *BB) const; /// @brief Add a new subregion to this Region. /// /// @param SubRegion The new subregion that will be added. /// @param moveChildren Move the children of this region, that are also /// contained in SubRegion into SubRegion. - void addSubRegion(Region *SubRegion, bool moveChildren = false); + void addSubRegion(RegionT *SubRegion, bool moveChildren = false); /// @brief Remove a subregion from this Region. /// /// The subregion is not deleted, as it will probably be inserted into another /// region. /// @param SubRegion The SubRegion that will be removed. - Region *removeSubRegion(Region *SubRegion); + RegionT *removeSubRegion(RegionT *SubRegion); /// @brief Move all direct child nodes of this Region to another Region. /// /// @param To The Region the child nodes will be transferred to. - void transferChildrenTo(Region *To); + void transferChildrenTo(RegionT *To); /// @brief Verify if the region is a correct region. /// @@ -477,8 +540,8 @@ public: /// /// These iterators iterator over all subregions of this Region. //@{ - typedef RegionSet::iterator iterator; - typedef RegionSet::const_iterator const_iterator; + typedef typename RegionSet::iterator iterator; + typedef typename RegionSet::const_iterator const_iterator; iterator begin() { return children.begin(); } iterator end() { return children.end(); } @@ -495,20 +558,18 @@ public: //@{ template <bool IsConst> class block_iterator_wrapper - : public df_iterator<typename conditional<IsConst, - const BasicBlock, - BasicBlock>::type*> { - typedef df_iterator<typename conditional<IsConst, - const BasicBlock, - BasicBlock>::type*> - super; + : public df_iterator< + typename std::conditional<IsConst, const BlockT, BlockT>::type *> { + typedef df_iterator< + typename std::conditional<IsConst, const BlockT, BlockT>::type *> super; + public: typedef block_iterator_wrapper<IsConst> Self; typedef typename super::pointer pointer; // Construct the begin iterator. - block_iterator_wrapper(pointer Entry, pointer Exit) : super(df_begin(Entry)) - { + block_iterator_wrapper(pointer Entry, pointer Exit) + : super(df_begin(Entry)) { // Mark the exit of the region as visited, so that the children of the // exit and the exit itself, i.e. the block outside the region will never // be visited. @@ -516,34 +577,43 @@ public: } // Construct the end iterator. - block_iterator_wrapper() : super(df_end<pointer>((BasicBlock *)0)) {} + block_iterator_wrapper() : super(df_end<pointer>((BlockT *)nullptr)) {} /*implicit*/ block_iterator_wrapper(super I) : super(I) {} // FIXME: Even a const_iterator returns a non-const BasicBlock pointer. // This was introduced for backwards compatibility, but should // be removed as soon as all users are fixed. - BasicBlock *operator*() const { - return const_cast<BasicBlock*>(super::operator*()); + BlockT *operator*() const { + return const_cast<BlockT *>(super::operator*()); } }; typedef block_iterator_wrapper<false> block_iterator; - typedef block_iterator_wrapper<true> const_block_iterator; + typedef block_iterator_wrapper<true> const_block_iterator; - block_iterator block_begin() { - return block_iterator(getEntry(), getExit()); - } + block_iterator block_begin() { return block_iterator(getEntry(), getExit()); } - block_iterator block_end() { - return block_iterator(); - } + block_iterator block_end() { return block_iterator(); } const_block_iterator block_begin() const { return const_block_iterator(getEntry(), getExit()); } - const_block_iterator block_end() const { - return const_block_iterator(); + const_block_iterator block_end() const { return const_block_iterator(); } + + typedef iterator_range<block_iterator> block_range; + typedef iterator_range<const_block_iterator> const_block_range; + + /// @brief Returns a range view of the basic blocks in the region. + inline block_range blocks() { + return block_range(block_begin(), block_end()); + } + + /// @brief Returns a range view of the basic blocks in the region. + /// + /// This is the 'const' version of the range view. + inline const_block_range blocks() const { + return const_block_range(block_begin(), block_end()); } //@} @@ -553,12 +623,12 @@ public: /// are direct children of this Region. It does not iterate over any /// RegionNodes that are also element of a subregion of this Region. //@{ - typedef df_iterator<RegionNode*, SmallPtrSet<RegionNode*, 8>, false, - GraphTraits<RegionNode*> > element_iterator; + typedef df_iterator<RegionNodeT *, SmallPtrSet<RegionNodeT *, 8>, false, + GraphTraits<RegionNodeT *>> element_iterator; - typedef df_iterator<const RegionNode*, SmallPtrSet<const RegionNode*, 8>, - false, GraphTraits<const RegionNode*> > - const_element_iterator; + typedef df_iterator<const RegionNodeT *, SmallPtrSet<const RegionNodeT *, 8>, + false, + GraphTraits<const RegionNodeT *>> const_element_iterator; element_iterator element_begin(); element_iterator element_end(); @@ -568,132 +638,143 @@ public: //@} }; +/// Print a RegionNode. +template <class Tr> +inline raw_ostream &operator<<(raw_ostream &OS, const RegionNodeBase<Tr> &Node); + //===----------------------------------------------------------------------===// /// @brief Analysis that detects all canonical Regions. /// /// The RegionInfo pass detects all canonical regions in a function. The Regions /// are connected using the parent relation. This builds a Program Structure /// Tree. -class RegionInfo : public FunctionPass { - typedef DenseMap<BasicBlock*,BasicBlock*> BBtoBBMap; - typedef DenseMap<BasicBlock*, Region*> BBtoRegionMap; - typedef SmallPtrSet<Region*, 4> RegionSet; +template <class Tr> +class RegionInfoBase { + typedef typename Tr::BlockT BlockT; + typedef typename Tr::FuncT FuncT; + typedef typename Tr::RegionT RegionT; + typedef typename Tr::RegionInfoT RegionInfoT; + typedef typename Tr::DomTreeT DomTreeT; + typedef typename Tr::DomTreeNodeT DomTreeNodeT; + typedef typename Tr::PostDomTreeT PostDomTreeT; + typedef typename Tr::DomFrontierT DomFrontierT; + typedef GraphTraits<BlockT *> BlockTraits; + typedef GraphTraits<Inverse<BlockT *>> InvBlockTraits; + typedef typename BlockTraits::ChildIteratorType SuccIterTy; + typedef typename InvBlockTraits::ChildIteratorType PredIterTy; + + friend class RegionInfo; + friend class MachineRegionInfo; + typedef DenseMap<BlockT *, BlockT *> BBtoBBMap; + typedef DenseMap<BlockT *, RegionT *> BBtoRegionMap; + typedef SmallPtrSet<RegionT *, 4> RegionSet; + + RegionInfoBase(); + virtual ~RegionInfoBase(); - RegionInfo(const RegionInfo &) LLVM_DELETED_FUNCTION; - const RegionInfo &operator=(const RegionInfo &) LLVM_DELETED_FUNCTION; + RegionInfoBase(const RegionInfoBase &) LLVM_DELETED_FUNCTION; + const RegionInfoBase &operator=(const RegionInfoBase &) LLVM_DELETED_FUNCTION; - DominatorTree *DT; - PostDominatorTree *PDT; - DominanceFrontier *DF; + DomTreeT *DT; + PostDomTreeT *PDT; + DomFrontierT *DF; /// The top level region. - Region *TopLevelRegion; + RegionT *TopLevelRegion; +private: /// Map every BB to the smallest region, that contains BB. BBtoRegionMap BBtoRegion; // isCommonDomFrontier - Returns true if BB is in the dominance frontier of // entry, because it was inherited from exit. In the other case there is an // edge going from entry to BB without passing exit. - bool isCommonDomFrontier(BasicBlock* BB, BasicBlock* entry, - BasicBlock* exit) const; + bool isCommonDomFrontier(BlockT *BB, BlockT *entry, BlockT *exit) const; // isRegion - Check if entry and exit surround a valid region, based on // dominance tree and dominance frontier. - bool isRegion(BasicBlock* entry, BasicBlock* exit) const; + bool isRegion(BlockT *entry, BlockT *exit) const; // insertShortCut - Saves a shortcut pointing from entry to exit. // This function may extend this shortcut if possible. - void insertShortCut(BasicBlock* entry, BasicBlock* exit, - BBtoBBMap* ShortCut) const; + void insertShortCut(BlockT *entry, BlockT *exit, BBtoBBMap *ShortCut) const; // getNextPostDom - Returns the next BB that postdominates N, while skipping // all post dominators that cannot finish a canonical region. - DomTreeNode *getNextPostDom(DomTreeNode* N, BBtoBBMap *ShortCut) const; + DomTreeNodeT *getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const; // isTrivialRegion - A region is trivial, if it contains only one BB. - bool isTrivialRegion(BasicBlock *entry, BasicBlock *exit) const; + bool isTrivialRegion(BlockT *entry, BlockT *exit) const; // createRegion - Creates a single entry single exit region. - Region *createRegion(BasicBlock *entry, BasicBlock *exit); + RegionT *createRegion(BlockT *entry, BlockT *exit); // findRegionsWithEntry - Detect all regions starting with bb 'entry'. - void findRegionsWithEntry(BasicBlock *entry, BBtoBBMap *ShortCut); + void findRegionsWithEntry(BlockT *entry, BBtoBBMap *ShortCut); // scanForRegions - Detects regions in F. - void scanForRegions(Function &F, BBtoBBMap *ShortCut); + void scanForRegions(FuncT &F, BBtoBBMap *ShortCut); // getTopMostParent - Get the top most parent with the same entry block. - Region *getTopMostParent(Region *region); + RegionT *getTopMostParent(RegionT *region); // buildRegionsTree - build the region hierarchy after all region detected. - void buildRegionsTree(DomTreeNode *N, Region *region); - - // Calculate - detecte all regions in function and build the region tree. - void Calculate(Function& F); - - void releaseMemory(); + void buildRegionsTree(DomTreeNodeT *N, RegionT *region); // updateStatistics - Update statistic about created regions. - void updateStatistics(Region *R); + virtual void updateStatistics(RegionT *R) = 0; - // isSimple - Check if a region is a simple region with exactly one entry - // edge and exactly one exit edge. - bool isSimple(Region* R) const; + // calculate - detect all regions in function and build the region tree. + void calculate(FuncT &F); public: - static char ID; - explicit RegionInfo(); + static bool VerifyRegionInfo; + static typename RegionT::PrintStyle printStyle; - ~RegionInfo(); + void print(raw_ostream &OS) const; + void dump() const; - /// @name FunctionPass interface - //@{ - virtual bool runOnFunction(Function &F); - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void print(raw_ostream &OS, const Module *) const; - virtual void verifyAnalysis() const; - //@} + void releaseMemory(); /// @brief Get the smallest region that contains a BasicBlock. /// /// @param BB The basic block. /// @return The smallest region, that contains BB or NULL, if there is no /// region containing BB. - Region *getRegionFor(BasicBlock *BB) const; + RegionT *getRegionFor(BlockT *BB) const; /// @brief Set the smallest region that surrounds a basic block. /// /// @param BB The basic block surrounded by a region. /// @param R The smallest region that surrounds BB. - void setRegionFor(BasicBlock *BB, Region *R); + void setRegionFor(BlockT *BB, RegionT *R); /// @brief A shortcut for getRegionFor(). /// /// @param BB The basic block. /// @return The smallest region, that contains BB or NULL, if there is no /// region containing BB. - Region *operator[](BasicBlock *BB) const; + RegionT *operator[](BlockT *BB) const; /// @brief Return the exit of the maximal refined region, that starts at a /// BasicBlock. /// /// @param BB The BasicBlock the refined region starts. - BasicBlock *getMaxRegionExit(BasicBlock *BB) const; + BlockT *getMaxRegionExit(BlockT *BB) const; /// @brief Find the smallest region that contains two regions. /// /// @param A The first region. /// @param B The second region. /// @return The smallest region containing A and B. - Region *getCommonRegion(Region* A, Region *B) const; + RegionT *getCommonRegion(RegionT *A, RegionT *B) const; /// @brief Find the smallest region that contains two basic blocks. /// /// @param A The first basic block. /// @param B The second basic block. /// @return The smallest region that contains A and B. - Region* getCommonRegion(BasicBlock* A, BasicBlock *B) const { + RegionT *getCommonRegion(BlockT *A, BlockT *B) const { return getCommonRegion(getRegionFor(A), getRegionFor(B)); } @@ -701,23 +782,21 @@ public: /// /// @param Regions A vector of regions. /// @return The smallest region that contains all regions in Regions. - Region* getCommonRegion(SmallVectorImpl<Region*> &Regions) const; + RegionT *getCommonRegion(SmallVectorImpl<RegionT *> &Regions) const; /// @brief Find the smallest region that contains a set of basic blocks. /// /// @param BBs A vector of basic blocks. /// @return The smallest region that contains all basic blocks in BBS. - Region* getCommonRegion(SmallVectorImpl<BasicBlock*> &BBs) const; + RegionT *getCommonRegion(SmallVectorImpl<BlockT *> &BBs) const; - Region *getTopLevelRegion() const { - return TopLevelRegion; - } + RegionT *getTopLevelRegion() const { return TopLevelRegion; } /// @brief Update RegionInfo after a basic block was split. /// /// @param NewBB The basic block that was created before OldBB. /// @param OldBB The old basic block. - void splitBlock(BasicBlock* NewBB, BasicBlock *OldBB); + void splitBlock(BlockT *NewBB, BlockT *OldBB); /// @brief Clear the Node Cache for all Regions. /// @@ -726,14 +805,104 @@ public: if (TopLevelRegion) TopLevelRegion->clearNodeCache(); } + + void verifyAnalysis() const; +}; + +class Region; + +class RegionNode : public RegionNodeBase<RegionTraits<Function>> { +public: + inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false) + : RegionNodeBase<RegionTraits<Function>>(Parent, Entry, isSubRegion) {} + + ~RegionNode() {} + + bool operator==(const Region &RN) const { + return this == reinterpret_cast<const RegionNode *>(&RN); + } +}; + +class Region : public RegionBase<RegionTraits<Function>> { +public: + Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo *RI, DominatorTree *DT, + Region *Parent = nullptr); + ~Region(); + + bool operator==(const RegionNode &RN) const { + return &RN == reinterpret_cast<const RegionNode *>(this); + } +}; + +class RegionInfo : public RegionInfoBase<RegionTraits<Function>> { +public: + explicit RegionInfo(); + + virtual ~RegionInfo(); + + // updateStatistics - Update statistic about created regions. + void updateStatistics(Region *R) final; + + void recalculate(Function &F, DominatorTree *DT, PostDominatorTree *PDT, + DominanceFrontier *DF); +}; + +class RegionInfoPass : public FunctionPass { + RegionInfo RI; + +public: + static char ID; + explicit RegionInfoPass(); + + ~RegionInfoPass(); + + RegionInfo &getRegionInfo() { return RI; } + + const RegionInfo &getRegionInfo() const { return RI; } + + /// @name FunctionPass interface + //@{ + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void verifyAnalysis() const override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void print(raw_ostream &OS, const Module *) const override; + void dump() const; + //@} }; -inline raw_ostream &operator<<(raw_ostream &OS, const RegionNode &Node) { +template <> +template <> +inline BasicBlock * +RegionNodeBase<RegionTraits<Function>>::getNodeAs<BasicBlock>() const { + assert(!isSubRegion() && "This is not a BasicBlock RegionNode!"); + return getEntry(); +} + +template <> +template <> +inline Region * +RegionNodeBase<RegionTraits<Function>>::getNodeAs<Region>() const { + assert(isSubRegion() && "This is not a subregion RegionNode!"); + auto Unconst = const_cast<RegionNodeBase<RegionTraits<Function>> *>(this); + return reinterpret_cast<Region *>(Unconst); +} + +template <class Tr> +inline raw_ostream &operator<<(raw_ostream &OS, + const RegionNodeBase<Tr> &Node) { + typedef typename Tr::BlockT BlockT; + typedef typename Tr::RegionT RegionT; + if (Node.isSubRegion()) - return OS << Node.getNodeAs<Region>()->getNameStr(); + return OS << Node.template getNodeAs<RegionT>()->getNameStr(); else - return OS << Node.getNodeAs<BasicBlock>()->getName(); + return OS << Node.template getNodeAs<BlockT>()->getName(); } + +EXTERN_TEMPLATE_INSTANTIATION(class RegionBase<RegionTraits<Function>>); +EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase<RegionTraits<Function>>); +EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase<RegionTraits<Function>>); + } // End llvm namespace #endif - diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h new file mode 100644 index 000000000000..4266b84c32c4 --- /dev/null +++ b/include/llvm/Analysis/RegionInfoImpl.h @@ -0,0 +1,919 @@ +//===- RegionInfoImpl.h - SESE region detection analysis --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Detects single entry single exit regions in the control flow graph. +//===----------------------------------------------------------------------===// + +#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/RegionIterator.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <iterator> +#include <set> + +using namespace llvm; + +#define DEBUG_TYPE "region" + +//===----------------------------------------------------------------------===// +/// RegionBase Implementation +template <class Tr> +RegionBase<Tr>::RegionBase(BlockT *Entry, BlockT *Exit, + typename Tr::RegionInfoT *RInfo, DomTreeT *dt, + RegionT *Parent) + : RegionNodeBase<Tr>(Parent, Entry, 1), RI(RInfo), DT(dt), exit(Exit) {} + +template <class Tr> +RegionBase<Tr>::~RegionBase() { + // Free the cached nodes. + for (typename BBNodeMapT::iterator it = BBNodeMap.begin(), + ie = BBNodeMap.end(); + it != ie; ++it) + delete it->second; + + // Only clean the cache for this Region. Caches of child Regions will be + // cleaned when the child Regions are deleted. + BBNodeMap.clear(); +} + +template <class Tr> +void RegionBase<Tr>::replaceEntry(BlockT *BB) { + this->entry.setPointer(BB); +} + +template <class Tr> +void RegionBase<Tr>::replaceExit(BlockT *BB) { + assert(exit && "No exit to replace!"); + exit = BB; +} + +template <class Tr> +void RegionBase<Tr>::replaceEntryRecursive(BlockT *NewEntry) { + std::vector<RegionT *> RegionQueue; + BlockT *OldEntry = getEntry(); + + RegionQueue.push_back(static_cast<RegionT *>(this)); + while (!RegionQueue.empty()) { + RegionT *R = RegionQueue.back(); + RegionQueue.pop_back(); + + R->replaceEntry(NewEntry); + for (typename RegionT::const_iterator RI = R->begin(), RE = R->end(); + RI != RE; ++RI) { + if ((*RI)->getEntry() == OldEntry) + RegionQueue.push_back(RI->get()); + } + } +} + +template <class Tr> +void RegionBase<Tr>::replaceExitRecursive(BlockT *NewExit) { + std::vector<RegionT *> RegionQueue; + BlockT *OldExit = getExit(); + + RegionQueue.push_back(static_cast<RegionT *>(this)); + while (!RegionQueue.empty()) { + RegionT *R = RegionQueue.back(); + RegionQueue.pop_back(); + + R->replaceExit(NewExit); + for (typename RegionT::const_iterator RI = R->begin(), RE = R->end(); + RI != RE; ++RI) { + if ((*RI)->getExit() == OldExit) + RegionQueue.push_back(RI->get()); + } + } +} + +template <class Tr> +bool RegionBase<Tr>::contains(const BlockT *B) const { + BlockT *BB = const_cast<BlockT *>(B); + + if (!DT->getNode(BB)) + return false; + + BlockT *entry = getEntry(), *exit = getExit(); + + // Toplevel region. + if (!exit) + return true; + + return (DT->dominates(entry, BB) && + !(DT->dominates(exit, BB) && DT->dominates(entry, exit))); +} + +template <class Tr> +bool RegionBase<Tr>::contains(const LoopT *L) const { + // BBs that are not part of any loop are element of the Loop + // described by the NULL pointer. This loop is not part of any region, + // except if the region describes the whole function. + if (!L) + return getExit() == nullptr; + + if (!contains(L->getHeader())) + return false; + + SmallVector<BlockT *, 8> ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + + for (BlockT *BB : ExitingBlocks) { + if (!contains(BB)) + return false; + } + + return true; +} + +template <class Tr> +typename Tr::LoopT *RegionBase<Tr>::outermostLoopInRegion(LoopT *L) const { + if (!contains(L)) + return nullptr; + + while (L && contains(L->getParentLoop())) { + L = L->getParentLoop(); + } + + return L; +} + +template <class Tr> +typename Tr::LoopT *RegionBase<Tr>::outermostLoopInRegion(LoopInfoT *LI, + BlockT *BB) const { + assert(LI && BB && "LI and BB cannot be null!"); + LoopT *L = LI->getLoopFor(BB); + return outermostLoopInRegion(L); +} + +template <class Tr> +typename RegionBase<Tr>::BlockT *RegionBase<Tr>::getEnteringBlock() const { + BlockT *entry = getEntry(); + BlockT *Pred; + BlockT *enteringBlock = nullptr; + + for (PredIterTy PI = InvBlockTraits::child_begin(entry), + PE = InvBlockTraits::child_end(entry); + PI != PE; ++PI) { + Pred = *PI; + if (DT->getNode(Pred) && !contains(Pred)) { + if (enteringBlock) + return nullptr; + + enteringBlock = Pred; + } + } + + return enteringBlock; +} + +template <class Tr> +typename RegionBase<Tr>::BlockT *RegionBase<Tr>::getExitingBlock() const { + BlockT *exit = getExit(); + BlockT *Pred; + BlockT *exitingBlock = nullptr; + + if (!exit) + return nullptr; + + for (PredIterTy PI = InvBlockTraits::child_begin(exit), + PE = InvBlockTraits::child_end(exit); + PI != PE; ++PI) { + Pred = *PI; + if (contains(Pred)) { + if (exitingBlock) + return nullptr; + + exitingBlock = Pred; + } + } + + return exitingBlock; +} + +template <class Tr> +bool RegionBase<Tr>::isSimple() const { + return !isTopLevelRegion() && getEnteringBlock() && getExitingBlock(); +} + +template <class Tr> +std::string RegionBase<Tr>::getNameStr() const { + std::string exitName; + std::string entryName; + + if (getEntry()->getName().empty()) { + raw_string_ostream OS(entryName); + + getEntry()->printAsOperand(OS, false); + } else + entryName = getEntry()->getName(); + + if (getExit()) { + if (getExit()->getName().empty()) { + raw_string_ostream OS(exitName); + + getExit()->printAsOperand(OS, false); + } else + exitName = getExit()->getName(); + } else + exitName = "<Function Return>"; + + return entryName + " => " + exitName; +} + +template <class Tr> +void RegionBase<Tr>::verifyBBInRegion(BlockT *BB) const { + if (!contains(BB)) + llvm_unreachable("Broken region found!"); + + BlockT *entry = getEntry(), *exit = getExit(); + + for (SuccIterTy SI = BlockTraits::child_begin(BB), + SE = BlockTraits::child_end(BB); + SI != SE; ++SI) { + if (!contains(*SI) && exit != *SI) + llvm_unreachable("Broken region found!"); + } + + if (entry != BB) { + for (PredIterTy SI = InvBlockTraits::child_begin(BB), + SE = InvBlockTraits::child_end(BB); + SI != SE; ++SI) { + if (!contains(*SI)) + llvm_unreachable("Broken region found!"); + } + } +} + +template <class Tr> +void RegionBase<Tr>::verifyWalk(BlockT *BB, std::set<BlockT *> *visited) const { + BlockT *exit = getExit(); + + visited->insert(BB); + + verifyBBInRegion(BB); + + for (SuccIterTy SI = BlockTraits::child_begin(BB), + SE = BlockTraits::child_end(BB); + SI != SE; ++SI) { + if (*SI != exit && visited->find(*SI) == visited->end()) + verifyWalk(*SI, visited); + } +} + +template <class Tr> +void RegionBase<Tr>::verifyRegion() const { + // Only do verification when user wants to, otherwise this expensive check + // will be invoked by PMDataManager::verifyPreservedAnalysis when + // a regionpass (marked PreservedAll) finish. + if (!RegionInfoBase<Tr>::VerifyRegionInfo) + return; + + std::set<BlockT *> visited; + verifyWalk(getEntry(), &visited); +} + +template <class Tr> +void RegionBase<Tr>::verifyRegionNest() const { + for (typename RegionT::const_iterator RI = begin(), RE = end(); RI != RE; + ++RI) + (*RI)->verifyRegionNest(); + + verifyRegion(); +} + +template <class Tr> +typename RegionBase<Tr>::element_iterator RegionBase<Tr>::element_begin() { + return GraphTraits<RegionT *>::nodes_begin(static_cast<RegionT *>(this)); +} + +template <class Tr> +typename RegionBase<Tr>::element_iterator RegionBase<Tr>::element_end() { + return GraphTraits<RegionT *>::nodes_end(static_cast<RegionT *>(this)); +} + +template <class Tr> +typename RegionBase<Tr>::const_element_iterator +RegionBase<Tr>::element_begin() const { + return GraphTraits<const RegionT *>::nodes_begin( + static_cast<const RegionT *>(this)); +} + +template <class Tr> +typename RegionBase<Tr>::const_element_iterator +RegionBase<Tr>::element_end() const { + return GraphTraits<const RegionT *>::nodes_end( + static_cast<const RegionT *>(this)); +} + +template <class Tr> +typename Tr::RegionT *RegionBase<Tr>::getSubRegionNode(BlockT *BB) const { + typedef typename Tr::RegionT RegionT; + RegionT *R = RI->getRegionFor(BB); + + if (!R || R == this) + return nullptr; + + // If we pass the BB out of this region, that means our code is broken. + assert(contains(R) && "BB not in current region!"); + + while (contains(R->getParent()) && R->getParent() != this) + R = R->getParent(); + + if (R->getEntry() != BB) + return nullptr; + + return R; +} + +template <class Tr> +typename Tr::RegionNodeT *RegionBase<Tr>::getBBNode(BlockT *BB) const { + assert(contains(BB) && "Can get BB node out of this region!"); + + typename BBNodeMapT::const_iterator at = BBNodeMap.find(BB); + + if (at != BBNodeMap.end()) + return at->second; + + auto Deconst = const_cast<RegionBase<Tr> *>(this); + RegionNodeT *NewNode = new RegionNodeT(static_cast<RegionT *>(Deconst), BB); + BBNodeMap.insert(std::make_pair(BB, NewNode)); + return NewNode; +} + +template <class Tr> +typename Tr::RegionNodeT *RegionBase<Tr>::getNode(BlockT *BB) const { + assert(contains(BB) && "Can get BB node out of this region!"); + if (RegionT *Child = getSubRegionNode(BB)) + return Child->getNode(); + + return getBBNode(BB); +} + +template <class Tr> +void RegionBase<Tr>::transferChildrenTo(RegionT *To) { + for (iterator I = begin(), E = end(); I != E; ++I) { + (*I)->parent = To; + To->children.push_back(std::move(*I)); + } + children.clear(); +} + +template <class Tr> +void RegionBase<Tr>::addSubRegion(RegionT *SubRegion, bool moveChildren) { + assert(!SubRegion->parent && "SubRegion already has a parent!"); + assert(std::find_if(begin(), end(), [&](const std::unique_ptr<RegionT> &R) { + return R.get() == SubRegion; + }) == children.end() && + "Subregion already exists!"); + + SubRegion->parent = static_cast<RegionT *>(this); + children.push_back(std::unique_ptr<RegionT>(SubRegion)); + + if (!moveChildren) + return; + + assert(SubRegion->children.empty() && + "SubRegions that contain children are not supported"); + + for (element_iterator I = element_begin(), E = element_end(); I != E; ++I) { + if (!(*I)->isSubRegion()) { + BlockT *BB = (*I)->template getNodeAs<BlockT>(); + + if (SubRegion->contains(BB)) + RI->setRegionFor(BB, SubRegion); + } + } + + std::vector<std::unique_ptr<RegionT>> Keep; + for (iterator I = begin(), E = end(); I != E; ++I) { + if (SubRegion->contains(I->get()) && I->get() != SubRegion) { + (*I)->parent = SubRegion; + SubRegion->children.push_back(std::move(*I)); + } else + Keep.push_back(std::move(*I)); + } + + children.clear(); + children.insert( + children.begin(), + std::move_iterator<typename RegionSet::iterator>(Keep.begin()), + std::move_iterator<typename RegionSet::iterator>(Keep.end())); +} + +template <class Tr> +typename Tr::RegionT *RegionBase<Tr>::removeSubRegion(RegionT *Child) { + assert(Child->parent == this && "Child is not a child of this region!"); + Child->parent = nullptr; + typename RegionSet::iterator I = std::find_if( + children.begin(), children.end(), + [&](const std::unique_ptr<RegionT> &R) { return R.get() == Child; }); + assert(I != children.end() && "Region does not exit. Unable to remove."); + children.erase(children.begin() + (I - begin())); + return Child; +} + +template <class Tr> +unsigned RegionBase<Tr>::getDepth() const { + unsigned Depth = 0; + + for (RegionT *R = getParent(); R != nullptr; R = R->getParent()) + ++Depth; + + return Depth; +} + +template <class Tr> +typename Tr::RegionT *RegionBase<Tr>::getExpandedRegion() const { + unsigned NumSuccessors = Tr::getNumSuccessors(exit); + + if (NumSuccessors == 0) + return nullptr; + + for (PredIterTy PI = InvBlockTraits::child_begin(getExit()), + PE = InvBlockTraits::child_end(getExit()); + PI != PE; ++PI) { + if (!DT->dominates(getEntry(), *PI)) + return nullptr; + } + + RegionT *R = RI->getRegionFor(exit); + + if (R->getEntry() != exit) { + if (Tr::getNumSuccessors(exit) == 1) + return new RegionT(getEntry(), *BlockTraits::child_begin(exit), RI, DT); + return nullptr; + } + + while (R->getParent() && R->getParent()->getEntry() == exit) + R = R->getParent(); + + if (!DT->dominates(getEntry(), R->getExit())) { + for (PredIterTy PI = InvBlockTraits::child_begin(getExit()), + PE = InvBlockTraits::child_end(getExit()); + PI != PE; ++PI) { + if (!DT->dominates(R->getExit(), *PI)) + return nullptr; + } + } + + return new RegionT(getEntry(), R->getExit(), RI, DT); +} + +template <class Tr> +void RegionBase<Tr>::print(raw_ostream &OS, bool print_tree, unsigned level, + PrintStyle Style) const { + if (print_tree) + OS.indent(level * 2) << '[' << level << "] " << getNameStr(); + else + OS.indent(level * 2) << getNameStr(); + + OS << '\n'; + + if (Style != PrintNone) { + OS.indent(level * 2) << "{\n"; + OS.indent(level * 2 + 2); + + if (Style == PrintBB) { + for (const auto &BB : blocks()) + OS << BB->getName() << ", "; // TODO: remove the last "," + } else if (Style == PrintRN) { + for (const_element_iterator I = element_begin(), E = element_end(); + I != E; ++I) { + OS << **I << ", "; // TODO: remove the last ", + } + } + + OS << '\n'; + } + + if (print_tree) { + for (const_iterator RI = begin(), RE = end(); RI != RE; ++RI) + (*RI)->print(OS, print_tree, level + 1, Style); + } + + if (Style != PrintNone) + OS.indent(level * 2) << "} \n"; +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +template <class Tr> +void RegionBase<Tr>::dump() const { + print(dbgs(), true, getDepth(), RegionInfoBase<Tr>::printStyle); +} +#endif + +template <class Tr> +void RegionBase<Tr>::clearNodeCache() { + // Free the cached nodes. + for (typename BBNodeMapT::iterator I = BBNodeMap.begin(), + IE = BBNodeMap.end(); + I != IE; ++I) + delete I->second; + + BBNodeMap.clear(); + for (typename RegionT::iterator RI = begin(), RE = end(); RI != RE; ++RI) + (*RI)->clearNodeCache(); +} + +//===----------------------------------------------------------------------===// +// RegionInfoBase implementation +// + +template <class Tr> +RegionInfoBase<Tr>::RegionInfoBase() + : TopLevelRegion(nullptr) {} + +template <class Tr> +RegionInfoBase<Tr>::~RegionInfoBase() { + releaseMemory(); +} + +template <class Tr> +bool RegionInfoBase<Tr>::isCommonDomFrontier(BlockT *BB, BlockT *entry, + BlockT *exit) const { + for (PredIterTy PI = InvBlockTraits::child_begin(BB), + PE = InvBlockTraits::child_end(BB); + PI != PE; ++PI) { + BlockT *P = *PI; + if (DT->dominates(entry, P) && !DT->dominates(exit, P)) + return false; + } + + return true; +} + +template <class Tr> +bool RegionInfoBase<Tr>::isRegion(BlockT *entry, BlockT *exit) const { + assert(entry && exit && "entry and exit must not be null!"); + typedef typename DomFrontierT::DomSetType DST; + + DST *entrySuccs = &DF->find(entry)->second; + + // Exit is the header of a loop that contains the entry. In this case, + // the dominance frontier must only contain the exit. + if (!DT->dominates(entry, exit)) { + for (typename DST::iterator SI = entrySuccs->begin(), + SE = entrySuccs->end(); + SI != SE; ++SI) { + if (*SI != exit && *SI != entry) + return false; + } + + return true; + } + + DST *exitSuccs = &DF->find(exit)->second; + + // Do not allow edges leaving the region. + for (typename DST::iterator SI = entrySuccs->begin(), SE = entrySuccs->end(); + SI != SE; ++SI) { + if (*SI == exit || *SI == entry) + continue; + if (exitSuccs->find(*SI) == exitSuccs->end()) + return false; + if (!isCommonDomFrontier(*SI, entry, exit)) + return false; + } + + // Do not allow edges pointing into the region. + for (typename DST::iterator SI = exitSuccs->begin(), SE = exitSuccs->end(); + SI != SE; ++SI) { + if (DT->properlyDominates(entry, *SI) && *SI != exit) + return false; + } + + return true; +} + +template <class Tr> +void RegionInfoBase<Tr>::insertShortCut(BlockT *entry, BlockT *exit, + BBtoBBMap *ShortCut) const { + assert(entry && exit && "entry and exit must not be null!"); + + typename BBtoBBMap::iterator e = ShortCut->find(exit); + + if (e == ShortCut->end()) + // No further region at exit available. + (*ShortCut)[entry] = exit; + else { + // We found a region e that starts at exit. Therefore (entry, e->second) + // is also a region, that is larger than (entry, exit). Insert the + // larger one. + BlockT *BB = e->second; + (*ShortCut)[entry] = BB; + } +} + +template <class Tr> +typename Tr::DomTreeNodeT * +RegionInfoBase<Tr>::getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const { + typename BBtoBBMap::iterator e = ShortCut->find(N->getBlock()); + + if (e == ShortCut->end()) + return N->getIDom(); + + return PDT->getNode(e->second)->getIDom(); +} + +template <class Tr> +bool RegionInfoBase<Tr>::isTrivialRegion(BlockT *entry, BlockT *exit) const { + assert(entry && exit && "entry and exit must not be null!"); + + unsigned num_successors = + BlockTraits::child_end(entry) - BlockTraits::child_begin(entry); + + if (num_successors <= 1 && exit == *(BlockTraits::child_begin(entry))) + return true; + + return false; +} + +template <class Tr> +typename Tr::RegionT *RegionInfoBase<Tr>::createRegion(BlockT *entry, + BlockT *exit) { + assert(entry && exit && "entry and exit must not be null!"); + + if (isTrivialRegion(entry, exit)) + return nullptr; + + RegionT *region = + new RegionT(entry, exit, static_cast<RegionInfoT *>(this), DT); + BBtoRegion.insert(std::make_pair(entry, region)); + +#ifdef XDEBUG + region->verifyRegion(); +#else + DEBUG(region->verifyRegion()); +#endif + + updateStatistics(region); + return region; +} + +template <class Tr> +void RegionInfoBase<Tr>::findRegionsWithEntry(BlockT *entry, + BBtoBBMap *ShortCut) { + assert(entry); + + DomTreeNodeT *N = PDT->getNode(entry); + if (!N) + return; + + RegionT *lastRegion = nullptr; + BlockT *lastExit = entry; + + // As only a BasicBlock that postdominates entry can finish a region, walk the + // post dominance tree upwards. + while ((N = getNextPostDom(N, ShortCut))) { + BlockT *exit = N->getBlock(); + + if (!exit) + break; + + if (isRegion(entry, exit)) { + RegionT *newRegion = createRegion(entry, exit); + + if (lastRegion) + newRegion->addSubRegion(lastRegion); + + lastRegion = newRegion; + lastExit = exit; + } + + // This can never be a region, so stop the search. + if (!DT->dominates(entry, exit)) + break; + } + + // Tried to create regions from entry to lastExit. Next time take a + // shortcut from entry to lastExit. + if (lastExit != entry) + insertShortCut(entry, lastExit, ShortCut); +} + +template <class Tr> +void RegionInfoBase<Tr>::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) { + typedef typename std::add_pointer<FuncT>::type FuncPtrT; + BlockT *entry = GraphTraits<FuncPtrT>::getEntryNode(&F); + DomTreeNodeT *N = DT->getNode(entry); + + // Iterate over the dominance tree in post order to start with the small + // regions from the bottom of the dominance tree. If the small regions are + // detected first, detection of bigger regions is faster, as we can jump + // over the small regions. + for (po_iterator<DomTreeNodeT *> FI = po_begin(N), FE = po_end(N); FI != FE; + ++FI) { + findRegionsWithEntry(FI->getBlock(), ShortCut); + } +} + +template <class Tr> +typename Tr::RegionT *RegionInfoBase<Tr>::getTopMostParent(RegionT *region) { + while (region->getParent()) + region = region->getParent(); + + return region; +} + +template <class Tr> +void RegionInfoBase<Tr>::buildRegionsTree(DomTreeNodeT *N, RegionT *region) { + BlockT *BB = N->getBlock(); + + // Passed region exit + while (BB == region->getExit()) + region = region->getParent(); + + typename BBtoRegionMap::iterator it = BBtoRegion.find(BB); + + // This basic block is a start block of a region. It is already in the + // BBtoRegion relation. Only the child basic blocks have to be updated. + if (it != BBtoRegion.end()) { + RegionT *newRegion = it->second; + region->addSubRegion(getTopMostParent(newRegion)); + region = newRegion; + } else { + BBtoRegion[BB] = region; + } + + for (typename DomTreeNodeT::iterator CI = N->begin(), CE = N->end(); CI != CE; + ++CI) { + buildRegionsTree(*CI, region); + } +} + +#ifdef XDEBUG +template <class Tr> +bool RegionInfoBase<Tr>::VerifyRegionInfo = true; +#else +template <class Tr> +bool RegionInfoBase<Tr>::VerifyRegionInfo = false; +#endif + +template <class Tr> +typename Tr::RegionT::PrintStyle RegionInfoBase<Tr>::printStyle = + RegionBase<Tr>::PrintNone; + +template <class Tr> +void RegionInfoBase<Tr>::print(raw_ostream &OS) const { + OS << "Region tree:\n"; + TopLevelRegion->print(OS, true, 0, printStyle); + OS << "End region tree\n"; +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +template <class Tr> +void RegionInfoBase<Tr>::dump() const { print(dbgs()); } +#endif + +template <class Tr> +void RegionInfoBase<Tr>::releaseMemory() { + BBtoRegion.clear(); + if (TopLevelRegion) + delete TopLevelRegion; + TopLevelRegion = nullptr; +} + +template <class Tr> +void RegionInfoBase<Tr>::verifyAnalysis() const { + TopLevelRegion->verifyRegionNest(); +} + +// Region pass manager support. +template <class Tr> +typename Tr::RegionT *RegionInfoBase<Tr>::getRegionFor(BlockT *BB) const { + typename BBtoRegionMap::const_iterator I = BBtoRegion.find(BB); + return I != BBtoRegion.end() ? I->second : nullptr; +} + +template <class Tr> +void RegionInfoBase<Tr>::setRegionFor(BlockT *BB, RegionT *R) { + BBtoRegion[BB] = R; +} + +template <class Tr> +typename Tr::RegionT *RegionInfoBase<Tr>::operator[](BlockT *BB) const { + return getRegionFor(BB); +} + +template <class Tr> +typename RegionInfoBase<Tr>::BlockT * +RegionInfoBase<Tr>::getMaxRegionExit(BlockT *BB) const { + BlockT *Exit = nullptr; + + while (true) { + // Get largest region that starts at BB. + RegionT *R = getRegionFor(BB); + while (R && R->getParent() && R->getParent()->getEntry() == BB) + R = R->getParent(); + + // Get the single exit of BB. + if (R && R->getEntry() == BB) + Exit = R->getExit(); + else if (++BlockTraits::child_begin(BB) == BlockTraits::child_end(BB)) + Exit = *BlockTraits::child_begin(BB); + else // No single exit exists. + return Exit; + + // Get largest region that starts at Exit. + RegionT *ExitR = getRegionFor(Exit); + while (ExitR && ExitR->getParent() && + ExitR->getParent()->getEntry() == Exit) + ExitR = ExitR->getParent(); + + for (PredIterTy PI = InvBlockTraits::child_begin(Exit), + PE = InvBlockTraits::child_end(Exit); + PI != PE; ++PI) { + if (!R->contains(*PI) && !ExitR->contains(*PI)) + break; + } + + // This stops infinite cycles. + if (DT->dominates(Exit, BB)) + break; + + BB = Exit; + } + + return Exit; +} + +template <class Tr> +typename Tr::RegionT *RegionInfoBase<Tr>::getCommonRegion(RegionT *A, + RegionT *B) const { + assert(A && B && "One of the Regions is NULL"); + + if (A->contains(B)) + return A; + + while (!B->contains(A)) + B = B->getParent(); + + return B; +} + +template <class Tr> +typename Tr::RegionT * +RegionInfoBase<Tr>::getCommonRegion(SmallVectorImpl<RegionT *> &Regions) const { + RegionT *ret = Regions.back(); + Regions.pop_back(); + + for (RegionT *R : Regions) + ret = getCommonRegion(ret, R); + + return ret; +} + +template <class Tr> +typename Tr::RegionT * +RegionInfoBase<Tr>::getCommonRegion(SmallVectorImpl<BlockT *> &BBs) const { + RegionT *ret = getRegionFor(BBs.back()); + BBs.pop_back(); + + for (BlockT *BB : BBs) + ret = getCommonRegion(ret, getRegionFor(BB)); + + return ret; +} + +template <class Tr> +void RegionInfoBase<Tr>::splitBlock(BlockT *NewBB, BlockT *OldBB) { + RegionT *R = getRegionFor(OldBB); + + setRegionFor(NewBB, R); + + while (R->getEntry() == OldBB && !R->isTopLevelRegion()) { + R->replaceEntry(NewBB); + R = R->getParent(); + } + + setRegionFor(OldBB, R); +} + +template <class Tr> +void RegionInfoBase<Tr>::calculate(FuncT &F) { + typedef typename std::add_pointer<FuncT>::type FuncPtrT; + + // ShortCut a function where for every BB the exit of the largest region + // starting with BB is stored. These regions can be threated as single BBS. + // This improves performance on linear CFGs. + BBtoBBMap ShortCut; + + scanForRegions(F, &ShortCut); + BlockT *BB = GraphTraits<FuncPtrT>::getEntryNode(&F); + buildRegionsTree(DT->getNode(BB), TopLevelRegion); +} + +#endif diff --git a/include/llvm/Analysis/RegionIterator.h b/include/llvm/Analysis/RegionIterator.h index 8fd42637276e..0daff58475dd 100644 --- a/include/llvm/Analysis/RegionIterator.h +++ b/include/llvm/Analysis/RegionIterator.h @@ -15,7 +15,7 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/RegionInfo.h" -#include "llvm/Support/CFG.h" +#include "llvm/IR/CFG.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -30,13 +30,16 @@ namespace llvm { /// /// For a subregion RegionNode there is just one successor. The RegionNode /// representing the exit of the subregion. -template<class NodeType> +template<class NodeType, class BlockT, class RegionT> class RNSuccIterator : public std::iterator<std::forward_iterator_tag, - NodeType, ptrdiff_t> -{ + NodeType, ptrdiff_t> { typedef std::iterator<std::forward_iterator_tag, NodeType, ptrdiff_t> super; + + typedef GraphTraits<BlockT*> BlockTraits; + typedef typename BlockTraits::ChildIteratorType SuccIterTy; + // The iterator works in two modes, bb mode or region mode. - enum ItMode{ + enum ItMode { // In BB mode it returns all successors of this BasicBlock as its // successors. ItBB, @@ -47,10 +50,10 @@ class RNSuccIterator : public std::iterator<std::forward_iterator_tag, }; // Use two bit to represent the mode iterator. - PointerIntPair<NodeType*, 2, enum ItMode> Node; + PointerIntPair<NodeType*, 2, ItMode> Node; // The block successor iterator. - succ_iterator BItor; + SuccIterTy BItor; // advanceRegionSucc - A region node has only one successor. It reaches end // once we advance it. @@ -66,37 +69,36 @@ class RNSuccIterator : public std::iterator<std::forward_iterator_tag, // Get the immediate successor. This function may return a Basic Block // RegionNode or a subregion RegionNode. - RegionNode* getISucc(BasicBlock* BB) const { - RegionNode *succ; + NodeType* getISucc(BlockT* BB) const { + NodeType *succ; succ = getNode()->getParent()->getNode(BB); assert(succ && "BB not in Region or entered subregion!"); return succ; } // getRegionSucc - Return the successor basic block of a SubRegion RegionNode. - inline BasicBlock* getRegionSucc() const { + inline BlockT* getRegionSucc() const { assert(Node.getInt() == ItRgBegin && "Cannot get the region successor!"); - return getNode()->template getNodeAs<Region>()->getExit(); + return getNode()->template getNodeAs<RegionT>()->getExit(); } // isExit - Is this the exit BB of the Region? - inline bool isExit(BasicBlock* BB) const { + inline bool isExit(BlockT* BB) const { return getNode()->getParent()->getExit() == BB; } public: - typedef RNSuccIterator<NodeType> Self; + typedef RNSuccIterator<NodeType, BlockT, RegionT> Self; typedef typename super::pointer pointer; /// @brief Create begin iterator of a RegionNode. inline RNSuccIterator(NodeType* node) : Node(node, node->isSubRegion() ? ItRgBegin : ItBB), - BItor(succ_begin(node->getEntry())) { - + BItor(BlockTraits::child_begin(node->getEntry())) { // Skip the exit block if (!isRegionMode()) - while (succ_end(node->getEntry()) != BItor && isExit(*BItor)) + while (BlockTraits::child_end(node->getEntry()) != BItor && isExit(*BItor)) ++BItor; if (isRegionMode() && isExit(getRegionSucc())) @@ -106,7 +108,7 @@ public: /// @brief Create an end iterator. inline RNSuccIterator(NodeType* node, bool) : Node(node, node->isSubRegion() ? ItRgEnd : ItBB), - BItor(succ_end(node->getEntry())) {} + BItor(BlockTraits::child_end(node->getEntry())) {} inline bool operator==(const Self& x) const { assert(isRegionMode() == x.isRegionMode() && "Broken iterator!"); @@ -119,7 +121,7 @@ public: inline bool operator!=(const Self& x) const { return !operator==(x); } inline pointer operator*() const { - BasicBlock* BB = isRegionMode() ? getRegionSucc() : *BItor; + BlockT *BB = isRegionMode() ? getRegionSucc() : *BItor; assert(!isExit(BB) && "Iterator out of range!"); return getISucc(BB); } @@ -132,7 +134,7 @@ public: // Skip the exit. do ++BItor; - while (BItor != succ_end(getNode()->getEntry()) + while (BItor != BlockTraits::child_end(getNode()->getEntry()) && isExit(*BItor)); } return *this; @@ -162,36 +164,41 @@ public: /// The Flat Region iterator will iterate over all BasicBlock RegionNodes that /// are contained in the Region and its subregions. This is close to a virtual /// control flow graph of the Region. -template<class NodeType> -class RNSuccIterator<FlatIt<NodeType> > - : public std::iterator<std::forward_iterator_tag, NodeType, ptrdiff_t> -{ +template<class NodeType, class BlockT, class RegionT> +class RNSuccIterator<FlatIt<NodeType>, BlockT, RegionT> + : public std::iterator<std::forward_iterator_tag, NodeType, ptrdiff_t> { typedef std::iterator<std::forward_iterator_tag, NodeType, ptrdiff_t> super; + typedef GraphTraits<BlockT*> BlockTraits; + typedef typename BlockTraits::ChildIteratorType SuccIterTy; + NodeType* Node; - succ_iterator Itor; + SuccIterTy Itor; public: - typedef RNSuccIterator<FlatIt<NodeType> > Self; + typedef RNSuccIterator<FlatIt<NodeType>, BlockT, RegionT> Self; typedef typename super::pointer pointer; /// @brief Create the iterator from a RegionNode. /// /// Note that the incoming node must be a bb node, otherwise it will trigger /// an assertion when we try to get a BasicBlock. - inline RNSuccIterator(NodeType* node) : Node(node), - Itor(succ_begin(node->getEntry())) { + inline RNSuccIterator(NodeType* node) : + Node(node), + Itor(BlockTraits::child_begin(node->getEntry())) { assert(!Node->isSubRegion() && "Subregion node not allowed in flat iterating mode!"); assert(Node->getParent() && "A BB node must have a parent!"); // Skip the exit block of the iterating region. - while (succ_end(Node->getEntry()) != Itor + while (BlockTraits::child_end(Node->getEntry()) != Itor && Node->getParent()->getExit() == *Itor) ++Itor; } + /// @brief Create an end iterator - inline RNSuccIterator(NodeType* node, bool) : Node(node), - Itor(succ_end(node->getEntry())) { + inline RNSuccIterator(NodeType* node, bool) : + Node(node), + Itor(BlockTraits::child_end(node->getEntry())) { assert(!Node->isSubRegion() && "Subregion node not allowed in flat iterating mode!"); } @@ -206,10 +213,10 @@ public: inline bool operator!=(const Self& x) const { return !operator==(x); } inline pointer operator*() const { - BasicBlock* BB = *Itor; + BlockT *BB = *Itor; // Get the iterating region. - Region* Parent = Node->getParent(); + RegionT *Parent = Node->getParent(); // The only case that the successor reaches out of the region is it reaches // the exit of the region. @@ -245,14 +252,14 @@ public: } }; -template<class NodeType> -inline RNSuccIterator<NodeType> succ_begin(NodeType* Node) { - return RNSuccIterator<NodeType>(Node); +template<class NodeType, class BlockT, class RegionT> +inline RNSuccIterator<NodeType, BlockT, RegionT> succ_begin(NodeType* Node) { + return RNSuccIterator<NodeType, BlockT, RegionT>(Node); } -template<class NodeType> -inline RNSuccIterator<NodeType> succ_end(NodeType* Node) { - return RNSuccIterator<NodeType>(Node, true); +template<class NodeType, class BlockT, class RegionT> +inline RNSuccIterator<NodeType, BlockT, RegionT> succ_end(NodeType* Node) { + return RNSuccIterator<NodeType, BlockT, RegionT>(Node, true); } //===--------------------------------------------------------------------===// @@ -262,27 +269,27 @@ inline RNSuccIterator<NodeType> succ_end(NodeType* Node) { // NodeT can either be region node or const region node, otherwise child_begin // and child_end fail. -#define RegionNodeGraphTraits(NodeT) \ - template<> struct GraphTraits<NodeT*> { \ +#define RegionNodeGraphTraits(NodeT, BlockT, RegionT) \ + template<> struct GraphTraits<NodeT*> { \ typedef NodeT NodeType; \ - typedef RNSuccIterator<NodeType> ChildIteratorType; \ + typedef RNSuccIterator<NodeType, BlockT, RegionT> ChildIteratorType; \ static NodeType *getEntryNode(NodeType* N) { return N; } \ static inline ChildIteratorType child_begin(NodeType *N) { \ - return RNSuccIterator<NodeType>(N); \ + return RNSuccIterator<NodeType, BlockT, RegionT>(N); \ } \ static inline ChildIteratorType child_end(NodeType *N) { \ - return RNSuccIterator<NodeType>(N, true); \ + return RNSuccIterator<NodeType, BlockT, RegionT>(N, true); \ } \ }; \ -template<> struct GraphTraits<FlatIt<NodeT*> > { \ +template<> struct GraphTraits<FlatIt<NodeT*>> { \ typedef NodeT NodeType; \ - typedef RNSuccIterator<FlatIt<NodeT> > ChildIteratorType; \ + typedef RNSuccIterator<FlatIt<NodeT>, BlockT, RegionT > ChildIteratorType; \ static NodeType *getEntryNode(NodeType* N) { return N; } \ static inline ChildIteratorType child_begin(NodeType *N) { \ - return RNSuccIterator<FlatIt<NodeType> >(N); \ + return RNSuccIterator<FlatIt<NodeType>, BlockT, RegionT>(N); \ } \ static inline ChildIteratorType child_end(NodeType *N) { \ - return RNSuccIterator<FlatIt<NodeType> >(N, true); \ + return RNSuccIterator<FlatIt<NodeType>, BlockT, RegionT>(N, true); \ } \ } @@ -315,8 +322,8 @@ template<> struct GraphTraits<FlatIt<RegionT*> > \ } \ } -RegionNodeGraphTraits(RegionNode); -RegionNodeGraphTraits(const RegionNode); +RegionNodeGraphTraits(RegionNode, BasicBlock, Region); +RegionNodeGraphTraits(const RegionNode, BasicBlock, Region); RegionGraphTraits(Region, RegionNode); RegionGraphTraits(const Region, const RegionNode); @@ -337,6 +344,22 @@ template <> struct GraphTraits<RegionInfo*> } }; +template <> struct GraphTraits<RegionInfoPass*> + : public GraphTraits<RegionInfo *> { + typedef df_iterator<NodeType*, SmallPtrSet<NodeType*, 8>, false, + GraphTraits<FlatIt<NodeType*> > > nodes_iterator; + + static NodeType *getEntryNode(RegionInfoPass *RI) { + return GraphTraits<RegionInfo*>::getEntryNode(&RI->getRegionInfo()); + } + static nodes_iterator nodes_begin(RegionInfoPass* RI) { + return GraphTraits<RegionInfo*>::nodes_begin(&RI->getRegionInfo()); + } + static nodes_iterator nodes_end(RegionInfoPass *RI) { + return GraphTraits<RegionInfo*>::nodes_end(&RI->getRegionInfo()); + } +}; + } // End namespace llvm #endif diff --git a/include/llvm/Analysis/RegionPass.h b/include/llvm/Analysis/RegionPass.h index 3907ad9c7dd5..bd51c49e87db 100644 --- a/include/llvm/Analysis/RegionPass.h +++ b/include/llvm/Analysis/RegionPass.h @@ -1,4 +1,4 @@ -//===- RegionPass.h - RegionPass class ------------------------------------===// +//===- RegionPass.h - RegionPass class --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -55,7 +55,8 @@ public: /// @param Banner The banner to separate different printed passes. /// /// @return The pass to print the LLVM IR in the region. - Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const override; using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; @@ -68,12 +69,12 @@ public: /// @name PassManager API /// //@{ - void preparePassManager(PMStack &PMS); + void preparePassManager(PMStack &PMS) override; - virtual void assignPassManager(PMStack &PMS, - PassManagerType PMT = PMT_RegionPassManager); + void assignPassManager(PMStack &PMS, + PassManagerType PMT = PMT_RegionPassManager) override; - virtual PassManagerType getPotentialPassManagerType() const { + PassManagerType getPotentialPassManagerType() const override { return PMT_RegionPassManager; } //@} @@ -94,21 +95,21 @@ public: /// @brief Execute all of the passes scheduled for execution. /// /// @return True if any of the passes modifies the function. - bool runOnFunction(Function &F); + bool runOnFunction(Function &F) override; /// Pass Manager itself does not invalidate any analysis info. /// RGPassManager needs RegionInfo. - void getAnalysisUsage(AnalysisUsage &Info) const; + void getAnalysisUsage(AnalysisUsage &Info) const override; - virtual const char *getPassName() const { + const char *getPassName() const override { return "Region Pass Manager"; } - virtual PMDataManager *getAsPMDataManager() { return this; } - virtual Pass *getAsPass() { return this; } + PMDataManager *getAsPMDataManager() override { return this; } + Pass *getAsPass() override { return this; } /// @brief Print passes managed by this manager. - void dumpPassStructure(unsigned Offset); + void dumpPassStructure(unsigned Offset) override; /// @brief Get passes contained by this manager. Pass *getContainedPass(unsigned N) { @@ -117,7 +118,7 @@ public: return FP; } - virtual PassManagerType getPassManagerType() const { + PassManagerType getPassManagerType() const override { return PMT_RegionPassManager; } }; diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index d7f617817179..617e54541ee1 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -23,14 +23,14 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/ConstantRange.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/ValueHandle.h" #include <map> namespace llvm { @@ -207,10 +207,10 @@ namespace llvm { /// notified whenever a Value is deleted. class SCEVCallbackVH : public CallbackVH { ScalarEvolution *SE; - virtual void deleted(); - virtual void allUsesReplacedWith(Value *New); + void deleted() override; + void allUsesReplacedWith(Value *New) override; public: - SCEVCallbackVH(Value *V, ScalarEvolution *SE = 0); + SCEVCallbackVH(Value *V, ScalarEvolution *SE = nullptr); }; friend class SCEVCallbackVH; @@ -225,9 +225,9 @@ namespace llvm { /// LoopInfo *LI; - /// TD - The target data information for the target we are targeting. + /// The DataLayout information for the target we are targeting. /// - DataLayout *TD; + const DataLayout *DL; /// TLI - The target library information for the target we are targeting. /// @@ -253,17 +253,28 @@ namespace llvm { /// Mark predicate values currently being processed by isImpliedCond. DenseSet<Value*> PendingLoopPredicates; - /// ExitLimit - Information about the number of loop iterations for - /// which a 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. + /// ExitLimit - Information about the number of loop iterations for which a + /// 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) {} + /*implicit*/ ExitLimit(const SCEV *E) + : Exact(E), Max(E), MustExit(true) {} - ExitLimit(const SCEV *E, const SCEV *M) : Exact(E), Max(M) {} + ExitLimit(const SCEV *E, const SCEV *M, bool MustExit) + : Exact(E), Max(M), MustExit(MustExit) {} /// hasAnyInfo - Test whether this ExitLimit contains any computed /// information, or whether it's all SCEVCouldNotCompute values. @@ -280,7 +291,7 @@ namespace llvm { const SCEV *ExactNotTaken; PointerIntPair<ExitNotTakenInfo*, 1> NextExit; - ExitNotTakenInfo() : ExitingBlock(0), ExactNotTaken(0) {} + ExitNotTakenInfo() : ExitingBlock(nullptr), ExactNotTaken(nullptr) {} /// isCompleteList - Return true if all loop exits are computable. bool isCompleteList() const { @@ -310,7 +321,7 @@ namespace llvm { const SCEV *Max; public: - BackedgeTakenInfo() : Max(0) {} + BackedgeTakenInfo() : Max(nullptr) {} /// Initialize BackedgeTakenInfo from a list of exact exit counts. BackedgeTakenInfo( @@ -458,6 +469,13 @@ namespace llvm { BasicBlock *FBB, bool IsSubExpr); + /// ComputeExitLimitFromSingleExitSwitch - Compute the number of times the + /// backedge of the specified loop will execute if its exit condition were a + /// switch with a single exiting case to ExitingBB. + ExitLimit + ComputeExitLimitFromSingleExitSwitch(const Loop *L, SwitchInst *Switch, + BasicBlock *ExitingBB, bool IsSubExpr); + /// ComputeLoadConstantCompareExitLimit - Given an exit condition /// of 'icmp op load X, cst', try to see if we can compute the /// backedge-taken count. @@ -613,6 +631,7 @@ namespace llvm { return getMulExpr(Ops, Flags); } const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUDivExactExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step, const Loop *L, SCEV::NoWrapFlags Flags); const SCEV *getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands, @@ -776,7 +795,8 @@ namespace llvm { /// forgetLoop - This method should be called by the client when it has /// changed a loop in a way that may effect ScalarEvolution's ability to - /// compute a trip count, or if the loop is deleted. + /// compute a trip count, or if the loop is deleted. This call is + /// potentially expensive for large loop bodies. void forgetLoop(const Loop *L); /// forgetValue - This method should be called by the client when it has @@ -784,6 +804,13 @@ namespace llvm { /// disconnect it from a def-use chain linking it to a loop. void forgetValue(Value *V); + /// \brief Called when the client has changed the disposition of values in + /// this loop. + /// + /// We don't have a way to invalidate per-loop dispositions. Clear and + /// recompute is simpler. + void forgetLoopDispositions(const Loop *L) { LoopDispositions.clear(); } + /// GetMinTrailingZeros - Determine the minimum number of zero bits that S /// is guaranteed to end in (at every loop iteration). It is, at the same /// time, the minimum number of times S is divisible by 2. For example, @@ -868,11 +895,20 @@ namespace llvm { /// indirect operand. bool hasOperand(const SCEV *S, const SCEV *Op) const; - virtual bool runOnFunction(Function &F); - virtual void releaseMemory(); - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void print(raw_ostream &OS, const Module* = 0) const; - virtual void verifyAnalysis() const; + /// Return the size of an element read or written by Inst. + const SCEV *getElementSize(Instruction *Inst); + + /// Compute the array dimensions Sizes from the set of Terms extracted from + /// the memory access function of this SCEVAddRecExpr. + void findArrayDimensions(SmallVectorImpl<const SCEV *> &Terms, + SmallVectorImpl<const SCEV *> &Sizes, + const SCEV *ElementSize) const; + + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void print(raw_ostream &OS, const Module* = nullptr) const override; + void verifyAnalysis() const override; private: /// Compute the backedge taken count knowing the interval difference, the @@ -880,13 +916,13 @@ namespace llvm { const SCEV *computeBECount(const SCEV *Delta, const SCEV *Stride, bool Equality); - /// Verify if an linear IV with positive stride can overflow when in a + /// Verify if an linear IV with positive stride can overflow when in a /// less-than comparison, knowing the invariant term of the comparison, /// the stride and the knowledge of NSW/NUW flags on the recurrence. bool doesIVOverflowOnLT(const SCEV *RHS, const SCEV *Stride, bool IsSigned, bool NoWrap); - /// Verify if an linear IV with negative stride can overflow when in a + /// Verify if an linear IV with negative stride can overflow when in a /// greater-than comparison, knowing the invariant term of the comparison, /// the stride and the knowledge of NSW/NUW flags on the recurrence. bool doesIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 4433be000d77..b9bef970b5d3 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -16,9 +16,9 @@ #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ScalarEvolutionNormalization.h" +#include "llvm/Analysis/TargetFolder.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/Support/TargetFolder.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include <set> namespace llvm { @@ -92,9 +92,9 @@ namespace llvm { public: /// SCEVExpander - Construct a SCEVExpander in "canonical" mode. explicit SCEVExpander(ScalarEvolution &se, const char *name) - : SE(se), IVName(name), IVIncInsertLoop(0), IVIncInsertPos(0), + : SE(se), IVName(name), IVIncInsertLoop(nullptr), IVIncInsertPos(nullptr), CanonicalMode(true), LSRMode(false), - Builder(se.getContext(), TargetFolder(se.TD)) { + Builder(se.getContext(), TargetFolder(se.DL)) { #ifndef NDEBUG DebugType = ""; #endif @@ -131,7 +131,7 @@ namespace llvm { /// representative. Return the number of phis eliminated. unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT, SmallVectorImpl<WeakVH> &DeadInsts, - const TargetTransformInfo *TTI = NULL); + const TargetTransformInfo *TTI = nullptr); /// expandCodeFor - Insert code to directly compute the specified SCEV /// expression into the program. The inserted code is inserted into the @@ -219,7 +219,7 @@ namespace llvm { /// expression into the program. The inserted code is inserted into the /// SCEVExpander's current insertion point. If a type is specified, the /// result will be expanded to have that type, with a cast if necessary. - Value *expandCodeFor(const SCEV *SH, Type *Ty = 0); + Value *expandCodeFor(const SCEV *SH, Type *Ty = nullptr); /// getRelevantLoop - Determine the most "relevant" loop for the given SCEV. const Loop *getRelevantLoop(const SCEV *); @@ -260,7 +260,9 @@ namespace llvm { PHINode *getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, const Loop *L, Type *ExpandTy, - Type *IntTy); + Type *IntTy, + Type *&TruncTy, + bool &InvertStep); Value *expandIVInc(PHINode *PN, Value *StepV, const Loop *L, Type *ExpandTy, Type *IntTy, bool useSubtract); }; diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 9cd902a120cf..2f1b1c3841f3 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -14,6 +14,7 @@ #ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H #define LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Support/ErrorHandling.h" @@ -151,8 +152,12 @@ namespace llvm { } typedef const SCEV *const *op_iterator; + typedef iterator_range<op_iterator> op_range; op_iterator op_begin() const { return Operands; } op_iterator op_end() const { return Operands + NumOperands; } + op_range operands() const { + return make_range(op_begin(), op_end()); + } Type *getType() const { return getOperand(0)->getType(); } @@ -304,17 +309,17 @@ namespace llvm { getLoop(), FlagAnyWrap); } - /// isAffine - Return true if this is an affine AddRec (i.e., it represents - /// an expressions A+B*x where A and B are loop invariant values. + /// isAffine - Return true if this represents an expression + /// A + B*x where A and B are loop invariant values. bool isAffine() const { // We know that the start value is invariant. This expression is thus // affine iff the step is also invariant. return getNumOperands() == 2; } - /// isQuadratic - Return true if this is an quadratic AddRec (i.e., it - /// represents an expressions A+B*x+C*x^2 where A, B and C are loop - /// invariant values. This corresponds to an addrec of the form {L,+,M,+,N} + /// isQuadratic - Return true if this represents an expression + /// A + B*x + C*x^2 where A, B and C are loop invariant values. + /// This corresponds to an addrec of the form {L,+,M,+,N} bool isQuadratic() const { return getNumOperands() == 3; } @@ -352,12 +357,83 @@ namespace llvm { return S->getSCEVType() == scAddRecExpr; } - /// Splits the SCEV into two vectors of SCEVs representing the subscripts - /// and sizes of an array access. Returns the remainder of the - /// delinearization that is the offset start of the array. - const SCEV *delinearize(ScalarEvolution &SE, - SmallVectorImpl<const SCEV *> &Subscripts, - SmallVectorImpl<const SCEV *> &Sizes) const; + /// Collect parametric terms occurring in step expressions. + void collectParametricTerms(ScalarEvolution &SE, + SmallVectorImpl<const SCEV *> &Terms) const; + + /// Return in Subscripts the access functions for each dimension in Sizes. + void computeAccessFunctions(ScalarEvolution &SE, + SmallVectorImpl<const SCEV *> &Subscripts, + SmallVectorImpl<const SCEV *> &Sizes) const; + + /// Split this SCEVAddRecExpr into two vectors of SCEVs representing the + /// subscripts and sizes of an array access. + /// + /// The delinearization is a 3 step process: the first two steps compute the + /// sizes of each subscript and the third step computes the access functions + /// for the delinearized array: + /// + /// 1. Find the terms in the step functions + /// 2. Compute the array size + /// 3. Compute the access function: divide the SCEV by the array size + /// starting with the innermost dimensions found in step 2. The Quotient + /// is the SCEV to be divided in the next step of the recursion. The + /// Remainder is the subscript of the innermost dimension. Loop over all + /// array dimensions computed in step 2. + /// + /// To compute a uniform array size for several memory accesses to the same + /// object, one can collect in step 1 all the step terms for all the memory + /// accesses, and compute in step 2 a unique array shape. This guarantees + /// that the array shape will be the same across all memory accesses. + /// + /// FIXME: We could derive the result of steps 1 and 2 from a description of + /// the array shape given in metadata. + /// + /// Example: + /// + /// A[][n][m] + /// + /// for i + /// for j + /// for k + /// A[j+k][2i][5i] = + /// + /// The initial SCEV: + /// + /// A[{{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k] + /// + /// 1. Find the different terms in the step functions: + /// -> [2*m, 5, n*m, n*m] + /// + /// 2. Compute the array size: sort and unique them + /// -> [n*m, 2*m, 5] + /// find the GCD of all the terms = 1 + /// divide by the GCD and erase constant terms + /// -> [n*m, 2*m] + /// GCD = m + /// divide by GCD -> [n, 2] + /// remove constant terms + /// -> [n] + /// size of the array is A[unknown][n][m] + /// + /// 3. Compute the access function + /// a. Divide {{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k by the innermost size m + /// Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k + /// Remainder: {{{0,+,5}_i, +, 0}_j, +, 0}_k + /// The remainder is the subscript of the innermost array dimension: [5i]. + /// + /// b. Divide Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k by next outer size n + /// Quotient: {{{0,+,0}_i, +, 1}_j, +, 1}_k + /// Remainder: {{{0,+,2}_i, +, 0}_j, +, 0}_k + /// The Remainder is the subscript of the next array dimension: [2i]. + /// + /// The subscript of the outermost dimension is the Quotient: [j+k]. + /// + /// Overall, we have: A[][n][m], and the access function: A[j+k][2i][5i]. + void delinearize(ScalarEvolution &SE, + SmallVectorImpl<const SCEV *> &Subscripts, + SmallVectorImpl<const SCEV *> &Sizes, + const SCEV *ElementSize) const; }; //===--------------------------------------------------------------------===// @@ -410,8 +486,8 @@ namespace llvm { friend class ScalarEvolution; // Implement CallbackVH. - virtual void deleted(); - virtual void allUsesReplacedWith(Value *New); + void deleted() override; + void allUsesReplacedWith(Value *New) override; /// SE - The parent ScalarEvolution value. This is used to update /// the parent's maps when the value associated with a SCEVUnknown @@ -563,13 +639,14 @@ namespace llvm { : public SCEVVisitor<SCEVParameterRewriter, const SCEV*> { public: static const SCEV *rewrite(const SCEV *Scev, ScalarEvolution &SE, - ValueToValueMap &Map) { - SCEVParameterRewriter Rewriter(SE, Map); + ValueToValueMap &Map, + bool InterpretConsts = false) { + SCEVParameterRewriter Rewriter(SE, Map, InterpretConsts); return Rewriter.visit(Scev); } - SCEVParameterRewriter(ScalarEvolution &S, ValueToValueMap &M) - : SE(S), Map(M) {} + SCEVParameterRewriter(ScalarEvolution &S, ValueToValueMap &M, bool C) + : SE(S), Map(M), InterpretConsts(C) {} const SCEV *visitConstant(const SCEVConstant *Constant) { return Constant; @@ -632,8 +709,12 @@ namespace llvm { const SCEV *visitUnknown(const SCEVUnknown *Expr) { Value *V = Expr->getValue(); - if (Map.count(V)) - return SE.getUnknown(Map[V]); + if (Map.count(V)) { + Value *NV = Map[V]; + if (InterpretConsts && isa<ConstantInt>(NV)) + return SE.getConstant(cast<ConstantInt>(NV)); + return SE.getUnknown(NV); + } return Expr; } @@ -644,6 +725,7 @@ namespace llvm { private: ScalarEvolution &SE; ValueToValueMap ⤅ + bool InterpretConsts; }; typedef DenseMap<const Loop*, const SCEV*> LoopToScevMapT; diff --git a/include/llvm/Analysis/SparsePropagation.h b/include/llvm/Analysis/SparsePropagation.h index 76c8ccf59c2b..65ff2f643192 100644 --- a/include/llvm/Analysis/SparsePropagation.h +++ b/include/llvm/Analysis/SparsePropagation.h @@ -82,7 +82,7 @@ public: /// constant value, return it. Otherwise return null. The returned value /// must be in the same LLVM type as Val. virtual Constant *GetConstant(LatticeVal LV, Value *Val, SparseSolver &SS) { - return 0; + return nullptr; } /// ComputeArgument - Given a formal argument value, compute and return a diff --git a/include/llvm/Support/TargetFolder.h b/include/llvm/Analysis/TargetFolder.h index 5c1978dddb79..587a7ef5410a 100644 --- a/include/llvm/Support/TargetFolder.h +++ b/include/llvm/Analysis/TargetFolder.h @@ -1,4 +1,4 @@ -//====-- llvm/Support/TargetFolder.h - Constant folding helper -*- C++ -*-====// +//====- TargetFolder.h - Constant folding helper ---------------*- C++ -*-====// // // The LLVM Compiler Infrastructure // @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_TARGETFOLDER_H -#define LLVM_SUPPORT_TARGETFOLDER_H +#ifndef LLVM_ANALYSIS_TARGETFOLDER_H +#define LLVM_ANALYSIS_TARGETFOLDER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/Analysis/ConstantFolding.h" @@ -30,18 +30,18 @@ class DataLayout; /// TargetFolder - Create constants with target dependent folding. class TargetFolder { - const DataLayout *TD; + const DataLayout *DL; /// Fold - Fold the constant using target specific information. Constant *Fold(Constant *C) const { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) - if (Constant *CF = ConstantFoldConstantExpression(CE, TD)) + if (Constant *CF = ConstantFoldConstantExpression(CE, DL)) return CF; return C; } public: - explicit TargetFolder(const DataLayout *TheTD) : TD(TheTD) {} + explicit TargetFolder(const DataLayout *DL) : DL(DL) {} //===--------------------------------------------------------------------===// // Binary Operators @@ -211,6 +211,13 @@ public: return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy)); } + Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, + Type *DestTy) const { + if (C->getType() == DestTy) + return C; // avoid calling Fold + return Fold(ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy)); + } + //===--------------------------------------------------------------------===// // Compare Instructions //===--------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index 4f4756238929..f57f3eb009a1 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -59,11 +59,6 @@ protected: /// group's stack. void pushTTIStack(Pass *P); - /// All pass subclasses must in their finalizePass routine call popTTIStack - /// to update the pointers tracking the previous TTI instance in the analysis - /// group's stack, and the top of the analysis group's stack. - void popTTIStack(); - /// All pass subclasses must call TargetTransformInfo::getAnalysisUsage. virtual void getAnalysisUsage(AnalysisUsage &AU) const; @@ -110,7 +105,7 @@ public: /// The returned cost is defined in terms of \c TargetCostConstants, see its /// comments for a detailed explanation of the cost values. virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, - Type *OpTy = 0) const; + Type *OpTy = nullptr) const; /// \brief Estimate the cost of a GEP operation when lowered. /// @@ -203,11 +198,23 @@ public: /// The cost threshold for the unrolled loop when optimizing for size (set /// to UINT_MAX to disable). unsigned OptSizeThreshold; + /// The cost threshold for the unrolled loop, like Threshold, but used + /// for partial/runtime unrolling (set to UINT_MAX to disable). + unsigned PartialThreshold; + /// The cost threshold for the unrolled loop when optimizing for size, like + /// OptSizeThreshold, but used for partial/runtime unrolling (set to UINT_MAX + /// to disable). + unsigned PartialOptSizeThreshold; /// A forced unrolling factor (the number of concatenated bodies of the /// original loop in the unrolled loop body). When set to 0, the unrolling /// transformation will select an unrolling factor based on the current cost /// threshold and other factors. unsigned Count; + // Set the maximum unrolling factor. The unrolling factor may be selected + // using the appropriate cost threshold, but may not exceed this number + // (set to UINT_MAX to disable). This does not apply in cases where the + // loop is being fully unrolled. + unsigned MaxCount; /// Allow partial unrolling (unrolling of loops to expand the size of the /// loop body, not only to eliminate small constant-trip-count loops). bool Partial; @@ -241,20 +248,19 @@ public: PSK_FastHardware }; - /// isLegalAddImmediate - Return true if the specified immediate is legal - /// add immediate, that is the target has add instructions which can add - /// a register with the immediate without having to materialize the - /// immediate into a register. + /// \brief Return true if the specified immediate is legal add immediate, that + /// is the target has add instructions which can add a register with the + /// immediate without having to materialize the immediate into a register. virtual bool isLegalAddImmediate(int64_t Imm) const; - /// isLegalICmpImmediate - Return true if the specified immediate is legal - /// icmp immediate, that is the target has icmp instructions which can compare - /// a register against the immediate without having to materialize the - /// immediate into a register. + /// \brief Return true if the specified immediate is legal icmp immediate, + /// that is the target has icmp instructions which can compare a register + /// against the immediate without having to materialize the immediate into a + /// register. virtual bool isLegalICmpImmediate(int64_t Imm) const; - /// isLegalAddressingMode - Return true if the addressing mode represented by - /// AM is legal for this target, for a load/store of the specified type. + /// \brief Return true if the addressing mode represented by AM is legal for + /// this target, for a load/store of the specified type. /// The type may be VoidTy, in which case only return true if the addressing /// mode is legal for a load/store of any legal type. /// TODO: Handle pre/postinc as well. @@ -272,35 +278,41 @@ public: int64_t BaseOffset, bool HasBaseReg, int64_t Scale) const; - /// isTruncateFree - Return true if it's free to truncate a value of - /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in - /// register EAX to i16 by referencing its sub-register AX. + /// \brief Return true if it's free to truncate a value of type Ty1 to type + /// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16 + /// by referencing its sub-register AX. virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const; - /// Is this type legal. + /// \brief Return true if this type is legal. virtual bool isTypeLegal(Type *Ty) const; - /// getJumpBufAlignment - returns the target's jmp_buf alignment in bytes + /// \brief Returns the target's jmp_buf alignment in bytes. virtual unsigned getJumpBufAlignment() const; - /// getJumpBufSize - returns the target's jmp_buf size in bytes. + /// \brief Returns the target's jmp_buf size in bytes. virtual unsigned getJumpBufSize() const; - /// shouldBuildLookupTables - Return true if switches should be turned into - /// lookup tables for the target. + /// \brief Return true if switches should be turned into lookup tables for the + /// target. virtual bool shouldBuildLookupTables() const; - /// getPopcntSupport - Return hardware support for population count. + /// \brief Return hardware support for population count. virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; - /// haveFastSqrt -- Return true if the hardware has a fast square-root - /// instruction. + /// \brief Return true if the hardware has a fast square-root instruction. virtual bool haveFastSqrt(Type *Ty) const; - /// getIntImmCost - Return the expected cost of materializing the given - /// integer immediate of the specified type. + /// \brief Return the expected cost of materializing for the given integer + /// immediate of the specified type. virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; + /// \brief Return the expected cost of materialization for the given integer + /// immediate of the specified type for a given instruction. The cost can be + /// zero if the immediate can be folded into the specified instruction. + virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) const; + virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, + const APInt &Imm, Type *Ty) const; /// @} /// \name Vector Target Information @@ -310,15 +322,17 @@ public: enum ShuffleKind { SK_Broadcast, ///< Broadcast element 0 to all other elements. SK_Reverse, ///< Reverse the order of the vector. + SK_Alternate, ///< Choose alternate elements from vector. SK_InsertSubvector, ///< InsertSubvector. Index indicates start offset. SK_ExtractSubvector ///< ExtractSubvector Index indicates start offset. }; /// \brief Additional information about an operand's possible values. enum OperandValueKind { - OK_AnyValue, // Operand can have any value. - OK_UniformValue, // Operand is uniform (splat of a value). - OK_UniformConstantValue // Operand is uniform constant. + OK_AnyValue, // Operand can have any value. + OK_UniformValue, // Operand is uniform (splat of a value). + OK_UniformConstantValue, // Operand is uniform constant. + OK_NonUniformConstantValue // Operand is a non uniform constant value. }; /// \return The number of scalar or vector registers that the target has. @@ -343,7 +357,7 @@ public: /// The index and subtype parameters are used by the subvector insertion and /// extraction shuffle kinds. virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, - Type *SubTp = 0) const; + Type *SubTp = nullptr) const; /// \return The expected cost of cast instructions, such as bitcast, trunc, /// zext, etc. @@ -356,7 +370,7 @@ public: /// \returns The expected cost of compare and select instructions. virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, - Type *CondTy = 0) const; + Type *CondTy = nullptr) const; /// \return The expected cost of vector Insert and Extract. /// Use -1 to indicate that there is no information on the index value. diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 0392f98f075e..83b5408fb1c2 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -27,24 +27,25 @@ namespace llvm { class MDNode; class TargetLibraryInfo; - /// ComputeMaskedBits - Determine which of the bits specified in Mask are - /// known to be either zero or one and return them in the KnownZero/KnownOne - /// bit sets. This code only analyzes bits in Mask, in order to short-circuit - /// processing. + /// Determine which bits of V are known to be either zero or one and return + /// them in the KnownZero/KnownOne bit sets. /// /// This function is defined on values with integer type, values with pointer /// type (but only if TD is non-null), and vectors of integers. In the case - /// where V is a vector, the mask, known zero, and known one values are the + /// 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 ComputeMaskedBits(Value *V, APInt &KnownZero, APInt &KnownOne, - const DataLayout *TD = 0, unsigned Depth = 0); - void computeMaskedBitsLoad(const MDNode &Ranges, APInt &KnownZero); + void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, + const DataLayout *TD = nullptr, unsigned Depth = 0); + /// Compute known bits from the range metadata. + /// \p KnownZero the set of bits that are known to be zero + void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, + APInt &KnownZero); /// ComputeSignBit - Determine whether the sign bit is known to be zero or - /// one. Convenience wrapper around ComputeMaskedBits. + /// one. Convenience wrapper around computeKnownBits. void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, - const DataLayout *TD = 0, unsigned Depth = 0); + const DataLayout *TD = nullptr, unsigned Depth = 0); /// isKnownToBeAPowerOfTwo - Return true if the given value is known to have /// exactly one bit set when defined. For vectors return true if every @@ -57,7 +58,8 @@ namespace llvm { /// 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 = 0, unsigned Depth = 0); + bool isKnownNonZero(Value *V, const DataLayout *TD = nullptr, + unsigned Depth = 0); /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use /// this predicate to simplify operations downstream. Mask is known to be @@ -69,7 +71,7 @@ namespace llvm { /// 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 = 0, unsigned Depth = 0); + const DataLayout *TD = nullptr, unsigned Depth = 0); /// ComputeNumSignBits - Return the number of times the sign bit of the @@ -80,7 +82,7 @@ namespace llvm { /// /// 'Op' must have a scalar integer type. /// - unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = 0, + unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = nullptr, unsigned Depth = 0); /// ComputeMultiple - This function computes the integer multiple of Base that @@ -112,7 +114,7 @@ namespace llvm { /// insertvalues when a part of a nested struct is extracted. Value *FindInsertedValue(Value *V, ArrayRef<unsigned> idx_range, - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); /// GetPointerBaseWithConstantOffset - Analyze the specified pointer to see if /// it can be expressed as a base pointer plus a constant offset. Return the @@ -143,10 +145,10 @@ namespace llvm { /// being addressed. Note that the returned value has pointer type if the /// specified value does. If the MaxLookup value is non-zero, it limits the /// number of instructions to be stripped off. - Value *GetUnderlyingObject(Value *V, const DataLayout *TD = 0, + Value *GetUnderlyingObject(Value *V, const DataLayout *TD = nullptr, unsigned MaxLookup = 6); static inline const Value * - GetUnderlyingObject(const Value *V, const DataLayout *TD = 0, + GetUnderlyingObject(const Value *V, const DataLayout *TD = nullptr, unsigned MaxLookup = 6) { return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup); } @@ -156,7 +158,7 @@ namespace llvm { /// multiple objects. void GetUnderlyingObjects(Value *V, SmallVectorImpl<Value *> &Objects, - const DataLayout *TD = 0, + const DataLayout *TD = nullptr, unsigned MaxLookup = 6); /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer @@ -182,12 +184,12 @@ namespace llvm { /// However, this method can return true for instructions that read memory; /// for such instructions, moving them may change the resulting value. bool isSafeToSpeculativelyExecute(const Value *V, - const DataLayout *TD = 0); + const DataLayout *TD = nullptr); /// isKnownNonNull - Return true if this pointer couldn't possibly be null by /// its definition. This returns true for allocas, non-extern-weak globals /// and byval arguments. - bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = 0); + bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = nullptr); } // end namespace llvm diff --git a/include/llvm/Analysis/Verifier.h b/include/llvm/Analysis/Verifier.h deleted file mode 100644 index ce8aeef07645..000000000000 --- a/include/llvm/Analysis/Verifier.h +++ /dev/null @@ -1,75 +0,0 @@ -//===-- llvm/Analysis/Verifier.h - LLVM IR Verifier -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the function verifier interface, that can be used for some -// sanity checking of input to the system, and for checking that transformations -// haven't done something bad. -// -// Note that this does not provide full 'java style' security and verifications, -// instead it just tries to ensure that code is well formed. -// -// To see what specifically is checked, look at the top of Verifier.cpp -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_VERIFIER_H -#define LLVM_ANALYSIS_VERIFIER_H - -#include <string> - -namespace llvm { - -class FunctionPass; -class Module; -class Function; - -/// @brief An enumeration to specify the action to be taken if errors found. -/// -/// This enumeration is used in the functions below to indicate what should -/// happen if the verifier finds errors. Each of the functions that uses -/// this enumeration as an argument provides a default value for it. The -/// actions are listed below. -enum VerifierFailureAction { - AbortProcessAction, ///< verifyModule will print to stderr and abort() - PrintMessageAction, ///< verifyModule will print to stderr and return true - ReturnStatusAction ///< verifyModule will just return true -}; - -/// @brief Create a verifier pass. -/// -/// Check a module or function for validity. When the pass is used, the -/// action indicated by the \p action argument will be used if errors are -/// found. -FunctionPass *createVerifierPass( - VerifierFailureAction action = AbortProcessAction ///< Action to take -); - -/// @brief Check a module for errors. -/// -/// If there are no errors, the function returns false. If an error is found, -/// the action taken depends on the \p action parameter. -/// This should only be used for debugging, because it plays games with -/// PassManagers and stuff. - -bool verifyModule( - const Module &M, ///< The module to be verified - VerifierFailureAction action = AbortProcessAction, ///< Action to take - std::string *ErrorInfo = 0 ///< Information about failures. -); - -// verifyFunction - Check a function for errors, useful for use when debugging a -// pass. -bool verifyFunction( - const Function &F, ///< The function to be verified - VerifierFailureAction action = AbortProcessAction ///< Action to take -); - -} // End llvm namespace - -#endif diff --git a/include/llvm/Assembly/Parser.h b/include/llvm/AsmParser/Parser.h index b971c531ae05..165c46d6f271 100644 --- a/include/llvm/Assembly/Parser.h +++ b/include/llvm/AsmParser/Parser.h @@ -1,4 +1,4 @@ -//===-- llvm/Assembly/Parser.h - Parser for VM assembly files ---*- C++ -*-===// +//===-- Parser.h - Parser for LLVM IR text assembly files -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ASSEMBLY_PARSER_H -#define LLVM_ASSEMBLY_PARSER_H +#ifndef LLVM_ASMPARSER_PARSER_H +#define LLVM_ASMPARSER_PARSER_H #include <string> diff --git a/include/llvm/Assembly/PrintModulePass.h b/include/llvm/Assembly/PrintModulePass.h deleted file mode 100644 index 02b9bd9be505..000000000000 --- a/include/llvm/Assembly/PrintModulePass.h +++ /dev/null @@ -1,48 +0,0 @@ -//===- llvm/Assembly/PrintModulePass.h - Printing Pass ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines two passes to print out a module. The PrintModulePass pass -// simply prints out the entire module when it is executed. The -// PrintFunctionPass class is designed to be pipelined with other -// FunctionPass's, and prints out the functions of the module as they are -// processed. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ASSEMBLY_PRINTMODULEPASS_H -#define LLVM_ASSEMBLY_PRINTMODULEPASS_H - -#include <string> - -namespace llvm { - class FunctionPass; - class ModulePass; - class BasicBlockPass; - class raw_ostream; - - /// createPrintModulePass - Create and return a pass that writes the - /// module to the specified raw_ostream. - ModulePass *createPrintModulePass(raw_ostream *OS, - bool DeleteStream=false, - const std::string &Banner = ""); - - /// createPrintFunctionPass - Create and return a pass that prints - /// functions to the specified raw_ostream as they are processed. - FunctionPass *createPrintFunctionPass(const std::string &Banner, - raw_ostream *OS, - bool DeleteStream=false); - - /// createPrintBasicBlockPass - Create and return a pass that writes the - /// BB to the specified raw_ostream. - BasicBlockPass *createPrintBasicBlockPass(raw_ostream *OS, - bool DeleteStream=false, - const std::string &Banner = ""); -} // End llvm namespace - -#endif diff --git a/include/llvm/Assembly/Writer.h b/include/llvm/Assembly/Writer.h deleted file mode 100644 index 6b89ae022da3..000000000000 --- a/include/llvm/Assembly/Writer.h +++ /dev/null @@ -1,37 +0,0 @@ -//===-- llvm/Assembly/Writer.h - Printer for LLVM assembly files --*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This functionality is implemented by lib/VMCore/AsmWriter.cpp. -// This library is used to print LLVM assembly language files to an iostream. It -// can print LLVM code at a variety of granularities, including Modules, -// BasicBlocks, and Instructions. This makes it useful for debugging. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ASSEMBLY_WRITER_H -#define LLVM_ASSEMBLY_WRITER_H - -namespace llvm { - -class Module; -class Value; -class raw_ostream; - -// WriteAsOperand - Write the name of the specified value out to the specified -// ostream. This can be useful when you just want to print int %reg126, not the -// whole instruction that generated it. If you specify a Module for context, -// then even constants get pretty-printed; for example, the type of a null -// pointer is printed symbolically. -// -void WriteAsOperand(raw_ostream &, const Value *, bool PrintTy = true, - const Module *Context = 0); - -} // End llvm namespace - -#endif diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h new file mode 100644 index 000000000000..898cd523bd08 --- /dev/null +++ b/include/llvm/Bitcode/BitcodeWriterPass.h @@ -0,0 +1,51 @@ +//===-- BitcodeWriterPass.h - Bitcode writing pass --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file provides a bitcode writing pass. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_BITCODE_WRITER_PASS_H +#define LLVM_BITCODE_BITCODE_WRITER_PASS_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { +class Module; +class ModulePass; +class raw_ostream; +class PreservedAnalyses; + +/// \brief Create and return a pass that writes the module to the specified +/// ostream. Note that this pass is designed for use with the legacy pass +/// manager. +ModulePass *createBitcodeWriterPass(raw_ostream &Str); + +/// \brief Pass for writing a module of IR out to a bitcode file. +/// +/// Note that this is intended for use with the new pass manager. To construct +/// a pass for the legacy pass manager, use the function above. +class BitcodeWriterPass { + raw_ostream &OS; + +public: + /// \brief Construct a bitcode writer pass around a particular output stream. + explicit BitcodeWriterPass(raw_ostream &OS) : OS(OS) {} + + /// \brief Run the bitcode writer pass, and output the module to the selected + /// output stream. + PreservedAnalyses run(Module *M); + + static StringRef name() { return "BitcodeWriterPass"; } +}; + +} + +#endif diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index dc5e095155fb..6f478b72127d 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -15,7 +15,6 @@ #ifndef LLVM_BITCODE_BITSTREAMREADER_H #define LLVM_BITCODE_BITSTREAMREADER_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/Bitcode/BitCodes.h" #include "llvm/Support/Endian.h" #include "llvm/Support/StreamableMemoryObject.h" @@ -44,7 +43,7 @@ public: std::vector<std::pair<unsigned, std::string> > RecordNames; }; private: - OwningPtr<StreamableMemoryObject> BitcodeBytes; + std::unique_ptr<StreamableMemoryObject> BitcodeBytes; std::vector<BlockInfo> BlockInfoRecords; @@ -112,7 +111,7 @@ public: i != e; ++i) if (BlockInfoRecords[i].BlockID == BlockID) return &BlockInfoRecords[i]; - return 0; + return nullptr; } BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { @@ -201,9 +200,9 @@ class BitstreamCursor { public: - BitstreamCursor() : BitStream(0), NextChar(0) { - } - BitstreamCursor(const BitstreamCursor &RHS) : BitStream(0), NextChar(0) { + BitstreamCursor() : BitStream(nullptr), NextChar(0) {} + BitstreamCursor(const BitstreamCursor &RHS) + : BitStream(nullptr), NextChar(0) { operator=(RHS); } @@ -491,7 +490,7 @@ public: /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter /// the block, and return true if the block has an error. - bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0); + bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); bool ReadBlockEnd() { if (BlockScope.empty()) return true; @@ -542,7 +541,7 @@ public: void skipRecord(unsigned AbbrevID); unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, - StringRef *Blob = 0); + StringRef *Blob = nullptr); //===--------------------------------------------------------------------===// // Abbrev Processing diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index f40a0d1d259f..dcfebd9cc105 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -97,7 +97,7 @@ public: : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} ~BitstreamWriter() { - assert(CurBit == 0 && "Unflused data remaining"); + assert(CurBit == 0 && "Unflushed data remaining"); assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); // Free the BlockInfoRecords. @@ -204,7 +204,7 @@ public: i != e; ++i) if (BlockInfoRecords[i].BlockID == BlockID) return &BlockInfoRecords[i]; - return 0; + return nullptr; } void EnterSubblock(unsigned BlockID, unsigned CodeLen) { @@ -347,7 +347,7 @@ private: EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]); // Know that blob data is consumed for assertion below. - BlobData = 0; + BlobData = nullptr; } else { // Emit a vbr6 to indicate the number of elements present. EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6); @@ -378,7 +378,7 @@ private: WriteByte((unsigned char)BlobData[i]); // Know that blob data is consumed for assertion below. - BlobData = 0; + BlobData = nullptr; } else { for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) { assert(isUInt<8>(Vals[RecordIdx]) && @@ -397,7 +397,7 @@ private: } } assert(RecordIdx == Vals.size() && "Not all record operands emitted!"); - assert(BlobData == 0 && + assert(BlobData == nullptr && "Blob data specified for record that doesn't use it!"); } diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index b3d24661d70b..ee2efa2257b1 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -71,7 +71,8 @@ namespace bitc { // MODULE_CODE_PURGEVALS: [numvals] MODULE_CODE_PURGEVALS = 10, - MODULE_CODE_GCNAME = 11 // GCNAME: [strchr x N] + MODULE_CODE_GCNAME = 11, // GCNAME: [strchr x N] + MODULE_CODE_COMDAT = 12, // COMDAT: [selection_kind, name] }; /// PARAMATTR blocks have code for defining a parameter attribute set. @@ -289,7 +290,7 @@ namespace bitc { FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...] // 17 is unused. // 18 is unused. - FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, op, align] + FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, opty, op, align] FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol] // 21 is unused. // 22 is unused. @@ -311,7 +312,7 @@ namespace bitc { // 32 is unused. FUNC_CODE_DEBUG_LOC_AGAIN = 33, // DEBUG_LOC_AGAIN - FUNC_CODE_INST_CALL = 34, // CALL: [attr, fnty, fnid, args...] + FUNC_CODE_INST_CALL = 34, // CALL: [attr, cc, fnty, fnid, args...] FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal] FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope] @@ -370,7 +371,19 @@ namespace bitc { ATTR_KIND_Z_EXT = 34, ATTR_KIND_BUILTIN = 35, ATTR_KIND_COLD = 36, - ATTR_KIND_OPTIMIZE_NONE = 37 + ATTR_KIND_OPTIMIZE_NONE = 37, + ATTR_KIND_IN_ALLOCA = 38, + ATTR_KIND_NON_NULL = 39, + ATTR_KIND_JUMP_TABLE = 40, + ATTR_KIND_DEREFERENCEABLE = 41 + }; + + enum ComdatSelectionKindCodes { + COMDAT_SELECTION_KIND_ANY = 1, + COMDAT_SELECTION_KIND_EXACT_MATCH = 2, + COMDAT_SELECTION_KIND_LARGEST = 3, + COMDAT_SELECTION_KIND_NO_DUPLICATES = 4, + COMDAT_SELECTION_KIND_SAME_SIZE = 5, }; } // End bitc namespace diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 78f40ca17e61..8cf573544f8d 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -14,6 +14,7 @@ #ifndef LLVM_BITCODE_READERWRITER_H #define LLVM_BITCODE_READERWRITER_H +#include "llvm/Support/ErrorOr.h" #include <string> namespace llvm { @@ -25,14 +26,11 @@ namespace llvm { class ModulePass; class raw_ostream; - /// getLazyBitcodeModule - Read the header of the specified bitcode buffer - /// and prepare for lazy deserialization of function bodies. If successful, - /// this takes ownership of 'buffer' and returns a non-null pointer. On - /// error, this returns null, *does not* take ownership of Buffer, and fills - /// in *ErrMsg with an error description if ErrMsg is non-null. - Module *getLazyBitcodeModule(MemoryBuffer *Buffer, - LLVMContext &Context, - std::string *ErrMsg = 0); + /// Read the header of the specified bitcode buffer and prepare for lazy + /// deserialization of function bodies. If successful, this takes ownership + /// of 'buffer. On error, this *does not* take ownership of Buffer. + ErrorOr<Module *> getLazyBitcodeModule(MemoryBuffer *Buffer, + LLVMContext &Context); /// getStreamedBitcodeModule - Read the header of the specified stream /// and prepare for lazy deserialization and streaming of function bodies. @@ -41,32 +39,24 @@ namespace llvm { Module *getStreamedBitcodeModule(const std::string &name, DataStreamer *streamer, LLVMContext &Context, - std::string *ErrMsg = 0); + std::string *ErrMsg = nullptr); - /// getBitcodeTargetTriple - 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 "", and fills in *ErrMsg - /// if ErrMsg is non-null. + /// 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, - std::string *ErrMsg = 0); + LLVMContext &Context); - /// ParseBitcodeFile - Read the specified bitcode file, returning the module. - /// If an error occurs, this returns null and fills in *ErrMsg if it is - /// non-null. This method *never* takes ownership of Buffer. - Module *ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext &Context, - std::string *ErrMsg = 0); + /// Read the specified bitcode file, returning the module. + /// This method *never* takes ownership of Buffer. + ErrorOr<Module *> parseBitcodeFile(MemoryBuffer *Buffer, + LLVMContext &Context); /// WriteBitcodeToFile - Write the specified module to the specified /// raw output stream. For streams where it matters, the given stream /// should be in "binary" mode. void WriteBitcodeToFile(const Module *M, raw_ostream &Out); - /// createBitcodeWriterPass - Create and return a pass that writes the module - /// to the specified ostream. - ModulePass *createBitcodeWriterPass(raw_ostream &Str); - /// isBitcodeWrapper - Return true if the given bytes are the magic bytes /// for an LLVM IR bitcode wrapper. diff --git a/include/llvm/CMakeLists.txt b/include/llvm/CMakeLists.txt index 32ffca75bb7a..ca4fd1338ed7 100644 --- a/include/llvm/CMakeLists.txt +++ b/include/llvm/CMakeLists.txt @@ -2,12 +2,19 @@ add_subdirectory(IR) if( MSVC_IDE OR XCODE ) # Creates a dummy target containing all headers for the benefit of - # Visual Studio users. + # XCode and Visual Studio users. file(GLOB_RECURSE headers *.h) add_td_sources(headers) add_library(llvm_headers_do_not_build EXCLUDE_FROM_ALL # We need at least one source file: ${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello/Hello.cpp ${headers}) - set_target_properties(llvm_headers_do_not_build PROPERTIES FOLDER "Misc") + set_target_properties(llvm_headers_do_not_build PROPERTIES FOLDER "Misc" + EXCLUDE_FROM_DEFAULT_BUILD ON) endif() + +# If we're doing an out-of-tree build, copy a module map for generated +# header files into the build area. +if (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") + configure_file(module.modulemap.build module.modulemap COPYONLY) +endif (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index b2cc7047b30b..b791ba09adaf 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file declares several CodeGen-specific LLVM IR analysis utilties. +// This file declares several CodeGen-specific LLVM IR analysis utilities. // //===----------------------------------------------------------------------===// @@ -17,19 +17,19 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" -#include "llvm/Support/CallSite.h" namespace llvm { - class GlobalVariable; -class TargetLowering; class TargetLoweringBase; +class TargetLowering; +class TargetMachine; class SDNode; 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 @@ -55,7 +55,7 @@ inline unsigned ComputeLinearIndex(Type *Ty, /// void ComputeValueVTs(const TargetLowering &TLI, Type *Ty, SmallVectorImpl<EVT> &ValueVTs, - SmallVectorImpl<uint64_t> *Offsets = 0, + SmallVectorImpl<uint64_t> *Offsets = nullptr, uint64_t StartingOffset = 0); /// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. @@ -87,7 +87,7 @@ ISD::CondCode getICmpCondCode(ICmpInst::Predicate Pred); /// between it and the return. /// /// This function only tests target-independent requirements. -bool isInTailCallPosition(ImmutableCallSite CS, const TargetLowering &TLI); +bool isInTailCallPosition(ImmutableCallSite CS, const TargetMachine &TM); /// Test if given that the input instruction is in the tail call position if the /// return type or any attributes of the function will inhibit tail call diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 4bda0f1603ac..e1c9a14c9009 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -16,486 +16,496 @@ #ifndef LLVM_CODEGEN_ASMPRINTER_H #define LLVM_CODEGEN_ASMPRINTER_H +#include "llvm/ADT/Twine.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/IR/InlineAsm.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { - class BlockAddress; - class GCStrategy; - class Constant; - class ConstantArray; - class GCMetadataPrinter; - class GlobalValue; - class GlobalVariable; - class MachineBasicBlock; - class MachineFunction; - class MachineInstr; - class MachineLocation; - class MachineLoopInfo; - class MachineLoop; - class MachineConstantPoolValue; - class MachineJumpTableInfo; - class MachineModuleInfo; - class MCAsmInfo; - class MCCFIInstruction; - class MCContext; - class MCInstrInfo; - class MCSection; - class MCStreamer; - class MCSymbol; - class MDNode; - class DwarfDebug; - class DwarfException; - class Mangler; - class TargetLoweringObjectFile; - class DataLayout; - class TargetMachine; - - /// AsmPrinter - This class is intended to be used as a driving class for all - /// asm writers. - class AsmPrinter : public MachineFunctionPass { - public: - /// Target machine description. - /// - TargetMachine &TM; - - /// Target Asm Printer information. - /// - const MCAsmInfo *MAI; - - const MCInstrInfo *MII; - /// OutContext - This is the context for the output file that we are - /// streaming. This owns all of the global MC-related objects for the - /// generated translation unit. - MCContext &OutContext; - - /// OutStreamer - This is the MCStreamer object for the file we are - /// generating. This contains the transient state for the current - /// translation unit that we are generating (such as the current section - /// etc). - MCStreamer &OutStreamer; - - /// The current machine function. - const MachineFunction *MF; - - /// MMI - This is a pointer to the current MachineModuleInfo. - MachineModuleInfo *MMI; - - /// Name-mangler for global names. - /// - Mangler *Mang; - - /// The symbol for the current function. This is recalculated at the - /// beginning of each call to runOnMachineFunction(). - /// - MCSymbol *CurrentFnSym; - - /// The symbol used to represent the start of the current function for the - /// purpose of calculating its size (e.g. using the .size directive). By - /// default, this is equal to CurrentFnSym. - MCSymbol *CurrentFnSymForSize; - - private: - // GCMetadataPrinters - The garbage collection metadata printer table. - void *GCMetadataPrinters; // Really a DenseMap. - - /// VerboseAsm - Emit comments in assembly output if this is true. - /// - bool VerboseAsm; - static char ID; - - /// If VerboseAsm is set, a pointer to the loop info for this - /// function. - MachineLoopInfo *LI; - - /// DD - If the target supports dwarf debug info, this pointer is non-null. - DwarfDebug *DD; - - /// DE - If the target supports dwarf exception info, this pointer is - /// non-null. - DwarfException *DE; - - protected: - explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer); - - public: - virtual ~AsmPrinter(); - - const DwarfDebug *getDwarfDebug() const { return DD; } - - /// isVerbose - Return true if assembly output should contain comments. - /// - bool isVerbose() const { return VerboseAsm; } - - /// getFunctionNumber - Return a unique ID for the current function. - /// - unsigned getFunctionNumber() const; - - /// getObjFileLowering - Return information about object file lowering. - const TargetLoweringObjectFile &getObjFileLowering() const; - - /// getDataLayout - Return information about data layout. - const DataLayout &getDataLayout() const; - - /// getTargetTriple - Return the target triple string. - StringRef getTargetTriple() const; - - /// getCurrentSection() - Return the current section we are emitting to. - const MCSection *getCurrentSection() const; - - MCSymbol *getSymbol(const GlobalValue *GV) const; - - //===------------------------------------------------------------------===// - // MachineFunctionPass Implementation. - //===------------------------------------------------------------------===// - - /// getAnalysisUsage - Record analysis usage. - /// - void getAnalysisUsage(AnalysisUsage &AU) const; - - /// doInitialization - Set up the AsmPrinter when we are working on a new - /// module. If your pass overrides this, it must make sure to explicitly - /// call this implementation. - bool doInitialization(Module &M); - - /// doFinalization - Shut down the asmprinter. If you override this in your - /// pass, you must make sure to call it explicitly. - bool doFinalization(Module &M); - - /// runOnMachineFunction - Emit the specified function out to the - /// OutStreamer. - virtual bool runOnMachineFunction(MachineFunction &MF) { - SetupMachineFunction(MF); - EmitFunctionHeader(); - EmitFunctionBody(); - return false; - } +class AsmPrinterHandler; +class BlockAddress; +class ByteStreamer; +class GCStrategy; +class Constant; +class ConstantArray; +class GCMetadataPrinter; +class GlobalValue; +class GlobalVariable; +class MachineBasicBlock; +class MachineFunction; +class MachineInstr; +class MachineLocation; +class MachineLoopInfo; +class MachineLoop; +class MachineConstantPoolValue; +class MachineJumpTableInfo; +class MachineModuleInfo; +class MCAsmInfo; +class MCCFIInstruction; +class MCContext; +class MCInst; +class MCInstrInfo; +class MCSection; +class MCStreamer; +class MCSubtargetInfo; +class MCSymbol; +class MDNode; +class DwarfDebug; +class Mangler; +class TargetLoweringObjectFile; +class DataLayout; +class TargetMachine; + +/// This class is intended to be used as a driving class for all asm writers. +class AsmPrinter : public MachineFunctionPass { +public: + /// Target machine description. + /// + TargetMachine &TM; + + /// Target Asm Printer information. + /// + const MCAsmInfo *MAI; + + const MCInstrInfo *MII; + /// This is the context for the output file that we are streaming. This owns + /// all of the global MC-related objects for the generated translation unit. + MCContext &OutContext; + + /// This is the MCStreamer object for the file we are generating. This + /// contains the transient state for the current translation unit that we are + /// generating (such as the current section etc). + MCStreamer &OutStreamer; + + /// The current machine function. + const MachineFunction *MF; + + /// This is a pointer to the current MachineModuleInfo. + MachineModuleInfo *MMI; + + /// Name-mangler for global names. + /// + Mangler *Mang; + + /// The symbol for the current function. This is recalculated at the beginning + /// of each call to runOnMachineFunction(). + /// + MCSymbol *CurrentFnSym; + + /// The symbol used to represent the start of the current function for the + /// purpose of calculating its size (e.g. using the .size directive). By + /// default, this is equal to CurrentFnSym. + MCSymbol *CurrentFnSymForSize; + +private: + // The garbage collection metadata printer table. + void *GCMetadataPrinters; // Really a DenseMap. + + /// Emit comments in assembly output if this is true. + /// + bool VerboseAsm; + static char ID; + + /// If VerboseAsm is set, a pointer to the loop info for this function. + MachineLoopInfo *LI; + + struct HandlerInfo { + AsmPrinterHandler *Handler; + const char *TimerName, *TimerGroupName; + HandlerInfo(AsmPrinterHandler *Handler, const char *TimerName, + const char *TimerGroupName) + : Handler(Handler), TimerName(TimerName), + TimerGroupName(TimerGroupName) {} + }; + /// A vector of all debug/EH info emitters we should use. This vector + /// maintains ownership of the emitters. + SmallVector<HandlerInfo, 1> Handlers; - //===------------------------------------------------------------------===// - // Coarse grained IR lowering routines. - //===------------------------------------------------------------------===// + /// If the target supports dwarf debug info, this pointer is non-null. + DwarfDebug *DD; - /// SetupMachineFunction - This should be called when a new MachineFunction - /// is being processed from runOnMachineFunction. - void SetupMachineFunction(MachineFunction &MF); +protected: + explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer); - /// EmitFunctionHeader - This method emits the header for the current - /// function. - void EmitFunctionHeader(); - - /// EmitFunctionBody - This method emits the body and trailer for a - /// function. - void EmitFunctionBody(); - - void emitPrologLabel(const MachineInstr &MI); +public: + virtual ~AsmPrinter(); - enum CFIMoveType { - CFI_M_None, - CFI_M_EH, - CFI_M_Debug - }; - CFIMoveType needsCFIMoves(); - - bool needsSEHMoves(); + DwarfDebug *getDwarfDebug() { return DD; } - /// needsRelocationsForDwarfStringPool - Specifies whether the object format - /// expects to use relocations to refer to debug entries. Alternatively we - /// emit section offsets in bytes from the start of the string pool. - bool needsRelocationsForDwarfStringPool() const; + /// Return true if assembly output should contain comments. + /// + bool isVerbose() const { return VerboseAsm; } - /// EmitConstantPool - Print to the current output stream assembly - /// representations of the constants in the constant pool MCP. This is - /// used to print out constants which have been "spilled to memory" by - /// the code generator. - /// - virtual void EmitConstantPool(); + /// Return a unique ID for the current function. + /// + unsigned getFunctionNumber() const; - /// EmitJumpTableInfo - Print assembly representations of the jump tables - /// used by the current function to the current output stream. - /// - void EmitJumpTableInfo(); + /// Return information about object file lowering. + const TargetLoweringObjectFile &getObjFileLowering() const; - /// EmitGlobalVariable - Emit the specified global variable to the .s file. - virtual void EmitGlobalVariable(const GlobalVariable *GV); + /// Return information about data layout. + const DataLayout &getDataLayout() const; - /// EmitSpecialLLVMGlobal - Check to see if the specified global is a - /// special global used by LLVM. If so, emit it and return true, otherwise - /// do nothing and return false. - bool EmitSpecialLLVMGlobal(const GlobalVariable *GV); - - /// EmitAlignment - Emit an alignment directive to the specified power of - /// two boundary. For example, if you pass in 3 here, you will get an 8 - /// byte alignment. If a global value is specified, and if that global has - /// an explicit alignment requested, it will override the alignment request - /// if required for correctness. - /// - void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const; - - /// EmitBasicBlockStart - This method prints the label for the specified - /// MachineBasicBlock, an alignment (if present) and a comment describing - /// it if appropriate. - void EmitBasicBlockStart(const MachineBasicBlock *MBB) const; - - /// \brief Print a general LLVM constant to the .s file. - void EmitGlobalConstant(const Constant *CV); - - - //===------------------------------------------------------------------===// - // Overridable Hooks - //===------------------------------------------------------------------===// - - // Targets can, or in the case of EmitInstruction, must implement these to - // customize output. - - /// EmitStartOfAsmFile - This virtual method can be overridden by targets - /// that want to emit something at the start of their file. - virtual void EmitStartOfAsmFile(Module &) {} - - /// EmitEndOfAsmFile - This virtual method can be overridden by targets that - /// want to emit something at the end of their file. - virtual void EmitEndOfAsmFile(Module &) {} - - /// EmitFunctionBodyStart - Targets can override this to emit stuff before - /// the first basic block in the function. - virtual void EmitFunctionBodyStart() {} - - /// EmitFunctionBodyEnd - Targets can override this to emit stuff after - /// the last basic block in the function. - virtual void EmitFunctionBodyEnd() {} - - /// EmitInstruction - Targets should implement this to emit instructions. - virtual void EmitInstruction(const MachineInstr *) { - llvm_unreachable("EmitInstruction not implemented"); - } - - virtual void EmitFunctionEntryLabel(); - - virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); - - /// EmitXXStructor - Targets can override this to change how global - /// constants that are part of a C++ static/global constructor list are - /// emitted. - virtual void EmitXXStructor(const Constant *CV) { - EmitGlobalConstant(CV); - } - - /// isBlockOnlyReachableByFallthough - Return true if the basic block has - /// exactly one predecessor and the control transfer mechanism between - /// the predecessor and this block is a fall-through. - virtual bool - isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; - - /// emitImplicitDef - Targets can override this to customize the output of - /// IMPLICIT_DEF instructions in verbose mode. - virtual void emitImplicitDef(const MachineInstr *MI) const; - - //===------------------------------------------------------------------===// - // Symbol Lowering Routines. - //===------------------------------------------------------------------===// - public: - - /// GetTempSymbol - Return the MCSymbol corresponding to the assembler - /// temporary label with the specified stem and unique ID. - MCSymbol *GetTempSymbol(StringRef Name, unsigned ID) const; - - /// GetTempSymbol - Return an assembler temporary label with the specified - /// stem. - MCSymbol *GetTempSymbol(StringRef Name) const; - - - /// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with - /// global value name as its base, with the specified suffix, and where the - /// symbol is forced to have private linkage if ForcePrivate is true. - MCSymbol *GetSymbolWithGlobalValueBase(const GlobalValue *GV, - StringRef Suffix, - bool ForcePrivate = true) const; - - /// GetExternalSymbolSymbol - Return the MCSymbol for the specified - /// ExternalSymbol. - MCSymbol *GetExternalSymbolSymbol(StringRef Sym) const; - - /// GetCPISymbol - Return the symbol for the specified constant pool entry. - MCSymbol *GetCPISymbol(unsigned CPID) const; - - /// GetJTISymbol - Return the symbol for the specified jump table entry. - MCSymbol *GetJTISymbol(unsigned JTID, bool isLinkerPrivate = false) const; - - /// GetJTSetSymbol - Return the symbol for the specified jump table .set - /// FIXME: privatize to AsmPrinter. - MCSymbol *GetJTSetSymbol(unsigned UID, unsigned MBBID) const; - - /// GetBlockAddressSymbol - Return the MCSymbol used to satisfy BlockAddress - /// uses of the specified basic block. - MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA) const; - MCSymbol *GetBlockAddressSymbol(const BasicBlock *BB) const; - - //===------------------------------------------------------------------===// - // Emission Helper Routines. - //===------------------------------------------------------------------===// - public: - /// printOffset - This is just convenient handler for printing offsets. - void printOffset(int64_t Offset, raw_ostream &OS) const; - - /// EmitInt8 - Emit a byte directive and value. - /// - void EmitInt8(int Value) const; - - /// EmitInt16 - Emit a short directive and value. - /// - void EmitInt16(int Value) const; - - /// EmitInt32 - Emit a long directive and value. - /// - void EmitInt32(int Value) const; - - /// EmitLabelDifference - Emit something like ".long Hi-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 EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, - unsigned Size) const; - - /// EmitLabelOffsetDifference - 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; - - /// EmitLabelPlusOffset - 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. - void EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, - unsigned Size, - bool IsSectionRelative = false) const; - - /// EmitLabelReference - Emit something like ".long Label" - /// where the size in bytes of the directive is specified by Size and Label - /// specifies the label. - void EmitLabelReference(const MCSymbol *Label, unsigned Size, - bool IsSectionRelative = false) const { - EmitLabelPlusOffset(Label, 0, Size, IsSectionRelative); - } - - //===------------------------------------------------------------------===// - // Dwarf Emission Helper Routines - //===------------------------------------------------------------------===// - - /// EmitSLEB128 - emit the specified signed leb128 value. - void EmitSLEB128(int64_t Value, const char *Desc = 0) const; - - /// EmitULEB128 - emit the specified unsigned leb128 value. - void EmitULEB128(uint64_t Value, const char *Desc = 0, - unsigned PadTo = 0) const; - - /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. - void EmitCFAByte(unsigned Val) const; - - /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an - /// encoding. If verbose assembly output is enabled, we output comments - /// describing the encoding. Desc is a string saying what the encoding is - /// specifying (e.g. "LSDA"). - void EmitEncodingByte(unsigned Val, const char *Desc = 0) const; - - /// GetSizeOfEncodedValue - Return the size of the encoding in bytes. - unsigned GetSizeOfEncodedValue(unsigned Encoding) const; - - /// EmitReference - Emit reference to a ttype global with a specified encoding. - void EmitTTypeReference(const GlobalValue *GV, unsigned Encoding) const; - - /// EmitSectionOffset - Emit the 4-byte offset of Label from the start of - /// its section. This can be done with a special directive if the target - /// supports it (e.g. cygwin) or by emitting it as an offset from a label at - /// the start of the section. - /// - /// SectionLabel is a temporary label emitted at the start of the section - /// that Label lives in. - void EmitSectionOffset(const MCSymbol *Label, - const MCSymbol *SectionLabel) const; - - /// getISAEncoding - Get the value for DW_AT_APPLE_isa. Zero if no isa - /// encoding specified. - virtual unsigned getISAEncoding() { return 0; } - - /// EmitDwarfRegOp - Emit dwarf register operation. - virtual void EmitDwarfRegOp(const MachineLocation &MLoc, - bool Indirect) const; - - //===------------------------------------------------------------------===// - // Dwarf Lowering Routines - //===------------------------------------------------------------------===// - - /// \brief Emit frame instruction to describe the layout of the frame. - void emitCFIInstruction(const MCCFIInstruction &Inst) const; - - //===------------------------------------------------------------------===// - // Inline Asm Support - //===------------------------------------------------------------------===// - public: - // These are hooks that targets can override to implement inline asm - // support. These should probably be moved out of AsmPrinter someday. - - /// PrintSpecial - Print information related to the specified machine instr - /// that is independent of the operand, and may be independent of the instr - /// itself. This can be useful for portably encoding the comment character - /// or other bits of target-specific knowledge into the asmstrings. The - /// syntax used is ${:comment}. Targets can override this to add support - /// for their own strange codes. - virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS, - const char *Code) const; - - /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM - /// instruction, using the specified assembler variant. Targets should - /// override this to format as appropriate. This method can return true if - /// the operand is erroneous. - virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &OS); - - /// PrintAsmMemoryOperand - Print the specified operand of MI, an INLINEASM - /// instruction, using the specified assembler variant as an address. - /// Targets should override this to format as appropriate. This method can - /// return true if the operand is erroneous. - virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode, raw_ostream &OS); - - private: - /// Private state for PrintSpecial() - // Assign a unique ID to this machine instruction. - mutable const MachineInstr *LastMI; - mutable unsigned LastFn; - mutable unsigned Counter; - mutable unsigned SetCounter; - - /// EmitInlineAsm - Emit a blob of inline asm to the output streamer. - void EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = 0, - InlineAsm::AsmDialect AsmDialect = - InlineAsm::AD_ATT) const; - - /// EmitInlineAsm - This method formats and emits the specified machine - /// instruction that is an inline asm. - void EmitInlineAsm(const MachineInstr *MI) const; - - //===------------------------------------------------------------------===// - // Internal Implementation Details - //===------------------------------------------------------------------===// - - /// EmitVisibility - This emits visibility information about symbol, if - /// this is suported by the target. - void EmitVisibility(MCSymbol *Sym, unsigned Visibility, - bool IsDefinition = true) const; - - void EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; - - void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, - const MachineBasicBlock *MBB, unsigned uid) const; - void EmitLLVMUsedList(const ConstantArray *InitList); - /// Emit llvm.ident metadata in an '.ident' directive. - void EmitModuleIdents(Module &M); - void EmitXXStructorList(const Constant *List, bool isCtor); - GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C); - }; + /// Return information about subtarget. + const MCSubtargetInfo &getSubtargetInfo() const; + + void EmitToStreamer(MCStreamer &S, const MCInst &Inst); + + /// Return the target triple string. + StringRef getTargetTriple() const; + + /// Return the current section we are emitting to. + const MCSection *getCurrentSection() const; + + void getNameWithPrefix(SmallVectorImpl<char> &Name, + const GlobalValue *GV) const; + + MCSymbol *getSymbol(const GlobalValue *GV) const; + + //===------------------------------------------------------------------===// + // MachineFunctionPass Implementation. + //===------------------------------------------------------------------===// + + /// Record analysis usage. + /// + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// Set up the AsmPrinter when we are working on a new module. If your pass + /// overrides this, it must make sure to explicitly call this implementation. + bool doInitialization(Module &M) override; + + /// Shut down the asmprinter. If you override this in your pass, you must make + /// sure to call it explicitly. + bool doFinalization(Module &M) override; + + /// Emit the specified function out to the OutStreamer. + bool runOnMachineFunction(MachineFunction &MF) override { + SetupMachineFunction(MF); + EmitFunctionHeader(); + EmitFunctionBody(); + return false; + } + + //===------------------------------------------------------------------===// + // Coarse grained IR lowering routines. + //===------------------------------------------------------------------===// + + /// This should be called when a new MachineFunction is being processed from + /// runOnMachineFunction. + void SetupMachineFunction(MachineFunction &MF); + + /// This method emits the header for the current function. + void EmitFunctionHeader(); + + /// This method emits the body and trailer for a function. + void EmitFunctionBody(); + + void emitCFIInstruction(const MachineInstr &MI); + + enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; + CFIMoveType needsCFIMoves(); + + bool needsSEHMoves(); + + /// Print to the current output stream assembly representations of the + /// constants in the constant pool MCP. This is used to print out constants + /// which have been "spilled to memory" by the code generator. + /// + virtual void EmitConstantPool(); + + /// Print assembly representations of the jump tables used by the current + /// function to the current output stream. + /// + void EmitJumpTableInfo(); + + /// Emit the specified global variable to the .s file. + virtual void EmitGlobalVariable(const GlobalVariable *GV); + + /// Check to see if the specified global is a special global used by LLVM. If + /// so, emit it and return true, otherwise do nothing and return false. + bool EmitSpecialLLVMGlobal(const GlobalVariable *GV); + + /// Emit an alignment directive to the specified power of two boundary. For + /// example, if you pass in 3 here, you will get an 8 byte alignment. If a + /// global value is specified, and if that global has an explicit alignment + /// requested, it will override the alignment request if required for + /// correctness. + /// + void EmitAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) const; + + /// This method prints the label for the specified MachineBasicBlock, an + /// alignment (if present) and a comment describing it if appropriate. + void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; + + /// \brief Print a general LLVM constant to the .s file. + void EmitGlobalConstant(const Constant *CV); + + //===------------------------------------------------------------------===// + // Overridable Hooks + //===------------------------------------------------------------------===// + + // Targets can, or in the case of EmitInstruction, must implement these to + // customize output. + + /// This virtual method can be overridden by targets that want to emit + /// something at the start of their file. + virtual void EmitStartOfAsmFile(Module &) {} + + /// This virtual method can be overridden by targets that want to emit + /// something at the end of their file. + virtual void EmitEndOfAsmFile(Module &) {} + + /// Targets can override this to emit stuff before the first basic block in + /// the function. + virtual void EmitFunctionBodyStart() {} + + /// Targets can override this to emit stuff after the last basic block in the + /// function. + virtual void EmitFunctionBodyEnd() {} + + /// Targets should implement this to emit instructions. + virtual void EmitInstruction(const MachineInstr *) { + llvm_unreachable("EmitInstruction not implemented"); + } + + /// Return the symbol for the specified constant pool entry. + virtual MCSymbol *GetCPISymbol(unsigned CPID) const; + + virtual void EmitFunctionEntryLabel(); + + virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); + + /// Targets can override this to change how global constants that are part of + /// a C++ static/global constructor list are emitted. + virtual void EmitXXStructor(const Constant *CV) { EmitGlobalConstant(CV); } + + /// Return true if the basic block has exactly one predecessor and the control + /// transfer mechanism between the predecessor and this block is a + /// fall-through. + virtual bool + isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const; + + /// Targets can override this to customize the output of IMPLICIT_DEF + /// instructions in verbose mode. + virtual void emitImplicitDef(const MachineInstr *MI) const; + + //===------------------------------------------------------------------===// + // Symbol Lowering Routines. + //===------------------------------------------------------------------===// +public: + /// Return the MCSymbol corresponding to the assembler temporary label with + /// the specified stem and unique ID. + MCSymbol *GetTempSymbol(Twine Name, unsigned ID) const; + + /// Return an assembler temporary label with the specified stem. + MCSymbol *GetTempSymbol(Twine Name) const; + + /// Return the MCSymbol for a private symbol with global value name as its + /// base, with the specified suffix. + MCSymbol *getSymbolWithGlobalValueBase(const GlobalValue *GV, + StringRef Suffix) const; + + /// Return the MCSymbol for the specified ExternalSymbol. + MCSymbol *GetExternalSymbolSymbol(StringRef Sym) const; + + /// Return the symbol for the specified jump table entry. + MCSymbol *GetJTISymbol(unsigned JTID, bool isLinkerPrivate = false) const; + + /// Return the symbol for the specified jump table .set + /// FIXME: privatize to AsmPrinter. + MCSymbol *GetJTSetSymbol(unsigned UID, unsigned MBBID) const; + + /// Return the MCSymbol used to satisfy BlockAddress uses of the specified + /// basic block. + MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA) const; + MCSymbol *GetBlockAddressSymbol(const BasicBlock *BB) const; + + //===------------------------------------------------------------------===// + // Emission Helper Routines. + //===------------------------------------------------------------------===// +public: + /// This is just convenient handler for printing offsets. + void printOffset(int64_t Offset, raw_ostream &OS) const; + + /// Emit a byte directive and value. + /// + void EmitInt8(int Value) const; + + /// Emit a short directive and value. + /// + void EmitInt16(int Value) const; + + /// Emit a long directive and value. + /// + void EmitInt32(int Value) const; + + /// Emit something like ".long Hi-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 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. + void EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, + unsigned Size, bool IsSectionRelative = false) const; + + /// Emit something like ".long Label" where the size in bytes of the directive + /// is specified by Size and Label specifies the label. + void EmitLabelReference(const MCSymbol *Label, unsigned Size, + bool IsSectionRelative = false) const { + EmitLabelPlusOffset(Label, 0, Size, IsSectionRelative); + } + + //===------------------------------------------------------------------===// + // Dwarf Emission Helper Routines + //===------------------------------------------------------------------===// + + /// Emit the specified signed leb128 value. + void EmitSLEB128(int64_t Value, const char *Desc = nullptr) const; + + /// Emit the specified unsigned leb128 value. + void EmitULEB128(uint64_t Value, const char *Desc = nullptr, + unsigned PadTo = 0) const; + + /// Emit a .byte 42 directive for a DW_CFA_xxx value. + void EmitCFAByte(unsigned Val) const; + + /// Emit a .byte 42 directive that corresponds to an encoding. If verbose + /// assembly output is enabled, we output comments describing the encoding. + /// Desc is a string saying what the encoding is specifying (e.g. "LSDA"). + void EmitEncodingByte(unsigned Val, const char *Desc = nullptr) const; + + /// Return the size of the encoding in bytes. + unsigned GetSizeOfEncodedValue(unsigned Encoding) const; + + /// Emit reference to a ttype global with a specified encoding. + void EmitTTypeReference(const GlobalValue *GV, unsigned Encoding) const; + + /// Emit the 4-byte offset of Label from the start of its section. This can + /// be done with a special directive if the target supports it (e.g. cygwin) + /// or by emitting it as an offset from a label at the start of the section. + /// + /// SectionLabel is a temporary label emitted at the start of the section + /// that Label lives in. + void EmitSectionOffset(const MCSymbol *Label, + const MCSymbol *SectionLabel) const; + + /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. + virtual unsigned getISAEncoding() { return 0; } + + /// \brief Emit a partial DWARF register operation. + /// \param MLoc the register + /// \param PieceSize size and + /// \param PieceOffset offset of the piece in bits, if this is one + /// piece of an aggregate value. + /// + /// If size and offset is zero an operation for the entire + /// register is emitted: Some targets do not provide a DWARF + /// register number for every register. If this is the case, this + /// function will attempt to emit a DWARF register by emitting a + /// piece of a super-register or by piecing together multiple + /// subregisters that alias the register. + void EmitDwarfRegOpPiece(ByteStreamer &BS, const MachineLocation &MLoc, + unsigned PieceSize = 0, + unsigned PieceOffset = 0) const; + + /// Emit dwarf register operation. + /// \param Indirect whether this is a register-indirect address + virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc, + bool Indirect) const; + + //===------------------------------------------------------------------===// + // Dwarf Lowering Routines + //===------------------------------------------------------------------===// + + /// \brief Emit frame instruction to describe the layout of the frame. + void emitCFIInstruction(const MCCFIInstruction &Inst) const; + + //===------------------------------------------------------------------===// + // Inline Asm Support + //===------------------------------------------------------------------===// +public: + // These are hooks that targets can override to implement inline asm + // support. These should probably be moved out of AsmPrinter someday. + + /// Print information related to the specified machine instr that is + /// independent of the operand, and may be independent of the instr itself. + /// This can be useful for portably encoding the comment character or other + /// bits of target-specific knowledge into the asmstrings. The syntax used is + /// ${:comment}. Targets can override this to add support for their own + /// strange codes. + virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS, + const char *Code) const; + + /// Print the specified operand of MI, an INLINEASM instruction, using the + /// specified assembler variant. Targets should override this to format as + /// appropriate. This method can return true if the operand is erroneous. + virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS); + + /// Print the specified operand of MI, an INLINEASM instruction, using the + /// specified assembler variant as an address. Targets should override this to + /// format as appropriate. This method can return true if the operand is + /// erroneous. + virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS); + + /// 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. + /// \p StartInfo - the original subtarget info before inline asm + /// \p EndInfo - the final subtarget info after parsing the inline asm, + /// or NULL if the value is unknown. + virtual void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, + const MCSubtargetInfo *EndInfo) const; + +private: + /// Private state for PrintSpecial() + // Assign a unique ID to this machine instruction. + mutable const MachineInstr *LastMI; + mutable unsigned LastFn; + mutable unsigned Counter; + mutable unsigned SetCounter; + + /// Emit a blob of inline asm to the output streamer. + void + EmitInlineAsm(StringRef Str, const MDNode *LocMDNode = nullptr, + InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT) const; + + /// This method formats and emits the specified machine instruction that is an + /// inline asm. + void EmitInlineAsm(const MachineInstr *MI) const; + + //===------------------------------------------------------------------===// + // Internal Implementation Details + //===------------------------------------------------------------------===// + + /// This emits visibility information about symbol, if this is suported by the + /// target. + void EmitVisibility(MCSymbol *Sym, unsigned Visibility, + bool IsDefinition = true) const; + + void EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; + + void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, + const MachineBasicBlock *MBB, unsigned uid) const; + void EmitLLVMUsedList(const ConstantArray *InitList); + /// Emit llvm.ident metadata in an '.ident' directive. + void EmitModuleIdents(Module &M); + void EmitXXStructorList(const Constant *List, bool isCtor); + GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &C); +}; } #endif diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index a18f433bda40..04af4bd4d59d 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -18,14 +18,14 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/CallingConv.h" #include "llvm/Target/TargetCallingConv.h" namespace llvm { - class TargetRegisterInfo; - class TargetMachine; - class CCState; +class CCState; +class MVT; +class TargetMachine; +class TargetRegisterInfo; /// CCValAssign - Represent assignment of one arg/retval to a location. class CCValAssign { @@ -39,6 +39,7 @@ public: VExt, // The value is vector-widened in the location. // FIXME: Not implemented yet. Code that uses AExt to mean // vector-widen should be fixed to use VExt instead. + FPExt, // The floating-point value is fp-extended in the location. Indirect // The location contains pointer to the value. // TODO: a subset of the value is in the location. }; @@ -111,6 +112,23 @@ public: return Ret; } + // There is no need to differentiate between a pending CCValAssign and other + // kinds, as they are stored in a different list. + static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, + LocInfo HTP) { + return getReg(ValNo, ValVT, 0, LocVT, HTP); + } + + void convertToReg(unsigned RegNo) { + Loc = RegNo; + isMem = false; + } + + void convertToMem(unsigned Offset) { + Loc = Offset; + isMem = true; + } + unsigned getValNo() const { return ValNo; } MVT getValVT() const { return ValVT; } @@ -163,6 +181,7 @@ private: unsigned StackOffset; SmallVector<uint32_t, 16> UsedRegs; + SmallVector<CCValAssign, 4> PendingLocs; // ByValInfo and SmallVector<ByValInfo, 4> ByValRegs: // @@ -278,7 +297,7 @@ public: /// getFirstUnallocated - Return the first unallocated register in the set, or /// NumRegs if they are all allocated. - unsigned getFirstUnallocated(const uint16_t *Regs, unsigned NumRegs) const { + unsigned getFirstUnallocated(const MCPhysReg *Regs, unsigned NumRegs) const { for (unsigned i = 0; i != NumRegs; ++i) if (!isAllocated(Regs[i])) return i; @@ -305,7 +324,7 @@ public: /// AllocateReg - Attempt to allocate one of the specified registers. If none /// are available, return zero. Otherwise, return the first one available, /// marking it and any aliases as allocated. - unsigned AllocateReg(const uint16_t *Regs, unsigned NumRegs) { + unsigned AllocateReg(const MCPhysReg *Regs, unsigned NumRegs) { unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); if (FirstUnalloc == NumRegs) return 0; // Didn't find the reg. @@ -316,8 +335,33 @@ public: return Reg; } + /// 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) { + bool BlockAvailable = true; + // Check for already-allocated regs in this block + for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) { + if (isAllocated(Regs[StartIdx + BlockIdx])) { + BlockAvailable = false; + break; + } + } + if (BlockAvailable) { + // Mark the entire block as allocated + for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) { + MarkAllocated(Regs[StartIdx + BlockIdx]); + } + return Regs[StartIdx]; + } + } + // No block was available + return 0; + } + /// Version of AllocateReg with list of registers to be shadowed. - unsigned AllocateReg(const uint16_t *Regs, const uint16_t *ShadowRegs, + unsigned AllocateReg(const MCPhysReg *Regs, const MCPhysReg *ShadowRegs, unsigned NumRegs) { unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); if (FirstUnalloc == NumRegs) @@ -347,6 +391,15 @@ public: return AllocateStack(Size, Align); } + /// Version of AllocateStack with list of extra registers to be shadowed. + /// Note that, unlike AllocateReg, this shadows ALL of the shadow registers. + unsigned AllocateStack(unsigned Size, unsigned Align, + const MCPhysReg *ShadowRegs, unsigned NumShadowRegs) { + for (unsigned i = 0; i < NumShadowRegs; ++i) + MarkAllocated(ShadowRegs[i]); + return AllocateStack(Size, Align); + } + // HandleByVal - Allocate a stack slot large enough to pass an argument by // value. The size and alignment information of the argument is encoded in its // parameter attribute. @@ -394,8 +447,18 @@ public: ByValRegs.clear(); } + // Rewind byval registers tracking info. + void rewindByValRegsInfo() { + InRegsParamsProceed = 0; + } + ParmContext getCallOrPrologue() const { return CallOrPrologue; } + // Get list of pending assignments + SmallVectorImpl<llvm::CCValAssign> &getPendingLocs() { + return PendingLocs; + } + private: /// MarkAllocated - Mark a register and all of its aliases as allocated. void MarkAllocated(unsigned Reg); diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index bc8dce33356e..449d93418a4c 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -16,9 +16,11 @@ #ifndef LLVM_CODEGEN_COMMANDFLAGS_H #define LLVM_CODEGEN_COMMANDFLAGS_H +#include "llvm/MC/MCTargetOptionsCommandFlags.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" #include <string> using namespace llvm; @@ -68,11 +70,6 @@ CMModel("code-model", "Large code model"), clEnumValEnd)); -cl::opt<bool> -RelaxAll("mc-relax-all", - cl::desc("When used with filetype=obj, " - "relax all fixups in the emitted object file")); - cl::opt<TargetMachine::CodeGenFileType> FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile), cl::desc("Choose a file type (not all types are supported by all targets):"), @@ -85,15 +82,6 @@ FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile), "Emit nothing, for performance testing"), clEnumValEnd)); -cl::opt<bool> DisableDotLoc("disable-dot-loc", cl::Hidden, - cl::desc("Do not use .loc entries")); - -cl::opt<bool> DisableCFI("disable-cfi", cl::Hidden, - cl::desc("Do not use .cfi_* directives")); - -cl::opt<bool> EnableDwarfDirectory("enable-dwarf-directory", cl::Hidden, - cl::desc("Use .file directives with an explicit directory.")); - cl::opt<bool> DisableRedZone("disable-red-zone", cl::desc("Do not emit code that uses the red zone."), @@ -192,11 +180,6 @@ EnablePIE("enable-pie", cl::init(false)); cl::opt<bool> -SegmentedStacks("segmented-stacks", - cl::desc("Use segmented stacks if possible."), - cl::init(false)); - -cl::opt<bool> UseInitArray("use-init-array", cl::desc("Use .init_array instead of .ctors."), cl::init(false)); @@ -210,4 +193,59 @@ cl::opt<std::string> StartAfter("start-after", cl::value_desc("pass-name"), cl::init("")); +cl::opt<bool> DataSections("data-sections", + cl::desc("Emit data into separate sections"), + cl::init(false)); + +cl::opt<bool> +FunctionSections("function-sections", + cl::desc("Emit functions into separate sections"), + cl::init(false)); + +cl::opt<llvm::JumpTable::JumpTableType> +JTableType("jump-table-type", + cl::desc("Choose the type of Jump-Instruction Table for jumptable."), + cl::init(JumpTable::Single), + cl::values( + clEnumValN(JumpTable::Single, "single", + "Create a single table for all jumptable functions"), + clEnumValN(JumpTable::Arity, "arity", + "Create one table per number of parameters."), + clEnumValN(JumpTable::Simplified, "simplified", + "Create one table per simplified function type."), + clEnumValN(JumpTable::Full, "full", + "Create one table per unique function type."), + clEnumValEnd)); + +// Common utility function tightly tied to the options listed here. Initializes +// a TargetOptions object with CodeGen flags and returns it. +static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { + TargetOptions Options; + Options.LessPreciseFPMADOption = EnableFPMAD; + Options.NoFramePointerElim = DisableFPElim; + Options.AllowFPOpFusion = FuseFPOps; + Options.UnsafeFPMath = EnableUnsafeFPMath; + Options.NoInfsFPMath = EnableNoInfsFPMath; + Options.NoNaNsFPMath = EnableNoNaNsFPMath; + Options.HonorSignDependentRoundingFPMathOption = + EnableHonorSignDependentRoundingFPMath; + Options.UseSoftFloat = GenerateSoftFloatCalls; + if (FloatABIForCalls != FloatABI::Default) + Options.FloatABIType = FloatABIForCalls; + Options.NoZerosInBSS = DontPlaceZerosInBSS; + Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt; + Options.DisableTailCalls = DisableTailCalls; + Options.StackAlignmentOverride = OverrideStackAlignment; + Options.TrapFuncName = TrapFuncName; + Options.PositionIndependentExecutable = EnablePIE; + Options.UseInitArray = UseInitArray; + Options.DataSections = DataSections; + Options.FunctionSections = FunctionSections; + + Options.MCOptions = InitMCTargetOptionsFromFlags(); + Options.JTType = JTableType; + + return Options; +} + #endif diff --git a/include/llvm/CodeGen/EdgeBundles.h b/include/llvm/CodeGen/EdgeBundles.h index e8a4a2d2d894..c31fad246c96 100644 --- a/include/llvm/CodeGen/EdgeBundles.h +++ b/include/llvm/CodeGen/EdgeBundles.h @@ -55,15 +55,10 @@ public: void view() const; private: - virtual bool runOnMachineFunction(MachineFunction&); - virtual void getAnalysisUsage(AnalysisUsage&) const; + bool runOnMachineFunction(MachineFunction&) override; + void getAnalysisUsage(AnalysisUsage&) const override; }; -/// Specialize WriteGraph, the standard implementation won't work. -raw_ostream &WriteGraph(raw_ostream &O, const EdgeBundles &G, - bool ShortNames = false, - const Twine &Title = ""); - } // end namespace llvm #endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 1e0ef6b545ea..0d1b1dc09560 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -16,23 +16,28 @@ #define LLVM_CODEGEN_FASTISEL_H #include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Target/TargetLowering.h" +#include "llvm/IR/CallingConv.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 MachineFrameInfo; class MachineRegisterInfo; -class DataLayout; class TargetInstrInfo; class TargetLibraryInfo; class TargetLowering; @@ -45,15 +50,154 @@ 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. class FastISel { + 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; + 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) { } + + 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 IsReturnValueUsed : 1; + + // IsTailCall should be modified by implementations of + // FastLowerCall that perform tail call conversions. + bool IsTailCall; + + unsigned NumFixedArgs; + CallingConv::ID CallConv; + const Value *Callee; + const char *SymName; + ArgListTy Args; + ImmutableCallSite *CS; + MachineInstr *Call; + unsigned ResultReg; + unsigned NumResultRegs; + + SmallVector<Value *, 16> OutVals; + SmallVector<ISD::ArgFlagsTy, 16> OutFlags; + SmallVector<unsigned, 16> OutRegs; + SmallVector<ISD::InputArg, 4> Ins; + 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) + {} + + CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, + const Value *Target, ArgListTy &&ArgsList, + ImmutableCallSite &Call) { + RetTy = ResultTy; + Callee = Target; + + IsInReg = Call.paramHasAttr(0, Attribute::InReg); + DoesNotReturn = Call.doesNotReturn(); + IsVarArg = FuncTy->isVarArg(); + IsReturnValueUsed = !Call.getInstruction()->use_empty(); + RetSExt = Call.paramHasAttr(0, Attribute::SExt); + RetZExt = Call.paramHasAttr(0, Attribute::ZExt); + + CallConv = Call.getCallingConv(); + NumFixedArgs = FuncTy->getNumParams(); + Args = std::move(ArgsList); + + CS = &Call; + + return *this; + } + + CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, + const char *Target, ArgListTy &&ArgsList, + ImmutableCallSite &Call, + unsigned FixedArgs = ~0U) { + RetTy = ResultTy; + Callee = Call.getCalledValue(); + SymName = Target; + + IsInReg = Call.paramHasAttr(0, Attribute::InReg); + DoesNotReturn = Call.doesNotReturn(); + IsVarArg = FuncTy->isVarArg(); + IsReturnValueUsed = !Call.getInstruction()->use_empty(); + RetSExt = Call.paramHasAttr(0, Attribute::SExt); + RetZExt = Call.paramHasAttr(0, Attribute::ZExt); + + CallConv = Call.getCallingConv(); + NumFixedArgs = (FixedArgs == ~0U) ? FuncTy->getNumParams() : FixedArgs; + Args = std::move(ArgsList); + + CS = &Call; + + return *this; + } + + CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultTy, + const Value *Target, ArgListTy &&ArgsList, + unsigned FixedArgs = ~0U) { + RetTy = ResultTy; + Callee = Target; + CallConv = CC; + NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs; + Args = std::move(ArgsList); + return *this; + } + + CallLoweringInfo &setTailCall(bool Value = true) { + IsTailCall = Value; + return *this; + } + + ArgListTy &getArgs() { + return Args; + } + + void clearOuts() { + OutVals.clear(); + OutFlags.clear(); + OutRegs.clear(); + } + + void clearIns() { + Ins.clear(); + InRegs.clear(); + } + }; + protected: DenseMap<const Value *, unsigned> LocalValueMap; FunctionLoweringInfo &FuncInfo; + MachineFunction *MF; MachineRegisterInfo &MRI; MachineFrameInfo &MFI; MachineConstantPool &MCP; - DebugLoc DL; + DebugLoc DbgLoc; const TargetMachine &TM; - const DataLayout &TD; + const DataLayout &DL; const TargetInstrInfo &TII; const TargetLowering &TLI; const TargetRegisterInfo &TRI; @@ -87,7 +231,7 @@ public: void startNewBlock(); /// Return current debug location information. - DebugLoc getCurDebugLoc() const { return DL; } + 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. @@ -170,13 +314,20 @@ protected: /// 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; + virtual bool TargetSelectInstruction(const Instruction *I) = 0; /// This method is called by target-independent code to do target specific /// argument lowering. It returns true if it was successful. virtual bool FastLowerArguments(); + /// \brief This method is called by target-independent code to do target + /// specific call lowering. It returns true if it was successful. + virtual bool FastLowerCall(CallLoweringInfo &CLI); + + /// \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); + /// 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, @@ -343,6 +494,12 @@ protected: 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. + unsigned constrainOperandRegClass(const MCInstrDesc &II, unsigned Op, + unsigned OpNum); + /// Emit a constant in a register using target-specific logic, such as /// constant pool loads. virtual unsigned TargetMaterializeConstant(const Constant* C) { @@ -367,6 +524,15 @@ 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 Create a machine mem operand from the given instruction. + MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const; + + bool LowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs); + bool LowerCallTo(CallLoweringInfo &CLI); + private: bool SelectBinaryOp(const User *I, unsigned ISDOpcode); @@ -374,7 +540,11 @@ private: bool SelectGetElementPtr(const User *I); - bool SelectCall(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); @@ -403,8 +573,11 @@ private: /// heavy instructions like calls. void flushLocalValueMap(); - /// Test whether the given value has exactly one use. - bool hasTrivialKill(const Value *V) const; + bool addStackMapLiveVars(SmallVectorImpl<MachineOperand> &Ops, + const CallInst *CI, unsigned StartIdx); + bool lowerCallOperands(const CallInst *CI, unsigned ArgIdx, unsigned NumArgs, + const Value *Callee, bool ForceRetVoidTy, + CallLoweringInfo &CLI); }; } diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 50d320f8e839..9636b51e303d 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -21,7 +21,6 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/Target/TargetRegisterInfo.h" @@ -41,6 +40,8 @@ class MachineBasicBlock; class MachineFunction; class MachineModuleInfo; class MachineRegisterInfo; +class SelectionDAG; +class MVT; class TargetLowering; class Value; @@ -125,7 +126,7 @@ public: /// set - Initialize this FunctionLoweringInfo with the given Function /// and its associated MachineFunction. /// - void set(const Function &Fn, MachineFunction &MF); + void set(const Function &Fn, MachineFunction &MF, SelectionDAG *DAG); /// clear - Clear out all the function-specific state. This returns this /// FunctionLoweringInfo to an empty state, ready to be used for a @@ -152,11 +153,11 @@ public: /// register is a PHI destination and the PHI's LiveOutInfo is not valid. const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg) { if (!LiveOutRegInfo.inBounds(Reg)) - return NULL; + return nullptr; const LiveOutInfo *LOI = &LiveOutRegInfo[Reg]; if (!LOI->IsValid) - return NULL; + return nullptr; return LOI; } diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index 1070d29f7381..ddcc823ecd9e 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -35,8 +35,10 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/Pass.h" -#include "llvm/Support/DebugLoc.h" + +#include <memory> namespace llvm { class AsmPrinter; @@ -163,7 +165,7 @@ namespace llvm { /// class GCModuleInfo : public ImmutablePass { typedef StringMap<GCStrategy*> strategy_map_type; - typedef std::vector<GCStrategy*> list_type; + typedef std::vector<std::unique_ptr<GCStrategy>> list_type; typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type; strategy_map_type StrategyMap; @@ -178,7 +180,6 @@ namespace llvm { static char ID; GCModuleInfo(); - ~GCModuleInfo(); /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should /// call it in doFinalization(). diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index dfc26d72dc9f..81e1f85286e1 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -54,7 +54,7 @@ namespace llvm { /// be abstractly described. class GCStrategy { public: - typedef std::vector<GCFunctionInfo*> list_type; + typedef std::vector<std::unique_ptr<GCFunctionInfo>> list_type; typedef list_type::iterator iterator; private: @@ -77,7 +77,7 @@ namespace llvm { public: GCStrategy(); - virtual ~GCStrategy(); + virtual ~GCStrategy() {} /// getName - The name of the GC strategy, for debugging. diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index 456d2dcb51a6..bb170c85cbf8 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -17,13 +17,13 @@ namespace llvm { class GCStrategy; class GCMetadataPrinter; - + /// FIXME: Collector instances are not useful on their own. These no longer /// serve any purpose except to link in the plugins. - + /// Creates an ocaml-compatible garbage collector. void linkOcamlGC(); - + /// Creates an ocaml-compatible metadata printer. void linkOcamlGCPrinter(); @@ -32,7 +32,7 @@ namespace llvm { /// Creates an erlang-compatible metadata printer. void linkErlangGCPrinter(); - + /// Creates a shadow stack garbage collector. This collector requires no code /// generator support. void linkShadowStackGC(); diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 48a0523dc618..84447616c989 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -72,6 +72,11 @@ namespace ISD { /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, + /// READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on + /// the DAG, which implements the named register global variables extension. + READ_REGISTER, + WRITE_REGISTER, + /// FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to /// first (possible) on-stack argument. This is needed for correct stack /// adjustment during unwind. @@ -374,6 +379,37 @@ namespace ISD { /// operand, a ValueType node. SIGN_EXTEND_INREG, + /// ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an + /// in-register any-extension of the low lanes of an integer vector. The + /// result type must have fewer elements than the operand type, and those + /// elements must be larger integer types such that the total size of the + /// operand type and the result type match. Each of the low operand + /// elements is any-extended into the corresponding, wider result + /// elements with the high bits becoming undef. + ANY_EXTEND_VECTOR_INREG, + + /// SIGN_EXTEND_VECTOR_INREG(Vector) - This operator represents an + /// in-register sign-extension of the low lanes of an integer vector. The + /// result type must have fewer elements than the operand type, and those + /// elements must be larger integer types such that the total size of the + /// operand type and the result type match. Each of the low operand + /// elements is sign-extended into the corresponding, wider result + /// elements. + // FIXME: The SIGN_EXTEND_INREG node isn't specifically limited to + // scalars, but it also doesn't handle vectors well. Either it should be + // restricted to scalars or this node (and its handling) should be merged + // into it. + SIGN_EXTEND_VECTOR_INREG, + + /// ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an + /// in-register zero-extension of the low lanes of an integer vector. The + /// result type must have fewer elements than the operand type, and those + /// elements must be larger integer types such that the total size of the + /// operand type and the result type match. Each of the low operand + /// elements is zero-extended into the corresponding, wider result + /// elements. + ZERO_EXTEND_VECTOR_INREG, + /// FP_TO_[US]INT - Convert a floating point value to a signed or unsigned /// integer. FP_TO_SINT, @@ -436,11 +472,11 @@ namespace ISD { /// 5) ISD::CvtCode indicating the type of conversion to do CONVERT_RNDSAT, - /// FP16_TO_FP32, FP32_TO_FP16 - These operators are used to perform - /// promotions and truncation for half-precision (16 bit) floating - /// numbers. We need special nodes since FP16 is a storage-only type with - /// special semantics of operations. - FP16_TO_FP32, FP32_TO_FP16, + /// FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions + /// and truncation for half-precision (16 bit) floating numbers. These nodes + /// form a semi-softened interface for dealing with f16 (as an i16), which + /// is often a storage-only type but has native conversions. + FP16_TO_FP, FP_TO_FP16, /// FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, /// FLOG, FLOG2, FLOG10, FEXP, FEXP2, @@ -603,7 +639,7 @@ namespace ISD { /// This corresponds to "load atomic" instruction. ATOMIC_LOAD, - /// OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr, val) + /// OUTCHAIN = ATOMIC_STORE(INCHAIN, ptr, val) /// This corresponds to "store atomic" instruction. ATOMIC_STORE, @@ -614,6 +650,12 @@ namespace ISD { /// This corresponds to the cmpxchg instruction. ATOMIC_CMP_SWAP, + /// Val, Success, OUTCHAIN + /// = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) + /// N.b. this is still a strong cmpxchg operation, so + /// Success == "Val == cmp". + ATOMIC_CMP_SWAP_WITH_SUCCESS, + /// Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) /// Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) /// For double-word atomic operations: @@ -702,6 +744,8 @@ namespace ISD { LAST_LOADEXT_TYPE }; + NodeType getExtForLoadExtType(LoadExtType); + //===--------------------------------------------------------------------===// /// ISD::CondCode enum - These are ordered carefully to make the bitfields /// below work out, when considering SETFALSE (something that never exists diff --git a/include/llvm/CodeGen/IntrinsicLowering.h b/include/llvm/CodeGen/IntrinsicLowering.h index 68389dde494f..9e6ab7d45977 100644 --- a/include/llvm/CodeGen/IntrinsicLowering.h +++ b/include/llvm/CodeGen/IntrinsicLowering.h @@ -24,13 +24,13 @@ namespace llvm { class DataLayout; class IntrinsicLowering { - const DataLayout& TD; + const DataLayout& DL; bool Warned; public: - explicit IntrinsicLowering(const DataLayout &td) : - TD(td), Warned(false) {} + explicit IntrinsicLowering(const DataLayout &DL) : + DL(DL), Warned(false) {} /// AddPrototypes - This method, if called, causes all of the prototypes /// that might be needed by an intrinsic lowering implementation to be diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h index 9a7321418698..dc2a0272db4e 100644 --- a/include/llvm/CodeGen/JITCodeEmitter.h +++ b/include/llvm/CodeGen/JITCodeEmitter.h @@ -51,7 +51,7 @@ class Function; /// occurred, more memory is allocated, and we reemit the code into it. /// class JITCodeEmitter : public MachineCodeEmitter { - virtual void anchor(); + void anchor() override; public: virtual ~JITCodeEmitter() {} @@ -59,15 +59,15 @@ public: /// about to be code generated. This initializes the BufferBegin/End/Ptr /// fields. /// - virtual void startFunction(MachineFunction &F) = 0; + 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. /// - virtual bool finishFunction(MachineFunction &F) = 0; - + 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, @@ -248,19 +248,19 @@ public: /// emitLabel - Emits a label - virtual void emitLabel(MCSymbol *Label) = 0; + 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. - virtual void *allocateSpace(uintptr_t Size, unsigned Alignment) { + 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 = 0; + Result = nullptr; } else { // Allocate the space. Result = CurBufferPtr; @@ -278,18 +278,18 @@ public: /// StartMachineBasicBlock - This should be called by the target when a new /// basic block is about to be emitted. This way the MCE knows where the /// start of the block is, and can implement getMachineBasicBlockAddress. - virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0; - + void StartMachineBasicBlock(MachineBasicBlock *MBB) override = 0; + /// getCurrentPCValue - This returns the address that the next emitted byte /// will be output to. /// - virtual uintptr_t getCurrentPCValue() const { + 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 { + uintptr_t getCurrentPCOffset() const override { return CurBufferPtr-BufferBegin; } @@ -298,42 +298,45 @@ public: /// 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 { return true; } + bool earlyResolveAddresses() const override { return true; } /// addRelocation - Whenever a relocatable address is needed, it should be /// noted with this interface. - virtual void addRelocation(const MachineRelocation &MR) = 0; - + 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. /// - virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const = 0; + 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. /// - virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const = 0; - + 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. /// - virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0; + uintptr_t + getMachineBasicBlockAddress(MachineBasicBlock *MBB) const override = 0; /// getLabelAddress - Return the address of the specified Label, only usable /// after the Label has been emitted. /// - virtual uintptr_t getLabelAddress(MCSymbol *Label) const = 0; - + uintptr_t getLabelAddress(MCSymbol *Label) const override = 0; + /// Specifies the MachineModuleInfo object. This is used for exception handling /// purposes. - virtual void setModuleInfo(MachineModuleInfo* Info) = 0; + 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 0; } + virtual DenseMap<MCSymbol*, uintptr_t> *getLabelLocations() { + return nullptr; + } }; } // End llvm namespace diff --git a/include/llvm/CodeGen/JumpInstrTables.h b/include/llvm/CodeGen/JumpInstrTables.h new file mode 100644 index 000000000000..6ca3d7d1765f --- /dev/null +++ b/include/llvm/CodeGen/JumpInstrTables.h @@ -0,0 +1,104 @@ +//===-- JumpInstrTables.h: Jump-Instruction Tables --------------*- C++ -*-===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief An implementation of tables consisting of jump instructions +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_JUMPINSTRTABLES_H +#define LLVM_CODEGEN_JUMPINSTRTABLES_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetOptions.h" + +namespace llvm { +class Constant; +class Function; +class FunctionType; +class JumpInstrTableInfo; +class Module; + +/// A class to manage a set of jump tables indexed on function type. It looks at +/// each function in the module to find all the functions that have the +/// jumptable attribute set. For each such function, it creates a new +/// jump-instruction-table function and stores the mapping in the ImmutablePass +/// JumpInstrTableInfo. +/// +/// These special functions get lowered in AsmPrinter to assembly of the form: +/// \verbatim +/// .globl f +/// .type f,@function +/// .align 8,0x90 +/// f: +/// jmp f_orig@PLT +/// \endverbatim +/// +/// Support for an architecture depends on two functions in TargetInstrInfo: +/// getUnconditionalBranch, and getTrap. AsmPrinter uses these to generate the +/// appropriate instructions for the jump statement (an unconditional branch) +/// and for padding to make the table have a size that is a power of two. This +/// padding uses a trap instruction to ensure that calls to this area halt the +/// program. The default implementations of these functions call +/// llvm_unreachable. +class JumpInstrTables : public ModulePass { +public: + static char ID; + + JumpInstrTables(); + JumpInstrTables(JumpTable::JumpTableType JTT); + virtual ~JumpInstrTables(); + bool runOnModule(Module &M) override; + const char *getPassName() const override { return "Jump-Instruction Tables"; } + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// Creates a jump-instruction table function for the Target and adds it to + /// the tables. + Function *insertEntry(Module &M, Function *Target); + + /// Checks to see if there is already a table for the given FunctionType. + bool hasTable(FunctionType *FunTy); + +private: + /// The metadata used while a jump table is being built + struct TableMeta { + /// The number of this table + unsigned TableNum; + + /// The current number of jump entries in the table. + unsigned Count; + }; + + typedef DenseMap<FunctionType *, struct TableMeta> JumpMap; + + /// Maps the function into a subset of function types, depending on the + /// jump-instruction table style selected from JumpTableTypes in + /// JumpInstrTables.cpp. The choice of mapping determines the number of + /// jump-instruction tables generated by this pass. E.g., the simplest mapping + /// converts every function type into void f(); so, all functions end up in a + /// single table. + FunctionType *transformType(FunctionType *FunTy); + + /// The current state of functions and jump entries in the table(s). + JumpMap Metadata; + + /// The ImmutablePass that stores information about the generated tables. + JumpInstrTableInfo *JITI; + + /// The total number of tables. + unsigned TableCount; + + /// The type of tables to build. + JumpTable::JumpTableType JTType; +}; + +/// Creates a JumpInstrTables pass for the given type of jump table. +ModulePass *createJumpInstrTablesPass(JumpTable::JumpTableType JTT); +} + +#endif /* LLVM_CODEGEN_JUMPINSTRTABLES_H */ diff --git a/include/llvm/CodeGen/LatencyPriorityQueue.h b/include/llvm/CodeGen/LatencyPriorityQueue.h index d454347d0b82..cf601ae5384c 100644 --- a/include/llvm/CodeGen/LatencyPriorityQueue.h +++ b/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -47,22 +47,22 @@ namespace llvm { LatencyPriorityQueue() : Picker(this) { } - bool isBottomUp() const { return false; } + bool isBottomUp() const override { return false; } - void initNodes(std::vector<SUnit> &sunits) { + void initNodes(std::vector<SUnit> &sunits) override { SUnits = &sunits; NumNodesSolelyBlocking.resize(SUnits->size(), 0); } - void addNode(const SUnit *SU) { + void addNode(const SUnit *SU) override { NumNodesSolelyBlocking.resize(SUnits->size(), 0); } - void updateNode(const SUnit *SU) { + void updateNode(const SUnit *SU) override { } - void releaseState() { - SUnits = 0; + void releaseState() override { + SUnits = nullptr; } unsigned getLatency(unsigned NodeNum) const { @@ -75,21 +75,21 @@ namespace llvm { return NumNodesSolelyBlocking[NodeNum]; } - bool empty() const { return Queue.empty(); } + bool empty() const override { return Queue.empty(); } - virtual void push(SUnit *U); + void push(SUnit *U) override; - virtual SUnit *pop(); + SUnit *pop() override; - virtual void remove(SUnit *SU); + void remove(SUnit *SU) override; - virtual void dump(ScheduleDAG* DAG) const; + void dump(ScheduleDAG* DAG) const override; // scheduledNode - As nodes are scheduled, we look to see if there are any // successor nodes that have a single unscheduled predecessor. If so, that // single predecessor has a higher priority, since scheduling it will make // the node available. - void scheduledNode(SUnit *Node); + void scheduledNode(SUnit *Node) override; private: void AdjustPriorityOfUnscheduledPreds(SUnit *SU); diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 26563a605574..036aea30a510 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -21,16 +21,17 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" -#include "llvm/Support/DebugLoc.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include <utility> +#include <unordered_map> namespace llvm { class MachineInstr; class MachineBasicBlock; class MachineFunction; -class LexicalScope; //===----------------------------------------------------------------------===// /// InsnRange - This is used to track range of instructions with identical @@ -39,37 +40,130 @@ class LexicalScope; typedef std::pair<const MachineInstr *, const MachineInstr *> InsnRange; //===----------------------------------------------------------------------===// +/// LexicalScope - This class is used to track scope information. +/// +class LexicalScope { + +public: + LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) + : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), + LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) { + if (Parent) + Parent->addChild(this); + } + + // Accessors. + LexicalScope *getParent() const { return Parent; } + const MDNode *getDesc() const { return Desc; } + const MDNode *getInlinedAt() const { return InlinedAtLocation; } + const MDNode *getScopeNode() const { return Desc; } + bool isAbstractScope() const { return AbstractScope; } + SmallVectorImpl<LexicalScope *> &getChildren() { return Children; } + SmallVectorImpl<InsnRange> &getRanges() { return Ranges; } + + /// addChild - Add a child scope. + void addChild(LexicalScope *S) { Children.push_back(S); } + + /// openInsnRange - This scope covers instruction range starting from MI. + void openInsnRange(const MachineInstr *MI) { + if (!FirstInsn) + FirstInsn = MI; + + if (Parent) + Parent->openInsnRange(MI); + } + + /// extendInsnRange - Extend the current instruction range covered by + /// this scope. + void extendInsnRange(const MachineInstr *MI) { + assert(FirstInsn && "MI Range is not open!"); + LastInsn = MI; + if (Parent) + Parent->extendInsnRange(MI); + } + + /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected + /// until now. This is used when a new scope is encountered while walking + /// machine instructions. + void closeInsnRange(LexicalScope *NewScope = nullptr) { + assert(LastInsn && "Last insn missing!"); + Ranges.push_back(InsnRange(FirstInsn, LastInsn)); + FirstInsn = nullptr; + LastInsn = nullptr; + // If Parent dominates NewScope then do not close Parent's instruction + // range. + if (Parent && (!NewScope || !Parent->dominates(NewScope))) + Parent->closeInsnRange(NewScope); + } + + /// dominates - Return true if current scope dominates given lexical scope. + bool dominates(const LexicalScope *S) const { + if (S == this) + return true; + if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut()) + return true; + return false; + } + + // Depth First Search support to walk and manipulate LexicalScope hierarchy. + unsigned getDFSOut() const { return DFSOut; } + void setDFSOut(unsigned O) { DFSOut = O; } + unsigned getDFSIn() const { return DFSIn; } + void setDFSIn(unsigned I) { DFSIn = I; } + + /// dump - print lexical scope. + void dump(unsigned Indent = 0) const; + +private: + LexicalScope *Parent; // Parent to this scope. + AssertingVH<const MDNode> Desc; // Debug info descriptor. + AssertingVH<const MDNode> InlinedAtLocation; // Location at which this + // scope is inlined. + bool AbstractScope; // Abstract Scope + SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope. + // Contents not owned. + SmallVector<InsnRange, 4> Ranges; + + const MachineInstr *LastInsn; // Last instruction of this scope. + const MachineInstr *FirstInsn; // First instruction of this scope. + unsigned DFSIn, DFSOut; // In & Out Depth use to determine + // scope nesting. +}; + +//===----------------------------------------------------------------------===// /// LexicalScopes - This class provides interface to collect and use lexical /// scoping information from machine instruction. /// class LexicalScopes { public: - LexicalScopes() : MF(NULL), CurrentFnLexicalScope(NULL) { } - virtual ~LexicalScopes(); + LexicalScopes() : MF(nullptr), CurrentFnLexicalScope(nullptr) {} - /// initialize - Scan machine function and constuct lexical scope nest. - virtual void initialize(const MachineFunction &); + /// initialize - Scan machine function and constuct lexical scope nest, resets + /// the instance if necessary. + void initialize(const MachineFunction &); /// releaseMemory - release memory. - virtual void releaseMemory(); - + void reset(); + /// empty - Return true if there is any lexical scope information available. - bool empty() { return CurrentFnLexicalScope == NULL; } + bool empty() { return CurrentFnLexicalScope == nullptr; } - /// isCurrentFunctionScope - Return true if given lexical scope represents + /// isCurrentFunctionScope - Return true if given lexical scope represents /// current function. - bool isCurrentFunctionScope(const LexicalScope *LS) { + bool isCurrentFunctionScope(const LexicalScope *LS) { return LS == CurrentFnLexicalScope; } /// getCurrentFunctionScope - Return lexical scope for the current function. - LexicalScope *getCurrentFunctionScope() const { return CurrentFnLexicalScope;} + LexicalScope *getCurrentFunctionScope() const { + return CurrentFnLexicalScope; + } /// getMachineBasicBlocks - Populate given set using machine basic blocks /// which have machine instructions that belong to lexical scope identified by /// DebugLoc. void getMachineBasicBlocks(DebugLoc DL, - SmallPtrSet<const MachineBasicBlock*, 4> &MBBs); + SmallPtrSet<const MachineBasicBlock *, 4> &MBBs); /// dominates - Return true if DebugLoc's lexical scope dominates at least one /// machine instruction's lexical scope in a given machine basic block. @@ -84,27 +178,29 @@ public: return AbstractScopesList; } - /// findAbstractScope - Find an abstract scope or return NULL. + /// findAbstractScope - Find an abstract scope or return null. LexicalScope *findAbstractScope(const MDNode *N) { - return AbstractScopeMap.lookup(N); + auto I = AbstractScopeMap.find(N); + return I != AbstractScopeMap.end() ? &I->second : nullptr; } /// findInlinedScope - Find an inlined scope for the given DebugLoc or return /// NULL. - LexicalScope *findInlinedScope(DebugLoc DL) { - return InlinedLexicalScopeMap.lookup(DL); - } + LexicalScope *findInlinedScope(DebugLoc DL); - /// findLexicalScope - Find regular lexical scope or return NULL. + /// findLexicalScope - Find regular lexical scope or return null. LexicalScope *findLexicalScope(const MDNode *N) { - return LexicalScopeMap.lookup(N); + auto I = LexicalScopeMap.find(N); + return I != LexicalScopeMap.end() ? &I->second : nullptr; } /// dump - Print data structures to dbgs(). void dump(); -private: + /// getOrCreateAbstractScope - Find or create an abstract lexical scope. + LexicalScope *getOrCreateAbstractScope(const MDNode *N); +private: /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If /// not available then create new lexical scope. LexicalScope *getOrCreateLexicalScope(DebugLoc DL); @@ -115,30 +211,31 @@ private: /// getOrCreateInlinedScope - Find or create an inlined lexical scope. LexicalScope *getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt); - /// getOrCreateAbstractScope - Find or create an abstract lexical scope. - LexicalScope *getOrCreateAbstractScope(const MDNode *N); - /// extractLexicalScopes - Extract instruction ranges for each lexical scopes /// for the given machine function. void extractLexicalScopes(SmallVectorImpl<InsnRange> &MIRanges, DenseMap<const MachineInstr *, LexicalScope *> &M); void constructScopeNest(LexicalScope *Scope); - void assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges, - DenseMap<const MachineInstr *, LexicalScope *> &M); + void + assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges, + DenseMap<const MachineInstr *, LexicalScope *> &M); private: const MachineFunction *MF; - /// LexicalScopeMap - Tracks the scopes in the current function. Owns the - /// contained LexicalScope*s. - DenseMap<const MDNode *, LexicalScope *> LexicalScopeMap; + /// LexicalScopeMap - Tracks the scopes in the current function. + // Use an unordered_map to ensure value pointer validity over insertion. + std::unordered_map<const MDNode *, LexicalScope> LexicalScopeMap; - /// InlinedLexicalScopeMap - Tracks inlined function scopes in current function. - DenseMap<DebugLoc, LexicalScope *> InlinedLexicalScopeMap; + /// InlinedLexicalScopeMap - Tracks inlined function scopes in current + /// function. + std::unordered_map<std::pair<const MDNode *, const MDNode *>, LexicalScope, + pair_hash<const MDNode *, const MDNode *>> + InlinedLexicalScopeMap; - /// AbstractScopeMap - These scopes are not included LexicalScopeMap. - /// AbstractScopes owns its LexicalScope*s. - DenseMap<const MDNode *, LexicalScope *> AbstractScopeMap; + /// AbstractScopeMap - These scopes are not included LexicalScopeMap. + // Use an unordered_map to ensure value pointer validity over insertion. + std::unordered_map<const MDNode *, LexicalScope> AbstractScopeMap; /// AbstractScopesList - Tracks abstract scopes constructed while processing /// a function. @@ -149,100 +246,6 @@ private: LexicalScope *CurrentFnLexicalScope; }; -//===----------------------------------------------------------------------===// -/// LexicalScope - This class is used to track scope information. -/// -class LexicalScope { - virtual void anchor(); - -public: - LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) - : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), - LastInsn(0), FirstInsn(0), DFSIn(0), DFSOut(0) { - if (Parent) - Parent->addChild(this); - } - - virtual ~LexicalScope() {} - - // Accessors. - LexicalScope *getParent() const { return Parent; } - const MDNode *getDesc() const { return Desc; } - const MDNode *getInlinedAt() const { return InlinedAtLocation; } - const MDNode *getScopeNode() const { return Desc; } - bool isAbstractScope() const { return AbstractScope; } - SmallVectorImpl<LexicalScope *> &getChildren() { return Children; } - SmallVectorImpl<InsnRange> &getRanges() { return Ranges; } - - /// addChild - Add a child scope. - void addChild(LexicalScope *S) { Children.push_back(S); } - - /// openInsnRange - This scope covers instruction range starting from MI. - void openInsnRange(const MachineInstr *MI) { - if (!FirstInsn) - FirstInsn = MI; - - if (Parent) - Parent->openInsnRange(MI); - } - - /// extendInsnRange - Extend the current instruction range covered by - /// this scope. - void extendInsnRange(const MachineInstr *MI) { - assert (FirstInsn && "MI Range is not open!"); - LastInsn = MI; - if (Parent) - Parent->extendInsnRange(MI); - } - - /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected - /// until now. This is used when a new scope is encountered while walking - /// machine instructions. - void closeInsnRange(LexicalScope *NewScope = NULL) { - assert (LastInsn && "Last insn missing!"); - Ranges.push_back(InsnRange(FirstInsn, LastInsn)); - FirstInsn = NULL; - LastInsn = NULL; - // If Parent dominates NewScope then do not close Parent's instruction - // range. - if (Parent && (!NewScope || !Parent->dominates(NewScope))) - Parent->closeInsnRange(NewScope); - } - - /// dominates - Return true if current scope dominates given lexical scope. - bool dominates(const LexicalScope *S) const { - if (S == this) - return true; - if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut()) - return true; - return false; - } - - // Depth First Search support to walk and manipulate LexicalScope hierarchy. - unsigned getDFSOut() const { return DFSOut; } - void setDFSOut(unsigned O) { DFSOut = O; } - unsigned getDFSIn() const { return DFSIn; } - void setDFSIn(unsigned I) { DFSIn = I; } - - /// dump - print lexical scope. - void dump(unsigned Indent = 0) const; - -private: - LexicalScope *Parent; // Parent to this scope. - AssertingVH<const MDNode> Desc; // Debug info descriptor. - AssertingVH<const MDNode> InlinedAtLocation; // Location at which this - // scope is inlined. - bool AbstractScope; // Abstract Scope - SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope. - // Contents not owned. - SmallVector<InsnRange, 4> Ranges; - - const MachineInstr *LastInsn; // Last instruction of this scope. - const MachineInstr *FirstInsn; // First instruction of this scope. - unsigned DFSIn, DFSOut; // In & Out Depth use to determine - // scope nesting. -}; - } // end llvm namespace #endif diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 916c0f233ef8..372c294da306 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -40,12 +40,15 @@ namespace { llvm::linkErlangGC(); llvm::linkShadowStackGC(); - (void) llvm::createBURRListDAGScheduler(NULL, llvm::CodeGenOpt::Default); - (void) llvm::createSourceListDAGScheduler(NULL,llvm::CodeGenOpt::Default); - (void) llvm::createHybridListDAGScheduler(NULL,llvm::CodeGenOpt::Default); - (void) llvm::createFastDAGScheduler(NULL, llvm::CodeGenOpt::Default); - (void) llvm::createDefaultScheduler(NULL, llvm::CodeGenOpt::Default); - (void) llvm::createVLIWDAGScheduler(NULL, llvm::CodeGenOpt::Default); + (void) llvm::createBURRListDAGScheduler(nullptr, + llvm::CodeGenOpt::Default); + (void) llvm::createSourceListDAGScheduler(nullptr, + llvm::CodeGenOpt::Default); + (void) llvm::createHybridListDAGScheduler(nullptr, + llvm::CodeGenOpt::Default); + (void) llvm::createFastDAGScheduler(nullptr, llvm::CodeGenOpt::Default); + (void) llvm::createDefaultScheduler(nullptr, llvm::CodeGenOpt::Default); + (void) llvm::createVLIWDAGScheduler(nullptr, llvm::CodeGenOpt::Default); } } ForceCodegenLinking; // Force link by creating a global definition. diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 3a9fef6fbd78..6629e6046532 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -116,13 +116,13 @@ namespace llvm { /// Return the value leaving the instruction, if any. This can be a /// live-through value, or a live def. A dead def returns NULL. VNInfo *valueOut() const { - return isDeadDef() ? 0 : LateVal; + return isDeadDef() ? nullptr : LateVal; } /// Return the value defined by this instruction, if any. This includes /// dead defs, it is the value created by the instruction's def operands. VNInfo *valueDefined() const { - return EarlyVal == LateVal ? 0 : LateVal; + return EarlyVal == LateVal ? nullptr : LateVal; } /// Return the end point of the last live range segment to interact with @@ -154,7 +154,7 @@ namespace llvm { SlotIndex end; // End point of the interval (exclusive) VNInfo *valno; // identifier for the value contained in this segment. - Segment() : valno(0) {} + Segment() : valno(nullptr) {} Segment(SlotIndex S, SlotIndex E, VNInfo *V) : start(S), end(E), valno(V) { @@ -173,7 +173,7 @@ namespace llvm { } bool operator<(const Segment &Other) const { - return start < Other.start || (start == Other.start && end < Other.end); + return std::tie(start, end) < std::tie(Other.start, Other.end); } bool operator==(const Segment &Other) const { return start == Other.start && end == Other.end; @@ -336,20 +336,20 @@ namespace llvm { /// is none. const Segment *getSegmentContaining(SlotIndex Idx) const { const_iterator I = FindSegmentContaining(Idx); - return I == end() ? 0 : &*I; + return I == end() ? nullptr : &*I; } /// Return the live segment that contains the specified index, or null if /// there is none. Segment *getSegmentContaining(SlotIndex Idx) { iterator I = FindSegmentContaining(Idx); - return I == end() ? 0 : &*I; + return I == end() ? nullptr : &*I; } /// getVNInfoAt - Return the VNInfo that is live at Idx, or NULL. VNInfo *getVNInfoAt(SlotIndex Idx) const { const_iterator I = FindSegmentContaining(Idx); - return I == end() ? 0 : I->valno; + return I == end() ? nullptr : I->valno; } /// getVNInfoBefore - Return the VNInfo that is live up to but not @@ -357,7 +357,7 @@ namespace llvm { /// used by an instruction at this SlotIndex position. VNInfo *getVNInfoBefore(SlotIndex Idx) const { const_iterator I = FindSegmentContaining(Idx.getPrevSlot()); - return I == end() ? 0 : I->valno; + return I == end() ? nullptr : I->valno; } /// Return an iterator to the segment that contains the specified index, or @@ -443,13 +443,13 @@ namespace llvm { const_iterator I = find(Idx.getBaseIndex()); const_iterator E = end(); if (I == E) - return LiveQueryResult(0, 0, SlotIndex(), false); + return LiveQueryResult(nullptr, nullptr, SlotIndex(), false); // Is this an instruction live-in segment? // If Idx is the start index of a basic block, include live-in segments // that start at Idx.getBaseIndex(). - VNInfo *EarlyVal = 0; - VNInfo *LateVal = 0; + VNInfo *EarlyVal = nullptr; + VNInfo *LateVal = nullptr; SlotIndex EndPoint; bool Kill = false; if (I->start <= Idx.getBaseIndex()) { @@ -466,7 +466,7 @@ namespace llvm { // predecessor. // Such a value is not live-in. if (EarlyVal->def == Idx.getBaseIndex()) - EarlyVal = 0; + EarlyVal = nullptr; } // I now points to the segment that may be live-through, or defined by // this instr. Ignore segments starting after the current instr. @@ -552,8 +552,7 @@ namespace llvm { bool operator<(const LiveInterval& other) const { const SlotIndex &thisIndex = beginIndex(); const SlotIndex &otherIndex = other.beginIndex(); - return thisIndex < otherIndex || - (thisIndex == otherIndex && reg < other.reg); + return std::tie(thisIndex, reg) < std::tie(otherIndex, other.reg); } void print(raw_ostream &OS) const; @@ -598,7 +597,7 @@ namespace llvm { public: /// Create a LiveRangeUpdater for adding segments to LR. /// LR will temporarily be in an invalid state until flush() is called. - LiveRangeUpdater(LiveRange *lr = 0) : LR(lr) {} + LiveRangeUpdater(LiveRange *lr = nullptr) : LR(lr) {} ~LiveRangeUpdater() { flush(); } diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index d8437f09aaa7..176665bc2566 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -45,6 +45,7 @@ namespace llvm { class TargetInstrInfo; class TargetRegisterClass; class VirtRegMap; + class MachineBlockFrequencyInfo; class LiveIntervals : public MachineFunctionPass { MachineFunction* MF; @@ -100,7 +101,9 @@ namespace llvm { virtual ~LiveIntervals(); // Calculate the spill weight to assign to a single instruction. - static float getSpillWeight(bool isDef, bool isUse, BlockFrequency freq); + static float getSpillWeight(bool isDef, bool isUse, + const MachineBlockFrequencyInfo *MBFI, + const MachineInstr *Instr); LiveInterval &getInterval(unsigned Reg) { if (hasInterval(Reg)) @@ -134,7 +137,7 @@ namespace llvm { // Interval removal. void removeInterval(unsigned Reg) { delete VirtRegIntervals[Reg]; - VirtRegIntervals[Reg] = 0; + VirtRegIntervals[Reg] = nullptr; } /// Given a register and an instruction, adds a live segment from that @@ -150,7 +153,18 @@ namespace llvm { /// Return true if the interval may have been separated into multiple /// connected components. bool shrinkToUses(LiveInterval *li, - SmallVectorImpl<MachineInstr*> *dead = 0); + SmallVectorImpl<MachineInstr*> *dead = nullptr); + + /// \brief Walk the values in the given interval and compute which ones + /// are dead. Dead values are not deleted, however: + /// - Dead PHIDef values are marked as unused. + /// - New dead machine instructions are added to the dead vector. + /// - CanSeparate is set to true if the interval may have been separated + /// into multiple connected components. + void computeDeadValues(LiveInterval *li, + LiveRange &LR, + bool *CanSeparate, + SmallVectorImpl<MachineInstr*> *dead); /// extendToIndices - Extend the live range of LI to reach all points in /// Indices. The points in the Indices array must be jointly dominated by @@ -252,14 +266,14 @@ namespace llvm { VNInfo::Allocator& getVNInfoAllocator() { return VNInfoAllocator; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() override; /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); + bool runOnMachineFunction(MachineFunction&) override; /// print - Implement the dump method. - virtual void print(raw_ostream &O, const Module* = 0) const; + void print(raw_ostream &O, const Module* = nullptr) const override; /// intervalIsInOneMBB - If LI is confined to a single basic block, return /// a pointer to that block. If LI is live in to or out of any block, diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 95933d11dbb3..2f40509a1111 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -122,8 +122,8 @@ public: {} void clear() { - LiveUnion = NULL; - VirtReg = NULL; + LiveUnion = nullptr; + VirtReg = nullptr; InterferingVRegs.clear(); CheckedFirstInterference = false; SeenAllInterferences = false; @@ -182,7 +182,7 @@ public: unsigned Size; LiveIntervalUnion *LIUs; public: - Array() : Size(0), LIUs(0) {} + Array() : Size(0), LIUs(nullptr) {} ~Array() { clear(); } // Initialize the array to have Size entries. diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h new file mode 100644 index 000000000000..847092b1d824 --- /dev/null +++ b/include/llvm/CodeGen/LivePhysRegs.h @@ -0,0 +1,146 @@ +//===- llvm/CodeGen/LivePhysRegs.h - Live Physical Register Set -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LivePhysRegs utility for tracking liveness of +// physical registers. This can be used for ad-hoc liveness tracking after +// register allocation. You can start with the live-ins/live-outs at the +// beginning/end of a block and update the information while walking the +// instructions inside the block. This implementation tracks the liveness on a +// sub-register granularity. +// +// We assume that the high bits of a physical super-register are not preserved +// unless the instruction has an implicit-use operand reading the super- +// register. +// +// X86 Example: +// %YMM0<def> = ... +// %XMM0<def> = ... (Kills %XMM0, all %XMM0s sub-registers, and %YMM0) +// +// %YMM0<def> = ... +// %XMM0<def> = ..., %YMM0<imp-use> (%YMM0 and all its sub-registers are alive) +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVE_PHYS_REGS_H +#define LLVM_CODEGEN_LIVE_PHYS_REGS_H + +#include "llvm/ADT/SparseSet.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include <cassert> + +namespace llvm { + +class MachineInstr; + +/// \brief A set of live physical registers with functions to track liveness +/// when walking backward/forward through a basic block. +class LivePhysRegs { + const TargetRegisterInfo *TRI; + SparseSet<unsigned> LiveRegs; + + LivePhysRegs(const LivePhysRegs&) LLVM_DELETED_FUNCTION; + LivePhysRegs &operator=(const LivePhysRegs&) LLVM_DELETED_FUNCTION; +public: + /// \brief Constructs a new empty LivePhysRegs set. + LivePhysRegs() : TRI(nullptr), LiveRegs() {} + + /// \brief Constructs and initialize an empty LivePhysRegs set. + LivePhysRegs(const TargetRegisterInfo *TRI) : TRI(TRI) { + assert(TRI && "Invalid TargetRegisterInfo pointer."); + LiveRegs.setUniverse(TRI->getNumRegs()); + } + + /// \brief Clear and initialize the LivePhysRegs set. + void init(const TargetRegisterInfo *_TRI) { + assert(_TRI && "Invalid TargetRegisterInfo pointer."); + TRI = _TRI; + LiveRegs.clear(); + LiveRegs.setUniverse(TRI->getNumRegs()); + } + + /// \brief Clears the LivePhysRegs set. + void clear() { LiveRegs.clear(); } + + /// \brief Returns true if the set is empty. + bool empty() const { return LiveRegs.empty(); } + + /// \brief Adds a physical register and all its sub-registers to the set. + void addReg(unsigned Reg) { + assert(TRI && "LivePhysRegs is not initialized."); + assert(Reg <= TRI->getNumRegs() && "Expected a physical register."); + for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true); + SubRegs.isValid(); ++SubRegs) + LiveRegs.insert(*SubRegs); + } + + /// \brief Removes a physical register, all its sub-registers, and all its + /// super-registers from the set. + void removeReg(unsigned Reg) { + assert(TRI && "LivePhysRegs is not initialized."); + assert(Reg <= TRI->getNumRegs() && "Expected a physical register."); + for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true); + SubRegs.isValid(); ++SubRegs) + LiveRegs.erase(*SubRegs); + for (MCSuperRegIterator SuperRegs(Reg, TRI, /*IncludeSelf=*/false); + SuperRegs.isValid(); ++SuperRegs) + LiveRegs.erase(*SuperRegs); + } + + /// \brief Removes physical registers clobbered by the regmask operand @p MO. + void removeRegsInMask(const MachineOperand &MO); + + /// \brief Returns true if register @p Reg is contained in the set. This also + /// works if only the super register of @p Reg has been defined, because we + /// always add also all sub-registers to the set. + bool contains(unsigned Reg) const { return LiveRegs.count(Reg); } + + /// \brief Simulates liveness when stepping backwards over an + /// instruction(bundle): Remove Defs, add uses. This is the recommended way of + /// calculating liveness. + void stepBackward(const MachineInstr &MI); + + /// \brief Simulates liveness when stepping forward over an + /// instruction(bundle): Remove killed-uses, add defs. This is the not + /// recommended way, because it depends on accurate kill flags. If possible + /// use stepBackwards() instead of this function. + void stepForward(const MachineInstr &MI); + + /// \brief Adds all live-in registers of basic block @p MBB. + void addLiveIns(const MachineBasicBlock *MBB) { + for (MachineBasicBlock::livein_iterator LI = MBB->livein_begin(), + LE = MBB->livein_end(); LI != LE; ++LI) + addReg(*LI); + } + + /// \brief Adds all live-out registers of basic block @p MBB. + void addLiveOuts(const MachineBasicBlock *MBB) { + for (MachineBasicBlock::const_succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) + addLiveIns(*SI); + } + + typedef SparseSet<unsigned>::const_iterator const_iterator; + const_iterator begin() const { return LiveRegs.begin(); } + const_iterator end() const { return LiveRegs.end(); } + + /// \brief Prints the currently live registers to @p OS. + void print(raw_ostream &OS) const; + + /// \brief Dumps the currently live registers to the debug output. + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const LivePhysRegs& LR) { + LR.print(OS); + return OS; +} + +} // namespace llvm + +#endif // LLVM_CODEGEN_LIVE_PHYS_REGS_H diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index 7edf67cc24d1..5767cab1a4db 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -99,7 +99,7 @@ private: /// MachineRegisterInfo callback to notify when new virtual /// registers are created. - void MRI_NoteNewVirtualRegister(unsigned VReg); + void MRI_NoteNewVirtualRegister(unsigned VReg) override; public: /// Create a LiveRangeEdit for breaking down parent into smaller pieces. @@ -116,7 +116,7 @@ public: MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm, - Delegate *delegate = 0) + Delegate *delegate = nullptr) : Parent(parent), NewRegs(newRegs), MRI(MF.getRegInfo()), LIS(lis), VRM(vrm), TII(*MF.getTarget().getInstrInfo()), @@ -174,7 +174,7 @@ public: struct Remat { VNInfo *ParentVNI; // parent_'s value at the remat location. MachineInstr *OrigMI; // Instruction defining ParentVNI. - explicit Remat(VNInfo *ParentVNI) : ParentVNI(ParentVNI), OrigMI(0) {} + explicit Remat(VNInfo *ParentVNI) : ParentVNI(ParentVNI), OrigMI(nullptr) {} }; /// canRematerializeAt - Determine if ParentVNI can be rematerialized at diff --git a/include/llvm/CodeGen/LiveRegMatrix.h b/include/llvm/CodeGen/LiveRegMatrix.h index 7a3e9e8347f4..878b4d9836f2 100644 --- a/include/llvm/CodeGen/LiveRegMatrix.h +++ b/include/llvm/CodeGen/LiveRegMatrix.h @@ -25,7 +25,6 @@ #define LLVM_CODEGEN_LIVEREGMATRIX_H #include "llvm/ADT/BitVector.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/CodeGen/LiveIntervalUnion.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -51,7 +50,7 @@ class LiveRegMatrix : public MachineFunctionPass { LiveIntervalUnion::Array Matrix; // Cached queries per register unit. - OwningArrayPtr<LiveIntervalUnion::Query> Queries; + std::unique_ptr<LiveIntervalUnion::Query[]> Queries; // Cached register mask interference info. unsigned RegMaskTag; @@ -59,9 +58,9 @@ class LiveRegMatrix : public MachineFunctionPass { BitVector RegMaskUsable; // MachineFunctionPass boilerplate. - virtual void getAnalysisUsage(AnalysisUsage&) const; - virtual bool runOnMachineFunction(MachineFunction&); - virtual void releaseMemory(); + void getAnalysisUsage(AnalysisUsage&) const override; + bool runOnMachineFunction(MachineFunction&) override; + void releaseMemory() override; public: static char ID; LiveRegMatrix(); diff --git a/include/llvm/CodeGen/LiveRegUnits.h b/include/llvm/CodeGen/LiveRegUnits.h deleted file mode 100644 index 02b9c55cc61f..000000000000 --- a/include/llvm/CodeGen/LiveRegUnits.h +++ /dev/null @@ -1,88 +0,0 @@ -//===-- llvm/CodeGen/LiveRegUnits.h - Live register unit set ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a Set of live register units. This can be used for ad -// hoc liveness tracking after register allocation. You can start with the -// live-ins/live-outs at the beginning/end of a block and update the information -// while walking the instructions inside the block. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_LIVEREGUNITS_H -#define LLVM_CODEGEN_LIVEREGUNITS_H - -#include "llvm/ADT/SparseSet.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include <cassert> - -namespace llvm { - -class MachineInstr; - -/// A set of live register units with functions to track liveness when walking -/// backward/forward through a basic block. -class LiveRegUnits { - SparseSet<unsigned> LiveUnits; - - LiveRegUnits(const LiveRegUnits&) LLVM_DELETED_FUNCTION; - LiveRegUnits &operator=(const LiveRegUnits&) LLVM_DELETED_FUNCTION; -public: - /// \brief Constructs a new empty LiveRegUnits set. - LiveRegUnits() {} - - void init(const TargetRegisterInfo *TRI) { - LiveUnits.clear(); - LiveUnits.setUniverse(TRI->getNumRegs()); - } - - void clear() { LiveUnits.clear(); } - - bool empty() const { return LiveUnits.empty(); } - - /// \brief Adds a register to the set. - void addReg(unsigned Reg, const MCRegisterInfo &MCRI) { - for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) - LiveUnits.insert(*RUnits); - } - - /// \brief Removes a register from the set. - void removeReg(unsigned Reg, const MCRegisterInfo &MCRI) { - for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) - LiveUnits.erase(*RUnits); - } - - /// \brief Removes registers clobbered by the regmask operand @p Op. - void removeRegsInMask(const MachineOperand &Op, const MCRegisterInfo &MCRI); - - /// \brief Returns true if register @p Reg (or one of its super register) is - /// contained in the set. - bool contains(unsigned Reg, const MCRegisterInfo &MCRI) const { - for (MCRegUnitIterator RUnits(Reg, &MCRI); RUnits.isValid(); ++RUnits) { - if (LiveUnits.count(*RUnits)) - return true; - } - return false; - } - - /// \brief Simulates liveness when stepping backwards over an - /// instruction(bundle): Remove Defs, add uses. - void stepBackward(const MachineInstr &MI, const MCRegisterInfo &MCRI); - - /// \brief Simulates liveness when stepping forward over an - /// instruction(bundle): Remove killed-uses, add defs. - void stepForward(const MachineInstr &MI, const MCRegisterInfo &MCRI); - - /// \brief Adds all registers in the live-in list of block @p BB. - void addLiveIns(const MachineBasicBlock *MBB, const MCRegisterInfo &MCRI); -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/CodeGen/LiveStackAnalysis.h b/include/llvm/CodeGen/LiveStackAnalysis.h index 92c35f784d4c..df683983fa53 100644 --- a/include/llvm/CodeGen/LiveStackAnalysis.h +++ b/include/llvm/CodeGen/LiveStackAnalysis.h @@ -85,14 +85,14 @@ namespace llvm { VNInfo::Allocator& getVNInfoAllocator() { return VNInfoAllocator; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() override; /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); + bool runOnMachineFunction(MachineFunction&) override; /// print - Implement the dump method. - virtual void print(raw_ostream &O, const Module* = 0) const; + void print(raw_ostream &O, const Module* = nullptr) const override; }; } diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index dc735f7b50b9..a4a5fcc31e12 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -177,7 +177,7 @@ private: // Intermediate data structures void analyzePHINodes(const MachineFunction& Fn); public: - virtual bool runOnMachineFunction(MachineFunction &MF); + bool runOnMachineFunction(MachineFunction &MF) override; /// RegisterDefIsDead - Return true if the specified instruction defines the /// specified register, but that definition is dead. @@ -258,10 +258,10 @@ public: (void)Removed; return true; } - - void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory() { + void getAnalysisUsage(AnalysisUsage &AU) const override; + + void releaseMemory() override { VirtRegInfo.clear(); } diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 7717809e0d9f..a08cc2eb508a 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -160,7 +160,7 @@ public: template<class OtherTy, class OtherIterTy> bundle_iterator(const bundle_iterator<OtherTy, OtherIterTy> &I) : MII(I.getInstrIterator()) {} - bundle_iterator() : MII(0) {} + bundle_iterator() : MII(nullptr) {} Ty &operator*() const { return *MII; } Ty *operator->() const { return &operator*(); } @@ -219,10 +219,15 @@ public: unsigned size() const { return (unsigned)Insts.size(); } bool empty() const { return Insts.empty(); } - MachineInstr& front() { return Insts.front(); } - MachineInstr& back() { return Insts.back(); } - const MachineInstr& front() const { return Insts.front(); } - const MachineInstr& back() const { return Insts.back(); } + MachineInstr &instr_front() { return Insts.front(); } + MachineInstr &instr_back() { return Insts.back(); } + const MachineInstr &instr_front() const { return Insts.front(); } + const MachineInstr &instr_back() const { return Insts.back(); } + + MachineInstr &front() { return Insts.front(); } + MachineInstr &back() { return *--end(); } + const MachineInstr &front() const { return Insts.front(); } + const MachineInstr &back() const { return *--end(); } instr_iterator instr_begin() { return Insts.begin(); } const_instr_iterator instr_begin() const { return Insts.begin(); } @@ -242,6 +247,12 @@ public: reverse_iterator rend () { return instr_rend(); } const_reverse_iterator rend () const { return instr_rend(); } + inline iterator_range<iterator> terminators() { + return iterator_range<iterator>(getFirstTerminator(), end()); + } + inline iterator_range<const_iterator> terminators() const { + return iterator_range<const_iterator>(getFirstTerminator(), end()); + } // Machine-CFG iterators typedef std::vector<MachineBasicBlock *>::iterator pred_iterator; @@ -256,7 +267,6 @@ public: succ_reverse_iterator; typedef std::vector<MachineBasicBlock *>::const_reverse_iterator const_succ_reverse_iterator; - pred_iterator pred_begin() { return Predecessors.begin(); } const_pred_iterator pred_begin() const { return Predecessors.begin(); } pred_iterator pred_end() { return Predecessors.end(); } @@ -290,6 +300,19 @@ public: } bool succ_empty() const { return Successors.empty(); } + inline iterator_range<pred_iterator> predecessors() { + return iterator_range<pred_iterator>(pred_begin(), pred_end()); + } + inline iterator_range<const_pred_iterator> predecessors() const { + return iterator_range<const_pred_iterator>(pred_begin(), pred_end()); + } + inline iterator_range<succ_iterator> successors() { + return iterator_range<succ_iterator>(succ_begin(), succ_end()); + } + inline iterator_range<const_succ_iterator> successors() const { + return iterator_range<const_succ_iterator>(succ_begin(), succ_end()); + } + // LiveIn management methods. /// addLiveIn - Add the specified register as a live in. Note that it @@ -363,6 +386,9 @@ public: /// void addSuccessor(MachineBasicBlock *succ, uint32_t weight = 0); + /// Set successor weight of a given iterator. + void setSuccWeight(succ_iterator I, uint32_t weight); + /// removeSuccessor - Remove successor from the successors list of this /// MachineBasicBlock. The Predecessors list of succ is automatically updated. /// @@ -500,7 +526,7 @@ public: /// /// If I points to a bundle of instructions, they are all erased. iterator erase(iterator I) { - return erase(I, llvm::next(I)); + return erase(I, std::next(I)); } /// Remove an instruction from the instruction list and delete it. @@ -539,7 +565,7 @@ public: void splice(iterator Where, MachineBasicBlock *Other, iterator From) { // The range splice() doesn't allow noop moves, but this one does. if (Where != From) - splice(Where, Other, From, llvm::next(From)); + splice(Where, Other, From, std::next(From)); } /// Take a block of instructions from MBB 'Other' in the range [From, To), @@ -594,7 +620,7 @@ public: /// computeRegisterLiveness - Return whether (physical) register \c Reg /// has been <def>ined and not <kill>ed as of just before \c MI. - /// + /// /// Search is localised to a neighborhood of /// \c Neighborhood instructions before (searching for defs or kills) and /// Neighborhood instructions after (searching just for defs) MI. @@ -606,7 +632,10 @@ public: // Debugging methods. void dump() const; - void print(raw_ostream &OS, SlotIndexes* = 0) const; + void print(raw_ostream &OS, SlotIndexes* = nullptr) const; + + // Printing method used by LoopInfo. + void printAsOperand(raw_ostream &OS, bool PrintType = true) const; /// getNumber - MachineBasicBlocks are uniquely numbered at the function /// level, unless they're not in a MachineFunction yet, in which case this @@ -655,8 +684,6 @@ private: raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB); -void WriteAsOperand(raw_ostream &, const MachineBasicBlock*, bool t); - // This is useful when building IndexedMaps keyed on basic block pointers. struct MBB2NumberFunctor : public std::unary_function<const MachineBasicBlock*, unsigned> { @@ -746,11 +773,11 @@ public: MachineInstrSpan(MachineBasicBlock::iterator I) : MBB(*I->getParent()), I(I), - B(I == MBB.begin() ? MBB.end() : llvm::prior(I)), - E(llvm::next(I)) {} + B(I == MBB.begin() ? MBB.end() : std::prev(I)), + E(std::next(I)) {} MachineBasicBlock::iterator begin() { - return B == MBB.end() ? MBB.begin() : llvm::next(B); + return B == MBB.end() ? MBB.begin() : std::next(B); } MachineBasicBlock::iterator end() { return E; } bool empty() { return begin() == end(); } diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h index a9c7bf7dbc60..1aef689eb7a4 100644 --- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h +++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h @@ -1,4 +1,4 @@ -//====----- MachineBlockFrequencyInfo.h - MachineBlock Frequency Analysis ----====// +//===- MachineBlockFrequencyInfo.h - MBB Frequency Analysis -*- C++ -*-----===// // // The LLVM Compiler Infrastructure // @@ -22,15 +22,13 @@ namespace llvm { class MachineBasicBlock; class MachineBranchProbabilityInfo; -template<class BlockT, class FunctionT, class BranchProbInfoT> -class BlockFrequencyImpl; +template <class BlockT> class BlockFrequencyInfoImpl; -/// MachineBlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate -/// machine basic block frequencies. +/// MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation +/// to estimate machine basic block frequencies. class MachineBlockFrequencyInfo : public MachineFunctionPass { - - BlockFrequencyImpl<MachineBasicBlock, MachineFunction, - MachineBranchProbabilityInfo> *MBFI; + typedef BlockFrequencyInfoImpl<MachineBasicBlock> ImplType; + std::unique_ptr<ImplType> MBFI; public: static char ID; @@ -39,9 +37,11 @@ public: ~MachineBlockFrequencyInfo(); - void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnMachineFunction(MachineFunction &F) override; - bool runOnMachineFunction(MachineFunction &F); + void releaseMemory() override; /// getblockFreq - Return block frequency. Return 0 if we don't have the /// information. Please note that initial frequency is equal to 1024. It means @@ -49,6 +49,21 @@ public: /// the other block frequencies. We do this to avoid using of floating points. /// BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const; + + const MachineFunction *getFunction() const; + void view() const; + + // Print the block frequency Freq to OS using the current functions entry + // frequency to convert freq into a relative decimal form. + raw_ostream &printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const; + + // Convenience method that attempts to look up the frequency associated with + // BB and print it to OS. + raw_ostream &printBlockFreq(raw_ostream &OS, + const MachineBasicBlock *MBB) const; + + uint64_t getEntryFreq() const; + }; } diff --git a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h index c59948fd654e..7ba749559c0f 100644 --- a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h +++ b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h @@ -40,7 +40,7 @@ public: initializeMachineBranchProbabilityInfoPass(Registry); } - void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } @@ -60,7 +60,8 @@ public: uint32_t getSumForBlock(const MachineBasicBlock *MBB, uint32_t &Scale) const; // A 'Hot' edge is an edge which probability is >= 80%. - bool isEdgeHot(MachineBasicBlock *Src, MachineBasicBlock *Dst) const; + bool isEdgeHot(const MachineBasicBlock *Src, + const MachineBasicBlock *Dst) const; // Return a hot successor for the block BB or null if there isn't one. // NB: This routine's complexity is linear on the number of successors. @@ -72,14 +73,15 @@ public: // NB: This routine's complexity is linear on the number of successors of // Src. Querying sequentially for each successor's probability is a quadratic // query pattern. - BranchProbability getEdgeProbability(MachineBasicBlock *Src, - MachineBasicBlock *Dst) const; + BranchProbability getEdgeProbability(const MachineBasicBlock *Src, + const MachineBasicBlock *Dst) const; // Print value between 0 (0% probability) and 1 (100% probability), // however the value is never equal to 0, and can be 1 only iff SRC block // has only one successor. - raw_ostream &printEdgeProbability(raw_ostream &OS, MachineBasicBlock *Src, - MachineBasicBlock *Dst) const; + raw_ostream &printEdgeProbability(raw_ostream &OS, + const MachineBasicBlock *Src, + const MachineBasicBlock *Dst) const; }; } diff --git a/include/llvm/CodeGen/MachineCodeEmitter.h b/include/llvm/CodeGen/MachineCodeEmitter.h index 9e41e6e9c1ee..81b0ba1e7c71 100644 --- a/include/llvm/CodeGen/MachineCodeEmitter.h +++ b/include/llvm/CodeGen/MachineCodeEmitter.h @@ -17,8 +17,8 @@ #ifndef LLVM_CODEGEN_MACHINECODEEMITTER_H #define LLVM_CODEGEN_MACHINECODEEMITTER_H +#include "llvm/IR/DebugLoc.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/DebugLoc.h" #include <string> namespace llvm { @@ -262,7 +262,7 @@ public: // Check for buffer overflow. if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) { CurBufferPtr = BufferEnd; - Result = 0; + Result = nullptr; } else { // Allocate the space. Result = CurBufferPtr; diff --git a/include/llvm/CodeGen/MachineCodeInfo.h b/include/llvm/CodeGen/MachineCodeInfo.h index ba9dfab91a7e..820bc87425b9 100644 --- a/include/llvm/CodeGen/MachineCodeInfo.h +++ b/include/llvm/CodeGen/MachineCodeInfo.h @@ -27,7 +27,7 @@ private: void *Address; // The address of the function in memory public: - MachineCodeInfo() : Size(0), Address(0) {} + MachineCodeInfo() : Size(0), Address(nullptr) {} void setSize(size_t s) { Size = s; diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index 912ce8966268..c619afb83333 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -17,6 +17,7 @@ #define LLVM_CODEGEN_MACHINECONSTANTPOOL_H #include "llvm/ADT/DenseSet.h" +#include "llvm/MC/SectionKind.h" #include <cassert> #include <climits> #include <vector> @@ -119,6 +120,8 @@ public: /// them. /// 2: This entry may have arbitrary relocations. unsigned getRelocationInfo() const; + + SectionKind getSectionKind(const DataLayout *DL) const; }; /// The MachineConstantPool class keeps track of constants referenced by a diff --git a/include/llvm/CodeGen/MachineDominanceFrontier.h b/include/llvm/CodeGen/MachineDominanceFrontier.h new file mode 100644 index 000000000000..e099e716c63d --- /dev/null +++ b/include/llvm/CodeGen/MachineDominanceFrontier.h @@ -0,0 +1,109 @@ +//===- llvm/CodeGen/MachineDominanceFrontier.h ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEDOMINANCEFRONTIER_H +#define LLVM_CODEGEN_MACHINEDOMINANCEFRONTIER_H + +#include "llvm/Analysis/DominanceFrontier.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + + +namespace llvm { + +class MachineDominanceFrontier : public MachineFunctionPass { + ForwardDominanceFrontierBase<MachineBasicBlock> Base; +public: + typedef DominatorTreeBase<MachineBasicBlock> DomTreeT; + typedef DomTreeNodeBase<MachineBasicBlock> DomTreeNodeT; + typedef DominanceFrontierBase<MachineBasicBlock>::DomSetType DomSetType; + typedef DominanceFrontierBase<MachineBasicBlock>::iterator iterator; + typedef DominanceFrontierBase<MachineBasicBlock>::const_iterator const_iterator; + + void operator=(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION; + MachineDominanceFrontier(const MachineDominanceFrontier &) LLVM_DELETED_FUNCTION; + + static char ID; + + MachineDominanceFrontier(); + + DominanceFrontierBase<MachineBasicBlock> &getBase() { + return Base; + } + + inline const std::vector<MachineBasicBlock*> &getRoots() const { + return Base.getRoots(); + } + + MachineBasicBlock *getRoot() const { + return Base.getRoot(); + } + + bool isPostDominator() const { + return Base.isPostDominator(); + } + + iterator begin() { + return Base.begin(); + } + + const_iterator begin() const { + return Base.begin(); + } + + iterator end() { + return Base.end(); + } + + const_iterator end() const { + return Base.end(); + } + + iterator find(MachineBasicBlock *B) { + return Base.find(B); + } + + const_iterator find(MachineBasicBlock *B) const { + return Base.find(B); + } + + iterator addBasicBlock(MachineBasicBlock *BB, const DomSetType &frontier) { + return Base.addBasicBlock(BB, frontier); + } + + void removeBlock(MachineBasicBlock *BB) { + return Base.removeBlock(BB); + } + + void addToFrontier(iterator I, MachineBasicBlock *Node) { + return Base.addToFrontier(I, Node); + } + + void removeFromFrontier(iterator I, MachineBasicBlock *Node) { + return Base.removeFromFrontier(I, Node); + } + + bool compareDomSet(DomSetType &DS1, const DomSetType &DS2) const { + return Base.compareDomSet(DS1, DS2); + } + + bool compare(DominanceFrontierBase<MachineBasicBlock> &Other) const { + return Base.compare(Other); + } + + bool runOnMachineFunction(MachineFunction &F) override; + + void releaseMemory() override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +} + +#endif diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index e41d206da65c..f1ae0bf5f9cf 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -15,11 +15,11 @@ #ifndef LLVM_CODEGEN_MACHINEDOMINATORS_H #define LLVM_CODEGEN_MACHINEDOMINATORS_H -#include "llvm/Analysis/DominatorInternals.h" -#include "llvm/Analysis/Dominators.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/GenericDomTree.h" +#include "llvm/Support/GenericDomTreeConstruction.h" namespace llvm { @@ -48,7 +48,7 @@ public: DominatorTreeBase<MachineBasicBlock>& getBase() { return *DT; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; /// getRoots - Return the root blocks of the current CFG. This may include /// multiple blocks if we are computing post dominators. For forward @@ -66,7 +66,7 @@ public: return DT->getRootNode(); } - virtual bool runOnMachineFunction(MachineFunction &F); + bool runOnMachineFunction(MachineFunction &F) override; inline bool dominates(const MachineDomTreeNode* A, const MachineDomTreeNode* B) const { @@ -166,9 +166,9 @@ public: return DT->isReachableFromEntry(A); } - virtual void releaseMemory(); + void releaseMemory() override; - virtual void print(raw_ostream &OS, const Module*) const; + void print(raw_ostream &OS, const Module*) const override; }; //===------------------------------------- diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 022634df87cf..c51f8fe03bbf 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -101,11 +101,6 @@ class MachineFrameInfo { // cannot alias any other memory objects. bool isSpillSlot; - // MayNeedSP - If true the stack object triggered the creation of the stack - // protector. We should allocate this object right after the stack - // protector. - bool MayNeedSP; - /// Alloca - If this stack object is originated from an Alloca instruction /// this value saves the original IR allocation. Can be NULL. const AllocaInst *Alloca; @@ -115,9 +110,9 @@ class MachineFrameInfo { bool PreAllocated; StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM, - bool isSS, bool NSP, const AllocaInst *Val) + bool isSS, const AllocaInst *Val) : SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM), - isSpillSlot(isSS), MayNeedSP(NSP), Alloca(Val), PreAllocated(false) {} + isSpillSlot(isSS), Alloca(Val), PreAllocated(false) {} }; const TargetMachine &TM; @@ -145,6 +140,14 @@ class MachineFrameInfo { /// to builtin \@llvm.returnaddress. bool ReturnAddressTaken; + /// HasStackMap - This boolean keeps track of whether there is a call + /// to builtin \@llvm.experimental.stackmap. + bool HasStackMap; + + /// HasPatchPoint - This boolean keeps track of whether there is a call + /// to builtin \@llvm.experimental.patchpoint. + bool HasPatchPoint; + /// StackSize - The prolog/epilog code inserter calculates the final stack /// offsets for all of the fixed size objects, updating the Objects list /// above. It then updates StackSize to contain the number of bytes that need @@ -223,6 +226,10 @@ class MachineFrameInfo { /// Whether the "realign-stack" option is on. bool RealignOption; + /// True if the function includes inline assembly that adjusts the stack + /// pointer. + bool HasInlineAsmWithSPAdjust; + const TargetFrameLowering *getFrameLowering() const; public: explicit MachineFrameInfo(const TargetMachine &TM, bool RealignOpt) @@ -231,6 +238,8 @@ public: HasVarSizedObjects = false; FrameAddressTaken = false; ReturnAddressTaken = false; + HasStackMap = false; + HasPatchPoint = false; AdjustsStack = false; HasCalls = false; StackProtectorIdx = -1; @@ -240,6 +249,7 @@ public: LocalFrameSize = 0; LocalFrameMaxAlign = 0; UseLocalStackAllocationBlock = false; + HasInlineAsmWithSPAdjust = false; } /// hasStackObjects - Return true if there are any stack objects in this @@ -276,6 +286,18 @@ public: bool isReturnAddressTaken() const { return ReturnAddressTaken; } void setReturnAddressIsTaken(bool s) { ReturnAddressTaken = s; } + /// hasStackMap - This method may be called any time after instruction + /// selection is complete to determine if there is a call to builtin + /// \@llvm.experimental.stackmap. + bool hasStackMap() const { return HasStackMap; } + void setHasStackMap(bool s = true) { HasStackMap = s; } + + /// hasPatchPoint - This method may be called any time after instruction + /// selection is complete to determine if there is a call to builtin + /// \@llvm.experimental.patchpoint. + bool hasPatchPoint() const { return HasPatchPoint; } + void setHasPatchPoint(bool s = true) { HasPatchPoint = s; } + /// getObjectIndexBegin - Return the minimum frame object index. /// int getObjectIndexBegin() const { return -NumFixedObjects; } @@ -380,14 +402,6 @@ public: return Objects[ObjectIdx+NumFixedObjects].Alloca; } - /// NeedsStackProtector - Returns true if the object may need stack - /// protectors. - bool MayNeedStackProtector(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].MayNeedSP; - } - /// getObjectOffset - Return the assigned stack offset of the specified object /// from the incoming stack pointer. /// @@ -451,6 +465,10 @@ public: bool hasCalls() const { return HasCalls; } void setHasCalls(bool V) { HasCalls = V; } + /// Returns true if the function contains any stack-adjusting inline assembly. + bool hasInlineAsmWithSPAdjust() const { return HasInlineAsmWithSPAdjust; } + void setHasInlineAsmWithSPAdjust(bool B) { HasInlineAsmWithSPAdjust = B; } + /// getMaxCallFrameSize - Return the maximum size of a call frame that must be /// allocated for an outgoing function call. This is only available if /// CallFrameSetup/Destroy pseudo instructions are used by the target, and @@ -466,6 +484,9 @@ public: /// int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable); + /// CreateFixedSpillStackObject - Create a spill slot at a fixed location + /// on the stack. Returns an index with a negative value. + int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); /// isFixedObjectIndex - Returns true if the specified index corresponds to a /// fixed stack object. @@ -501,7 +522,7 @@ public: /// a nonnegative identifier to represent it. /// int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS, - bool MayNeedSP = false, const AllocaInst *Alloca = 0); + const AllocaInst *Alloca = nullptr); /// CreateSpillStackObject - Create a new statically sized stack object that /// represents a spill slot, returning a nonnegative identifier to represent @@ -521,7 +542,7 @@ public: /// variable sized object is created, whether or not the index returned is /// actually used. /// - int CreateVariableSizedObject(unsigned Alignment); + int CreateVariableSizedObject(unsigned Alignment, const AllocaInst *Alloca); /// getCalleeSavedInfo - Returns a reference to call saved info vector for the /// current function. diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index c886e256e044..042c62b4a887 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -20,9 +20,9 @@ #include "llvm/ADT/ilist.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ArrayRecycler.h" -#include "llvm/Support/DebugLoc.h" #include "llvm/Support/Recycler.h" namespace llvm { @@ -131,8 +131,8 @@ class MachineFunction { /// about the control flow of such functions. bool ExposesReturnsTwice; - /// True if the function includes MS-style inline assembly. - bool HasMSInlineAsm; + /// True if the function includes any inline assembly. + bool HasInlineAsm; MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION; void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; @@ -218,29 +218,23 @@ public: ExposesReturnsTwice = B; } - /// Returns true if the function contains any MS-style inline assembly. - bool hasMSInlineAsm() const { - return HasMSInlineAsm; + /// Returns true if the function contains any inline assembly. + bool hasInlineAsm() const { + return HasInlineAsm; } - /// Set a flag that indicates that the function contains MS-style inline - /// assembly. - void setHasMSInlineAsm(bool B) { - HasMSInlineAsm = B; + /// Set a flag that indicates that the function contains inline assembly. + void setHasInlineAsm(bool B) { + HasInlineAsm = B; } - + /// getInfo - Keep track of various per-function pieces of information for /// backends that would like to do so. /// template<typename Ty> Ty *getInfo() { - if (!MFInfo) { - // This should be just `new (Allocator.Allocate<Ty>()) Ty(*this)', but - // that apparently breaks GCC 3.3. - Ty *Loc = static_cast<Ty*>(Allocator.Allocate(sizeof(Ty), - AlignOf<Ty>::Alignment)); - MFInfo = new (Loc) Ty(*this); - } + if (!MFInfo) + MFInfo = new (Allocator.Allocate<Ty>()) Ty(*this); return static_cast<Ty*>(MFInfo); } @@ -260,6 +254,9 @@ public: return MBBNumbering[N]; } + /// Should we be emitting segmented stack stuff for the function + bool shouldSplitStack(); + /// getNumBlockIDs - Return the number of MBB ID's allocated. /// unsigned getNumBlockIDs() const { return (unsigned)MBBNumbering.size(); } @@ -269,12 +266,12 @@ public: /// dense, and match the ordering of the blocks within the function. If a /// specific MachineBasicBlock is specified, only that block and those after /// it are renumbered. - void RenumberBlocks(MachineBasicBlock *MBBFrom = 0); + void RenumberBlocks(MachineBasicBlock *MBBFrom = nullptr); /// print - Print out the MachineFunction in a format suitable for debugging /// to the specified stream. /// - void print(raw_ostream &OS, SlotIndexes* = 0) const; + void print(raw_ostream &OS, SlotIndexes* = nullptr) const; /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the @@ -297,7 +294,7 @@ public: /// verify - Run the current MachineFunction through the machine code /// verifier, useful for debugger use. - void verify(Pass *p = NULL, const char *Banner = NULL) const; + void verify(Pass *p = nullptr, const char *Banner = nullptr) const; // Provide accessors for the MachineBasicBlock list... typedef BasicBlockListType::iterator iterator; @@ -365,7 +362,7 @@ public: /// implementation. void removeFromMBBNumbering(unsigned N) { assert(N < MBBNumbering.size() && "Illegal basic block #"); - MBBNumbering[N] = 0; + MBBNumbering[N] = nullptr; } /// CreateMachineInstr - Allocate a new MachineInstr. Use this instead @@ -390,7 +387,7 @@ public: /// CreateMachineBasicBlock - Allocate a new MachineBasicBlock. Use this /// instead of `new MachineBasicBlock'. /// - MachineBasicBlock *CreateMachineBasicBlock(const BasicBlock *bb = 0); + MachineBasicBlock *CreateMachineBasicBlock(const BasicBlock *bb = nullptr); /// DeleteMachineBasicBlock - Delete the given MachineBasicBlock. /// @@ -402,8 +399,8 @@ public: MachineMemOperand *getMachineMemOperand(MachinePointerInfo PtrInfo, unsigned f, uint64_t s, unsigned base_alignment, - const MDNode *TBAAInfo = 0, - const MDNode *Ranges = 0); + const MDNode *TBAAInfo = nullptr, + const MDNode *Ranges = nullptr); /// getMachineMemOperand - Allocate a new MachineMemOperand by copying /// an existing one, adjusting by an offset and using the given size. @@ -427,6 +424,15 @@ public: OperandRecycler.deallocate(Cap, Array); } + /// \brief Allocate and initialize a register mask with @p NumRegister bits. + uint32_t *allocateRegisterMask(unsigned NumRegister) { + unsigned Size = (NumRegister + 31) / 32; + uint32_t *Mask = Allocator.Allocate<uint32_t>(Size); + for (unsigned i = 0; i != Size; ++i) + Mask[i] = 0; + return Mask; + } + /// allocateMemRefsArray - Allocate an array to hold MachineMemOperand /// pointers. This array is owned by the MachineFunction. MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num); diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h index 112f07ea50d7..36f1c6627096 100644 --- a/include/llvm/CodeGen/MachineFunctionAnalysis.h +++ b/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -34,16 +34,16 @@ public: ~MachineFunctionAnalysis(); MachineFunction &getMF() const { return *MF; } - - virtual const char* getPassName() const { + + const char* getPassName() const override { return "Machine Function Analysis"; } private: - virtual bool doInitialization(Module &M); - virtual bool runOnFunction(Function &F); - virtual void releaseMemory(); - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + bool doInitialization(Module &M) override; + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void getAnalysisUsage(AnalysisUsage &AU) const override; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineFunctionPass.h b/include/llvm/CodeGen/MachineFunctionPass.h index 04881e52ca7f..50a1f6e96217 100644 --- a/include/llvm/CodeGen/MachineFunctionPass.h +++ b/include/llvm/CodeGen/MachineFunctionPass.h @@ -44,14 +44,14 @@ protected: /// For MachineFunctionPasses, calling AU.preservesCFG() indicates that /// the pass does not modify the MachineBasicBlock CFG. /// - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; private: /// createPrinterPass - Get a machine function printer pass. - virtual Pass *createPrinterPass(raw_ostream &O, - const std::string &Banner) const; + Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const override; - virtual bool runOnFunction(Function &F); + bool runOnFunction(Function &F) override; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index cccab81efbb2..3c828116411e 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -22,13 +22,14 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/InlineAsm.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/Support/ArrayRecycler.h" -#include "llvm/Support/DebugLoc.h" #include "llvm/Target/TargetOpcodes.h" -#include <vector> namespace llvm { @@ -243,6 +244,14 @@ public: /// DebugLoc getDebugLoc() const { return debugLoc; } + /// getDebugVariable() - Return the debug variable referenced by + /// this DBG_VALUE instruction. + DIVariable getDebugVariable() const { + assert(isDebugValue() && "not a DBG_VALUE"); + const MDNode *Var = getOperand(getNumOperands() - 1).getMetadata(); + return DIVariable(Var); + } + /// emitError - Emit an error referring to the source location of this /// instruction. This should only be used for inline assembly that is somehow /// impossible to compile. Other errors should have been handled much @@ -287,11 +296,57 @@ public: const_mop_iterator operands_begin() const { return Operands; } const_mop_iterator operands_end() const { return Operands + NumOperands; } + iterator_range<mop_iterator> operands() { + return iterator_range<mop_iterator>(operands_begin(), operands_end()); + } + iterator_range<const_mop_iterator> operands() const { + return iterator_range<const_mop_iterator>(operands_begin(), operands_end()); + } + iterator_range<mop_iterator> explicit_operands() { + return iterator_range<mop_iterator>( + operands_begin(), operands_begin() + getNumExplicitOperands()); + } + iterator_range<const_mop_iterator> explicit_operands() const { + return iterator_range<const_mop_iterator>( + operands_begin(), operands_begin() + getNumExplicitOperands()); + } + iterator_range<mop_iterator> implicit_operands() { + return iterator_range<mop_iterator>(explicit_operands().end(), + operands_end()); + } + iterator_range<const_mop_iterator> implicit_operands() const { + return iterator_range<const_mop_iterator>(explicit_operands().end(), + operands_end()); + } + iterator_range<mop_iterator> defs() { + return iterator_range<mop_iterator>( + operands_begin(), operands_begin() + getDesc().getNumDefs()); + } + iterator_range<const_mop_iterator> defs() const { + return iterator_range<const_mop_iterator>( + operands_begin(), operands_begin() + getDesc().getNumDefs()); + } + iterator_range<mop_iterator> uses() { + return iterator_range<mop_iterator>( + operands_begin() + getDesc().getNumDefs(), operands_end()); + } + iterator_range<const_mop_iterator> uses() const { + return iterator_range<const_mop_iterator>( + operands_begin() + getDesc().getNumDefs(), operands_end()); + } + /// Access to memory operands of the instruction mmo_iterator memoperands_begin() const { return MemRefs; } mmo_iterator memoperands_end() const { return MemRefs + NumMemRefs; } bool memoperands_empty() const { return NumMemRefs == 0; } + iterator_range<mmo_iterator> memoperands() { + return iterator_range<mmo_iterator>(memoperands_begin(), memoperands_end()); + } + iterator_range<mmo_iterator> memoperands() const { + return iterator_range<mmo_iterator>(memoperands_begin(), memoperands_end()); + } + /// hasOneMemOperand - Return true if this instruction has exactly one /// MachineMemOperand. bool hasOneMemOperand() const { @@ -623,19 +678,19 @@ public: /// bundle remain bundled. void eraseFromBundle(); + bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; } + bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; } + /// isLabel - Returns true if the MachineInstr represents a label. /// - bool isLabel() const { - return getOpcode() == TargetOpcode::PROLOG_LABEL || - getOpcode() == TargetOpcode::EH_LABEL || - getOpcode() == TargetOpcode::GC_LABEL; + bool isLabel() const { return isEHLabel() || isGCLabel(); } + bool isCFIInstruction() const { + return getOpcode() == TargetOpcode::CFI_INSTRUCTION; } - bool isPrologLabel() const { - return getOpcode() == TargetOpcode::PROLOG_LABEL; - } - bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; } - bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; } + // True if the instruction represents a position in the function. + bool isPosition() const { return isLabel() || isCFIInstruction(); } + bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; } /// A DBG_VALUE is indirect iff the first operand is a register and /// the second operand is an immediate. @@ -672,6 +727,9 @@ public: bool isFullCopy() const { return isCopy() && !getOperand(0).getSubReg() && !getOperand(1).getSubReg(); } + bool isExtractSubreg() const { + return getOpcode() == TargetOpcode::EXTRACT_SUBREG; + } /// isCopyLike - Return true if the instruction behaves like a copy. /// This does not include native copy instructions. @@ -701,7 +759,7 @@ public: // Pseudo-instructions that don't produce any real output. case TargetOpcode::IMPLICIT_DEF: case TargetOpcode::KILL: - case TargetOpcode::PROLOG_LABEL: + case TargetOpcode::CFI_INSTRUCTION: case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: case TargetOpcode::DBG_VALUE: @@ -721,7 +779,8 @@ public: /// is a read of a super-register. /// This does not count partial redefines of virtual registers as reads: /// %reg1024:6 = OP. - bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI = NULL) const { + bool readsRegister(unsigned Reg, + const TargetRegisterInfo *TRI = nullptr) const { return findRegisterUseOperandIdx(Reg, false, TRI) != -1; } @@ -737,12 +796,13 @@ public: /// partial defines. /// If Ops is not null, all operand indices for Reg are added. std::pair<bool,bool> readsWritesVirtualRegister(unsigned Reg, - SmallVectorImpl<unsigned> *Ops = 0) const; + SmallVectorImpl<unsigned> *Ops = nullptr) const; /// killsRegister - Return true if the MachineInstr kills the specified /// register. If TargetRegisterInfo is passed, then it also checks if there is /// a kill of a super-register. - bool killsRegister(unsigned Reg, const TargetRegisterInfo *TRI = NULL) const { + bool killsRegister(unsigned Reg, + const TargetRegisterInfo *TRI = nullptr) const { return findRegisterUseOperandIdx(Reg, true, TRI) != -1; } @@ -750,7 +810,8 @@ public: /// specified register. If TargetRegisterInfo is passed, then it also checks /// if there is a def of a super-register. /// NOTE: It's ignoring subreg indices on virtual registers. - bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=NULL) const { + bool definesRegister(unsigned Reg, + const TargetRegisterInfo *TRI = nullptr) const { return findRegisterDefOperandIdx(Reg, false, false, TRI) != -1; } @@ -765,7 +826,7 @@ public: /// instruction. If TargetRegisterInfo is passed, then it also checks /// if there is a dead def of a super-register. bool registerDefIsDead(unsigned Reg, - const TargetRegisterInfo *TRI = NULL) const { + const TargetRegisterInfo *TRI = nullptr) const { return findRegisterDefOperandIdx(Reg, true, false, TRI) != -1; } @@ -773,14 +834,14 @@ public: /// the specific register or -1 if it is not found. It further tightens /// the search criteria to a use that kills the register if isKill is true. int findRegisterUseOperandIdx(unsigned Reg, bool isKill = false, - const TargetRegisterInfo *TRI = NULL) const; + const TargetRegisterInfo *TRI = nullptr) const; /// findRegisterUseOperand - Wrapper for findRegisterUseOperandIdx, it returns /// a pointer to the MachineOperand rather than an index. MachineOperand *findRegisterUseOperand(unsigned Reg, bool isKill = false, - const TargetRegisterInfo *TRI = NULL) { + const TargetRegisterInfo *TRI = nullptr) { int Idx = findRegisterUseOperandIdx(Reg, isKill, TRI); - return (Idx == -1) ? NULL : &getOperand(Idx); + return (Idx == -1) ? nullptr : &getOperand(Idx); } /// findRegisterDefOperandIdx() - Returns the operand index that is a def of @@ -791,14 +852,14 @@ public: /// This may also return a register mask operand when Overlap is true. int findRegisterDefOperandIdx(unsigned Reg, bool isDead = false, bool Overlap = false, - const TargetRegisterInfo *TRI = NULL) const; + const TargetRegisterInfo *TRI = nullptr) const; /// findRegisterDefOperand - Wrapper for findRegisterDefOperandIdx, it returns /// a pointer to the MachineOperand rather than an index. MachineOperand *findRegisterDefOperand(unsigned Reg, bool isDead = false, - const TargetRegisterInfo *TRI = NULL) { + const TargetRegisterInfo *TRI = nullptr) { int Idx = findRegisterDefOperandIdx(Reg, isDead, false, TRI); - return (Idx == -1) ? NULL : &getOperand(Idx); + return (Idx == -1) ? nullptr : &getOperand(Idx); } /// findFirstPredOperandIdx() - Find the index of the first operand in the @@ -816,7 +877,7 @@ public: /// The flag operand is an immediate that can be decoded with methods like /// InlineAsm::hasRegClassConstraint(). /// - int findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo = 0) const; + int findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo = nullptr) const; /// getRegClassConstraint - Compute the static register class constraint for /// operand OpIdx. For normal instructions, this is derived from the @@ -830,6 +891,37 @@ public: const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const; + /// \brief Applies the constraints (def/use) implied by this MI on \p Reg to + /// the given \p CurRC. + /// If \p ExploreBundle is set and MI is part of a bundle, all the + /// instructions inside the bundle will be taken into account. In other words, + /// this method accumulates all the constrains of the operand of this MI and + /// the related bundle if MI is a bundle or inside a bundle. + /// + /// Returns the register class that statisfies both \p CurRC and the + /// constraints set by MI. Returns NULL if such a register class does not + /// exist. + /// + /// \pre CurRC must not be NULL. + const TargetRegisterClass *getRegClassConstraintEffectForVReg( + unsigned Reg, const TargetRegisterClass *CurRC, + const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, + bool ExploreBundle = false) const; + + /// \brief Applies the constraints (def/use) implied by the \p OpIdx operand + /// to the given \p CurRC. + /// + /// Returns the register class that statisfies both \p CurRC and the + /// constraints set by \p OpIdx MI. Returns NULL if such a register class + /// does not exist. + /// + /// \pre CurRC must not be NULL. + /// \pre The operand at \p OpIdx must be a register. + const TargetRegisterClass * + getRegClassConstraintEffect(unsigned OpIdx, const TargetRegisterClass *CurRC, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI) const; + /// tieOperands - Add a tie between the register operands at DefIdx and /// UseIdx. The tie will cause the register allocator to ensure that the two /// operands are assigned the same physical register. @@ -847,7 +939,8 @@ public: /// check if the register def is tied to a source operand, due to either /// two-address elimination or inline assembly constraints. Returns the /// first tied use operand index by reference if UseOpIdx is not null. - bool isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx = 0) const { + bool isRegTiedToUseOperand(unsigned DefOpIdx, + unsigned *UseOpIdx = nullptr) const { const MachineOperand &MO = getOperand(DefOpIdx); if (!MO.isReg() || !MO.isDef() || !MO.isTied()) return false; @@ -857,9 +950,10 @@ public: } /// isRegTiedToDefOperand - Return true if the use operand of the specified - /// index is tied to an def operand. It also returns the def operand index by + /// index is tied to a def operand. It also returns the def operand index by /// reference if DefOpIdx is not null. - bool isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx = 0) const { + bool isRegTiedToDefOperand(unsigned UseOpIdx, + unsigned *DefOpIdx = nullptr) const { const MachineOperand &MO = getOperand(UseOpIdx); if (!MO.isReg() || !MO.isUse() || !MO.isTied()) return false; @@ -898,7 +992,8 @@ public: /// addRegisterDefined - We have determined MI defines a register. Make sure /// there is an operand defining Reg. - void addRegisterDefined(unsigned Reg, const TargetRegisterInfo *RegInfo = 0); + void addRegisterDefined(unsigned Reg, + const TargetRegisterInfo *RegInfo = nullptr); /// setPhysRegsDeadExcept - Mark every physreg used by this instruction as /// dead except those in the UsedRegs list. @@ -952,7 +1047,7 @@ public: // // Debugging support // - void print(raw_ostream &OS, const TargetMachine *TM = 0, + void print(raw_ostream &OS, const TargetMachine *TM = nullptr, bool SkipOpers = false) const; void dump() const; @@ -1038,6 +1133,13 @@ private: /// hasPropertyInBundle - Slow path for hasProperty when we're dealing with a /// bundle. bool hasPropertyInBundle(unsigned Mask, QueryType Type) const; + + /// \brief Implements the logic of getRegClassConstraintEffectForVReg for the + /// this MI and the given operand index \p OpIdx. + /// If the related operand does not constrained Reg, this returns CurRC. + const TargetRegisterClass *getRegClassConstraintEffectForVRegImpl( + unsigned OpIdx, unsigned Reg, const TargetRegisterClass *CurRC, + const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const; }; /// MachineInstrExpressionTrait - Special DenseMapInfo traits to compare @@ -1046,7 +1148,7 @@ private: /// useful for CSE, etc. struct MachineInstrExpressionTrait : DenseMapInfo<MachineInstr*> { static inline MachineInstr *getEmptyKey() { - return 0; + return nullptr; } static inline MachineInstr *getTombstoneKey() { diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index df01371a47ec..21a482cdbd4c 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -46,7 +46,7 @@ class MachineInstrBuilder { MachineFunction *MF; MachineInstr *MI; public: - MachineInstrBuilder() : MF(0), MI(0) {} + MachineInstrBuilder() : MF(nullptr), MI(nullptr) {} /// Create a MachineInstrBuilder for manipulating an existing instruction. /// F must be the machine function that was used to allocate I. @@ -172,7 +172,12 @@ public: MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); return *this; } - + + const MachineInstrBuilder &addCFIIndex(unsigned CFIIndex) const { + MI->addOperand(*MF, MachineOperand::CreateCFIIndex(CFIIndex)); + return *this; + } + const MachineInstrBuilder &addSym(MCSymbol *Sym) const { MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym)); return *this; diff --git a/include/llvm/CodeGen/MachineInstrBundle.h b/include/llvm/CodeGen/MachineInstrBundle.h index 9519edb3ebae..122022486345 100644 --- a/include/llvm/CodeGen/MachineInstrBundle.h +++ b/include/llvm/CodeGen/MachineInstrBundle.h @@ -196,7 +196,7 @@ public: /// each operand referring to Reg. /// @returns A filled-in RegInfo struct. VirtRegInfo analyzeVirtReg(unsigned Reg, - SmallVectorImpl<std::pair<MachineInstr*, unsigned> > *Ops = 0); + SmallVectorImpl<std::pair<MachineInstr*, unsigned> > *Ops = nullptr); /// analyzePhysReg - Analyze how the current instruction or bundle uses a /// physical register. This function should not be called after operator++(), diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index b058ecb4c279..4fbd46b6fb57 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -31,6 +31,7 @@ #define LLVM_CODEGEN_MACHINELOOPINFO_H #include "llvm/Analysis/LoopInfo.h" +#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" namespace llvm { @@ -119,11 +120,11 @@ public: /// runOnFunction - Calculate the natural loop information. /// - virtual bool runOnMachineFunction(MachineFunction &F); + bool runOnMachineFunction(MachineFunction &F) override; - virtual void releaseMemory() { LI.releaseMemory(); } + void releaseMemory() override { LI.releaseMemory(); } - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; /// removeLoop - This removes the specified top-level loop from this loop info /// object. The loop is not deleted, as it will presumably be inserted into diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index 00a55b57f334..2532c16271f0 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -16,11 +16,13 @@ #ifndef LLVM_CODEGEN_MACHINEMEMOPERAND_H #define LLVM_CODEGEN_MACHINEMEMOPERAND_H +#include "llvm/ADT/PointerUnion.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/IR/Value.h" // PointerLikeTypeTraits<Value*> #include "llvm/Support/DataTypes.h" namespace llvm { -class Value; class FoldingSetNodeID; class MDNode; class raw_ostream; @@ -33,17 +35,23 @@ struct MachinePointerInfo { /// V - This is the IR pointer value for the access, or it is null if unknown. /// If this is null, then the access is to a pointer in the default address /// space. - const Value *V; + PointerUnion<const Value *, const PseudoSourceValue *> V; /// Offset - This is an offset from the base Value*. int64_t Offset; - explicit MachinePointerInfo(const Value *v = 0, int64_t offset = 0) + explicit MachinePointerInfo(const Value *v = nullptr, int64_t offset = 0) + : V(v), Offset(offset) {} + + explicit MachinePointerInfo(const PseudoSourceValue *v, + int64_t offset = 0) : V(v), Offset(offset) {} MachinePointerInfo getWithOffset(int64_t O) const { - if (V == 0) return MachinePointerInfo(0, 0); - return MachinePointerInfo(V, Offset+O); + if (V.isNull()) return MachinePointerInfo(); + if (V.is<const Value*>()) + return MachinePointerInfo(V.get<const Value*>(), Offset+O); + return MachinePointerInfo(V.get<const PseudoSourceValue*>(), Offset+O); } /// getAddrSpace - Return the LLVM IR address space number that this pointer @@ -109,8 +117,8 @@ public: /// MachineMemOperand - Construct an MachineMemOperand object with the /// specified PtrInfo, flags, size, and base alignment. MachineMemOperand(MachinePointerInfo PtrInfo, unsigned flags, uint64_t s, - unsigned base_alignment, const MDNode *TBAAInfo = 0, - const MDNode *Ranges = 0); + unsigned base_alignment, const MDNode *TBAAInfo = nullptr, + const MDNode *Ranges = nullptr); const MachinePointerInfo &getPointerInfo() const { return PtrInfo; } @@ -121,7 +129,13 @@ public: /// other PseudoSourceValue member functions which return objects which stand /// for frame/stack pointer relative references and other special references /// which are not representable in the high-level IR. - const Value *getValue() const { return PtrInfo.V; } + const Value *getValue() const { return PtrInfo.V.dyn_cast<const Value*>(); } + + const PseudoSourceValue *getPseudoValue() const { + return PtrInfo.V.dyn_cast<const PseudoSourceValue*>(); + } + + const void *getOpaqueValue() const { return PtrInfo.V.getOpaqueValue(); } /// getFlags - Return the raw flags of the source value, \see MemOperandFlags. unsigned int getFlags() const { return Flags & ((1 << MOMaxBits) - 1); } @@ -134,6 +148,8 @@ public: /// number. int64_t getOffset() const { return PtrInfo.Offset; } + unsigned getAddrSpace() const { return PtrInfo.getAddrSpace(); } + /// getSize - Return the size in bytes of the memory reference. uint64_t getSize() const { return Size; } @@ -175,6 +191,7 @@ public: /// should only be used when an object is being relocated and all references /// to it are being updated. void setValue(const Value *NewSV) { PtrInfo.V = NewSV; } + void setValue(const PseudoSourceValue *NewSV) { PtrInfo.V = NewSV; } void setOffset(int64_t NewOffset) { PtrInfo.Offset = NewOffset; } /// Profile - Gather unique data for the object. diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 460c08c8ca7e..6d8d05684c56 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -35,14 +35,14 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MachineLocation.h" #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/DebugLoc.h" #include "llvm/Support/Dwarf.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { @@ -71,7 +71,7 @@ struct LandingPadInfo { std::vector<int> TypeIds; // List of type ids (filters negative) explicit LandingPadInfo(MachineBasicBlock *MBB) - : LandingPadBlock(MBB), LandingPadLabel(0), Personality(0) {} + : LandingPadBlock(MBB), LandingPadLabel(nullptr), Personality(nullptr) {} }; //===----------------------------------------------------------------------===// @@ -168,10 +168,13 @@ class MachineModuleInfo : public ImmutablePass { public: static char ID; // Pass identification, replacement for typeid - typedef std::pair<unsigned, DebugLoc> UnsignedDebugLocPair; - typedef SmallVector<std::pair<TrackingVH<MDNode>, UnsignedDebugLocPair>, 4> - VariableDbgInfoMapTy; - VariableDbgInfoMapTy VariableDbgInfo; + struct VariableDbgInfo { + TrackingVH<MDNode> Var; + unsigned Slot; + DebugLoc Loc; + }; + typedef SmallVector<VariableDbgInfo, 4> VariableDbgInfoMapTy; + VariableDbgInfoMapTy VariableDbgInfos; MachineModuleInfo(); // DUMMY CONSTRUCTOR, DO NOT CALL. // Real constructor. @@ -180,8 +183,8 @@ public: ~MachineModuleInfo(); // Initialization and Finalization - virtual bool doInitialization(Module &); - virtual bool doFinalization(Module &); + bool doInitialization(Module &) override; + bool doFinalization(Module &) override; /// EndFunction - Discard function meta information. /// @@ -198,7 +201,7 @@ public: /// template<typename Ty> Ty &getObjFileInfo() { - if (ObjFileMMI == 0) + if (ObjFileMMI == nullptr) ObjFileMMI = new Ty(*this); return *static_cast<Ty*>(ObjFileMMI); } @@ -238,8 +241,10 @@ public: return FrameInstructions; } - void addFrameInst(const MCCFIInstruction &Inst) { + unsigned LLVM_ATTRIBUTE_UNUSED_RESULT + addFrameInst(const MCCFIInstruction &Inst) { FrameInstructions.push_back(Inst); + return FrameInstructions.size() - 1; } /// getCompactUnwindEncoding - Returns the compact unwind encoding for a @@ -329,7 +334,7 @@ public: /// TidyLandingPads - Remap landing pad labels and remove any deleted landing /// pads. - void TidyLandingPads(DenseMap<MCSymbol*, uintptr_t> *LPMap = 0); + void TidyLandingPads(DenseMap<MCSymbol*, uintptr_t> *LPMap = nullptr); /// getLandingPads - Return a reference to the landing pad info for the /// current function. @@ -399,10 +404,11 @@ public: /// setVariableDbgInfo - Collect information used to emit debugging /// information of a variable. void setVariableDbgInfo(MDNode *N, unsigned Slot, DebugLoc Loc) { - VariableDbgInfo.push_back(std::make_pair(N, std::make_pair(Slot, Loc))); + VariableDbgInfo Info = { N, Slot, Loc }; + VariableDbgInfos.push_back(std::move(Info)); } - VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfo; } + VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfos; } }; // End class MachineModuleInfo diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 40f3580bfdb4..22969bc80776 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -42,28 +42,30 @@ class MCSymbol; /// class MachineOperand { public: - enum MachineOperandType { - MO_Register, ///< Register operand. - MO_Immediate, ///< Immediate operand - MO_CImmediate, ///< Immediate >64bit operand - MO_FPImmediate, ///< Floating-point immediate operand - MO_MachineBasicBlock, ///< MachineBasicBlock reference - MO_FrameIndex, ///< Abstract Stack Frame Index - MO_ConstantPoolIndex, ///< Address of indexed Constant in Constant Pool - MO_TargetIndex, ///< Target-dependent index+offset operand. - MO_JumpTableIndex, ///< Address of indexed Jump Table for switch - MO_ExternalSymbol, ///< Name of external global symbol - MO_GlobalAddress, ///< Address of a global value - MO_BlockAddress, ///< Address of a basic block - MO_RegisterMask, ///< Mask of preserved registers. - MO_Metadata, ///< Metadata reference (for debug info) - MO_MCSymbol ///< MCSymbol reference (for debug/eh info) + enum MachineOperandType : unsigned char { + MO_Register, ///< Register operand. + MO_Immediate, ///< Immediate operand + MO_CImmediate, ///< Immediate >64bit operand + MO_FPImmediate, ///< Floating-point immediate operand + MO_MachineBasicBlock, ///< MachineBasicBlock reference + MO_FrameIndex, ///< Abstract Stack Frame Index + MO_ConstantPoolIndex, ///< Address of indexed Constant in Constant Pool + MO_TargetIndex, ///< Target-dependent index+offset operand. + MO_JumpTableIndex, ///< Address of indexed Jump Table for switch + MO_ExternalSymbol, ///< Name of external global symbol + MO_GlobalAddress, ///< Address of a global value + MO_BlockAddress, ///< Address of a basic block + MO_RegisterMask, ///< Mask of preserved registers. + MO_RegisterLiveOut, ///< Mask of live-out registers. + MO_Metadata, ///< Metadata reference (for debug info) + MO_MCSymbol, ///< MCSymbol reference (for debug/eh info) + MO_CFIIndex ///< MCCFIInstruction index. }; private: /// OpKind - Specify what kind of operand this is. This discriminates the /// union. - unsigned char OpKind; // MachineOperandType + MachineOperandType OpKind; /// Subregister number for MO_Register. A value of 0 indicates the /// MO_Register has no subReg. @@ -149,13 +151,14 @@ private: /// Contents union - This contains the payload for the various operand types. union { - MachineBasicBlock *MBB; // For MO_MachineBasicBlock. - const ConstantFP *CFP; // For MO_FPImmediate. - const ConstantInt *CI; // For MO_CImmediate. Integers > 64bit. - int64_t ImmVal; // For MO_Immediate. - const uint32_t *RegMask; // For MO_RegisterMask. - const MDNode *MD; // For MO_Metadata. - MCSymbol *Sym; // For MO_MCSymbol + MachineBasicBlock *MBB; // For MO_MachineBasicBlock. + const ConstantFP *CFP; // For MO_FPImmediate. + const ConstantInt *CI; // For MO_CImmediate. Integers > 64bit. + int64_t ImmVal; // For MO_Immediate. + const uint32_t *RegMask; // For MO_RegisterMask and MO_RegisterLiveOut. + const MDNode *MD; // For MO_Metadata. + MCSymbol *Sym; // For MO_MCSymbol. + unsigned CFIIndex; // For MO_CFI. struct { // For MO_Register. // Register number is in SmallContents.RegNo. @@ -178,7 +181,7 @@ private: } Contents; explicit MachineOperand(MachineOperandType K) - : OpKind(K), SubReg_TargetFlags(0), ParentMI(0) {} + : OpKind(K), SubReg_TargetFlags(0), ParentMI(nullptr) {} public: /// getType - Returns the MachineOperandType for this operand. /// @@ -212,9 +215,9 @@ public: /// /// Never call clearParent() on an operand in a MachineInstr. /// - void clearParent() { ParentMI = 0; } + void clearParent() { ParentMI = nullptr; } - void print(raw_ostream &os, const TargetMachine *TM = 0) const; + void print(raw_ostream &os, const TargetMachine *TM = nullptr) const; //===--------------------------------------------------------------------===// // Accessors that tell you what kind of MachineOperand you're looking at. @@ -224,7 +227,7 @@ public: bool isReg() const { return OpKind == MO_Register; } /// isImm - Tests if this is a MO_Immediate operand. bool isImm() const { return OpKind == MO_Immediate; } - /// isCImm - Test if t his is a MO_CImmediate operand. + /// isCImm - Test if this is a MO_CImmediate operand. bool isCImm() const { return OpKind == MO_CImmediate; } /// isFPImm - Tests if this is a MO_FPImmediate operand. bool isFPImm() const { return OpKind == MO_FPImmediate; } @@ -246,10 +249,12 @@ public: bool isBlockAddress() const { return OpKind == MO_BlockAddress; } /// isRegMask - Tests if this is a MO_RegisterMask operand. bool isRegMask() const { return OpKind == MO_RegisterMask; } + /// isRegLiveOut - Tests if this is a MO_RegisterLiveOut operand. + bool isRegLiveOut() const { return OpKind == MO_RegisterLiveOut; } /// isMetadata - Tests if this is a MO_Metadata operand. bool isMetadata() const { return OpKind == MO_Metadata; } bool isMCSymbol() const { return OpKind == MO_MCSymbol; } - + bool isCFIIndex() const { return OpKind == MO_CFIIndex; } //===--------------------------------------------------------------------===// // Accessors for Register Operands @@ -440,6 +445,11 @@ public: return Contents.Sym; } + unsigned getCFIIndex() const { + assert(isCFIIndex() && "Wrong MachineOperand accessor"); + return Contents.CFIIndex; + } + /// getOffset - Return the offset from the symbol in this operand. This always /// returns 0 for ExternalSymbol operands. int64_t getOffset() const { @@ -476,6 +486,12 @@ public: return Contents.RegMask; } + /// getRegLiveOut - Returns a bit mask of live-out registers. + const uint32_t *getRegLiveOut() const { + assert(isRegLiveOut() && "Wrong MachineOperand accessor"); + return Contents.RegMask; + } + const MDNode *getMetadata() const { assert(isMetadata() && "Wrong MachineOperand accessor"); return Contents.MD; @@ -577,8 +593,8 @@ public: Op.TiedTo = 0; Op.IsDebug = isDebug; Op.SmallContents.RegNo = Reg; - Op.Contents.Reg.Prev = 0; - Op.Contents.Reg.Next = 0; + Op.Contents.Reg.Prev = nullptr; + Op.Contents.Reg.Next = nullptr; Op.setSubReg(SubReg); return Op; } @@ -659,6 +675,12 @@ public: Op.Contents.RegMask = Mask; return Op; } + static MachineOperand CreateRegLiveOut(const uint32_t *Mask) { + assert(Mask && "Missing live-out register mask"); + MachineOperand Op(MachineOperand::MO_RegisterLiveOut); + Op.Contents.RegMask = Mask; + return Op; + } static MachineOperand CreateMetadata(const MDNode *Meta) { MachineOperand Op(MachineOperand::MO_Metadata); Op.Contents.MD = Meta; @@ -671,6 +693,12 @@ public: return Op; } + static MachineOperand CreateCFIIndex(unsigned CFIIndex) { + MachineOperand Op(MachineOperand::MO_CFIIndex); + Op.Contents.CFIIndex = CFIIndex; + return Op; + } + friend class MachineInstr; friend class MachineRegisterInfo; private: @@ -683,12 +711,12 @@ private: /// part of a machine instruction. bool isOnRegUseList() const { assert(isReg() && "Can only add reg operand to use lists"); - return Contents.Reg.Prev != 0; + return Contents.Reg.Prev != nullptr; } }; inline raw_ostream &operator<<(raw_ostream &OS, const MachineOperand& MO) { - MO.print(OS, 0); + MO.print(OS, nullptr); return OS; } diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h index 90ee7f4bb9e7..c962e687243e 100644 --- a/include/llvm/CodeGen/MachinePassRegistry.h +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -59,7 +59,7 @@ private: public: MachinePassRegistryNode(const char *N, const char *D, MachinePassCtor C) - : Next(NULL) + : Next(nullptr) , Name(N) , Description(D) , Ctor(C) @@ -123,7 +123,7 @@ class RegisterPassParser : public MachinePassRegistryListener, public cl::parser<typename RegistryClass::FunctionPassCtor> { public: RegisterPassParser() {} - ~RegisterPassParser() { RegistryClass::setListener(NULL); } + ~RegisterPassParser() { RegistryClass::setListener(nullptr); } void initialize(cl::Option &O) { cl::parser<typename RegistryClass::FunctionPassCtor>::initialize(O); @@ -142,12 +142,10 @@ public: // Implement the MachinePassRegistryListener callbacks. // - virtual void NotifyAdd(const char *N, - MachinePassCtor C, - const char *D) { + void NotifyAdd(const char *N, MachinePassCtor C, const char *D) override { this->addLiteralOption(N, (typename RegistryClass::FunctionPassCtor)C, D); } - virtual void NotifyRemove(const char *N) { + void NotifyRemove(const char *N) override { this->removeLiteralOption(N); } }; diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h index ca09aef82616..beb2c4f0c5c0 100644 --- a/include/llvm/CodeGen/MachinePostDominators.h +++ b/include/llvm/CodeGen/MachinePostDominators.h @@ -15,7 +15,6 @@ #ifndef LLVM_CODEGEN_MACHINEPOSTDOMINATORS_H #define LLVM_CODEGEN_MACHINEPOSTDOMINATORS_H -#include "llvm/Analysis/Dominators.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -78,9 +77,9 @@ public: return DT->findNearestCommonDominator(A, B); } - virtual bool runOnMachineFunction(MachineFunction &MF); - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void print(llvm::raw_ostream &OS, const Module *M = 0) const; + bool runOnMachineFunction(MachineFunction &MF) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void print(llvm::raw_ostream &OS, const Module *M = nullptr) const override; }; } //end of namespace llvm diff --git a/include/llvm/CodeGen/MachineRegionInfo.h b/include/llvm/CodeGen/MachineRegionInfo.h new file mode 100644 index 000000000000..43499dba71c0 --- /dev/null +++ b/include/llvm/CodeGen/MachineRegionInfo.h @@ -0,0 +1,183 @@ +//===- llvm/CodeGen/MachineRegionInfo.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEREGIONINFO_H +#define LLVM_CODEGEN_MACHINEREGIONINFO_H + +#include "llvm/Analysis/RegionInfo.h" +#include "llvm/Analysis/RegionIterator.h" +#include "llvm/CodeGen/MachineDominanceFrontier.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" + + +namespace llvm { + +class MachineDominatorTree; +struct MachinePostDominatorTree; +class MachineRegion; +class MachineRegionNode; +class MachineRegionInfo; + +template<> +struct RegionTraits<MachineFunction> { + typedef MachineFunction FuncT; + typedef MachineBasicBlock BlockT; + typedef MachineRegion RegionT; + typedef MachineRegionNode RegionNodeT; + typedef MachineRegionInfo RegionInfoT; + typedef MachineDominatorTree DomTreeT; + typedef MachineDomTreeNode DomTreeNodeT; + typedef MachinePostDominatorTree PostDomTreeT; + typedef MachineDominanceFrontier DomFrontierT; + typedef MachineInstr InstT; + typedef MachineLoop LoopT; + typedef MachineLoopInfo LoopInfoT; + + static unsigned getNumSuccessors(MachineBasicBlock *BB) { + return BB->succ_size(); + } +}; + + +class MachineRegionNode : public RegionNodeBase<RegionTraits<MachineFunction>> { +public: + inline MachineRegionNode(MachineRegion *Parent, + MachineBasicBlock *Entry, + bool isSubRegion = false) + : RegionNodeBase<RegionTraits<MachineFunction>>(Parent, Entry, isSubRegion) { + + } + + ~MachineRegionNode() { } + + bool operator==(const MachineRegion &RN) const { + return this == reinterpret_cast<const MachineRegionNode*>(&RN); + } +}; + +class MachineRegion : public RegionBase<RegionTraits<MachineFunction>> { +public: + MachineRegion(MachineBasicBlock *Entry, MachineBasicBlock *Exit, + MachineRegionInfo* RI, + MachineDominatorTree *DT, MachineRegion *Parent = nullptr); + ~MachineRegion(); + + bool operator==(const MachineRegionNode &RN) const { + return &RN == reinterpret_cast<const MachineRegionNode*>(this); + } +}; + +class MachineRegionInfo : public RegionInfoBase<RegionTraits<MachineFunction>> { +public: + explicit MachineRegionInfo(); + + virtual ~MachineRegionInfo(); + + // updateStatistics - Update statistic about created regions. + void updateStatistics(MachineRegion *R) final; + + void recalculate(MachineFunction &F, + MachineDominatorTree *DT, + MachinePostDominatorTree *PDT, + MachineDominanceFrontier *DF); +}; + +class MachineRegionInfoPass : public MachineFunctionPass { + MachineRegionInfo RI; + +public: + static char ID; + explicit MachineRegionInfoPass(); + + ~MachineRegionInfoPass(); + + MachineRegionInfo &getRegionInfo() { + return RI; + } + + const MachineRegionInfo &getRegionInfo() const { + return RI; + } + + /// @name MachineFunctionPass interface + //@{ + bool runOnMachineFunction(MachineFunction &F) override; + void releaseMemory() override; + void verifyAnalysis() const override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void print(raw_ostream &OS, const Module *) const override; + void dump() const; + //@} +}; + + +template <> +template <> +inline MachineBasicBlock* RegionNodeBase<RegionTraits<MachineFunction>>::getNodeAs<MachineBasicBlock>() const { + assert(!isSubRegion() && "This is not a MachineBasicBlock RegionNode!"); + return getEntry(); +} + +template<> +template<> +inline MachineRegion* RegionNodeBase<RegionTraits<MachineFunction>>::getNodeAs<MachineRegion>() const { + assert(isSubRegion() && "This is not a subregion RegionNode!"); + auto Unconst = const_cast<RegionNodeBase<RegionTraits<MachineFunction>>*>(this); + return reinterpret_cast<MachineRegion*>(Unconst); +} + + +RegionNodeGraphTraits(MachineRegionNode, MachineBasicBlock, MachineRegion); +RegionNodeGraphTraits(const MachineRegionNode, MachineBasicBlock, MachineRegion); + +RegionGraphTraits(MachineRegion, MachineRegionNode); +RegionGraphTraits(const MachineRegion, const MachineRegionNode); + +template <> struct GraphTraits<MachineRegionInfo*> + : public GraphTraits<FlatIt<MachineRegionNode*> > { + typedef df_iterator<NodeType*, SmallPtrSet<NodeType*, 8>, false, + GraphTraits<FlatIt<NodeType*> > > nodes_iterator; + + static NodeType *getEntryNode(MachineRegionInfo *RI) { + return GraphTraits<FlatIt<MachineRegion*> >::getEntryNode(RI->getTopLevelRegion()); + } + static nodes_iterator nodes_begin(MachineRegionInfo* RI) { + return nodes_iterator::begin(getEntryNode(RI)); + } + static nodes_iterator nodes_end(MachineRegionInfo *RI) { + return nodes_iterator::end(getEntryNode(RI)); + } +}; + +template <> struct GraphTraits<MachineRegionInfoPass*> + : public GraphTraits<MachineRegionInfo *> { + typedef df_iterator<NodeType*, SmallPtrSet<NodeType*, 8>, false, + GraphTraits<FlatIt<NodeType*> > > nodes_iterator; + + static NodeType *getEntryNode(MachineRegionInfoPass *RI) { + return GraphTraits<MachineRegionInfo*>::getEntryNode(&RI->getRegionInfo()); + } + static nodes_iterator nodes_begin(MachineRegionInfoPass* RI) { + return GraphTraits<MachineRegionInfo*>::nodes_begin(&RI->getRegionInfo()); + } + static nodes_iterator nodes_end(MachineRegionInfoPass *RI) { + return GraphTraits<MachineRegionInfo*>::nodes_end(&RI->getRegionInfo()); + } +}; + +EXTERN_TEMPLATE_INSTANTIATION(class RegionBase<RegionTraits<MachineFunction>>); +EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase<RegionTraits<MachineFunction>>); +EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase<RegionTraits<MachineFunction>>); + +} + +#endif diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 58ca907316ac..51139f72ba22 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -16,6 +16,7 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/MachineInstrBundle.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" @@ -134,7 +135,7 @@ public: // notifications, we will need to change to using a list. assert(TheDelegate == delegate && "Only the current delegate can perform reset!"); - TheDelegate = 0; + TheDelegate = nullptr; } void setDelegate(Delegate *delegate) { @@ -200,19 +201,66 @@ public: /// reg_begin/reg_end - Provide iteration support to walk over all definitions /// and uses of a register within the MachineFunction that corresponds to this /// MachineRegisterInfo object. - template<bool Uses, bool Defs, bool SkipDebug> + template<bool Uses, bool Defs, bool SkipDebug, + bool ByOperand, bool ByInstr, bool ByBundle> class defusechain_iterator; + template<bool Uses, bool Defs, bool SkipDebug, + bool ByOperand, bool ByInstr, bool ByBundle> + class defusechain_instr_iterator; // Make it a friend so it can access getNextOperandForReg(). - template<bool, bool, bool> friend class defusechain_iterator; + template<bool, bool, bool, bool, bool, bool> + friend class defusechain_iterator; + template<bool, bool, bool, bool, bool, bool> + friend class defusechain_instr_iterator; + + /// reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified /// register. - typedef defusechain_iterator<true,true,false> reg_iterator; + typedef defusechain_iterator<true,true,false,true,false,false> + reg_iterator; reg_iterator reg_begin(unsigned RegNo) const { return reg_iterator(getRegUseDefListHead(RegNo)); } - static reg_iterator reg_end() { return reg_iterator(0); } + static reg_iterator reg_end() { return reg_iterator(nullptr); } + + inline iterator_range<reg_iterator> reg_operands(unsigned Reg) const { + return iterator_range<reg_iterator>(reg_begin(Reg), reg_end()); + } + + /// reg_instr_iterator/reg_instr_begin/reg_instr_end - Walk all defs and uses + /// of the specified register, stepping by MachineInstr. + typedef defusechain_instr_iterator<true,true,false,false,true,false> + reg_instr_iterator; + reg_instr_iterator reg_instr_begin(unsigned RegNo) const { + return reg_instr_iterator(getRegUseDefListHead(RegNo)); + } + static reg_instr_iterator reg_instr_end() { + return reg_instr_iterator(nullptr); + } + + inline iterator_range<reg_instr_iterator> + reg_instructions(unsigned Reg) const { + return iterator_range<reg_instr_iterator>(reg_instr_begin(Reg), + reg_instr_end()); + } + + /// reg_bundle_iterator/reg_bundle_begin/reg_bundle_end - Walk all defs and uses + /// of the specified register, stepping by bundle. + typedef defusechain_instr_iterator<true,true,false,false,false,true> + reg_bundle_iterator; + reg_bundle_iterator reg_bundle_begin(unsigned RegNo) const { + return reg_bundle_iterator(getRegUseDefListHead(RegNo)); + } + static reg_bundle_iterator reg_bundle_end() { + return reg_bundle_iterator(nullptr); + } + + inline iterator_range<reg_bundle_iterator> reg_bundles(unsigned Reg) const { + return iterator_range<reg_bundle_iterator>(reg_bundle_begin(Reg), + reg_bundle_end()); + } /// reg_empty - Return true if there are no instructions using or defining the /// specified register (it may be live-in). @@ -220,11 +268,56 @@ public: /// reg_nodbg_iterator/reg_nodbg_begin/reg_nodbg_end - Walk all defs and uses /// of the specified register, skipping those marked as Debug. - typedef defusechain_iterator<true,true,true> reg_nodbg_iterator; + typedef defusechain_iterator<true,true,true,true,false,false> + reg_nodbg_iterator; reg_nodbg_iterator reg_nodbg_begin(unsigned RegNo) const { return reg_nodbg_iterator(getRegUseDefListHead(RegNo)); } - static reg_nodbg_iterator reg_nodbg_end() { return reg_nodbg_iterator(0); } + static reg_nodbg_iterator reg_nodbg_end() { + return reg_nodbg_iterator(nullptr); + } + + inline iterator_range<reg_nodbg_iterator> + reg_nodbg_operands(unsigned Reg) const { + return iterator_range<reg_nodbg_iterator>(reg_nodbg_begin(Reg), + reg_nodbg_end()); + } + + /// reg_instr_nodbg_iterator/reg_instr_nodbg_begin/reg_instr_nodbg_end - Walk + /// all defs and uses of the specified register, stepping by MachineInstr, + /// skipping those marked as Debug. + typedef defusechain_instr_iterator<true,true,true,false,true,false> + reg_instr_nodbg_iterator; + reg_instr_nodbg_iterator reg_instr_nodbg_begin(unsigned RegNo) const { + return reg_instr_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static reg_instr_nodbg_iterator reg_instr_nodbg_end() { + return reg_instr_nodbg_iterator(nullptr); + } + + inline iterator_range<reg_instr_nodbg_iterator> + reg_nodbg_instructions(unsigned Reg) const { + return iterator_range<reg_instr_nodbg_iterator>(reg_instr_nodbg_begin(Reg), + reg_instr_nodbg_end()); + } + + /// reg_bundle_nodbg_iterator/reg_bundle_nodbg_begin/reg_bundle_nodbg_end - Walk + /// all defs and uses of the specified register, stepping by bundle, + /// skipping those marked as Debug. + typedef defusechain_instr_iterator<true,true,true,false,false,true> + reg_bundle_nodbg_iterator; + reg_bundle_nodbg_iterator reg_bundle_nodbg_begin(unsigned RegNo) const { + return reg_bundle_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static reg_bundle_nodbg_iterator reg_bundle_nodbg_end() { + return reg_bundle_nodbg_iterator(nullptr); + } + + inline iterator_range<reg_bundle_nodbg_iterator> + reg_nodbg_bundles(unsigned Reg) const { + return iterator_range<reg_bundle_nodbg_iterator>(reg_bundle_nodbg_begin(Reg), + reg_bundle_nodbg_end()); + } /// reg_nodbg_empty - Return true if the only instructions using or defining /// Reg are Debug instructions. @@ -233,11 +326,49 @@ public: } /// def_iterator/def_begin/def_end - Walk all defs of the specified register. - typedef defusechain_iterator<false,true,false> def_iterator; + typedef defusechain_iterator<false,true,false,true,false,false> + def_iterator; def_iterator def_begin(unsigned RegNo) const { return def_iterator(getRegUseDefListHead(RegNo)); } - static def_iterator def_end() { return def_iterator(0); } + static def_iterator def_end() { return def_iterator(nullptr); } + + inline iterator_range<def_iterator> def_operands(unsigned Reg) const { + return iterator_range<def_iterator>(def_begin(Reg), def_end()); + } + + /// def_instr_iterator/def_instr_begin/def_instr_end - Walk all defs of the + /// specified register, stepping by MachineInst. + typedef defusechain_instr_iterator<false,true,false,false,true,false> + def_instr_iterator; + def_instr_iterator def_instr_begin(unsigned RegNo) const { + return def_instr_iterator(getRegUseDefListHead(RegNo)); + } + static def_instr_iterator def_instr_end() { + return def_instr_iterator(nullptr); + } + + inline iterator_range<def_instr_iterator> + def_instructions(unsigned Reg) const { + return iterator_range<def_instr_iterator>(def_instr_begin(Reg), + def_instr_end()); + } + + /// def_bundle_iterator/def_bundle_begin/def_bundle_end - Walk all defs of the + /// specified register, stepping by bundle. + typedef defusechain_instr_iterator<false,true,false,false,false,true> + def_bundle_iterator; + def_bundle_iterator def_bundle_begin(unsigned RegNo) const { + return def_bundle_iterator(getRegUseDefListHead(RegNo)); + } + static def_bundle_iterator def_bundle_end() { + return def_bundle_iterator(nullptr); + } + + inline iterator_range<def_bundle_iterator> def_bundles(unsigned Reg) const { + return iterator_range<def_bundle_iterator>(def_bundle_begin(Reg), + def_bundle_end()); + } /// def_empty - Return true if there are no instructions defining the /// specified register (it may be live-in). @@ -253,11 +384,49 @@ public: } /// use_iterator/use_begin/use_end - Walk all uses of the specified register. - typedef defusechain_iterator<true,false,false> use_iterator; + typedef defusechain_iterator<true,false,false,true,false,false> + use_iterator; use_iterator use_begin(unsigned RegNo) const { return use_iterator(getRegUseDefListHead(RegNo)); } - static use_iterator use_end() { return use_iterator(0); } + static use_iterator use_end() { return use_iterator(nullptr); } + + inline iterator_range<use_iterator> use_operands(unsigned Reg) const { + return iterator_range<use_iterator>(use_begin(Reg), use_end()); + } + + /// use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the + /// specified register, stepping by MachineInstr. + typedef defusechain_instr_iterator<true,false,false,false,true,false> + use_instr_iterator; + use_instr_iterator use_instr_begin(unsigned RegNo) const { + return use_instr_iterator(getRegUseDefListHead(RegNo)); + } + static use_instr_iterator use_instr_end() { + return use_instr_iterator(nullptr); + } + + inline iterator_range<use_instr_iterator> + use_instructions(unsigned Reg) const { + return iterator_range<use_instr_iterator>(use_instr_begin(Reg), + use_instr_end()); + } + + /// use_bundle_iterator/use_bundle_begin/use_bundle_end - Walk all uses of the + /// specified register, stepping by bundle. + typedef defusechain_instr_iterator<true,false,false,false,false,true> + use_bundle_iterator; + use_bundle_iterator use_bundle_begin(unsigned RegNo) const { + return use_bundle_iterator(getRegUseDefListHead(RegNo)); + } + static use_bundle_iterator use_bundle_end() { + return use_bundle_iterator(nullptr); + } + + inline iterator_range<use_bundle_iterator> use_bundles(unsigned Reg) const { + return iterator_range<use_bundle_iterator>(use_bundle_begin(Reg), + use_bundle_end()); + } /// use_empty - Return true if there are no instructions using the specified /// register. @@ -274,11 +443,56 @@ public: /// use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the /// specified register, skipping those marked as Debug. - typedef defusechain_iterator<true,false,true> use_nodbg_iterator; + typedef defusechain_iterator<true,false,true,true,false,false> + use_nodbg_iterator; use_nodbg_iterator use_nodbg_begin(unsigned RegNo) const { return use_nodbg_iterator(getRegUseDefListHead(RegNo)); } - static use_nodbg_iterator use_nodbg_end() { return use_nodbg_iterator(0); } + static use_nodbg_iterator use_nodbg_end() { + return use_nodbg_iterator(nullptr); + } + + inline iterator_range<use_nodbg_iterator> + use_nodbg_operands(unsigned Reg) const { + return iterator_range<use_nodbg_iterator>(use_nodbg_begin(Reg), + use_nodbg_end()); + } + + /// use_instr_nodbg_iterator/use_instr_nodbg_begin/use_instr_nodbg_end - Walk + /// all uses of the specified register, stepping by MachineInstr, skipping + /// those marked as Debug. + typedef defusechain_instr_iterator<true,false,true,false,true,false> + use_instr_nodbg_iterator; + use_instr_nodbg_iterator use_instr_nodbg_begin(unsigned RegNo) const { + return use_instr_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static use_instr_nodbg_iterator use_instr_nodbg_end() { + return use_instr_nodbg_iterator(nullptr); + } + + inline iterator_range<use_instr_nodbg_iterator> + use_nodbg_instructions(unsigned Reg) const { + return iterator_range<use_instr_nodbg_iterator>(use_instr_nodbg_begin(Reg), + use_instr_nodbg_end()); + } + + /// use_bundle_nodbg_iterator/use_bundle_nodbg_begin/use_bundle_nodbg_end - Walk + /// all uses of the specified register, stepping by bundle, skipping + /// those marked as Debug. + typedef defusechain_instr_iterator<true,false,true,false,false,true> + use_bundle_nodbg_iterator; + use_bundle_nodbg_iterator use_bundle_nodbg_begin(unsigned RegNo) const { + return use_bundle_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static use_bundle_nodbg_iterator use_bundle_nodbg_end() { + return use_bundle_nodbg_iterator(nullptr); + } + + inline iterator_range<use_bundle_nodbg_iterator> + use_nodbg_bundles(unsigned Reg) const { + return iterator_range<use_bundle_nodbg_iterator>(use_bundle_nodbg_begin(Reg), + use_bundle_nodbg_end()); + } /// use_nodbg_empty - Return true if there are no non-Debug instructions /// using the specified register. @@ -401,6 +615,10 @@ public: return Hint.first ? 0 : Hint.second; } + /// markUsesInDebugValueAsUndef - Mark every DBG_VALUE referencing the + /// specified register as undefined which causes the DBG_VALUE to be + /// deleted during LiveDebugVariables analysis. + void markUsesInDebugValueAsUndef(unsigned Reg) const; //===--------------------------------------------------------------------===// // Physical Register Use Info @@ -552,7 +770,8 @@ public: /// returns defs. If neither are true then you are silly and it always /// returns end(). If SkipDebug is true it skips uses marked Debug /// when incrementing. - template<bool ReturnUses, bool ReturnDefs, bool SkipDebug> + template<bool ReturnUses, bool ReturnDefs, bool SkipDebug, + bool ByOperand, bool ByInstr, bool ByBundle> class defusechain_iterator : public std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t> { MachineOperand *Op; @@ -563,10 +782,30 @@ public: if ((!ReturnUses && op->isUse()) || (!ReturnDefs && op->isDef()) || (SkipDebug && op->isDebug())) - ++*this; + advance(); } } friend class MachineRegisterInfo; + + void advance() { + assert(Op && "Cannot increment end iterator!"); + Op = getNextOperandForReg(Op); + + // All defs come before the uses, so stop def_iterator early. + if (!ReturnUses) { + if (Op) { + if (Op->isUse()) + Op = nullptr; + else + assert(!Op->isDebug() && "Can't have debug defs"); + } + } else { + // If this is an operand we don't care about, skip it. + while (Op && ((!ReturnDefs && Op->isDef()) || + (SkipDebug && Op->isDebug()))) + Op = getNextOperandForReg(Op); + } + } public: typedef std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t>::reference reference; @@ -574,7 +813,7 @@ public: MachineInstr, ptrdiff_t>::pointer pointer; defusechain_iterator(const defusechain_iterator &I) : Op(I.Op) {} - defusechain_iterator() : Op(0) {} + defusechain_iterator() : Op(nullptr) {} bool operator==(const defusechain_iterator &x) const { return Op == x.Op; @@ -584,18 +823,82 @@ public: } /// atEnd - return true if this iterator is equal to reg_end() on the value. - bool atEnd() const { return Op == 0; } + bool atEnd() const { return Op == nullptr; } // Iterator traversal: forward iteration only defusechain_iterator &operator++() { // Preincrement assert(Op && "Cannot increment end iterator!"); + if (ByOperand) + advance(); + else if (ByInstr) { + MachineInstr *P = Op->getParent(); + do { + advance(); + } while (Op && Op->getParent() == P); + } else if (ByBundle) { + MachineInstr *P = getBundleStart(Op->getParent()); + do { + advance(); + } while (Op && getBundleStart(Op->getParent()) == P); + } + + return *this; + } + defusechain_iterator operator++(int) { // Postincrement + defusechain_iterator tmp = *this; ++*this; return tmp; + } + + /// getOperandNo - Return the operand # of this MachineOperand in its + /// MachineInstr. + unsigned getOperandNo() const { + assert(Op && "Cannot dereference end iterator!"); + return Op - &Op->getParent()->getOperand(0); + } + + // Retrieve a reference to the current operand. + MachineOperand &operator*() const { + assert(Op && "Cannot dereference end iterator!"); + return *Op; + } + + MachineOperand *operator->() const { + assert(Op && "Cannot dereference end iterator!"); + return Op; + } + }; + + /// defusechain_iterator - This class provides iterator support for machine + /// operands in the function that use or define a specific register. If + /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it + /// returns defs. If neither are true then you are silly and it always + /// returns end(). If SkipDebug is true it skips uses marked Debug + /// when incrementing. + template<bool ReturnUses, bool ReturnDefs, bool SkipDebug, + bool ByOperand, bool ByInstr, bool ByBundle> + class defusechain_instr_iterator + : public std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t> { + MachineOperand *Op; + explicit defusechain_instr_iterator(MachineOperand *op) : Op(op) { + // If the first node isn't one we're interested in, advance to one that + // we are interested in. + if (op) { + if ((!ReturnUses && op->isUse()) || + (!ReturnDefs && op->isDef()) || + (SkipDebug && op->isDebug())) + advance(); + } + } + friend class MachineRegisterInfo; + + void advance() { + assert(Op && "Cannot increment end iterator!"); Op = getNextOperandForReg(Op); // All defs come before the uses, so stop def_iterator early. if (!ReturnUses) { if (Op) { if (Op->isUse()) - Op = 0; + Op = nullptr; else assert(!Op->isDebug() && "Can't have debug defs"); } @@ -605,52 +908,59 @@ public: (SkipDebug && Op->isDebug()))) Op = getNextOperandForReg(Op); } + } + public: + typedef std::iterator<std::forward_iterator_tag, + MachineInstr, ptrdiff_t>::reference reference; + typedef std::iterator<std::forward_iterator_tag, + MachineInstr, ptrdiff_t>::pointer pointer; - return *this; + defusechain_instr_iterator(const defusechain_instr_iterator &I) : Op(I.Op){} + defusechain_instr_iterator() : Op(nullptr) {} + + bool operator==(const defusechain_instr_iterator &x) const { + return Op == x.Op; } - defusechain_iterator operator++(int) { // Postincrement - defusechain_iterator tmp = *this; ++*this; return tmp; + bool operator!=(const defusechain_instr_iterator &x) const { + return !operator==(x); } - /// skipInstruction - move forward until reaching a different instruction. - /// Return the skipped instruction that is no longer pointed to, or NULL if - /// already pointing to end(). - MachineInstr *skipInstruction() { - if (!Op) return 0; - MachineInstr *MI = Op->getParent(); - do ++*this; - while (Op && Op->getParent() == MI); - return MI; - } + /// atEnd - return true if this iterator is equal to reg_end() on the value. + bool atEnd() const { return Op == nullptr; } - MachineInstr *skipBundle() { - if (!Op) return 0; - MachineInstr *MI = getBundleStart(Op->getParent()); - do ++*this; - while (Op && getBundleStart(Op->getParent()) == MI); - return MI; - } + // Iterator traversal: forward iteration only + defusechain_instr_iterator &operator++() { // Preincrement + assert(Op && "Cannot increment end iterator!"); + if (ByOperand) + advance(); + else if (ByInstr) { + MachineInstr *P = Op->getParent(); + do { + advance(); + } while (Op && Op->getParent() == P); + } else if (ByBundle) { + MachineInstr *P = getBundleStart(Op->getParent()); + do { + advance(); + } while (Op && getBundleStart(Op->getParent()) == P); + } - MachineOperand &getOperand() const { - assert(Op && "Cannot dereference end iterator!"); - return *Op; + return *this; } - - /// getOperandNo - Return the operand # of this MachineOperand in its - /// MachineInstr. - unsigned getOperandNo() const { - assert(Op && "Cannot dereference end iterator!"); - return Op - &Op->getParent()->getOperand(0); + defusechain_instr_iterator operator++(int) { // Postincrement + defusechain_instr_iterator tmp = *this; ++*this; return tmp; } // Retrieve a reference to the current operand. MachineInstr &operator*() const { assert(Op && "Cannot dereference end iterator!"); + if (ByBundle) return *(getBundleStart(Op->getParent())); return *Op->getParent(); } MachineInstr *operator->() const { assert(Op && "Cannot dereference end iterator!"); + if (ByBundle) return getBundleStart(Op->getParent()); return Op->getParent(); } }; @@ -663,7 +973,7 @@ class PSetIterator { const int *PSet; unsigned Weight; public: - PSetIterator(): PSet(0), Weight(0) {} + PSetIterator(): PSet(nullptr), Weight(0) {} PSetIterator(unsigned RegUnit, const MachineRegisterInfo *MRI) { const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo(); if (TargetRegisterInfo::isVirtualRegister(RegUnit)) { @@ -676,7 +986,7 @@ public: Weight = TRI->getRegUnitWeight(RegUnit); } if (*PSet == -1) - PSet = 0; + PSet = nullptr; } bool isValid() const { return PSet; } @@ -688,7 +998,7 @@ public: assert(isValid() && "Invalid PSetIterator."); ++PSet; if (*PSet == -1) - PSet = 0; + PSet = nullptr; } }; diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h index edf93d13bd1d..486a26e92714 100644 --- a/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/include/llvm/CodeGen/MachineSSAUpdater.h @@ -14,6 +14,7 @@ #ifndef LLVM_CODEGEN_MACHINESSAUPDATER_H #define LLVM_CODEGEN_MACHINESSAUPDATER_H +#include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" namespace llvm { @@ -26,7 +27,6 @@ namespace llvm { class TargetRegisterClass; template<typename T> class SmallVectorImpl; template<typename T> class SSAUpdaterTraits; - class BumpPtrAllocator; /// MachineSSAUpdater - This class updates SSA form for a set of virtual /// registers defined in multiple blocks. This is used when code duplication @@ -57,7 +57,7 @@ public: /// MachineSSAUpdater constructor. If InsertedPHIs is specified, it will be /// filled in with all PHI Nodes created by rewriting. explicit MachineSSAUpdater(MachineFunction &MF, - SmallVectorImpl<MachineInstr*> *InsertedPHIs = 0); + SmallVectorImpl<MachineInstr*> *InsertedPHIs = nullptr); ~MachineSSAUpdater(); /// Initialize - Reset this object to get ready for a new set of SSA @@ -105,7 +105,6 @@ public: void RewriteUse(MachineOperand &U); private: - void ReplaceRegWith(unsigned OldReg, unsigned NewReg); unsigned GetValueAtEndOfBlockInternal(MachineBasicBlock *BB); void operator=(const MachineSSAUpdater&) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 77828953347c..7d85432101b5 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -23,7 +23,7 @@ // return new CustomMachineScheduler(C); // } // -// The default scheduler, ScheduleDAGMI, builds the DAG and drives list +// The default scheduler, ScheduleDAGMILive, builds the DAG and drives list // scheduling while updating the instruction stream, register pressure, and live // intervals. Most targets don't need to override the DAG builder and list // schedulier, but subtargets that require custom scheduling heuristics may @@ -81,6 +81,8 @@ #include "llvm/CodeGen/RegisterPressure.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" +#include <memory> + namespace llvm { extern cl::opt<bool> ForceTopDown; @@ -93,6 +95,7 @@ class MachineLoopInfo; class RegisterClassInfo; class ScheduleDAGInstrs; class SchedDFSResult; +class ScheduleHazardRecognizer; /// MachineSchedContext provides enough context from the MachineScheduler pass /// for the target to instantiate a scheduler. @@ -154,8 +157,8 @@ struct MachineSchedPolicy { bool OnlyTopDown; bool OnlyBottomUp; - MachineSchedPolicy(): - ShouldTrackPressure(false), OnlyTopDown(false), OnlyBottomUp(false) {} + MachineSchedPolicy(): ShouldTrackPressure(false), OnlyTopDown(false), + OnlyBottomUp(false) {} }; /// MachineSchedStrategy - Interface to the scheduling algorithm used by @@ -204,63 +207,6 @@ public: virtual void releaseBottomNode(SUnit *SU) = 0; }; -/// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience -/// methods for pushing and removing nodes. ReadyQueue's are uniquely identified -/// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in. -/// -/// This is a convenience class that may be used by implementations of -/// MachineSchedStrategy. -class ReadyQueue { - unsigned ID; - std::string Name; - std::vector<SUnit*> Queue; - -public: - ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {} - - unsigned getID() const { return ID; } - - StringRef getName() const { return Name; } - - // SU is in this queue if it's NodeQueueID is a superset of this ID. - bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); } - - bool empty() const { return Queue.empty(); } - - void clear() { Queue.clear(); } - - unsigned size() const { return Queue.size(); } - - typedef std::vector<SUnit*>::iterator iterator; - - iterator begin() { return Queue.begin(); } - - iterator end() { return Queue.end(); } - - ArrayRef<SUnit*> elements() { return Queue; } - - iterator find(SUnit *SU) { - return std::find(Queue.begin(), Queue.end(), SU); - } - - void push(SUnit *SU) { - Queue.push_back(SU); - SU->NodeQueueId |= ID; - } - - iterator remove(iterator I) { - (*I)->NodeQueueId &= ~ID; - *I = Queue.back(); - unsigned idx = I - Queue.begin(); - Queue.pop_back(); - return Queue.begin() + idx; - } - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - void dump(); -#endif -}; - /// Mutate the DAG as a postpass after normal DAG building. class ScheduleDAGMutation { virtual void anchor(); @@ -270,52 +216,27 @@ public: virtual void apply(ScheduleDAGMI *DAG) = 0; }; -/// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that schedules -/// machine instructions while updating LiveIntervals and tracking regpressure. +/// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply +/// schedules machine instructions according to the given MachineSchedStrategy +/// without much extra book-keeping. This is the common functionality between +/// PreRA and PostRA MachineScheduler. class ScheduleDAGMI : public ScheduleDAGInstrs { protected: AliasAnalysis *AA; - RegisterClassInfo *RegClassInfo; - MachineSchedStrategy *SchedImpl; - - /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees - /// will be empty. - SchedDFSResult *DFSResult; - BitVector ScheduledTrees; + std::unique_ptr<MachineSchedStrategy> SchedImpl; /// Topo - A topological ordering for SUnits which permits fast IsReachable /// and similar queries. ScheduleDAGTopologicalSort Topo; /// Ordered list of DAG postprocessing steps. - std::vector<ScheduleDAGMutation*> Mutations; - - MachineBasicBlock::iterator LiveRegionEnd; - - // Map each SU to its summary of pressure changes. This array is updated for - // liveness during bottom-up scheduling. Top-down scheduling may proceed but - // has no affect on the pressure diffs. - PressureDiffs SUPressureDiffs; - - /// Register pressure in this region computed by initRegPressure. - bool ShouldTrackPressure; - IntervalPressure RegPressure; - RegPressureTracker RPTracker; - - /// List of pressure sets that exceed the target's pressure limit before - /// scheduling, listed in increasing set ID order. Each pressure set is paired - /// with its max pressure in the currently scheduled regions. - std::vector<PressureChange> RegionCriticalPSets; + std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations; /// The top of the unscheduled zone. MachineBasicBlock::iterator CurrentTop; - IntervalPressure TopPressure; - RegPressureTracker TopRPTracker; /// The bottom of the unscheduled zone. MachineBasicBlock::iterator CurrentBottom; - IntervalPressure BotPressure; - RegPressureTracker BotRPTracker; /// Record the next node in a scheduled cluster. const SUnit *NextClusterPred; @@ -326,32 +247,31 @@ protected: /// scheduler at the point determined by misched-cutoff. unsigned NumInstrsScheduled; #endif - public: - ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S): - ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), - AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), DFSResult(0), - Topo(SUnits, &ExitSU), ShouldTrackPressure(false), - RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure), - CurrentBottom(), BotRPTracker(BotPressure), - NextClusterPred(NULL), NextClusterSucc(NULL) { + ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S, + bool IsPostRA) + : ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, IsPostRA, + /*RemoveKillFlags=*/IsPostRA, C->LIS), + AA(C->AA), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU), CurrentTop(), + CurrentBottom(), NextClusterPred(nullptr), NextClusterSucc(nullptr) { #ifndef NDEBUG NumInstrsScheduled = 0; #endif } - virtual ~ScheduleDAGMI(); + // Provide a vtable anchor + ~ScheduleDAGMI() override; - /// \brief Return true if register pressure tracking is enabled. - bool isTrackingPressure() const { return ShouldTrackPressure; } + /// Return true if this DAG supports VReg liveness and RegPressure. + virtual bool hasVRegLiveness() const { return false; } /// Add a postprocessing step to the DAG builder. /// Mutations are applied in the order that they are added after normal DAG /// building and before MachineSchedStrategy initialization. /// /// ScheduleDAGMI takes ownership of the Mutation object. - void addMutation(ScheduleDAGMutation *Mutation) { - Mutations.push_back(Mutation); + void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) { + Mutations.push_back(std::move(Mutation)); } /// \brief True if an edge can be added from PredSU to SuccSU without creating @@ -374,16 +294,106 @@ public: void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, - unsigned regioninstrs) LLVM_OVERRIDE; + unsigned regioninstrs) override; /// Implement ScheduleDAGInstrs interface for scheduling a sequence of /// reorderable instructions. - virtual void schedule(); + void schedule() override; /// Change the position of an instruction within the basic block and update /// live ranges and region boundary iterators. void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); + const SUnit *getNextClusterPred() const { return NextClusterPred; } + + const SUnit *getNextClusterSucc() const { return NextClusterSucc; } + + void viewGraph(const Twine &Name, const Twine &Title) override; + void viewGraph() override; + +protected: + // Top-Level entry points for the schedule() driver... + + /// Apply each ScheduleDAGMutation step in order. This allows different + /// instances of ScheduleDAGMI to perform custom DAG postprocessing. + void postprocessDAG(); + + /// Release ExitSU predecessors and setup scheduler queues. + void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots); + + /// Update scheduler DAG and queues after scheduling an instruction. + void updateQueues(SUnit *SU, bool IsTopNode); + + /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues. + void placeDebugValues(); + + /// \brief dump the scheduled Sequence. + void dumpSchedule() const; + + // Lesser helpers... + bool checkSchedLimit(); + + void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots, + SmallVectorImpl<SUnit*> &BotRoots); + + void releaseSucc(SUnit *SU, SDep *SuccEdge); + void releaseSuccessors(SUnit *SU); + void releasePred(SUnit *SU, SDep *PredEdge); + void releasePredecessors(SUnit *SU); +}; + +/// ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules +/// machine instructions while updating LiveIntervals and tracking regpressure. +class ScheduleDAGMILive : public ScheduleDAGMI { +protected: + RegisterClassInfo *RegClassInfo; + + /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees + /// will be empty. + SchedDFSResult *DFSResult; + BitVector ScheduledTrees; + + MachineBasicBlock::iterator LiveRegionEnd; + + // Map each SU to its summary of pressure changes. This array is updated for + // liveness during bottom-up scheduling. Top-down scheduling may proceed but + // has no affect on the pressure diffs. + PressureDiffs SUPressureDiffs; + + /// Register pressure in this region computed by initRegPressure. + bool ShouldTrackPressure; + IntervalPressure RegPressure; + RegPressureTracker RPTracker; + + /// List of pressure sets that exceed the target's pressure limit before + /// scheduling, listed in increasing set ID order. Each pressure set is paired + /// with its max pressure in the currently scheduled regions. + std::vector<PressureChange> RegionCriticalPSets; + + /// The top of the unscheduled zone. + IntervalPressure TopPressure; + RegPressureTracker TopRPTracker; + + /// The bottom of the unscheduled zone. + IntervalPressure BotPressure; + RegPressureTracker BotRPTracker; + +public: + ScheduleDAGMILive(MachineSchedContext *C, + std::unique_ptr<MachineSchedStrategy> S) + : ScheduleDAGMI(C, std::move(S), /*IsPostRA=*/false), + RegClassInfo(C->RegClassInfo), DFSResult(nullptr), + ShouldTrackPressure(false), RPTracker(RegPressure), + TopRPTracker(TopPressure), BotRPTracker(BotPressure) {} + + virtual ~ScheduleDAGMILive(); + + /// Return true if this DAG supports VReg liveness and RegPressure. + bool hasVRegLiveness() const override { return true; } + + /// \brief Return true if register pressure tracking is enabled. + bool isTrackingPressure() const { return ShouldTrackPressure; } + /// Get current register pressure for the top scheduled instructions. const IntervalPressure &getTopPressure() const { return TopPressure; } const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; } @@ -403,10 +413,6 @@ public: return SUPressureDiffs[SU->NodeNum]; } - const SUnit *getNextClusterPred() const { return NextClusterPred; } - - const SUnit *getNextClusterSucc() const { return NextClusterSucc; } - /// Compute a DFSResult after DAG building is complete, and before any /// queue comparisons. void computeDFSResult(); @@ -416,12 +422,21 @@ public: BitVector &getScheduledTrees() { return ScheduledTrees; } + /// Implement the ScheduleDAGInstrs interface for handling the next scheduling + /// region. This covers all instructions in a block, while schedule() may only + /// cover a subset. + void enterRegion(MachineBasicBlock *bb, + MachineBasicBlock::iterator begin, + MachineBasicBlock::iterator end, + unsigned regioninstrs) override; + + /// Implement ScheduleDAGInstrs interface for scheduling a sequence of + /// reorderable instructions. + void schedule() override; + /// Compute the cyclic critical path through the DAG. unsigned computeCyclicCriticalPath(); - void viewGraph(const Twine &Name, const Twine &Title) LLVM_OVERRIDE; - void viewGraph() LLVM_OVERRIDE; - protected: // Top-Level entry points for the schedule() driver... @@ -431,25 +446,9 @@ protected: /// bottom of the DAG region without covereing any unscheduled instruction. void buildDAGWithRegPressure(); - /// Apply each ScheduleDAGMutation step in order. This allows different - /// instances of ScheduleDAGMI to perform custom DAG postprocessing. - void postprocessDAG(); - - /// Release ExitSU predecessors and setup scheduler queues. - void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots); - /// Move an instruction and update register pressure. void scheduleMI(SUnit *SU, bool IsTopNode); - /// Update scheduler DAG and queues after scheduling an instruction. - void updateQueues(SUnit *SU, bool IsTopNode); - - /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues. - void placeDebugValues(); - - /// \brief dump the scheduled Sequence. - void dumpSchedule() const; - // Lesser helpers... void initRegPressure(); @@ -458,16 +457,495 @@ protected: void updateScheduledPressure(const SUnit *SU, const std::vector<unsigned> &NewMaxPressure); +}; - bool checkSchedLimit(); +//===----------------------------------------------------------------------===// +/// +/// Helpers for implementing custom MachineSchedStrategy classes. These take +/// care of the book-keeping associated with list scheduling heuristics. +/// +//===----------------------------------------------------------------------===// - void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots, - SmallVectorImpl<SUnit*> &BotRoots); +/// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience +/// methods for pushing and removing nodes. ReadyQueue's are uniquely identified +/// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in. +/// +/// This is a convenience class that may be used by implementations of +/// MachineSchedStrategy. +class ReadyQueue { + unsigned ID; + std::string Name; + std::vector<SUnit*> Queue; - void releaseSucc(SUnit *SU, SDep *SuccEdge); - void releaseSuccessors(SUnit *SU); - void releasePred(SUnit *SU, SDep *PredEdge); - void releasePredecessors(SUnit *SU); +public: + ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {} + + unsigned getID() const { return ID; } + + StringRef getName() const { return Name; } + + // SU is in this queue if it's NodeQueueID is a superset of this ID. + bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); } + + bool empty() const { return Queue.empty(); } + + void clear() { Queue.clear(); } + + unsigned size() const { return Queue.size(); } + + typedef std::vector<SUnit*>::iterator iterator; + + iterator begin() { return Queue.begin(); } + + iterator end() { return Queue.end(); } + + ArrayRef<SUnit*> elements() { return Queue; } + + iterator find(SUnit *SU) { + return std::find(Queue.begin(), Queue.end(), SU); + } + + void push(SUnit *SU) { + Queue.push_back(SU); + SU->NodeQueueId |= ID; + } + + iterator remove(iterator I) { + (*I)->NodeQueueId &= ~ID; + *I = Queue.back(); + unsigned idx = I - Queue.begin(); + Queue.pop_back(); + return Queue.begin() + idx; + } + + void dump(); +}; + +/// Summarize the unscheduled region. +struct SchedRemainder { + // Critical path through the DAG in expected latency. + unsigned CriticalPath; + unsigned CyclicCritPath; + + // Scaled count of micro-ops left to schedule. + unsigned RemIssueCount; + + bool IsAcyclicLatencyLimited; + + // Unscheduled resources + SmallVector<unsigned, 16> RemainingCounts; + + void reset() { + CriticalPath = 0; + CyclicCritPath = 0; + RemIssueCount = 0; + IsAcyclicLatencyLimited = false; + RemainingCounts.clear(); + } + + SchedRemainder() { reset(); } + + void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel); +}; + +/// Each Scheduling boundary is associated with ready queues. It tracks the +/// current cycle in the direction of movement, and maintains the state +/// of "hazards" and other interlocks at the current cycle. +class SchedBoundary { +public: + /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both) + enum { + TopQID = 1, + BotQID = 2, + LogMaxQID = 2 + }; + + ScheduleDAGMI *DAG; + const TargetSchedModel *SchedModel; + SchedRemainder *Rem; + + ReadyQueue Available; + ReadyQueue Pending; + + ScheduleHazardRecognizer *HazardRec; + +private: + /// True if the pending Q should be checked/updated before scheduling another + /// instruction. + bool CheckPending; + + // For heuristics, keep a list of the nodes that immediately depend on the + // most recently scheduled node. + SmallPtrSet<const SUnit*, 8> NextSUs; + + /// Number of cycles it takes to issue the instructions scheduled in this + /// zone. It is defined as: scheduled-micro-ops / issue-width + stalls. + /// See getStalls(). + unsigned CurrCycle; + + /// Micro-ops issued in the current cycle + unsigned CurrMOps; + + /// MinReadyCycle - Cycle of the soonest available instruction. + unsigned MinReadyCycle; + + // The expected latency of the critical path in this scheduled zone. + unsigned ExpectedLatency; + + // The latency of dependence chains leading into this zone. + // For each node scheduled bottom-up: DLat = max DLat, N.Depth. + // For each cycle scheduled: DLat -= 1. + unsigned DependentLatency; + + /// Count the scheduled (issued) micro-ops that can be retired by + /// time=CurrCycle assuming the first scheduled instr is retired at time=0. + unsigned RetiredMOps; + + // Count scheduled resources that have been executed. Resources are + // considered executed if they become ready in the time that it takes to + // saturate any resource including the one in question. Counts are scaled + // for direct comparison with other resources. Counts can be compared with + // MOps * getMicroOpFactor and Latency * getLatencyFactor. + SmallVector<unsigned, 16> ExecutedResCounts; + + /// Cache the max count for a single resource. + unsigned MaxExecutedResCount; + + // Cache the critical resources ID in this scheduled zone. + unsigned ZoneCritResIdx; + + // Is the scheduled region resource limited vs. latency limited. + bool IsResourceLimited; + + // Record the highest cycle at which each resource has been reserved by a + // scheduled instruction. + SmallVector<unsigned, 16> ReservedCycles; + +#ifndef NDEBUG + // Remember the greatest possible stall as an upper bound on the number of + // times we should retry the pending queue because of a hazard. + unsigned MaxObservedStall; +#endif + +public: + /// Pending queues extend the ready queues with the same ID and the + /// PendingFlag set. + SchedBoundary(unsigned ID, const Twine &Name): + DAG(nullptr), SchedModel(nullptr), Rem(nullptr), Available(ID, Name+".A"), + Pending(ID << LogMaxQID, Name+".P"), + HazardRec(nullptr) { + reset(); + } + + ~SchedBoundary(); + + void reset(); + + void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel, + SchedRemainder *rem); + + bool isTop() const { + return Available.getID() == TopQID; + } + + /// Number of cycles to issue the instructions scheduled in this zone. + unsigned getCurrCycle() const { return CurrCycle; } + + /// Micro-ops issued in the current cycle + unsigned getCurrMOps() const { return CurrMOps; } + + /// Return true if the given SU is used by the most recently scheduled + /// instruction. + bool isNextSU(const SUnit *SU) const { return NextSUs.count(SU); } + + // The latency of dependence chains leading into this zone. + unsigned getDependentLatency() const { return DependentLatency; } + + /// Get the number of latency cycles "covered" by the scheduled + /// instructions. This is the larger of the critical path within the zone + /// and the number of cycles required to issue the instructions. + unsigned getScheduledLatency() const { + return std::max(ExpectedLatency, CurrCycle); + } + + unsigned getUnscheduledLatency(SUnit *SU) const { + return isTop() ? SU->getHeight() : SU->getDepth(); + } + + unsigned getResourceCount(unsigned ResIdx) const { + return ExecutedResCounts[ResIdx]; + } + + /// Get the scaled count of scheduled micro-ops and resources, including + /// executed resources. + unsigned getCriticalCount() const { + if (!ZoneCritResIdx) + return RetiredMOps * SchedModel->getMicroOpFactor(); + return getResourceCount(ZoneCritResIdx); + } + + /// Get a scaled count for the minimum execution time of the scheduled + /// micro-ops that are ready to execute by getExecutedCount. Notice the + /// feedback loop. + unsigned getExecutedCount() const { + return std::max(CurrCycle * SchedModel->getLatencyFactor(), + MaxExecutedResCount); + } + + unsigned getZoneCritResIdx() const { return ZoneCritResIdx; } + + // Is the scheduled region resource limited vs. latency limited. + bool isResourceLimited() const { return IsResourceLimited; } + + /// Get the difference between the given SUnit's ready time and the current + /// cycle. + unsigned getLatencyStallCycles(SUnit *SU); + + unsigned getNextResourceCycle(unsigned PIdx, unsigned Cycles); + + bool checkHazard(SUnit *SU); + + unsigned findMaxLatency(ArrayRef<SUnit*> ReadySUs); + + unsigned getOtherResourceCount(unsigned &OtherCritIdx); + + void releaseNode(SUnit *SU, unsigned ReadyCycle); + + void releaseTopNode(SUnit *SU); + + void releaseBottomNode(SUnit *SU); + + void bumpCycle(unsigned NextCycle); + + void incExecutedResources(unsigned PIdx, unsigned Count); + + unsigned countResource(unsigned PIdx, unsigned Cycles, unsigned ReadyCycle); + + void bumpNode(SUnit *SU); + + void releasePending(); + + void removeReady(SUnit *SU); + + /// Call this before applying any other heuristics to the Available queue. + /// Updates the Available/Pending Q's if necessary and returns the single + /// available instruction, or NULL if there are multiple candidates. + SUnit *pickOnlyChoice(); + +#ifndef NDEBUG + void dumpScheduledState(); +#endif +}; + +/// Base class for GenericScheduler. This class maintains information about +/// scheduling candidates based on TargetSchedModel making it easy to implement +/// heuristics for either preRA or postRA scheduling. +class GenericSchedulerBase : public MachineSchedStrategy { +public: + /// Represent the type of SchedCandidate found within a single queue. + /// pickNodeBidirectional depends on these listed by decreasing priority. + enum CandReason { + NoCand, PhysRegCopy, RegExcess, RegCritical, Stall, Cluster, Weak, RegMax, + ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce, + TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder}; + +#ifndef NDEBUG + static const char *getReasonStr(GenericSchedulerBase::CandReason Reason); +#endif + + /// Policy for scheduling the next instruction in the candidate's zone. + struct CandPolicy { + bool ReduceLatency; + unsigned ReduceResIdx; + unsigned DemandResIdx; + + CandPolicy(): ReduceLatency(false), ReduceResIdx(0), DemandResIdx(0) {} + }; + + /// Status of an instruction's critical resource consumption. + struct SchedResourceDelta { + // Count critical resources in the scheduled region required by SU. + unsigned CritResources; + + // Count critical resources from another region consumed by SU. + unsigned DemandedResources; + + SchedResourceDelta(): CritResources(0), DemandedResources(0) {} + + bool operator==(const SchedResourceDelta &RHS) const { + return CritResources == RHS.CritResources + && DemandedResources == RHS.DemandedResources; + } + bool operator!=(const SchedResourceDelta &RHS) const { + return !operator==(RHS); + } + }; + + /// Store the state used by GenericScheduler heuristics, required for the + /// lifetime of one invocation of pickNode(). + struct SchedCandidate { + CandPolicy Policy; + + // The best SUnit candidate. + SUnit *SU; + + // The reason for this candidate. + CandReason Reason; + + // Set of reasons that apply to multiple candidates. + uint32_t RepeatReasonSet; + + // Register pressure values for the best candidate. + RegPressureDelta RPDelta; + + // Critical resource consumption of the best candidate. + SchedResourceDelta ResDelta; + + SchedCandidate(const CandPolicy &policy) + : Policy(policy), SU(nullptr), Reason(NoCand), RepeatReasonSet(0) {} + + bool isValid() const { return SU; } + + // Copy the status of another candidate without changing policy. + void setBest(SchedCandidate &Best) { + assert(Best.Reason != NoCand && "uninitialized Sched candidate"); + SU = Best.SU; + Reason = Best.Reason; + RPDelta = Best.RPDelta; + ResDelta = Best.ResDelta; + } + + bool isRepeat(CandReason R) { return RepeatReasonSet & (1 << R); } + void setRepeat(CandReason R) { RepeatReasonSet |= (1 << R); } + + void initResourceDelta(const ScheduleDAGMI *DAG, + const TargetSchedModel *SchedModel); + }; + +protected: + const MachineSchedContext *Context; + const TargetSchedModel *SchedModel; + const TargetRegisterInfo *TRI; + + SchedRemainder Rem; +protected: + GenericSchedulerBase(const MachineSchedContext *C): + Context(C), SchedModel(nullptr), TRI(nullptr) {} + + void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone, + SchedBoundary *OtherZone); + +#ifndef NDEBUG + void traceCandidate(const SchedCandidate &Cand); +#endif +}; + +/// GenericScheduler shrinks the unscheduled zone using heuristics to balance +/// the schedule. +class GenericScheduler : public GenericSchedulerBase { + ScheduleDAGMILive *DAG; + + // State of the top and bottom scheduled instruction boundaries. + SchedBoundary Top; + SchedBoundary Bot; + + MachineSchedPolicy RegionPolicy; +public: + GenericScheduler(const MachineSchedContext *C): + GenericSchedulerBase(C), DAG(nullptr), Top(SchedBoundary::TopQID, "TopQ"), + Bot(SchedBoundary::BotQID, "BotQ") {} + + void initPolicy(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned NumRegionInstrs) override; + + bool shouldTrackPressure() const override { + return RegionPolicy.ShouldTrackPressure; + } + + void initialize(ScheduleDAGMI *dag) override; + + SUnit *pickNode(bool &IsTopNode) override; + + void schedNode(SUnit *SU, bool IsTopNode) override; + + void releaseTopNode(SUnit *SU) override { + Top.releaseTopNode(SU); + } + + void releaseBottomNode(SUnit *SU) override { + Bot.releaseBottomNode(SU); + } + + void registerRoots() override; + +protected: + void checkAcyclicLatency(); + + void tryCandidate(SchedCandidate &Cand, + SchedCandidate &TryCand, + SchedBoundary &Zone, + const RegPressureTracker &RPTracker, + RegPressureTracker &TempTracker); + + SUnit *pickNodeBidirectional(bool &IsTopNode); + + void pickNodeFromQueue(SchedBoundary &Zone, + const RegPressureTracker &RPTracker, + SchedCandidate &Candidate); + + void reschedulePhysRegCopies(SUnit *SU, bool isTop); +}; + +/// PostGenericScheduler - Interface to the scheduling algorithm used by +/// ScheduleDAGMI. +/// +/// Callbacks from ScheduleDAGMI: +/// initPolicy -> initialize(DAG) -> registerRoots -> pickNode ... +class PostGenericScheduler : public GenericSchedulerBase { + ScheduleDAGMI *DAG; + SchedBoundary Top; + SmallVector<SUnit*, 8> BotRoots; +public: + PostGenericScheduler(const MachineSchedContext *C): + GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {} + + virtual ~PostGenericScheduler() {} + + void initPolicy(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + unsigned NumRegionInstrs) override { + /* no configurable policy */ + }; + + /// PostRA scheduling does not track pressure. + bool shouldTrackPressure() const override { return false; } + + void initialize(ScheduleDAGMI *Dag) override; + + void registerRoots() override; + + SUnit *pickNode(bool &IsTopNode) override; + + void scheduleTree(unsigned SubtreeID) override { + llvm_unreachable("PostRA scheduler does not support subtree analysis."); + } + + void schedNode(SUnit *SU, bool IsTopNode) override; + + void releaseTopNode(SUnit *SU) override { + Top.releaseTopNode(SU); + } + + // Only called for roots. + void releaseBottomNode(SUnit *SU) override { + BotRoots.push_back(SU); + } + +protected: + void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand); + + void pickNodeFromQueue(SchedCandidate &Cand); }; } // namespace llvm diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h index 9794707e3544..323b694f3933 100644 --- a/include/llvm/CodeGen/MachineTraceMetrics.h +++ b/include/llvm/CodeGen/MachineTraceMetrics.h @@ -77,10 +77,10 @@ public: class Trace; static char ID; MachineTraceMetrics(); - void getAnalysisUsage(AnalysisUsage&) const; - bool runOnMachineFunction(MachineFunction&); - void releaseMemory(); - void verifyAnalysis() const; + void getAnalysisUsage(AnalysisUsage&) const override; + bool runOnMachineFunction(MachineFunction&) override; + void releaseMemory() override; + void verifyAnalysis() const override; friend class Ensemble; friend class Trace; @@ -154,7 +154,7 @@ public: unsigned InstrHeight; TraceBlockInfo() : - Pred(0), Succ(0), + Pred(nullptr), Succ(nullptr), InstrDepth(~0u), InstrHeight(~0u), HasValidInstrDepths(false), HasValidInstrHeights(false) {} diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h new file mode 100644 index 000000000000..ad215ec09843 --- /dev/null +++ b/include/llvm/CodeGen/MachineValueType.h @@ -0,0 +1,579 @@ +//===- CodeGen/MachineValueType.h - Machine-Level types ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the set of machine-level target independent types which +// legal values in the code generator use. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEVALUETYPE_H +#define LLVM_CODEGEN_MACHINEVALUETYPE_H + +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" + +namespace llvm { + + class Type; + + /// MVT - Machine Value Type. Every type that is supported natively by some + /// processor targeted by LLVM occurs here. This means that any legal value + /// type can be represented by an MVT. + class MVT { + public: + enum SimpleValueType { + // INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are + // considered extended value types. + INVALID_SIMPLE_VALUE_TYPE = -1, + + // If you change this numbering, you must change the values in + // ValueTypes.td as well! + Other = 0, // This is a non-standard value + i1 = 1, // This is a 1 bit integer value + i8 = 2, // This is an 8 bit integer value + i16 = 3, // This is a 16 bit integer value + i32 = 4, // This is a 32 bit integer value + i64 = 5, // This is a 64 bit integer value + i128 = 6, // This is a 128 bit integer value + + FIRST_INTEGER_VALUETYPE = i1, + LAST_INTEGER_VALUETYPE = i128, + + f16 = 7, // This is a 16 bit floating point value + f32 = 8, // This is a 32 bit floating point value + f64 = 9, // This is a 64 bit floating point value + f80 = 10, // This is a 80 bit floating point value + f128 = 11, // This is a 128 bit floating point value + ppcf128 = 12, // This is a PPC 128-bit floating point value + + FIRST_FP_VALUETYPE = f16, + LAST_FP_VALUETYPE = ppcf128, + + v2i1 = 13, // 2 x i1 + v4i1 = 14, // 4 x i1 + v8i1 = 15, // 8 x i1 + v16i1 = 16, // 16 x i1 + v32i1 = 17, // 32 x i1 + v64i1 = 18, // 64 x i1 + + v1i8 = 19, // 1 x i8 + v2i8 = 20, // 2 x i8 + v4i8 = 21, // 4 x i8 + v8i8 = 22, // 8 x i8 + v16i8 = 23, // 16 x i8 + v32i8 = 24, // 32 x i8 + v64i8 = 25, // 64 x i8 + v1i16 = 26, // 1 x i16 + v2i16 = 27, // 2 x i16 + v4i16 = 28, // 4 x i16 + v8i16 = 29, // 8 x i16 + v16i16 = 30, // 16 x i16 + v32i16 = 31, // 32 x i16 + v1i32 = 32, // 1 x i32 + v2i32 = 33, // 2 x i32 + v4i32 = 34, // 4 x i32 + v8i32 = 35, // 8 x i32 + v16i32 = 36, // 16 x i32 + v1i64 = 37, // 1 x i64 + v2i64 = 38, // 2 x i64 + v4i64 = 39, // 4 x i64 + v8i64 = 40, // 8 x i64 + v16i64 = 41, // 16 x i64 + + FIRST_INTEGER_VECTOR_VALUETYPE = v2i1, + LAST_INTEGER_VECTOR_VALUETYPE = v16i64, + + v2f16 = 42, // 2 x f16 + v4f16 = 43, // 4 x f16 + v8f16 = 44, // 8 x f16 + v1f32 = 45, // 1 x f32 + v2f32 = 46, // 2 x f32 + v4f32 = 47, // 4 x f32 + v8f32 = 48, // 8 x f32 + v16f32 = 49, // 16 x f32 + v1f64 = 50, // 1 x f64 + v2f64 = 51, // 2 x f64 + v4f64 = 52, // 4 x f64 + v8f64 = 53, // 8 x f64 + + FIRST_FP_VECTOR_VALUETYPE = v2f16, + LAST_FP_VECTOR_VALUETYPE = v8f64, + + FIRST_VECTOR_VALUETYPE = v2i1, + LAST_VECTOR_VALUETYPE = v8f64, + + x86mmx = 54, // This is an X86 MMX value + + Glue = 55, // This glues nodes together during pre-RA sched + + isVoid = 56, // This has no value + + Untyped = 57, // This value takes a register, but has + // unspecified type. The register class + // will be determined by the opcode. + + LAST_VALUETYPE = 58, // This always remains at the end of the list. + + // This is the current maximum for LAST_VALUETYPE. + // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors + // This value must be a multiple of 32. + MAX_ALLOWED_VALUETYPE = 64, + + // Metadata - This is MDNode or MDString. + Metadata = 250, + + // iPTRAny - An int value the size of the pointer of the current + // target to any address space. This must only be used internal to + // tblgen. Other than for overloading, we treat iPTRAny the same as iPTR. + iPTRAny = 251, + + // vAny - A vector with any length and element size. This is used + // for intrinsics that have overloadings based on vector types. + // This is only for tblgen's consumption! + vAny = 252, + + // fAny - Any floating-point or vector floating-point value. This is used + // for intrinsics that have overloadings based on floating-point types. + // This is only for tblgen's consumption! + fAny = 253, + + // iAny - An integer or vector integer value of any bit width. This is + // used for intrinsics that have overloadings based on integer bit widths. + // This is only for tblgen's consumption! + iAny = 254, + + // iPTR - An int value the size of the pointer of the current + // target. This should only be used internal to tblgen! + iPTR = 255 + }; + + SimpleValueType SimpleTy; + + MVT() : SimpleTy((SimpleValueType)(INVALID_SIMPLE_VALUE_TYPE)) {} + MVT(SimpleValueType SVT) : SimpleTy(SVT) { } + + bool operator>(const MVT& S) const { return SimpleTy > S.SimpleTy; } + bool operator<(const MVT& S) const { return SimpleTy < S.SimpleTy; } + bool operator==(const MVT& S) const { return SimpleTy == S.SimpleTy; } + bool operator!=(const MVT& S) const { return SimpleTy != S.SimpleTy; } + bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } + bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } + + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. + bool isFloatingPoint() const { + return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE && + SimpleTy <= MVT::LAST_FP_VALUETYPE) || + (SimpleTy >= MVT::FIRST_FP_VECTOR_VALUETYPE && + SimpleTy <= MVT::LAST_FP_VECTOR_VALUETYPE)); + } + + /// isInteger - Return true if this is an integer, or a vector integer type. + bool isInteger() const { + return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && + SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) || + (SimpleTy >= MVT::FIRST_INTEGER_VECTOR_VALUETYPE && + SimpleTy <= MVT::LAST_INTEGER_VECTOR_VALUETYPE)); + } + + /// isVector - Return true if this is a vector value type. + bool isVector() const { + return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE && + SimpleTy <= MVT::LAST_VECTOR_VALUETYPE); + } + + /// is16BitVector - Return true if this is a 16-bit vector type. + bool is16BitVector() const { + return (SimpleTy == MVT::v2i8 || SimpleTy == MVT::v1i16 || + SimpleTy == MVT::v16i1); + } + + /// is32BitVector - Return true if this is a 32-bit vector type. + bool is32BitVector() const { + return (SimpleTy == MVT::v4i8 || SimpleTy == MVT::v2i16 || + SimpleTy == MVT::v1i32); + } + + /// is64BitVector - Return true if this is a 64-bit vector type. + bool is64BitVector() const { + return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 || + SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 || + SimpleTy == MVT::v1f64 || SimpleTy == MVT::v2f32); + } + + /// is128BitVector - Return true if this is a 128-bit vector type. + bool is128BitVector() const { + return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 || + SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 || + SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64); + } + + /// is256BitVector - Return true if this is a 256-bit vector type. + bool is256BitVector() const { + return (SimpleTy == MVT::v8f32 || SimpleTy == MVT::v4f64 || + SimpleTy == MVT::v32i8 || SimpleTy == MVT::v16i16 || + SimpleTy == MVT::v8i32 || SimpleTy == MVT::v4i64); + } + + /// is512BitVector - Return true if this is a 512-bit vector type. + bool is512BitVector() const { + return (SimpleTy == MVT::v8f64 || SimpleTy == MVT::v16f32 || + SimpleTy == MVT::v64i8 || SimpleTy == MVT::v32i16 || + SimpleTy == MVT::v8i64 || SimpleTy == MVT::v16i32); + } + + /// is1024BitVector - Return true if this is a 1024-bit vector type. + bool is1024BitVector() const { + return (SimpleTy == MVT::v16i64); + } + + /// isOverloaded - Return true if this is an overloaded type for TableGen. + bool isOverloaded() const { + return (SimpleTy==MVT::iAny || SimpleTy==MVT::fAny || + SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny); + } + + /// isPow2VectorType - Returns true if the given vector is a power of 2. + bool isPow2VectorType() const { + unsigned NElts = getVectorNumElements(); + return !(NElts & (NElts - 1)); + } + + /// getPow2VectorType - Widens the length of the given vector MVT up to + /// the nearest power of 2 and returns that type. + MVT getPow2VectorType() const { + if (isPow2VectorType()) + return *this; + + unsigned NElts = getVectorNumElements(); + unsigned Pow2NElts = 1 << Log2_32_Ceil(NElts); + return MVT::getVectorVT(getVectorElementType(), Pow2NElts); + } + + /// getScalarType - If this is a vector type, return the element type, + /// otherwise return this. + MVT getScalarType() const { + return isVector() ? getVectorElementType() : *this; + } + + MVT getVectorElementType() const { + switch (SimpleTy) { + default: + llvm_unreachable("Not a vector MVT!"); + case v2i1 : + case v4i1 : + case v8i1 : + case v16i1 : + case v32i1 : + case v64i1: return i1; + case v1i8 : + case v2i8 : + case v4i8 : + case v8i8 : + case v16i8: + case v32i8: + case v64i8: return i8; + case v1i16: + case v2i16: + case v4i16: + case v8i16: + case v16i16: + case v32i16: return i16; + case v1i32: + case v2i32: + case v4i32: + case v8i32: + case v16i32: return i32; + case v1i64: + case v2i64: + case v4i64: + case v8i64: + case v16i64: return i64; + case v2f16: + case v4f16: + case v8f16: return f16; + case v1f32: + case v2f32: + case v4f32: + case v8f32: + case v16f32: return f32; + case v1f64: + case v2f64: + case v4f64: + case v8f64: return f64; + } + } + + unsigned getVectorNumElements() const { + switch (SimpleTy) { + default: + llvm_unreachable("Not a vector MVT!"); + case v32i1: + case v32i8: + case v32i16: return 32; + case v64i1: + case v64i8: return 64; + case v16i1: + case v16i8: + case v16i16: + case v16i32: + case v16i64: + case v16f32: return 16; + case v8i1 : + case v8i8 : + case v8i16: + case v8i32: + case v8i64: + case v8f16: + case v8f32: + case v8f64: return 8; + case v4i1: + case v4i8: + case v4i16: + case v4i32: + case v4i64: + case v4f16: + case v4f32: + case v4f64: return 4; + case v2i1: + case v2i8: + case v2i16: + case v2i32: + case v2i64: + case v2f16: + case v2f32: + case v2f64: return 2; + case v1i8: + case v1i16: + case v1i32: + case v1i64: + case v1f32: + case v1f64: return 1; + } + } + + unsigned getSizeInBits() const { + switch (SimpleTy) { + default: + llvm_unreachable("getSizeInBits called on extended MVT."); + case Other: + llvm_unreachable("Value type is non-standard value, Other."); + case iPTR: + llvm_unreachable("Value type size is target-dependent. Ask TLI."); + case iPTRAny: + case iAny: + case fAny: + case vAny: + llvm_unreachable("Value type is overloaded."); + case Metadata: + llvm_unreachable("Value type is metadata."); + case i1 : return 1; + case v2i1: return 2; + case v4i1: return 4; + case i8 : + case v1i8: + case v8i1: return 8; + case i16 : + case f16: + case v16i1: + case v2i8: + case v1i16: return 16; + case f32 : + case i32 : + case v32i1: + case v4i8: + case v2i16: + case v2f16: + case v1f32: + case v1i32: return 32; + case x86mmx: + case f64 : + case i64 : + case v64i1: + case v8i8: + case v4i16: + case v2i32: + case v1i64: + case v4f16: + case v2f32: + case v1f64: return 64; + case f80 : return 80; + case f128: + case ppcf128: + case i128: + case v16i8: + case v8i16: + case v4i32: + case v2i64: + case v8f16: + case v4f32: + case v2f64: return 128; + case v32i8: + case v16i16: + case v8i32: + case v4i64: + case v8f32: + case v4f64: return 256; + case v64i8: + case v32i16: + case v16i32: + case v8i64: + case v16f32: + case v8f64: return 512; + case v16i64:return 1024; + } + } + + unsigned getScalarSizeInBits() const { + return getScalarType().getSizeInBits(); + } + + /// getStoreSize - Return the number of bytes overwritten by a store + /// of the specified value type. + unsigned getStoreSize() const { + return (getSizeInBits() + 7) / 8; + } + + /// getStoreSizeInBits - Return the number of bits overwritten by a store + /// of the specified value type. + unsigned getStoreSizeInBits() const { + return getStoreSize() * 8; + } + + /// Return true if this has more bits than VT. + bool bitsGT(MVT VT) const { + return getSizeInBits() > VT.getSizeInBits(); + } + + /// Return true if this has no less bits than VT. + bool bitsGE(MVT VT) const { + return getSizeInBits() >= VT.getSizeInBits(); + } + + /// Return true if this has less bits than VT. + bool bitsLT(MVT VT) const { + return getSizeInBits() < VT.getSizeInBits(); + } + + /// Return true if this has no more bits than VT. + bool bitsLE(MVT VT) const { + return getSizeInBits() <= VT.getSizeInBits(); + } + + + static MVT getFloatingPointVT(unsigned BitWidth) { + switch (BitWidth) { + default: + llvm_unreachable("Bad bit width!"); + case 16: + return MVT::f16; + case 32: + return MVT::f32; + case 64: + return MVT::f64; + case 80: + return MVT::f80; + case 128: + return MVT::f128; + } + } + + static MVT getIntegerVT(unsigned BitWidth) { + switch (BitWidth) { + default: + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + case 1: + return MVT::i1; + case 8: + return MVT::i8; + case 16: + return MVT::i16; + case 32: + return MVT::i32; + case 64: + return MVT::i64; + case 128: + return MVT::i128; + } + } + + static MVT getVectorVT(MVT VT, unsigned NumElements) { + switch (VT.SimpleTy) { + default: + break; + case MVT::i1: + if (NumElements == 2) return MVT::v2i1; + if (NumElements == 4) return MVT::v4i1; + if (NumElements == 8) return MVT::v8i1; + if (NumElements == 16) return MVT::v16i1; + if (NumElements == 32) return MVT::v32i1; + if (NumElements == 64) return MVT::v64i1; + break; + case MVT::i8: + if (NumElements == 1) return MVT::v1i8; + if (NumElements == 2) return MVT::v2i8; + if (NumElements == 4) return MVT::v4i8; + if (NumElements == 8) return MVT::v8i8; + if (NumElements == 16) return MVT::v16i8; + if (NumElements == 32) return MVT::v32i8; + if (NumElements == 64) return MVT::v64i8; + break; + case MVT::i16: + if (NumElements == 1) return MVT::v1i16; + if (NumElements == 2) return MVT::v2i16; + if (NumElements == 4) return MVT::v4i16; + if (NumElements == 8) return MVT::v8i16; + if (NumElements == 16) return MVT::v16i16; + if (NumElements == 32) return MVT::v32i16; + break; + case MVT::i32: + if (NumElements == 1) return MVT::v1i32; + if (NumElements == 2) return MVT::v2i32; + if (NumElements == 4) return MVT::v4i32; + if (NumElements == 8) return MVT::v8i32; + if (NumElements == 16) return MVT::v16i32; + break; + case MVT::i64: + if (NumElements == 1) return MVT::v1i64; + if (NumElements == 2) return MVT::v2i64; + if (NumElements == 4) return MVT::v4i64; + if (NumElements == 8) return MVT::v8i64; + if (NumElements == 16) return MVT::v16i64; + break; + case MVT::f16: + if (NumElements == 2) return MVT::v2f16; + if (NumElements == 4) return MVT::v4f16; + if (NumElements == 8) return MVT::v8f16; + break; + case MVT::f32: + if (NumElements == 1) return MVT::v1f32; + if (NumElements == 2) return MVT::v2f32; + if (NumElements == 4) return MVT::v4f32; + if (NumElements == 8) return MVT::v8f32; + if (NumElements == 16) return MVT::v16f32; + break; + case MVT::f64: + if (NumElements == 1) return MVT::v1f64; + if (NumElements == 2) return MVT::v2f64; + if (NumElements == 4) return MVT::v4f64; + if (NumElements == 8) return MVT::v8f64; + break; + } + return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); + } + + /// Return the value type corresponding to the specified type. This returns + /// all pointers as iPTR. If HandleUnknown is true, unknown types are + /// returned as Other, otherwise they are invalid. + static MVT getVT(Type *Ty, bool HandleUnknown = false); + + }; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/PBQP/CostAllocator.h b/include/llvm/CodeGen/PBQP/CostAllocator.h new file mode 100644 index 000000000000..ff62c0959344 --- /dev/null +++ b/include/llvm/CodeGen/PBQP/CostAllocator.h @@ -0,0 +1,147 @@ +//===---------- CostAllocator.h - PBQP Cost Allocator -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines classes conforming to the PBQP cost value manager concept. +// +// Cost value managers are memory managers for PBQP cost values (vectors and +// matrices). Since PBQP graphs can grow very large (E.g. hundreds of thousands +// of edges on the largest function in SPEC2006). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_COSTALLOCATOR_H +#define LLVM_COSTALLOCATOR_H + +#include <set> +#include <type_traits> + +namespace PBQP { + +template <typename CostT, + typename CostKeyTComparator> +class CostPool { +public: + + class PoolEntry { + public: + template <typename CostKeyT> + PoolEntry(CostPool &pool, CostKeyT cost) + : pool(pool), cost(std::move(cost)), refCount(0) {} + ~PoolEntry() { pool.removeEntry(this); } + void incRef() { ++refCount; } + bool decRef() { --refCount; return (refCount == 0); } + CostT& getCost() { return cost; } + const CostT& getCost() const { return cost; } + private: + CostPool &pool; + CostT cost; + std::size_t refCount; + }; + + class PoolRef { + public: + PoolRef(PoolEntry *entry) : entry(entry) { + this->entry->incRef(); + } + PoolRef(const PoolRef &r) { + entry = r.entry; + entry->incRef(); + } + PoolRef& operator=(const PoolRef &r) { + assert(entry != nullptr && "entry should not be null."); + PoolEntry *temp = r.entry; + temp->incRef(); + entry->decRef(); + entry = temp; + return *this; + } + + ~PoolRef() { + if (entry->decRef()) + delete entry; + } + void reset(PoolEntry *entry) { + entry->incRef(); + this->entry->decRef(); + this->entry = entry; + } + CostT& operator*() { return entry->getCost(); } + const CostT& operator*() const { return entry->getCost(); } + CostT* operator->() { return &entry->getCost(); } + const CostT* operator->() const { return &entry->getCost(); } + private: + PoolEntry *entry; + }; + +private: + class EntryComparator { + public: + template <typename CostKeyT> + typename std::enable_if< + !std::is_same<PoolEntry*, + typename std::remove_const<CostKeyT>::type>::value, + bool>::type + operator()(const PoolEntry* a, const CostKeyT &b) { + return compare(a->getCost(), b); + } + bool operator()(const PoolEntry* a, const PoolEntry* b) { + return compare(a->getCost(), b->getCost()); + } + private: + CostKeyTComparator compare; + }; + + typedef std::set<PoolEntry*, EntryComparator> EntrySet; + + EntrySet entrySet; + + void removeEntry(PoolEntry *p) { entrySet.erase(p); } + +public: + + template <typename CostKeyT> + PoolRef getCost(CostKeyT costKey) { + typename EntrySet::iterator itr = + std::lower_bound(entrySet.begin(), entrySet.end(), costKey, + EntryComparator()); + + if (itr != entrySet.end() && costKey == (*itr)->getCost()) + return PoolRef(*itr); + + PoolEntry *p = new PoolEntry(*this, std::move(costKey)); + entrySet.insert(itr, p); + return PoolRef(p); + } +}; + +template <typename VectorT, typename VectorTComparator, + typename MatrixT, typename MatrixTComparator> +class PoolCostAllocator { +private: + typedef CostPool<VectorT, VectorTComparator> VectorCostPool; + typedef CostPool<MatrixT, MatrixTComparator> MatrixCostPool; +public: + typedef VectorT Vector; + typedef MatrixT Matrix; + typedef typename VectorCostPool::PoolRef VectorPtr; + typedef typename MatrixCostPool::PoolRef MatrixPtr; + + template <typename VectorKeyT> + VectorPtr getVector(VectorKeyT v) { return vectorPool.getCost(std::move(v)); } + + template <typename MatrixKeyT> + MatrixPtr getMatrix(MatrixKeyT m) { return matrixPool.getCost(std::move(m)); } +private: + VectorCostPool vectorPool; + MatrixCostPool matrixPool; +}; + +} + +#endif // LLVM_COSTALLOCATOR_H diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index aca0a9130342..a55f0ea96c0a 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -15,464 +15,628 @@ #ifndef LLVM_CODEGEN_PBQP_GRAPH_H #define LLVM_CODEGEN_PBQP_GRAPH_H -#include "Math.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/Support/Compiler.h" #include <list> #include <map> #include <set> namespace PBQP { - /// PBQP Graph class. - /// Instances of this class describe PBQP problems. - class Graph { + class GraphBase { public: - typedef unsigned NodeId; typedef unsigned EdgeId; - private: + /// \brief Returns a value representing an invalid (non-existent) node. + static NodeId invalidNodeId() { + return std::numeric_limits<NodeId>::max(); + } - typedef std::set<NodeId> AdjEdgeList; + /// \brief Returns a value representing an invalid (non-existent) edge. + static EdgeId invalidEdgeId() { + return std::numeric_limits<EdgeId>::max(); + } + }; + /// PBQP Graph class. + /// Instances of this class describe PBQP problems. + /// + template <typename SolverT> + class Graph : public GraphBase { + private: + typedef typename SolverT::CostAllocator CostAllocator; public: - - typedef AdjEdgeList::iterator AdjEdgeItr; + typedef typename SolverT::RawVector RawVector; + typedef typename SolverT::RawMatrix RawMatrix; + typedef typename SolverT::Vector Vector; + typedef typename SolverT::Matrix Matrix; + typedef typename CostAllocator::VectorPtr VectorPtr; + typedef typename CostAllocator::MatrixPtr MatrixPtr; + typedef typename SolverT::NodeMetadata NodeMetadata; + typedef typename SolverT::EdgeMetadata EdgeMetadata; private: class NodeEntry { - private: - Vector costs; - AdjEdgeList adjEdges; - void *data; - NodeEntry() : costs(0, 0) {} public: - NodeEntry(const Vector &costs) : costs(costs), data(0) {} - Vector& getCosts() { return costs; } - const Vector& getCosts() const { return costs; } - unsigned getDegree() const { return adjEdges.size(); } - AdjEdgeItr edgesBegin() { return adjEdges.begin(); } - AdjEdgeItr edgesEnd() { return adjEdges.end(); } - AdjEdgeItr addEdge(EdgeId e) { - return adjEdges.insert(adjEdges.end(), e); + typedef std::vector<EdgeId> AdjEdgeList; + typedef AdjEdgeList::size_type AdjEdgeIdx; + typedef AdjEdgeList::const_iterator AdjEdgeItr; + + static AdjEdgeIdx getInvalidAdjEdgeIdx() { + return std::numeric_limits<AdjEdgeIdx>::max(); } - void removeEdge(AdjEdgeItr ae) { - adjEdges.erase(ae); + + NodeEntry(VectorPtr Costs) : Costs(Costs) {} + + AdjEdgeIdx addAdjEdgeId(EdgeId EId) { + AdjEdgeIdx Idx = AdjEdgeIds.size(); + AdjEdgeIds.push_back(EId); + return Idx; + } + + void removeAdjEdgeId(Graph &G, NodeId ThisNId, AdjEdgeIdx Idx) { + // Swap-and-pop for fast removal. + // 1) Update the adj index of the edge currently at back(). + // 2) Move last Edge down to Idx. + // 3) pop_back() + // If Idx == size() - 1 then the setAdjEdgeIdx and swap are + // redundant, but both operations are cheap. + G.getEdge(AdjEdgeIds.back()).setAdjEdgeIdx(ThisNId, Idx); + AdjEdgeIds[Idx] = AdjEdgeIds.back(); + AdjEdgeIds.pop_back(); } - void setData(void *data) { this->data = data; } - void* getData() { return data; } + + const AdjEdgeList& getAdjEdgeIds() const { return AdjEdgeIds; } + + VectorPtr Costs; + NodeMetadata Metadata; + private: + AdjEdgeList AdjEdgeIds; }; class EdgeEntry { - private: - NodeId node1, node2; - Matrix costs; - AdjEdgeItr node1AEItr, node2AEItr; - void *data; - EdgeEntry() : costs(0, 0, 0), data(0) {} public: - EdgeEntry(NodeId node1, NodeId node2, const Matrix &costs) - : node1(node1), node2(node2), costs(costs) {} - NodeId getNode1() const { return node1; } - NodeId getNode2() const { return node2; } - Matrix& getCosts() { return costs; } - const Matrix& getCosts() const { return costs; } - void setNode1AEItr(AdjEdgeItr ae) { node1AEItr = ae; } - AdjEdgeItr getNode1AEItr() { return node1AEItr; } - void setNode2AEItr(AdjEdgeItr ae) { node2AEItr = ae; } - AdjEdgeItr getNode2AEItr() { return node2AEItr; } - void setData(void *data) { this->data = data; } - void *getData() { return data; } + EdgeEntry(NodeId N1Id, NodeId N2Id, MatrixPtr Costs) + : Costs(Costs) { + NIds[0] = N1Id; + NIds[1] = N2Id; + ThisEdgeAdjIdxs[0] = NodeEntry::getInvalidAdjEdgeIdx(); + ThisEdgeAdjIdxs[1] = NodeEntry::getInvalidAdjEdgeIdx(); + } + + void invalidate() { + NIds[0] = NIds[1] = Graph::invalidNodeId(); + ThisEdgeAdjIdxs[0] = ThisEdgeAdjIdxs[1] = + NodeEntry::getInvalidAdjEdgeIdx(); + Costs = nullptr; + } + + void connectToN(Graph &G, EdgeId ThisEdgeId, unsigned NIdx) { + assert(ThisEdgeAdjIdxs[NIdx] == NodeEntry::getInvalidAdjEdgeIdx() && + "Edge already connected to NIds[NIdx]."); + NodeEntry &N = G.getNode(NIds[NIdx]); + ThisEdgeAdjIdxs[NIdx] = N.addAdjEdgeId(ThisEdgeId); + } + + void connectTo(Graph &G, EdgeId ThisEdgeId, NodeId NId) { + if (NId == NIds[0]) + connectToN(G, ThisEdgeId, 0); + else { + assert(NId == NIds[1] && "Edge does not connect NId."); + connectToN(G, ThisEdgeId, 1); + } + } + + void connect(Graph &G, EdgeId ThisEdgeId) { + connectToN(G, ThisEdgeId, 0); + connectToN(G, ThisEdgeId, 1); + } + + void setAdjEdgeIdx(NodeId NId, typename NodeEntry::AdjEdgeIdx NewIdx) { + if (NId == NIds[0]) + ThisEdgeAdjIdxs[0] = NewIdx; + else { + assert(NId == NIds[1] && "Edge not connected to NId"); + ThisEdgeAdjIdxs[1] = NewIdx; + } + } + + void disconnectFromN(Graph &G, unsigned NIdx) { + assert(ThisEdgeAdjIdxs[NIdx] != NodeEntry::getInvalidAdjEdgeIdx() && + "Edge not connected to NIds[NIdx]."); + NodeEntry &N = G.getNode(NIds[NIdx]); + N.removeAdjEdgeId(G, NIds[NIdx], ThisEdgeAdjIdxs[NIdx]); + ThisEdgeAdjIdxs[NIdx] = NodeEntry::getInvalidAdjEdgeIdx(); + } + + void disconnectFrom(Graph &G, NodeId NId) { + if (NId == NIds[0]) + disconnectFromN(G, 0); + else { + assert(NId == NIds[1] && "Edge does not connect NId"); + disconnectFromN(G, 1); + } + } + + NodeId getN1Id() const { return NIds[0]; } + NodeId getN2Id() const { return NIds[1]; } + MatrixPtr Costs; + EdgeMetadata Metadata; + private: + NodeId NIds[2]; + typename NodeEntry::AdjEdgeIdx ThisEdgeAdjIdxs[2]; }; // ----- MEMBERS ----- + CostAllocator CostAlloc; + SolverT *Solver; + typedef std::vector<NodeEntry> NodeVector; typedef std::vector<NodeId> FreeNodeVector; - NodeVector nodes; - FreeNodeVector freeNodes; + NodeVector Nodes; + FreeNodeVector FreeNodeIds; typedef std::vector<EdgeEntry> EdgeVector; typedef std::vector<EdgeId> FreeEdgeVector; - EdgeVector edges; - FreeEdgeVector freeEdges; + EdgeVector Edges; + FreeEdgeVector FreeEdgeIds; // ----- INTERNAL METHODS ----- - NodeEntry& getNode(NodeId nId) { return nodes[nId]; } - const NodeEntry& getNode(NodeId nId) const { return nodes[nId]; } + NodeEntry& getNode(NodeId NId) { return Nodes[NId]; } + const NodeEntry& getNode(NodeId NId) const { return Nodes[NId]; } - EdgeEntry& getEdge(EdgeId eId) { return edges[eId]; } - const EdgeEntry& getEdge(EdgeId eId) const { return edges[eId]; } + EdgeEntry& getEdge(EdgeId EId) { return Edges[EId]; } + const EdgeEntry& getEdge(EdgeId EId) const { return Edges[EId]; } - NodeId addConstructedNode(const NodeEntry &n) { - NodeId nodeId = 0; - if (!freeNodes.empty()) { - nodeId = freeNodes.back(); - freeNodes.pop_back(); - nodes[nodeId] = n; + NodeId addConstructedNode(const NodeEntry &N) { + NodeId NId = 0; + if (!FreeNodeIds.empty()) { + NId = FreeNodeIds.back(); + FreeNodeIds.pop_back(); + Nodes[NId] = std::move(N); } else { - nodeId = nodes.size(); - nodes.push_back(n); + NId = Nodes.size(); + Nodes.push_back(std::move(N)); } - return nodeId; + return NId; } - EdgeId addConstructedEdge(const EdgeEntry &e) { - assert(findEdge(e.getNode1(), e.getNode2()) == invalidEdgeId() && + EdgeId addConstructedEdge(const EdgeEntry &E) { + assert(findEdge(E.getN1Id(), E.getN2Id()) == invalidEdgeId() && "Attempt to add duplicate edge."); - EdgeId edgeId = 0; - if (!freeEdges.empty()) { - edgeId = freeEdges.back(); - freeEdges.pop_back(); - edges[edgeId] = e; + EdgeId EId = 0; + if (!FreeEdgeIds.empty()) { + EId = FreeEdgeIds.back(); + FreeEdgeIds.pop_back(); + Edges[EId] = std::move(E); } else { - edgeId = edges.size(); - edges.push_back(e); + EId = Edges.size(); + Edges.push_back(std::move(E)); } - EdgeEntry &ne = getEdge(edgeId); - NodeEntry &n1 = getNode(ne.getNode1()); - NodeEntry &n2 = getNode(ne.getNode2()); - - // Sanity check on matrix dimensions: - assert((n1.getCosts().getLength() == ne.getCosts().getRows()) && - (n2.getCosts().getLength() == ne.getCosts().getCols()) && - "Edge cost dimensions do not match node costs dimensions."); + EdgeEntry &NE = getEdge(EId); - ne.setNode1AEItr(n1.addEdge(edgeId)); - ne.setNode2AEItr(n2.addEdge(edgeId)); - return edgeId; + // Add the edge to the adjacency sets of its nodes. + NE.connect(*this, EId); + return EId; } - Graph(const Graph &other) {} - void operator=(const Graph &other) {} + Graph(const Graph &Other) {} + void operator=(const Graph &Other) {} public: + typedef typename NodeEntry::AdjEdgeItr AdjEdgeItr; + class NodeItr { public: - NodeItr(NodeId nodeId, const Graph &g) - : nodeId(nodeId), endNodeId(g.nodes.size()), freeNodes(g.freeNodes) { - this->nodeId = findNextInUse(nodeId); // Move to the first in-use nodeId + NodeItr(NodeId CurNId, const Graph &G) + : CurNId(CurNId), EndNId(G.Nodes.size()), FreeNodeIds(G.FreeNodeIds) { + this->CurNId = findNextInUse(CurNId); // Move to first in-use node id } - bool operator==(const NodeItr& n) const { return nodeId == n.nodeId; } - bool operator!=(const NodeItr& n) const { return !(*this == n); } - NodeItr& operator++() { nodeId = findNextInUse(++nodeId); return *this; } - NodeId operator*() const { return nodeId; } + bool operator==(const NodeItr &O) const { return CurNId == O.CurNId; } + bool operator!=(const NodeItr &O) const { return !(*this == O); } + NodeItr& operator++() { CurNId = findNextInUse(++CurNId); return *this; } + NodeId operator*() const { return CurNId; } private: - NodeId findNextInUse(NodeId n) const { - while (n < endNodeId && - std::find(freeNodes.begin(), freeNodes.end(), n) != - freeNodes.end()) { - ++n; + NodeId findNextInUse(NodeId NId) const { + while (NId < EndNId && + std::find(FreeNodeIds.begin(), FreeNodeIds.end(), NId) != + FreeNodeIds.end()) { + ++NId; } - return n; + return NId; } - NodeId nodeId, endNodeId; - const FreeNodeVector& freeNodes; + NodeId CurNId, EndNId; + const FreeNodeVector &FreeNodeIds; }; class EdgeItr { public: - EdgeItr(EdgeId edgeId, const Graph &g) - : edgeId(edgeId), endEdgeId(g.edges.size()), freeEdges(g.freeEdges) { - this->edgeId = findNextInUse(edgeId); // Move to the first in-use edgeId + EdgeItr(EdgeId CurEId, const Graph &G) + : CurEId(CurEId), EndEId(G.Edges.size()), FreeEdgeIds(G.FreeEdgeIds) { + this->CurEId = findNextInUse(CurEId); // Move to first in-use edge id } - bool operator==(const EdgeItr& n) const { return edgeId == n.edgeId; } - bool operator!=(const EdgeItr& n) const { return !(*this == n); } - EdgeItr& operator++() { edgeId = findNextInUse(++edgeId); return *this; } - EdgeId operator*() const { return edgeId; } + bool operator==(const EdgeItr &O) const { return CurEId == O.CurEId; } + bool operator!=(const EdgeItr &O) const { return !(*this == O); } + EdgeItr& operator++() { CurEId = findNextInUse(++CurEId); return *this; } + EdgeId operator*() const { return CurEId; } private: - EdgeId findNextInUse(EdgeId n) const { - while (n < endEdgeId && - std::find(freeEdges.begin(), freeEdges.end(), n) != - freeEdges.end()) { - ++n; + EdgeId findNextInUse(EdgeId EId) const { + while (EId < EndEId && + std::find(FreeEdgeIds.begin(), FreeEdgeIds.end(), EId) != + FreeEdgeIds.end()) { + ++EId; } - return n; + return EId; + } + + EdgeId CurEId, EndEId; + const FreeEdgeVector &FreeEdgeIds; + }; + + class NodeIdSet { + public: + NodeIdSet(const Graph &G) : G(G) { } + NodeItr begin() const { return NodeItr(0, G); } + NodeItr end() const { return NodeItr(G.Nodes.size(), G); } + bool empty() const { return G.Nodes.empty(); } + typename NodeVector::size_type size() const { + return G.Nodes.size() - G.FreeNodeIds.size(); } + private: + const Graph& G; + }; - EdgeId edgeId, endEdgeId; - const FreeEdgeVector& freeEdges; + class EdgeIdSet { + public: + EdgeIdSet(const Graph &G) : G(G) { } + EdgeItr begin() const { return EdgeItr(0, G); } + EdgeItr end() const { return EdgeItr(G.Edges.size(), G); } + bool empty() const { return G.Edges.empty(); } + typename NodeVector::size_type size() const { + return G.Edges.size() - G.FreeEdgeIds.size(); + } + private: + const Graph& G; + }; + + class AdjEdgeIdSet { + public: + AdjEdgeIdSet(const NodeEntry &NE) : NE(NE) { } + typename NodeEntry::AdjEdgeItr begin() const { + return NE.getAdjEdgeIds().begin(); + } + typename NodeEntry::AdjEdgeItr end() const { + return NE.getAdjEdgeIds().end(); + } + bool empty() const { return NE.getAdjEdgeIds().empty(); } + typename NodeEntry::AdjEdgeList::size_type size() const { + return NE.getAdjEdgeIds().size(); + } + private: + const NodeEntry &NE; }; /// \brief Construct an empty PBQP graph. - Graph() {} + Graph() : Solver(nullptr) { } + + /// \brief Lock this graph to the given solver instance in preparation + /// for running the solver. This method will call solver.handleAddNode for + /// each node in the graph, and handleAddEdge for each edge, to give the + /// solver an opportunity to set up any requried metadata. + void setSolver(SolverT &S) { + assert(!Solver && "Solver already set. Call unsetSolver()."); + Solver = &S; + for (auto NId : nodeIds()) + Solver->handleAddNode(NId); + for (auto EId : edgeIds()) + Solver->handleAddEdge(EId); + } + + /// \brief Release from solver instance. + void unsetSolver() { + assert(Solver && "Solver not set."); + Solver = nullptr; + } /// \brief Add a node with the given costs. - /// @param costs Cost vector for the new node. + /// @param Costs Cost vector for the new node. /// @return Node iterator for the added node. - NodeId addNode(const Vector &costs) { - return addConstructedNode(NodeEntry(costs)); + template <typename OtherVectorT> + NodeId addNode(OtherVectorT Costs) { + // Get cost vector from the problem domain + VectorPtr AllocatedCosts = CostAlloc.getVector(std::move(Costs)); + NodeId NId = addConstructedNode(NodeEntry(AllocatedCosts)); + if (Solver) + Solver->handleAddNode(NId); + return NId; } /// \brief Add an edge between the given nodes with the given costs. - /// @param n1Id First node. - /// @param n2Id Second node. + /// @param N1Id First node. + /// @param N2Id Second node. /// @return Edge iterator for the added edge. - EdgeId addEdge(NodeId n1Id, NodeId n2Id, const Matrix &costs) { - assert(getNodeCosts(n1Id).getLength() == costs.getRows() && - getNodeCosts(n2Id).getLength() == costs.getCols() && + template <typename OtherVectorT> + EdgeId addEdge(NodeId N1Id, NodeId N2Id, OtherVectorT Costs) { + assert(getNodeCosts(N1Id).getLength() == Costs.getRows() && + getNodeCosts(N2Id).getLength() == Costs.getCols() && "Matrix dimensions mismatch."); - return addConstructedEdge(EdgeEntry(n1Id, n2Id, costs)); + // Get cost matrix from the problem domain. + MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs)); + EdgeId EId = addConstructedEdge(EdgeEntry(N1Id, N2Id, AllocatedCosts)); + if (Solver) + Solver->handleAddEdge(EId); + return EId; } + /// \brief Returns true if the graph is empty. + bool empty() const { return NodeIdSet(*this).empty(); } + + NodeIdSet nodeIds() const { return NodeIdSet(*this); } + EdgeIdSet edgeIds() const { return EdgeIdSet(*this); } + + AdjEdgeIdSet adjEdgeIds(NodeId NId) { return AdjEdgeIdSet(getNode(NId)); } + /// \brief Get the number of nodes in the graph. /// @return Number of nodes in the graph. - unsigned getNumNodes() const { return nodes.size() - freeNodes.size(); } + unsigned getNumNodes() const { return NodeIdSet(*this).size(); } /// \brief Get the number of edges in the graph. /// @return Number of edges in the graph. - unsigned getNumEdges() const { return edges.size() - freeEdges.size(); } - - /// \brief Get a node's cost vector. - /// @param nId Node id. - /// @return Node cost vector. - Vector& getNodeCosts(NodeId nId) { return getNode(nId).getCosts(); } + unsigned getNumEdges() const { return EdgeIdSet(*this).size(); } + + /// \brief Set a node's cost vector. + /// @param NId Node to update. + /// @param Costs New costs to set. + template <typename OtherVectorT> + void setNodeCosts(NodeId NId, OtherVectorT Costs) { + VectorPtr AllocatedCosts = CostAlloc.getVector(std::move(Costs)); + if (Solver) + Solver->handleSetNodeCosts(NId, *AllocatedCosts); + getNode(NId).Costs = AllocatedCosts; + } /// \brief Get a node's cost vector (const version). - /// @param nId Node id. + /// @param NId Node id. /// @return Node cost vector. - const Vector& getNodeCosts(NodeId nId) const { - return getNode(nId).getCosts(); + const Vector& getNodeCosts(NodeId NId) const { + return *getNode(NId).Costs; } - /// \brief Set a node's data pointer. - /// @param nId Node id. - /// @param data Pointer to node data. - /// - /// Typically used by a PBQP solver to attach data to aid in solution. - void setNodeData(NodeId nId, void *data) { getNode(nId).setData(data); } - - /// \brief Get the node's data pointer. - /// @param nId Node id. - /// @return Pointer to node data. - void* getNodeData(NodeId nId) { return getNode(nId).getData(); } - - /// \brief Get an edge's cost matrix. - /// @param eId Edge id. - /// @return Edge cost matrix. - Matrix& getEdgeCosts(EdgeId eId) { return getEdge(eId).getCosts(); } - - /// \brief Get an edge's cost matrix (const version). - /// @param eId Edge id. - /// @return Edge cost matrix. - const Matrix& getEdgeCosts(EdgeId eId) const { - return getEdge(eId).getCosts(); + NodeMetadata& getNodeMetadata(NodeId NId) { + return getNode(NId).Metadata; } - /// \brief Set an edge's data pointer. - /// @param eId Edge id. - /// @param data Pointer to edge data. - /// - /// Typically used by a PBQP solver to attach data to aid in solution. - void setEdgeData(EdgeId eId, void *data) { getEdge(eId).setData(data); } - - /// \brief Get an edge's data pointer. - /// @param eId Edge id. - /// @return Pointer to edge data. - void* getEdgeData(EdgeId eId) { return getEdge(eId).getData(); } - - /// \brief Get a node's degree. - /// @param nId Node id. - /// @return The degree of the node. - unsigned getNodeDegree(NodeId nId) const { - return getNode(nId).getDegree(); + const NodeMetadata& getNodeMetadata(NodeId NId) const { + return getNode(NId).Metadata; } - /// \brief Begin iterator for node set. - NodeItr nodesBegin() const { return NodeItr(0, *this); } - - /// \brief End iterator for node set. - NodeItr nodesEnd() const { return NodeItr(nodes.size(), *this); } + typename NodeEntry::AdjEdgeList::size_type getNodeDegree(NodeId NId) const { + return getNode(NId).getAdjEdgeIds().size(); + } - /// \brief Begin iterator for edge set. - EdgeItr edgesBegin() const { return EdgeItr(0, *this); } + /// \brief Set an edge's cost matrix. + /// @param EId Edge id. + /// @param Costs New cost matrix. + template <typename OtherMatrixT> + void setEdgeCosts(EdgeId EId, OtherMatrixT Costs) { + MatrixPtr AllocatedCosts = CostAlloc.getMatrix(std::move(Costs)); + if (Solver) + Solver->handleSetEdgeCosts(EId, *AllocatedCosts); + getEdge(EId).Costs = AllocatedCosts; + } - /// \brief End iterator for edge set. - EdgeItr edgesEnd() const { return EdgeItr(edges.size(), *this); } + /// \brief Get an edge's cost matrix (const version). + /// @param EId Edge id. + /// @return Edge cost matrix. + const Matrix& getEdgeCosts(EdgeId EId) const { return *getEdge(EId).Costs; } - /// \brief Get begin iterator for adjacent edge set. - /// @param nId Node id. - /// @return Begin iterator for the set of edges connected to the given node. - AdjEdgeItr adjEdgesBegin(NodeId nId) { - return getNode(nId).edgesBegin(); + EdgeMetadata& getEdgeMetadata(EdgeId NId) { + return getEdge(NId).Metadata; } - /// \brief Get end iterator for adjacent edge set. - /// @param nId Node id. - /// @return End iterator for the set of edges connected to the given node. - AdjEdgeItr adjEdgesEnd(NodeId nId) { - return getNode(nId).edgesEnd(); + const EdgeMetadata& getEdgeMetadata(EdgeId NId) const { + return getEdge(NId).Metadata; } /// \brief Get the first node connected to this edge. - /// @param eId Edge id. + /// @param EId Edge id. /// @return The first node connected to the given edge. - NodeId getEdgeNode1(EdgeId eId) { - return getEdge(eId).getNode1(); + NodeId getEdgeNode1Id(EdgeId EId) { + return getEdge(EId).getN1Id(); } /// \brief Get the second node connected to this edge. - /// @param eId Edge id. + /// @param EId Edge id. /// @return The second node connected to the given edge. - NodeId getEdgeNode2(EdgeId eId) { - return getEdge(eId).getNode2(); + NodeId getEdgeNode2Id(EdgeId EId) { + return getEdge(EId).getN2Id(); } /// \brief Get the "other" node connected to this edge. - /// @param eId Edge id. - /// @param nId Node id for the "given" node. + /// @param EId Edge id. + /// @param NId Node id for the "given" node. /// @return The iterator for the "other" node connected to this edge. - NodeId getEdgeOtherNode(EdgeId eId, NodeId nId) { - EdgeEntry &e = getEdge(eId); - if (e.getNode1() == nId) { - return e.getNode2(); + NodeId getEdgeOtherNodeId(EdgeId EId, NodeId NId) { + EdgeEntry &E = getEdge(EId); + if (E.getN1Id() == NId) { + return E.getN2Id(); } // else - return e.getNode1(); - } - - EdgeId invalidEdgeId() const { - return std::numeric_limits<EdgeId>::max(); + return E.getN1Id(); } /// \brief Get the edge connecting two nodes. - /// @param n1Id First node id. - /// @param n2Id Second node id. - /// @return An id for edge (n1Id, n2Id) if such an edge exists, + /// @param N1Id First node id. + /// @param N2Id Second node id. + /// @return An id for edge (N1Id, N2Id) if such an edge exists, /// otherwise returns an invalid edge id. - EdgeId findEdge(NodeId n1Id, NodeId n2Id) { - for (AdjEdgeItr aeItr = adjEdgesBegin(n1Id), aeEnd = adjEdgesEnd(n1Id); - aeItr != aeEnd; ++aeItr) { - if ((getEdgeNode1(*aeItr) == n2Id) || - (getEdgeNode2(*aeItr) == n2Id)) { - return *aeItr; + EdgeId findEdge(NodeId N1Id, NodeId N2Id) { + for (auto AEId : adjEdgeIds(N1Id)) { + if ((getEdgeNode1Id(AEId) == N2Id) || + (getEdgeNode2Id(AEId) == N2Id)) { + return AEId; } } return invalidEdgeId(); } /// \brief Remove a node from the graph. - /// @param nId Node id. - void removeNode(NodeId nId) { - NodeEntry &n = getNode(nId); - for (AdjEdgeItr itr = n.edgesBegin(), end = n.edgesEnd(); itr != end; ++itr) { - EdgeId eId = *itr; - removeEdge(eId); + /// @param NId Node id. + void removeNode(NodeId NId) { + if (Solver) + Solver->handleRemoveNode(NId); + NodeEntry &N = getNode(NId); + // TODO: Can this be for-each'd? + for (AdjEdgeItr AEItr = N.adjEdgesBegin(), + AEEnd = N.adjEdgesEnd(); + AEItr != AEEnd;) { + EdgeId EId = *AEItr; + ++AEItr; + removeEdge(EId); } - freeNodes.push_back(nId); + FreeNodeIds.push_back(NId); + } + + /// \brief Disconnect an edge from the given node. + /// + /// Removes the given edge from the adjacency list of the given node. + /// This operation leaves the edge in an 'asymmetric' state: It will no + /// longer appear in an iteration over the given node's (NId's) edges, but + /// will appear in an iteration over the 'other', unnamed node's edges. + /// + /// This does not correspond to any normal graph operation, but exists to + /// support efficient PBQP graph-reduction based solvers. It is used to + /// 'effectively' remove the unnamed node from the graph while the solver + /// is performing the reduction. The solver will later call reconnectNode + /// to restore the edge in the named node's adjacency list. + /// + /// Since the degree of a node is the number of connected edges, + /// disconnecting an edge from a node 'u' will cause the degree of 'u' to + /// drop by 1. + /// + /// A disconnected edge WILL still appear in an iteration over the graph + /// edges. + /// + /// A disconnected edge should not be removed from the graph, it should be + /// reconnected first. + /// + /// A disconnected edge can be reconnected by calling the reconnectEdge + /// method. + void disconnectEdge(EdgeId EId, NodeId NId) { + if (Solver) + Solver->handleDisconnectEdge(EId, NId); + + EdgeEntry &E = getEdge(EId); + E.disconnectFrom(*this, NId); + } + + /// \brief Convenience method to disconnect all neighbours from the given + /// node. + void disconnectAllNeighborsFromNode(NodeId NId) { + for (auto AEId : adjEdgeIds(NId)) + disconnectEdge(AEId, getEdgeOtherNodeId(AEId, NId)); + } + + /// \brief Re-attach an edge to its nodes. + /// + /// Adds an edge that had been previously disconnected back into the + /// adjacency set of the nodes that the edge connects. + void reconnectEdge(EdgeId EId, NodeId NId) { + EdgeEntry &E = getEdge(EId); + E.connectTo(*this, EId, NId); + if (Solver) + Solver->handleReconnectEdge(EId, NId); } /// \brief Remove an edge from the graph. - /// @param eId Edge id. - void removeEdge(EdgeId eId) { - EdgeEntry &e = getEdge(eId); - NodeEntry &n1 = getNode(e.getNode1()); - NodeEntry &n2 = getNode(e.getNode2()); - n1.removeEdge(e.getNode1AEItr()); - n2.removeEdge(e.getNode2AEItr()); - freeEdges.push_back(eId); + /// @param EId Edge id. + void removeEdge(EdgeId EId) { + if (Solver) + Solver->handleRemoveEdge(EId); + EdgeEntry &E = getEdge(EId); + E.disconnect(); + FreeEdgeIds.push_back(EId); + Edges[EId].invalidate(); } /// \brief Remove all nodes and edges from the graph. void clear() { - nodes.clear(); - freeNodes.clear(); - edges.clear(); - freeEdges.clear(); + Nodes.clear(); + FreeNodeIds.clear(); + Edges.clear(); + FreeEdgeIds.clear(); } /// \brief Dump a graph to an output stream. template <typename OStream> - void dump(OStream &os) { - os << getNumNodes() << " " << getNumEdges() << "\n"; - - for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd(); - nodeItr != nodeEnd; ++nodeItr) { - const Vector& v = getNodeCosts(*nodeItr); - os << "\n" << v.getLength() << "\n"; - assert(v.getLength() != 0 && "Empty vector in graph."); - os << v[0]; - for (unsigned i = 1; i < v.getLength(); ++i) { - os << " " << v[i]; + void dump(OStream &OS) { + OS << nodeIds().size() << " " << edgeIds().size() << "\n"; + + for (auto NId : nodeIds()) { + const Vector& V = getNodeCosts(NId); + OS << "\n" << V.getLength() << "\n"; + assert(V.getLength() != 0 && "Empty vector in graph."); + OS << V[0]; + for (unsigned i = 1; i < V.getLength(); ++i) { + OS << " " << V[i]; } - os << "\n"; + OS << "\n"; } - for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); - edgeItr != edgeEnd; ++edgeItr) { - NodeId n1 = getEdgeNode1(*edgeItr); - NodeId n2 = getEdgeNode2(*edgeItr); - assert(n1 != n2 && "PBQP graphs shound not have self-edges."); - const Matrix& m = getEdgeCosts(*edgeItr); - os << "\n" << n1 << " " << n2 << "\n" - << m.getRows() << " " << m.getCols() << "\n"; - assert(m.getRows() != 0 && "No rows in matrix."); - assert(m.getCols() != 0 && "No cols in matrix."); - for (unsigned i = 0; i < m.getRows(); ++i) { - os << m[i][0]; - for (unsigned j = 1; j < m.getCols(); ++j) { - os << " " << m[i][j]; + for (auto EId : edgeIds()) { + NodeId N1Id = getEdgeNode1Id(EId); + NodeId N2Id = getEdgeNode2Id(EId); + assert(N1Id != N2Id && "PBQP graphs shound not have self-edges."); + const Matrix& M = getEdgeCosts(EId); + OS << "\n" << N1Id << " " << N2Id << "\n" + << M.getRows() << " " << M.getCols() << "\n"; + assert(M.getRows() != 0 && "No rows in matrix."); + assert(M.getCols() != 0 && "No cols in matrix."); + for (unsigned i = 0; i < M.getRows(); ++i) { + OS << M[i][0]; + for (unsigned j = 1; j < M.getCols(); ++j) { + OS << " " << M[i][j]; } - os << "\n"; + OS << "\n"; } } } /// \brief Print a representation of this graph in DOT format. - /// @param os Output stream to print on. + /// @param OS Output stream to print on. template <typename OStream> - void printDot(OStream &os) { - - os << "graph {\n"; - - for (NodeItr nodeItr = nodesBegin(), nodeEnd = nodesEnd(); - nodeItr != nodeEnd; ++nodeItr) { - - os << " node" << nodeItr << " [ label=\"" - << nodeItr << ": " << getNodeCosts(*nodeItr) << "\" ]\n"; + void printDot(OStream &OS) { + OS << "graph {\n"; + for (auto NId : nodeIds()) { + OS << " node" << NId << " [ label=\"" + << NId << ": " << getNodeCosts(NId) << "\" ]\n"; } - - os << " edge [ len=" << getNumNodes() << " ]\n"; - - for (EdgeItr edgeItr = edgesBegin(), edgeEnd = edgesEnd(); - edgeItr != edgeEnd; ++edgeItr) { - - os << " node" << getEdgeNode1(*edgeItr) - << " -- node" << getEdgeNode2(*edgeItr) + OS << " edge [ len=" << nodeIds().size() << " ]\n"; + for (auto EId : edgeIds()) { + OS << " node" << getEdgeNode1Id(EId) + << " -- node" << getEdgeNode2Id(EId) << " [ label=\""; - - const Matrix &edgeCosts = getEdgeCosts(*edgeItr); - - for (unsigned i = 0; i < edgeCosts.getRows(); ++i) { - os << edgeCosts.getRowAsVector(i) << "\\n"; + const Matrix &EdgeCosts = getEdgeCosts(EId); + for (unsigned i = 0; i < EdgeCosts.getRows(); ++i) { + OS << EdgeCosts.getRowAsVector(i) << "\\n"; } - os << "\" ]\n"; + OS << "\" ]\n"; } - os << "}\n"; + OS << "}\n"; } - }; -// void Graph::copyFrom(const Graph &other) { -// std::map<Graph::ConstNodeItr, Graph::NodeItr, -// NodeItrComparator> nodeMap; - -// for (Graph::ConstNodeItr nItr = other.nodesBegin(), -// nEnd = other.nodesEnd(); -// nItr != nEnd; ++nItr) { -// nodeMap[nItr] = addNode(other.getNodeCosts(nItr)); -// } -// } - } #endif // LLVM_CODEGEN_PBQP_GRAPH_HPP diff --git a/include/llvm/CodeGen/PBQP/HeuristicBase.h b/include/llvm/CodeGen/PBQP/HeuristicBase.h deleted file mode 100644 index 8bcbb9ed1d6b..000000000000 --- a/include/llvm/CodeGen/PBQP/HeuristicBase.h +++ /dev/null @@ -1,247 +0,0 @@ -//===-- HeuristcBase.h --- Heuristic base class for PBQP --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_HEURISTICBASE_H -#define LLVM_CODEGEN_PBQP_HEURISTICBASE_H - -#include "HeuristicSolver.h" - -namespace PBQP { - - /// \brief Abstract base class for heuristic implementations. - /// - /// This class provides a handy base for heuristic implementations with common - /// solver behaviour implemented for a number of methods. - /// - /// To implement your own heuristic using this class as a base you'll have to - /// implement, as a minimum, the following methods: - /// <ul> - /// <li> void addToHeuristicList(Graph::NodeItr) : Add a node to the - /// heuristic reduction list. - /// <li> void heuristicReduce() : Perform a single heuristic reduction. - /// <li> void preUpdateEdgeCosts(Graph::EdgeItr) : Handle the (imminent) - /// change to the cost matrix on the given edge (by R2). - /// <li> void postUpdateEdgeCostts(Graph::EdgeItr) : Handle the new - /// costs on the given edge. - /// <li> void handleAddEdge(Graph::EdgeItr) : Handle the addition of a new - /// edge into the PBQP graph (by R2). - /// <li> void handleRemoveEdge(Graph::EdgeItr, Graph::NodeItr) : Handle the - /// disconnection of the given edge from the given node. - /// <li> A constructor for your derived class : to pass back a reference to - /// the solver which is using this heuristic. - /// </ul> - /// - /// These methods are implemented in this class for documentation purposes, - /// but will assert if called. - /// - /// Note that this class uses the curiously recursive template idiom to - /// forward calls to the derived class. These methods need not be made - /// virtual, and indeed probably shouldn't for performance reasons. - /// - /// You'll also need to provide NodeData and EdgeData structs in your class. - /// These can be used to attach data relevant to your heuristic to each - /// node/edge in the PBQP graph. - - template <typename HImpl> - class HeuristicBase { - private: - - typedef std::list<Graph::NodeId> OptimalList; - - HeuristicSolverImpl<HImpl> &s; - Graph &g; - OptimalList optimalList; - - // Return a reference to the derived heuristic. - HImpl& impl() { return static_cast<HImpl&>(*this); } - - // Add the given node to the optimal reductions list. Keep an iterator to - // its location for fast removal. - void addToOptimalReductionList(Graph::NodeId nId) { - optimalList.insert(optimalList.end(), nId); - } - - public: - - /// \brief Construct an instance with a reference to the given solver. - /// @param solver The solver which is using this heuristic instance. - HeuristicBase(HeuristicSolverImpl<HImpl> &solver) - : s(solver), g(s.getGraph()) { } - - /// \brief Get the solver which is using this heuristic instance. - /// @return The solver which is using this heuristic instance. - /// - /// You can use this method to get access to the solver in your derived - /// heuristic implementation. - HeuristicSolverImpl<HImpl>& getSolver() { return s; } - - /// \brief Get the graph representing the problem to be solved. - /// @return The graph representing the problem to be solved. - Graph& getGraph() { return g; } - - /// \brief Tell the solver to simplify the graph before the reduction phase. - /// @return Whether or not the solver should run a simplification phase - /// prior to the main setup and reduction. - /// - /// HeuristicBase returns true from this method as it's a sensible default, - /// however you can over-ride it in your derived class if you want different - /// behaviour. - bool solverRunSimplify() const { return true; } - - /// \brief Decide whether a node should be optimally or heuristically - /// reduced. - /// @return Whether or not the given node should be listed for optimal - /// reduction (via R0, R1 or R2). - /// - /// HeuristicBase returns true for any node with degree less than 3. This is - /// sane and sensible for many situations, but not all. You can over-ride - /// this method in your derived class if you want a different selection - /// criteria. Note however that your criteria for selecting optimal nodes - /// should be <i>at least</i> as strong as this. I.e. Nodes of degree 3 or - /// higher should not be selected under any circumstances. - bool shouldOptimallyReduce(Graph::NodeId nId) { - if (g.getNodeDegree(nId) < 3) - return true; - // else - return false; - } - - /// \brief Add the given node to the list of nodes to be optimally reduced. - /// @param nId Node id to be added. - /// - /// You probably don't want to over-ride this, except perhaps to record - /// statistics before calling this implementation. HeuristicBase relies on - /// its behaviour. - void addToOptimalReduceList(Graph::NodeId nId) { - optimalList.push_back(nId); - } - - /// \brief Initialise the heuristic. - /// - /// HeuristicBase iterates over all nodes in the problem and adds them to - /// the appropriate list using addToOptimalReduceList or - /// addToHeuristicReduceList based on the result of shouldOptimallyReduce. - /// - /// This behaviour should be fine for most situations. - void setup() { - for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); - nItr != nEnd; ++nItr) { - if (impl().shouldOptimallyReduce(*nItr)) { - addToOptimalReduceList(*nItr); - } else { - impl().addToHeuristicReduceList(*nItr); - } - } - } - - /// \brief Optimally reduce one of the nodes in the optimal reduce list. - /// @return True if a reduction takes place, false if the optimal reduce - /// list is empty. - /// - /// Selects a node from the optimal reduce list and removes it, applying - /// R0, R1 or R2 as appropriate based on the selected node's degree. - bool optimalReduce() { - if (optimalList.empty()) - return false; - - Graph::NodeId nId = optimalList.front(); - optimalList.pop_front(); - - switch (s.getSolverDegree(nId)) { - case 0: s.applyR0(nId); break; - case 1: s.applyR1(nId); break; - case 2: s.applyR2(nId); break; - default: llvm_unreachable( - "Optimal reductions of degree > 2 nodes is invalid."); - } - - return true; - } - - /// \brief Perform the PBQP reduction process. - /// - /// Reduces the problem to the empty graph by repeated application of the - /// reduction rules R0, R1, R2 and RN. - /// R0, R1 or R2 are always applied if possible before RN is used. - void reduce() { - bool finished = false; - - while (!finished) { - if (!optimalReduce()) { - if (impl().heuristicReduce()) { - getSolver().recordRN(); - } else { - finished = true; - } - } - } - } - - /// \brief Add a node to the heuristic reduce list. - /// @param nId Node id to add to the heuristic reduce list. - void addToHeuristicList(Graph::NodeId nId) { - llvm_unreachable("Must be implemented in derived class."); - } - - /// \brief Heuristically reduce one of the nodes in the heuristic - /// reduce list. - /// @return True if a reduction takes place, false if the heuristic reduce - /// list is empty. - bool heuristicReduce() { - llvm_unreachable("Must be implemented in derived class."); - return false; - } - - /// \brief Prepare a change in the costs on the given edge. - /// @param eId Edge id. - void preUpdateEdgeCosts(Graph::EdgeId eId) { - llvm_unreachable("Must be implemented in derived class."); - } - - /// \brief Handle the change in the costs on the given edge. - /// @param eId Edge id. - void postUpdateEdgeCostts(Graph::EdgeId eId) { - llvm_unreachable("Must be implemented in derived class."); - } - - /// \brief Handle the addition of a new edge into the PBQP graph. - /// @param eId Edge id for the added edge. - void handleAddEdge(Graph::EdgeId eId) { - llvm_unreachable("Must be implemented in derived class."); - } - - /// \brief Handle disconnection of an edge from a node. - /// @param eId Edge id for edge being disconnected. - /// @param nId Node id for the node being disconnected from. - /// - /// Edges are frequently removed due to the removal of a node. This - /// method allows for the effect to be computed only for the remaining - /// node in the graph. - void handleRemoveEdge(Graph::EdgeId eId, Graph::NodeId nId) { - llvm_unreachable("Must be implemented in derived class."); - } - - /// \brief Clean up any structures used by HeuristicBase. - /// - /// At present this just performs a sanity check: that the optimal reduce - /// list is empty now that reduction has completed. - /// - /// If your derived class has more complex structures which need tearing - /// down you should over-ride this method but include a call back to this - /// implementation. - void cleanup() { - assert(optimalList.empty() && "Nodes left over in optimal reduce list?"); - } - - }; - -} - - -#endif // LLVM_CODEGEN_PBQP_HEURISTICBASE_H diff --git a/include/llvm/CodeGen/PBQP/HeuristicSolver.h b/include/llvm/CodeGen/PBQP/HeuristicSolver.h deleted file mode 100644 index e26ca02fff7e..000000000000 --- a/include/llvm/CodeGen/PBQP/HeuristicSolver.h +++ /dev/null @@ -1,618 +0,0 @@ -//===-- HeuristicSolver.h - Heuristic PBQP Solver --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Heuristic PBQP solver. This solver is able to perform optimal reductions for -// nodes of degree 0, 1 or 2. For nodes of degree >2 a plugable heuristic is -// used to select a node for reduction. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H -#define LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H - -#include "Graph.h" -#include "Solution.h" -#include <limits> -#include <vector> - -namespace PBQP { - - /// \brief Heuristic PBQP solver implementation. - /// - /// This class should usually be created (and destroyed) indirectly via a call - /// to HeuristicSolver<HImpl>::solve(Graph&). - /// See the comments for HeuristicSolver. - /// - /// HeuristicSolverImpl provides the R0, R1 and R2 reduction rules, - /// backpropagation phase, and maintains the internal copy of the graph on - /// which the reduction is carried out (the original being kept to facilitate - /// backpropagation). - template <typename HImpl> - class HeuristicSolverImpl { - private: - - typedef typename HImpl::NodeData HeuristicNodeData; - typedef typename HImpl::EdgeData HeuristicEdgeData; - - typedef std::list<Graph::EdgeId> SolverEdges; - - public: - - /// \brief Iterator type for edges in the solver graph. - typedef SolverEdges::iterator SolverEdgeItr; - - private: - - class NodeData { - public: - NodeData() : solverDegree(0) {} - - HeuristicNodeData& getHeuristicData() { return hData; } - - SolverEdgeItr addSolverEdge(Graph::EdgeId eId) { - ++solverDegree; - return solverEdges.insert(solverEdges.end(), eId); - } - - void removeSolverEdge(SolverEdgeItr seItr) { - --solverDegree; - solverEdges.erase(seItr); - } - - SolverEdgeItr solverEdgesBegin() { return solverEdges.begin(); } - SolverEdgeItr solverEdgesEnd() { return solverEdges.end(); } - unsigned getSolverDegree() const { return solverDegree; } - void clearSolverEdges() { - solverDegree = 0; - solverEdges.clear(); - } - - private: - HeuristicNodeData hData; - unsigned solverDegree; - SolverEdges solverEdges; - }; - - class EdgeData { - public: - HeuristicEdgeData& getHeuristicData() { return hData; } - - void setN1SolverEdgeItr(SolverEdgeItr n1SolverEdgeItr) { - this->n1SolverEdgeItr = n1SolverEdgeItr; - } - - SolverEdgeItr getN1SolverEdgeItr() { return n1SolverEdgeItr; } - - void setN2SolverEdgeItr(SolverEdgeItr n2SolverEdgeItr){ - this->n2SolverEdgeItr = n2SolverEdgeItr; - } - - SolverEdgeItr getN2SolverEdgeItr() { return n2SolverEdgeItr; } - - private: - - HeuristicEdgeData hData; - SolverEdgeItr n1SolverEdgeItr, n2SolverEdgeItr; - }; - - Graph &g; - HImpl h; - Solution s; - std::vector<Graph::NodeId> stack; - - typedef std::list<NodeData> NodeDataList; - NodeDataList nodeDataList; - - typedef std::list<EdgeData> EdgeDataList; - EdgeDataList edgeDataList; - - public: - - /// \brief Construct a heuristic solver implementation to solve the given - /// graph. - /// @param g The graph representing the problem instance to be solved. - HeuristicSolverImpl(Graph &g) : g(g), h(*this) {} - - /// \brief Get the graph being solved by this solver. - /// @return The graph representing the problem instance being solved by this - /// solver. - Graph& getGraph() { return g; } - - /// \brief Get the heuristic data attached to the given node. - /// @param nId Node id. - /// @return The heuristic data attached to the given node. - HeuristicNodeData& getHeuristicNodeData(Graph::NodeId nId) { - return getSolverNodeData(nId).getHeuristicData(); - } - - /// \brief Get the heuristic data attached to the given edge. - /// @param eId Edge id. - /// @return The heuristic data attached to the given node. - HeuristicEdgeData& getHeuristicEdgeData(Graph::EdgeId eId) { - return getSolverEdgeData(eId).getHeuristicData(); - } - - /// \brief Begin iterator for the set of edges adjacent to the given node in - /// the solver graph. - /// @param nId Node id. - /// @return Begin iterator for the set of edges adjacent to the given node - /// in the solver graph. - SolverEdgeItr solverEdgesBegin(Graph::NodeId nId) { - return getSolverNodeData(nId).solverEdgesBegin(); - } - - /// \brief End iterator for the set of edges adjacent to the given node in - /// the solver graph. - /// @param nId Node id. - /// @return End iterator for the set of edges adjacent to the given node in - /// the solver graph. - SolverEdgeItr solverEdgesEnd(Graph::NodeId nId) { - return getSolverNodeData(nId).solverEdgesEnd(); - } - - /// \brief Remove a node from the solver graph. - /// @param eId Edge id for edge to be removed. - /// - /// Does <i>not</i> notify the heuristic of the removal. That should be - /// done manually if necessary. - void removeSolverEdge(Graph::EdgeId eId) { - EdgeData &eData = getSolverEdgeData(eId); - NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eId)), - &n2Data = getSolverNodeData(g.getEdgeNode2(eId)); - - n1Data.removeSolverEdge(eData.getN1SolverEdgeItr()); - n2Data.removeSolverEdge(eData.getN2SolverEdgeItr()); - } - - /// \brief Compute a solution to the PBQP problem instance with which this - /// heuristic solver was constructed. - /// @return A solution to the PBQP problem. - /// - /// Performs the full PBQP heuristic solver algorithm, including setup, - /// calls to the heuristic (which will call back to the reduction rules in - /// this class), and cleanup. - Solution computeSolution() { - setup(); - h.setup(); - h.reduce(); - backpropagate(); - h.cleanup(); - cleanup(); - return s; - } - - /// \brief Add to the end of the stack. - /// @param nId Node id to add to the reduction stack. - void pushToStack(Graph::NodeId nId) { - getSolverNodeData(nId).clearSolverEdges(); - stack.push_back(nId); - } - - /// \brief Returns the solver degree of the given node. - /// @param nId Node id for which degree is requested. - /// @return Node degree in the <i>solver</i> graph (not the original graph). - unsigned getSolverDegree(Graph::NodeId nId) { - return getSolverNodeData(nId).getSolverDegree(); - } - - /// \brief Set the solution of the given node. - /// @param nId Node id to set solution for. - /// @param selection Selection for node. - void setSolution(const Graph::NodeId &nId, unsigned selection) { - s.setSelection(nId, selection); - - for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nId), - aeEnd = g.adjEdgesEnd(nId); - aeItr != aeEnd; ++aeItr) { - Graph::EdgeId eId(*aeItr); - Graph::NodeId anId(g.getEdgeOtherNode(eId, nId)); - getSolverNodeData(anId).addSolverEdge(eId); - } - } - - /// \brief Apply rule R0. - /// @param nId Node id for node to apply R0 to. - /// - /// Node will be automatically pushed to the solver stack. - void applyR0(Graph::NodeId nId) { - assert(getSolverNodeData(nId).getSolverDegree() == 0 && - "R0 applied to node with degree != 0."); - - // Nothing to do. Just push the node onto the reduction stack. - pushToStack(nId); - - s.recordR0(); - } - - /// \brief Apply rule R1. - /// @param xnId Node id for node to apply R1 to. - /// - /// Node will be automatically pushed to the solver stack. - void applyR1(Graph::NodeId xnId) { - NodeData &nd = getSolverNodeData(xnId); - assert(nd.getSolverDegree() == 1 && - "R1 applied to node with degree != 1."); - - Graph::EdgeId eId = *nd.solverEdgesBegin(); - - const Matrix &eCosts = g.getEdgeCosts(eId); - const Vector &xCosts = g.getNodeCosts(xnId); - - // Duplicate a little to avoid transposing matrices. - if (xnId == g.getEdgeNode1(eId)) { - Graph::NodeId ynId = g.getEdgeNode2(eId); - Vector &yCosts = g.getNodeCosts(ynId); - for (unsigned j = 0; j < yCosts.getLength(); ++j) { - PBQPNum min = eCosts[0][j] + xCosts[0]; - for (unsigned i = 1; i < xCosts.getLength(); ++i) { - PBQPNum c = eCosts[i][j] + xCosts[i]; - if (c < min) - min = c; - } - yCosts[j] += min; - } - h.handleRemoveEdge(eId, ynId); - } else { - Graph::NodeId ynId = g.getEdgeNode1(eId); - Vector &yCosts = g.getNodeCosts(ynId); - for (unsigned i = 0; i < yCosts.getLength(); ++i) { - PBQPNum min = eCosts[i][0] + xCosts[0]; - for (unsigned j = 1; j < xCosts.getLength(); ++j) { - PBQPNum c = eCosts[i][j] + xCosts[j]; - if (c < min) - min = c; - } - yCosts[i] += min; - } - h.handleRemoveEdge(eId, ynId); - } - removeSolverEdge(eId); - assert(nd.getSolverDegree() == 0 && - "Degree 1 with edge removed should be 0."); - pushToStack(xnId); - s.recordR1(); - } - - /// \brief Apply rule R2. - /// @param xnId Node id for node to apply R2 to. - /// - /// Node will be automatically pushed to the solver stack. - void applyR2(Graph::NodeId xnId) { - assert(getSolverNodeData(xnId).getSolverDegree() == 2 && - "R2 applied to node with degree != 2."); - - NodeData &nd = getSolverNodeData(xnId); - const Vector &xCosts = g.getNodeCosts(xnId); - - SolverEdgeItr aeItr = nd.solverEdgesBegin(); - Graph::EdgeId yxeId = *aeItr, - zxeId = *(++aeItr); - - Graph::NodeId ynId = g.getEdgeOtherNode(yxeId, xnId), - znId = g.getEdgeOtherNode(zxeId, xnId); - - bool flipEdge1 = (g.getEdgeNode1(yxeId) == xnId), - flipEdge2 = (g.getEdgeNode1(zxeId) == xnId); - - const Matrix *yxeCosts = flipEdge1 ? - new Matrix(g.getEdgeCosts(yxeId).transpose()) : - &g.getEdgeCosts(yxeId); - - const Matrix *zxeCosts = flipEdge2 ? - new Matrix(g.getEdgeCosts(zxeId).transpose()) : - &g.getEdgeCosts(zxeId); - - unsigned xLen = xCosts.getLength(), - yLen = yxeCosts->getRows(), - zLen = zxeCosts->getRows(); - - Matrix delta(yLen, zLen); - - for (unsigned i = 0; i < yLen; ++i) { - for (unsigned j = 0; j < zLen; ++j) { - PBQPNum min = (*yxeCosts)[i][0] + (*zxeCosts)[j][0] + xCosts[0]; - for (unsigned k = 1; k < xLen; ++k) { - PBQPNum c = (*yxeCosts)[i][k] + (*zxeCosts)[j][k] + xCosts[k]; - if (c < min) { - min = c; - } - } - delta[i][j] = min; - } - } - - if (flipEdge1) - delete yxeCosts; - - if (flipEdge2) - delete zxeCosts; - - Graph::EdgeId yzeId = g.findEdge(ynId, znId); - bool addedEdge = false; - - if (yzeId == g.invalidEdgeId()) { - yzeId = g.addEdge(ynId, znId, delta); - addedEdge = true; - } else { - Matrix &yzeCosts = g.getEdgeCosts(yzeId); - h.preUpdateEdgeCosts(yzeId); - if (ynId == g.getEdgeNode1(yzeId)) { - yzeCosts += delta; - } else { - yzeCosts += delta.transpose(); - } - } - - bool nullCostEdge = tryNormaliseEdgeMatrix(yzeId); - - if (!addedEdge) { - // If we modified the edge costs let the heuristic know. - h.postUpdateEdgeCosts(yzeId); - } - - if (nullCostEdge) { - // If this edge ended up null remove it. - if (!addedEdge) { - // We didn't just add it, so we need to notify the heuristic - // and remove it from the solver. - h.handleRemoveEdge(yzeId, ynId); - h.handleRemoveEdge(yzeId, znId); - removeSolverEdge(yzeId); - } - g.removeEdge(yzeId); - } else if (addedEdge) { - // If the edge was added, and non-null, finish setting it up, add it to - // the solver & notify heuristic. - edgeDataList.push_back(EdgeData()); - g.setEdgeData(yzeId, &edgeDataList.back()); - addSolverEdge(yzeId); - h.handleAddEdge(yzeId); - } - - h.handleRemoveEdge(yxeId, ynId); - removeSolverEdge(yxeId); - h.handleRemoveEdge(zxeId, znId); - removeSolverEdge(zxeId); - - pushToStack(xnId); - s.recordR2(); - } - - /// \brief Record an application of the RN rule. - /// - /// For use by the HeuristicBase. - void recordRN() { s.recordRN(); } - - private: - - NodeData& getSolverNodeData(Graph::NodeId nId) { - return *static_cast<NodeData*>(g.getNodeData(nId)); - } - - EdgeData& getSolverEdgeData(Graph::EdgeId eId) { - return *static_cast<EdgeData*>(g.getEdgeData(eId)); - } - - void addSolverEdge(Graph::EdgeId eId) { - EdgeData &eData = getSolverEdgeData(eId); - NodeData &n1Data = getSolverNodeData(g.getEdgeNode1(eId)), - &n2Data = getSolverNodeData(g.getEdgeNode2(eId)); - - eData.setN1SolverEdgeItr(n1Data.addSolverEdge(eId)); - eData.setN2SolverEdgeItr(n2Data.addSolverEdge(eId)); - } - - void setup() { - if (h.solverRunSimplify()) { - simplify(); - } - - // Create node data objects. - for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); - nItr != nEnd; ++nItr) { - nodeDataList.push_back(NodeData()); - g.setNodeData(*nItr, &nodeDataList.back()); - } - - // Create edge data objects. - for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); - eItr != eEnd; ++eItr) { - edgeDataList.push_back(EdgeData()); - g.setEdgeData(*eItr, &edgeDataList.back()); - addSolverEdge(*eItr); - } - } - - void simplify() { - disconnectTrivialNodes(); - eliminateIndependentEdges(); - } - - // Eliminate trivial nodes. - void disconnectTrivialNodes() { - unsigned numDisconnected = 0; - - for (Graph::NodeItr nItr = g.nodesBegin(), nEnd = g.nodesEnd(); - nItr != nEnd; ++nItr) { - - Graph::NodeId nId = *nItr; - - if (g.getNodeCosts(nId).getLength() == 1) { - - std::vector<Graph::EdgeId> edgesToRemove; - - for (Graph::AdjEdgeItr aeItr = g.adjEdgesBegin(nId), - aeEnd = g.adjEdgesEnd(nId); - aeItr != aeEnd; ++aeItr) { - - Graph::EdgeId eId = *aeItr; - - if (g.getEdgeNode1(eId) == nId) { - Graph::NodeId otherNodeId = g.getEdgeNode2(eId); - g.getNodeCosts(otherNodeId) += - g.getEdgeCosts(eId).getRowAsVector(0); - } - else { - Graph::NodeId otherNodeId = g.getEdgeNode1(eId); - g.getNodeCosts(otherNodeId) += - g.getEdgeCosts(eId).getColAsVector(0); - } - - edgesToRemove.push_back(eId); - } - - if (!edgesToRemove.empty()) - ++numDisconnected; - - while (!edgesToRemove.empty()) { - g.removeEdge(edgesToRemove.back()); - edgesToRemove.pop_back(); - } - } - } - } - - void eliminateIndependentEdges() { - std::vector<Graph::EdgeId> edgesToProcess; - unsigned numEliminated = 0; - - for (Graph::EdgeItr eItr = g.edgesBegin(), eEnd = g.edgesEnd(); - eItr != eEnd; ++eItr) { - edgesToProcess.push_back(*eItr); - } - - while (!edgesToProcess.empty()) { - if (tryToEliminateEdge(edgesToProcess.back())) - ++numEliminated; - edgesToProcess.pop_back(); - } - } - - bool tryToEliminateEdge(Graph::EdgeId eId) { - if (tryNormaliseEdgeMatrix(eId)) { - g.removeEdge(eId); - return true; - } - return false; - } - - bool tryNormaliseEdgeMatrix(Graph::EdgeId &eId) { - - const PBQPNum infinity = std::numeric_limits<PBQPNum>::infinity(); - - Matrix &edgeCosts = g.getEdgeCosts(eId); - Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eId)), - &vCosts = g.getNodeCosts(g.getEdgeNode2(eId)); - - for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { - PBQPNum rowMin = infinity; - - for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { - if (vCosts[c] != infinity && edgeCosts[r][c] < rowMin) - rowMin = edgeCosts[r][c]; - } - - uCosts[r] += rowMin; - - if (rowMin != infinity) { - edgeCosts.subFromRow(r, rowMin); - } - else { - edgeCosts.setRow(r, 0); - } - } - - for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { - PBQPNum colMin = infinity; - - for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { - if (uCosts[r] != infinity && edgeCosts[r][c] < colMin) - colMin = edgeCosts[r][c]; - } - - vCosts[c] += colMin; - - if (colMin != infinity) { - edgeCosts.subFromCol(c, colMin); - } - else { - edgeCosts.setCol(c, 0); - } - } - - return edgeCosts.isZero(); - } - - void backpropagate() { - while (!stack.empty()) { - computeSolution(stack.back()); - stack.pop_back(); - } - } - - void computeSolution(Graph::NodeId nId) { - - NodeData &nodeData = getSolverNodeData(nId); - - Vector v(g.getNodeCosts(nId)); - - // Solve based on existing solved edges. - for (SolverEdgeItr solvedEdgeItr = nodeData.solverEdgesBegin(), - solvedEdgeEnd = nodeData.solverEdgesEnd(); - solvedEdgeItr != solvedEdgeEnd; ++solvedEdgeItr) { - - Graph::EdgeId eId(*solvedEdgeItr); - Matrix &edgeCosts = g.getEdgeCosts(eId); - - if (nId == g.getEdgeNode1(eId)) { - Graph::NodeId adjNode(g.getEdgeNode2(eId)); - unsigned adjSolution = s.getSelection(adjNode); - v += edgeCosts.getColAsVector(adjSolution); - } - else { - Graph::NodeId adjNode(g.getEdgeNode1(eId)); - unsigned adjSolution = s.getSelection(adjNode); - v += edgeCosts.getRowAsVector(adjSolution); - } - - } - - setSolution(nId, v.minIndex()); - } - - void cleanup() { - h.cleanup(); - nodeDataList.clear(); - edgeDataList.clear(); - } - }; - - /// \brief PBQP heuristic solver class. - /// - /// Given a PBQP Graph g representing a PBQP problem, you can find a solution - /// by calling - /// <tt>Solution s = HeuristicSolver<H>::solve(g);</tt> - /// - /// The choice of heuristic for the H parameter will affect both the solver - /// speed and solution quality. The heuristic should be chosen based on the - /// nature of the problem being solved. - /// Currently the only solver included with LLVM is the Briggs heuristic for - /// register allocation. - template <typename HImpl> - class HeuristicSolver { - public: - static Solution solve(Graph &g) { - HeuristicSolverImpl<HImpl> hs(g); - return hs.computeSolution(); - } - }; - -} - -#endif // LLVM_CODEGEN_PBQP_HEURISTICSOLVER_H diff --git a/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h b/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h deleted file mode 100644 index c355c2c2f81a..000000000000 --- a/include/llvm/CodeGen/PBQP/Heuristics/Briggs.h +++ /dev/null @@ -1,468 +0,0 @@ -//===-- Briggs.h --- Briggs Heuristic for PBQP ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class implements the Briggs test for "allocability" of nodes in a -// PBQP graph representing a register allocation problem. Nodes which can be -// proven allocable (by a safe and relatively accurate test) are removed from -// the PBQP graph first. If no provably allocable node is present in the graph -// then the node with the minimal spill-cost to degree ratio is removed. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H -#define LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H - -#include "../HeuristicBase.h" -#include "../HeuristicSolver.h" -#include <limits> - -namespace PBQP { - namespace Heuristics { - - /// \brief PBQP Heuristic which applies an allocability test based on - /// Briggs. - /// - /// This heuristic assumes that the elements of cost vectors in the PBQP - /// problem represent storage options, with the first being the spill - /// option and subsequent elements representing legal registers for the - /// corresponding node. Edge cost matrices are likewise assumed to represent - /// register constraints. - /// If one or more nodes can be proven allocable by this heuristic (by - /// inspection of their constraint matrices) then the allocable node of - /// highest degree is selected for the next reduction and pushed to the - /// solver stack. If no nodes can be proven allocable then the node with - /// the lowest estimated spill cost is selected and push to the solver stack - /// instead. - /// - /// This implementation is built on top of HeuristicBase. - class Briggs : public HeuristicBase<Briggs> { - private: - - class LinkDegreeComparator { - public: - LinkDegreeComparator(HeuristicSolverImpl<Briggs> &s) : s(&s) {} - bool operator()(Graph::NodeId n1Id, Graph::NodeId n2Id) const { - if (s->getSolverDegree(n1Id) > s->getSolverDegree(n2Id)) - return true; - return false; - } - private: - HeuristicSolverImpl<Briggs> *s; - }; - - class SpillCostComparator { - public: - SpillCostComparator(HeuristicSolverImpl<Briggs> &s) - : s(&s), g(&s.getGraph()) {} - bool operator()(Graph::NodeId n1Id, Graph::NodeId n2Id) const { - const PBQP::Vector &cv1 = g->getNodeCosts(n1Id); - const PBQP::Vector &cv2 = g->getNodeCosts(n2Id); - - PBQPNum cost1 = cv1[0] / s->getSolverDegree(n1Id); - PBQPNum cost2 = cv2[0] / s->getSolverDegree(n2Id); - - if (cost1 < cost2) - return true; - return false; - } - - private: - HeuristicSolverImpl<Briggs> *s; - Graph *g; - }; - - typedef std::list<Graph::NodeId> RNAllocableList; - typedef RNAllocableList::iterator RNAllocableListItr; - - typedef std::list<Graph::NodeId> RNUnallocableList; - typedef RNUnallocableList::iterator RNUnallocableListItr; - - public: - - struct NodeData { - typedef std::vector<unsigned> UnsafeDegreesArray; - bool isHeuristic, isAllocable, isInitialized; - unsigned numDenied, numSafe; - UnsafeDegreesArray unsafeDegrees; - RNAllocableListItr rnaItr; - RNUnallocableListItr rnuItr; - - NodeData() - : isHeuristic(false), isAllocable(false), isInitialized(false), - numDenied(0), numSafe(0) { } - }; - - struct EdgeData { - typedef std::vector<unsigned> UnsafeArray; - unsigned worst, reverseWorst; - UnsafeArray unsafe, reverseUnsafe; - bool isUpToDate; - - EdgeData() : worst(0), reverseWorst(0), isUpToDate(false) {} - }; - - /// \brief Construct an instance of the Briggs heuristic. - /// @param solver A reference to the solver which is using this heuristic. - Briggs(HeuristicSolverImpl<Briggs> &solver) : - HeuristicBase<Briggs>(solver) {} - - /// \brief Determine whether a node should be reduced using optimal - /// reduction. - /// @param nId Node id to be considered. - /// @return True if the given node should be optimally reduced, false - /// otherwise. - /// - /// Selects nodes of degree 0, 1 or 2 for optimal reduction, with one - /// exception. Nodes whose spill cost (element 0 of their cost vector) is - /// infinite are checked for allocability first. Allocable nodes may be - /// optimally reduced, but nodes whose allocability cannot be proven are - /// selected for heuristic reduction instead. - bool shouldOptimallyReduce(Graph::NodeId nId) { - if (getSolver().getSolverDegree(nId) < 3) { - return true; - } - // else - return false; - } - - /// \brief Add a node to the heuristic reduce list. - /// @param nId Node id to add to the heuristic reduce list. - void addToHeuristicReduceList(Graph::NodeId nId) { - NodeData &nd = getHeuristicNodeData(nId); - initializeNode(nId); - nd.isHeuristic = true; - if (nd.isAllocable) { - nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nId); - } else { - nd.rnuItr = rnUnallocableList.insert(rnUnallocableList.end(), nId); - } - } - - /// \brief Heuristically reduce one of the nodes in the heuristic - /// reduce list. - /// @return True if a reduction takes place, false if the heuristic reduce - /// list is empty. - /// - /// If the list of allocable nodes is non-empty a node is selected - /// from it and pushed to the stack. Otherwise if the non-allocable list - /// is non-empty a node is selected from it and pushed to the stack. - /// If both lists are empty the method simply returns false with no action - /// taken. - bool heuristicReduce() { - if (!rnAllocableList.empty()) { - RNAllocableListItr rnaItr = - min_element(rnAllocableList.begin(), rnAllocableList.end(), - LinkDegreeComparator(getSolver())); - Graph::NodeId nId = *rnaItr; - rnAllocableList.erase(rnaItr); - handleRemoveNode(nId); - getSolver().pushToStack(nId); - return true; - } else if (!rnUnallocableList.empty()) { - RNUnallocableListItr rnuItr = - min_element(rnUnallocableList.begin(), rnUnallocableList.end(), - SpillCostComparator(getSolver())); - Graph::NodeId nId = *rnuItr; - rnUnallocableList.erase(rnuItr); - handleRemoveNode(nId); - getSolver().pushToStack(nId); - return true; - } - // else - return false; - } - - /// \brief Prepare a change in the costs on the given edge. - /// @param eId Edge id. - void preUpdateEdgeCosts(Graph::EdgeId eId) { - Graph &g = getGraph(); - Graph::NodeId n1Id = g.getEdgeNode1(eId), - n2Id = g.getEdgeNode2(eId); - NodeData &n1 = getHeuristicNodeData(n1Id), - &n2 = getHeuristicNodeData(n2Id); - - if (n1.isHeuristic) - subtractEdgeContributions(eId, getGraph().getEdgeNode1(eId)); - if (n2.isHeuristic) - subtractEdgeContributions(eId, getGraph().getEdgeNode2(eId)); - - EdgeData &ed = getHeuristicEdgeData(eId); - ed.isUpToDate = false; - } - - /// \brief Handle the change in the costs on the given edge. - /// @param eId Edge id. - void postUpdateEdgeCosts(Graph::EdgeId eId) { - // This is effectively the same as adding a new edge now, since - // we've factored out the costs of the old one. - handleAddEdge(eId); - } - - /// \brief Handle the addition of a new edge into the PBQP graph. - /// @param eId Edge id for the added edge. - /// - /// Updates allocability of any nodes connected by this edge which are - /// being managed by the heuristic. If allocability changes they are - /// moved to the appropriate list. - void handleAddEdge(Graph::EdgeId eId) { - Graph &g = getGraph(); - Graph::NodeId n1Id = g.getEdgeNode1(eId), - n2Id = g.getEdgeNode2(eId); - NodeData &n1 = getHeuristicNodeData(n1Id), - &n2 = getHeuristicNodeData(n2Id); - - // If neither node is managed by the heuristic there's nothing to be - // done. - if (!n1.isHeuristic && !n2.isHeuristic) - return; - - // Ok - we need to update at least one node. - computeEdgeContributions(eId); - - // Update node 1 if it's managed by the heuristic. - if (n1.isHeuristic) { - bool n1WasAllocable = n1.isAllocable; - addEdgeContributions(eId, n1Id); - updateAllocability(n1Id); - if (n1WasAllocable && !n1.isAllocable) { - rnAllocableList.erase(n1.rnaItr); - n1.rnuItr = - rnUnallocableList.insert(rnUnallocableList.end(), n1Id); - } - } - - // Likewise for node 2. - if (n2.isHeuristic) { - bool n2WasAllocable = n2.isAllocable; - addEdgeContributions(eId, n2Id); - updateAllocability(n2Id); - if (n2WasAllocable && !n2.isAllocable) { - rnAllocableList.erase(n2.rnaItr); - n2.rnuItr = - rnUnallocableList.insert(rnUnallocableList.end(), n2Id); - } - } - } - - /// \brief Handle disconnection of an edge from a node. - /// @param eId Edge id for edge being disconnected. - /// @param nId Node id for the node being disconnected from. - /// - /// Updates allocability of the given node and, if appropriate, moves the - /// node to a new list. - void handleRemoveEdge(Graph::EdgeId eId, Graph::NodeId nId) { - NodeData &nd =getHeuristicNodeData(nId); - - // If the node is not managed by the heuristic there's nothing to be - // done. - if (!nd.isHeuristic) - return; - - EdgeData &ed = getHeuristicEdgeData(eId); - (void)ed; - assert(ed.isUpToDate && "Edge data is not up to date."); - - // Update node. - bool ndWasAllocable = nd.isAllocable; - subtractEdgeContributions(eId, nId); - updateAllocability(nId); - - // If the node has gone optimal... - if (shouldOptimallyReduce(nId)) { - nd.isHeuristic = false; - addToOptimalReduceList(nId); - if (ndWasAllocable) { - rnAllocableList.erase(nd.rnaItr); - } else { - rnUnallocableList.erase(nd.rnuItr); - } - } else { - // Node didn't go optimal, but we might have to move it - // from "unallocable" to "allocable". - if (!ndWasAllocable && nd.isAllocable) { - rnUnallocableList.erase(nd.rnuItr); - nd.rnaItr = rnAllocableList.insert(rnAllocableList.end(), nId); - } - } - } - - private: - - NodeData& getHeuristicNodeData(Graph::NodeId nId) { - return getSolver().getHeuristicNodeData(nId); - } - - EdgeData& getHeuristicEdgeData(Graph::EdgeId eId) { - return getSolver().getHeuristicEdgeData(eId); - } - - // Work out what this edge will contribute to the allocability of the - // nodes connected to it. - void computeEdgeContributions(Graph::EdgeId eId) { - EdgeData &ed = getHeuristicEdgeData(eId); - - if (ed.isUpToDate) - return; // Edge data is already up to date. - - Matrix &eCosts = getGraph().getEdgeCosts(eId); - - unsigned numRegs = eCosts.getRows() - 1, - numReverseRegs = eCosts.getCols() - 1; - - std::vector<unsigned> rowInfCounts(numRegs, 0), - colInfCounts(numReverseRegs, 0); - - ed.worst = 0; - ed.reverseWorst = 0; - ed.unsafe.clear(); - ed.unsafe.resize(numRegs, 0); - ed.reverseUnsafe.clear(); - ed.reverseUnsafe.resize(numReverseRegs, 0); - - for (unsigned i = 0; i < numRegs; ++i) { - for (unsigned j = 0; j < numReverseRegs; ++j) { - if (eCosts[i + 1][j + 1] == - std::numeric_limits<PBQPNum>::infinity()) { - ed.unsafe[i] = 1; - ed.reverseUnsafe[j] = 1; - ++rowInfCounts[i]; - ++colInfCounts[j]; - - if (colInfCounts[j] > ed.worst) { - ed.worst = colInfCounts[j]; - } - - if (rowInfCounts[i] > ed.reverseWorst) { - ed.reverseWorst = rowInfCounts[i]; - } - } - } - } - - ed.isUpToDate = true; - } - - // Add the contributions of the given edge to the given node's - // numDenied and safe members. No action is taken other than to update - // these member values. Once updated these numbers can be used by clients - // to update the node's allocability. - void addEdgeContributions(Graph::EdgeId eId, Graph::NodeId nId) { - EdgeData &ed = getHeuristicEdgeData(eId); - - assert(ed.isUpToDate && "Using out-of-date edge numbers."); - - NodeData &nd = getHeuristicNodeData(nId); - unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; - - bool nIsNode1 = nId == getGraph().getEdgeNode1(eId); - EdgeData::UnsafeArray &unsafe = - nIsNode1 ? ed.unsafe : ed.reverseUnsafe; - nd.numDenied += nIsNode1 ? ed.worst : ed.reverseWorst; - - for (unsigned r = 0; r < numRegs; ++r) { - if (unsafe[r]) { - if (nd.unsafeDegrees[r]==0) { - --nd.numSafe; - } - ++nd.unsafeDegrees[r]; - } - } - } - - // Subtract the contributions of the given edge to the given node's - // numDenied and safe members. No action is taken other than to update - // these member values. Once updated these numbers can be used by clients - // to update the node's allocability. - void subtractEdgeContributions(Graph::EdgeId eId, Graph::NodeId nId) { - EdgeData &ed = getHeuristicEdgeData(eId); - - assert(ed.isUpToDate && "Using out-of-date edge numbers."); - - NodeData &nd = getHeuristicNodeData(nId); - unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; - - bool nIsNode1 = nId == getGraph().getEdgeNode1(eId); - EdgeData::UnsafeArray &unsafe = - nIsNode1 ? ed.unsafe : ed.reverseUnsafe; - nd.numDenied -= nIsNode1 ? ed.worst : ed.reverseWorst; - - for (unsigned r = 0; r < numRegs; ++r) { - if (unsafe[r]) { - if (nd.unsafeDegrees[r] == 1) { - ++nd.numSafe; - } - --nd.unsafeDegrees[r]; - } - } - } - - void updateAllocability(Graph::NodeId nId) { - NodeData &nd = getHeuristicNodeData(nId); - unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; - nd.isAllocable = nd.numDenied < numRegs || nd.numSafe > 0; - } - - void initializeNode(Graph::NodeId nId) { - NodeData &nd = getHeuristicNodeData(nId); - - if (nd.isInitialized) - return; // Node data is already up to date. - - unsigned numRegs = getGraph().getNodeCosts(nId).getLength() - 1; - - nd.numDenied = 0; - const Vector& nCosts = getGraph().getNodeCosts(nId); - for (unsigned i = 1; i < nCosts.getLength(); ++i) { - if (nCosts[i] == std::numeric_limits<PBQPNum>::infinity()) - ++nd.numDenied; - } - - nd.numSafe = numRegs; - nd.unsafeDegrees.resize(numRegs, 0); - - typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr; - - for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(nId), - aeEnd = getSolver().solverEdgesEnd(nId); - aeItr != aeEnd; ++aeItr) { - - Graph::EdgeId eId = *aeItr; - computeEdgeContributions(eId); - addEdgeContributions(eId, nId); - } - - updateAllocability(nId); - nd.isInitialized = true; - } - - void handleRemoveNode(Graph::NodeId xnId) { - typedef HeuristicSolverImpl<Briggs>::SolverEdgeItr SolverEdgeItr; - std::vector<Graph::EdgeId> edgesToRemove; - for (SolverEdgeItr aeItr = getSolver().solverEdgesBegin(xnId), - aeEnd = getSolver().solverEdgesEnd(xnId); - aeItr != aeEnd; ++aeItr) { - Graph::NodeId ynId = getGraph().getEdgeOtherNode(*aeItr, xnId); - handleRemoveEdge(*aeItr, ynId); - edgesToRemove.push_back(*aeItr); - } - while (!edgesToRemove.empty()) { - getSolver().removeSolverEdge(edgesToRemove.back()); - edgesToRemove.pop_back(); - } - } - - RNAllocableList rnAllocableList; - RNUnallocableList rnUnallocableList; - }; - - } -} - - -#endif // LLVM_CODEGEN_PBQP_HEURISTICS_BRIGGS_H diff --git a/include/llvm/CodeGen/PBQP/Math.h b/include/llvm/CodeGen/PBQP/Math.h index 08f8b981ae27..69a9d83cc092 100644 --- a/include/llvm/CodeGen/PBQP/Math.h +++ b/include/llvm/CodeGen/PBQP/Math.h @@ -20,268 +20,418 @@ typedef float PBQPNum; /// \brief PBQP Vector class. class Vector { - public: - - /// \brief Construct a PBQP vector of the given size. - explicit Vector(unsigned length) : - length(length), data(new PBQPNum[length]) { - } - - /// \brief Construct a PBQP vector with initializer. - Vector(unsigned length, PBQPNum initVal) : - length(length), data(new PBQPNum[length]) { - std::fill(data, data + length, initVal); - } - - /// \brief Copy construct a PBQP vector. - Vector(const Vector &v) : - length(v.length), data(new PBQPNum[length]) { - std::copy(v.data, v.data + length, data); - } - - /// \brief Destroy this vector, return its memory. - ~Vector() { delete[] data; } - - /// \brief Assignment operator. - Vector& operator=(const Vector &v) { - delete[] data; - length = v.length; - data = new PBQPNum[length]; - std::copy(v.data, v.data + length, data); - return *this; - } - - /// \brief Return the length of the vector - unsigned getLength() const { - return length; - } - - /// \brief Element access. - PBQPNum& operator[](unsigned index) { - assert(index < length && "Vector element access out of bounds."); - return data[index]; - } - - /// \brief Const element access. - const PBQPNum& operator[](unsigned index) const { - assert(index < length && "Vector element access out of bounds."); - return data[index]; - } - - /// \brief Add another vector to this one. - Vector& operator+=(const Vector &v) { - assert(length == v.length && "Vector length mismatch."); - std::transform(data, data + length, v.data, data, std::plus<PBQPNum>()); - return *this; - } - - /// \brief Subtract another vector from this one. - Vector& operator-=(const Vector &v) { - assert(length == v.length && "Vector length mismatch."); - std::transform(data, data + length, v.data, data, std::minus<PBQPNum>()); - return *this; - } - - /// \brief Returns the index of the minimum value in this vector - unsigned minIndex() const { - return std::min_element(data, data + length) - data; - } - - private: - unsigned length; - PBQPNum *data; + friend class VectorComparator; +public: + + /// \brief Construct a PBQP vector of the given size. + explicit Vector(unsigned Length) + : Length(Length), Data(new PBQPNum[Length]) { + // llvm::dbgs() << "Constructing PBQP::Vector " + // << this << " (length " << Length << ")\n"; + } + + /// \brief Construct a PBQP vector with initializer. + Vector(unsigned Length, PBQPNum InitVal) + : Length(Length), Data(new PBQPNum[Length]) { + // llvm::dbgs() << "Constructing PBQP::Vector " + // << this << " (length " << Length << ", fill " + // << InitVal << ")\n"; + std::fill(Data, Data + Length, InitVal); + } + + /// \brief Copy construct a PBQP vector. + Vector(const Vector &V) + : Length(V.Length), Data(new PBQPNum[Length]) { + // llvm::dbgs() << "Copy-constructing PBQP::Vector " << this + // << " from PBQP::Vector " << &V << "\n"; + std::copy(V.Data, V.Data + Length, Data); + } + + /// \brief Move construct a PBQP vector. + Vector(Vector &&V) + : Length(V.Length), Data(V.Data) { + V.Length = 0; + V.Data = nullptr; + } + + /// \brief Destroy this vector, return its memory. + ~Vector() { + // llvm::dbgs() << "Deleting PBQP::Vector " << this << "\n"; + delete[] Data; + } + + /// \brief Copy-assignment operator. + Vector& operator=(const Vector &V) { + // llvm::dbgs() << "Assigning to PBQP::Vector " << this + // << " from PBQP::Vector " << &V << "\n"; + delete[] Data; + Length = V.Length; + Data = new PBQPNum[Length]; + std::copy(V.Data, V.Data + Length, Data); + return *this; + } + + /// \brief Move-assignment operator. + Vector& operator=(Vector &&V) { + delete[] Data; + Length = V.Length; + Data = V.Data; + V.Length = 0; + V.Data = nullptr; + return *this; + } + + /// \brief Comparison operator. + bool operator==(const Vector &V) const { + assert(Length != 0 && Data != nullptr && "Invalid vector"); + if (Length != V.Length) + return false; + return std::equal(Data, Data + Length, V.Data); + } + + /// \brief Return the length of the vector + unsigned getLength() const { + assert(Length != 0 && Data != nullptr && "Invalid vector"); + return Length; + } + + /// \brief Element access. + PBQPNum& operator[](unsigned Index) { + assert(Length != 0 && Data != nullptr && "Invalid vector"); + assert(Index < Length && "Vector element access out of bounds."); + return Data[Index]; + } + + /// \brief Const element access. + const PBQPNum& operator[](unsigned Index) const { + assert(Length != 0 && Data != nullptr && "Invalid vector"); + assert(Index < Length && "Vector element access out of bounds."); + return Data[Index]; + } + + /// \brief Add another vector to this one. + Vector& operator+=(const Vector &V) { + assert(Length != 0 && Data != nullptr && "Invalid vector"); + assert(Length == V.Length && "Vector length mismatch."); + std::transform(Data, Data + Length, V.Data, Data, std::plus<PBQPNum>()); + return *this; + } + + /// \brief Subtract another vector from this one. + Vector& operator-=(const Vector &V) { + assert(Length != 0 && Data != nullptr && "Invalid vector"); + assert(Length == V.Length && "Vector length mismatch."); + std::transform(Data, Data + Length, V.Data, Data, std::minus<PBQPNum>()); + return *this; + } + + /// \brief Returns the index of the minimum value in this vector + unsigned minIndex() const { + assert(Length != 0 && Data != nullptr && "Invalid vector"); + return std::min_element(Data, Data + Length) - Data; + } + +private: + unsigned Length; + PBQPNum *Data; +}; + +class VectorComparator { +public: + bool operator()(const Vector &A, const Vector &B) { + if (A.Length < B.Length) + return true; + if (B.Length < A.Length) + return false; + char *AData = reinterpret_cast<char*>(A.Data); + char *BData = reinterpret_cast<char*>(B.Data); + return std::lexicographical_compare(AData, + AData + A.Length * sizeof(PBQPNum), + BData, + BData + A.Length * sizeof(PBQPNum)); + } }; /// \brief Output a textual representation of the given vector on the given /// output stream. template <typename OStream> -OStream& operator<<(OStream &os, const Vector &v) { - assert((v.getLength() != 0) && "Zero-length vector badness."); +OStream& operator<<(OStream &OS, const Vector &V) { + assert((V.getLength() != 0) && "Zero-length vector badness."); - os << "[ " << v[0]; - for (unsigned i = 1; i < v.getLength(); ++i) { - os << ", " << v[i]; - } - os << " ]"; + OS << "[ " << V[0]; + for (unsigned i = 1; i < V.getLength(); ++i) + OS << ", " << V[i]; + OS << " ]"; - return os; -} + return OS; +} /// \brief PBQP Matrix class class Matrix { - public: - - /// \brief Construct a PBQP Matrix with the given dimensions. - Matrix(unsigned rows, unsigned cols) : - rows(rows), cols(cols), data(new PBQPNum[rows * cols]) { - } - - /// \brief Construct a PBQP Matrix with the given dimensions and initial - /// value. - Matrix(unsigned rows, unsigned cols, PBQPNum initVal) : - rows(rows), cols(cols), data(new PBQPNum[rows * cols]) { - std::fill(data, data + (rows * cols), initVal); - } - - /// \brief Copy construct a PBQP matrix. - Matrix(const Matrix &m) : - rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) { - std::copy(m.data, m.data + (rows * cols), data); - } - - /// \brief Destroy this matrix, return its memory. - ~Matrix() { delete[] data; } - - /// \brief Assignment operator. - Matrix& operator=(const Matrix &m) { - delete[] data; - rows = m.rows; cols = m.cols; - data = new PBQPNum[rows * cols]; - std::copy(m.data, m.data + (rows * cols), data); - return *this; - } - - /// \brief Return the number of rows in this matrix. - unsigned getRows() const { return rows; } - - /// \brief Return the number of cols in this matrix. - unsigned getCols() const { return cols; } - - /// \brief Matrix element access. - PBQPNum* operator[](unsigned r) { - assert(r < rows && "Row out of bounds."); - return data + (r * cols); - } - - /// \brief Matrix element access. - const PBQPNum* operator[](unsigned r) const { - assert(r < rows && "Row out of bounds."); - return data + (r * cols); - } - - /// \brief Returns the given row as a vector. - Vector getRowAsVector(unsigned r) const { - Vector v(cols); - for (unsigned c = 0; c < cols; ++c) - v[c] = (*this)[r][c]; - return v; - } - - /// \brief Returns the given column as a vector. - Vector getColAsVector(unsigned c) const { - Vector v(rows); - for (unsigned r = 0; r < rows; ++r) - v[r] = (*this)[r][c]; - return v; - } - - /// \brief Reset the matrix to the given value. - Matrix& reset(PBQPNum val = 0) { - std::fill(data, data + (rows * cols), val); - return *this; - } - - /// \brief Set a single row of this matrix to the given value. - Matrix& setRow(unsigned r, PBQPNum val) { - assert(r < rows && "Row out of bounds."); - std::fill(data + (r * cols), data + ((r + 1) * cols), val); - return *this; - } - - /// \brief Set a single column of this matrix to the given value. - Matrix& setCol(unsigned c, PBQPNum val) { - assert(c < cols && "Column out of bounds."); - for (unsigned r = 0; r < rows; ++r) - (*this)[r][c] = val; - return *this; - } - - /// \brief Matrix transpose. - Matrix transpose() const { - Matrix m(cols, rows); - for (unsigned r = 0; r < rows; ++r) - for (unsigned c = 0; c < cols; ++c) - m[c][r] = (*this)[r][c]; - return m; - } - - /// \brief Returns the diagonal of the matrix as a vector. - /// - /// Matrix must be square. - Vector diagonalize() const { - assert(rows == cols && "Attempt to diagonalize non-square matrix."); - - Vector v(rows); - for (unsigned r = 0; r < rows; ++r) - v[r] = (*this)[r][r]; - return v; - } - - /// \brief Add the given matrix to this one. - Matrix& operator+=(const Matrix &m) { - assert(rows == m.rows && cols == m.cols && - "Matrix dimensions mismatch."); - std::transform(data, data + (rows * cols), m.data, data, - std::plus<PBQPNum>()); - return *this; - } - - /// \brief Returns the minimum of the given row - PBQPNum getRowMin(unsigned r) const { - assert(r < rows && "Row out of bounds"); - return *std::min_element(data + (r * cols), data + ((r + 1) * cols)); - } - - /// \brief Returns the minimum of the given column - PBQPNum getColMin(unsigned c) const { - PBQPNum minElem = (*this)[0][c]; - for (unsigned r = 1; r < rows; ++r) - if ((*this)[r][c] < minElem) minElem = (*this)[r][c]; - return minElem; - } - - /// \brief Subtracts the given scalar from the elements of the given row. - Matrix& subFromRow(unsigned r, PBQPNum val) { - assert(r < rows && "Row out of bounds"); - std::transform(data + (r * cols), data + ((r + 1) * cols), - data + (r * cols), - std::bind2nd(std::minus<PBQPNum>(), val)); - return *this; - } - - /// \brief Subtracts the given scalar from the elements of the given column. - Matrix& subFromCol(unsigned c, PBQPNum val) { - for (unsigned r = 0; r < rows; ++r) - (*this)[r][c] -= val; - return *this; - } - - /// \brief Returns true if this is a zero matrix. - bool isZero() const { - return find_if(data, data + (rows * cols), - std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) == - data + (rows * cols); - } - - private: - unsigned rows, cols; - PBQPNum *data; +private: + friend class MatrixComparator; +public: + + /// \brief Construct a PBQP Matrix with the given dimensions. + Matrix(unsigned Rows, unsigned Cols) : + Rows(Rows), Cols(Cols), Data(new PBQPNum[Rows * Cols]) { + } + + /// \brief Construct a PBQP Matrix with the given dimensions and initial + /// value. + Matrix(unsigned Rows, unsigned Cols, PBQPNum InitVal) + : Rows(Rows), Cols(Cols), Data(new PBQPNum[Rows * Cols]) { + std::fill(Data, Data + (Rows * Cols), InitVal); + } + + /// \brief Copy construct a PBQP matrix. + Matrix(const Matrix &M) + : Rows(M.Rows), Cols(M.Cols), Data(new PBQPNum[Rows * Cols]) { + std::copy(M.Data, M.Data + (Rows * Cols), Data); + } + + /// \brief Move construct a PBQP matrix. + Matrix(Matrix &&M) + : Rows(M.Rows), Cols(M.Cols), Data(M.Data) { + M.Rows = M.Cols = 0; + M.Data = nullptr; + } + + /// \brief Destroy this matrix, return its memory. + ~Matrix() { delete[] Data; } + + /// \brief Copy-assignment operator. + Matrix& operator=(const Matrix &M) { + delete[] Data; + Rows = M.Rows; Cols = M.Cols; + Data = new PBQPNum[Rows * Cols]; + std::copy(M.Data, M.Data + (Rows * Cols), Data); + return *this; + } + + /// \brief Move-assignment operator. + Matrix& operator=(Matrix &&M) { + delete[] Data; + Rows = M.Rows; + Cols = M.Cols; + Data = M.Data; + M.Rows = M.Cols = 0; + M.Data = nullptr; + return *this; + } + + /// \brief Comparison operator. + bool operator==(const Matrix &M) const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + if (Rows != M.Rows || Cols != M.Cols) + return false; + return std::equal(Data, Data + (Rows * Cols), M.Data); + } + + /// \brief Return the number of rows in this matrix. + unsigned getRows() const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + return Rows; + } + + /// \brief Return the number of cols in this matrix. + unsigned getCols() const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + return Cols; + } + + /// \brief Matrix element access. + PBQPNum* operator[](unsigned R) { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + assert(R < Rows && "Row out of bounds."); + return Data + (R * Cols); + } + + /// \brief Matrix element access. + const PBQPNum* operator[](unsigned R) const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + assert(R < Rows && "Row out of bounds."); + return Data + (R * Cols); + } + + /// \brief Returns the given row as a vector. + Vector getRowAsVector(unsigned R) const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + Vector V(Cols); + for (unsigned C = 0; C < Cols; ++C) + V[C] = (*this)[R][C]; + return V; + } + + /// \brief Returns the given column as a vector. + Vector getColAsVector(unsigned C) const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + Vector V(Rows); + for (unsigned R = 0; R < Rows; ++R) + V[R] = (*this)[R][C]; + return V; + } + + /// \brief Reset the matrix to the given value. + Matrix& reset(PBQPNum Val = 0) { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + std::fill(Data, Data + (Rows * Cols), Val); + return *this; + } + + /// \brief Set a single row of this matrix to the given value. + Matrix& setRow(unsigned R, PBQPNum Val) { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + assert(R < Rows && "Row out of bounds."); + std::fill(Data + (R * Cols), Data + ((R + 1) * Cols), Val); + return *this; + } + + /// \brief Set a single column of this matrix to the given value. + Matrix& setCol(unsigned C, PBQPNum Val) { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + assert(C < Cols && "Column out of bounds."); + for (unsigned R = 0; R < Rows; ++R) + (*this)[R][C] = Val; + return *this; + } + + /// \brief Matrix transpose. + Matrix transpose() const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + Matrix M(Cols, Rows); + for (unsigned r = 0; r < Rows; ++r) + for (unsigned c = 0; c < Cols; ++c) + M[c][r] = (*this)[r][c]; + return M; + } + + /// \brief Returns the diagonal of the matrix as a vector. + /// + /// Matrix must be square. + Vector diagonalize() const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + assert(Rows == Cols && "Attempt to diagonalize non-square matrix."); + Vector V(Rows); + for (unsigned r = 0; r < Rows; ++r) + V[r] = (*this)[r][r]; + return V; + } + + /// \brief Add the given matrix to this one. + Matrix& operator+=(const Matrix &M) { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + assert(Rows == M.Rows && Cols == M.Cols && + "Matrix dimensions mismatch."); + std::transform(Data, Data + (Rows * Cols), M.Data, Data, + std::plus<PBQPNum>()); + return *this; + } + + Matrix operator+(const Matrix &M) { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + Matrix Tmp(*this); + Tmp += M; + return Tmp; + } + + /// \brief Returns the minimum of the given row + PBQPNum getRowMin(unsigned R) const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + assert(R < Rows && "Row out of bounds"); + return *std::min_element(Data + (R * Cols), Data + ((R + 1) * Cols)); + } + + /// \brief Returns the minimum of the given column + PBQPNum getColMin(unsigned C) const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + PBQPNum MinElem = (*this)[0][C]; + for (unsigned R = 1; R < Rows; ++R) + if ((*this)[R][C] < MinElem) + MinElem = (*this)[R][C]; + return MinElem; + } + + /// \brief Subtracts the given scalar from the elements of the given row. + Matrix& subFromRow(unsigned R, PBQPNum Val) { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + assert(R < Rows && "Row out of bounds"); + std::transform(Data + (R * Cols), Data + ((R + 1) * Cols), + Data + (R * Cols), + std::bind2nd(std::minus<PBQPNum>(), Val)); + return *this; + } + + /// \brief Subtracts the given scalar from the elements of the given column. + Matrix& subFromCol(unsigned C, PBQPNum Val) { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + for (unsigned R = 0; R < Rows; ++R) + (*this)[R][C] -= Val; + return *this; + } + + /// \brief Returns true if this is a zero matrix. + bool isZero() const { + assert(Rows != 0 && Cols != 0 && Data != nullptr && "Invalid matrix"); + return find_if(Data, Data + (Rows * Cols), + std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) == + Data + (Rows * Cols); + } + +private: + unsigned Rows, Cols; + PBQPNum *Data; +}; + +class MatrixComparator { +public: + bool operator()(const Matrix &A, const Matrix &B) { + if (A.Rows < B.Rows) + return true; + if (B.Rows < A.Rows) + return false; + if (A.Cols < B.Cols) + return true; + if (B.Cols < A.Cols) + return false; + char *AData = reinterpret_cast<char*>(A.Data); + char *BData = reinterpret_cast<char*>(B.Data); + return std::lexicographical_compare( + AData, AData + (A.Rows * A.Cols * sizeof(PBQPNum)), + BData, BData + (A.Rows * A.Cols * sizeof(PBQPNum))); + } }; /// \brief Output a textual representation of the given matrix on the given /// output stream. template <typename OStream> -OStream& operator<<(OStream &os, const Matrix &m) { - - assert((m.getRows() != 0) && "Zero-row matrix badness."); +OStream& operator<<(OStream &OS, const Matrix &M) { + assert((M.getRows() != 0) && "Zero-row matrix badness."); + for (unsigned i = 0; i < M.getRows(); ++i) + OS << M.getRowAsVector(i); + return OS; +} - for (unsigned i = 0; i < m.getRows(); ++i) { - os << m.getRowAsVector(i); - } +template <typename Metadata> +class MDVector : public Vector { +public: + MDVector(const Vector &v) : Vector(v), md(*this) { } + MDVector(Vector &&v) : Vector(std::move(v)), md(*this) { } + const Metadata& getMetadata() const { return md; } +private: + Metadata md; +}; - return os; -} +template <typename Metadata> +class MDMatrix : public Matrix { +public: + MDMatrix(const Matrix &m) : Matrix(m), md(*this) { } + MDMatrix(Matrix &&m) : Matrix(std::move(m)), md(*this) { } + const Metadata& getMetadata() const { return md; } +private: + Metadata md; +}; } diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h new file mode 100644 index 000000000000..a55a06033c4e --- /dev/null +++ b/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -0,0 +1,191 @@ +//===----------- ReductionRules.h - Reduction Rules -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Reduction Rules. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REDUCTIONRULES_H +#define LLVM_REDUCTIONRULES_H + +#include "Graph.h" +#include "Math.h" +#include "Solution.h" + +namespace PBQP { + + /// \brief Reduce a node of degree one. + /// + /// Propagate costs from the given node, which must be of degree one, to its + /// neighbor. Notify the problem domain. + template <typename GraphT> + void applyR1(GraphT &G, typename GraphT::NodeId NId) { + typedef typename GraphT::NodeId NodeId; + typedef typename GraphT::EdgeId EdgeId; + typedef typename GraphT::Vector Vector; + typedef typename GraphT::Matrix Matrix; + typedef typename GraphT::RawVector RawVector; + + assert(G.getNodeDegree(NId) == 1 && + "R1 applied to node with degree != 1."); + + EdgeId EId = *G.adjEdgeIds(NId).begin(); + NodeId MId = G.getEdgeOtherNodeId(EId, NId); + + const Matrix &ECosts = G.getEdgeCosts(EId); + const Vector &XCosts = G.getNodeCosts(NId); + RawVector YCosts = G.getNodeCosts(MId); + + // Duplicate a little to avoid transposing matrices. + if (NId == G.getEdgeNode1Id(EId)) { + for (unsigned j = 0; j < YCosts.getLength(); ++j) { + PBQPNum Min = ECosts[0][j] + XCosts[0]; + for (unsigned i = 1; i < XCosts.getLength(); ++i) { + PBQPNum C = ECosts[i][j] + XCosts[i]; + if (C < Min) + Min = C; + } + YCosts[j] += Min; + } + } else { + for (unsigned i = 0; i < YCosts.getLength(); ++i) { + PBQPNum Min = ECosts[i][0] + XCosts[0]; + for (unsigned j = 1; j < XCosts.getLength(); ++j) { + PBQPNum C = ECosts[i][j] + XCosts[j]; + if (C < Min) + Min = C; + } + YCosts[i] += Min; + } + } + G.setNodeCosts(MId, YCosts); + G.disconnectEdge(EId, MId); + } + + template <typename GraphT> + void applyR2(GraphT &G, typename GraphT::NodeId NId) { + typedef typename GraphT::NodeId NodeId; + typedef typename GraphT::EdgeId EdgeId; + typedef typename GraphT::Vector Vector; + typedef typename GraphT::Matrix Matrix; + typedef typename GraphT::RawMatrix RawMatrix; + + assert(G.getNodeDegree(NId) == 2 && + "R2 applied to node with degree != 2."); + + const Vector &XCosts = G.getNodeCosts(NId); + + typename GraphT::AdjEdgeItr AEItr = G.adjEdgeIds(NId).begin(); + EdgeId YXEId = *AEItr, + ZXEId = *(++AEItr); + + NodeId YNId = G.getEdgeOtherNodeId(YXEId, NId), + ZNId = G.getEdgeOtherNodeId(ZXEId, NId); + + bool FlipEdge1 = (G.getEdgeNode1Id(YXEId) == NId), + FlipEdge2 = (G.getEdgeNode1Id(ZXEId) == NId); + + const Matrix *YXECosts = FlipEdge1 ? + new Matrix(G.getEdgeCosts(YXEId).transpose()) : + &G.getEdgeCosts(YXEId); + + const Matrix *ZXECosts = FlipEdge2 ? + new Matrix(G.getEdgeCosts(ZXEId).transpose()) : + &G.getEdgeCosts(ZXEId); + + unsigned XLen = XCosts.getLength(), + YLen = YXECosts->getRows(), + ZLen = ZXECosts->getRows(); + + RawMatrix Delta(YLen, ZLen); + + for (unsigned i = 0; i < YLen; ++i) { + for (unsigned j = 0; j < ZLen; ++j) { + PBQPNum Min = (*YXECosts)[i][0] + (*ZXECosts)[j][0] + XCosts[0]; + for (unsigned k = 1; k < XLen; ++k) { + PBQPNum C = (*YXECosts)[i][k] + (*ZXECosts)[j][k] + XCosts[k]; + if (C < Min) { + Min = C; + } + } + Delta[i][j] = Min; + } + } + + if (FlipEdge1) + delete YXECosts; + + if (FlipEdge2) + delete ZXECosts; + + EdgeId YZEId = G.findEdge(YNId, ZNId); + + if (YZEId == G.invalidEdgeId()) { + YZEId = G.addEdge(YNId, ZNId, Delta); + } else { + const Matrix &YZECosts = G.getEdgeCosts(YZEId); + if (YNId == G.getEdgeNode1Id(YZEId)) { + G.setEdgeCosts(YZEId, Delta + YZECosts); + } else { + G.setEdgeCosts(YZEId, Delta.transpose() + YZECosts); + } + } + + G.disconnectEdge(YXEId, YNId); + G.disconnectEdge(ZXEId, ZNId); + + // TODO: Try to normalize newly added/modified edge. + } + + + // \brief Find a solution to a fully reduced graph by backpropagation. + // + // Given a graph and a reduction order, pop each node from the reduction + // order and greedily compute a minimum solution based on the node costs, and + // the dependent costs due to previously solved nodes. + // + // Note - This does not return the graph to its original (pre-reduction) + // state: the existing solvers destructively alter the node and edge + // costs. Given that, the backpropagate function doesn't attempt to + // replace the edges either, but leaves the graph in its reduced + // state. + template <typename GraphT, typename StackT> + Solution backpropagate(GraphT& G, StackT stack) { + typedef GraphBase::NodeId NodeId; + typedef typename GraphT::Matrix Matrix; + typedef typename GraphT::RawVector RawVector; + + Solution s; + + while (!stack.empty()) { + NodeId NId = stack.back(); + stack.pop_back(); + + RawVector v = G.getNodeCosts(NId); + + for (auto EId : G.adjEdgeIds(NId)) { + const Matrix& edgeCosts = G.getEdgeCosts(EId); + if (NId == G.getEdgeNode1Id(EId)) { + NodeId mId = G.getEdgeNode2Id(EId); + v += edgeCosts.getColAsVector(s.getSelection(mId)); + } else { + NodeId mId = G.getEdgeNode1Id(EId); + v += edgeCosts.getRowAsVector(s.getSelection(mId)); + } + } + + s.setSelection(NId, v.minIndex()); + } + + return s; + } + +} + +#endif // LLVM_REDUCTIONRULES_H diff --git a/include/llvm/CodeGen/PBQP/RegAllocSolver.h b/include/llvm/CodeGen/PBQP/RegAllocSolver.h new file mode 100644 index 000000000000..977c34843bbd --- /dev/null +++ b/include/llvm/CodeGen/PBQP/RegAllocSolver.h @@ -0,0 +1,359 @@ +//===-- RegAllocSolver.h - Heuristic PBQP Solver for reg alloc --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Heuristic PBQP solver for register allocation problems. This solver uses a +// graph reduction approach. Nodes of degree 0, 1 and 2 are eliminated with +// optimality-preserving rules (see ReductionRules.h). When no low-degree (<3) +// nodes are present, a heuristic derived from Brigg's graph coloring approach +// is used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H +#define LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H + +#include "CostAllocator.h" +#include "Graph.h" +#include "ReductionRules.h" +#include "Solution.h" +#include "llvm/Support/ErrorHandling.h" +#include <limits> +#include <vector> + +namespace PBQP { + + namespace RegAlloc { + + /// \brief Metadata to speed allocatability test. + /// + /// Keeps track of the number of infinities in each row and column. + class MatrixMetadata { + private: + MatrixMetadata(const MatrixMetadata&); + void operator=(const MatrixMetadata&); + public: + MatrixMetadata(const PBQP::Matrix& M) + : WorstRow(0), WorstCol(0), + UnsafeRows(new bool[M.getRows() - 1]()), + UnsafeCols(new bool[M.getCols() - 1]()) { + + unsigned* ColCounts = new unsigned[M.getCols() - 1](); + + for (unsigned i = 1; i < M.getRows(); ++i) { + unsigned RowCount = 0; + for (unsigned j = 1; j < M.getCols(); ++j) { + if (M[i][j] == std::numeric_limits<PBQP::PBQPNum>::infinity()) { + ++RowCount; + ++ColCounts[j - 1]; + UnsafeRows[i - 1] = true; + UnsafeCols[j - 1] = true; + } + } + WorstRow = std::max(WorstRow, RowCount); + } + unsigned WorstColCountForCurRow = + *std::max_element(ColCounts, ColCounts + M.getCols() - 1); + WorstCol = std::max(WorstCol, WorstColCountForCurRow); + delete[] ColCounts; + } + + ~MatrixMetadata() { + delete[] UnsafeRows; + delete[] UnsafeCols; + } + + unsigned getWorstRow() const { return WorstRow; } + unsigned getWorstCol() const { return WorstCol; } + const bool* getUnsafeRows() const { return UnsafeRows; } + const bool* getUnsafeCols() const { return UnsafeCols; } + + private: + unsigned WorstRow, WorstCol; + bool* UnsafeRows; + bool* UnsafeCols; + }; + + class NodeMetadata { + public: + typedef enum { Unprocessed, + OptimallyReducible, + ConservativelyAllocatable, + NotProvablyAllocatable } ReductionState; + + NodeMetadata() : RS(Unprocessed), DeniedOpts(0), OptUnsafeEdges(nullptr){} + ~NodeMetadata() { delete[] OptUnsafeEdges; } + + void setup(const Vector& Costs) { + NumOpts = Costs.getLength() - 1; + OptUnsafeEdges = new unsigned[NumOpts](); + } + + ReductionState getReductionState() const { return RS; } + void setReductionState(ReductionState RS) { this->RS = RS; } + + void handleAddEdge(const MatrixMetadata& MD, bool Transpose) { + DeniedOpts += Transpose ? MD.getWorstCol() : MD.getWorstRow(); + const bool* UnsafeOpts = + Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); + for (unsigned i = 0; i < NumOpts; ++i) + OptUnsafeEdges[i] += UnsafeOpts[i]; + } + + void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) { + DeniedOpts -= Transpose ? MD.getWorstCol() : MD.getWorstRow(); + const bool* UnsafeOpts = + Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); + for (unsigned i = 0; i < NumOpts; ++i) + OptUnsafeEdges[i] -= UnsafeOpts[i]; + } + + bool isConservativelyAllocatable() const { + return (DeniedOpts < NumOpts) || + (std::find(OptUnsafeEdges, OptUnsafeEdges + NumOpts, 0) != + OptUnsafeEdges + NumOpts); + } + + private: + ReductionState RS; + unsigned NumOpts; + unsigned DeniedOpts; + unsigned* OptUnsafeEdges; + }; + + class RegAllocSolverImpl { + private: + typedef PBQP::MDMatrix<MatrixMetadata> RAMatrix; + public: + typedef PBQP::Vector RawVector; + typedef PBQP::Matrix RawMatrix; + typedef PBQP::Vector Vector; + typedef RAMatrix Matrix; + typedef PBQP::PoolCostAllocator< + Vector, PBQP::VectorComparator, + Matrix, PBQP::MatrixComparator> CostAllocator; + + typedef PBQP::GraphBase::NodeId NodeId; + typedef PBQP::GraphBase::EdgeId EdgeId; + + typedef RegAlloc::NodeMetadata NodeMetadata; + + struct EdgeMetadata { }; + + typedef PBQP::Graph<RegAllocSolverImpl> Graph; + + RegAllocSolverImpl(Graph &G) : G(G) {} + + Solution solve() { + G.setSolver(*this); + Solution S; + setup(); + S = backpropagate(G, reduce()); + G.unsetSolver(); + return S; + } + + void handleAddNode(NodeId NId) { + G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); + } + void handleRemoveNode(NodeId NId) {} + void handleSetNodeCosts(NodeId NId, const Vector& newCosts) {} + + void handleAddEdge(EdgeId EId) { + handleReconnectEdge(EId, G.getEdgeNode1Id(EId)); + handleReconnectEdge(EId, G.getEdgeNode2Id(EId)); + } + + void handleRemoveEdge(EdgeId EId) { + handleDisconnectEdge(EId, G.getEdgeNode1Id(EId)); + handleDisconnectEdge(EId, G.getEdgeNode2Id(EId)); + } + + void handleDisconnectEdge(EdgeId EId, NodeId NId) { + NodeMetadata& NMd = G.getNodeMetadata(NId); + const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); + NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId)); + if (G.getNodeDegree(NId) == 3) { + // This node is becoming optimally reducible. + moveToOptimallyReducibleNodes(NId); + } else if (NMd.getReductionState() == + NodeMetadata::NotProvablyAllocatable && + NMd.isConservativelyAllocatable()) { + // This node just became conservatively allocatable. + moveToConservativelyAllocatableNodes(NId); + } + } + + void handleReconnectEdge(EdgeId EId, NodeId NId) { + NodeMetadata& NMd = G.getNodeMetadata(NId); + const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); + NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId)); + } + + void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) { + handleRemoveEdge(EId); + + NodeId N1Id = G.getEdgeNode1Id(EId); + NodeId N2Id = G.getEdgeNode2Id(EId); + NodeMetadata& N1Md = G.getNodeMetadata(N1Id); + NodeMetadata& N2Md = G.getNodeMetadata(N2Id); + const MatrixMetadata& MMd = NewCosts.getMetadata(); + N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId)); + N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId)); + } + + private: + + void removeFromCurrentSet(NodeId NId) { + switch (G.getNodeMetadata(NId).getReductionState()) { + case NodeMetadata::Unprocessed: break; + case NodeMetadata::OptimallyReducible: + assert(OptimallyReducibleNodes.find(NId) != + OptimallyReducibleNodes.end() && + "Node not in optimally reducible set."); + OptimallyReducibleNodes.erase(NId); + break; + case NodeMetadata::ConservativelyAllocatable: + assert(ConservativelyAllocatableNodes.find(NId) != + ConservativelyAllocatableNodes.end() && + "Node not in conservatively allocatable set."); + ConservativelyAllocatableNodes.erase(NId); + break; + case NodeMetadata::NotProvablyAllocatable: + assert(NotProvablyAllocatableNodes.find(NId) != + NotProvablyAllocatableNodes.end() && + "Node not in not-provably-allocatable set."); + NotProvablyAllocatableNodes.erase(NId); + break; + } + } + + void moveToOptimallyReducibleNodes(NodeId NId) { + removeFromCurrentSet(NId); + OptimallyReducibleNodes.insert(NId); + G.getNodeMetadata(NId).setReductionState( + NodeMetadata::OptimallyReducible); + } + + void moveToConservativelyAllocatableNodes(NodeId NId) { + removeFromCurrentSet(NId); + ConservativelyAllocatableNodes.insert(NId); + G.getNodeMetadata(NId).setReductionState( + NodeMetadata::ConservativelyAllocatable); + } + + void moveToNotProvablyAllocatableNodes(NodeId NId) { + removeFromCurrentSet(NId); + NotProvablyAllocatableNodes.insert(NId); + G.getNodeMetadata(NId).setReductionState( + NodeMetadata::NotProvablyAllocatable); + } + + void setup() { + // Set up worklists. + for (auto NId : G.nodeIds()) { + if (G.getNodeDegree(NId) < 3) + moveToOptimallyReducibleNodes(NId); + else if (G.getNodeMetadata(NId).isConservativelyAllocatable()) + moveToConservativelyAllocatableNodes(NId); + else + moveToNotProvablyAllocatableNodes(NId); + } + } + + // Compute a reduction order for the graph by iteratively applying PBQP + // reduction rules. Locally optimal rules are applied whenever possible (R0, + // R1, R2). If no locally-optimal rules apply then any conservatively + // allocatable node is reduced. Finally, if no conservatively allocatable + // node exists then the node with the lowest spill-cost:degree ratio is + // selected. + std::vector<GraphBase::NodeId> reduce() { + assert(!G.empty() && "Cannot reduce empty graph."); + + typedef GraphBase::NodeId NodeId; + std::vector<NodeId> NodeStack; + + // Consume worklists. + while (true) { + if (!OptimallyReducibleNodes.empty()) { + NodeSet::iterator NItr = OptimallyReducibleNodes.begin(); + NodeId NId = *NItr; + OptimallyReducibleNodes.erase(NItr); + NodeStack.push_back(NId); + switch (G.getNodeDegree(NId)) { + case 0: + break; + case 1: + applyR1(G, NId); + break; + case 2: + applyR2(G, NId); + break; + default: llvm_unreachable("Not an optimally reducible node."); + } + } else if (!ConservativelyAllocatableNodes.empty()) { + // Conservatively allocatable nodes will never spill. For now just + // take the first node in the set and push it on the stack. When we + // start optimizing more heavily for register preferencing, it may + // would be better to push nodes with lower 'expected' or worst-case + // register costs first (since early nodes are the most + // constrained). + NodeSet::iterator NItr = ConservativelyAllocatableNodes.begin(); + NodeId NId = *NItr; + ConservativelyAllocatableNodes.erase(NItr); + NodeStack.push_back(NId); + G.disconnectAllNeighborsFromNode(NId); + + } else if (!NotProvablyAllocatableNodes.empty()) { + NodeSet::iterator NItr = + std::min_element(NotProvablyAllocatableNodes.begin(), + NotProvablyAllocatableNodes.end(), + SpillCostComparator(G)); + NodeId NId = *NItr; + NotProvablyAllocatableNodes.erase(NItr); + NodeStack.push_back(NId); + G.disconnectAllNeighborsFromNode(NId); + } else + break; + } + + return NodeStack; + } + + class SpillCostComparator { + public: + SpillCostComparator(const Graph& G) : G(G) {} + bool operator()(NodeId N1Id, NodeId N2Id) { + PBQPNum N1SC = G.getNodeCosts(N1Id)[0] / G.getNodeDegree(N1Id); + PBQPNum N2SC = G.getNodeCosts(N2Id)[0] / G.getNodeDegree(N2Id); + return N1SC < N2SC; + } + private: + const Graph& G; + }; + + Graph& G; + typedef std::set<NodeId> NodeSet; + NodeSet OptimallyReducibleNodes; + NodeSet ConservativelyAllocatableNodes; + NodeSet NotProvablyAllocatableNodes; + }; + + typedef Graph<RegAllocSolverImpl> Graph; + + inline Solution solve(Graph& G) { + if (G.empty()) + return Solution(); + RegAllocSolverImpl RegAllocSolver(G); + return RegAllocSolver.solve(); + } + + } +} + +#endif // LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h index 091805d00f3e..3556e60f3967 100644 --- a/include/llvm/CodeGen/PBQP/Solution.h +++ b/include/llvm/CodeGen/PBQP/Solution.h @@ -26,7 +26,7 @@ namespace PBQP { class Solution { private: - typedef std::map<Graph::NodeId, unsigned> SelectionsMap; + typedef std::map<GraphBase::NodeId, unsigned> SelectionsMap; SelectionsMap selections; unsigned r0Reductions, r1Reductions, r2Reductions, rNReductions; @@ -72,14 +72,14 @@ namespace PBQP { /// \brief Set the selection for a given node. /// @param nodeId Node id. /// @param selection Selection for nodeId. - void setSelection(Graph::NodeId nodeId, unsigned selection) { + void setSelection(GraphBase::NodeId nodeId, unsigned selection) { selections[nodeId] = selection; } /// \brief Get a node's selection. /// @param nodeId Node id. /// @return The selection for nodeId; - unsigned getSelection(Graph::NodeId nodeId) const { + unsigned getSelection(GraphBase::NodeId nodeId) const { SelectionsMap::const_iterator sItr = selections.find(nodeId); assert(sItr != selections.end() && "No selection for node."); return sItr->second; diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index ae4a2fa0bf83..87f55e8572fe 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -59,7 +59,7 @@ class IdentifyingPassPtr { }; bool IsInstance; public: - IdentifyingPassPtr() : P(0), IsInstance(false) {} + IdentifyingPassPtr() : P(nullptr), IsInstance(false) {} IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr), IsInstance(false) {} IdentifyingPassPtr(Pass *InstancePtr) : P(InstancePtr), IsInstance(true) {} @@ -133,10 +133,6 @@ public: return *static_cast<TMC*>(TM); } - const TargetLowering *getTargetLowering() const { - return TM->getTargetLowering(); - } - // void setInitialized() { Initialized = true; } @@ -151,7 +147,7 @@ public: void setStartStopPasses(AnalysisID Start, AnalysisID Stop) { StartAfter = Start; StopAfter = Stop; - Started = (StartAfter == 0); + Started = (StartAfter == nullptr); } void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); } @@ -207,9 +203,9 @@ public: /// Fully developed targets will not generally override this. virtual void addMachinePasses(); - /// createTargetScheduler - Create an instance of ScheduleDAGInstrs to be run - /// within the standard MachineScheduler pass for this function and target at - /// the current optimization level. + /// Create an instance of ScheduleDAGInstrs to be run within the standard + /// MachineScheduler pass for this function and target at the current + /// optimization level. /// /// This can also be used to plug a new MachineSchedStrategy into an instance /// of the standard ScheduleDAGMI: @@ -218,7 +214,14 @@ public: /// Return NULL to select the default (generic) machine scheduler. virtual ScheduleDAGInstrs * createMachineScheduler(MachineSchedContext *C) const { - return 0; + return nullptr; + } + + /// Similar to createMachineScheduler but used when postRA machine scheduling + /// is enabled. + virtual ScheduleDAGInstrs * + createPostMachineScheduler(MachineSchedContext *C) const { + return nullptr; } protected: @@ -342,6 +345,8 @@ protected: /// List of target independent CodeGen pass IDs. namespace llvm { + FunctionPass *createAtomicExpandLoadLinkedPass(const TargetMachine *TM); + /// \brief Create a basic TargetTransformInfo analysis pass. /// /// This pass implements the target transform info analysis using the target @@ -363,12 +368,22 @@ namespace llvm { createMachineFunctionPrinterPass(raw_ostream &OS, const std::string &Banner =""); + /// createCodeGenPreparePass - Transform the code to expose more pattern + /// matching during instruction selection. + FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr); + + /// AtomicExpandLoadLinkedID -- FIXME + extern char &AtomicExpandLoadLinkedID; + /// MachineLoopInfo - This pass is a loop analysis pass. extern char &MachineLoopInfoID; /// MachineDominators - This pass is a machine dominators analysis pass. extern char &MachineDominatorsID; +/// MachineDominanaceFrontier - This pass is a machine dominators analysis pass. + extern char &MachineDominanceFrontierID; + /// EdgeBundles analysis - Bundle machine CFG edges. extern char &EdgeBundlesID; @@ -403,6 +418,9 @@ namespace llvm { /// MachineScheduler - This pass schedules machine instructions. extern char &MachineSchedulerID; + /// PostMachineScheduler - This pass schedules machine instructions postRA. + extern char &PostMachineSchedulerID; + /// SpillPlacement analysis. Suggest optimal placement of spill code between /// basic blocks. extern char &SpillPlacementID; @@ -533,7 +551,7 @@ namespace llvm { /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. /// - FunctionPass *createMachineVerifierPass(const char *Banner = 0); + FunctionPass *createMachineVerifierPass(const char *Banner = nullptr); /// createDwarfEHPass - This pass mulches exception handling code into a form /// adapted to code generation. Required if using dwarf exception handling. @@ -568,6 +586,30 @@ namespace llvm { /// bundles (created earlier, e.g. during pre-RA scheduling). extern char &FinalizeMachineBundlesID; + /// StackMapLiveness - This pass analyses the register live-out set of + /// stackmap/patchpoint intrinsics and attaches the calculated information to + /// the intrinsic for later emission to the StackMap. + extern char &StackMapLivenessID; + + /// createJumpInstrTables - This pass creates jump-instruction tables. + ModulePass *createJumpInstrTablesPass(); } // End llvm namespace +/// This initializer registers TargetMachine constructor, so the pass being +/// initialized can use target dependent interfaces. Please do not move this +/// macro to be together with INITIALIZE_PASS, which is a complete target +/// independent initializer, and we don't want to make libScalarOpts depend +/// on libCodeGen. +#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \ + static void* initialize##passName##PassOnce(PassRegistry &Registry) { \ + PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis, \ + PassInfo::TargetMachineCtor_t(callTargetMachineCtor< passName >)); \ + Registry.registerPass(*PI, true); \ + return PI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } + #endif diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h index 705086c22b45..cc3e25aeb89f 100644 --- a/include/llvm/CodeGen/PseudoSourceValue.h +++ b/include/llvm/CodeGen/PseudoSourceValue.h @@ -18,21 +18,32 @@ namespace llvm { class MachineFrameInfo; + class MachineMemOperand; class raw_ostream; + raw_ostream &operator<<(raw_ostream &OS, const MachineMemOperand &MMO); + /// PseudoSourceValue - Special value supplied for machine level alias /// analysis. It indicates that a memory access references the functions /// stack frame (e.g., a spill slot), below the stack frame (e.g., argument /// space), or constant pool. - class PseudoSourceValue : public Value { + class PseudoSourceValue { private: + friend raw_ostream &llvm::operator<<(raw_ostream &OS, + const MachineMemOperand &MMO); + /// printCustom - Implement printing for PseudoSourceValue. This is called /// from Value::print or Value's operator<<. /// virtual void printCustom(raw_ostream &O) const; public: - explicit PseudoSourceValue(enum ValueTy Subclass = PseudoSourceValueVal); + /// isFixed - Whether this is a FixedStackPseudoSourceValue. + bool isFixed; + + explicit PseudoSourceValue(bool isFixed = false); + + virtual ~PseudoSourceValue(); /// isConstant - Test whether the memory pointed to by this /// PseudoSourceValue has a constant value. @@ -47,14 +58,6 @@ namespace llvm { /// PseudoSourceValue can ever alias an LLVM IR Value. virtual bool mayAlias(const MachineFrameInfo *) const; - /// classof - Methods for support type inquiry through isa, cast, and - /// dyn_cast: - /// - static inline bool classof(const Value *V) { - return V->getValueID() == PseudoSourceValueVal || - V->getValueID() == FixedStackPseudoSourceValueVal; - } - /// A pseudo source value referencing a fixed stack frame entry, /// e.g., a spill slot. static const PseudoSourceValue *getFixedStack(int FI); @@ -84,22 +87,22 @@ namespace llvm { const int FI; public: explicit FixedStackPseudoSourceValue(int fi) : - PseudoSourceValue(FixedStackPseudoSourceValueVal), FI(fi) {} + PseudoSourceValue(true), FI(fi) {} /// classof - Methods for support type inquiry through isa, cast, and /// dyn_cast: /// - static inline bool classof(const Value *V) { - return V->getValueID() == FixedStackPseudoSourceValueVal; + static inline bool classof(const PseudoSourceValue *V) { + return V->isFixed == true; } - virtual bool isConstant(const MachineFrameInfo *MFI) const; + bool isConstant(const MachineFrameInfo *MFI) const override; - virtual bool isAliased(const MachineFrameInfo *MFI) const; + bool isAliased(const MachineFrameInfo *MFI) const override; - virtual bool mayAlias(const MachineFrameInfo *) const; + bool mayAlias(const MachineFrameInfo *) const override; - virtual void printCustom(raw_ostream &OS) const; + void printCustom(raw_ostream &OS) const override; int getFrameIndex() const { return FI; } }; diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 7472e5a62d6b..441b0f084e69 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -17,9 +17,9 @@ #define LLVM_CODEGEN_REGALLOCPBQP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/PBQP/Graph.h" -#include "llvm/CodeGen/PBQP/Solution.h" +#include "llvm/CodeGen/PBQP/RegAllocSolver.h" #include <map> #include <set> @@ -29,30 +29,30 @@ namespace llvm { class MachineBlockFrequencyInfo; class MachineFunction; class TargetRegisterInfo; - template<class T> class OwningPtr; + + typedef PBQP::RegAlloc::Graph PBQPRAGraph; /// This class wraps up a PBQP instance representing a register allocation /// problem, plus the structures necessary to map back from the PBQP solution /// to a register allocation solution. (i.e. The PBQP-node <--> vreg map, /// and the PBQP option <--> storage location map). - class PBQPRAProblem { public: typedef SmallVector<unsigned, 16> AllowedSet; - PBQP::Graph& getGraph() { return graph; } + PBQPRAGraph& getGraph() { return graph; } - const PBQP::Graph& getGraph() const { return graph; } + const PBQPRAGraph& getGraph() const { return graph; } /// Record the mapping between the given virtual register and PBQP node, /// and the set of allowed pregs for the vreg. /// /// If you are extending /// PBQPBuilder you are unlikely to need this: Nodes and options for all - /// vregs will already have been set up for you by the base class. + /// vregs will already have been set up for you by the base class. template <typename AllowedRegsItr> - void recordVReg(unsigned vreg, PBQP::Graph::NodeId nodeId, + void recordVReg(unsigned vreg, PBQPRAGraph::NodeId nodeId, AllowedRegsItr arBegin, AllowedRegsItr arEnd) { assert(node2VReg.find(nodeId) == node2VReg.end() && "Re-mapping node."); assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg."); @@ -64,10 +64,10 @@ namespace llvm { } /// Get the virtual register corresponding to the given PBQP node. - unsigned getVRegForNode(PBQP::Graph::NodeId nodeId) const; + unsigned getVRegForNode(PBQPRAGraph::NodeId nodeId) const; /// Get the PBQP node corresponding to the given virtual register. - PBQP::Graph::NodeId getNodeForVReg(unsigned vreg) const; + PBQPRAGraph::NodeId getNodeForVReg(unsigned vreg) const; /// Returns true if the given PBQP option represents a physical register, /// false otherwise. @@ -92,16 +92,16 @@ namespace llvm { private: - typedef std::map<PBQP::Graph::NodeId, unsigned> Node2VReg; - typedef DenseMap<unsigned, PBQP::Graph::NodeId> VReg2Node; + typedef std::map<PBQPRAGraph::NodeId, unsigned> Node2VReg; + typedef DenseMap<unsigned, PBQPRAGraph::NodeId> VReg2Node; typedef DenseMap<unsigned, AllowedSet> AllowedSetMap; - PBQP::Graph graph; + PBQPRAGraph graph; Node2VReg node2VReg; VReg2Node vreg2Node; AllowedSetMap allowedSets; - + }; /// Builds PBQP instances to represent register allocation problems. Includes @@ -114,7 +114,7 @@ namespace llvm { public: typedef std::set<unsigned> RegSet; - + /// Default constructor. PBQPBuilder() {} @@ -139,12 +139,12 @@ namespace llvm { /// Extended builder which adds coalescing constraints to a problem. class PBQPBuilderWithCoalescing : public PBQPBuilder { public: - + /// Build a PBQP instance to represent the register allocation problem for /// the given MachineFunction. - virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineBlockFrequencyInfo *mbfi, - const RegSet &vregs); + PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, + const MachineBlockFrequencyInfo *mbfi, + const RegSet &vregs) override; private: @@ -157,8 +157,9 @@ namespace llvm { PBQP::PBQPNum benefit); }; - FunctionPass* createPBQPRegisterAllocator(OwningPtr<PBQPBuilder> &builder, - char *customPassID=0); + FunctionPass * + createPBQPRegisterAllocator(std::unique_ptr<PBQPBuilder> builder, + char *customPassID = nullptr); } #endif /* LLVM_CODEGEN_REGALLOCPBQP_H */ diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h index 9ec12bdea0ad..d784dfbda7ec 100644 --- a/include/llvm/CodeGen/RegisterClassInfo.h +++ b/include/llvm/CodeGen/RegisterClassInfo.h @@ -19,7 +19,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/Target/TargetRegisterInfo.h" namespace llvm { @@ -31,7 +30,7 @@ class RegisterClassInfo { bool ProperSubClass; uint8_t MinCost; uint16_t LastCostChange; - OwningArrayPtr<MCPhysReg> Order; + std::unique_ptr<MCPhysReg[]> Order; RCInfo() : Tag(0), NumRegs(0), ProperSubClass(false), MinCost(0), @@ -43,7 +42,7 @@ class RegisterClassInfo { }; // Brief cached information for each register class. - OwningArrayPtr<RCInfo> RegClass; + std::unique_ptr<RCInfo[]> RegClass; // Tag changes whenever cached information needs to be recomputed. An RCInfo // entry is valid when its tag matches. @@ -54,7 +53,7 @@ class RegisterClassInfo { // Callee saved registers of last MF. Assumed to be valid until the next // runOnFunction() call. - const uint16_t *CalleeSaved; + const MCPhysReg *CalleeSaved; // Map register number to CalleeSaved index + 1; SmallVector<uint8_t, 4> CSRNum; @@ -62,7 +61,7 @@ class RegisterClassInfo { // Reserved registers in the current MF. BitVector Reserved; - OwningArrayPtr<unsigned> PSetLimits; + std::unique_ptr<unsigned[]> PSetLimits; // Compute all information about RC. void compute(const TargetRegisterClass *RC) const; diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index a801d1d1eee9..cc9e00055146 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -158,7 +158,7 @@ class PressureDiffs { unsigned Size; unsigned Max; public: - PressureDiffs(): PDiffArray(0), Size(0), Max(0) {} + PressureDiffs(): PDiffArray(nullptr), Size(0), Max(0) {} ~PressureDiffs() { free(PDiffArray); } void clear() { Size = 0; } @@ -285,12 +285,12 @@ class RegPressureTracker { public: RegPressureTracker(IntervalPressure &rp) : - MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true), - TrackUntiedDefs(false) {} + MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp), + RequireIntervals(true), TrackUntiedDefs(false) {} RegPressureTracker(RegionPressure &rp) : - MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false), - TrackUntiedDefs(false) {} + MF(nullptr), TRI(nullptr), RCI(nullptr), LIS(nullptr), MBB(nullptr), P(rp), + RequireIntervals(false), TrackUntiedDefs(false) {} void reset(); @@ -318,7 +318,8 @@ public: SlotIndex getCurrSlot() const; /// Recede across the previous instruction. - bool recede(SmallVectorImpl<unsigned> *LiveUses = 0, PressureDiff *PDiff = 0); + bool recede(SmallVectorImpl<unsigned> *LiveUses = nullptr, + PressureDiff *PDiff = nullptr); /// Advance across the current instruction. bool advance(); @@ -393,7 +394,7 @@ public: MaxPressureLimit); assert(isBottomClosed() && "Uninitialized pressure tracker"); - return getMaxUpwardPressureDelta(MI, 0, Delta, CriticalPSets, + return getMaxUpwardPressureDelta(MI, nullptr, Delta, CriticalPSets, MaxPressureLimit); } @@ -433,10 +434,8 @@ protected: void bumpDownwardPressure(const MachineInstr *MI); }; -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dumpRegSetPressure(ArrayRef<unsigned> SetPressure, const TargetRegisterInfo *TRI); -#endif } // end namespace llvm #endif diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 28ebe5361b4a..335dd7f084c1 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -42,7 +42,7 @@ class RegScavenger { /// Information on scavenged registers (held in a spill slot). struct ScavengedInfo { - ScavengedInfo(int FI = -1) : FrameIndex(FI), Reg(0), Restore(NULL) {} + ScavengedInfo(int FI = -1) : FrameIndex(FI), Reg(0), Restore(nullptr) {} /// A spill slot used for scavenging a register post register allocation. int FrameIndex; @@ -73,7 +73,7 @@ class RegScavenger { public: RegScavenger() - : MBB(NULL), NumPhysRegs(0), Tracking(false) {} + : MBB(nullptr), NumPhysRegs(0), Tracking(false) {} /// enterBasicBlock - Start tracking liveness from the begin of the specific /// basic block. @@ -104,7 +104,7 @@ public: /// skipTo - Move the internal MBB iterator but do not update register states. void skipTo(MachineBasicBlock::iterator I) { - if (I == MachineBasicBlock::iterator(NULL)) + if (I == MachineBasicBlock::iterator(nullptr)) Tracking = false; MBBI = I; } diff --git a/include/llvm/CodeGen/ResourcePriorityQueue.h b/include/llvm/CodeGen/ResourcePriorityQueue.h index f20a9fce2ae8..114fe7c35b82 100644 --- a/include/llvm/CodeGen/ResourcePriorityQueue.h +++ b/include/llvm/CodeGen/ResourcePriorityQueue.h @@ -81,18 +81,18 @@ namespace llvm { delete ResourcesModel; } - bool isBottomUp() const { return false; } + bool isBottomUp() const override { return false; } - void initNodes(std::vector<SUnit> &sunits); + void initNodes(std::vector<SUnit> &sunits) override; - void addNode(const SUnit *SU) { + void addNode(const SUnit *SU) override { NumNodesSolelyBlocking.resize(SUnits->size(), 0); } - void updateNode(const SUnit *SU) {} + void updateNode(const SUnit *SU) override {} - void releaseState() { - SUnits = 0; + void releaseState() override { + SUnits = nullptr; } unsigned getLatency(unsigned NodeNum) const { @@ -116,18 +116,18 @@ namespace llvm { signed regPressureDelta(SUnit *SU, bool RawPressure = false); signed rawRegPressureDelta (SUnit *SU, unsigned RCId); - bool empty() const { return Queue.empty(); } + bool empty() const override { return Queue.empty(); } - virtual void push(SUnit *U); + void push(SUnit *U) override; - virtual SUnit *pop(); + SUnit *pop() override; - virtual void remove(SUnit *SU); + void remove(SUnit *SU) override; - virtual void dump(ScheduleDAG* DAG) const; + void dump(ScheduleDAG* DAG) const override; /// scheduledNode - Main resource tracking point. - void scheduledNode(SUnit *Node); + void scheduledNode(SUnit *Node) override; bool isResourceAvailable(SUnit *SU); void reserveResources(SUnit *SU); diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 009b8a0f697a..81db8a2f79b5 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -210,6 +210,10 @@ namespace RTLIB { FPEXT_F32_F64, FPEXT_F16_F32, FPROUND_F32_F16, + FPROUND_F64_F16, + FPROUND_F80_F16, + FPROUND_F128_F16, + FPROUND_PPCF128_F16, FPROUND_F64_F32, FPROUND_F80_F32, FPROUND_F128_F32, diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index ccba1b0364e4..5a65d590802a 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -95,7 +95,7 @@ namespace llvm { /// SDep - Construct a null SDep. This is only for use by container /// classes which require default constructors. SUnits may not /// have null SDep edges. - SDep() : Dep(0, Data) {} + SDep() : Dep(nullptr, Data) {} /// SDep - Construct an SDep with the specified values. SDep(SUnit *S, Kind kind, unsigned Reg) @@ -184,6 +184,12 @@ namespace llvm { || Contents.OrdKind == MustAliasMem); } + /// isBarrier - Test if this is an Order dependence that is marked + /// as a barrier. + bool isBarrier() const { + return getKind() == Order && Contents.OrdKind == Barrier; + } + /// isMustAlias - Test if this is an Order dependence that is marked /// as "must alias", meaning that the SUnits at either end of the edge /// have a memory dependence on a known memory location. @@ -248,7 +254,7 @@ namespace llvm { /// SUnit - Scheduling unit. This is a node in the scheduling DAG. class SUnit { private: - enum LLVM_ENUM_INT_TYPE(unsigned) { BoundaryID = ~0u }; + enum : unsigned { BoundaryID = ~0u }; SDNode *Node; // Representative node. MachineInstr *Instr; // Alternatively, a MachineInstr. @@ -292,6 +298,8 @@ namespace llvm { bool isScheduleHigh : 1; // True if preferable to schedule high. bool isScheduleLow : 1; // True if preferable to schedule low. bool isCloned : 1; // True if this node has been cloned. + bool isUnbuffered : 1; // Uses an unbuffered resource. + bool hasReservedResource : 1; // Uses a reserved resource. Sched::Preference SchedulingPref; // Scheduling preference. private: @@ -309,43 +317,49 @@ namespace llvm { /// SUnit - Construct an SUnit for pre-regalloc scheduling to represent /// an SDNode and any nodes flagged to it. SUnit(SDNode *node, unsigned nodenum) - : Node(node), Instr(0), OrigNode(0), SchedClass(0), NodeNum(nodenum), - NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0), - Latency(0), isVRegCycle(false), isCall(false), isCallOp(false), - isTwoAddress(false), isCommutable(false), hasPhysRegUses(false), - hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), - isAvailable(false), isScheduled(false), isScheduleHigh(false), - isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), - isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), - TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} + : Node(node), Instr(nullptr), OrigNode(nullptr), SchedClass(nullptr), + NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0), + NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), + NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false), + isCallOp(false), isTwoAddress(false), isCommutable(false), + hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), + isPending(false), isAvailable(false), isScheduled(false), + isScheduleHigh(false), isScheduleLow(false), isCloned(false), + isUnbuffered(false), hasReservedResource(false), + SchedulingPref(Sched::None), isDepthCurrent(false), + isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), + BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {} /// SUnit - Construct an SUnit for post-regalloc scheduling to represent /// a MachineInstr. SUnit(MachineInstr *instr, unsigned nodenum) - : Node(0), Instr(instr), OrigNode(0), SchedClass(0), NodeNum(nodenum), - NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0), - Latency(0), isVRegCycle(false), isCall(false), isCallOp(false), - isTwoAddress(false), isCommutable(false), hasPhysRegUses(false), - hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), - isAvailable(false), isScheduled(false), isScheduleHigh(false), - isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), - isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), - TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} + : Node(nullptr), Instr(instr), OrigNode(nullptr), SchedClass(nullptr), + NodeNum(nodenum), NodeQueueId(0), NumPreds(0), NumSuccs(0), + NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), + NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false), + isCallOp(false), isTwoAddress(false), isCommutable(false), + hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), + isPending(false), isAvailable(false), isScheduled(false), + isScheduleHigh(false), isScheduleLow(false), isCloned(false), + isUnbuffered(false), hasReservedResource(false), + SchedulingPref(Sched::None), isDepthCurrent(false), + isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), + BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {} /// SUnit - Construct a placeholder SUnit. SUnit() - : Node(0), Instr(0), OrigNode(0), SchedClass(0), NodeNum(BoundaryID), - NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), - NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0), - Latency(0), isVRegCycle(false), isCall(false), isCallOp(false), - isTwoAddress(false), isCommutable(false), hasPhysRegUses(false), - hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), - isAvailable(false), isScheduled(false), isScheduleHigh(false), - isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), - isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), - TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} + : Node(nullptr), Instr(nullptr), OrigNode(nullptr), SchedClass(nullptr), + NodeNum(BoundaryID), NodeQueueId(0), NumPreds(0), NumSuccs(0), + NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), + NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false), + isCallOp(false), isTwoAddress(false), isCommutable(false), + hasPhysRegUses(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), + isPending(false), isAvailable(false), isScheduled(false), + isScheduleHigh(false), isScheduleLow(false), isCloned(false), + isUnbuffered(false), hasReservedResource(false), + SchedulingPref(Sched::None), isDepthCurrent(false), + isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), + BotReadyCycle(0), CopyDstRC(nullptr), CopySrcRC(nullptr) {} /// \brief Boundary nodes are placeholders for the boundary of the /// scheduling region. diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index fe4f3c2de3b6..e6754a2c0342 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -15,8 +15,8 @@ #ifndef LLVM_CODEGEN_SCHEDULEDAGINSTRS_H #define LLVM_CODEGEN_SCHEDULEDAGINSTRS_H -#include "llvm/ADT/SparseSet.h" #include "llvm/ADT/SparseMultiSet.h" +#include "llvm/ADT/SparseSet.h" #include "llvm/CodeGen/ScheduleDAG.h" #include "llvm/CodeGen/TargetSchedule.h" #include "llvm/Support/Compiler.h" @@ -43,7 +43,7 @@ namespace llvm { }; /// Record a physical register access. - /// For non data-dependent uses, OpIdx == -1. + /// For non-data-dependent uses, OpIdx == -1. struct PhysRegSUOper { SUnit *SU; int OpIdx; @@ -88,9 +88,13 @@ namespace llvm { /// isPostRA flag indicates vregs cannot be present. bool IsPostRA; + /// True if the DAG builder should remove kill flags (in preparation for + /// rescheduling). + bool RemoveKillFlags; + /// The standard DAG builder does not normally include terminators as DAG /// nodes because it does not create the necessary dependencies to prevent - /// reordering. A specialized scheduler can overide + /// reordering. A specialized scheduler can override /// TargetInstrInfo::isSchedulingBoundary then enable this flag to indicate /// it has taken responsibility for scheduling the terminator correctly. bool CanHandleTerminators; @@ -145,15 +149,21 @@ namespace llvm { DbgValueVector DbgValues; MachineInstr *FirstDbgValue; + /// Set of live physical registers for updating kill flags. + BitVector LiveRegs; + public: explicit ScheduleDAGInstrs(MachineFunction &mf, const MachineLoopInfo &mli, const MachineDominatorTree &mdt, bool IsPostRAFlag, - LiveIntervals *LIS = 0); + bool RemoveKillFlags = false, + LiveIntervals *LIS = nullptr); virtual ~ScheduleDAGInstrs() {} + bool isPostRA() const { return IsPostRA; } + /// \brief Expose LiveIntervals for use in DAG mutators and such. LiveIntervals *getLIS() const { return LIS; } @@ -196,8 +206,9 @@ namespace llvm { /// buildSchedGraph - Build SUnits from the MachineBasicBlock that we are /// input. - void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0, - PressureDiffs *PDiffs = 0); + void buildSchedGraph(AliasAnalysis *AA, + RegPressureTracker *RPTracker = nullptr, + PressureDiffs *PDiffs = nullptr); /// addSchedBarrierDeps - Add dependencies from instructions in the current /// list of instructions being scheduled to scheduling barrier. We want to @@ -219,29 +230,40 @@ namespace llvm { /// the level of the whole MachineFunction. By default does nothing. virtual void finalizeSchedule() {} - virtual void dumpNode(const SUnit *SU) const; + void dumpNode(const SUnit *SU) const override; /// Return a label for a DAG node that points to an instruction. - virtual std::string getGraphNodeLabel(const SUnit *SU) const; + std::string getGraphNodeLabel(const SUnit *SU) const override; /// Return a label for the region of code covered by the DAG. - virtual std::string getDAGName() const; + std::string getDAGName() const override; + /// \brief Fix register kill flags that scheduling has made invalid. + void fixupKills(MachineBasicBlock *MBB); protected: void initSUnits(); void addPhysRegDataDeps(SUnit *SU, unsigned OperIdx); void addPhysRegDeps(SUnit *SU, unsigned OperIdx); void addVRegDefDeps(SUnit *SU, unsigned OperIdx); void addVRegUseDeps(SUnit *SU, unsigned OperIdx); + + /// \brief PostRA helper for rewriting kill flags. + void startBlockForKills(MachineBasicBlock *BB); + + /// \brief Toggle a register operand kill flag. + /// + /// Other adjustments may be made to the instruction if necessary. Return + /// true if the operand has been deleted, false if not. + bool toggleKillFlag(MachineInstr *MI, MachineOperand &MO); }; /// newSUnit - Creates a new SUnit and return a ptr to it. inline SUnit *ScheduleDAGInstrs::newSUnit(MachineInstr *MI) { #ifndef NDEBUG - const SUnit *Addr = SUnits.empty() ? 0 : &SUnits[0]; + const SUnit *Addr = SUnits.empty() ? nullptr : &SUnits[0]; #endif SUnits.push_back(SUnit(MI, (unsigned)SUnits.size())); - assert((Addr == 0 || Addr == &SUnits[0]) && + assert((Addr == nullptr || Addr == &SUnits[0]) && "SUnits std::vector reallocated on the fly!"); SUnits.back().OrigNode = &SUnits.back(); return &SUnits.back(); @@ -251,7 +273,7 @@ namespace llvm { inline SUnit *ScheduleDAGInstrs::getSUnit(MachineInstr *MI) const { DenseMap<MachineInstr*, SUnit*>::const_iterator I = MISUnitMap.find(MI); if (I == MISUnitMap.end()) - return 0; + return nullptr; return I->second; } } // namespace llvm diff --git a/include/llvm/CodeGen/ScheduleDFS.h b/include/llvm/CodeGen/ScheduleDFS.h index 73ce99f4713d..b2108ad3bedb 100644 --- a/include/llvm/CodeGen/ScheduleDFS.h +++ b/include/llvm/CodeGen/ScheduleDFS.h @@ -57,11 +57,9 @@ struct ILPValue { return RHS <= *this; } -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void print(raw_ostream &OS) const; void dump() const; -#endif }; /// \brief Compute the values of each DAG node for various metrics during DFS. diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h index 9dfa3446ef50..8a40e7212ff6 100644 --- a/include/llvm/CodeGen/ScheduleHazardRecognizer.h +++ b/include/llvm/CodeGen/ScheduleHazardRecognizer.h @@ -70,6 +70,22 @@ public: /// emitted, to advance the hazard state. virtual void EmitInstruction(SUnit *) {} + /// PreEmitNoops - This callback is invoked prior to emitting an instruction. + /// It should return the number of noops to emit prior to the provided + /// instruction. + /// Note: This is only used during PostRA scheduling. EmitNoop is not called + /// for these noops. + virtual unsigned PreEmitNoops(SUnit *) { + return 0; + } + + /// ShouldPreferAnother - This callback may be invoked if getHazardType + /// returns NoHazard. If, even though there is no hazard, it would be better to + /// schedule another available instruction, this callback should return true. + virtual bool ShouldPreferAnother(SUnit *) { + return false; + } + /// AdvanceCycle - This callback is invoked whenever the next top-down /// instruction to be scheduled cannot issue in the current cycle, either /// because of latency or resource conflicts. This should increment the diff --git a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h index c2103fb233f8..ab14c2de32b0 100644 --- a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h +++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -47,7 +47,7 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer { // Indices into the Scoreboard that represent the current cycle. size_t Head; public: - Scoreboard():Data(NULL), Depth(0), Head(0) { } + Scoreboard():Data(nullptr), Depth(0), Head(0) { } ~Scoreboard() { delete[] Data; } @@ -62,7 +62,7 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer { } void reset(size_t d = 1) { - if (Data == NULL) { + if (!Data) { Depth = d; Data = new unsigned[Depth]; } @@ -110,15 +110,15 @@ public: /// atIssueLimit - Return true if no more instructions may be issued in this /// cycle. - virtual bool atIssueLimit() const; + bool atIssueLimit() const override; // Stalls provides an cycle offset at which SU will be scheduled. It will be // negative for bottom-up scheduling. - virtual HazardType getHazardType(SUnit *SU, int Stalls); - virtual void Reset(); - virtual void EmitInstruction(SUnit *SU); - virtual void AdvanceCycle(); - virtual void RecedeCycle(); + HazardType getHazardType(SUnit *SU, int Stalls) override; + void Reset() override; + void EmitInstruction(SUnit *SU) override; + void AdvanceCycle() override; + void RecedeCycle() override; }; } diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 82becca315a1..bb87f82d2def 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -36,7 +36,6 @@ class MDNode; class SDDbgValue; class TargetLowering; class TargetSelectionDAGInfo; -class TargetTransformInfo; class SDVTListNode : public FoldingSetNode { friend struct FoldingSetTrait<SDVTListNode>; @@ -152,8 +151,7 @@ public: }; class SelectionDAG; -void checkForCycles(const SDNode *N); -void checkForCycles(const SelectionDAG *DAG); +void checkForCycles(const SelectionDAG *DAG, bool force = false); /// SelectionDAG class - This is used to represent a portion of an LLVM function /// in a low-level Data Dependence DAG representation suitable for instruction @@ -169,7 +167,6 @@ void checkForCycles(const SelectionDAG *DAG); class SelectionDAG { const TargetMachine &TM; const TargetSelectionDAGInfo &TSI; - const TargetTransformInfo *TTI; const TargetLowering *TLI; MachineFunction *MF; LLVMContext *Context; @@ -269,8 +266,7 @@ public: /// init - Prepare this SelectionDAG to process code in the given /// MachineFunction. /// - void init(MachineFunction &mf, const TargetTransformInfo *TTI, - const TargetLowering *TLI); + void init(MachineFunction &mf, const TargetLowering *TLI); /// clear - Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -281,7 +277,6 @@ public: const TargetMachine &getTarget() const { return TM; } const TargetLowering &getTargetLoweringInfo() const { return *TLI; } const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; } - const TargetTransformInfo *getTargetTransformInfo() const { return TTI; } LLVMContext *getContext() const {return Context; } /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. @@ -339,7 +334,7 @@ public: assert((!N.getNode() || N.getValueType() == MVT::Other) && "DAG root value is not a chain!"); if (N.getNode()) - checkForCycles(N.getNode()); + checkForCycles(N.getNode(), this); Root = N; if (N.getNode()) checkForCycles(this); @@ -396,23 +391,27 @@ public: SDVTList getVTList(EVT VT1, EVT VT2); SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3); SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3, EVT VT4); - SDVTList getVTList(const EVT *VTs, unsigned NumVTs); + SDVTList getVTList(ArrayRef<EVT> VTs); //===--------------------------------------------------------------------===// // Node creation methods. // - SDValue getConstant(uint64_t Val, EVT VT, bool isTarget = false); - SDValue getConstant(const APInt &Val, EVT VT, bool isTarget = false); - SDValue getConstant(const ConstantInt &Val, EVT VT, bool isTarget = false); + SDValue getConstant(uint64_t Val, EVT VT, bool isTarget = false, + bool isOpaque = false); + SDValue getConstant(const APInt &Val, EVT VT, bool isTarget = false, + bool isOpaque = false); + SDValue getConstant(const ConstantInt &Val, EVT VT, bool isTarget = false, + bool isOpaque = false); SDValue getIntPtrConstant(uint64_t Val, bool isTarget = false); - SDValue getTargetConstant(uint64_t Val, EVT VT) { - return getConstant(Val, VT, true); + SDValue getTargetConstant(uint64_t Val, EVT VT, bool isOpaque = false) { + return getConstant(Val, VT, true, isOpaque); } - SDValue getTargetConstant(const APInt &Val, EVT VT) { - return getConstant(Val, VT, true); + SDValue getTargetConstant(const APInt &Val, EVT VT, bool isOpaque = false) { + return getConstant(Val, VT, true, isOpaque); } - SDValue getTargetConstant(const ConstantInt &Val, EVT VT) { - return getConstant(Val, VT, true); + SDValue getTargetConstant(const ConstantInt &Val, EVT VT, + bool isOpaque = false) { + return getConstant(Val, VT, true, isOpaque); } // The forms below that take a double should only be used for simple // constants that can be exactly represented in VT. No checks are made. @@ -496,7 +495,8 @@ public: SDValue Glue) { SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Glue }; - return getNode(ISD::CopyToReg, dl, VTs, Ops, Glue.getNode() ? 4 : 3); + return getNode(ISD::CopyToReg, dl, VTs, + ArrayRef<SDValue>(Ops, Glue.getNode() ? 4 : 3)); } // Similar to last getCopyToReg() except parameter Reg is a SDValue @@ -504,13 +504,14 @@ public: SDValue Glue) { SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, Reg, N, Glue }; - return getNode(ISD::CopyToReg, dl, VTs, Ops, Glue.getNode() ? 4 : 3); + return getNode(ISD::CopyToReg, dl, VTs, + ArrayRef<SDValue>(Ops, Glue.getNode() ? 4 : 3)); } SDValue getCopyFromReg(SDValue Chain, SDLoc dl, unsigned Reg, EVT VT) { SDVTList VTs = getVTList(VT, MVT::Other); SDValue Ops[] = { Chain, getRegister(Reg, VT) }; - return getNode(ISD::CopyFromReg, dl, VTs, Ops, 2); + return getNode(ISD::CopyFromReg, dl, VTs, Ops); } // This version of the getCopyFromReg method takes an extra operand, which @@ -520,7 +521,8 @@ public: SDValue Glue) { SDVTList VTs = getVTList(VT, MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, getRegister(Reg, VT), Glue }; - return getNode(ISD::CopyFromReg, dl, VTs, Ops, Glue.getNode() ? 3 : 2); + return getNode(ISD::CopyFromReg, dl, VTs, + ArrayRef<SDValue>(Ops, Glue.getNode() ? 3 : 2)); } SDValue getCondCode(ISD::CondCode Cond); @@ -537,6 +539,18 @@ public: /// undefined. SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2, const int *MaskElts); + SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2, + ArrayRef<int> MaskElts) { + assert(VT.getVectorNumElements() == MaskElts.size() && + "Must have the same number of vector elements as mask elements!"); + return getVectorShuffle(VT, dl, N1, N2, MaskElts.data()); + } + + /// \brief Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to + /// the shuffle node in input but with swapped operands. + /// + /// Example: shuffle A, B, <0,5,2,7> -> shuffle B, A, <4,1,6,3> + SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV); /// getAnyExtOrTrunc - Convert Op, which must be of integer type, to the /// integer type VT, by either any-extending or truncating it. @@ -554,16 +568,42 @@ public: /// value assuming it was the smaller SrcTy value. SDValue getZeroExtendInReg(SDValue Op, SDLoc DL, EVT SrcTy); + /// getAnyExtendVectorInReg - Return an operation which will any-extend the + /// low lanes of the operand into the specified vector type. For example, + /// this can convert a v16i8 into a v4i32 by any-extending the low four + /// lanes of the operand from i8 to i32. + SDValue getAnyExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); + + /// getSignExtendVectorInReg - Return an operation which will sign extend the + /// low lanes of the operand into the specified vector type. For example, + /// this can convert a v16i8 into a v4i32 by sign extending the low four + /// lanes of the operand from i8 to i32. + SDValue getSignExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); + + /// getZeroExtendVectorInReg - Return an operation which will zero extend the + /// low lanes of the operand into the specified vector type. For example, + /// this can convert a v16i8 into a v4i32 by zero extending the low four + /// lanes of the operand from i8 to i32. + SDValue getZeroExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); + + /// getBoolExtOrTrunc - Convert Op, which must be of integer type, to the + /// integer type VT, by using an extension appropriate for the target's + /// BooleanContent for type OpVT or truncating it. + SDValue getBoolExtOrTrunc(SDValue Op, SDLoc SL, EVT VT, EVT OpVT); + /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). SDValue getNOT(SDLoc DL, SDValue Val, EVT VT); + /// \brief Create a logical NOT operation as (XOR Val, BooleanOne). + SDValue getLogicalNOT(SDLoc DL, SDValue Val, EVT VT); + /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have /// a glue result (to ensure it's not CSE'd). CALLSEQ_START does not have a /// useful SDLoc. SDValue getCALLSEQ_START(SDValue Chain, SDValue Op, SDLoc DL) { SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, Op }; - return getNode(ISD::CALLSEQ_START, DL, VTs, Ops, 2); + return getNode(ISD::CALLSEQ_START, DL, VTs, Ops); } /// getCALLSEQ_END - Return a new CALLSEQ_END node, which always must have a @@ -576,9 +616,9 @@ public: Ops.push_back(Chain); Ops.push_back(Op1); Ops.push_back(Op2); - Ops.push_back(InGlue); - return getNode(ISD::CALLSEQ_END, DL, NodeTys, &Ops[0], - (unsigned)Ops.size() - (InGlue.getNode() == 0 ? 1 : 0)); + if (InGlue.getNode()) + Ops.push_back(InGlue); + return getNode(ISD::CALLSEQ_END, DL, NodeTys, Ops); } /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful SDLoc. @@ -596,25 +636,22 @@ public: /// SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, - SDValue N1, SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, - SDValue N1, SDValue N2, SDValue N3, SDValue N4); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, + bool nuw = false, bool nsw = false, bool exact = false); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, + SDValue N3); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, + SDValue N3, SDValue N4); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, + SDValue N3, SDValue N4, SDValue N5); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, ArrayRef<SDUse> Ops); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, - SDValue N1, SDValue N2, SDValue N3, SDValue N4, - SDValue N5); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, - const SDUse *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, - const SDValue *Ops, unsigned NumOps); + ArrayRef<SDValue> Ops); SDValue getNode(unsigned Opcode, SDLoc DL, ArrayRef<EVT> ResultTys, - const SDValue *Ops, unsigned NumOps); - SDValue getNode(unsigned Opcode, SDLoc DL, const EVT *VTs, unsigned NumVTs, - const SDValue *Ops, unsigned NumOps); + ArrayRef<SDValue> Ops); SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - const SDValue *Ops, unsigned NumOps); + ArrayRef<SDValue> Ops); SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs); SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N); SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, @@ -687,23 +724,27 @@ public: SDValue getVAArg(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, SDValue SV, unsigned Align); - /// getAtomic - Gets a node for an atomic op, produces result and chain and - /// takes 3 operands - SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, - SDValue Ptr, SDValue Cmp, SDValue Swp, - MachinePointerInfo PtrInfo, unsigned Alignment, - AtomicOrdering Ordering, - SynchronizationScope SynchScope); - SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, - SDValue Ptr, SDValue Cmp, SDValue Swp, - MachineMemOperand *MMO, - AtomicOrdering Ordering, - SynchronizationScope SynchScope); + /// getAtomicCmpSwap - Gets a node for an atomic cmpxchg op. There are two + /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces a the value loaded and a + /// chain result. ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS produces the value loaded, + /// a success flag (initially i1), and a chain. + SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs, + SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, + MachinePointerInfo PtrInfo, unsigned Alignment, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope); + SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs, + SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, + MachineMemOperand *MMO, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope); /// getAtomic - Gets a node for an atomic op, produces result (if relevant) /// and chain and takes 2 operands. SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, - SDValue Ptr, SDValue Val, const Value* PtrVal, + SDValue Ptr, SDValue Val, const Value *PtrVal, unsigned Alignment, AtomicOrdering Ordering, SynchronizationScope SynchScope); SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, @@ -714,11 +755,6 @@ public: /// getAtomic - Gets a node for an atomic op, produces result and chain and /// takes 1 operand. SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT, - SDValue Chain, SDValue Ptr, const Value* PtrVal, - unsigned Alignment, - AtomicOrdering Ordering, - SynchronizationScope SynchScope); - SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope); @@ -726,33 +762,30 @@ public: /// getAtomic - Gets a node for an atomic op, produces result and chain and /// takes N operands. SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList, - SDValue* Ops, unsigned NumOps, MachineMemOperand *MMO, - AtomicOrdering Ordering, + ArrayRef<SDValue> Ops, MachineMemOperand *MMO, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList, + ArrayRef<SDValue> Ops, MachineMemOperand *MMO, + AtomicOrdering Ordering, SynchronizationScope SynchScope); /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a /// result and takes a list of operands. Opcode may be INTRINSIC_VOID, /// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not /// less than FIRST_TARGET_MEMORY_OPCODE. - SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, - const EVT *VTs, unsigned NumVTs, - const SDValue *Ops, unsigned NumOps, - EVT MemVT, MachinePointerInfo PtrInfo, - unsigned Align = 0, bool Vol = false, - bool ReadMem = true, bool WriteMem = true); - SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList, - const SDValue *Ops, unsigned NumOps, + ArrayRef<SDValue> Ops, EVT MemVT, MachinePointerInfo PtrInfo, unsigned Align = 0, bool Vol = false, bool ReadMem = true, bool WriteMem = true); SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList, - const SDValue *Ops, unsigned NumOps, + ArrayRef<SDValue> Ops, EVT MemVT, MachineMemOperand *MMO); /// getMergeValues - Create a MERGE_VALUES node from the given operands. - SDValue getMergeValues(const SDValue *Ops, unsigned NumOps, SDLoc dl); + SDValue getMergeValues(ArrayRef<SDValue> Ops, SDLoc dl); /// getLoad - Loads are not normal binary operators: their result type is not /// determined by their operands, and they produce a value AND a token chain. @@ -760,14 +793,15 @@ public: SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, bool isInvariant, unsigned Alignment, - const MDNode *TBAAInfo = 0, const MDNode *Ranges = 0); + const MDNode *TBAAInfo = nullptr, + const MDNode *Ranges = nullptr); SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO); SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, unsigned Alignment, - const MDNode *TBAAInfo = 0); + const MDNode *TBAAInfo = nullptr); SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, SDValue Chain, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO); @@ -778,8 +812,8 @@ public: SDValue Chain, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, bool isInvariant, - unsigned Alignment, const MDNode *TBAAInfo = 0, - const MDNode *Ranges = 0); + unsigned Alignment, const MDNode *TBAAInfo = nullptr, + const MDNode *Ranges = nullptr); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, SDValue Offset, @@ -790,14 +824,14 @@ public: SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, unsigned Alignment, - const MDNode *TBAAInfo = 0); + const MDNode *TBAAInfo = nullptr); SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachineMemOperand *MMO); SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT TVT, bool isNonTemporal, bool isVolatile, unsigned Alignment, - const MDNode *TBAAInfo = 0); + const MDNode *TBAAInfo = nullptr); SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, EVT TVT, MachineMemOperand *MMO); SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base, @@ -831,8 +865,7 @@ public: SDValue Op3, SDValue Op4); SDNode *UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, SDValue Op3, SDValue Op4, SDValue Op5); - SDNode *UpdateNodeOperands(SDNode *N, - const SDValue *Ops, unsigned NumOps); + SDNode *UpdateNodeOperands(SDNode *N, ArrayRef<SDValue> Ops); /// SelectNodeTo - These are used for target selectors to *mutate* the /// specified node to have the specified return type, Target opcode, and @@ -845,15 +878,14 @@ public: SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, SDValue Op1, SDValue Op2, SDValue Op3); SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, - const SDValue *Ops, unsigned NumOps); + ArrayRef<SDValue> Ops); SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, EVT VT2); SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, - EVT VT2, const SDValue *Ops, unsigned NumOps); + EVT VT2, ArrayRef<SDValue> Ops); SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, - EVT VT2, EVT VT3, const SDValue *Ops, unsigned NumOps); + EVT VT2, EVT VT3, ArrayRef<SDValue> Ops); SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, - EVT VT2, EVT VT3, EVT VT4, const SDValue *Ops, - unsigned NumOps); + EVT VT2, EVT VT3, EVT VT4, ArrayRef<SDValue> Ops); SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, EVT VT2, SDValue Op1); SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, @@ -863,12 +895,12 @@ public: SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, EVT VT2, EVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, SDVTList VTs, - const SDValue *Ops, unsigned NumOps); + ArrayRef<SDValue> Ops); /// MorphNodeTo - This *mutates* the specified node to have the specified /// return type, opcode, and operands. SDNode *MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs, - const SDValue *Ops, unsigned NumOps); + ArrayRef<SDValue> Ops); /// getMachineNode - These are used for target selectors to create a new node /// with specified return type(s), MachineInstr opcode, and operands. @@ -921,17 +953,21 @@ public: /// getNodeIfExists - Get the specified node if it's already available, or /// else return NULL. - SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, - const SDValue *Ops, unsigned NumOps); + SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, ArrayRef<SDValue> Ops, + bool nuw = false, bool nsw = false, + bool exact = false); /// getDbgValue - Creates a SDDbgValue node. /// - SDDbgValue *getDbgValue(MDNode *MDPtr, SDNode *N, unsigned R, uint64_t Off, - DebugLoc DL, unsigned O); - SDDbgValue *getDbgValue(MDNode *MDPtr, const Value *C, uint64_t Off, - DebugLoc DL, unsigned O); - SDDbgValue *getDbgValue(MDNode *MDPtr, unsigned FI, uint64_t Off, + SDDbgValue *getDbgValue(MDNode *MDPtr, SDNode *N, unsigned R, + bool IsIndirect, uint64_t Off, DebugLoc DL, unsigned O); + /// Constant. + SDDbgValue *getConstantDbgValue(MDNode *MDPtr, const Value *C, uint64_t Off, + DebugLoc DL, unsigned O); + /// Frame index. + SDDbgValue *getFrameIndexDbgValue(MDNode *MDPtr, unsigned FI, uint64_t Off, + DebugLoc DL, unsigned O); /// RemoveDeadNode - Remove the specified node from the system. If any of its /// operands then becomes dead, remove them as well. Inform UpdateListener @@ -1076,13 +1112,12 @@ public: bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth = 0) const; - /// ComputeMaskedBits - Determine which of the bits specified in Mask are - /// known to be either zero or one and return them in the KnownZero/KnownOne - /// bitsets. This code only analyzes bits in Mask, in order to short-circuit - /// processing. Targets can implement the computeMaskedBitsForTargetNode - /// method in the TargetLowering class to allow target nodes to be understood. - void ComputeMaskedBits(SDValue Op, APInt &KnownZero, APInt &KnownOne, - unsigned Depth = 0) const; + /// Determine which bits of Op are known to be either zero or one and return + /// them in the KnownZero/KnownOne bitsets. Targets can implement the + /// computeKnownBitsForTargetNode method in the TargetLowering class to allow + /// target nodes to be understood. + void computeKnownBits(SDValue Op, APInt &KnownZero, APInt &KnownOne, + unsigned Depth = 0) const; /// 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 @@ -1143,7 +1178,7 @@ public: /// low/high part. std::pair<SDValue, SDValue> SplitVector(const SDValue &N, const SDLoc &DL) { EVT LoVT, HiVT; - llvm::tie(LoVT, HiVT) = GetSplitDestVTs(N.getValueType()); + std::tie(LoVT, HiVT) = GetSplitDestVTs(N.getValueType()); return SplitVector(N, DL, LoVT, HiVT); } @@ -1154,23 +1189,33 @@ public: return SplitVector(N->getOperand(OpNo), SDLoc(N)); } + /// ExtractVectorElements - Append the extracted elements from Start to Count + /// out of the vector Op in Args. If Count is 0, all of the elements will be + /// extracted. + void ExtractVectorElements(SDValue Op, SmallVectorImpl<SDValue> &Args, + unsigned Start = 0, unsigned Count = 0); + + unsigned getEVTAlignment(EVT MemoryVT) const; + private: bool RemoveNodeFromCSEMaps(SDNode *N); void AddModifiedNodeToCSEMaps(SDNode *N); SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op, void *&InsertPos); SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op1, SDValue Op2, void *&InsertPos); - SDNode *FindModifiedNodeSlot(SDNode *N, const SDValue *Ops, unsigned NumOps, + SDNode *FindModifiedNodeSlot(SDNode *N, ArrayRef<SDValue> Ops, void *&InsertPos); SDNode *UpdadeSDLocOnMergedSDNode(SDNode *N, SDLoc loc); void DeleteNodeNotInCSEMaps(SDNode *N); void DeallocateNode(SDNode *N); - unsigned getEVTAlignment(EVT MemoryVT) const; - void allnodes_clear(); + BinarySDNode *GetBinarySDNode(unsigned Opcode, SDLoc DL, SDVTList VTs, + SDValue N1, SDValue N2, bool nuw, bool nsw, + bool exact); + /// VTList - List of non-single value types. FoldingSet<SDVTListNode> VTListMap; diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index b5ec8cb075dc..520be402cfc5 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -30,7 +30,6 @@ namespace llvm { class MachineInstr; class TargetLowering; class TargetLibraryInfo; - class TargetTransformInfo; class FunctionLoweringInfo; class ScheduleHazardRecognizer; class GCFunctionInfo; @@ -43,7 +42,6 @@ class SelectionDAGISel : public MachineFunctionPass { public: TargetMachine &TM; const TargetLibraryInfo *LibInfo; - const TargetTransformInfo *TTI; FunctionLoweringInfo *FuncInfo; MachineFunction *MF; MachineRegisterInfo *RegInfo; @@ -62,9 +60,9 @@ public: return TM.getTargetLowering(); } - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; - virtual bool runOnMachineFunction(MachineFunction &MF); + bool runOnMachineFunction(MachineFunction &MF) override; virtual void EmitFunctionEntryCode() {} @@ -125,6 +123,8 @@ public: OPC_CheckChild3Type, OPC_CheckChild4Type, OPC_CheckChild5Type, OPC_CheckChild6Type, OPC_CheckChild7Type, OPC_CheckInteger, + OPC_CheckChild0Integer, OPC_CheckChild1Integer, OPC_CheckChild2Integer, + OPC_CheckChild3Integer, OPC_CheckChild4Integer, OPC_CheckCondCode, OPC_CheckValueType, OPC_CheckComplexPat, @@ -242,13 +242,15 @@ private: // Calls to these functions are generated by tblgen. SDNode *Select_INLINEASM(SDNode *N); + SDNode *Select_READ_REGISTER(SDNode *N); + SDNode *Select_WRITE_REGISTER(SDNode *N); SDNode *Select_UNDEF(SDNode *N); void CannotYetSelect(SDNode *N); private: void DoInstructionSelection(); SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs, - const SDValue *Ops, unsigned NumOps, unsigned EmitNodeInfo); + ArrayRef<SDValue> Ops, unsigned EmitNodeInfo); void PrepareEHLandingPad(); diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 70c15e6c6e6f..223151105b0d 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -19,6 +19,8 @@ #ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H #define LLVM_CODEGEN_SELECTIONDAGNODES_H +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/STLExtras.h" @@ -29,9 +31,9 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/Instructions.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/DebugLoc.h" #include "llvm/Support/MathExtras.h" #include <cassert> @@ -48,7 +50,26 @@ template <typename T> struct DenseMapInfo; template <typename T> struct simplify_type; template <typename T> struct ilist_traits; -void checkForCycles(const SDNode *N); +/// isBinOpWithFlags - Returns true if the opcode is a binary operation +/// with flags. +static bool isBinOpWithFlags(unsigned Opcode) { + switch (Opcode) { + case ISD::SDIV: + case ISD::UDIV: + case ISD::SRA: + case ISD::SRL: + case ISD::MUL: + case ISD::ADD: + case ISD::SUB: + case ISD::SHL: + return true; + default: + return false; + } +} + +void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr, + bool force = false); /// SDVTList - This represents a list of ValueType's that has been intern'd by /// a SelectionDAG. Instances of this simple value class are returned by @@ -70,6 +91,10 @@ namespace ISD { /// BUILD_VECTOR where all of the elements are 0 or undef. bool isBuildVectorAllZeros(const SDNode *N); + /// \brief Return true if the specified node is a BUILD_VECTOR node of + /// all ConstantSDNode or undef. + bool isBuildVectorOfConstantSDNodes(const SDNode *N); + /// isScalarToVector - Return true if the specified node is a /// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low /// element is not an undef. @@ -95,7 +120,7 @@ class SDValue { SDNode *Node; // The node defining the value we are using. unsigned ResNo; // Which return value of the node we are using. public: - SDValue() : Node(0), ResNo(0) {} + SDValue() : Node(nullptr), ResNo(0) {} SDValue(SDNode *node, unsigned resno) : Node(node), ResNo(resno) {} /// get the index which selects a specific result in the SDNode @@ -116,7 +141,10 @@ public: return !operator==(O); } bool operator<(const SDValue &O) const { - return Node < O.Node || (Node == O.Node && ResNo < O.ResNo); + return std::tie(Node, ResNo) < std::tie(O.Node, O.ResNo); + } + LLVM_EXPLICIT operator bool() const { + return Node != nullptr; } SDValue getValue(unsigned R) const { @@ -141,6 +169,10 @@ public: return getValueType().getSizeInBits(); } + unsigned getScalarValueSizeInBits() const { + return getValueType().getScalarType().getSizeInBits(); + } + // Forwarding methods - These forward to the corresponding methods in SDNode. inline unsigned getOpcode() const; inline unsigned getNumOperands() const; @@ -225,7 +257,7 @@ class SDUse { void operator=(const SDUse &U) LLVM_DELETED_FUNCTION; public: - SDUse() : Val(), User(NULL), Prev(NULL), Next(NULL) {} + SDUse() : Val(), User(nullptr), Prev(nullptr), Next(nullptr) {} /// Normally SDUse will just implicitly convert to an SDValue that it holds. operator const SDValue&() const { return Val; } @@ -399,12 +431,12 @@ public: /// use_empty - Return true if there are no uses of this node. /// - bool use_empty() const { return UseList == NULL; } + bool use_empty() const { return UseList == nullptr; } /// hasOneUse - Return true if there is exactly one use of this node. /// bool hasOneUse() const { - return !use_empty() && llvm::next(use_begin()) == use_end(); + return !use_empty() && std::next(use_begin()) == use_end(); } /// use_size - Return the number of uses of this node. This method takes @@ -449,7 +481,7 @@ public: SDUse, ptrdiff_t>::pointer pointer; use_iterator(const use_iterator &I) : Op(I.Op) {} - use_iterator() : Op(0) {} + use_iterator() : Op(nullptr) {} bool operator==(const use_iterator &x) const { return Op == x.Op; @@ -459,7 +491,7 @@ public: } /// atEnd - return true if this iterator is at the end of uses list. - bool atEnd() const { return Op == 0; } + bool atEnd() const { return Op == nullptr; } // Iterator traversal: forward iteration only. use_iterator &operator++() { // Preincrement @@ -497,8 +529,14 @@ public: return use_iterator(UseList); } - static use_iterator use_end() { return use_iterator(0); } + static use_iterator use_end() { return use_iterator(nullptr); } + inline iterator_range<use_iterator> uses() { + return iterator_range<use_iterator>(use_begin(), use_end()); + } + inline iterator_range<use_iterator> uses() const { + return iterator_range<use_iterator>(use_begin(), use_end()); + } /// hasNUsesOfValue - Return true if there are exactly NUSES uses of the /// indicated value. This method ignores uses of other values defined by this @@ -559,6 +597,7 @@ public: typedef SDUse* op_iterator; op_iterator op_begin() const { return OperandList; } op_iterator op_end() const { return OperandList+NumOperands; } + ArrayRef<SDUse> ops() const { return makeArrayRef(op_begin(), op_end()); } SDVTList getVTList() const { SDVTList X = { ValueList, NumValues }; @@ -571,7 +610,7 @@ public: if (getNumOperands() != 0 && getOperand(getNumOperands()-1).getValueType() == MVT::Glue) return getOperand(getNumOperands()-1).getNode(); - return 0; + return nullptr; } // If this is a pseudo op, like copyfromreg, look to see if there is a @@ -596,7 +635,7 @@ public: for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI) if (UI.getUse().get().getValueType() == MVT::Glue) return *UI; - return 0; + return nullptr; } /// getNumValues - Return the number of values defined/returned by this @@ -629,12 +668,12 @@ public: /// getOperationName - Return the opcode of this operation for printing. /// - std::string getOperationName(const SelectionDAG *G = 0) const; + std::string getOperationName(const SelectionDAG *G = nullptr) const; static const char* getIndexedModeName(ISD::MemIndexedMode AM); void print_types(raw_ostream &OS, const SelectionDAG *G) const; void print_details(raw_ostream &OS, const SelectionDAG *G) const; - void print(raw_ostream &OS, const SelectionDAG *G = 0) const; - void printr(raw_ostream &OS, const SelectionDAG *G = 0) const; + void print(raw_ostream &OS, const SelectionDAG *G = nullptr) const; + void printr(raw_ostream &OS, const SelectionDAG *G = nullptr) const; /// printrFull - Print a SelectionDAG node and all children down to /// the leaves. The given SelectionDAG allows target-specific nodes @@ -642,7 +681,7 @@ public: /// print the whole DAG, including children that appear multiple /// times. /// - void printrFull(raw_ostream &O, const SelectionDAG *G = 0) const; + void printrFull(raw_ostream &O, const SelectionDAG *G = nullptr) const; /// printrWithDepth - Print a SelectionDAG node and children up to /// depth "depth." The given SelectionDAG allows target-specific @@ -650,7 +689,7 @@ public: /// will print children that appear multiple times wherever they are /// used. /// - void printrWithDepth(raw_ostream &O, const SelectionDAG *G = 0, + void printrWithDepth(raw_ostream &O, const SelectionDAG *G = nullptr, unsigned depth = 100) const; @@ -675,14 +714,15 @@ public: /// Unlike dumpr, this will print the whole DAG, including children /// that appear multiple times. /// - void dumprFull(const SelectionDAG *G = 0) const; + void dumprFull(const SelectionDAG *G = nullptr) const; /// dumprWithDepth - printrWithDepth to dbgs(). The given /// SelectionDAG allows target-specific nodes to be printed in /// human-readable form. Unlike dumpr, this will print children /// that appear multiple times wherever they are used. /// - void dumprWithDepth(const SelectionDAG *G = 0, unsigned depth = 100) const; + void dumprWithDepth(const SelectionDAG *G = nullptr, + unsigned depth = 100) const; /// Profile - Gather unique data for the node. /// @@ -699,14 +739,14 @@ protected: } SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs, - const SDValue *Ops, unsigned NumOps) + ArrayRef<SDValue> Ops) : NodeType(Opc), OperandsNeedDelete(true), HasDebugValue(false), SubclassData(0), NodeId(-1), - OperandList(NumOps ? new SDUse[NumOps] : 0), - ValueList(VTs.VTs), UseList(NULL), - NumOperands(NumOps), NumValues(VTs.NumVTs), + OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), + ValueList(VTs.VTs), UseList(nullptr), + NumOperands(Ops.size()), NumValues(VTs.NumVTs), debugLoc(dl), IROrder(Order) { - for (unsigned i = 0; i != NumOps; ++i) { + for (unsigned i = 0; i != Ops.size(); ++i) { OperandList[i].setUser(this); OperandList[i].setInitial(Ops[i]); } @@ -717,9 +757,9 @@ protected: /// set later with InitOperands. SDNode(unsigned Opc, unsigned Order, const DebugLoc dl, SDVTList VTs) : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), - SubclassData(0), NodeId(-1), OperandList(0), - ValueList(VTs.VTs), UseList(NULL), NumOperands(0), NumValues(VTs.NumVTs), - debugLoc(dl), IROrder(Order) {} + SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), + UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), debugLoc(dl), + IROrder(Order) {} /// InitOperands - Initialize the operands list of this with 1 operand. void InitOperands(SDUse *Ops, const SDValue &Op0) { @@ -804,7 +844,7 @@ private: int IROrder; public: - SDLoc() : Ptr(NULL), IROrder(0) {} + SDLoc() : Ptr(nullptr), IROrder(0) {} SDLoc(const SDNode *N) : Ptr(N), IROrder(-1) { assert(N && "null SDNode"); } @@ -815,14 +855,14 @@ public: assert(Order >= 0 && "bad IROrder"); } unsigned getIROrder() { - if (IROrder >= 0 || Ptr == NULL) { + if (IROrder >= 0 || Ptr == nullptr) { return (unsigned)IROrder; } const SDNode *N = (const SDNode*)(Ptr); return N->getIROrder(); } DebugLoc getDebugLoc() { - if (Ptr == NULL) { + if (!Ptr) { return DebugLoc(); } if (IROrder >= 0) { @@ -922,6 +962,36 @@ public: } }; +/// BinaryWithFlagsSDNode - This class is an extension of BinarySDNode +/// used from those opcodes that have associated extra flags. +class BinaryWithFlagsSDNode : public BinarySDNode { + enum { NUW = (1 << 0), NSW = (1 << 1), EXACT = (1 << 2) }; + +public: + BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X, SDValue Y) + : BinarySDNode(Opc, Order, dl, VTs, X, Y) {} + /// getRawSubclassData - Return the SubclassData value, which contains an + /// encoding of the flags. + /// This function should be used to add subclass data to the NodeID value. + unsigned getRawSubclassData() const { return SubclassData; } + void setHasNoUnsignedWrap(bool b) { + SubclassData = (SubclassData & ~NUW) | (b ? NUW : 0); + } + void setHasNoSignedWrap(bool b) { + SubclassData = (SubclassData & ~NSW) | (b ? NSW : 0); + } + void setIsExact(bool b) { + SubclassData = (SubclassData & ~EXACT) | (b ? EXACT : 0); + } + bool hasNoUnsignedWrap() const { return SubclassData & NUW; } + bool hasNoSignedWrap() const { return SubclassData & NSW; } + bool isExact() const { return SubclassData & EXACT; } + static bool classof(const SDNode *N) { + return isBinOpWithFlags(N->getOpcode()); + } +}; + /// TernarySDNode - This class is used for three-operand SDNodes. This is solely /// to allow co-allocation of node operands with the node itself. class TernarySDNode : public SDNode { @@ -982,8 +1052,7 @@ public: EVT MemoryVT, MachineMemOperand *MMO); MemSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - const SDValue *Ops, - unsigned NumOps, EVT MemoryVT, MachineMemOperand *MMO); + ArrayRef<SDValue> Ops, EVT MemoryVT, MachineMemOperand *MMO); bool readMem() const { return MMO->isLoad(); } bool writeMem() const { return MMO->isStore(); } @@ -1016,8 +1085,7 @@ public: return SynchronizationScope((SubclassData >> 12) & 1); } - /// Returns the SrcValue and offset that describes the location of the access - const Value *getSrcValue() const { return MMO->getValue(); } + // Returns the offset from the location of the access. int64_t getSrcValueOffset() const { return MMO->getOffset(); } /// Returns the TBAAInfo that describes the dereference. @@ -1063,6 +1131,7 @@ public: N->getOpcode() == ISD::STORE || N->getOpcode() == ISD::PREFETCH || N->getOpcode() == ISD::ATOMIC_CMP_SWAP || + N->getOpcode() == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS || N->getOpcode() == ISD::ATOMIC_SWAP || N->getOpcode() == ISD::ATOMIC_LOAD_ADD || N->getOpcode() == ISD::ATOMIC_LOAD_SUB || @@ -1085,15 +1154,27 @@ public: class AtomicSDNode : public MemSDNode { SDUse Ops[4]; - void InitAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope) { + /// For cmpxchg instructions, the ordering requirements when a store does not + /// occur. + AtomicOrdering FailureOrdering; + + void InitAtomic(AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope) { // This must match encodeMemSDNodeFlags() in SelectionDAG.cpp. - assert((Ordering & 15) == Ordering && + assert((SuccessOrdering & 15) == SuccessOrdering && + "Ordering may not require more than 4 bits!"); + assert((FailureOrdering & 15) == FailureOrdering && "Ordering may not require more than 4 bits!"); assert((SynchScope & 1) == SynchScope && "SynchScope may not require more than 1 bit!"); - SubclassData |= Ordering << 8; + SubclassData |= SuccessOrdering << 8; SubclassData |= SynchScope << 12; - assert(getOrdering() == Ordering && "Ordering encoding error!"); + this->FailureOrdering = FailureOrdering; + assert(getSuccessOrdering() == SuccessOrdering && + "Ordering encoding error!"); + assert(getFailureOrdering() == FailureOrdering && + "Ordering encoding error!"); assert(getSynchScope() == SynchScope && "Synch-scope encoding error!"); } @@ -1107,12 +1188,11 @@ public: // SrcVal: address to update as a Value (used for MemOperand) // Align: alignment of memory AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, - EVT MemVT, - SDValue Chain, SDValue Ptr, - SDValue Cmp, SDValue Swp, MachineMemOperand *MMO, - AtomicOrdering Ordering, SynchronizationScope SynchScope) - : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { - InitAtomic(Ordering, SynchScope); + EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, + MachineMemOperand *MMO, AtomicOrdering Ordering, + SynchronizationScope SynchScope) + : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { + InitAtomic(Ordering, Ordering, SynchScope); InitOperands(Ops, Chain, Ptr, Cmp, Swp); } AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, @@ -1121,7 +1201,7 @@ public: SDValue Val, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { - InitAtomic(Ordering, SynchScope); + InitAtomic(Ordering, Ordering, SynchScope); InitOperands(Ops, Chain, Ptr, Val); } AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, @@ -1130,15 +1210,16 @@ public: MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope) : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { - InitAtomic(Ordering, SynchScope); + InitAtomic(Ordering, Ordering, SynchScope); InitOperands(Ops, Chain, Ptr); } AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT, - SDValue* AllOps, SDUse *DynOps, unsigned NumOps, + const SDValue* AllOps, SDUse *DynOps, unsigned NumOps, MachineMemOperand *MMO, - AtomicOrdering Ordering, SynchronizationScope SynchScope) + AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope) : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) { - InitAtomic(Ordering, SynchScope); + InitAtomic(SuccessOrdering, FailureOrdering, SynchScope); assert((DynOps || NumOps <= array_lengthof(Ops)) && "Too many ops for internal storage!"); InitOperands(DynOps ? DynOps : Ops, AllOps, NumOps); @@ -1147,14 +1228,25 @@ public: const SDValue &getBasePtr() const { return getOperand(1); } const SDValue &getVal() const { return getOperand(2); } + AtomicOrdering getSuccessOrdering() const { + return getOrdering(); + } + + // Not quite enough room in SubclassData for everything, so failure gets its + // own field. + AtomicOrdering getFailureOrdering() const { + return FailureOrdering; + } + bool isCompareAndSwap() const { unsigned Op = getOpcode(); - return Op == ISD::ATOMIC_CMP_SWAP; + return Op == ISD::ATOMIC_CMP_SWAP || Op == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS; } // Methods to support isa and dyn_cast static bool classof(const SDNode *N) { return N->getOpcode() == ISD::ATOMIC_CMP_SWAP || + N->getOpcode() == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS || N->getOpcode() == ISD::ATOMIC_SWAP || N->getOpcode() == ISD::ATOMIC_LOAD_ADD || N->getOpcode() == ISD::ATOMIC_LOAD_SUB || @@ -1178,9 +1270,9 @@ public: class MemIntrinsicSDNode : public MemSDNode { public: MemIntrinsicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - const SDValue *Ops, unsigned NumOps, - EVT MemoryVT, MachineMemOperand *MMO) - : MemSDNode(Opc, Order, dl, VTs, Ops, NumOps, MemoryVT, MMO) { + ArrayRef<SDValue> Ops, EVT MemoryVT, + MachineMemOperand *MMO) + : MemSDNode(Opc, Order, dl, VTs, Ops, MemoryVT, MMO) { } // Methods to support isa and dyn_cast @@ -1246,9 +1338,10 @@ public: class ConstantSDNode : public SDNode { const ConstantInt *Value; friend class SelectionDAG; - ConstantSDNode(bool isTarget, const ConstantInt *val, EVT VT) + ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, EVT VT) : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DebugLoc(), getSDVTList(VT)), Value(val) { + SubclassData |= (uint16_t)isOpaque; } public: @@ -1261,6 +1354,8 @@ public: bool isNullValue() const { return Value->isNullValue(); } bool isAllOnesValue() const { return Value->isAllOnesValue(); } + bool isOpaque() const { return SubclassData & 1; } + static bool classof(const SDNode *N) { return N->getOpcode() == ISD::Constant || N->getOpcode() == ISD::TargetConstant; @@ -1486,7 +1581,32 @@ public: /// undefined. isBigEndian describes the endianness of the target. bool isConstantSplat(APInt &SplatValue, APInt &SplatUndef, unsigned &SplatBitSize, bool &HasAnyUndefs, - unsigned MinSplatBits = 0, bool isBigEndian = false); + unsigned MinSplatBits = 0, + bool isBigEndian = false) const; + + /// \brief Returns the splatted value or a null value if this is not a splat. + /// + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + SDValue getSplatValue(BitVector *UndefElements = nullptr) const; + + /// \brief Returns the splatted constant or null if this is not a constant + /// splat. + /// + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + ConstantSDNode * + getConstantSplatNode(BitVector *UndefElements = nullptr) const; + + /// \brief Returns the splatted constant FP or null if this is not a constant + /// FP splat. + /// + /// If passed a non-null UndefElements bitvector, it will resize it to match + /// the vector width and set the bits where elements are undef. + ConstantFPSDNode * + getConstantFPSplatNode(BitVector *UndefElements = nullptr) const; + + bool isConstant() const; static inline bool classof(const SDNode *N) { return N->getOpcode() == ISD::BUILD_VECTOR; @@ -1638,11 +1758,10 @@ class CvtRndSatSDNode : public SDNode { ISD::CvtCode CvtCode; friend class SelectionDAG; explicit CvtRndSatSDNode(EVT VT, unsigned Order, DebugLoc dl, - const SDValue *Ops, unsigned NumOps, - ISD::CvtCode Code) - : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT), Ops, NumOps), + ArrayRef<SDValue> Ops, ISD::CvtCode Code) + : SDNode(ISD::CONVERT_RNDSAT, Order, dl, getSDVTList(VT), Ops), CvtCode(Code) { - assert(NumOps == 5 && "wrong number of operations"); + assert(Ops.size() == 5 && "wrong number of operations"); } public: ISD::CvtCode getCvtCode() const { return CvtCode; } @@ -1785,7 +1904,7 @@ public: private: friend class SelectionDAG; MachineSDNode(unsigned Opc, unsigned Order, const DebugLoc DL, SDVTList VTs) - : SDNode(Opc, Order, DL, VTs), MemRefs(0), MemRefsEnd(0) {} + : SDNode(Opc, Order, DL, VTs), MemRefs(nullptr), MemRefsEnd(nullptr) {} /// LocalOperands - Operands for this instruction, if they fit here. If /// they don't, this field is unused. diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 984796af8644..00bb22b91d32 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -147,11 +147,11 @@ namespace llvm { }; /// Construct an invalid index. - SlotIndex() : lie(0, 0) {} + SlotIndex() : lie(nullptr, 0) {} // Construct a new slot index from the given one, and set the slot. SlotIndex(const SlotIndex &li, Slot s) : lie(li.listEntry(), unsigned(s)) { - assert(lie.getPointer() != 0 && + assert(lie.getPointer() != nullptr && "Attempt to construct index with 0 pointer."); } @@ -377,10 +377,10 @@ namespace llvm { initializeSlotIndexesPass(*PassRegistry::getPassRegistry()); } - virtual void getAnalysisUsage(AnalysisUsage &au) const; - virtual void releaseMemory(); + void getAnalysisUsage(AnalysisUsage &au) const override; + void releaseMemory() override; - virtual bool runOnMachineFunction(MachineFunction &fn); + bool runOnMachineFunction(MachineFunction &fn) override; /// Dump the indexes. void dump() const; @@ -421,7 +421,7 @@ namespace llvm { /// Returns the instruction for the given index, or null if the given /// index has no instruction associated with it. MachineInstr* getInstructionFromIndex(SlotIndex index) const { - return index.isValid() ? index.listEntry()->getInstr() : 0; + return index.isValid() ? index.listEntry()->getInstr() : nullptr; } /// Returns the next non-null index, if one exists. @@ -545,20 +545,20 @@ namespace llvm { std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), start); if (itr == idx2MBBMap.end()) { - itr = prior(itr); + itr = std::prev(itr); return itr->second; } // Check that we don't cross the boundary into this block. if (itr->first < end) - return 0; + return nullptr; - itr = prior(itr); + itr = std::prev(itr); if (itr->first <= start) return itr->second; - return 0; + return nullptr; } /// Insert the given machine instruction into the mapping. Returns the @@ -574,18 +574,18 @@ namespace llvm { // affected by debug information. assert(!mi->isDebugValue() && "Cannot number DBG_VALUE instructions."); - assert(mi->getParent() != 0 && "Instr must be added to function."); + assert(mi->getParent() != nullptr && "Instr must be added to function."); // Get the entries where mi should be inserted. IndexList::iterator prevItr, nextItr; if (Late) { // Insert mi's index immediately before the following instruction. nextItr = getIndexAfter(mi).listEntry(); - prevItr = prior(nextItr); + prevItr = std::prev(nextItr); } else { // Insert mi's index immediately after the preceding instruction. prevItr = getIndexBefore(mi).listEntry(); - nextItr = llvm::next(prevItr); + nextItr = std::next(prevItr); } // Get a number for the new instr, or 0 if there's no room currently. @@ -615,7 +615,7 @@ namespace llvm { IndexListEntry *miEntry(mi2iItr->second.listEntry()); assert(miEntry->getInstr() == mi && "Instruction indexes broken."); // FIXME: Eventually we want to actually delete these indexes. - miEntry->setInstr(0); + miEntry->setInstr(nullptr); mi2iMap.erase(mi2iItr); } } @@ -638,17 +638,17 @@ namespace llvm { /// Add the given MachineBasicBlock into the maps. void insertMBBInMaps(MachineBasicBlock *mbb) { MachineFunction::iterator nextMBB = - llvm::next(MachineFunction::iterator(mbb)); + std::next(MachineFunction::iterator(mbb)); - IndexListEntry *startEntry = 0; - IndexListEntry *endEntry = 0; + IndexListEntry *startEntry = nullptr; + IndexListEntry *endEntry = nullptr; IndexList::iterator newItr; if (nextMBB == mbb->getParent()->end()) { startEntry = &indexList.back(); - endEntry = createEntry(0, 0); + endEntry = createEntry(nullptr, 0); newItr = indexList.insertAfter(startEntry, endEntry); } else { - startEntry = createEntry(0, 0); + startEntry = createEntry(nullptr, 0); endEntry = getMBBStartIdx(nextMBB).listEntry(); newItr = indexList.insert(endEntry, startEntry); } diff --git a/include/llvm/CodeGen/StackMapLivenessAnalysis.h b/include/llvm/CodeGen/StackMapLivenessAnalysis.h new file mode 100644 index 000000000000..6f0754616206 --- /dev/null +++ b/include/llvm/CodeGen/StackMapLivenessAnalysis.h @@ -0,0 +1,64 @@ +//===--- StackMapLivenessAnalysis - StackMap Liveness Analysis --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass calculates the liveness for each basic block in a function and +// attaches the register live-out information to a patchpoint intrinsic (if +// present). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H +#define LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H + +#include "llvm/CodeGen/LivePhysRegs.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + + +namespace llvm { + +/// \brief This pass calculates the liveness information for each basic block in +/// a function and attaches the register live-out information to a patchpoint +/// intrinsic if present. +/// +/// This pass can be disabled via the -enable-patchpoint-liveness=false flag. +/// The pass skips functions that don't have any patchpoint intrinsics. The +/// information provided by this pass is optional and not required by the +/// aformentioned intrinsic to function. +class StackMapLiveness : public MachineFunctionPass { + MachineFunction *MF; + const TargetRegisterInfo *TRI; + LivePhysRegs LiveRegs; +public: + static char ID; + + /// \brief Default construct and initialize the pass. + StackMapLiveness(); + + /// \brief Tell the pass manager which passes we depend on and what + /// information we preserve. + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// \brief Calculate the liveness information for the given machine function. + bool runOnMachineFunction(MachineFunction &MF) override; + +private: + /// \brief Performs the actual liveness calculation for the function. + bool calculateLiveness(); + + /// \brief Add the current register live set to the instruction. + void addLiveOutSetToMI(MachineInstr &MI); + + /// \brief Create a register mask and initialize it with the registers from + /// the register live set. + uint32_t *createRegisterMask() const; +}; + +} // llvm namespace + +#endif // LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index e90f22e5b69a..5eddbb65259e 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -1,4 +1,5 @@ //===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===// + // // The LLVM Compiler Infrastructure // @@ -10,6 +11,7 @@ #ifndef LLVM_STACKMAPS #define LLVM_STACKMAPS +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineInstr.h" #include <map> @@ -19,6 +21,7 @@ namespace llvm { class AsmPrinter; class MCExpr; +class MCStreamer; /// \brief MI-level patchpoint operands. /// @@ -92,19 +95,28 @@ public: : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {} }; - // Typedef a function pointer for functions that parse sequences of operands - // and return a Location, plus a new "next" operand iterator. - typedef std::pair<Location, MachineInstr::const_mop_iterator> - (*OperandParser)(MachineInstr::const_mop_iterator, - MachineInstr::const_mop_iterator, const TargetMachine&); + struct LiveOutReg { + unsigned short Reg; + unsigned short RegNo; + unsigned short Size; + + LiveOutReg() : Reg(0), RegNo(0), Size(0) {} + LiveOutReg(unsigned short Reg, unsigned short RegNo, unsigned short Size) + : Reg(Reg), RegNo(RegNo), Size(Size) {} + + void MarkInvalid() { Reg = 0; } + + // Only sort by the dwarf register number. + bool operator< (const LiveOutReg &LO) const { return RegNo < LO.RegNo; } + static bool IsInvalid(const LiveOutReg &LO) { return LO.Reg == 0; } + }; // OpTypes are used to encode information about the following logical // operand (which may consist of several MachineOperands) for the // OpParser. typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType; - StackMaps(AsmPrinter &AP, OperandParser OpParser) - : AP(AP), OpParser(OpParser) {} + StackMaps(AsmPrinter &AP); /// \brief Generate a stackmap record for a stackmap instruction. /// @@ -120,54 +132,66 @@ public: void serializeToStackMapSection(); private: + static const char *WSMP; + typedef SmallVector<Location, 8> LocationVec; + typedef SmallVector<LiveOutReg, 8> LiveOutVec; + typedef MapVector<int64_t, int64_t> ConstantPool; + typedef MapVector<const MCSymbol *, uint64_t> FnStackSizeMap; struct CallsiteInfo { const MCExpr *CSOffsetExpr; - unsigned ID; + uint64_t ID; LocationVec Locations; - CallsiteInfo() : CSOffsetExpr(0), ID(0) {} - CallsiteInfo(const MCExpr *CSOffsetExpr, unsigned ID, - LocationVec Locations) - : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations) {} + LiveOutVec LiveOuts; + CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {} + CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID, + LocationVec &Locations, LiveOutVec &LiveOuts) + : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations), + LiveOuts(LiveOuts) {} }; typedef std::vector<CallsiteInfo> CallsiteInfoList; - struct ConstantPool { - private: - typedef std::map<int64_t, size_t> ConstantsMap; - std::vector<int64_t> ConstantsList; - ConstantsMap ConstantIndexes; - - public: - size_t getNumConstants() const { return ConstantsList.size(); } - int64_t getConstant(size_t Idx) const { return ConstantsList[Idx]; } - size_t getConstantIndex(int64_t ConstVal) { - size_t NextIdx = ConstantsList.size(); - ConstantsMap::const_iterator I = - ConstantIndexes.insert(ConstantIndexes.end(), - std::make_pair(ConstVal, NextIdx)); - if (I->second == NextIdx) - ConstantsList.push_back(ConstVal); - return I->second; - } - }; - AsmPrinter &AP; - OperandParser OpParser; CallsiteInfoList CSInfos; ConstantPool ConstPool; + FnStackSizeMap FnStackSize; + + MachineInstr::const_mop_iterator + parseOperand(MachineInstr::const_mop_iterator MOI, + MachineInstr::const_mop_iterator MOE, + LocationVec &Locs, LiveOutVec &LiveOuts) const; + + /// \brief Create a live-out register record for the given register @p Reg. + LiveOutReg createLiveOutReg(unsigned Reg, + const TargetRegisterInfo *TRI) const; + + /// \brief Parse the register live-out mask and return a vector of live-out + /// registers that need to be recorded in the stackmap. + LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const; /// This should be called by the MC lowering code _immediately_ before /// lowering the MI to an MCInst. It records where the operands for the /// instruction are stored, and outputs a label to record the offset of /// the call from the start of the text section. In special cases (e.g. AnyReg /// calling convention) the return register is also recorded if requested. - void recordStackMapOpers(const MachineInstr &MI, uint32_t ID, + void recordStackMapOpers(const MachineInstr &MI, uint64_t ID, MachineInstr::const_mop_iterator MOI, MachineInstr::const_mop_iterator MOE, bool recordResult = false); + + /// \brief Emit the stackmap header. + void emitStackmapHeader(MCStreamer &OS); + + /// \brief Emit the function frame record for each function. + void emitFunctionFrameRecords(MCStreamer &OS); + + /// \brief Emit the constant pool. + void emitConstantPoolEntries(MCStreamer &OS); + + /// \brief Emit the callsite info for each stackmap/patchpoint intrinsic call. + void emitCallsiteEntries(MCStreamer &OS, const TargetRegisterInfo *TRI); }; } diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h index d09a933a663b..8cef85cb4485 100644 --- a/include/llvm/CodeGen/StackProtector.h +++ b/include/llvm/CodeGen/StackProtector.h @@ -19,12 +19,12 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Triple.h" -#include "llvm/ADT/ValueMap.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/ValueMap.h" #include "llvm/Pass.h" #include "llvm/Target/TargetLowering.h" namespace llvm { -class DominatorTree; class Function; class Module; class PHINode; @@ -105,22 +105,24 @@ private: public: static char ID; // Pass identification, replacement for typeid. - StackProtector() : FunctionPass(ID), TM(0), TLI(0), SSPBufferSize(0) { + StackProtector() + : FunctionPass(ID), TM(nullptr), TLI(nullptr), SSPBufferSize(0) { initializeStackProtectorPass(*PassRegistry::getPassRegistry()); } StackProtector(const TargetMachine *TM) - : FunctionPass(ID), TM(TM), TLI(0), Trip(TM->getTargetTriple()), + : FunctionPass(ID), TM(TM), TLI(nullptr), Trip(TM->getTargetTriple()), SSPBufferSize(8) { initializeStackProtectorPass(*PassRegistry::getPassRegistry()); } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addPreserved<DominatorTree>(); + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addPreserved<DominatorTreeWrapperPass>(); } SSPLayoutKind getSSPLayout(const AllocaInst *AI) const; + void adjustForColoring(const AllocaInst *From, const AllocaInst *To); - virtual bool runOnFunction(Function &Fn); + bool runOnFunction(Function &Fn) override; }; } // end namespace llvm diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 5b22c9c685ae..87f140190a75 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -38,81 +38,83 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { public: virtual ~TargetLoweringObjectFileELF() {} - virtual void emitPersonalityValue(MCStreamer &Streamer, + void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, + const MCSymbol *Sym) const override; + + /// Given a constant with the SectionKind, return a section that it should be + /// placed in. + const MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const override; + + const MCSection *getExplicitSectionGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const override; + + const MCSection *SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const override; + + /// Return an MCExpr to use for a reference to the specified type info global + /// variable from exception handling information. + const MCExpr * + getTTypeGlobalReference(const GlobalValue *GV, unsigned Encoding, + Mangler &Mang, const TargetMachine &TM, + MachineModuleInfo *MMI, + MCStreamer &Streamer) const override; + + // The symbol that gets passed to .cfi_personality. + MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, Mangler &Mang, const TargetMachine &TM, - const MCSymbol *Sym) const; + MachineModuleInfo *MMI) const override; - /// getSectionForConstant - Given a constant with the SectionKind, return a - /// section that it should be placed in. - virtual const MCSection *getSectionForConstant(SectionKind Kind) const; + void InitializeELF(bool UseInitArray_); + const MCSection *getStaticCtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; + const MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; +}; - virtual const MCSection * - getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const; - virtual const MCSection * - SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const; +class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { +public: + virtual ~TargetLoweringObjectFileMachO() {} - /// getTTypeGlobalReference - Return an MCExpr to use for a reference to the - /// specified type info global variable from exception handling information. - virtual const MCExpr * - getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, unsigned Encoding, - MCStreamer &Streamer) const; + /// Extract the dependent library name from a linker option string. Returns + /// StringRef() if the option does not specify a library. + StringRef getDepLibFromLinkerOpt(StringRef LinkerOption) const override; - // getCFIPersonalitySymbol - The symbol that gets passed to .cfi_personality. - virtual MCSymbol * - getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI) const; + /// Emit the module flags that specify the garbage collection information. + void emitModuleFlags(MCStreamer &Streamer, + ArrayRef<Module::ModuleFlagEntry> ModuleFlags, + Mangler &Mang, const TargetMachine &TM) const override; - void InitializeELF(bool UseInitArray_); - virtual const MCSection * - getStaticCtorSection(unsigned Priority = 65535) const; - virtual const MCSection * - getStaticDtorSection(unsigned Priority = 65535) const; -}; + bool isSectionAtomizableBySymbols(const MCSection &Section) const override; + const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const override; + const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const override; -class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { -public: - virtual ~TargetLoweringObjectFileMachO() {} + const MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const override; + + /// The mach-o version of this method defaults to returning a stub reference. + const MCExpr * + getTTypeGlobalReference(const GlobalValue *GV, unsigned Encoding, + Mangler &Mang, const TargetMachine &TM, + MachineModuleInfo *MMI, + MCStreamer &Streamer) const override; - /// emitModuleFlags - Emit the module flags that specify the garbage - /// collection information. - virtual void emitModuleFlags(MCStreamer &Streamer, - ArrayRef<Module::ModuleFlagEntry> ModuleFlags, - Mangler *Mang, const TargetMachine &TM) const; - - virtual const MCSection * - SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const; - - virtual const MCSection * - getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const; - - virtual const MCSection *getSectionForConstant(SectionKind Kind) const; - - /// shouldEmitUsedDirectiveFor - This hook allows targets to selectively - /// decide not to emit the UsedDirective for some symbols in llvm.used. - /// FIXME: REMOVE this (rdar://7071300) - virtual bool shouldEmitUsedDirectiveFor(const GlobalValue *GV, - Mangler *) const; - - /// getTTypeGlobalReference - The mach-o version of this method - /// defaults to returning a stub reference. - virtual const MCExpr * - getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, unsigned Encoding, - MCStreamer &Streamer) const; - - // getCFIPersonalitySymbol - The symbol that gets passed to .cfi_personality. - virtual MCSymbol * - getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI) const; + // The symbol that gets passed to .cfi_personality. + MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, Mangler &Mang, + const TargetMachine &TM, + MachineModuleInfo *MMI) const override; }; @@ -121,19 +123,30 @@ class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { public: virtual ~TargetLoweringObjectFileCOFF() {} - virtual const MCSection * - getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const; - - virtual const MCSection * - SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const; - - /// emitModuleFlags - Emit Obj-C garbage collection and linker options. Only - /// linker option emission is implemented for COFF. - virtual void emitModuleFlags(MCStreamer &Streamer, - ArrayRef<Module::ModuleFlagEntry> ModuleFlags, - Mangler *Mang, const TargetMachine &TM) const; + const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const override; + + const MCSection * + SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const override; + + /// Extract the dependent library name from a linker option string. Returns + /// StringRef() if the option does not specify a library. + StringRef getDepLibFromLinkerOpt(StringRef LinkerOption) const override; + + /// Emit Obj-C garbage collection and linker options. Only linker option + /// emission is implemented for COFF. + void emitModuleFlags(MCStreamer &Streamer, + ArrayRef<Module::ModuleFlagEntry> ModuleFlags, + Mangler &Mang, const TargetMachine &TM) const override; + + const MCSection *getStaticCtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; + const MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; }; } // end namespace llvm diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index 8ef26b7ca548..690b70fad89b 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -41,7 +41,7 @@ class TargetSchedModel { unsigned MicroOpFactor; // Multiply to normalize microops to resource units. unsigned ResourceLCM; // Resource units per cycle. Latency normalization factor. public: - TargetSchedModel(): STI(0), TII(0) {} + TargetSchedModel(): STI(nullptr), TII(nullptr) {} /// \brief Initialize the machine model for instruction scheduling. /// @@ -75,7 +75,7 @@ public: const InstrItineraryData *getInstrItineraries() const { if (hasInstrItineraries()) return &InstrItins; - return 0; + return nullptr; } /// \brief Identify the processor corresponding to the current subtarget. @@ -86,7 +86,7 @@ public: /// \brief Return the number of issue slots required for this MI. unsigned getNumMicroOps(const MachineInstr *MI, - const MCSchedClassDesc *SC = 0) const; + const MCSchedClassDesc *SC = nullptr) const; /// \brief Get the number of kinds of resources for this target. unsigned getNumProcResourceKinds() const { @@ -98,6 +98,14 @@ public: return SchedModel.getProcResource(PIdx); } +#ifndef NDEBUG + const char *getResourceName(unsigned PIdx) const { + if (!PIdx) + return "MOps"; + return SchedModel.getProcResource(PIdx)->Name; + } +#endif + typedef const MCWriteProcResEntry *ProcResIter; // \brief Get an iterator into the processor resources consumed by this @@ -150,7 +158,7 @@ public: /// model. /// /// Compute and return the expected latency of this instruction independent of - /// a particular use. computeOperandLatency is the prefered API, but this is + /// a particular use. computeOperandLatency is the preferred API, but this is /// occasionally useful to help estimate instruction cost. /// /// If UseDefaultDefLatency is false and no new machine sched model is diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index 79f323341fd0..4e93940e223e 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -16,559 +16,14 @@ #ifndef LLVM_CODEGEN_VALUETYPES_H #define LLVM_CODEGEN_VALUETYPES_H -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" +#include "llvm/CodeGen/MachineValueType.h" #include <cassert> #include <string> namespace llvm { - class Type; - class LLVMContext; - struct EVT; - - /// MVT - Machine Value Type. Every type that is supported natively by some - /// processor targeted by LLVM occurs here. This means that any legal value - /// type can be represented by an MVT. - class MVT { - public: - enum SimpleValueType { - // INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are - // considered extended value types. - INVALID_SIMPLE_VALUE_TYPE = -1, - - // If you change this numbering, you must change the values in - // ValueTypes.td as well! - Other = 0, // This is a non-standard value - i1 = 1, // This is a 1 bit integer value - i8 = 2, // This is an 8 bit integer value - i16 = 3, // This is a 16 bit integer value - i32 = 4, // This is a 32 bit integer value - i64 = 5, // This is a 64 bit integer value - i128 = 6, // This is a 128 bit integer value - - FIRST_INTEGER_VALUETYPE = i1, - LAST_INTEGER_VALUETYPE = i128, - - f16 = 7, // This is a 16 bit floating point value - f32 = 8, // This is a 32 bit floating point value - f64 = 9, // This is a 64 bit floating point value - f80 = 10, // This is a 80 bit floating point value - f128 = 11, // This is a 128 bit floating point value - ppcf128 = 12, // This is a PPC 128-bit floating point value - - FIRST_FP_VALUETYPE = f16, - LAST_FP_VALUETYPE = ppcf128, - - v2i1 = 13, // 2 x i1 - v4i1 = 14, // 4 x i1 - v8i1 = 15, // 8 x i1 - v16i1 = 16, // 16 x i1 - v32i1 = 17, // 32 x i1 - v64i1 = 18, // 64 x i1 - - v1i8 = 19, // 1 x i8 - v2i8 = 20, // 2 x i8 - v4i8 = 21, // 4 x i8 - v8i8 = 22, // 8 x i8 - v16i8 = 23, // 16 x i8 - v32i8 = 24, // 32 x i8 - v64i8 = 25, // 64 x i8 - v1i16 = 26, // 1 x i16 - v2i16 = 27, // 2 x i16 - v4i16 = 28, // 4 x i16 - v8i16 = 29, // 8 x i16 - v16i16 = 30, // 16 x i16 - v32i16 = 31, // 32 x i16 - v1i32 = 32, // 1 x i32 - v2i32 = 33, // 2 x i32 - v4i32 = 34, // 4 x i32 - v8i32 = 35, // 8 x i32 - v16i32 = 36, // 16 x i32 - v1i64 = 37, // 1 x i64 - v2i64 = 38, // 2 x i64 - v4i64 = 39, // 4 x i64 - v8i64 = 40, // 8 x i64 - v16i64 = 41, // 16 x i64 - - FIRST_INTEGER_VECTOR_VALUETYPE = v2i1, - LAST_INTEGER_VECTOR_VALUETYPE = v16i64, - - v2f16 = 42, // 2 x f16 - v4f16 = 43, // 4 x f16 - v8f16 = 44, // 8 x f16 - v1f32 = 45, // 1 x f32 - v2f32 = 46, // 2 x f32 - v4f32 = 47, // 4 x f32 - v8f32 = 48, // 8 x f32 - v16f32 = 49, // 16 x f32 - v1f64 = 50, // 1 x f64 - v2f64 = 51, // 2 x f64 - v4f64 = 52, // 4 x f64 - v8f64 = 53, // 8 x f64 - - FIRST_FP_VECTOR_VALUETYPE = v2f16, - LAST_FP_VECTOR_VALUETYPE = v8f64, - - FIRST_VECTOR_VALUETYPE = v2i1, - LAST_VECTOR_VALUETYPE = v8f64, - - x86mmx = 54, // This is an X86 MMX value - - Glue = 55, // This glues nodes together during pre-RA sched - - isVoid = 56, // This has no value - - Untyped = 57, // This value takes a register, but has - // unspecified type. The register class - // will be determined by the opcode. - - LAST_VALUETYPE = 58, // This always remains at the end of the list. - - // This is the current maximum for LAST_VALUETYPE. - // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors - // This value must be a multiple of 32. - MAX_ALLOWED_VALUETYPE = 64, - - // Metadata - This is MDNode or MDString. - Metadata = 250, - - // iPTRAny - An int value the size of the pointer of the current - // target to any address space. This must only be used internal to - // tblgen. Other than for overloading, we treat iPTRAny the same as iPTR. - iPTRAny = 251, - - // vAny - A vector with any length and element size. This is used - // for intrinsics that have overloadings based on vector types. - // This is only for tblgen's consumption! - vAny = 252, - - // fAny - Any floating-point or vector floating-point value. This is used - // for intrinsics that have overloadings based on floating-point types. - // This is only for tblgen's consumption! - fAny = 253, - - // iAny - An integer or vector integer value of any bit width. This is - // used for intrinsics that have overloadings based on integer bit widths. - // This is only for tblgen's consumption! - iAny = 254, - - // iPTR - An int value the size of the pointer of the current - // target. This should only be used internal to tblgen! - iPTR = 255 - }; - - SimpleValueType SimpleTy; - - MVT() : SimpleTy((SimpleValueType)(INVALID_SIMPLE_VALUE_TYPE)) {} - MVT(SimpleValueType SVT) : SimpleTy(SVT) { } - - bool operator>(const MVT& S) const { return SimpleTy > S.SimpleTy; } - bool operator<(const MVT& S) const { return SimpleTy < S.SimpleTy; } - bool operator==(const MVT& S) const { return SimpleTy == S.SimpleTy; } - bool operator!=(const MVT& S) const { return SimpleTy != S.SimpleTy; } - bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } - bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } - - /// isFloatingPoint - Return true if this is a FP, or a vector FP type. - bool isFloatingPoint() const { - return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE && - SimpleTy <= MVT::LAST_FP_VALUETYPE) || - (SimpleTy >= MVT::FIRST_FP_VECTOR_VALUETYPE && - SimpleTy <= MVT::LAST_FP_VECTOR_VALUETYPE)); - } - - /// isInteger - Return true if this is an integer, or a vector integer type. - bool isInteger() const { - return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && - SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) || - (SimpleTy >= MVT::FIRST_INTEGER_VECTOR_VALUETYPE && - SimpleTy <= MVT::LAST_INTEGER_VECTOR_VALUETYPE)); - } - - /// isVector - Return true if this is a vector value type. - bool isVector() const { - return (SimpleTy >= MVT::FIRST_VECTOR_VALUETYPE && - SimpleTy <= MVT::LAST_VECTOR_VALUETYPE); - } - - /// is16BitVector - Return true if this is a 16-bit vector type. - bool is16BitVector() const { - return (SimpleTy == MVT::v2i8 || SimpleTy == MVT::v1i16 || - SimpleTy == MVT::v16i1); - } - - /// is32BitVector - Return true if this is a 32-bit vector type. - bool is32BitVector() const { - return (SimpleTy == MVT::v4i8 || SimpleTy == MVT::v2i16 || - SimpleTy == MVT::v1i32); - } - - /// is64BitVector - Return true if this is a 64-bit vector type. - bool is64BitVector() const { - return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 || - SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 || - SimpleTy == MVT::v1f64 || SimpleTy == MVT::v2f32); - } - - /// is128BitVector - Return true if this is a 128-bit vector type. - bool is128BitVector() const { - return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 || - SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 || - SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64); - } - - /// is256BitVector - Return true if this is a 256-bit vector type. - bool is256BitVector() const { - return (SimpleTy == MVT::v8f32 || SimpleTy == MVT::v4f64 || - SimpleTy == MVT::v32i8 || SimpleTy == MVT::v16i16 || - SimpleTy == MVT::v8i32 || SimpleTy == MVT::v4i64); - } - - /// is512BitVector - Return true if this is a 512-bit vector type. - bool is512BitVector() const { - return (SimpleTy == MVT::v8f64 || SimpleTy == MVT::v16f32 || - SimpleTy == MVT::v64i8 || SimpleTy == MVT::v32i16 || - SimpleTy == MVT::v8i64 || SimpleTy == MVT::v16i32); - } - - /// is1024BitVector - Return true if this is a 1024-bit vector type. - bool is1024BitVector() const { - return (SimpleTy == MVT::v16i64); - } - - /// isPow2VectorType - Returns true if the given vector is a power of 2. - bool isPow2VectorType() const { - unsigned NElts = getVectorNumElements(); - return !(NElts & (NElts - 1)); - } - - /// getPow2VectorType - Widens the length of the given vector MVT up to - /// the nearest power of 2 and returns that type. - MVT getPow2VectorType() const { - if (isPow2VectorType()) - return *this; - - unsigned NElts = getVectorNumElements(); - unsigned Pow2NElts = 1 << Log2_32_Ceil(NElts); - return MVT::getVectorVT(getVectorElementType(), Pow2NElts); - } - - /// getScalarType - If this is a vector type, return the element type, - /// otherwise return this. - MVT getScalarType() const { - return isVector() ? getVectorElementType() : *this; - } - - MVT getVectorElementType() const { - switch (SimpleTy) { - default: - llvm_unreachable("Not a vector MVT!"); - case v2i1 : - case v4i1 : - case v8i1 : - case v16i1 : - case v32i1 : - case v64i1: return i1; - case v1i8 : - case v2i8 : - case v4i8 : - case v8i8 : - case v16i8: - case v32i8: - case v64i8: return i8; - case v1i16: - case v2i16: - case v4i16: - case v8i16: - case v16i16: - case v32i16: return i16; - case v1i32: - case v2i32: - case v4i32: - case v8i32: - case v16i32: return i32; - case v1i64: - case v2i64: - case v4i64: - case v8i64: - case v16i64: return i64; - case v2f16: - case v4f16: - case v8f16: return f16; - case v1f32: - case v2f32: - case v4f32: - case v8f32: - case v16f32: return f32; - case v1f64: - case v2f64: - case v4f64: - case v8f64: return f64; - } - } - - unsigned getVectorNumElements() const { - switch (SimpleTy) { - default: - llvm_unreachable("Not a vector MVT!"); - case v32i1: - case v32i8: - case v32i16: return 32; - case v64i1: - case v64i8: return 64; - case v16i1: - case v16i8: - case v16i16: - case v16i32: - case v16i64: - case v16f32: return 16; - case v8i1 : - case v8i8 : - case v8i16: - case v8i32: - case v8i64: - case v8f16: - case v8f32: - case v8f64: return 8; - case v4i1: - case v4i8: - case v4i16: - case v4i32: - case v4i64: - case v4f16: - case v4f32: - case v4f64: return 4; - case v2i1: - case v2i8: - case v2i16: - case v2i32: - case v2i64: - case v2f16: - case v2f32: - case v2f64: return 2; - case v1i8: - case v1i16: - case v1i32: - case v1i64: - case v1f32: - case v1f64: return 1; - } - } - - unsigned getSizeInBits() const { - switch (SimpleTy) { - default: - llvm_unreachable("getSizeInBits called on extended MVT."); - case Other: - llvm_unreachable("Value type is non-standard value, Other."); - case iPTR: - llvm_unreachable("Value type size is target-dependent. Ask TLI."); - case iPTRAny: - case iAny: - case fAny: - case vAny: - llvm_unreachable("Value type is overloaded."); - case Metadata: - llvm_unreachable("Value type is metadata."); - case i1 : return 1; - case v2i1: return 2; - case v4i1: return 4; - case i8 : - case v1i8: - case v8i1: return 8; - case i16 : - case f16: - case v16i1: - case v2i8: - case v1i16: return 16; - case f32 : - case i32 : - case v32i1: - case v4i8: - case v2i16: - case v2f16: - case v1f32: - case v1i32: return 32; - case x86mmx: - case f64 : - case i64 : - case v64i1: - case v8i8: - case v4i16: - case v2i32: - case v1i64: - case v4f16: - case v2f32: - case v1f64: return 64; - case f80 : return 80; - case f128: - case ppcf128: - case i128: - case v16i8: - case v8i16: - case v4i32: - case v2i64: - case v8f16: - case v4f32: - case v2f64: return 128; - case v32i8: - case v16i16: - case v8i32: - case v4i64: - case v8f32: - case v4f64: return 256; - case v64i8: - case v32i16: - case v16i32: - case v8i64: - case v16f32: - case v8f64: return 512; - case v16i64:return 1024; - } - } - - /// getStoreSize - Return the number of bytes overwritten by a store - /// of the specified value type. - unsigned getStoreSize() const { - return (getSizeInBits() + 7) / 8; - } - - /// getStoreSizeInBits - Return the number of bits overwritten by a store - /// of the specified value type. - unsigned getStoreSizeInBits() const { - return getStoreSize() * 8; - } - - /// Return true if this has more bits than VT. - bool bitsGT(MVT VT) const { - return getSizeInBits() > VT.getSizeInBits(); - } - - /// Return true if this has no less bits than VT. - bool bitsGE(MVT VT) const { - return getSizeInBits() >= VT.getSizeInBits(); - } - - /// Return true if this has less bits than VT. - bool bitsLT(MVT VT) const { - return getSizeInBits() < VT.getSizeInBits(); - } - - /// Return true if this has no more bits than VT. - bool bitsLE(MVT VT) const { - return getSizeInBits() <= VT.getSizeInBits(); - } - - - static MVT getFloatingPointVT(unsigned BitWidth) { - switch (BitWidth) { - default: - llvm_unreachable("Bad bit width!"); - case 16: - return MVT::f16; - case 32: - return MVT::f32; - case 64: - return MVT::f64; - case 80: - return MVT::f80; - case 128: - return MVT::f128; - } - } - - static MVT getIntegerVT(unsigned BitWidth) { - switch (BitWidth) { - default: - return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); - case 1: - return MVT::i1; - case 8: - return MVT::i8; - case 16: - return MVT::i16; - case 32: - return MVT::i32; - case 64: - return MVT::i64; - case 128: - return MVT::i128; - } - } - - static MVT getVectorVT(MVT VT, unsigned NumElements) { - switch (VT.SimpleTy) { - default: - break; - case MVT::i1: - if (NumElements == 2) return MVT::v2i1; - if (NumElements == 4) return MVT::v4i1; - if (NumElements == 8) return MVT::v8i1; - if (NumElements == 16) return MVT::v16i1; - if (NumElements == 32) return MVT::v32i1; - if (NumElements == 64) return MVT::v64i1; - break; - case MVT::i8: - if (NumElements == 1) return MVT::v1i8; - if (NumElements == 2) return MVT::v2i8; - if (NumElements == 4) return MVT::v4i8; - if (NumElements == 8) return MVT::v8i8; - if (NumElements == 16) return MVT::v16i8; - if (NumElements == 32) return MVT::v32i8; - if (NumElements == 64) return MVT::v64i8; - break; - case MVT::i16: - if (NumElements == 1) return MVT::v1i16; - if (NumElements == 2) return MVT::v2i16; - if (NumElements == 4) return MVT::v4i16; - if (NumElements == 8) return MVT::v8i16; - if (NumElements == 16) return MVT::v16i16; - if (NumElements == 32) return MVT::v32i16; - break; - case MVT::i32: - if (NumElements == 1) return MVT::v1i32; - if (NumElements == 2) return MVT::v2i32; - if (NumElements == 4) return MVT::v4i32; - if (NumElements == 8) return MVT::v8i32; - if (NumElements == 16) return MVT::v16i32; - break; - case MVT::i64: - if (NumElements == 1) return MVT::v1i64; - if (NumElements == 2) return MVT::v2i64; - if (NumElements == 4) return MVT::v4i64; - if (NumElements == 8) return MVT::v8i64; - if (NumElements == 16) return MVT::v16i64; - break; - case MVT::f16: - if (NumElements == 2) return MVT::v2f16; - if (NumElements == 4) return MVT::v4f16; - if (NumElements == 8) return MVT::v8f16; - break; - case MVT::f32: - if (NumElements == 1) return MVT::v1f32; - if (NumElements == 2) return MVT::v2f32; - if (NumElements == 4) return MVT::v4f32; - if (NumElements == 8) return MVT::v8f32; - if (NumElements == 16) return MVT::v16f32; - break; - case MVT::f64: - if (NumElements == 1) return MVT::v1f64; - if (NumElements == 2) return MVT::v2f64; - if (NumElements == 4) return MVT::v4f64; - if (NumElements == 8) return MVT::v8f64; - break; - } - return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE); - } - - /// Return the value type corresponding to the specified type. This returns - /// all pointers as iPTR. If HandleUnknown is true, unknown types are - /// returned as Other, otherwise they are invalid. - static MVT getVT(Type *Ty, bool HandleUnknown = false); - - }; + class LLVMContext; + class Type; /// EVT - Extended Value Type. Capable of holding value types which are not /// native for any processor (such as the i12345 type), as well as the types @@ -580,9 +35,9 @@ namespace llvm { public: EVT() : V((MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE)), - LLVMTy(0) {} - EVT(MVT::SimpleValueType SVT) : V(SVT), LLVMTy(0) { } - EVT(MVT S) : V(S), LLVMTy(0) {} + LLVMTy(nullptr) {} + EVT(MVT::SimpleValueType SVT) : V(SVT), LLVMTy(nullptr) { } + EVT(MVT S) : V(S), LLVMTy(nullptr) {} bool operator==(EVT VT) const { return !(*this != VT); @@ -782,6 +237,10 @@ namespace llvm { return getExtendedSizeInBits(); } + unsigned getScalarSizeInBits() const { + return getScalarType().getSizeInBits(); + } + /// getStoreSize - Return the number of bytes overwritten by a store /// of the specified value type. unsigned getStoreSize() const { @@ -821,6 +280,14 @@ namespace llvm { return getIntegerVT(Context, (EVTSize + 1) / 2); } + /// \brief Return a VT for an integer vector type with the size of the + /// elements doubled. The typed returned may be an extended type. + EVT widenIntegerVectorElementType(LLVMContext &Context) const { + EVT EltVT = getVectorElementType(); + EltVT = EVT::getIntegerVT(Context, 2 * EltVT.getSizeInBits()); + return EVT::getVectorVT(Context, EltVT, getVectorNumElements()); + } + /// isPow2VectorType - Returns true if the given vector is a power of 2. bool isPow2VectorType() const { unsigned NElts = getVectorNumElements(); @@ -880,18 +347,18 @@ namespace llvm { static EVT getExtendedIntegerVT(LLVMContext &C, unsigned BitWidth); static EVT getExtendedVectorVT(LLVMContext &C, EVT VT, unsigned NumElements); - bool isExtendedFloatingPoint() const; - bool isExtendedInteger() const; - bool isExtendedVector() const; - bool isExtended16BitVector() const; - bool isExtended32BitVector() const; - bool isExtended64BitVector() const; - bool isExtended128BitVector() const; - bool isExtended256BitVector() const; - bool isExtended512BitVector() const; - bool isExtended1024BitVector() const; + bool isExtendedFloatingPoint() const LLVM_READONLY; + bool isExtendedInteger() const LLVM_READONLY; + bool isExtendedVector() const LLVM_READONLY; + bool isExtended16BitVector() const LLVM_READONLY; + bool isExtended32BitVector() const LLVM_READONLY; + bool isExtended64BitVector() const LLVM_READONLY; + bool isExtended128BitVector() const LLVM_READONLY; + bool isExtended256BitVector() const LLVM_READONLY; + bool isExtended512BitVector() const LLVM_READONLY; + bool isExtended1024BitVector() const LLVM_READONLY; EVT getExtendedVectorElementType() const; - unsigned getExtendedVectorNumElements() const; + unsigned getExtendedVectorNumElements() const LLVM_READONLY; unsigned getExtendedSizeInBits() const; }; diff --git a/include/llvm/CodeGen/VirtRegMap.h b/include/llvm/CodeGen/VirtRegMap.h index 3bc6ebd563f2..eceb8755763e 100644 --- a/include/llvm/CodeGen/VirtRegMap.h +++ b/include/llvm/CodeGen/VirtRegMap.h @@ -70,9 +70,9 @@ namespace llvm { static char ID; VirtRegMap() : MachineFunctionPass(ID), Virt2PhysMap(NO_PHYS_REG), Virt2StackSlotMap(NO_STACK_SLOT), Virt2SplitMap(0) { } - virtual bool runOnMachineFunction(MachineFunction &MF); + bool runOnMachineFunction(MachineFunction &MF) override; - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); MachineFunctionPass::getAnalysisUsage(AU); } @@ -177,7 +177,7 @@ namespace llvm { /// the specified stack slot void assignVirt2StackSlot(unsigned virtReg, int frameIndex); - void print(raw_ostream &OS, const Module* M = 0) const; + void print(raw_ostream &OS, const Module* M = nullptr) const override; void dump() const; }; diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 5c72ad8a99c2..996f9ba29a12 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -3,20 +3,14 @@ #ifndef CONFIG_H #define CONFIG_H -/* Bug report URL. */ -#define BUG_REPORT_URL "${BUG_REPORT_URL}" - -/* Define if we have libxml2 */ -#cmakedefine CLANG_HAVE_LIBXML ${CLANG_HAVE_LIBXML} - -/* Relative directory for resource files */ -#define CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}" +/* Exported configuration */ +#include "llvm/Config/llvm-config.h" -/* Directories clang will search for headers */ -#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}" +/* Patch version of the LLVM API */ +#cmakedefine LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} -/* Default <path> to all compiler invocations for --sysroot=<path>. */ -#undef DEFAULT_SYSROOT +/* Bug report URL. */ +#define BUG_REPORT_URL "${BUG_REPORT_URL}" /* Define if you want backtraces on crash */ #cmakedefine ENABLE_BACKTRACES @@ -30,11 +24,8 @@ /* Define if timestamp information (e.g., __DATE__) is allowed */ #cmakedefine ENABLE_TIMESTAMPS ${ENABLE_TIMESTAMPS} -/* Directory where gcc is installed. */ -#undef GCC_INSTALL_PREFIX - /* Define to 1 if you have the `arc4random' function. */ -#cmakedefine HAVE_ARC4RANDOM +#cmakedefine HAVE_DECL_ARC4RANDOM ${HAVE_DECL_ARC4RANDOM} /* Define to 1 if you have the `backtrace' function. */ #cmakedefine HAVE_BACKTRACE ${HAVE_BACKTRACE} @@ -45,9 +36,6 @@ /* Define to 1 if you have the `ceilf' function. */ #cmakedefine HAVE_CEILF ${HAVE_CEILF} -/* Define if the neat program is available */ -#cmakedefine HAVE_CIRCO ${HAVE_CIRCO} - /* Define to 1 if you have the `closedir' function. */ #cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR} @@ -80,12 +68,6 @@ /* Define if dlopen() is available on this platform. */ #cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN} -/* Define if the dot program is available */ -#cmakedefine HAVE_DOT ${HAVE_DOT} - -/* Define if the dotty program is available */ -#cmakedefine HAVE_DOTTY ${HAVE_DOTTY} - /* Define if you have the _dyld_func_lookup function. */ #undef HAVE_DYLD @@ -98,9 +80,6 @@ /* Define to 1 if you have the <fcntl.h> header file. */ #cmakedefine HAVE_FCNTL_H ${HAVE_FCNTL_H} -/* Define if the neat program is available */ -#cmakedefine HAVE_FDP ${HAVE_FDP} - /* Define to 1 if you have the <fenv.h> header file. */ #cmakedefine HAVE_FENV_H ${HAVE_FENV_H} @@ -161,12 +140,6 @@ /* Define to 1 if you have the `gettimeofday' function. */ #cmakedefine HAVE_GETTIMEOFDAY ${HAVE_GETTIMEOFDAY} -/* Define if the Graphviz program is available */ -#cmakedefine HAVE_GRAPHVIZ ${HAVE_GRAPHVIZ} - -/* Define if the gv program is available */ -#cmakedefine HAVE_GV ${HAVE_GV} - /* Define to 1 if the system has the type `int64_t'. */ #cmakedefine HAVE_INT64_T ${HAVE_INT64_T} @@ -206,12 +179,12 @@ /* Define to 1 if you have the `shell32' library (-lshell32). */ #cmakedefine HAVE_LIBSHELL32 ${HAVE_LIBSHELL32} -/* Define to 1 if you have the `udis86' library (-ludis86). */ -#undef HAVE_LIBUDIS86 - /* Define to 1 if you have the 'z' library (-lz). */ #cmakedefine HAVE_LIBZ ${HAVE_LIBZ} +/* Define to 1 if you have the 'edit' library (-ledit). */ +#cmakedefine HAVE_LIBEDIT ${HAVE_LIBEDIT} + /* Define to 1 if you have the <limits.h> header file. */ #cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H} @@ -268,9 +241,6 @@ /* Define to 1 if you have the `nearbyintf' function. */ #cmakedefine HAVE_NEARBYINTF ${HAVE_NEARBYINTF} -/* Define if the neat program is available */ -#cmakedefine HAVE_NEATO ${HAVE_NEATO} - /* Define to 1 if you have the `opendir' function. */ #cmakedefine HAVE_OPENDIR ${HAVE_OPENDIR} @@ -414,9 +384,6 @@ /* Define to 1 if you have the <termios.h> header file. */ #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} -/* Define if the neat program is available */ -#cmakedefine HAVE_TWOPI ${HAVE_TWOPI} - /* Define to 1 if the system has the type `uint64_t'. */ #cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T} @@ -435,9 +402,6 @@ /* Define to 1 if you have the `writev' function. */ #cmakedefine HAVE_WRITEV ${HAVE_WRITEV} -/* Define if the xdot.py program is available */ -#cmakedefine HAVE_XDOT ${HAVE_XDOT} - /* Define to 1 if you have the <zlib.h> header file. */ #cmakedefine HAVE_ZLIB_H ${HAVE_ZLIB_H} @@ -495,114 +459,12 @@ /* Linker version detected at compile time. */ #undef HOST_LINK_VERSION -/* Installation directory for binary executables */ -#cmakedefine LLVM_BINDIR "${LLVM_BINDIR}" - -/* Time at which LLVM was configured */ -#cmakedefine LLVM_CONFIGTIME "${LLVM_CONFIGTIME}" - -/* Installation directory for data files */ -#cmakedefine LLVM_DATADIR "${LLVM_DATADIR}" - -/* Target triple LLVM will generate code for by default */ -#cmakedefine LLVM_DEFAULT_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" - -/* Installation directory for documentation */ -#cmakedefine LLVM_DOCSDIR "${LLVM_DOCSDIR}" - -/* Define if threads enabled */ -#cmakedefine01 LLVM_ENABLE_THREADS +/* Define if we link Polly to the tools */ +#cmakedefine LINK_POLLY_INTO_TOOLS /* Define if zlib compression is available */ #cmakedefine01 LLVM_ENABLE_ZLIB -/* Installation directory for config files */ -#cmakedefine LLVM_ETCDIR "${LLVM_ETCDIR}" - -/* Has gcc/MSVC atomic intrinsics */ -#cmakedefine01 LLVM_HAS_ATOMICS - -/* Host triple LLVM will be executed on */ -#cmakedefine LLVM_HOST_TRIPLE "${LLVM_HOST_TRIPLE}" - -/* Installation directory for include files */ -#cmakedefine LLVM_INCLUDEDIR "${LLVM_INCLUDEDIR}" - -/* Installation directory for .info files */ -#cmakedefine LLVM_INFODIR "${LLVM_INFODIR}" - -/* Installation directory for man pages */ -#cmakedefine LLVM_MANDIR "${LLVM_MANDIR}" - -/* LLVM architecture name for the native architecture, if available */ -#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH} - -/* LLVM name for the native AsmParser init function, if available */ -#cmakedefine LLVM_NATIVE_ASMPARSER LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser - -/* LLVM name for the native AsmPrinter init function, if available */ -#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter - -/* LLVM name for the native Disassembler init function, if available */ -#cmakedefine LLVM_NATIVE_DISASSEMBLER LLVMInitialize${LLVM_NATIVE_ARCH}Disassembler - -/* LLVM name for the native Target init function, if available */ -#cmakedefine LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target - -/* LLVM name for the native TargetInfo init function, if available */ -#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo - -/* LLVM name for the native target MC init function, if available */ -#cmakedefine LLVM_NATIVE_TARGETMC LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC - -/* Define if this is Unixish platform */ -#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX} - -/* Define if this is Win32ish platform */ -#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32} - -/* Define to path to circo program if found or 'echo circo' otherwise */ -#cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}" - -/* Define to path to dot program if found or 'echo dot' otherwise */ -#cmakedefine LLVM_PATH_DOT "${LLVM_PATH_DOT}" - -/* Define to path to dotty program if found or 'echo dotty' otherwise */ -#cmakedefine LLVM_PATH_DOTTY "${LLVM_PATH_DOTTY}" - -/* Define to path to fdp program if found or 'echo fdp' otherwise */ -#cmakedefine LLVM_PATH_FDP "${LLVM_PATH_FDP}" - -/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ -#cmakedefine LLVM_PATH_GRAPHVIZ "${LLVM_PATH_GRAPHVIZ}" - -/* Define to path to gv program if found or 'echo gv' otherwise */ -#cmakedefine LLVM_PATH_GV "${LLVM_PATH_GV}" - -/* Define to path to neato program if found or 'echo neato' otherwise */ -#cmakedefine LLVM_PATH_NEATO "${LLVM_PATH_NEATO}" - -/* Define to path to twopi program if found or 'echo twopi' otherwise */ -#cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}" - -/* Define to path to xdot.py program if found or 'echo xdot' otherwise */ -#cmakedefine LLVM_PATH_XDOT "${LLVM_PATH_XDOT}" - -/* Installation prefix directory */ -#cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" - -/* Define if we have the Intel JIT API runtime support library */ -#cmakedefine LLVM_USE_INTEL_JITEVENTS 1 - -/* Define if we have the oprofile JIT-support library */ -#cmakedefine LLVM_USE_OPROFILE 1 - -/* Major version of the LLVM API */ -#cmakedefine LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} - -/* Minor version of the LLVM API */ -#cmakedefine LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} - /* Define if the OS needs help to load dependent libraries for dlopen(). */ #cmakedefine LTDL_DLOPEN_DEPLIBS ${LTDL_DLOPEN_DEPLIBS} @@ -653,9 +515,6 @@ /* Define to 1 if your <sys/time.h> declares `struct tm'. */ #undef TM_IN_SYS_TIME -/* Define if use udis86 library */ -#undef USE_UDIS86 - /* Type of 1st arg on ELM Callback */ #cmakedefine WIN32_ELMCB_PCSTR ${WIN32_ELMCB_PCSTR} @@ -683,7 +542,7 @@ /* Define to 1 if you have the `_chsize_s' function. */ #cmakedefine HAVE__CHSIZE_S ${HAVE__CHSIZE_S} -/* Added by Kevin -- Maximum path length */ +/* Maximum path length */ #cmakedefine MAXPATHLEN ${MAXPATHLEN} #endif diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 2317823349ee..beed1182c3f6 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -33,39 +33,12 @@ /* Directory where gcc is installed. */ #undef GCC_INSTALL_PREFIX -/* Define to 1 if you have the `arc4random' function. */ -#undef HAVE_ARC4RANDOM - -/* Define to 1 if you have the `argz_append' function. */ -#undef HAVE_ARGZ_APPEND - -/* Define to 1 if you have the `argz_create_sep' function. */ -#undef HAVE_ARGZ_CREATE_SEP - -/* Define to 1 if you have the <argz.h> header file. */ -#undef HAVE_ARGZ_H - -/* Define to 1 if you have the `argz_insert' function. */ -#undef HAVE_ARGZ_INSERT - -/* Define to 1 if you have the `argz_next' function. */ -#undef HAVE_ARGZ_NEXT - -/* Define to 1 if you have the `argz_stringify' function. */ -#undef HAVE_ARGZ_STRINGIFY - /* Define to 1 if you have the `backtrace' function. */ #undef HAVE_BACKTRACE /* Define to 1 if you have the `ceilf' function. */ #undef HAVE_CEILF -/* Define if the neat program is available */ -#undef HAVE_CIRCO - -/* Define to 1 if you have the `closedir' function. */ -#undef HAVE_CLOSEDIR - /* Define to 1 if you have the <CrashReporterClient.h> header file. */ #undef HAVE_CRASHREPORTERCLIENT_H @@ -75,6 +48,10 @@ /* Define to 1 if you have the <cxxabi.h> header file. */ #undef HAVE_CXXABI_H +/* Define to 1 if you have the declaration of `arc4random', and to 0 if you + don't. */ +#undef HAVE_DECL_ARC4RANDOM + /* Define to 1 if you have the declaration of `FE_ALL_EXCEPT', and to 0 if you don't. */ #undef HAVE_DECL_FE_ALL_EXCEPT @@ -91,12 +68,6 @@ */ #undef HAVE_DIRENT_H -/* Define if you have the GNU dld library. */ -#undef HAVE_DLD - -/* Define to 1 if you have the `dlerror' function. */ -#undef HAVE_DLERROR - /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H @@ -106,18 +77,9 @@ /* Define if the dot program is available */ #undef HAVE_DOT -/* Define if the dotty program is available */ -#undef HAVE_DOTTY - -/* Define if you have the _dyld_func_lookup function. */ -#undef HAVE_DYLD - /* Define to 1 if you have the <errno.h> header file. */ #undef HAVE_ERRNO_H -/* Define to 1 if the system has the type `error_t'. */ -#undef HAVE_ERROR_T - /* Define to 1 if you have the <execinfo.h> header file. */ #undef HAVE_EXECINFO_H @@ -130,9 +92,6 @@ /* Define to 1 if you have the <fcntl.h> header file. */ #undef HAVE_FCNTL_H -/* Define if the neat program is available */ -#undef HAVE_FDP - /* Define to 1 if you have the <fenv.h> header file. */ #undef HAVE_FENV_H @@ -175,12 +134,6 @@ /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY -/* Define if the Graphviz program is available */ -#undef HAVE_GRAPHVIZ - -/* Define if the gv program is available */ -#undef HAVE_GV - /* Define to 1 if the system has the type `int64_t'. */ #undef HAVE_INT64_T @@ -202,8 +155,8 @@ /* Set to 1 if the isnan function is found in <math.h> */ #undef HAVE_ISNAN_IN_MATH_H -/* Define if you have the libdl library or equivalent. */ -#undef HAVE_LIBDL +/* Define if libedit is available on this platform. */ +#undef HAVE_LIBEDIT /* Define to 1 if you have the `imagehlp' library (-limagehlp). */ #undef HAVE_LIBIMAGEHLP @@ -220,9 +173,6 @@ /* Define to 1 if you have the `shell32' library (-lshell32). */ #undef HAVE_LIBSHELL32 -/* Define to 1 if you have the `udis86' library (-ludis86). */ -#undef HAVE_LIBUDIS86 - /* Define to 1 if you have the `z' library (-lz). */ #undef HAVE_LIBZ @@ -251,9 +201,6 @@ /* Define to 1 if you have the <mach/mach.h> header file. */ #undef HAVE_MACH_MACH_H -/* Define to 1 if you have the <mach-o/dyld.h> header file. */ -#undef HAVE_MACH_O_DYLD_H - /* Define if mallinfo() is available on this platform. */ #undef HAVE_MALLINFO @@ -294,12 +241,6 @@ /* Define to 1 if you have the `nearbyintf' function. */ #undef HAVE_NEARBYINTF -/* Define if the neat program is available */ -#undef HAVE_NEATO - -/* Define to 1 if you have the `opendir' function. */ -#undef HAVE_OPENDIR - /* Define to 1 if you have the `posix_spawn' function. */ #undef HAVE_POSIX_SPAWN @@ -309,9 +250,6 @@ /* Define to 1 if you have the `pread' function. */ #undef HAVE_PREAD -/* Define if libtool can extract symbol lists from object files. */ -#undef HAVE_PRELOADED_SYMBOLS - /* Define to have the %a format string */ #undef HAVE_PRINTF_A @@ -330,9 +268,6 @@ /* Define to 1 if srand48/lrand48/drand48 exist in <stdlib.h> */ #undef HAVE_RAND48 -/* Define to 1 if you have the `readdir' function. */ -#undef HAVE_READDIR - /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH @@ -360,9 +295,6 @@ /* Define to 1 if you have the `setrlimit' function. */ #undef HAVE_SETRLIMIT -/* Define if you have the shl_load function. */ -#undef HAVE_SHL_LOAD - /* Define to 1 if you have the `siglongjmp' function. */ #undef HAVE_SIGLONGJMP @@ -449,9 +381,6 @@ /* Define to 1 if you have the <termios.h> header file. */ #undef HAVE_TERMIOS_H -/* Define if the neat program is available */ -#undef HAVE_TWOPI - /* Define to 1 if the system has the type `uint64_t'. */ #undef HAVE_UINT64_T @@ -470,9 +399,6 @@ /* Define to 1 if you have the `writev' function. */ #undef HAVE_WRITEV -/* Define if the xdot program is available */ -#undef HAVE_XDOT - /* Define to 1 if you have the <zlib.h> header file. */ #undef HAVE_ZLIB_H @@ -596,33 +522,9 @@ /* Define if this is Win32ish platform */ #undef LLVM_ON_WIN32 -/* Define to path to circo program if found or 'echo circo' otherwise */ -#undef LLVM_PATH_CIRCO - /* Define to path to dot program if found or 'echo dot' otherwise */ #undef LLVM_PATH_DOT -/* Define to path to dotty program if found or 'echo dotty' otherwise */ -#undef LLVM_PATH_DOTTY - -/* Define to path to fdp program if found or 'echo fdp' otherwise */ -#undef LLVM_PATH_FDP - -/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ -#undef LLVM_PATH_GRAPHVIZ - -/* Define to path to gv program if found or 'echo gv' otherwise */ -#undef LLVM_PATH_GV - -/* Define to path to neato program if found or 'echo neato' otherwise */ -#undef LLVM_PATH_NEATO - -/* Define to path to twopi program if found or 'echo twopi' otherwise */ -#undef LLVM_PATH_TWOPI - -/* Define to path to xdot program if found or 'echo xdot' otherwise */ -#undef LLVM_PATH_XDOT - /* Installation prefix directory */ #undef LLVM_PREFIX @@ -641,26 +543,13 @@ /* Patch version of the LLVM API */ #undef LLVM_VERSION_PATCH -/* Define if the OS needs help to load dependent libraries for dlopen(). */ -#undef LTDL_DLOPEN_DEPLIBS - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#undef LTDL_OBJDIR - -/* Define to the extension used for shared libraries, say, ".so". */ +/* The shared library extension */ #undef LTDL_SHLIB_EXT -/* Define to the system default library search path. */ -#undef LTDL_SYSSEARCHPATH - /* Define if /dev/zero should be used when mapping RWX memory, or undefine if its not necessary */ #undef NEED_DEV_ZERO_FOR_MMAP -/* Define if dlsym() requires a leading underscore in symbol names. */ -#undef NEED_USCORE - /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT @@ -691,18 +580,9 @@ /* Define to 1 if your <sys/time.h> declares `struct tm'. */ #undef TM_IN_SYS_TIME -/* Define if use udis86 library */ -#undef USE_UDIS86 - /* Type of 1st arg on ELM Callback */ #undef WIN32_ELMCB_PCSTR -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - -/* Define to a type to use for `error_t' if it is not otherwise available. */ -#undef error_t - /* Define to `int' if <sys/types.h> does not define. */ #undef pid_t diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index 80616ef9508c..58111644ffa9 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -1,4 +1,4 @@ -/*===-- llvm/config/llvm-config.h - llvm configure variable -------*- C -*-===*/ +/*===------- llvm/Config/llvm-config.h - llvm configuration -------*- C -*-===*/ /* */ /* The LLVM Compiler Infrastructure */ /* */ @@ -7,14 +7,12 @@ /* */ /*===----------------------------------------------------------------------===*/ -/* This file enumerates all of the llvm variables from configure so that - they can be in exported headers and won't override package specific - directives. This is a C file so we can include it in the llvm-c headers. */ +/* This file enumerates variables from the LLVM configuration so that they + can be in exported headers and won't override package specific directives. + This is a C header that can be included in the llvm-c headers. */ -/* To avoid multiple inclusions of these variables when we include the exported - headers and config.h, conditionally include these. */ -/* TODO: This is a bit of a hack. */ -#ifndef CONFIG_H +#ifndef LLVM_CONFIG_H +#define LLVM_CONFIG_H /* Installation directory for binary executables */ #cmakedefine LLVM_BINDIR "${LLVM_BINDIR}" @@ -79,33 +77,6 @@ /* Define if this is Win32ish platform */ #cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32} -/* Define to path to circo program if found or 'echo circo' otherwise */ -#cmakedefine LLVM_PATH_CIRCO "${LLVM_PATH_CIRCO}" - -/* Define to path to dot program if found or 'echo dot' otherwise */ -#cmakedefine LLVM_PATH_DOT "${LLVM_PATH_DOT}" - -/* Define to path to dotty program if found or 'echo dotty' otherwise */ -#cmakedefine LLVM_PATH_DOTTY "${LLVM_PATH_DOTTY}" - -/* Define to path to fdp program if found or 'echo fdp' otherwise */ -#cmakedefine LLVM_PATH_FDP "${LLVM_PATH_FDP}" - -/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ -#cmakedefine LLVM_PATH_GRAPHVIZ "${LLVM_PATH_GRAPHVIZ}" - -/* Define to path to gv program if found or 'echo gv' otherwise */ -#cmakedefine LLVM_PATH_GV "${LLVM_PATH_GV}" - -/* Define to path to neato program if found or 'echo neato' otherwise */ -#cmakedefine LLVM_PATH_NEATO "${LLVM_PATH_NEATO}" - -/* Define to path to twopi program if found or 'echo twopi' otherwise */ -#cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}" - -/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ -#cmakedefine LLVM_PATH_XDOT_PY "${LLVM_PATH_XDOT_PY}" - /* Installation prefix directory */ #cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" @@ -121,7 +92,7 @@ /* Minor version of the LLVM API */ #cmakedefine LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} -/* Define to 1 if you have the <sanitizer/msan_interface.h> header file. */ -#cmakedefine HAVE_SANITIZER_MSAN_INTERFACE_H ${HAVE_SANITIZER_MSAN_INTERFACE_H} +/* Define if we link Polly to the tools */ +#cmakedefine LINK_POLLY_INTO_TOOLS #endif diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index a4fae5537abe..5656240eb127 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -1,4 +1,4 @@ -/*===-- llvm/config/llvm-config.h - llvm configure variable -------*- C -*-===*/ +/*===------- llvm/Config/llvm-config.h - llvm configuration -------*- C -*-===*/ /* */ /* The LLVM Compiler Infrastructure */ /* */ @@ -7,14 +7,12 @@ /* */ /*===----------------------------------------------------------------------===*/ -/* This file enumerates all of the llvm variables from configure so that - they can be in exported headers and won't override package specific - directives. This is a C file so we can include it in the llvm-c headers. */ +/* This file enumerates variables from the LLVM configuration so that they + can be in exported headers and won't override package specific directives. + This is a C header that can be included in the llvm-c headers. */ -/* To avoid multiple inclusions of these variables when we include the exported - headers and config.h, conditionally include these. */ -/* TODO: This is a bit of a hack. */ -#ifndef CONFIG_H +#ifndef LLVM_CONFIG_H +#define LLVM_CONFIG_H /* Installation directory for binary executables */ #undef LLVM_BINDIR @@ -79,33 +77,6 @@ /* Define if this is Win32ish platform */ #undef LLVM_ON_WIN32 -/* Define to path to circo program if found or 'echo circo' otherwise */ -#undef LLVM_PATH_CIRCO - -/* Define to path to dot program if found or 'echo dot' otherwise */ -#undef LLVM_PATH_DOT - -/* Define to path to dotty program if found or 'echo dotty' otherwise */ -#undef LLVM_PATH_DOTTY - -/* Define to path to fdp program if found or 'echo fdp' otherwise */ -#undef LLVM_PATH_FDP - -/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ -#undef LLVM_PATH_GRAPHVIZ - -/* Define to path to gv program if found or 'echo gv' otherwise */ -#undef LLVM_PATH_GV - -/* Define to path to neato program if found or 'echo neato' otherwise */ -#undef LLVM_PATH_NEATO - -/* Define to path to twopi program if found or 'echo twopi' otherwise */ -#undef LLVM_PATH_TWOPI - -/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ -#undef LLVM_PATH_XDOT_PY - /* Installation prefix directory */ #undef LLVM_PREFIX diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index a1a4642103d8..c1aba01fbf75 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -16,42 +16,31 @@ #define LLVM_DEBUGINFO_DICONTEXT_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/RelocVisitor.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" +#include <string> + namespace llvm { class raw_ostream; /// DILineInfo - a format-neutral container for source line information. -class DILineInfo { - SmallString<16> FileName; - SmallString<16> FunctionName; +struct DILineInfo { + std::string FileName; + std::string FunctionName; uint32_t Line; uint32_t Column; -public: + DILineInfo() - : FileName("<invalid>"), FunctionName("<invalid>"), - Line(0), Column(0) {} - DILineInfo(StringRef fileName, StringRef functionName, uint32_t line, - uint32_t column) - : FileName(fileName), FunctionName(functionName), Line(line), - Column(column) {} - - const char *getFileName() { return FileName.c_str(); } - const char *getFunctionName() { return FunctionName.c_str(); } - uint32_t getLine() const { return Line; } - uint32_t getColumn() const { return Column; } + : FileName("<invalid>"), FunctionName("<invalid>"), Line(0), Column(0) {} bool operator==(const DILineInfo &RHS) const { return Line == RHS.Line && Column == RHS.Column && - FileName.equals(RHS.FileName) && - FunctionName.equals(RHS.FunctionName); + FileName == RHS.FileName && FunctionName == RHS.FunctionName; } bool operator!=(const DILineInfo &RHS) const { return !(*this == RHS); @@ -79,19 +68,16 @@ class DIInliningInfo { /// DILineInfoSpecifier - controls which fields of DILineInfo container /// should be filled with data. -class DILineInfoSpecifier { - const uint32_t Flags; // Or'ed flags that set the info we want to fetch. -public: - enum Specification { - FileLineInfo = 1 << 0, - AbsoluteFilePath = 1 << 1, - FunctionName = 1 << 2 - }; - // Use file/line info by default. - DILineInfoSpecifier(uint32_t flags = FileLineInfo) : Flags(flags) {} - bool needs(Specification spec) const { - return (Flags & spec) > 0; - } +struct DILineInfoSpecifier { + enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; + enum class FunctionNameKind { None, ShortName, LinkageName }; + + FileLineInfoKind FLIKind; + FunctionNameKind FNKind; + + DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default, + FunctionNameKind FNKind = FunctionNameKind::None) + : FLIKind(FLIKind), FNKind(FNKind) {} }; /// Selects which debug sections get dumped. @@ -105,8 +91,11 @@ enum DIDumpType { DIDT_Info, DIDT_InfoDwo, DIDT_Types, + DIDT_TypesDwo, DIDT_Line, + DIDT_LineDwo, DIDT_Loc, + DIDT_LocDwo, DIDT_Ranges, DIDT_Pubnames, DIDT_Pubtypes, diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h index 533d2593b18b..d517a72d62e0 100644 --- a/include/llvm/DebugInfo/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARFFormValue.h @@ -36,7 +36,7 @@ public: private: struct ValueType { - ValueType() : data(NULL) { + ValueType() : data(nullptr) { uval = 0; } @@ -60,7 +60,7 @@ public: bool extractValue(DataExtractor data, uint32_t *offset_ptr, const DWARFUnit *u); bool isInlinedCStr() const { - return Value.data != NULL && Value.data == (const uint8_t*)Value.cstr; + return Value.data != nullptr && Value.data == (const uint8_t*)Value.cstr; } /// getAsFoo functions below return the extracted value as Foo if only diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 233084dd50fa..e5dab6191ab6 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -18,11 +18,11 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/ValueMap.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/IR/ValueMap.h" #include "llvm/MC/MCCodeGenInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Mutex.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include <map> @@ -48,8 +48,13 @@ class RTDyldMemoryManager; class Triple; class Type; +namespace object { + class Archive; + class ObjectFile; +} + /// \brief Helper class for helping synchronize access to the global address map -/// table. +/// table. Access to this class should be serialized under a mutex. class ExecutionEngineState { public: struct AddressMapConfig : public ValueMapConfig<const GlobalValue*> { @@ -79,19 +84,19 @@ private: public: ExecutionEngineState(ExecutionEngine &EE); - GlobalAddressMapTy &getGlobalAddressMap(const MutexGuard &) { + GlobalAddressMapTy &getGlobalAddressMap() { return GlobalAddressMap; } std::map<void*, AssertingVH<const GlobalValue> > & - getGlobalAddressReverseMap(const MutexGuard &) { + getGlobalAddressReverseMap() { return GlobalAddressReverseMap; } /// \brief Erase an entry from the mapping table. /// /// \returns The address that \p ToUnmap was happed to. - void *RemoveMapping(const MutexGuard &, const GlobalValue *ToUnmap); + void *RemoveMapping(const GlobalValue *ToUnmap); }; /// \brief Abstract interface for implementation execution of LLVM modules, @@ -106,7 +111,7 @@ class ExecutionEngine { ExecutionEngineState EEState; /// The target data for the platform for which execution is being performed. - const DataLayout *TD; + const DataLayout *DL; /// Whether lazy JIT compilation is enabled. bool CompilingLazily; @@ -118,6 +123,9 @@ class ExecutionEngine { /// using dlsym). bool SymbolSearchingDisabled; + /// Whether the JIT should verify IR modules during compilation. + bool VerifyModules; + friend class EngineBuilder; // To allow access to JITCtor and InterpCtor. protected: @@ -125,7 +133,7 @@ protected: /// optimize for the case where there is only one module. SmallVector<Module*, 1> Modules; - void setDataLayout(const DataLayout *td) { TD = td; } + void setDataLayout(const DataLayout *Val) { DL = Val; } /// getMemoryforGV - Allocate memory for a global variable. virtual char *getMemoryForGV(const GlobalVariable *GV); @@ -176,7 +184,7 @@ public: /// freeMachineCodeForFunction works. static ExecutionEngine *create(Module *M, bool ForceInterpreter = false, - std::string *ErrorStr = 0, + std::string *ErrorStr = nullptr, CodeGenOpt::Level OptLevel = CodeGenOpt::Default, bool GVsWithCode = true); @@ -188,8 +196,8 @@ public: /// Clients should make sure to initialize targets prior to calling this /// function. static ExecutionEngine *createJIT(Module *M, - std::string *ErrorStr = 0, - JITMemoryManager *JMM = 0, + std::string *ErrorStr = nullptr, + JITMemoryManager *JMM = nullptr, CodeGenOpt::Level OptLevel = CodeGenOpt::Default, bool GVsWithCode = true, @@ -204,9 +212,33 @@ public: Modules.push_back(M); } + /// addObjectFile - Add an ObjectFile to the execution engine. + /// + /// This method is only supported by MCJIT. MCJIT will immediately load the + /// object into memory and adds its symbols to the list used to resolve + /// external symbols while preparing other objects for execution. + /// + /// Objects added using this function will not be made executable until + /// needed by another object. + /// + /// MCJIT will take ownership of the ObjectFile. + virtual void addObjectFile(std::unique_ptr<object::ObjectFile> O); + + /// addArchive - Add an Archive to the execution engine. + /// + /// This method is only supported by MCJIT. MCJIT will use the archive to + /// resolve external symbols in objects it is loading. If a symbol is found + /// in the Archive the contained object file will be extracted (in memory) + /// and loaded for possible execution. + /// + /// MCJIT will take ownership of the Archive. + virtual void addArchive(object::Archive *A) { + llvm_unreachable("ExecutionEngine subclass doesn't implement addArchive."); + } + //===--------------------------------------------------------------------===// - const DataLayout *getDataLayout() const { return TD; } + const DataLayout *getDataLayout() const { return DL; } /// removeModule - Remove a Module from the list of modules. Returns true if /// M is found. @@ -232,7 +264,7 @@ public: /// /// This function is deprecated for the MCJIT execution engine. /// - /// FIXME: the JIT and MCJIT interfaces should be disentangled or united + /// FIXME: the JIT and MCJIT interfaces should be disentangled or united /// again, if possible. /// virtual void *getPointerToNamedFunction(const std::string &Name, @@ -379,7 +411,7 @@ public: } // The JIT overrides a version that actually does this. - virtual void runJITOnFunction(Function *, MachineCodeInfo * = 0) { } + virtual void runJITOnFunction(Function *, MachineCodeInfo * = nullptr) { } /// getGlobalValueAtAddress - Return the LLVM global value object that starts /// at the specified address. @@ -430,6 +462,24 @@ public: llvm_unreachable("No support for an object cache"); } + /// setProcessAllSections (MCJIT Only): By default, only sections that are + /// "required for execution" are passed to the RTDyldMemoryManager, and other + /// sections are discarded. Passing 'true' to this method will cause + /// RuntimeDyld to pass all sections to its RTDyldMemoryManager regardless + /// of whether they are "required to execute" in the usual sense. + /// + /// Rationale: Some MCJIT clients want to be able to inspect metadata + /// sections (e.g. Dwarf, Stack-maps) to enable functionality or analyze + /// performance. Passing these sections to the memory manager allows the + /// client to make policy about the relevant sections, rather than having + /// MCJIT do it. + virtual void setProcessAllSections(bool ProcessAllSections) { + llvm_unreachable("No support for ProcessAllSections option"); + } + + /// Return the target machine (if available). + virtual TargetMachine *getTargetMachine() { return nullptr; } + /// DisableLazyCompilation - When lazy compilation is off (the default), the /// JIT will eagerly compile every function reachable from the argument to /// getPointerToFunction. If lazy compilation is turned on, the JIT will only @@ -475,6 +525,17 @@ public: return SymbolSearchingDisabled; } + /// Enable/Disable IR module verification. + /// + /// Note: Module verification is enabled by default in Debug builds, and + /// disabled by default in Release. Use this method to override the default. + void setVerifyModules(bool Verify) { + VerifyModules = Verify; + } + bool getVerifyModules() const { + return VerifyModules; + } + /// InstallLazyFunctionCreator - If an unknown function is needed, the /// specified function pointer is invoked to create it. If it returns null, /// the JIT will abort. @@ -522,20 +583,10 @@ private: std::string MCPU; SmallVector<std::string, 4> MAttrs; bool UseMCJIT; + bool VerifyModules; /// InitEngine - Does the common initialization of default options. - void InitEngine() { - WhichEngine = EngineKind::Either; - ErrorStr = NULL; - OptLevel = CodeGenOpt::Default; - MCJMM = NULL; - JMM = NULL; - Options = TargetOptions(); - AllocateGVsWithCode = false; - RelocModel = Reloc::Default; - CMModel = CodeModel::JITDefault; - UseMCJIT = false; - } + void InitEngine(); public: /// EngineBuilder - Constructor for EngineBuilder. If create() is called and @@ -550,7 +601,7 @@ public: WhichEngine = w; return *this; } - + /// setMCJITMemoryManager - Sets the MCJIT memory manager to use. This allows /// clients to customize their memory allocation policies for the MCJIT. This /// is only appropriate for the MCJIT; setting this and configuring the builder @@ -560,7 +611,7 @@ public: /// the setJITMemoryManager() option. EngineBuilder &setMCJITMemoryManager(RTDyldMemoryManager *mcjmm) { MCJMM = mcjmm; - JMM = NULL; + JMM = nullptr; return *this; } @@ -572,7 +623,7 @@ public: /// memory manager. This option defaults to NULL. This option overrides /// setMCJITMemoryManager() as well. EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) { - MCJMM = NULL; + MCJMM = nullptr; JMM = jmm; return *this; } @@ -644,6 +695,13 @@ public: return *this; } + /// setVerifyModules - Set whether the JIT implementation should verify + /// IR modules during compilation. + EngineBuilder &setVerifyModules(bool Verify) { + VerifyModules = Verify; + return *this; + } + /// setMAttrs - Set cpu-specific attributes. template<typename StringSequence> EngineBuilder &setMAttrs(const StringSequence &mattrs) { diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index ed66102d4696..99fe36c6b5f6 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -16,8 +16,8 @@ #define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H #include "llvm/Config/llvm-config.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/DebugLoc.h" #include <vector> namespace llvm { @@ -98,11 +98,11 @@ public: static JITEventListener *createIntelJITEventListener( IntelJITEventsWrapper* AlternativeImpl); #else - static JITEventListener *createIntelJITEventListener() { return 0; } + static JITEventListener *createIntelJITEventListener() { return nullptr; } static JITEventListener *createIntelJITEventListener( IntelJITEventsWrapper* AlternativeImpl) { - return 0; + return nullptr; } #endif // USE_INTEL_JITEVENTS @@ -115,11 +115,11 @@ public: OProfileWrapper* AlternativeImpl); #else - static JITEventListener *createOProfileJITEventListener() { return 0; } + static JITEventListener *createOProfileJITEventListener() { return nullptr; } static JITEventListener *createOProfileJITEventListener( OProfileWrapper* AlternativeImpl) { - return 0; + return nullptr; } #endif // USE_OPROFILE diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h index af2a9263ff12..6221d3b335df 100644 --- a/include/llvm/ExecutionEngine/ObjectBuffer.h +++ b/include/llvm/ExecutionEngine/ObjectBuffer.h @@ -1,6 +1,6 @@ //===---- ObjectBuffer.h - Utility class to wrap object image memory -----===// // -// The LLVM Compiler Infrastructure +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. @@ -15,7 +15,6 @@ #ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H #define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" @@ -40,7 +39,8 @@ public: /// returns a pointer to an object that is owned by the caller. However, /// the caller does not take ownership of the underlying memory. MemoryBuffer *getMemBuffer() const { - return MemoryBuffer::getMemBuffer(Buffer->getBuffer(), "", false); + return MemoryBuffer::getMemBuffer(Buffer->getBuffer(), + Buffer->getBufferIdentifier(), false); } const char *getBufferStart() const { return Buffer->getBufferStart(); } @@ -49,7 +49,7 @@ public: protected: // The memory contained in an ObjectBuffer - OwningPtr<MemoryBuffer> Buffer; + std::unique_ptr<MemoryBuffer> Buffer; }; /// ObjectBufferStream - This class encapsulates the SmallVector and @@ -57,7 +57,7 @@ protected: /// while providing a common ObjectBuffer interface for access to the /// memory once the object has been generated. class ObjectBufferStream : public ObjectBuffer { - virtual void anchor(); + void anchor() override; public: ObjectBufferStream() : OS(SV) {} virtual ~ObjectBufferStream() {} @@ -69,13 +69,13 @@ public: // Make the data accessible via the ObjectBuffer::Buffer Buffer.reset(MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()), - "", - false)); + "", + false)); } protected: SmallVector<char, 4096> SV; // Working buffer into which we JIT. - raw_svector_ostream OS; // streaming wrapper + raw_svector_ostream OS; // streaming wrapper }; } // namespace llvm diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h index 076f4b1146c1..1fcedd8d6a92 100644 --- a/include/llvm/ExecutionEngine/ObjectImage.h +++ b/include/llvm/ExecutionEngine/ObjectImage.h @@ -1,6 +1,6 @@ //===---- ObjectImage.h - Format independent executuable object image -----===// // -// The LLVM Compiler Infrastructure +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. @@ -28,7 +28,7 @@ class ObjectImage { virtual void anchor(); protected: - OwningPtr<ObjectBuffer> Buffer; + std::unique_ptr<ObjectBuffer> Buffer; public: ObjectImage(ObjectBuffer *Input) : Buffer(Input) {} @@ -36,18 +36,26 @@ public: virtual object::symbol_iterator begin_symbols() const = 0; virtual object::symbol_iterator end_symbols() const = 0; + iterator_range<object::symbol_iterator> symbols() const { + return iterator_range<object::symbol_iterator>(begin_symbols(), + end_symbols()); + } virtual object::section_iterator begin_sections() const = 0; virtual object::section_iterator end_sections() const = 0; + iterator_range<object::section_iterator> sections() const { + return iterator_range<object::section_iterator>(begin_sections(), + end_sections()); + } virtual /* Triple::ArchType */ unsigned getArch() const = 0; // Subclasses can override these methods to update the image with loaded // addresses for sections and common symbols virtual void updateSectionAddress(const object::SectionRef &Sec, - uint64_t Addr) = 0; + uint64_t Addr) = 0; virtual void updateSymbolAddress(const object::SymbolRef &Sym, - uint64_t Addr) = 0; + uint64_t Addr) = 0; virtual StringRef getData() const = 0; @@ -61,4 +69,3 @@ public: } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_OBJECTIMAGE_H - diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index 3ad2e5022da3..b1d6810f374b 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -14,10 +14,10 @@ #ifndef LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H #define LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H +#include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Memory.h" -#include "llvm-c/ExecutionEngine.h" namespace llvm { @@ -52,6 +52,20 @@ public: uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool IsReadOnly) = 0; + /// Inform the memory manager about the total amount of memory required to + /// allocate all sections to be loaded: + /// \p CodeSize - the total size of all code sections + /// \p DataSizeRO - the total size of all read-only data sections + /// \p DataSizeRW - the total size of all read-write data sections + /// + /// Note that by default the callback is disabled. To enable it + /// redefine the method needsToReserveAllocationSpace to return true. + virtual void reserveAllocationSpace( + uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) { } + + /// Override to return true to enable the reserveAllocationSpace callback. + virtual bool needsToReserveAllocationSpace() { return false; } + /// Register the EH frames with the runtime so that c++ exceptions work. /// /// \p Addr parameter provides the local address of the EH frame section @@ -100,7 +114,7 @@ public: /// operations needed to reliably use the memory are also performed. /// /// Returns true if an error occurred, false otherwise. - virtual bool finalizeMemory(std::string *ErrMsg = 0) = 0; + virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0; }; // Create wrappers for C Binding types (see CBindingWrapping.h). diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index b8324387bbe6..f123ffb803bd 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -21,10 +21,16 @@ namespace llvm { +namespace object { + class ObjectFile; +} + class RuntimeDyldImpl; class ObjectImage; class RuntimeDyld { + friend class RuntimeDyldChecker; + RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; @@ -32,6 +38,7 @@ class RuntimeDyld { // interface. RuntimeDyldImpl *Dyld; RTDyldMemoryManager *MM; + bool ProcessAllSections; protected: // Change the address associated with a section when resolving relocations. // Any relocations already associated with the symbol will be re-resolved. @@ -46,6 +53,12 @@ public: /// failure, the input buffer will be deleted. ObjectImage *loadObject(ObjectBuffer *InputBuffer); + /// Prepare the referenced object file for execution. + /// Ownership of the input object is transferred to the ObjectImage + /// instance returned from this function if successful. In the case of load + /// failure, the input object will be deleted. + ObjectImage *loadObject(std::unique_ptr<object::ObjectFile> InputObject); + /// Get the address of our local copy of the symbol. This may or may not /// be the address used for relocation (clients can copy the data around /// and resolve relocatons based on where they put it). @@ -73,7 +86,21 @@ public: void deregisterEHFrames(); + bool hasError(); StringRef getErrorString(); + + /// By default, only sections that are "required for execution" are passed to + /// the RTDyldMemoryManager, and other sections are discarded. Passing 'true' + /// to this method will cause RuntimeDyld to pass all sections to its + /// memory manager regardless of whether they are "required to execute" in the + /// usual sense. This is useful for inspecting metadata sections that may not + /// contain relocations, E.g. Debug info, stackmaps. + /// + /// Must be called before the first object file is loaded. + void setProcessAllSections(bool ProcessAllSections) { + assert(!Dyld && "setProcessAllSections must be called before loadObject."); + this->ProcessAllSections = ProcessAllSections; + } }; } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h new file mode 100644 index 000000000000..8dd891e83648 --- /dev/null +++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h @@ -0,0 +1,98 @@ +//===---- RuntimeDyldChecker.h - RuntimeDyld tester framework -----*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_RUNTIMEDYLDCHECKER_H +#define LLVM_RUNTIMEDYLDCHECKER_H + +#include "RuntimeDyld.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include <map> + +namespace llvm { + +class MCDisassembler; +class MCInstPrinter; + +/// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has +/// correctly applied relocations. +/// +/// The RuntimeDyldChecker class evaluates expressions against an attached +/// RuntimeDyld instance to verify that relocations have been applied +/// correctly. +/// +/// The expression language supports basic pointer arithmetic and bit-masking, +/// and has limited disassembler integration for accessing instruction +/// operands and the next PC (program counter) address for each instruction. +/// +/// The language syntax is: +/// +/// check = expr '=' expr +/// +/// expr = binary_expr +/// | sliceable_expr +/// +/// sliceable_expr = '*{' number '}' load_addr_expr [slice] +/// | '(' expr ')' [slice] +/// | ident_expr [slice] +/// | number [slice] +/// +/// slice = '[' high-bit-index ':' low-bit-index ']' +/// +/// load_addr_expr = symbol +/// | '(' symbol '+' number ')' +/// | '(' symbol '-' number ')' +/// +/// ident_expr = 'decode_operand' '(' symbol ',' operand-index ')' +/// | 'next_pc' '(' symbol ')' +/// | symbol +/// +/// binary_expr = expr '+' expr +/// | expr '-' expr +/// | expr '&' expr +/// | expr '|' expr +/// | expr '<<' expr +/// | expr '>>' expr +/// +class RuntimeDyldChecker { + friend class RuntimeDyldCheckerExprEval; +public: + RuntimeDyldChecker(RuntimeDyld &RTDyld, + MCDisassembler *Disassembler, + MCInstPrinter *InstPrinter, + llvm::raw_ostream &ErrStream) + : RTDyld(*RTDyld.Dyld), Disassembler(Disassembler), + InstPrinter(InstPrinter), ErrStream(ErrStream) {} + + /// \brief Check a single expression against the attached RuntimeDyld + /// instance. + bool check(StringRef CheckExpr) const; + + /// \brief Scan the given memory buffer for lines beginning with the string + /// in RulePrefix. The remainder of the line is passed to the check + /// method to be evaluated as an expression. + bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const; + +private: + + bool isSymbolValid(StringRef Symbol) const; + uint64_t getSymbolAddress(StringRef Symbol) const; + uint64_t readMemoryAtSymbol(StringRef Symbol, int64_t Offset, + unsigned Size) const; + StringRef getSubsectionStartingAt(StringRef Name) const; + + RuntimeDyldImpl &RTDyld; + MCDisassembler *Disassembler; + MCInstPrinter *InstPrinter; + llvm::raw_ostream &ErrStream; +}; + +} // end namespace llvm + +#endif // LLVM_RUNTIMEDYLDCHECKER_H diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index fd6e41f91ffb..136856390b21 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -21,7 +21,6 @@ #include "llvm/Support/Memory.h" namespace llvm { - /// This is a simple memory manager which implements the methods called by /// the RuntimeDyld class to allocate memory for section-based loading of /// objects, usually those generated by the MCJIT execution engine. @@ -48,19 +47,18 @@ public: /// /// The value of \p Alignment must be a power of two. If \p Alignment is zero /// a default alignment of 16 will be used. - virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, - StringRef SectionName); + uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) override; /// \brief Allocates a memory block of (at least) the given size suitable for /// executable code. /// /// The value of \p Alignment must be a power of two. If \p Alignment is zero /// a default alignment of 16 will be used. - virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, - unsigned SectionID, - StringRef SectionName, - bool isReadOnly); + uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName, + bool isReadOnly) override; /// \brief Update section-specific memory permissions and other attributes. /// @@ -73,7 +71,7 @@ public: /// operations needed to reliably use the memory are also performed. /// /// \returns true if an error occurred, false otherwise. - virtual bool finalizeMemory(std::string *ErrMsg = 0); + bool finalizeMemory(std::string *ErrMsg = nullptr) override; /// \brief Invalidate instruction cache for code sections. /// @@ -94,8 +92,8 @@ private: uint8_t *allocateSection(MemoryGroup &MemGroup, uintptr_t Size, unsigned Alignment); - error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, - unsigned Permissions); + std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, + unsigned Permissions); MemoryGroup CodeMem; MemoryGroup RWDataMem; diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index eb6ed46b473e..7c398a5e5530 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -44,7 +44,7 @@ public: /// /// If \p F is specified, the argument is inserted at the end of the argument /// list for \p F. - explicit Argument(Type *Ty, const Twine &Name = "", Function *F = 0); + explicit Argument(Type *Ty, const Twine &Name = "", Function *F = nullptr); inline const Function *getParent() const { return Parent; } inline Function *getParent() { return Parent; } @@ -55,11 +55,26 @@ public: /// For example in "void foo(int a, float b)" a is 0 and b is 1. unsigned getArgNo() const; + /// \brief Return true if this argument has the nonnull attribute on it in + /// its containing function. Also returns true if at least one byte is known + /// to be dereferenceable and the pointer is in addrspace(0). + bool hasNonNullAttr() const; + + /// \brief If this argument has the dereferenceable attribute on it in its + /// containing function, return the number of bytes known to be + /// dereferenceable. Otherwise, zero is returned. + uint64_t getDereferenceableBytes() const; + /// \brief Return true if this argument has the byval attribute on it in its /// containing function. bool hasByValAttr() const; - /// \brief If this is a byval argument, return its alignment. + /// \brief Return true if this argument has the byval attribute or inalloca + /// attribute on it in its containing function. These attributes both + /// represent arguments being passed by value. + bool hasByValOrInAllocaAttr() const; + + /// \brief If this is a byval or inalloca argument, return its alignment. unsigned getParamAlignment() const; /// \brief Return true if this argument has the nest attribute on it in its @@ -86,6 +101,9 @@ public: /// on it in its containing function. bool onlyReadsMemory() const; + /// \brief Return true if this argument has the inalloca attribute on it in + /// its containing function. + bool hasInAllocaAttr() const; /// \brief Add a Attribute to an argument. void addAttr(AttributeSet AS); diff --git a/include/llvm/Assembly/AssemblyAnnotationWriter.h b/include/llvm/IR/AssemblyAnnotationWriter.h index 37b47c31e8c7..a8d52f68176c 100644 --- a/include/llvm/Assembly/AssemblyAnnotationWriter.h +++ b/include/llvm/IR/AssemblyAnnotationWriter.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ASSEMBLY_ASMANNOTATIONWRITER_H -#define LLVM_ASSEMBLY_ASMANNOTATIONWRITER_H +#ifndef LLVM_IR_ASMANNOTATIONWRITER_H +#define LLVM_IR_ASMANNOTATIONWRITER_H namespace llvm { diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index c23ba0f73c58..5ff48d688918 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -71,9 +71,11 @@ public: Builtin, ///< Callee is recognized as a builtin, despite ///< nobuiltin attribute on its declaration. ByVal, ///< Pass structure by value + InAlloca, ///< Pass structure in an alloca Cold, ///< Marks function as being in a cold path. InlineHint, ///< Source said inlining was desirable InReg, ///< Force argument to be passed in register + JumpTable, ///< Build jump-instruction tables and replace refs. MinSize, ///< Function must be optimized for size first Naked, ///< Naked function Nest, ///< Nested function static chain @@ -85,6 +87,8 @@ public: NoInline, ///< inline=never NonLazyBind, ///< Function is called early and/or ///< often, so lazy binding isn't worthwhile + NonNull, ///< Pointer is known to be not null + Dereferenceable, ///< Pointer is known to be dereferenceable NoRedZone, ///< Disable redzone NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack @@ -115,7 +119,7 @@ private: AttributeImpl *pImpl; Attribute(AttributeImpl *A) : pImpl(A) {} public: - Attribute() : pImpl(0) {} + Attribute() : pImpl(nullptr) {} //===--------------------------------------------------------------------===// // Attribute Construction @@ -130,6 +134,8 @@ public: /// alignment set. static Attribute getWithAlignment(LLVMContext &Context, uint64_t Align); static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align); + static Attribute getWithDereferenceableBytes(LLVMContext &Context, + uint64_t Bytes); //===--------------------------------------------------------------------===// // Attribute Accessors @@ -138,8 +144,8 @@ public: /// \brief Return true if the attribute is an Attribute::AttrKind type. bool isEnumAttribute() const; - /// \brief Return true if the attribute is an alignment attribute. - bool isAlignAttribute() const; + /// \brief Return true if the attribute is an integer attribute. + bool isIntAttribute() const; /// \brief Return true if the attribute is a string (target-dependent) /// attribute. @@ -175,6 +181,10 @@ public: /// alignment value. unsigned getStackAlignment() const; + /// \brief Returns the number of dereferenceable bytes from the + /// dereferenceable attribute (or zero if unknown). + uint64_t getDereferenceableBytes() const; + /// \brief The Attribute is converted to a string of equivalent mnemonic. This /// is, presumably, for writing out the mnemonics for the assembly writer. std::string getAsString(bool InAttrGrp = false) const; @@ -201,7 +211,7 @@ public: /// index `1'. class AttributeSet { public: - enum AttrIndex LLVM_ENUM_INT_TYPE(unsigned) { + enum AttrIndex : unsigned { ReturnIndex = 0U, FunctionIndex = ~0U }; @@ -231,7 +241,7 @@ private: explicit AttributeSet(AttributeSetImpl *LI) : pImpl(LI) {} public: - AttributeSet() : pImpl(0) {} + AttributeSet() : pImpl(nullptr) {} //===--------------------------------------------------------------------===// // AttributeSet Construction and Mutation @@ -241,7 +251,7 @@ public: static AttributeSet get(LLVMContext &C, ArrayRef<AttributeSet> Attrs); static AttributeSet get(LLVMContext &C, unsigned Index, ArrayRef<Attribute::AttrKind> Kind); - static AttributeSet get(LLVMContext &C, unsigned Index, AttrBuilder &B); + static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B); /// \brief Add an attribute to the attribute set at the given index. Since /// attribute sets are immutable, this returns a new set. @@ -313,6 +323,9 @@ public: /// \brief Get the stack alignment. unsigned getStackAlignment(unsigned Index) const; + /// \brief Get the number of dereferenceable bytes (or zero if unknown). + uint64_t getDereferenceableBytes(unsigned Index) const; + /// \brief Return the attributes at the index as a string. std::string getAsString(unsigned Index, bool InAttrGrp = false) const; @@ -392,20 +405,18 @@ class AttrBuilder { std::map<std::string, std::string> TargetDepAttrs; uint64_t Alignment; uint64_t StackAlignment; + uint64_t DerefBytes; public: - AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0) {} + AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {} explicit AttrBuilder(uint64_t Val) - : Attrs(0), Alignment(0), StackAlignment(0) { + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { addRawValue(Val); } - AttrBuilder(const Attribute &A) : Attrs(0), Alignment(0), StackAlignment(0) { + AttrBuilder(const Attribute &A) + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { addAttribute(A); } AttrBuilder(AttributeSet AS, unsigned Idx); - AttrBuilder(const AttrBuilder &B) - : Attrs(B.Attrs), - TargetDepAttrs(B.TargetDepAttrs.begin(), B.TargetDepAttrs.end()), - Alignment(B.Alignment), StackAlignment(B.StackAlignment) {} void clear(); @@ -456,6 +467,10 @@ public: /// \brief Retrieve the stack alignment attribute, if it exists. uint64_t getStackAlignment() const { return StackAlignment; } + /// \brief Retrieve the number of dereferenceable bytes, if the dereferenceable + /// attribute exists (zero is returned otherwise). + uint64_t getDereferenceableBytes() const { return DerefBytes; } + /// \brief This turns an int alignment (which must be a power of 2) into the /// form used internally in Attribute. AttrBuilder &addAlignmentAttr(unsigned Align); @@ -464,6 +479,10 @@ public: /// the form used internally in Attribute. AttrBuilder &addStackAlignmentAttr(unsigned Align); + /// \brief This turns the number of dereferenceable bytes into the form used + /// internally in Attribute. + AttrBuilder &addDereferenceableAttr(uint64_t Bytes); + /// \brief Return true if the builder contains no target-independent /// attributes. bool empty() const { return Attrs.none(); } @@ -472,6 +491,8 @@ public: typedef std::pair<std::string, std::string> td_type; typedef std::map<std::string, std::string>::iterator td_iterator; typedef std::map<std::string, std::string>::const_iterator td_const_iterator; + typedef llvm::iterator_range<td_iterator> td_range; + typedef llvm::iterator_range<td_const_iterator> td_const_range; td_iterator td_begin() { return TargetDepAttrs.begin(); } td_iterator td_end() { return TargetDepAttrs.end(); } @@ -479,6 +500,11 @@ public: td_const_iterator td_begin() const { return TargetDepAttrs.begin(); } td_const_iterator td_end() const { return TargetDepAttrs.end(); } + td_range td_attrs() { return td_range(td_begin(), td_end()); } + td_const_range td_attrs() const { + return td_const_range(td_begin(), td_end()); + } + bool td_empty() const { return TargetDepAttrs.empty(); } bool operator==(const AttrBuilder &B); diff --git a/include/llvm/AutoUpgrade.h b/include/llvm/IR/AutoUpgrade.h index c774782f19ec..a4b3c410c4f6 100644 --- a/include/llvm/AutoUpgrade.h +++ b/include/llvm/IR/AutoUpgrade.h @@ -1,4 +1,4 @@ -//===-- llvm/AutoUpgrade.h - AutoUpgrade Helpers ----------------*- C++ -*-===// +//===- AutoUpgrade.h - AutoUpgrade Helpers ----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,8 +11,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_AUTOUPGRADE_H -#define LLVM_AUTOUPGRADE_H +#ifndef LLVM_IR_AUTOUPGRADE_H +#define LLVM_IR_AUTOUPGRADE_H + +#include <string> namespace llvm { class CallInst; @@ -61,6 +63,9 @@ namespace llvm { /// Check the debug info version number, if it is out-dated, drop the debug /// info. Return true if module is modified. bool UpgradeDebugInfo(Module &M); + + /// Upgrade a metadata string constant in place. + void UpgradeMDStringConstant(std::string &String); } // End llvm namespace #endif diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 3bdc95d556f3..a19489aa49b1 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -90,7 +90,8 @@ private: /// inserted at either the end of the function (if InsertBefore is null), or /// before the specified basic block. explicit BasicBlock(LLVMContext &C, const Twine &Name = "", - Function *Parent = 0, BasicBlock *InsertBefore = 0); + Function *Parent = nullptr, + BasicBlock *InsertBefore = nullptr); public: /// \brief Get the context in which this basic block lives. LLVMContext &getContext() const; @@ -107,7 +108,8 @@ public: /// inserted at either the end of the function (if InsertBefore is 0), or /// before the specified basic block. static BasicBlock *Create(LLVMContext &Context, const Twine &Name = "", - Function *Parent = 0,BasicBlock *InsertBefore = 0) { + Function *Parent = nullptr, + BasicBlock *InsertBefore = nullptr) { return new BasicBlock(Context, Name, Parent, InsertBefore); } ~BasicBlock(); @@ -116,6 +118,8 @@ public: const Function *getParent() const { return Parent; } Function *getParent() { return Parent; } + const DataLayout *getDataLayout() const; + /// \brief Returns the terminator instruction if the block is well formed or /// null if the block is not well formed. TerminatorInst *getTerminator(); @@ -170,14 +174,15 @@ public: void moveAfter(BasicBlock *MovePos); - /// \brief Return this block if it has a single predecessor block. Otherwise - /// return a null pointer. + /// \brief Return the predecessor of this block if it has a single predecessor + /// block. Otherwise return a null pointer. BasicBlock *getSinglePredecessor(); const BasicBlock *getSinglePredecessor() const { return const_cast<BasicBlock*>(this)->getSinglePredecessor(); } - /// \brief Return this block if it has a unique predecessor block. Otherwise return a null pointer. + /// \brief Return the predecessor of this block if it has a unique predecessor + /// block. Otherwise return a null pointer. /// /// Note that unique predecessor doesn't mean single edge, there can be /// multiple edges from the unique predecessor to this block (for example a diff --git a/include/llvm/Support/CFG.h b/include/llvm/IR/CFG.h index 74ec7260927c..c8be8bd1f2a7 100644 --- a/include/llvm/Support/CFG.h +++ b/include/llvm/IR/CFG.h @@ -1,4 +1,4 @@ -//===-- llvm/Support/CFG.h - Process LLVM structures as graphs --*- C++ -*-===// +//===- CFG.h - Process LLVM structures as graphs ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_CFG_H -#define LLVM_SUPPORT_CFG_H +#ifndef LLVM_IR_CFG_H +#define LLVM_IR_CFG_H #include "llvm/ADT/GraphTraits.h" #include "llvm/IR/Function.h" @@ -34,7 +34,7 @@ class PredIterator : public std::iterator<std::forward_iterator_tag, USE_iterator It; inline void advancePastNonTerminators() { - // Loop to ignore non terminator uses (for example BlockAddresses). + // Loop to ignore non-terminator uses (for example BlockAddresses). while (!It.atEnd() && !isa<TerminatorInst>(*It)) ++It; } @@ -44,10 +44,10 @@ public: typedef typename super::reference reference; PredIterator() {} - explicit inline PredIterator(Ptr *bb) : It(bb->use_begin()) { + explicit inline PredIterator(Ptr *bb) : It(bb->user_begin()) { advancePastNonTerminators(); } - inline PredIterator(Ptr *bb, bool) : It(bb->use_end()) {} + inline PredIterator(Ptr *bb, bool) : It(bb->user_end()) {} inline bool operator==(const Self& x) const { return It == x.It; } inline bool operator!=(const Self& x) const { return !operator==(x); } @@ -81,9 +81,9 @@ public: } }; -typedef PredIterator<BasicBlock, Value::use_iterator> pred_iterator; +typedef PredIterator<BasicBlock, Value::user_iterator> pred_iterator; typedef PredIterator<const BasicBlock, - Value::const_use_iterator> const_pred_iterator; + Value::const_user_iterator> const_pred_iterator; inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } inline const_pred_iterator pred_begin(const BasicBlock *BB) { @@ -101,23 +101,45 @@ inline const_pred_iterator pred_end(const BasicBlock *BB) { //===----------------------------------------------------------------------===// template <class Term_, class BB_> // Successor Iterator -class SuccIterator : public std::iterator<std::bidirectional_iterator_tag, - BB_, ptrdiff_t, BB_*, BB_*> { +class SuccIterator : public std::iterator<std::random_access_iterator_tag, BB_, + int, BB_ *, BB_ *> { + typedef std::iterator<std::random_access_iterator_tag, BB_, int, BB_ *, BB_ *> + super; + +public: + typedef typename super::pointer pointer; + typedef typename super::reference reference; + +private: const Term_ Term; unsigned idx; - typedef std::iterator<std::bidirectional_iterator_tag, BB_, ptrdiff_t, BB_*, - BB_*> super; typedef SuccIterator<Term_, BB_> Self; inline bool index_is_valid(int idx) { return idx >= 0 && (unsigned) idx < Term->getNumSuccessors(); } -public: - typedef typename super::pointer pointer; - typedef typename super::reference reference; - // TODO: This can be random access iterator, only operator[] missing. + /// \brief Proxy object to allow write access in operator[] + class SuccessorProxy { + Self it; + + public: + explicit SuccessorProxy(const Self &it) : it(it) {} + + SuccessorProxy &operator=(SuccessorProxy r) { + *this = reference(r); + return *this; + } + + SuccessorProxy &operator=(reference r) { + it.Term->setSuccessor(it.idx, r); + return *this; + } + operator reference() const { return *it; } + }; + +public: explicit inline SuccIterator(Term_ T) : Term(T), idx(0) {// begin iterator } inline SuccIterator(Term_ T, bool) // end iterator @@ -186,7 +208,7 @@ public: return *this; } - inline Self operator+(int Right) { + inline Self operator+(int Right) const { Self tmp = *this; tmp += Right; return tmp; @@ -196,25 +218,21 @@ public: return operator+=(-Right); } - inline Self operator-(int Right) { + inline Self operator-(int Right) const { return operator+(-Right); } - inline int operator-(const Self& x) { + inline int operator-(const Self& x) const { assert(Term == x.Term && "Cannot work on iterators of different blocks!"); int distance = idx - x.idx; return distance; } - // This works for read access, however write access is difficult as changes - // to Term are only possible with Term->setSuccessor(idx). Pointers that can - // be modified are not available. - // - // inline pointer operator[](int offset) { - // Self tmp = *this; - // tmp += offset; - // return tmp.operator*(); - // } + inline SuccessorProxy operator[](int offset) { + Self tmp = *this; + tmp += offset; + return SuccessorProxy(tmp); + } /// Get the source BB of this iterator. inline BB_ *getSource() { diff --git a/include/llvm/IR/CMakeLists.txt b/include/llvm/IR/CMakeLists.txt index 2d52a89f9cd5..dd8e04f1510c 100644 --- a/include/llvm/IR/CMakeLists.txt +++ b/include/llvm/IR/CMakeLists.txt @@ -2,6 +2,4 @@ set(LLVM_TARGET_DEFINITIONS Intrinsics.td) tablegen(LLVM Intrinsics.gen -gen-intrinsic) -add_custom_target(intrinsics_gen ALL - DEPENDS ${llvm_builded_incs_dir}/IR/Intrinsics.gen) -set_target_properties(intrinsics_gen PROPERTIES FOLDER "Tablegenning") +add_public_tablegen_target(intrinsics_gen) diff --git a/include/llvm/Support/CallSite.h b/include/llvm/IR/CallSite.h index 2a1c5ca4d47b..df082577a0e2 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -1,4 +1,4 @@ -//===-- llvm/Support/CallSite.h - Abstract Call & Invoke instrs -*- C++ -*-===// +//===- CallSite.h - Abstract Call & Invoke instrs ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -23,8 +23,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_CALLSITE_H -#define LLVM_SUPPORT_CALLSITE_H +#ifndef LLVM_IR_CALLSITE_H +#define LLVM_IR_CALLSITE_H #include "llvm/ADT/PointerIntPair.h" #include "llvm/IR/Attributes.h" @@ -47,7 +47,7 @@ class CallSiteBase { protected: PointerIntPair<InstrTy*, 1, bool> I; public: - CallSiteBase() : I(0, false) {} + CallSiteBase() : I(nullptr, false) {} CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } CallSiteBase(ValTy *II) { *this = get(II); } @@ -103,11 +103,13 @@ public: /// isCallee - Determine whether the passed iterator points to the /// callee operand's Use. - /// - bool isCallee(value_use_iterator<UserTy> UI) const { - return getCallee() == &UI.getUse(); + bool isCallee(Value::const_user_iterator UI) const { + return isCallee(&UI.getUse()); } + /// Determine whether this Use is the callee operand's Use. + bool isCallee(const Use *U) const { return getCallee() == U; } + ValTy *getArgument(unsigned ArgNo) const { assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); return *(arg_begin() + ArgNo); @@ -121,11 +123,17 @@ public: /// Given a value use iterator, returns the argument that corresponds to it. /// Iterator must actually correspond to an argument. - unsigned getArgumentNo(value_use_iterator<UserTy> I) const { + unsigned getArgumentNo(Value::const_user_iterator I) const { + return getArgumentNo(&I.getUse()); + } + + /// Given a use for an argument, get the argument number that corresponds to + /// it. + unsigned getArgumentNo(const Use *U) const { assert(getInstruction() && "Not a call or invoke instruction!"); - assert(arg_begin() <= &I.getUse() && &I.getUse() < arg_end() + assert(arg_begin() <= U && U < arg_end() && "Argument # out of range!"); - return &I.getUse() - arg_begin(); + return U - arg_begin(); } /// arg_iterator - The type of iterator to use when looping over actual @@ -152,6 +160,17 @@ public: /// FunTy *getCaller() const { return (*this)->getParent()->getParent(); } + /// \brief Tests if this call site must be tail call optimized. Only a + /// CallInst can be tail call optimized. + bool isMustTailCall() const { + return isCall() && cast<CallInst>(getInstruction())->isMustTailCall(); + } + + /// \brief Tests if this call site is marked as a tail call. + bool isTailCall() const { + return isCall() && cast<CallInst>(getInstruction())->isTailCall(); + } + #define CALLSITE_DELEGATE_GETTER(METHOD) \ InstrTy *II = getInstruction(); \ return isCall() \ @@ -198,6 +217,12 @@ public: CALLSITE_DELEGATE_GETTER(getParamAlignment(i)); } + /// @brief Extract the number of dereferenceable bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableBytes(uint16_t i) const { + CALLSITE_DELEGATE_GETTER(getDereferenceableBytes(i)); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -257,6 +282,23 @@ public: return paramHasAttr(ArgNo + 1, Attribute::ByVal); } + /// @brief Determine whether this argument is passed in an alloca. + bool isInAllocaArgument(unsigned ArgNo) const { + return paramHasAttr(ArgNo + 1, Attribute::InAlloca); + } + + /// @brief Determine whether this argument is passed by value or in an alloca. + bool isByValOrInAllocaArgument(unsigned ArgNo) const { + return paramHasAttr(ArgNo + 1, Attribute::ByVal) || + paramHasAttr(ArgNo + 1, Attribute::InAlloca); + } + + /// @brief Determine if there are is an inalloca argument. Only the last + /// argument can have the inalloca attribute. + bool hasInAllocaArgument() const { + return paramHasAttr(arg_size(), Attribute::InAlloca); + } + bool doesNotAccessMemory(unsigned ArgNo) const { return paramHasAttr(ArgNo + 1, Attribute::ReadNone); } @@ -266,6 +308,19 @@ public: paramHasAttr(ArgNo + 1, Attribute::ReadNone); } + /// @brief Return true if the return value is known to be not null. + /// This may be because it has the nonnull attribute, or because at least + /// one byte is dereferenceable and the pointer is in addrspace(0). + bool isReturnNonNull() const { + if (paramHasAttr(0, Attribute::NonNull)) + return true; + else if (getDereferenceableBytes(0) > 0 && + getType()->getPointerAddressSpace() == 0) + return true; + + return false; + } + /// hasArgument - Returns true if this CallSite passes the given Value* as an /// argument to the called function. bool hasArgument(const Value *Arg) const { diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 4437af255748..1eaf4f7f469f 100644 --- a/include/llvm/IR/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -58,6 +58,14 @@ namespace CallingConv { // stackmap and patchpoint intrinsics). AnyReg = 13, + // PreserveMost - Calling convention for runtime calls that preserves most + // registers. + PreserveMost = 14, + + // PreserveAll - Calling convention for runtime calls that preserves + // (almost) all registers. + PreserveAll = 15, + // Target - This is the start of the target-specific calling conventions, // e.g. fastcall and thiscall on X86. FirstTargetCC = 64, diff --git a/include/llvm/IR/Comdat.h b/include/llvm/IR/Comdat.h new file mode 100644 index 000000000000..3e77a7709d5c --- /dev/null +++ b/include/llvm/IR/Comdat.h @@ -0,0 +1,66 @@ +//===-- llvm/IR/Comdat.h - Comdat definitions -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains the declaration of the Comdat class, which represents a +/// single COMDAT in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_COMDAT_H +#define LLVM_IR_COMDAT_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +class raw_ostream; +template <typename ValueTy> class StringMapEntry; + +// This is a Name X SelectionKind pair. The reason for having this be an +// independent object instead of just adding the name and the SelectionKind +// to a GlobalObject is that it is invalid to have two Comdats with the same +// name but different SelectionKind. This structure makes that unrepresentable. +class Comdat { +public: + enum SelectionKind { + Any, ///< The linker may choose any COMDAT. + ExactMatch, ///< The data referenced by the COMDAT must be the same. + Largest, ///< The linker will choose the largest COMDAT. + NoDuplicates, ///< No other Module may specify this COMDAT. + SameSize, ///< The data referenced by the COMDAT must be the same size. + }; + + Comdat(Comdat &&C); + SelectionKind getSelectionKind() const { return SK; } + void setSelectionKind(SelectionKind Val) { SK = Val; } + StringRef getName() const; + void print(raw_ostream &OS) const; + void dump() const; + +private: + friend class Module; + Comdat(); + Comdat(SelectionKind SK, StringMapEntry<Comdat> *Name); + Comdat(const Comdat &) LLVM_DELETED_FUNCTION; + + // Points to the map in Module. + StringMapEntry<Comdat> *Name; + SelectionKind SK; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const Comdat &C) { + C.print(OS); + return OS; +} + +} // end llvm namespace + +#endif diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index 26bad1dd1f79..82ad9fc2f407 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -41,8 +41,8 @@ namespace llvm { class Constant : public User { void operator=(const Constant &) LLVM_DELETED_FUNCTION; Constant(const Constant &) LLVM_DELETED_FUNCTION; - virtual void anchor(); - + void anchor() override; + protected: Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps) : User(ty, vty, Ops, NumOps) {} @@ -64,6 +64,9 @@ public: /// Return true if the value is negative zero or null value. bool isZeroValue() const; + /// \brief Return true if the value is the smallest signed value. + bool isMinSignedValue() const; + /// canTrap - Return true if evaluation of this constant could trap. This is /// true for things like constant expressions that could divide by zero. bool canTrap() const; @@ -71,6 +74,9 @@ public: /// isThreadDependent - Return true if the value can vary between threads. bool isThreadDependent() const; + /// Return true if the value is dependent on a dllimport variable. + bool isDLLImportDependent() const; + /// isConstantUsed - Return true if the constant has users other than constant /// exprs and other dangling things. bool isConstantUsed() const; @@ -163,6 +169,14 @@ public: /// that want to check to see if a global is unused, but don't want to deal /// with potentially dead constants hanging off of the globals. void removeDeadConstantUsers() const; + + Constant *stripPointerCasts() { + return cast<Constant>(Value::stripPointerCasts()); + } + + const Constant *stripPointerCasts() const { + return const_cast<Constant*>(this)->stripPointerCasts(); + } }; } // End llvm namespace diff --git a/include/llvm/Support/ConstantFolder.h b/include/llvm/IR/ConstantFolder.h index 4aad952aaca1..e271a1482117 100644 --- a/include/llvm/Support/ConstantFolder.h +++ b/include/llvm/IR/ConstantFolder.h @@ -1,4 +1,4 @@ -//===-- llvm/Support/ConstantFolder.h - Constant folding helper -*- C++ -*-===// +//===- ConstantFolder.h - Constant folding helper ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_CONSTANTFOLDER_H -#define LLVM_SUPPORT_CONSTANTFOLDER_H +#ifndef LLVM_IR_CONSTANTFOLDER_H +#define LLVM_IR_CONSTANTFOLDER_H #include "llvm/IR/Constants.h" #include "llvm/IR/InstrTypes.h" @@ -159,6 +159,12 @@ public: Constant *CreatePointerCast(Constant *C, Type *DestTy) const { return ConstantExpr::getPointerCast(C, DestTy); } + + Constant *CreatePointerBitCastOrAddrSpaceCast(Constant *C, + Type *DestTy) const { + return ConstantExpr::getPointerBitCastOrAddrSpaceCast(C, DestTy); + } + Constant *CreateIntCast(Constant *C, Type *DestTy, bool isSigned) const { return ConstantExpr::getIntegerCast(C, DestTy, isSigned); diff --git a/include/llvm/Support/ConstantRange.h b/include/llvm/IR/ConstantRange.h index f757c6ea60f0..342422cbe25f 100644 --- a/include/llvm/Support/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -1,4 +1,4 @@ -//===-- llvm/Support/ConstantRange.h - Represent a range --------*- C++ -*-===// +//===- ConstantRange.h - Represent a range ----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -42,13 +42,8 @@ namespace llvm { class ConstantRange { APInt Lower, Upper; -#if LLVM_HAS_RVALUE_REFERENCES // If we have move semantics, pass APInts by value and move them into place. typedef APInt APIntMoveTy; -#else - // Otherwise pass by const ref to save one copy. - typedef const APInt &APIntMoveTy; -#endif public: /// Initialize a full (the default) or empty set for the specified bit width. @@ -119,12 +114,12 @@ public: const APInt *getSingleElement() const { if (Upper == Lower + 1) return &Lower; - return 0; + return nullptr; } /// isSingleElement - Return true if this set contains exactly one member. /// - bool isSingleElement() const { return getSingleElement() != 0; } + bool isSingleElement() const { return getSingleElement() != nullptr; } /// getSetSize - Return the number of elements in this set. /// diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index dac20c9ec5c0..0e72f040d3e0 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -25,8 +25,8 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/Constant.h" -#include "llvm/IR/OperandTraits.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/OperandTraits.h" namespace llvm { @@ -49,7 +49,7 @@ struct ConvertConstantType; /// represents both boolean and integral constants. /// @brief Class for constant integers. class ConstantInt : public Constant { - virtual void anchor(); + void anchor() override; void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; ConstantInt(const ConstantInt &) LLVM_DELETED_FUNCTION; ConstantInt(IntegerType *Ty, const APInt& V); @@ -231,7 +231,7 @@ public: /// class ConstantFP : public Constant { APFloat Val; - virtual void anchor(); + void anchor() override; void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; ConstantFP(const ConstantFP &) LLVM_DELETED_FUNCTION; friend class LLVMContextImpl; @@ -255,8 +255,8 @@ public: static Constant *get(Type* Ty, double V); static Constant *get(Type* Ty, StringRef Str); static ConstantFP *get(LLVMContext &Context, const APFloat &V); - static ConstantFP *getNegativeZero(Type* Ty); - static ConstantFP *getInfinity(Type *Ty, bool Negative = false); + static Constant *getNegativeZero(Type *Ty); + static Constant *getInfinity(Type *Ty, bool Negative = false); /// isValueValidForType - return true if Ty is big enough to represent V. static bool isValueValidForType(Type *Ty, const APFloat &V); @@ -299,7 +299,7 @@ class ConstantAggregateZero : public Constant { ConstantAggregateZero(const ConstantAggregateZero &) LLVM_DELETED_FUNCTION; protected: explicit ConstantAggregateZero(Type *ty) - : Constant(ty, ConstantAggregateZeroVal, 0, 0) {} + : Constant(ty, ConstantAggregateZeroVal, nullptr, 0) {} protected: // allocate space for exactly zero operands void *operator new(size_t s) { @@ -308,7 +308,7 @@ protected: public: static ConstantAggregateZero *get(Type *Ty); - virtual void destroyConstant(); + void destroyConstant() override; /// getSequentialElement - If this CAZ has array or vector type, return a zero /// with the right element type. @@ -356,8 +356,8 @@ public: return cast<ArrayType>(Value::getType()); } - virtual void destroyConstant(); - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + void destroyConstant() override; + void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { @@ -414,8 +414,8 @@ public: return cast<StructType>(Value::getType()); } - virtual void destroyConstant(); - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + void destroyConstant() override; + void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { @@ -461,8 +461,8 @@ public: /// elements have the same value, return that value. Otherwise return NULL. Constant *getSplatValue() const; - virtual void destroyConstant(); - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + void destroyConstant() override; + void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { @@ -486,7 +486,7 @@ class ConstantPointerNull : public Constant { protected: explicit ConstantPointerNull(PointerType *T) : Constant(T, - Value::ConstantPointerNullVal, 0, 0) {} + Value::ConstantPointerNullVal, nullptr, 0) {} protected: // allocate space for exactly zero operands @@ -497,7 +497,7 @@ public: /// get() - Static factory methods - Return objects of the specified value static ConstantPointerNull *get(PointerType *T); - virtual void destroyConstant(); + void destroyConstant() override; /// getType - Specialize the getType() method to always return an PointerType, /// which reduces the amount of casting needed in parts of the compiler. @@ -536,7 +536,7 @@ class ConstantDataSequential : public Constant { ConstantDataSequential(const ConstantDataSequential &) LLVM_DELETED_FUNCTION; protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) - : Constant(ty, VT, 0, 0), DataElements(Data), Next(0) {} + : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {} ~ConstantDataSequential() { delete Next; } static Constant *getImpl(StringRef Bytes, Type *Ty); @@ -624,7 +624,7 @@ public: /// host endianness of the data elements. StringRef getRawDataValues() const; - virtual void destroyConstant(); + void destroyConstant() override; /// Methods for support type inquiry through isa, cast, and dyn_cast: /// @@ -645,7 +645,7 @@ private: class ConstantDataArray : public ConstantDataSequential { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; ConstantDataArray(const ConstantDataArray &) LLVM_DELETED_FUNCTION; - virtual void anchor(); + void anchor() override; friend class ConstantDataSequential; explicit ConstantDataArray(Type *ty, const char *Data) : ConstantDataSequential(ty, ConstantDataArrayVal, Data) {} @@ -697,7 +697,7 @@ public: class ConstantDataVector : public ConstantDataSequential { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; ConstantDataVector(const ConstantDataVector &) LLVM_DELETED_FUNCTION; - virtual void anchor(); + void anchor() override; friend class ConstantDataSequential; explicit ConstantDataVector(Type *ty, const char *Data) : ConstantDataSequential(ty, ConstantDataVectorVal, Data) {} @@ -757,14 +757,20 @@ public: /// block must be embedded into a function. static BlockAddress *get(BasicBlock *BB); + /// \brief Lookup an existing \c BlockAddress constant for the given + /// BasicBlock. + /// + /// \returns 0 if \c !BB->hasAddressTaken(), otherwise the \c BlockAddress. + static BlockAddress *lookup(const BasicBlock *BB); + /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); Function *getFunction() const { return (Function*)Op<0>().get(); } BasicBlock *getBasicBlock() const { return (BasicBlock*)Op<1>().get(); } - virtual void destroyConstant(); - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + void destroyConstant() override; + void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { @@ -1093,8 +1099,8 @@ public: /// would make it harder to remove ConstantExprs altogether. Instruction *getAsInstruction(); - virtual void destroyConstant(); - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + void destroyConstant() override; + void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { @@ -1130,7 +1136,7 @@ class UndefValue : public Constant { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; UndefValue(const UndefValue &) LLVM_DELETED_FUNCTION; protected: - explicit UndefValue(Type *T) : Constant(T, UndefValueVal, 0, 0) {} + explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {} protected: // allocate space for exactly zero operands void *operator new(size_t s) { @@ -1158,7 +1164,7 @@ public: /// index. UndefValue *getElementValue(unsigned Idx) const; - virtual void destroyConstant(); + void destroyConstant() override; /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { diff --git a/include/llvm/DIBuilder.h b/include/llvm/IR/DIBuilder.h index bac16795f3f3..267350409604 100644 --- a/include/llvm/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -1,4 +1,4 @@ -//===--- llvm/DIBuilder.h - Debug Information Builder -----------*- C++ -*-===// +//===- DIBuilder.h - Debug Information Builder ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,14 +12,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DIBUILDER_H -#define LLVM_DIBUILDER_H +#ifndef LLVM_IR_DIBUILDER_H +#define LLVM_IR_DIBUILDER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { class BasicBlock; @@ -55,7 +55,7 @@ namespace llvm { class DIBuilder { private: Module &M; - LLVMContext & VMContext; + LLVMContext &VMContext; MDNode *TempEnumTypes; MDNode *TempRetainTypes; @@ -72,12 +72,13 @@ namespace llvm { SmallVector<TrackingVH<MDNode>, 4> AllRetainTypes; SmallVector<Value *, 4> AllSubprograms; SmallVector<Value *, 4> AllGVs; - SmallVector<Value *, 4> AllImportedModules; + SmallVector<TrackingVH<MDNode>, 4> AllImportedModules; + // Private use for multiple types of template parameters. DITemplateValueParameter createTemplateValueParameter(unsigned Tag, DIDescriptor Scope, StringRef Name, DIType Ty, Value *Val, - MDNode *File = 0, unsigned LineNo = 0, + MDNode *File = nullptr, unsigned LineNo = 0, unsigned ColumnNo = 0); DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; @@ -86,6 +87,7 @@ namespace llvm { public: explicit DIBuilder(Module &M); enum ComplexAddrKind { OpPlus=1, OpDeref }; + enum DebugEmissionKind { FullDebug=1, LineTablesOnly }; /// finalize - Construct any deferred debug info descriptors. void finalize(); @@ -95,8 +97,8 @@ namespace llvm { /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 /// @param File File name /// @param Dir Directory - /// @param Producer String identify producer of debugging information. - /// Usuall this is a compiler version string. + /// @param Producer Identify the producer of debugging information and code. + /// Usually this is a compiler version string. /// @param isOptimized A boolean flag which indicates whether optimization /// is ON or not. /// @param Flags This string lists command line options. This string is @@ -106,11 +108,23 @@ namespace llvm { /// Objective-C. /// @param SplitName The name of the file that we'll split debug info out /// into. + /// @param Kind The kind of debug information to generate. + /// @param EmitDebugInfo A boolean flag which indicates whether debug + /// information should be written to the final + /// output or not. When this is false, debug + /// information annotations will be present in + /// the IL but they are not written to the final + /// assembly or object file. This supports tracking + /// source location information in the back end + /// without actually changing the output (e.g., + /// when using optimization remarks). DICompileUnit createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, - StringRef SplitName = StringRef()); + StringRef SplitName = StringRef(), + DebugEmissionKind Kind = FullDebug, + bool EmitDebugInfo = true); /// createFile - Create a file descriptor to hold debugging information /// for a file. @@ -290,7 +304,7 @@ namespace llvm { uint64_t OffsetInBits, unsigned Flags, DIType DerivedFrom, DIArray Elements, DIType VTableHolder = DIType(), - MDNode *TemplateParms = 0, + MDNode *TemplateParms = nullptr, StringRef UniqueIdentifier = StringRef()); /// createStructType - Create debugging information entry for a struct. @@ -339,7 +353,7 @@ namespace llvm { /// @param ColumnNo Column Number. DITemplateTypeParameter createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty, - MDNode *File = 0, unsigned LineNo = 0, + MDNode *File = nullptr, unsigned LineNo = 0, unsigned ColumnNo = 0); /// createTemplateValueParameter - Create debugging information for template @@ -353,7 +367,7 @@ namespace llvm { /// @param ColumnNo Column Number. DITemplateValueParameter createTemplateValueParameter(DIDescriptor Scope, StringRef Name, - DIType Ty, Value *Val, MDNode *File = 0, + DIType Ty, Value *Val, MDNode *File = nullptr, unsigned LineNo = 0, unsigned ColumnNo = 0); /// \brief Create debugging information for a template template parameter. @@ -366,8 +380,9 @@ namespace llvm { /// @param ColumnNo Column Number. DITemplateValueParameter createTemplateTemplateParameter(DIDescriptor Scope, StringRef Name, - DIType Ty, StringRef Val, MDNode *File = 0, - unsigned LineNo = 0, unsigned ColumnNo = 0); + DIType Ty, StringRef Val, + MDNode *File = nullptr, unsigned LineNo = 0, + unsigned ColumnNo = 0); /// \brief Create debugging information for a template parameter pack. /// @param Scope Scope in which this type is defined. @@ -379,7 +394,7 @@ namespace llvm { /// @param ColumnNo Column Number. DITemplateValueParameter createTemplateParameterPack(DIDescriptor Scope, StringRef Name, - DIType Ty, DIArray Val, MDNode *File = 0, + DIType Ty, DIArray Val, MDNode *File = nullptr, unsigned LineNo = 0, unsigned ColumnNo = 0); /// createArrayType - Create debugging information entry for an array. @@ -415,10 +430,13 @@ namespace llvm { StringRef UniqueIdentifier = StringRef()); /// createSubroutineType - Create subroutine type. - /// @param File File in which this subroutine is defined. - /// @param ParameterTypes An array of subroutine parameter types. This - /// includes return type at 0th index. - DICompositeType createSubroutineType(DIFile File, DIArray ParameterTypes); + /// @param File File in which this subroutine is defined. + /// @param ParameterTypes An array of subroutine parameter types. This + /// includes return type at 0th index. + /// @param Flags E.g.: LValueReference. + /// These flags are used to emit dwarf attributes. + DICompositeType createSubroutineType(DIFile File, DIArray ParameterTypes, + unsigned Flags = 0); /// createArtificialType - Create a new DIType with "artificial" flag set. DIType createArtificialType(DIType Ty); @@ -427,7 +445,7 @@ namespace llvm { /// flag set. DIType createObjectPointerType(DIType Ty); - /// createForwardDecl - Create a temporary forward-declared type. + /// \brief Create a permanent forward-declared type. DICompositeType createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, unsigned RuntimeLang = 0, @@ -435,11 +453,17 @@ namespace llvm { uint64_t AlignInBits = 0, StringRef UniqueIdentifier = StringRef()); + /// \brief Create a temporary forward-declared type. + DICompositeType createReplaceableForwardDecl( + unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, + unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, StringRef UniqueIdentifier = StringRef()); + /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. void retainType(DIType T); - /// createUnspecifiedParameter - Create unspeicified type descriptor + /// createUnspecifiedParameter - Create unspecified type descriptor /// for a subroutine type. DIDescriptor createUnspecifiedParameter(); @@ -460,7 +484,7 @@ namespace llvm { /// @param Val llvm::Value of the variable. DIGlobalVariable createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo, - DIType Ty, bool isLocalToUnit, llvm::Value *Val); + DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val); /// \brief Create a new descriptor for the specified global. /// @param Name Name of the variable. @@ -473,7 +497,7 @@ namespace llvm { /// @param Val llvm::Value of the variable. DIGlobalVariable createGlobalVariable(StringRef Name, StringRef LinkageName, DIFile File, - unsigned LineNo, DIType Ty, bool isLocalToUnit, + unsigned LineNo, DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val); /// createStaticVariable - Create a new descriptor for the specified @@ -491,8 +515,8 @@ namespace llvm { DIGlobalVariable createStaticVariable(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, - DIType Ty, bool isLocalToUnit, llvm::Value *Val, - MDNode *Decl = NULL); + DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val, + MDNode *Decl = nullptr); /// createLocalVariable - Create a new descriptor for the specified @@ -506,13 +530,13 @@ namespace llvm { /// @param Ty Variable Type /// @param AlwaysPreserve Boolean. Set to true if debug info for this /// variable should be preserved in optimized build. - /// @param Flags Flags, e.g. artificial variable. + /// @param Flags Flags, e.g. artificial variable. /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, - DIType Ty, bool AlwaysPreserve = false, + DITypeRef Ty, bool AlwaysPreserve = false, unsigned Flags = 0, unsigned ArgNo = 0); @@ -531,7 +555,7 @@ namespace llvm { /// number. 1 indicates 1st argument. DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile F, unsigned LineNo, - DIType Ty, ArrayRef<Value *> Addr, + DITypeRef Ty, ArrayRef<Value *> Addr, unsigned ArgNo = 0); /// createFunction - Create a new descriptor for the specified subprogram. @@ -542,11 +566,11 @@ namespace llvm { /// @param File File where this variable is defined. /// @param LineNo Line number. /// @param Ty Function type. - /// @param isLocalToUnit True if this function is not externally visible.. + /// @param isLocalToUnit True if this function is not externally visible. /// @param isDefinition True if this is a function definition. /// @param ScopeLine Set to the beginning of the scope this starts /// @param Flags e.g. is this function prototyped or not. - /// This flags are used to emit dwarf attributes. + /// These flags are used to emit dwarf attributes. /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. @@ -558,9 +582,9 @@ namespace llvm { unsigned ScopeLine, unsigned Flags = 0, bool isOptimized = false, - Function *Fn = 0, - MDNode *TParam = 0, - MDNode *Decl = 0); + Function *Fn = nullptr, + MDNode *TParam = nullptr, + MDNode *Decl = nullptr); /// FIXME: this is added for dragonegg. Once we update dragonegg /// to call resolve function, this will be removed. @@ -572,9 +596,9 @@ namespace llvm { unsigned ScopeLine, unsigned Flags = 0, bool isOptimized = false, - Function *Fn = 0, - MDNode *TParam = 0, - MDNode *Decl = 0); + Function *Fn = nullptr, + MDNode *TParam = nullptr, + MDNode *Decl = nullptr); /// createMethod - Create a new descriptor for the specified C++ method. /// See comments in DISubprogram for descriptions of these fields. @@ -604,8 +628,8 @@ namespace llvm { DIType VTableHolder = DIType(), unsigned Flags = 0, bool isOptimized = false, - Function *Fn = 0, - MDNode *TParam = 0); + Function *Fn = nullptr, + MDNode *TParam = nullptr); /// createNameSpace - This creates new descriptor for a namespace /// with the specified parent scope. @@ -627,36 +651,41 @@ namespace llvm { /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. - /// @param Scope Parent lexical scope. - /// @param File Source file - /// @param Line Line number - /// @param Col Column number + /// @param Scope Parent lexical scope. + /// @param File Source file. + /// @param Line Line number. + /// @param Col Column number. + /// @param Discriminator DWARF path discriminator value. DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, - unsigned Line, unsigned Col); + unsigned Line, unsigned Col, + unsigned Discriminator); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS The namespace being imported here /// @param Line Line number DIImportedEntity createImportedModule(DIScope Context, DINameSpace NS, - unsigned Line, - StringRef Name = StringRef()); + unsigned Line); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS An aliased namespace /// @param Line Line number DIImportedEntity createImportedModule(DIScope Context, DIImportedEntity NS, - unsigned Line, StringRef Name); + unsigned Line); /// \brief Create a descriptor for an imported function. /// @param Context The scope this module is imported into /// @param Decl The declaration (or definition) of a function, type, or /// variable /// @param Line Line number + DIImportedEntity createImportedDeclaration(DIScope Context, DIScope Decl, + unsigned Line, + StringRef Name = StringRef()); DIImportedEntity createImportedDeclaration(DIScope Context, - DIDescriptor Decl, - unsigned Line); + DIImportedEntity NS, + unsigned Line, + StringRef Name = StringRef()); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 10630a262008..877029f92f0b 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -27,6 +27,9 @@ #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" +// this needs to be outside of the namespace, to avoid conflict with llvm-c decl +typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; + namespace llvm { class Value; @@ -34,6 +37,7 @@ class Type; class IntegerType; class StructType; class StructLayout; +class Triple; class GlobalVariable; class LLVMContext; template<typename T> @@ -45,8 +49,7 @@ enum AlignTypeEnum { INTEGER_ALIGN = 'i', ///< Integer type alignment VECTOR_ALIGN = 'v', ///< Vector type alignment FLOAT_ALIGN = 'f', ///< Floating point type alignment - AGGREGATE_ALIGN = 'a', ///< Aggregate alignment - STACK_ALIGN = 's' ///< Stack objects alignment + AGGREGATE_ALIGN = 'a' ///< Aggregate alignment }; /// Layout alignment element. @@ -78,38 +81,52 @@ struct LayoutAlignElem { struct PointerAlignElem { unsigned ABIAlign; ///< ABI alignment for this type/bitw unsigned PrefAlign; ///< Pref. alignment for this type/bitw - uint32_t TypeBitWidth; ///< Type bit width + uint32_t TypeByteWidth; ///< Type byte width uint32_t AddressSpace; ///< Address space for the pointer type /// Initializer - static PointerAlignElem get(uint32_t addr_space, unsigned abi_align, - unsigned pref_align, uint32_t bit_width); + static PointerAlignElem get(uint32_t AddressSpace, unsigned ABIAlign, + unsigned PrefAlign, uint32_t TypeByteWidth); /// Equality predicate bool operator==(const PointerAlignElem &rhs) const; }; - -/// DataLayout - This class holds a parsed version of the target data layout -/// string in a module and provides methods for querying it. The target data -/// layout string is specified *by the target* - a frontend generating LLVM IR -/// is required to generate the right target data for the target being codegen'd -/// to. If some measure of portability is desired, an empty string may be -/// specified in the module. -class DataLayout : public ImmutablePass { +/// This class holds a parsed version of the target data layout string in a +/// module and provides methods for querying it. The target data layout string +/// is specified *by the target* - a frontend generating LLVM IR is required to +/// generate the right target data for the target being codegen'd to. +class DataLayout { private: bool LittleEndian; ///< Defaults to false unsigned StackNaturalAlign; ///< Stack natural alignment + enum ManglingModeT { + MM_None, + MM_ELF, + MM_MachO, + MM_WINCOFF, + MM_Mips + }; + ManglingModeT ManglingMode; + SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers. /// Alignments - Where the primitive type alignment data is stored. /// - /// @sa init(). + /// @sa reset(). /// @note Could support multiple size pointer alignments, e.g., 32-bit /// pointers vs. 64-bit pointers by extending LayoutAlignment, but for now, /// we don't. SmallVector<LayoutAlignElem, 16> Alignments; - DenseMap<unsigned, PointerAlignElem> Pointers; + typedef SmallVector<PointerAlignElem, 8> PointersTy; + PointersTy Pointers; + + PointersTy::const_iterator + findPointerLowerBound(uint32_t AddressSpace) const { + return const_cast<DataLayout *>(this)->findPointerLowerBound(AddressSpace); + } + + PointersTy::iterator findPointerLowerBound(uint32_t AddressSpace); /// InvalidAlignmentElem - This member is a signal that a requested alignment /// type and bit width were not found in the SmallVector. @@ -129,8 +146,8 @@ private: bool ABIAlign, Type *Ty) const; //! Set/initialize pointer alignments - void setPointerAlignment(uint32_t addr_space, unsigned abi_align, - unsigned pref_align, uint32_t bit_width); + void setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign, + unsigned PrefAlign, uint32_t TypeByteWidth); //! Internal helper method that returns requested alignment for type. unsigned getAlignment(Type *Ty, bool abi_or_pref) const; @@ -155,41 +172,38 @@ private: /// malformed. void parseSpecifier(StringRef LayoutDescription); + // Free all internal data structures. + void clear(); + public: - /// Default ctor. - /// - /// @note This has to exist, because this is a pass, but it should never be - /// used. - DataLayout(); - - /// Constructs a DataLayout from a specification string. See init(). - explicit DataLayout(StringRef LayoutDescription) - : ImmutablePass(ID) { - init(LayoutDescription); + /// Constructs a DataLayout from a specification string. See reset(). + explicit DataLayout(StringRef LayoutDescription) : LayoutMap(nullptr) { + reset(LayoutDescription); } /// Initialize target data from properties stored in the module. explicit DataLayout(const Module *M); - DataLayout(const DataLayout &DL) : - ImmutablePass(ID), - LittleEndian(DL.isLittleEndian()), - StackNaturalAlign(DL.StackNaturalAlign), - LegalIntWidths(DL.LegalIntWidths), - Alignments(DL.Alignments), - Pointers(DL.Pointers), - LayoutMap(0) - { } + DataLayout(const DataLayout &DL) : LayoutMap(nullptr) { *this = DL; } + + DataLayout &operator=(const DataLayout &DL) { + clear(); + LittleEndian = DL.isLittleEndian(); + StackNaturalAlign = DL.StackNaturalAlign; + ManglingMode = DL.ManglingMode; + LegalIntWidths = DL.LegalIntWidths; + Alignments = DL.Alignments; + Pointers = DL.Pointers; + return *this; + } - ~DataLayout(); // Not virtual, do not subclass this class + bool operator==(const DataLayout &Other) const; + bool operator!=(const DataLayout &Other) const { return !(*this == Other); } - /// DataLayout is an immutable pass, but holds state. This allows the pass - /// manager to clear its mutable state. - bool doFinalization(Module &M); + ~DataLayout(); // Not virtual, do not subclass this class - /// Parse a data layout string (with fallback to default values). Ensure that - /// the data layout pass is registered. - void init(StringRef LayoutDescription); + /// Parse a data layout string (with fallback to default values). + void reset(StringRef LayoutDescription); /// Layout endianness... bool isLittleEndian() const { return LittleEndian; } @@ -208,8 +222,8 @@ public: /// The width is specified in bits. /// bool isLegalInteger(unsigned Width) const { - for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i) - if (LegalIntWidths[i] == Width) + for (unsigned LegalIntWidth : LegalIntWidths) + if (LegalIntWidth == Width) return true; return false; } @@ -223,13 +237,57 @@ public: return (StackNaturalAlign != 0) && (Align > StackNaturalAlign); } + bool hasMicrosoftFastStdCallMangling() const { + return ManglingMode == MM_WINCOFF; + } + + bool hasLinkerPrivateGlobalPrefix() const { + return ManglingMode == MM_MachO; + } + + const char *getLinkerPrivateGlobalPrefix() const { + if (ManglingMode == MM_MachO) + return "l"; + return getPrivateGlobalPrefix(); + } + + char getGlobalPrefix() const { + switch (ManglingMode) { + case MM_None: + case MM_ELF: + case MM_Mips: + return '\0'; + case MM_MachO: + case MM_WINCOFF: + return '_'; + } + llvm_unreachable("invalid mangling mode"); + } + + const char *getPrivateGlobalPrefix() const { + switch (ManglingMode) { + case MM_None: + return ""; + case MM_ELF: + return ".L"; + case MM_Mips: + return "$"; + case MM_MachO: + case MM_WINCOFF: + return "L"; + } + llvm_unreachable("invalid mangling mode"); + } + + static const char *getManglingComponent(const Triple &T); + /// fitsInLegalInteger - This function returns true if the specified type fits /// in a native integer type supported by the CPU. For example, if the CPU /// only supports i32 as a native integer type, then i27 fits in a legal - // integer type but i45 does not. + /// integer type but i45 does not. bool fitsInLegalInteger(unsigned Width) const { - for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i) - if (Width <= LegalIntWidths[i]) + for (unsigned LegalIntWidth : LegalIntWidths) + if (Width <= LegalIntWidth) return true; return false; } @@ -237,34 +295,18 @@ public: /// Layout pointer alignment /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerABIAlignment(unsigned AS = 0) const { - DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); - if (val == Pointers.end()) { - val = Pointers.find(0); - } - return val->second.ABIAlign; - } + unsigned getPointerABIAlignment(unsigned AS = 0) const; /// Return target's alignment for stack-based pointers /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerPrefAlignment(unsigned AS = 0) const { - DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); - if (val == Pointers.end()) { - val = Pointers.find(0); - } - return val->second.PrefAlign; - } + unsigned getPointerPrefAlignment(unsigned AS = 0) const; + /// Layout pointer size /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerSize(unsigned AS = 0) const { - DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); - if (val == Pointers.end()) { - val = Pointers.find(0); - } - return val->second.TypeBitWidth; - } + unsigned getPointerSize(unsigned AS = 0) const; + /// Layout pointer size, in bits /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. @@ -344,10 +386,6 @@ public: /// an integer type of the specified bitwidth. unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const; - /// getCallFrameTypeAlignment - Return the minimum ABI-required alignment - /// for the specified type when it is part of a call frame. - unsigned getCallFrameTypeAlignment(Type *Ty) const; - /// getPrefTypeAlignment - Return the preferred stack/global alignment for /// the specified type. This is always at least as good as the ABI alignment. unsigned getPrefTypeAlignment(Type *Ty) const; @@ -373,11 +411,11 @@ public: /// none are set. Type *getLargestLegalIntType(LLVMContext &C) const { unsigned LargestSize = getLargestLegalIntTypeSize(); - return (LargestSize == 0) ? 0 : Type::getIntNTy(C, LargestSize); + return (LargestSize == 0) ? nullptr : Type::getIntNTy(C, LargestSize); } - /// getLargestLegalIntType - Return the size of largest legal integer type - /// size, or 0 if none are set. + /// getLargestLegalIntTypeSize - Return the size of largest legal integer + /// type size, or 0 if none are set. unsigned getLargestLegalIntTypeSize() const; /// getIndexedOffset - return the offset from the beginning of the type for @@ -408,6 +446,31 @@ public: assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!"); return (Val + (Alignment-1)) & ~UIntTy(Alignment-1); } +}; + +inline DataLayout *unwrap(LLVMTargetDataRef P) { + return reinterpret_cast<DataLayout*>(P); +} + +inline LLVMTargetDataRef wrap(const DataLayout *P) { + return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout*>(P)); +} + +class DataLayoutPass : public ImmutablePass { + DataLayout DL; + +public: + /// This has to exist, because this is a pass, but it should never be used. + DataLayoutPass(); + ~DataLayoutPass(); + + const DataLayout &getDataLayout() const { return DL; } + + // For use with the C API. C++ code should always use the constructor that + // takes a module. + explicit DataLayoutPass(const DataLayout &DL); + + explicit DataLayoutPass(const Module *M); static char ID; // Pass identification, replacement for typeid }; diff --git a/include/llvm/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 768cf4ea10f2..088eb9f01049 100644 --- a/include/llvm/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -1,4 +1,4 @@ -//===--- llvm/Analysis/DebugInfo.h - Debug Information Helpers --*- C++ -*-===// +//===- DebugInfo.h - Debug Information Helpers ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,15 +14,16 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_H -#define LLVM_DEBUGINFO_H +#ifndef LLVM_IR_DEBUGINFO_H +#define LLVM_IR_DEBUGINFO_H -#include "llvm/Support/Casting.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/Metadata.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Dwarf.h" namespace llvm { @@ -64,20 +65,22 @@ class DIDescriptor { public: enum { - FlagPrivate = 1 << 0, - FlagProtected = 1 << 1, - FlagFwdDecl = 1 << 2, - FlagAppleBlock = 1 << 3, - FlagBlockByrefStruct = 1 << 4, - FlagVirtual = 1 << 5, - FlagArtificial = 1 << 6, - FlagExplicit = 1 << 7, - FlagPrototyped = 1 << 8, + FlagPrivate = 1 << 0, + FlagProtected = 1 << 1, + FlagFwdDecl = 1 << 2, + FlagAppleBlock = 1 << 3, + FlagBlockByrefStruct = 1 << 4, + FlagVirtual = 1 << 5, + FlagArtificial = 1 << 6, + FlagExplicit = 1 << 7, + FlagPrototyped = 1 << 8, FlagObjcClassComplete = 1 << 9, - FlagObjectPointer = 1 << 10, - FlagVector = 1 << 11, - FlagStaticMember = 1 << 12, - FlagIndirectVariable = 1 << 13 + FlagObjectPointer = 1 << 10, + FlagVector = 1 << 11, + FlagStaticMember = 1 << 12, + FlagIndirectVariable = 1 << 13, + FlagLValueReference = 1 << 14, + FlagRValueReference = 1 << 15 }; protected: @@ -101,7 +104,7 @@ protected: void replaceFunctionField(unsigned Elt, Function *F); public: - explicit DIDescriptor(const MDNode *N = 0) : DbgNode(N) {} + explicit DIDescriptor(const MDNode *N = nullptr) : DbgNode(N) {} bool Verify() const; @@ -113,7 +116,7 @@ public: // FIXME: This operator bool isn't actually protecting anything at the // moment due to the conversion operator above making DIDescriptor nodes // implicitly convertable to bool. - LLVM_EXPLICIT operator bool() const { return DbgNode != 0; } + LLVM_EXPLICIT operator bool() const { return DbgNode != nullptr; } bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } bool operator!=(DIDescriptor Other) const { return !operator==(Other); } @@ -156,7 +159,7 @@ class DISubrange : public DIDescriptor { void printInternal(raw_ostream &OS) const; public: - explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} + explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {} int64_t getLo() const { return getInt64Field(1); } int64_t getCount() const { return getInt64Field(2); } @@ -166,7 +169,7 @@ public: /// DIArray - This descriptor holds an array of descriptors. class DIArray : public DIDescriptor { public: - explicit DIArray(const MDNode *N = 0) : DIDescriptor(N) {} + explicit DIArray(const MDNode *N = nullptr) : DIDescriptor(N) {} unsigned getNumElements() const; DIDescriptor getElement(unsigned Idx) const { @@ -182,7 +185,7 @@ class DIEnumerator : public DIDescriptor { void printInternal(raw_ostream &OS) const; public: - explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} + explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {} StringRef getName() const { return getStringField(1); } int64_t getEnumValue() const { return getInt64Field(2); } @@ -194,13 +197,20 @@ typedef DIRef<DIScope> DIScopeRef; typedef DIRef<DIType> DITypeRef; /// DIScope - A base class for various scopes. +/// +/// Although, implementation-wise, DIScope is the parent class of most +/// other DIxxx classes, including DIType and its descendants, most of +/// DIScope's descendants are not a substitutable subtype of +/// DIScope. The DIDescriptor::isScope() method only is true for +/// DIScopes that are scopes in the strict lexical scope sense +/// (DICompileUnit, DISubprogram, etc.), but not for, e.g., a DIType. class DIScope : public DIDescriptor { protected: friend class DIDescriptor; void printInternal(raw_ostream &OS) const; public: - explicit DIScope(const MDNode *N = 0) : DIDescriptor(N) {} + explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {} /// Gets the parent scope for this scope node or returns a /// default constructed scope. @@ -222,6 +232,7 @@ template <typename T> class DIRef { friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; friend DIScopeRef DIScope::getContext() const; friend DIScopeRef DIScope::getRef() const; + friend class DIType; /// Val can be either a MDNode or a MDString, in the latter, /// MDString specifies the type identifier. @@ -281,7 +292,12 @@ protected: void printInternal(raw_ostream &OS) const; public: - explicit DIType(const MDNode *N = 0) : DIScope(N) {} + explicit DIType(const MDNode *N = nullptr) : DIScope(N) {} + operator DITypeRef () const { + assert(isType() && + "constructing DITypeRef from an MDNode that is not a type"); + return DITypeRef(&*getRef()); + } /// Verify - Verify that a type descriptor is well formed. bool Verify() const; @@ -313,18 +329,24 @@ public: } bool isVector() const { return (getFlags() & FlagVector) != 0; } bool isStaticMember() const { return (getFlags() & FlagStaticMember) != 0; } + bool isLValueReference() const { + return (getFlags() & FlagLValueReference) != 0; + } + bool isRValueReference() const { + return (getFlags() & FlagRValueReference) != 0; + } bool isValid() const { return DbgNode && isType(); } /// replaceAllUsesWith - Replace all uses of debug info referenced by /// this descriptor. - void replaceAllUsesWith(DIDescriptor &D); + void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); void replaceAllUsesWith(MDNode *D); }; /// DIBasicType - A basic type, like 'int' or 'float'. class DIBasicType : public DIType { public: - explicit DIBasicType(const MDNode *N = 0) : DIType(N) {} + explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {} unsigned getEncoding() const { return getUnsignedField(9); } @@ -340,7 +362,7 @@ class DIDerivedType : public DIType { void printInternal(raw_ostream &OS) const; public: - explicit DIDerivedType(const MDNode *N = 0) : DIType(N) {} + explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {} DITypeRef getTypeDerivedFrom() const { return getFieldAs<DITypeRef>(9); } @@ -373,11 +395,10 @@ class DICompositeType : public DIDerivedType { void printInternal(raw_ostream &OS) const; public: - explicit DICompositeType(const MDNode *N = 0) : DIDerivedType(N) {} + explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {} DIArray getTypeArray() const { return getFieldAs<DIArray>(10); } void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); - void addMember(DIDescriptor D); unsigned getRunTimeLang() const { return getUnsignedField(11); } DITypeRef getContainingType() const { return getFieldAs<DITypeRef>(12); } void setContainingType(DICompositeType ContainingType); @@ -393,7 +414,7 @@ class DIFile : public DIScope { friend class DIDescriptor; public: - explicit DIFile(const MDNode *N = 0) : DIScope(N) {} + explicit DIFile(const MDNode *N = nullptr) : DIScope(N) {} MDNode *getFileNode() const; bool Verify() const; }; @@ -404,9 +425,11 @@ class DICompileUnit : public DIScope { void printInternal(raw_ostream &OS) const; public: - explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} + explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {} - unsigned getLanguage() const { return getUnsignedField(2); } + dwarf::SourceLanguage getLanguage() const { + return static_cast<dwarf::SourceLanguage>(getUnsignedField(2)); + } StringRef getProducer() const { return getStringField(3); } bool isOptimized() const { return getUnsignedField(4) != 0; } @@ -420,6 +443,7 @@ public: DIArray getImportedEntities() const; StringRef getSplitDebugFilename() const { return getStringField(12); } + unsigned getEmissionKind() const { return getUnsignedField(13); } /// Verify - Verify that a compile unit is well formed. bool Verify() const; @@ -431,7 +455,7 @@ class DISubprogram : public DIScope { void printInternal(raw_ostream &OS) const; public: - explicit DISubprogram(const MDNode *N = 0) : DIScope(N) {} + explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {} DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(2); } StringRef getName() const { return getStringField(3); } @@ -470,6 +494,19 @@ public: return (getUnsignedField(13) & FlagPrototyped) != 0; } + /// Return true if this subprogram is a C++11 reference-qualified + /// non-static member function (void foo() &). + unsigned isLValueReference() const { + return (getUnsignedField(13) & FlagLValueReference) != 0; + } + + /// Return true if this subprogram is a C++11 + /// rvalue-reference-qualified non-static member function + /// (void foo() &&). + unsigned isRValueReference() const { + return (getUnsignedField(13) & FlagRValueReference) != 0; + } + unsigned isOptimized() const; /// Verify - Verify that a subprogram descriptor is well formed. @@ -497,10 +534,11 @@ public: /// DILexicalBlock - This is a wrapper for a lexical block. class DILexicalBlock : public DIScope { public: - explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} + explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(2); } unsigned getLineNumber() const { return getUnsignedField(3); } unsigned getColumnNumber() const { return getUnsignedField(4); } + unsigned getDiscriminator() const { return getUnsignedField(5); } bool Verify() const; }; @@ -508,7 +546,7 @@ public: /// a filename change. class DILexicalBlockFile : public DIScope { public: - explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} + explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { if (getScope().isSubprogram()) return getScope(); @@ -526,17 +564,26 @@ class DINameSpace : public DIScope { void printInternal(raw_ostream &OS) const; public: - explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} + explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(2); } StringRef getName() const { return getStringField(3); } unsigned getLineNumber() const { return getUnsignedField(4); } bool Verify() const; }; +/// DIUnspecifiedParameter - This is a wrapper for unspecified parameters. +class DIUnspecifiedParameter : public DIDescriptor { +public: + explicit DIUnspecifiedParameter(const MDNode *N = nullptr) + : DIDescriptor(N) {} + bool Verify() const; +}; + /// DITemplateTypeParameter - This is a wrapper for template type parameter. class DITemplateTypeParameter : public DIDescriptor { public: - explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} + explicit DITemplateTypeParameter(const MDNode *N = nullptr) + : DIDescriptor(N) {} DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } StringRef getName() const { return getStringField(2); } @@ -553,7 +600,8 @@ public: /// DITemplateValueParameter - This is a wrapper for template value parameter. class DITemplateValueParameter : public DIDescriptor { public: - explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} + explicit DITemplateValueParameter(const MDNode *N = nullptr) + : DIDescriptor(N) {} DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); } StringRef getName() const { return getStringField(2); } @@ -574,7 +622,7 @@ class DIGlobalVariable : public DIDescriptor { void printInternal(raw_ostream &OS) const; public: - explicit DIGlobalVariable(const MDNode *N = 0) : DIDescriptor(N) {} + explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs<DIScope>(2); } StringRef getName() const { return getStringField(3); } @@ -586,7 +634,7 @@ public: } unsigned getLineNumber() const { return getUnsignedField(7); } - DIType getType() const { return getFieldAs<DIType>(8); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(8); } unsigned isLocalToUnit() const { return getUnsignedField(9); } unsigned isDefinition() const { return getUnsignedField(10); } @@ -607,7 +655,7 @@ class DIVariable : public DIDescriptor { void printInternal(raw_ostream &OS) const; public: - explicit DIVariable(const MDNode *N = 0) : DIDescriptor(N) {} + explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getName() const { return getStringField(2); } @@ -617,7 +665,7 @@ public: unsigned L = getUnsignedField(4); return L >> 24; } - DIType getType() const { return getFieldAs<DIType>(5); } + DITypeRef getType() const { return getFieldAs<DITypeRef>(5); } /// isArtificial - Return true if this variable is marked as "artificial". bool isArtificial() const { @@ -642,15 +690,22 @@ public: /// HasComplexAddr - Return true if the variable has a complex address. bool hasComplexAddress() const { return getNumAddrElements() > 0; } - unsigned getNumAddrElements() const; - - uint64_t getAddrElement(unsigned Idx) const { - return getUInt64Field(Idx + 8); + /// \brief Return the size of this variable's complex address or + /// zero if there is none. + unsigned getNumAddrElements() const { + if (DbgNode->getNumOperands() < 9) + return 0; + return getDescriptorField(8)->getNumOperands(); } + /// \brief return the Idx'th complex address element. + uint64_t getAddrElement(unsigned Idx) const; + /// isBlockByrefVariable - Return true if the variable was declared as /// a "__block" variable (Apple Blocks). - bool isBlockByrefVariable() const { return getType().isBlockByrefStruct(); } + bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const { + return (getType().resolve(Map)).isBlockByrefStruct(); + } /// isInlinedFnArgument - Return true if this variable provides debugging /// information for an inlined function arguments. @@ -672,6 +727,27 @@ public: StringRef getFilename() const { return getScope().getFilename(); } StringRef getDirectory() const { return getScope().getDirectory(); } bool Verify() const; + bool atSameLineAs(const DILocation &Other) const { + return (getLineNumber() == Other.getLineNumber() && + getFilename() == Other.getFilename()); + } + /// getDiscriminator - DWARF discriminators are used to distinguish + /// identical file locations for instructions that are on different + /// basic blocks. If two instructions are inside the same lexical block + /// and are in different basic blocks, we create a new lexical block + /// with identical location as the original but with a different + /// discriminator value (lib/Transforms/Util/AddDiscriminators.cpp + /// for details). + unsigned getDiscriminator() const { + // Since discriminators are associated with lexical blocks, make + // sure this location is a lexical block before retrieving its + // value. + return getScope().isLexicalBlock() + ? getFieldAs<DILexicalBlock>(2).getDiscriminator() + : 0; + } + unsigned computeNewDiscriminator(LLVMContext &Ctx); + DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlock NewScope); }; class DIObjCProperty : public DIDescriptor { @@ -706,6 +782,8 @@ public: return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; } + /// Objective-C doesn't have an ODR, so there is no benefit in storing + /// the type as a DITypeRef here. DIType getType() const { return getFieldAs<DIType>(7); } /// Verify - Verify that a derived type descriptor is well formed. @@ -720,7 +798,7 @@ class DIImportedEntity : public DIDescriptor { public: explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } - DIDescriptor getEntity() const { return getFieldAs<DIDescriptor>(2); } + DIScopeRef getEntity() const { return getFieldAs<DIScopeRef>(2); } unsigned getLineNumber() const { return getUnsignedField(3); } StringRef getName() const { return getStringField(4); } bool Verify() const; @@ -793,9 +871,6 @@ private: /// processType - Process DIType. void processType(DIType DT); - /// processLexicalBlock - Process DILexicalBlock. - void processLexicalBlock(DILexicalBlock LB); - /// processSubprogram - Process DISubprogram. void processSubprogram(DISubprogram SP); @@ -816,17 +891,31 @@ private: bool addScope(DIScope Scope); public: - typedef SmallVectorImpl<MDNode *>::const_iterator iterator; - iterator compile_unit_begin() const { return CUs.begin(); } - iterator compile_unit_end() const { return CUs.end(); } - iterator subprogram_begin() const { return SPs.begin(); } - iterator subprogram_end() const { return SPs.end(); } - iterator global_variable_begin() const { return GVs.begin(); } - iterator global_variable_end() const { return GVs.end(); } - iterator type_begin() const { return TYs.begin(); } - iterator type_end() const { return TYs.end(); } - iterator scope_begin() const { return Scopes.begin(); } - iterator scope_end() const { return Scopes.end(); } + typedef SmallVectorImpl<DICompileUnit>::const_iterator compile_unit_iterator; + typedef SmallVectorImpl<DISubprogram>::const_iterator subprogram_iterator; + typedef SmallVectorImpl<DIGlobalVariable>::const_iterator global_variable_iterator; + typedef SmallVectorImpl<DIType>::const_iterator type_iterator; + typedef SmallVectorImpl<DIScope>::const_iterator scope_iterator; + + iterator_range<compile_unit_iterator> compile_units() const { + return iterator_range<compile_unit_iterator>(CUs.begin(), CUs.end()); + } + + iterator_range<subprogram_iterator> subprograms() const { + return iterator_range<subprogram_iterator>(SPs.begin(), SPs.end()); + } + + iterator_range<global_variable_iterator> global_variables() const { + return iterator_range<global_variable_iterator>(GVs.begin(), GVs.end()); + } + + iterator_range<type_iterator> types() const { + return iterator_range<type_iterator>(TYs.begin(), TYs.end()); + } + + iterator_range<scope_iterator> scopes() const { + return iterator_range<scope_iterator>(Scopes.begin(), Scopes.end()); + } unsigned compile_unit_count() const { return CUs.size(); } unsigned global_variable_count() const { return GVs.size(); } @@ -835,16 +924,19 @@ public: unsigned scope_count() const { return Scopes.size(); } private: - SmallVector<MDNode *, 8> CUs; // Compile Units - SmallVector<MDNode *, 8> SPs; // Subprograms - SmallVector<MDNode *, 8> GVs; // Global Variables; - SmallVector<MDNode *, 8> TYs; // Types - SmallVector<MDNode *, 8> Scopes; // Scopes + SmallVector<DICompileUnit, 8> CUs; // Compile Units + SmallVector<DISubprogram, 8> SPs; // Subprograms + SmallVector<DIGlobalVariable, 8> GVs; // Global Variables; + SmallVector<DIType, 8> TYs; // Types + SmallVector<DIScope, 8> Scopes; // Scopes SmallPtrSet<MDNode *, 64> NodesSeen; DITypeIdentifierMap TypeIdentifierMap; /// Specify if TypeIdentifierMap is initialized. bool TypeMapInitialized; }; + +DenseMap<const Function *, DISubprogram> makeSubprogramMap(const Module &M); + } // end namespace llvm #endif diff --git a/include/llvm/Support/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 05f31d7a4994..3d969a8b7532 100644 --- a/include/llvm/Support/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -1,4 +1,4 @@ -//===---- llvm/Support/DebugLoc.h - Debug Location Information --*- C++ -*-===// +//===- DebugLoc.h - Debug Location Information ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,15 +12,16 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_DEBUGLOC_H -#define LLVM_SUPPORT_DEBUGLOC_H +#ifndef LLVM_IR_DEBUGLOC_H +#define LLVM_IR_DEBUGLOC_H -#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/DataTypes.h" namespace llvm { template <typename T> struct DenseMapInfo; class MDNode; class LLVMContext; + class raw_ostream; /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, /// and MachineInstr to compactly encode file/line/scope information for an @@ -58,7 +59,7 @@ namespace llvm { /// get - Get a new DebugLoc that corresponds to the specified line/col /// scope/inline location. static DebugLoc get(unsigned Line, unsigned Col, - MDNode *Scope, MDNode *InlinedAt = 0); + MDNode *Scope, MDNode *InlinedAt = nullptr); /// getFromDILocation - Translate the DILocation quad into a DebugLoc. static DebugLoc getFromDILocation(MDNode *N); @@ -89,6 +90,12 @@ namespace llvm { void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, const LLVMContext &Ctx) const; + /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. + MDNode *getScopeNode(const LLVMContext &Ctx) const; + + // getFnDebugLoc - Walk up the scope chain of given debug loc and find line + // number info for the function. + DebugLoc getFnDebugLoc(const LLVMContext &Ctx) const; /// getAsMDNode - This method converts the compressed DebugLoc node into a /// DILocation compatible MDNode. @@ -100,6 +107,8 @@ namespace llvm { bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } void dump(const LLVMContext &Ctx) const; + /// \brief prints source location /path/to/file.exe:line:col @[inlined at] + void print(const LLVMContext &Ctx, raw_ostream &OS) const; }; template <> diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index e279e60e4768..ff150872a4e1 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -188,7 +188,7 @@ class StructType : public CompositeType { StructType(const StructType &) LLVM_DELETED_FUNCTION; const StructType &operator=(const StructType &) LLVM_DELETED_FUNCTION; StructType(LLVMContext &C) - : CompositeType(C, StructTyID), SymbolTableEntry(0) {} + : CompositeType(C, StructTyID), SymbolTableEntry(nullptr) {} enum { /// This is the contents of the SubClassData field. SCDB_HasBody = 1, @@ -249,10 +249,10 @@ public: bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; } /// isSized - Return true if this is a sized type. - bool isSized() const; + bool isSized(SmallPtrSet<const Type*, 4> *Visited = nullptr) const; /// hasName - Return true if this is a named struct that has a non-empty name. - bool hasName() const { return SymbolTableEntry != 0; } + bool hasName() const { return SymbolTableEntry != nullptr; } /// getName - Return the name for this struct type if it has an identity. /// This may return an empty string for an unnamed struct type. Do not call @@ -400,6 +400,26 @@ public: return VectorType::get(EltTy, VTy->getNumElements()); } + /// VectorType::getHalfElementsVectorType - This static method returns + /// a VectorType with half as many elements as the input type and the + /// same element type. + /// + static VectorType *getHalfElementsVectorType(VectorType *VTy) { + unsigned NumElts = VTy->getNumElements(); + assert ((NumElts & 1) == 0 && + "Cannot halve vector with odd number of elements."); + return VectorType::get(VTy->getElementType(), NumElts/2); + } + + /// VectorType::getDoubleElementsVectorType - This static method returns + /// a VectorType with twice as many elements as the input type and the + /// same element type. + /// + static VectorType *getDoubleElementsVectorType(VectorType *VTy) { + unsigned NumElts = VTy->getNumElements(); + return VectorType::get(VTy->getElementType(), NumElts*2); + } + /// isValidElementType - Return true if the specified type is valid as a /// element type. static bool isValidElementType(Type *ElemTy); diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h new file mode 100644 index 000000000000..9c9f236180ce --- /dev/null +++ b/include/llvm/IR/DiagnosticInfo.h @@ -0,0 +1,452 @@ +//===- llvm/Support/DiagnosticInfo.h - Diagnostic Declaration ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the different classes involved in low level diagnostics. +// +// Diagnostics reporting is still done as part of the LLVMContext. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DIAGNOSTICINFO_H +#define LLVM_SUPPORT_DIAGNOSTICINFO_H + +#include "llvm-c/Core.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/IR/DebugLoc.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +// Forward declarations. +class DiagnosticPrinter; +class Function; +class Instruction; +class LLVMContextImpl; +class Twine; +class Value; +class DebugLoc; + +/// \brief Defines the different supported severity of a diagnostic. +enum DiagnosticSeverity { + DS_Error, + DS_Warning, + DS_Remark, + // A note attaches additional information to one of the previous diagnostic + // types. + DS_Note +}; + +/// \brief Defines the different supported kind of a diagnostic. +/// This enum should be extended with a new ID for each added concrete subclass. +enum DiagnosticKind { + DK_InlineAsm, + DK_StackSize, + DK_DebugMetadataVersion, + DK_SampleProfile, + DK_OptimizationRemark, + DK_OptimizationRemarkMissed, + DK_OptimizationRemarkAnalysis, + DK_OptimizationFailure, + DK_FirstPluginKind +}; + +/// \brief Get the next available kind ID for a plugin diagnostic. +/// Each time this function is called, it returns a different number. +/// Therefore, a plugin that wants to "identify" its own classes +/// with a dynamic identifier, just have to use this method to get a new ID +/// and assign it to each of its classes. +/// The returned ID will be greater than or equal to DK_FirstPluginKind. +/// Thus, the plugin identifiers will not conflict with the +/// DiagnosticKind values. +int getNextAvailablePluginDiagnosticKind(); + +/// \brief This is the base abstract class for diagnostic reporting in +/// the backend. +/// The print method must be overloaded by the subclasses to print a +/// user-friendly message in the client of the backend (let us call it a +/// frontend). +class DiagnosticInfo { +private: + /// Kind defines the kind of report this is about. + const /* DiagnosticKind */ int Kind; + /// Severity gives the severity of the diagnostic. + const DiagnosticSeverity Severity; + +public: + DiagnosticInfo(/* DiagnosticKind */ int Kind, DiagnosticSeverity Severity) + : Kind(Kind), Severity(Severity) {} + + virtual ~DiagnosticInfo() {} + + /* DiagnosticKind */ int getKind() const { return Kind; } + DiagnosticSeverity getSeverity() const { return Severity; } + + /// Print using the given \p DP a user-friendly message. + /// This is the default message that will be printed to the user. + /// It is used when the frontend does not directly take advantage + /// of the information contained in fields of the subclasses. + /// The printed message must not end with '.' nor start with a severity + /// keyword. + virtual void print(DiagnosticPrinter &DP) const = 0; +}; + +/// Diagnostic information for inline asm reporting. +/// This is basically a message and an optional location. +class DiagnosticInfoInlineAsm : public DiagnosticInfo { +private: + /// Optional line information. 0 if not set. + unsigned LocCookie; + /// Message to be reported. + const Twine &MsgStr; + /// Optional origin of the problem. + const Instruction *Instr; + +public: + /// \p MsgStr is the message to be reported to the frontend. + /// This class does not copy \p MsgStr, therefore the reference must be valid + /// for the whole life time of the Diagnostic. + DiagnosticInfoInlineAsm(const Twine &MsgStr, + DiagnosticSeverity Severity = DS_Error) + : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr), + Instr(nullptr) {} + + /// \p LocCookie if non-zero gives the line number for this report. + /// \p MsgStr gives the message. + /// This class does not copy \p MsgStr, therefore the reference must be valid + /// for the whole life time of the Diagnostic. + DiagnosticInfoInlineAsm(unsigned LocCookie, const Twine &MsgStr, + DiagnosticSeverity Severity = DS_Error) + : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie), + MsgStr(MsgStr), Instr(nullptr) {} + + /// \p Instr gives the original instruction that triggered the diagnostic. + /// \p MsgStr gives the message. + /// This class does not copy \p MsgStr, therefore the reference must be valid + /// for the whole life time of the Diagnostic. + /// Same for \p I. + DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr, + DiagnosticSeverity Severity = DS_Error); + + unsigned getLocCookie() const { return LocCookie; } + const Twine &getMsgStr() const { return MsgStr; } + const Instruction *getInstruction() const { return Instr; } + + /// \see DiagnosticInfo::print. + void print(DiagnosticPrinter &DP) const override; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_InlineAsm; + } +}; + +/// Diagnostic information for stack size reporting. +/// This is basically a function and a size. +class DiagnosticInfoStackSize : public DiagnosticInfo { +private: + /// The function that is concerned by this stack size diagnostic. + const Function &Fn; + /// The computed stack size. + unsigned StackSize; + +public: + /// \p The function that is concerned by this stack size diagnostic. + /// \p The computed stack size. + DiagnosticInfoStackSize(const Function &Fn, unsigned StackSize, + DiagnosticSeverity Severity = DS_Warning) + : DiagnosticInfo(DK_StackSize, Severity), Fn(Fn), StackSize(StackSize) {} + + const Function &getFunction() const { return Fn; } + unsigned getStackSize() const { return StackSize; } + + /// \see DiagnosticInfo::print. + void print(DiagnosticPrinter &DP) const override; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_StackSize; + } +}; + +/// Diagnostic information for debug metadata version reporting. +/// This is basically a module and a version. +class DiagnosticInfoDebugMetadataVersion : public DiagnosticInfo { +private: + /// The module that is concerned by this debug metadata version diagnostic. + const Module &M; + /// The actual metadata version. + unsigned MetadataVersion; + +public: + /// \p The module that is concerned by this debug metadata version diagnostic. + /// \p The actual metadata version. + DiagnosticInfoDebugMetadataVersion(const Module &M, unsigned MetadataVersion, + DiagnosticSeverity Severity = DS_Warning) + : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M), + MetadataVersion(MetadataVersion) {} + + const Module &getModule() const { return M; } + unsigned getMetadataVersion() const { return MetadataVersion; } + + /// \see DiagnosticInfo::print. + void print(DiagnosticPrinter &DP) const override; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_DebugMetadataVersion; + } +}; + +/// Diagnostic information for the sample profiler. +class DiagnosticInfoSampleProfile : public DiagnosticInfo { +public: + DiagnosticInfoSampleProfile(const char *FileName, unsigned LineNum, + const Twine &Msg, + DiagnosticSeverity Severity = DS_Error) + : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName), + LineNum(LineNum), Msg(Msg) {} + DiagnosticInfoSampleProfile(const char *FileName, const Twine &Msg, + DiagnosticSeverity Severity = DS_Error) + : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName), + LineNum(0), Msg(Msg) {} + DiagnosticInfoSampleProfile(const Twine &Msg, + DiagnosticSeverity Severity = DS_Error) + : DiagnosticInfo(DK_SampleProfile, Severity), FileName(nullptr), + LineNum(0), Msg(Msg) {} + + /// \see DiagnosticInfo::print. + void print(DiagnosticPrinter &DP) const override; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_SampleProfile; + } + + const char *getFileName() const { return FileName; } + unsigned getLineNum() const { return LineNum; } + const Twine &getMsg() const { return Msg; } + +private: + /// Name of the input file associated with this diagnostic. + const char *FileName; + + /// Line number where the diagnostic occurred. If 0, no line number will + /// be emitted in the message. + unsigned LineNum; + + /// Message to report. + const Twine &Msg; +}; + +/// Common features for diagnostics dealing with optimization remarks. +class DiagnosticInfoOptimizationBase : public DiagnosticInfo { +public: + /// \p PassName is the name of the pass emitting this diagnostic. + /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is + /// the location information to use in the diagnostic. If line table + /// information is available, the diagnostic will include the source code + /// location. \p Msg is the message to show. Note that this class does not + /// copy this message, so this reference must be valid for the whole life time + /// of the diagnostic. + DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind, + enum DiagnosticSeverity Severity, + const char *PassName, const Function &Fn, + const DebugLoc &DLoc, const Twine &Msg) + : DiagnosticInfo(Kind, Severity), PassName(PassName), Fn(Fn), DLoc(DLoc), + Msg(Msg) {} + + /// \see DiagnosticInfo::print. + void print(DiagnosticPrinter &DP) const override; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_OptimizationRemark; + } + + /// Return true if this optimization remark is enabled by one of + /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed, + /// or -pass-remarks-analysis). Note that this only handles the LLVM + /// flags. We cannot access Clang flags from here (they are handled + /// in BackendConsumer::OptimizationRemarkHandler). + virtual bool isEnabled() const = 0; + + /// Return true if location information is available for this diagnostic. + bool isLocationAvailable() const; + + /// Return a string with the location information for this diagnostic + /// in the format "file:line:col". If location information is not available, + /// it returns "<unknown>:0:0". + const std::string getLocationStr() const; + + /// Return location information for this diagnostic in three parts: + /// the source file name, line number and column. + void getLocation(StringRef *Filename, unsigned *Line, unsigned *Column) const; + + const char *getPassName() const { return PassName; } + const Function &getFunction() const { return Fn; } + const DebugLoc &getDebugLoc() const { return DLoc; } + const Twine &getMsg() const { return Msg; } + +private: + /// Name of the pass that triggers this report. If this matches the + /// regular expression given in -Rpass=regexp, then the remark will + /// be emitted. + const char *PassName; + + /// Function where this diagnostic is triggered. + const Function &Fn; + + /// Debug location where this diagnostic is triggered. + DebugLoc DLoc; + + /// Message to report. + const Twine &Msg; +}; + +/// Diagnostic information for applied optimization remarks. +class DiagnosticInfoOptimizationRemark : public DiagnosticInfoOptimizationBase { +public: + /// \p PassName is the name of the pass emitting this diagnostic. If + /// this name matches the regular expression given in -Rpass=, then the + /// diagnostic will be emitted. \p Fn is the function where the diagnostic + /// is being emitted. \p DLoc is the location information to use in the + /// diagnostic. If line table information is available, the diagnostic + /// will include the source code location. \p Msg is the message to show. + /// Note that this class does not copy this message, so this reference + /// must be valid for the whole life time of the diagnostic. + DiagnosticInfoOptimizationRemark(const char *PassName, const Function &Fn, + const DebugLoc &DLoc, const Twine &Msg) + : DiagnosticInfoOptimizationBase(DK_OptimizationRemark, DS_Remark, + PassName, Fn, DLoc, Msg) {} + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_OptimizationRemark; + } + + /// \see DiagnosticInfoOptimizationBase::isEnabled. + virtual bool isEnabled() const override; +}; + +/// Diagnostic information for missed-optimization remarks. +class DiagnosticInfoOptimizationRemarkMissed + : public DiagnosticInfoOptimizationBase { +public: + /// \p PassName is the name of the pass emitting this diagnostic. If + /// this name matches the regular expression given in -Rpass-missed=, then the + /// diagnostic will be emitted. \p Fn is the function where the diagnostic + /// is being emitted. \p DLoc is the location information to use in the + /// diagnostic. If line table information is available, the diagnostic + /// will include the source code location. \p Msg is the message to show. + /// Note that this class does not copy this message, so this reference + /// must be valid for the whole life time of the diagnostic. + DiagnosticInfoOptimizationRemarkMissed(const char *PassName, + const Function &Fn, + const DebugLoc &DLoc, const Twine &Msg) + : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkMissed, DS_Remark, + PassName, Fn, DLoc, Msg) {} + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_OptimizationRemarkMissed; + } + + /// \see DiagnosticInfoOptimizationBase::isEnabled. + virtual bool isEnabled() const override; +}; + +/// Diagnostic information for optimization analysis remarks. +class DiagnosticInfoOptimizationRemarkAnalysis + : public DiagnosticInfoOptimizationBase { +public: + /// \p PassName is the name of the pass emitting this diagnostic. If + /// this name matches the regular expression given in -Rpass-analysis=, then + /// the diagnostic will be emitted. \p Fn is the function where the diagnostic + /// is being emitted. \p DLoc is the location information to use in the + /// diagnostic. If line table information is available, the diagnostic will + /// include the source code location. \p Msg is the message to show. Note that + /// this class does not copy this message, so this reference must be valid for + /// the whole life time of the diagnostic. + DiagnosticInfoOptimizationRemarkAnalysis(const char *PassName, + const Function &Fn, + const DebugLoc &DLoc, + const Twine &Msg) + : DiagnosticInfoOptimizationBase(DK_OptimizationRemarkAnalysis, DS_Remark, + PassName, Fn, DLoc, Msg) {} + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_OptimizationRemarkAnalysis; + } + + /// \see DiagnosticInfoOptimizationBase::isEnabled. + virtual bool isEnabled() const override; +}; + +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef) + +/// Emit an optimization-applied message. \p PassName is the name of the pass +/// emitting the message. If -Rpass= is given and \p PassName matches the +/// regular expression in -Rpass, then the remark will be emitted. \p Fn is +/// the function triggering the remark, \p DLoc is the debug location where +/// the diagnostic is generated. \p Msg is the message string to use. +void emitOptimizationRemark(LLVMContext &Ctx, const char *PassName, + const Function &Fn, const DebugLoc &DLoc, + const Twine &Msg); + +/// Emit an optimization-missed message. \p PassName is the name of the +/// pass emitting the message. If -Rpass-missed= is given and \p PassName +/// matches the regular expression in -Rpass, then the remark will be +/// emitted. \p Fn is the function triggering the remark, \p DLoc is the +/// debug location where the diagnostic is generated. \p Msg is the +/// message string to use. +void emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName, + const Function &Fn, const DebugLoc &DLoc, + const Twine &Msg); + +/// Emit an optimization analysis remark message. \p PassName is the name of +/// the pass emitting the message. If -Rpass-analysis= is given and \p +/// PassName matches the regular expression in -Rpass, then the remark will be +/// emitted. \p Fn is the function triggering the remark, \p DLoc is the debug +/// location where the diagnostic is generated. \p Msg is the message string +/// to use. +void emitOptimizationRemarkAnalysis(LLVMContext &Ctx, const char *PassName, + const Function &Fn, const DebugLoc &DLoc, + const Twine &Msg); + +/// Diagnostic information for optimization failures. +class DiagnosticInfoOptimizationFailure + : public DiagnosticInfoOptimizationBase { +public: + /// \p Fn is the function where the diagnostic is being emitted. \p DLoc is + /// the location information to use in the diagnostic. If line table + /// information is available, the diagnostic will include the source code + /// location. \p Msg is the message to show. Note that this class does not + /// copy this message, so this reference must be valid for the whole life time + /// of the diagnostic. + DiagnosticInfoOptimizationFailure(const Function &Fn, const DebugLoc &DLoc, + const Twine &Msg) + : DiagnosticInfoOptimizationBase(DK_OptimizationFailure, DS_Warning, + nullptr, Fn, DLoc, Msg) {} + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_OptimizationFailure; + } + + /// \see DiagnosticInfoOptimizationBase::isEnabled. + virtual bool isEnabled() const override; +}; + +/// Emit a warning when loop vectorization is specified but fails. \p Fn is the +/// function triggering the warning, \p DLoc is the debug location where the +/// diagnostic is generated. \p Msg is the message string to use. +void emitLoopVectorizeWarning(LLVMContext &Ctx, const Function &Fn, + const DebugLoc &DLoc, const Twine &Msg); + +/// Emit a warning when loop interleaving is specified but fails. \p Fn is the +/// function triggering the warning, \p DLoc is the debug location where the +/// diagnostic is generated. \p Msg is the message string to use. +void emitLoopInterleaveWarning(LLVMContext &Ctx, const Function &Fn, + const DebugLoc &DLoc, const Twine &Msg); + +} // End namespace llvm + +#endif diff --git a/include/llvm/IR/DiagnosticPrinter.h b/include/llvm/IR/DiagnosticPrinter.h new file mode 100644 index 000000000000..411c781e01c5 --- /dev/null +++ b/include/llvm/IR/DiagnosticPrinter.h @@ -0,0 +1,87 @@ +//===- llvm/Support/DiagnosticPrinter.h - Diagnostic Printer ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the main interface for printer backend diagnostic. +// +// Clients of the backend diagnostics should overload this interface based +// on their needs. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DIAGNOSTICPRINTER_H +#define LLVM_SUPPORT_DIAGNOSTICPRINTER_H + +#include <string> + +namespace llvm { +// Forward declarations. +class Module; +class raw_ostream; +class StringRef; +class Twine; +class Value; + +/// \brief Interface for custom diagnostic printing. +class DiagnosticPrinter { +public: + virtual ~DiagnosticPrinter() {} + + // Simple types. + virtual DiagnosticPrinter &operator<<(char C) = 0; + virtual DiagnosticPrinter &operator<<(unsigned char C) = 0; + virtual DiagnosticPrinter &operator<<(signed char C) = 0; + virtual DiagnosticPrinter &operator<<(StringRef Str) = 0; + virtual DiagnosticPrinter &operator<<(const char *Str) = 0; + virtual DiagnosticPrinter &operator<<(const std::string &Str) = 0; + virtual DiagnosticPrinter &operator<<(unsigned long N) = 0; + virtual DiagnosticPrinter &operator<<(long N) = 0; + virtual DiagnosticPrinter &operator<<(unsigned long long N) = 0; + virtual DiagnosticPrinter &operator<<(long long N) = 0; + virtual DiagnosticPrinter &operator<<(const void *P) = 0; + virtual DiagnosticPrinter &operator<<(unsigned int N) = 0; + virtual DiagnosticPrinter &operator<<(int N) = 0; + virtual DiagnosticPrinter &operator<<(double N) = 0; + virtual DiagnosticPrinter &operator<<(const Twine &Str) = 0; + + // IR related types. + virtual DiagnosticPrinter &operator<<(const Value &V) = 0; + virtual DiagnosticPrinter &operator<<(const Module &M) = 0; +}; + +/// \brief Basic diagnostic printer that uses an underlying raw_ostream. +class DiagnosticPrinterRawOStream : public DiagnosticPrinter { +protected: + raw_ostream &Stream; + +public: + DiagnosticPrinterRawOStream(raw_ostream &Stream) : Stream(Stream) {}; + + // Simple types. + DiagnosticPrinter &operator<<(char C) override; + DiagnosticPrinter &operator<<(unsigned char C) override; + DiagnosticPrinter &operator<<(signed char C) override; + DiagnosticPrinter &operator<<(StringRef Str) override; + DiagnosticPrinter &operator<<(const char *Str) override; + DiagnosticPrinter &operator<<(const std::string &Str) override; + DiagnosticPrinter &operator<<(unsigned long N) override; + DiagnosticPrinter &operator<<(long N) override; + DiagnosticPrinter &operator<<(unsigned long long N) override; + DiagnosticPrinter &operator<<(long long N) override; + DiagnosticPrinter &operator<<(const void *P) override; + DiagnosticPrinter &operator<<(unsigned int N) override; + DiagnosticPrinter &operator<<(int N) override; + DiagnosticPrinter &operator<<(double N) override; + DiagnosticPrinter &operator<<(const Twine &Str) override; + + // IR related types. + DiagnosticPrinter &operator<<(const Value &V) override; + DiagnosticPrinter &operator<<(const Module &M) override; +}; +} // End namespace llvm + +#endif diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h new file mode 100644 index 000000000000..e2d1ccc8a3ca --- /dev/null +++ b/include/llvm/IR/Dominators.h @@ -0,0 +1,186 @@ +//===- Dominators.h - Dominator Info Calculation ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DominatorTree class, which provides fast and efficient +// dominance queries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_DOMINATORS_H +#define LLVM_IR_DOMINATORS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/Function.h" +#include "llvm/Pass.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/GenericDomTree.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> + +namespace llvm { + +EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>); +EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>); + +#define LLVM_COMMA , +EXTERN_TEMPLATE_INSTANTIATION(void Calculate<Function LLVM_COMMA BasicBlock *>( + DominatorTreeBase<GraphTraits<BasicBlock *>::NodeType> &DT LLVM_COMMA + Function &F)); +EXTERN_TEMPLATE_INSTANTIATION( + void Calculate<Function LLVM_COMMA Inverse<BasicBlock *> >( + DominatorTreeBase<GraphTraits<Inverse<BasicBlock *> >::NodeType> &DT + LLVM_COMMA Function &F)); +#undef LLVM_COMMA + +typedef DomTreeNodeBase<BasicBlock> DomTreeNode; + +class BasicBlockEdge { + const BasicBlock *Start; + const BasicBlock *End; +public: + BasicBlockEdge(const BasicBlock *Start_, const BasicBlock *End_) : + Start(Start_), End(End_) { } + const BasicBlock *getStart() const { + return Start; + } + const BasicBlock *getEnd() const { + return End; + } + bool isSingleEdge() const; +}; + +/// \brief Concrete subclass of DominatorTreeBase that is used to compute a +/// normal dominator tree. +class DominatorTree : public DominatorTreeBase<BasicBlock> { +public: + typedef DominatorTreeBase<BasicBlock> Base; + + DominatorTree() : DominatorTreeBase<BasicBlock>(false) {} + + /// \brief Returns *false* if the other dominator tree matches this dominator + /// tree. + inline bool compare(const DominatorTree &Other) const { + const DomTreeNode *R = getRootNode(); + const DomTreeNode *OtherR = Other.getRootNode(); + + if (!R || !OtherR || R->getBlock() != OtherR->getBlock()) + return true; + + if (Base::compare(Other)) + return true; + + return false; + } + + // Ensure base-class overloads are visible. + using Base::dominates; + + /// \brief Return true if Def dominates a use in User. + /// + /// This performs the special checks necessary if Def and User are in the same + /// basic block. Note that Def doesn't dominate a use in Def itself! + bool dominates(const Instruction *Def, const Use &U) const; + bool dominates(const Instruction *Def, const Instruction *User) const; + bool dominates(const Instruction *Def, const BasicBlock *BB) const; + bool dominates(const BasicBlockEdge &BBE, const Use &U) const; + bool dominates(const BasicBlockEdge &BBE, const BasicBlock *BB) const; + + // Ensure base class overloads are visible. + using Base::isReachableFromEntry; + + /// \brief Provide an overload for a Use. + bool isReachableFromEntry(const Use &U) const; + + /// \brief Verify the correctness of the domtree by re-computing it. + /// + /// This should only be used for debugging as it aborts the program if the + /// verification fails. + void verifyDomTree() const; +}; + +//===------------------------------------- +// DominatorTree GraphTraits specializations so the DominatorTree can be +// iterable by generic graph iterators. + +template <> struct GraphTraits<DomTreeNode*> { + typedef DomTreeNode NodeType; + typedef NodeType::iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { + return N; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } + + typedef df_iterator<DomTreeNode*> nodes_iterator; + + static nodes_iterator nodes_begin(DomTreeNode *N) { + return df_begin(getEntryNode(N)); + } + + static nodes_iterator nodes_end(DomTreeNode *N) { + return df_end(getEntryNode(N)); + } +}; + +template <> struct GraphTraits<DominatorTree*> + : public GraphTraits<DomTreeNode*> { + static NodeType *getEntryNode(DominatorTree *DT) { + return DT->getRootNode(); + } + + static nodes_iterator nodes_begin(DominatorTree *N) { + return df_begin(getEntryNode(N)); + } + + static nodes_iterator nodes_end(DominatorTree *N) { + return df_end(getEntryNode(N)); + } +}; + +/// \brief Analysis pass which computes a \c DominatorTree. +class DominatorTreeWrapperPass : public FunctionPass { + DominatorTree DT; + +public: + static char ID; + + DominatorTreeWrapperPass() : FunctionPass(ID) { + initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry()); + } + + DominatorTree &getDomTree() { return DT; } + const DominatorTree &getDomTree() const { return DT; } + + bool runOnFunction(Function &F) override; + + void verifyAnalysis() const override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + void releaseMemory() override { DT.releaseMemory(); } + + void print(raw_ostream &OS, const Module *M = nullptr) const override; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index bba7ecdd2372..ad4b1395f0cb 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -18,11 +18,12 @@ #ifndef LLVM_IR_FUNCTION_H #define LLVM_IR_FUNCTION_H +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallingConv.h" -#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/GlobalObject.h" #include "llvm/Support/Compiler.h" namespace llvm { @@ -67,8 +68,7 @@ private: mutable ilist_half_node<Argument> Sentinel; }; -class Function : public GlobalValue, - public ilist_node<Function> { +class Function : public GlobalObject, public ilist_node<Function> { public: typedef iplist<Argument> ArgumentListType; typedef iplist<BasicBlock> BasicBlockListType; @@ -122,11 +122,11 @@ private: /// the module. /// Function(FunctionType *Ty, LinkageTypes Linkage, - const Twine &N = "", Module *M = 0); + const Twine &N = "", Module *M = nullptr); public: static Function *Create(FunctionType *Ty, LinkageTypes Linkage, - const Twine &N = "", Module *M = 0) { + const Twine &N = "", Module *M = nullptr) { return new(0) Function(Ty, Linkage, N, M); } @@ -233,6 +233,12 @@ public: return AttributeSets.getParamAlignment(i); } + /// @brief Extract the number of dereferenceable bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableBytes(unsigned i) const { + return AttributeSets.getDereferenceableBytes(i); + } + /// @brief Determine if the function does not access memory. bool doesNotAccessMemory() const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, @@ -297,7 +303,8 @@ public: /// @brief Determine if the function returns a structure through first /// pointer argument. bool hasStructRetAttr() const { - return AttributeSets.hasAttribute(1, Attribute::StructRet); + return AttributeSets.hasAttribute(1, Attribute::StructRet) || + AttributeSets.hasAttribute(2, Attribute::StructRet); } /// @brief Determine if the parameter does not alias other parameters. @@ -335,7 +342,7 @@ public: /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a Function) from the Function Src to this one. - void copyAttributesFrom(const GlobalValue *Src); + void copyAttributesFrom(const GlobalValue *Src) override; /// deleteBody - This method deletes the body of the function, and converts /// the linkage to external. @@ -348,12 +355,12 @@ public: /// removeFromParent - This method unlinks 'this' from the containing module, /// but does not delete it. /// - virtual void removeFromParent(); + void removeFromParent() override; /// eraseFromParent - This method unlinks 'this' from the containing module /// and deletes it. /// - virtual void eraseFromParent(); + void eraseFromParent() override; /// Get the underlying elements of the Function... the basic block list is @@ -404,9 +411,9 @@ public: const BasicBlock &back() const { return BasicBlocks.back(); } BasicBlock &back() { return BasicBlocks.back(); } - //===--------------------------------------------------------------------===// - // Argument iterator forwarding functions - // +/// @name Function Argument Iteration +/// @{ + arg_iterator arg_begin() { CheckLazyArguments(); return ArgumentList.begin(); @@ -424,6 +431,16 @@ public: return ArgumentList.end(); } + iterator_range<arg_iterator> args() { + return iterator_range<arg_iterator>(arg_begin(), arg_end()); + } + + iterator_range<const_arg_iterator> args() const { + return iterator_range<const_arg_iterator>(arg_begin(), arg_end()); + } + +/// @} + size_t arg_size() const; bool arg_empty() const; @@ -472,7 +489,7 @@ public: /// other than direct calls or invokes to it, or blockaddress expressions. /// Optionally passes back an offending user for diagnostic purposes. /// - bool hasAddressTaken(const User** = 0) const; + bool hasAddressTaken(const User** = nullptr) const; /// isDefTriviallyDead - Return true if it is trivially safe to remove /// this function definition from the module (because it isn't externally @@ -494,12 +511,12 @@ private: inline ValueSymbolTable * ilist_traits<BasicBlock>::getSymTab(Function *F) { - return F ? &F->getValueSymbolTable() : 0; + return F ? &F->getValueSymbolTable() : nullptr; } inline ValueSymbolTable * ilist_traits<Argument>::getSymTab(Function *F) { - return F ? &F->getValueSymbolTable() : 0; + return F ? &F->getValueSymbolTable() : nullptr; } } // End llvm namespace diff --git a/include/llvm/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index 8efe50ae94ba..a1216a174282 100644 --- a/include/llvm/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -1,4 +1,4 @@ -//===-- llvm/GVMaterializer.h - Interface for GV materializers --*- C++ -*-===// +//===- GVMaterializer.h - Interface for GV materializers --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,13 +15,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_GVMATERIALIZER_H -#define LLVM_GVMATERIALIZER_H +#ifndef LLVM_IR_GVMATERIALIZER_H +#define LLVM_IR_GVMATERIALIZER_H -#include "llvm/Support/system_error.h" +#include <system_error> namespace llvm { - class Function; class GlobalValue; class Module; @@ -33,28 +32,30 @@ protected: public: virtual ~GVMaterializer(); - /// isMaterializable - True if GV can be materialized from whatever backing - /// store this GVMaterializer uses and has not been materialized yet. + /// True if GV can be materialized from whatever backing store this + /// GVMaterializer uses and has not been materialized yet. virtual bool isMaterializable(const GlobalValue *GV) const = 0; - /// isDematerializable - True if GV has been materialized and can be - /// dematerialized back to whatever backing store this GVMaterializer uses. + /// True if GV has been materialized and can be dematerialized back to + /// whatever backing store this GVMaterializer uses. virtual bool isDematerializable(const GlobalValue *GV) const = 0; - /// Materialize - make sure the given GlobalValue is fully read. + /// Make sure the given GlobalValue is fully read. /// - virtual error_code Materialize(GlobalValue *GV) = 0; + virtual std::error_code Materialize(GlobalValue *GV) = 0; - /// Dematerialize - If the given GlobalValue is read in, and if the - /// GVMaterializer supports it, release the memory for the GV, and set it up - /// to be materialized lazily. If the Materializer doesn't support this - /// capability, this method is a noop. + /// If the given GlobalValue is read in, and if the GVMaterializer supports + /// it, release the memory for the GV, and set it up to be materialized + /// lazily. If the Materializer doesn't support this capability, this method + /// is a noop. /// virtual void Dematerialize(GlobalValue *) {} - /// MaterializeModule - make sure the entire Module has been completely read. + /// Make sure the entire Module has been completely read. /// - virtual error_code MaterializeModule(Module *M) = 0; + virtual std::error_code MaterializeModule(Module *M) = 0; + + virtual void releaseBuffer() = 0; }; } // End llvm namespace diff --git a/include/llvm/Support/GetElementPtrTypeIterator.h b/include/llvm/IR/GetElementPtrTypeIterator.h index aacb53162cf7..dcf8e64dbb27 100644 --- a/include/llvm/Support/GetElementPtrTypeIterator.h +++ b/include/llvm/IR/GetElementPtrTypeIterator.h @@ -1,4 +1,4 @@ -//===- llvm/Support/GetElementPtrTypeIterator.h -----------------*- C++ -*-===// +//===- GetElementPtrTypeIterator.h ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_GETELEMENTPTRTYPEITERATOR_H -#define LLVM_SUPPORT_GETELEMENTPTRTYPEITERATOR_H +#ifndef LLVM_IR_GETELEMENTPTRTYPEITERATOR_H +#define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/User.h" @@ -38,7 +38,7 @@ namespace llvm { } static generic_gep_type_iterator end(ItTy It) { generic_gep_type_iterator I; - I.CurTy = 0; + I.CurTy = nullptr; I.OpIt = It; return I; } @@ -69,7 +69,7 @@ namespace llvm { if (CompositeType *CT = dyn_cast<CompositeType>(CurTy)) { CurTy = CT->getTypeAtIndex(getOperand()); } else { - CurTy = 0; + CurTy = nullptr; } ++OpIt; return *this; diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index fec61a7ceaf1..075b5703bccf 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -33,15 +33,37 @@ class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> { void setParent(Module *parent); + GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, + const Twine &Name, Constant *Aliasee, Module *Parent); + public: // allocate space for exactly one operand void *operator new(size_t s) { return User::operator new(s, 1); } - /// GlobalAlias ctor - If a parent module is specified, the alias is - /// automatically inserted into the end of the specified module's alias list. - GlobalAlias(Type *Ty, LinkageTypes Linkage, const Twine &Name = "", - Constant* Aliasee = 0, Module *Parent = 0); + + /// If a parent module is specified, the alias is automatically inserted into + /// the end of the specified module's alias list. + static GlobalAlias *create(Type *Ty, unsigned AddressSpace, + LinkageTypes Linkage, const Twine &Name, + Constant *Aliasee, Module *Parent); + + // Without the Aliasee. + static GlobalAlias *create(Type *Ty, unsigned AddressSpace, + LinkageTypes Linkage, const Twine &Name, + Module *Parent); + + // The module is taken from the Aliasee. + static GlobalAlias *create(Type *Ty, unsigned AddressSpace, + LinkageTypes Linkage, const Twine &Name, + GlobalValue *Aliasee); + + // Type, Parent and AddressSpace taken from the Aliasee. + static GlobalAlias *create(LinkageTypes Linkage, const Twine &Name, + GlobalValue *Aliasee); + + // Linkage, Type, Parent and AddressSpace taken from the Aliasee. + static GlobalAlias *create(const Twine &Name, GlobalValue *Aliasee); /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -49,36 +71,35 @@ public: /// removeFromParent - This method unlinks 'this' from the containing module, /// but does not delete it. /// - virtual void removeFromParent(); + void removeFromParent() override; /// eraseFromParent - This method unlinks 'this' from the containing module /// and deletes it. /// - virtual void eraseFromParent(); + void eraseFromParent() override; - /// set/getAliasee - These methods retrive and set alias target. - void setAliasee(Constant *GV); + /// These methods retrive and set alias target. + void setAliasee(Constant *Aliasee); const Constant *getAliasee() const { - return getOperand(0); + return const_cast<GlobalAlias *>(this)->getAliasee(); } Constant *getAliasee() { return getOperand(0); } - /// getAliasedGlobal() - Aliasee can be either global or bitcast of - /// global. This method retrives the global for both aliasee flavours. - GlobalValue *getAliasedGlobal(); - const GlobalValue *getAliasedGlobal() const { - return const_cast<GlobalAlias *>(this)->getAliasedGlobal(); + + const GlobalObject *getBaseObject() const { + return const_cast<GlobalAlias *>(this)->getBaseObject(); + } + GlobalObject *getBaseObject() { + return dyn_cast<GlobalObject>(getAliasee()->stripInBoundsOffsets()); } - /// resolveAliasedGlobal() - This method tries to ultimately resolve the alias - /// by going through the aliasing chain and trying to find the very last - /// global. Returns NULL if a cycle was found. If stopOnWeak is false, then - /// the whole chain aliasing chain is traversed, otherwise - only strong - /// aliases. - GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true); - const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const { - return const_cast<GlobalAlias *>(this)->resolveAliasedGlobal(stopOnWeak); + const GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) const { + return const_cast<GlobalAlias *>(this)->getBaseObject(DL, Offset); + } + GlobalObject *getBaseObject(const DataLayout &DL, APInt &Offset) { + return dyn_cast<GlobalObject>( + getAliasee()->stripAndAccumulateInBoundsConstantOffsets(DL, Offset)); } static bool isValidLinkage(LinkageTypes L) { diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h new file mode 100644 index 000000000000..2e042f489749 --- /dev/null +++ b/include/llvm/IR/GlobalObject.h @@ -0,0 +1,64 @@ +//===-- llvm/GlobalObject.h - Class to represent a global object *- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This represents an independent object. That is, a function or a global +// variable, but not an alias. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_GLOBALOBJECT_H +#define LLVM_IR_GLOBALOBJECT_H + +#include "llvm/IR/Constant.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/GlobalValue.h" + +namespace llvm { +class Comdat; +class Module; + +class GlobalObject : public GlobalValue { + GlobalObject(const GlobalObject &) LLVM_DELETED_FUNCTION; + +protected: + GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + LinkageTypes Linkage, const Twine &Name) + : GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name), ObjComdat(nullptr) { + setGlobalValueSubClassData(0); + } + + std::string Section; // Section to emit this into, empty means default + Comdat *ObjComdat; +public: + unsigned getAlignment() const { + return (1u << getGlobalValueSubClassData()) >> 1; + } + void setAlignment(unsigned Align); + + bool hasSection() const { return !StringRef(getSection()).empty(); } + const char *getSection() const { return Section.c_str(); } + void setSection(StringRef S); + + bool hasComdat() const { return getComdat() != nullptr; } + const Comdat *getComdat() const { return ObjComdat; } + Comdat *getComdat() { return ObjComdat; } + void setComdat(Comdat *C) { ObjComdat = C; } + + void copyAttributesFrom(const GlobalValue *Src) override; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal || + V->getValueID() == Value::GlobalVariableVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 4f20a31a294b..68e410ba4b8b 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -23,6 +23,7 @@ namespace llvm { +class Comdat; class PointerType; class Module; @@ -40,10 +41,6 @@ public: AppendingLinkage, ///< Special purpose, only applies to global arrays InternalLinkage, ///< Rename collisions when linking (static functions). PrivateLinkage, ///< Like Internal, but omit from symbol table. - LinkerPrivateLinkage, ///< Like Private, but linker removes. - LinkerPrivateWeakLinkage, ///< Like LinkerPrivate, but weak. - DLLImportLinkage, ///< Function to be imported from DLL - DLLExportLinkage, ///< Function to be accessible from DLL. ExternalWeakLinkage,///< ExternalWeak linkage description. CommonLinkage ///< Tentative definitions. }; @@ -55,11 +52,20 @@ public: ProtectedVisibility ///< The GV is protected }; + /// @brief Storage classes of global values for PE targets. + enum DLLStorageClassTypes { + DefaultStorageClass = 0, + DLLImportStorageClass = 1, ///< Function to be imported from DLL + DLLExportStorageClass = 2 ///< Function to be accessible from DLL. + }; + protected: - GlobalValue(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps, - LinkageTypes linkage, const Twine &Name) - : Constant(ty, vty, Ops, NumOps), Linkage(linkage), - Visibility(DefaultVisibility), Alignment(0), UnnamedAddr(0), Parent(0) { + GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + LinkageTypes Linkage, const Twine &Name) + : Constant(Ty, VTy, Ops, NumOps), Linkage(Linkage), + Visibility(DefaultVisibility), UnnamedAddr(0), + DllStorageClass(DefaultStorageClass), + ThreadLocal(NotThreadLocal), Parent(nullptr) { setName(Name); } @@ -67,43 +73,96 @@ protected: // Linkage and Visibility from turning into negative values. LinkageTypes Linkage : 5; // The linkage of this global unsigned Visibility : 2; // The visibility style of this global - unsigned Alignment : 16; // Alignment of this symbol, must be power of two unsigned UnnamedAddr : 1; // This value's address is not significant + unsigned DllStorageClass : 2; // DLL storage class + + unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is + // the desired model? + +private: + // Give subclasses access to what otherwise would be wasted padding. + // (19 + 3 + 2 + 1 + 2 + 5) == 32. + unsigned SubClassData : 19; +protected: + unsigned getGlobalValueSubClassData() const { + return SubClassData; + } + void setGlobalValueSubClassData(unsigned V) { + assert(V < (1 << 19) && "It will not fit"); + SubClassData = V; + } + Module *Parent; // The containing module. - std::string Section; // Section to emit this into, empty mean default public: + enum ThreadLocalMode { + NotThreadLocal = 0, + GeneralDynamicTLSModel, + LocalDynamicTLSModel, + InitialExecTLSModel, + LocalExecTLSModel + }; + ~GlobalValue() { removeDeadConstantUsers(); // remove any dead constants using this. } - unsigned getAlignment() const { - return (1u << Alignment) >> 1; - } - void setAlignment(unsigned Align); + unsigned getAlignment() const; bool hasUnnamedAddr() const { return UnnamedAddr; } void setUnnamedAddr(bool Val) { UnnamedAddr = Val; } + bool hasComdat() const { return getComdat() != nullptr; } + Comdat *getComdat(); + const Comdat *getComdat() const { + return const_cast<GlobalValue *>(this)->getComdat(); + } + VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } bool hasProtectedVisibility() const { return Visibility == ProtectedVisibility; } - void setVisibility(VisibilityTypes V) { Visibility = V; } - - bool hasSection() const { return !Section.empty(); } - const std::string &getSection() const { return Section; } - void setSection(StringRef S) { Section = S; } - - /// If the usage is empty (except transitively dead constants), then this - /// global value can be safely deleted since the destructor will - /// delete the dead constants as well. - /// @brief Determine if the usage of this global value is empty except - /// for transitively dead constants. - bool use_empty_except_constants(); - - /// getType - Global values are always pointers. + void setVisibility(VisibilityTypes V) { + assert((!hasLocalLinkage() || V == DefaultVisibility) && + "local linkage requires default visibility"); + Visibility = V; + } + + /// If the value is "Thread Local", its value isn't shared by the threads. + bool isThreadLocal() const { return getThreadLocalMode() != NotThreadLocal; } + void setThreadLocal(bool Val) { + setThreadLocalMode(Val ? GeneralDynamicTLSModel : NotThreadLocal); + } + void setThreadLocalMode(ThreadLocalMode Val) { + assert(Val == NotThreadLocal || getValueID() != Value::FunctionVal); + ThreadLocal = Val; + } + ThreadLocalMode getThreadLocalMode() const { + return static_cast<ThreadLocalMode>(ThreadLocal); + } + + DLLStorageClassTypes getDLLStorageClass() const { + return DLLStorageClassTypes(DllStorageClass); + } + bool hasDLLImportStorageClass() const { + return DllStorageClass == DLLImportStorageClass; + } + bool hasDLLExportStorageClass() const { + return DllStorageClass == DLLExportStorageClass; + } + void setDLLStorageClass(DLLStorageClassTypes C) { DllStorageClass = C; } + + bool hasSection() const { return !StringRef(getSection()).empty(); } + // It is unfortunate that we have to use "char *" in here since this is + // always non NULL, but: + // * The C API expects a null terminated string, so we cannot use StringRef. + // * The C API expects us to own it, so we cannot use a std:string. + // * For GlobalAliases we can fail to find the section and we have to + // return "", so we cannot use a "const std::string &". + const char *getSection() const; + + /// Global values are always pointers. inline PointerType *getType() const { return cast<PointerType>(User::getType()); } @@ -121,11 +180,20 @@ public: static bool isAvailableExternallyLinkage(LinkageTypes Linkage) { return Linkage == AvailableExternallyLinkage; } + static bool isLinkOnceODRLinkage(LinkageTypes Linkage) { + return Linkage == LinkOnceODRLinkage; + } static bool isLinkOnceLinkage(LinkageTypes Linkage) { return Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage; } + static bool isWeakAnyLinkage(LinkageTypes Linkage) { + return Linkage == WeakAnyLinkage; + } + static bool isWeakODRLinkage(LinkageTypes Linkage) { + return Linkage == WeakODRLinkage; + } static bool isWeakLinkage(LinkageTypes Linkage) { - return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage; + return isWeakAnyLinkage(Linkage) || isWeakODRLinkage(Linkage); } static bool isAppendingLinkage(LinkageTypes Linkage) { return Linkage == AppendingLinkage; @@ -136,21 +204,8 @@ public: static bool isPrivateLinkage(LinkageTypes Linkage) { return Linkage == PrivateLinkage; } - static bool isLinkerPrivateLinkage(LinkageTypes Linkage) { - return Linkage == LinkerPrivateLinkage; - } - static bool isLinkerPrivateWeakLinkage(LinkageTypes Linkage) { - return Linkage == LinkerPrivateWeakLinkage; - } static bool isLocalLinkage(LinkageTypes Linkage) { - return isInternalLinkage(Linkage) || isPrivateLinkage(Linkage) || - isLinkerPrivateLinkage(Linkage) || isLinkerPrivateWeakLinkage(Linkage); - } - static bool isDLLImportLinkage(LinkageTypes Linkage) { - return Linkage == DLLImportLinkage; - } - static bool isDLLExportLinkage(LinkageTypes Linkage) { - return Linkage == DLLExportLinkage; + return isInternalLinkage(Linkage) || isPrivateLinkage(Linkage); } static bool isExternalWeakLinkage(LinkageTypes Linkage) { return Linkage == ExternalWeakLinkage; @@ -159,36 +214,29 @@ public: return Linkage == CommonLinkage; } - /// isDiscardableIfUnused - Whether the definition of this global may be - /// discarded if it is not used in its compilation unit. + /// Whether the definition of this global may be discarded if it is not used + /// in its compilation unit. static bool isDiscardableIfUnused(LinkageTypes Linkage) { return isLinkOnceLinkage(Linkage) || isLocalLinkage(Linkage); } - /// mayBeOverridden - Whether the definition of this global may be replaced - /// by something non-equivalent at link time. For example, if a function has - /// weak linkage then the code defining it may be replaced by different code. + /// Whether the definition of this global may be replaced by something + /// non-equivalent at link time. For example, if a function has weak linkage + /// then the code defining it may be replaced by different code. static bool mayBeOverridden(LinkageTypes Linkage) { - return Linkage == WeakAnyLinkage || - Linkage == LinkOnceAnyLinkage || - Linkage == CommonLinkage || - Linkage == ExternalWeakLinkage || - Linkage == LinkerPrivateWeakLinkage; + return Linkage == WeakAnyLinkage || Linkage == LinkOnceAnyLinkage || + Linkage == CommonLinkage || Linkage == ExternalWeakLinkage; } - /// isWeakForLinker - Whether the definition of this global may be replaced at - /// link time. NB: Using this method outside of the code generators is almost - /// always a mistake: when working at the IR level use mayBeOverridden instead - /// as it knows about ODR semantics. + /// Whether the definition of this global may be replaced at link time. NB: + /// Using this method outside of the code generators is almost always a + /// mistake: when working at the IR level use mayBeOverridden instead as it + /// knows about ODR semantics. static bool isWeakForLinker(LinkageTypes Linkage) { - return Linkage == AvailableExternallyLinkage || - Linkage == WeakAnyLinkage || - Linkage == WeakODRLinkage || - Linkage == LinkOnceAnyLinkage || - Linkage == LinkOnceODRLinkage || - Linkage == CommonLinkage || - Linkage == ExternalWeakLinkage || - Linkage == LinkerPrivateWeakLinkage; + return Linkage == AvailableExternallyLinkage || Linkage == WeakAnyLinkage || + Linkage == WeakODRLinkage || Linkage == LinkOnceAnyLinkage || + Linkage == LinkOnceODRLinkage || Linkage == CommonLinkage || + Linkage == ExternalWeakLinkage; } bool hasExternalLinkage() const { return isExternalLinkage(Linkage); } @@ -201,20 +249,24 @@ public: bool hasWeakLinkage() const { return isWeakLinkage(Linkage); } + bool hasWeakAnyLinkage() const { + return isWeakAnyLinkage(Linkage); + } + bool hasWeakODRLinkage() const { + return isWeakODRLinkage(Linkage); + } bool hasAppendingLinkage() const { return isAppendingLinkage(Linkage); } bool hasInternalLinkage() const { return isInternalLinkage(Linkage); } bool hasPrivateLinkage() const { return isPrivateLinkage(Linkage); } - bool hasLinkerPrivateLinkage() const { return isLinkerPrivateLinkage(Linkage); } - bool hasLinkerPrivateWeakLinkage() const { - return isLinkerPrivateWeakLinkage(Linkage); - } bool hasLocalLinkage() const { return isLocalLinkage(Linkage); } - bool hasDLLImportLinkage() const { return isDLLImportLinkage(Linkage); } - bool hasDLLExportLinkage() const { return isDLLExportLinkage(Linkage); } bool hasExternalWeakLinkage() const { return isExternalWeakLinkage(Linkage); } bool hasCommonLinkage() const { return isCommonLinkage(Linkage); } - void setLinkage(LinkageTypes LT) { Linkage = LT; } + void setLinkage(LinkageTypes LT) { + if (isLocalLinkage(LT)) + Visibility = DefaultVisibility; + Linkage = LT; + } LinkageTypes getLinkage() const { return Linkage; } bool isDiscardableIfUnused() const { @@ -225,13 +277,13 @@ public: bool isWeakForLinker() const { return isWeakForLinker(Linkage); } - /// copyAttributesFrom - copy all additional attributes (those not needed to - /// create a GlobalValue) from the GlobalValue Src to this one. + /// Copy all additional attributes (those not needed to create a GlobalValue) + /// from the GlobalValue Src to this one. virtual void copyAttributesFrom(const GlobalValue *Src); - /// getRealLinkageName - If special LLVM prefix that is used to inform the asm - /// printer to not emit usual symbol prefix before the symbol name is used - /// then return linkage name after skipping this special LLVM prefix. + /// If special LLVM prefix that is used to inform the asm printer to not emit + /// usual symbol prefix before the symbol name is used then return linkage + /// name after skipping this special LLVM prefix. static StringRef getRealLinkageName(StringRef Name) { if (!Name.empty() && Name[0] == '\1') return Name.substr(1); @@ -244,48 +296,48 @@ public: /// BitcodeReader to load the Module. /// @{ - /// isMaterializable - If this function's Module is being lazily streamed in - /// functions from disk or some other source, this method can be used to check - /// to see if the function has been read in yet or not. + /// If this function's Module is being lazily streamed in functions from disk + /// or some other source, this method can be used to check to see if the + /// function has been read in yet or not. bool isMaterializable() const; - /// isDematerializable - Returns true if this function was loaded from a - /// GVMaterializer that's still attached to its Module and that knows how to - /// dematerialize the function. + /// Returns true if this function was loaded from a GVMaterializer that's + /// still attached to its Module and that knows how to dematerialize the + /// function. bool isDematerializable() const; - /// Materialize - make sure this GlobalValue is fully read. If the module is - /// corrupt, this returns true and fills in the optional string with - /// information about the problem. If successful, this returns false. - bool Materialize(std::string *ErrInfo = 0); + /// Make sure this GlobalValue is fully read. If the module is corrupt, this + /// returns true and fills in the optional string with information about the + /// problem. If successful, this returns false. + bool Materialize(std::string *ErrInfo = nullptr); - /// Dematerialize - If this GlobalValue is read in, and if the GVMaterializer - /// supports it, release the memory for the function, and set it up to be - /// materialized lazily. If !isDematerializable(), this method is a noop. + /// If this GlobalValue is read in, and if the GVMaterializer supports it, + /// release the memory for the function, and set it up to be materialized + /// lazily. If !isDematerializable(), this method is a noop. void Dematerialize(); /// @} /// Override from Constant class. - virtual void destroyConstant(); + void destroyConstant() override; - /// isDeclaration - Return true if the primary definition of this global - /// value is outside of the current translation unit. + /// Return true if the primary definition of this global value is outside of + /// the current translation unit. bool isDeclaration() const; - /// removeFromParent - This method unlinks 'this' from the containing module, - /// but does not delete it. + /// This method unlinks 'this' from the containing module, but does not delete + /// it. virtual void removeFromParent() = 0; - /// eraseFromParent - This method unlinks 'this' from the containing module - /// and deletes it. + /// This method unlinks 'this' from the containing module and deletes it. virtual void eraseFromParent() = 0; - /// getParent - Get the module that this global value is contained inside - /// of... + /// Get the module that this global value is contained inside of... inline Module *getParent() { return Parent; } inline const Module *getParent() const { return Parent; } + const DataLayout *getDataLayout() const; + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 660092df3dee..4189ccb90a54 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -22,7 +22,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/GlobalObject.h" #include "llvm/IR/OperandTraits.h" namespace llvm { @@ -32,7 +32,7 @@ class Constant; template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; -class GlobalVariable : public GlobalValue, public ilist_node<GlobalVariable> { +class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> { friend class SymbolTableListTraits<GlobalVariable, Module>; void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; void operator=(const GlobalVariable &) LLVM_DELETED_FUNCTION; @@ -41,9 +41,6 @@ class GlobalVariable : public GlobalValue, public ilist_node<GlobalVariable> { void setParent(Module *parent); bool isConstantGlobal : 1; // Is this a global constant? - unsigned threadLocalMode : 3; // Is this symbol "Thread Local", - // if so, what is the desired - // model? bool isExternallyInitializedConstant : 1; // Is this a global whose value // can change from its initial // value before global @@ -55,25 +52,17 @@ public: return User::operator new(s, 1); } - enum ThreadLocalMode { - NotThreadLocal = 0, - GeneralDynamicTLSModel, - LocalDynamicTLSModel, - InitialExecTLSModel, - LocalExecTLSModel - }; - /// GlobalVariable ctor - If a parent module is specified, the global is /// automatically inserted into the end of the specified modules global list. GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, - Constant *Initializer = 0, const Twine &Name = "", + Constant *Initializer = nullptr, const Twine &Name = "", ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, bool isExternallyInitialized = false); /// GlobalVariable ctor - This creates a global and inserts it before the /// specified other global. GlobalVariable(Module &M, Type *Ty, bool isConstant, LinkageTypes Linkage, Constant *Initializer, - const Twine &Name = "", GlobalVariable *InsertBefore = 0, + const Twine &Name = "", GlobalVariable *InsertBefore = nullptr, ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, bool isExternallyInitialized = false); @@ -155,16 +144,6 @@ public: bool isConstant() const { return isConstantGlobal; } void setConstant(bool Val) { isConstantGlobal = Val; } - /// If the value is "Thread Local", its value isn't shared by the threads. - bool isThreadLocal() const { return threadLocalMode != NotThreadLocal; } - void setThreadLocal(bool Val) { - threadLocalMode = Val ? GeneralDynamicTLSModel : NotThreadLocal; - } - void setThreadLocalMode(ThreadLocalMode Val) { threadLocalMode = Val; } - ThreadLocalMode getThreadLocalMode() const { - return static_cast<ThreadLocalMode>(threadLocalMode); - } - bool isExternallyInitialized() const { return isExternallyInitializedConstant; } @@ -174,21 +153,21 @@ public: /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a GlobalVariable) from the GlobalVariable Src to this one. - void copyAttributesFrom(const GlobalValue *Src); + void copyAttributesFrom(const GlobalValue *Src) override; /// removeFromParent - This method unlinks 'this' from the containing module, /// but does not delete it. /// - virtual void removeFromParent(); + void removeFromParent() override; /// eraseFromParent - This method unlinks 'this' from the containing module /// and deletes it. /// - virtual void eraseFromParent(); + void eraseFromParent() override; /// Override Constant's implementation of this method so we can /// replace constant initializers. - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 8d1432d6c921..aed2463d42d8 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -19,13 +19,13 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/ConstantFolder.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/ConstantFolder.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { class MDNode; @@ -58,7 +58,7 @@ protected: FastMathFlags FMF; public: - IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = 0) + IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr) : Context(context), DefaultFPMathTag(FPMathTag), FMF() { ClearInsertionPoint(); } @@ -70,8 +70,8 @@ public: /// \brief Clear the insertion point: created instructions will not be /// inserted into a block. void ClearInsertionPoint() { - BB = 0; - InsertPt = 0; + BB = nullptr; + InsertPt = nullptr; } BasicBlock *GetInsertBlock() const { return BB; } @@ -140,14 +140,14 @@ public: public: /// \brief Creates a new insertion point which doesn't point to anything. - InsertPoint() : Block(0) {} + InsertPoint() : Block(nullptr) {} /// \brief Creates a new insertion point at the given location. InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint) : Block(InsertBlock), Point(InsertPoint) {} /// \brief Returns true if this insert point is set. - bool isSet() const { return (Block != 0); } + bool isSet() const { return (Block != nullptr); } llvm::BasicBlock *getBlock() const { return Block; } llvm::BasicBlock::iterator getPoint() const { return Point; } @@ -282,6 +282,12 @@ public: return ConstantInt::get(getInt64Ty(), C); } + /// \brief Get a constant N-bit value, zero extended or truncated from + /// a 64-bit value. + ConstantInt *getIntN(unsigned N, uint64_t C) { + return ConstantInt::get(getIntNTy(N), C); + } + /// \brief Get a constant integer value. ConstantInt *getInt(const APInt &AI) { return ConstantInt::get(Context, AI); @@ -316,6 +322,16 @@ public: return Type::getInt64Ty(Context); } + /// \brief Fetch the type representing an N-bit integer. + IntegerType *getIntNTy(unsigned N) { + return Type::getIntNTy(Context, N); + } + + /// \brief Fetch the type representing a 16-bit floating point value. + Type *getHalfTy() { + return Type::getHalfTy(Context); + } + /// \brief Fetch the type representing a 32-bit floating point value. Type *getFloatTy() { return Type::getFloatTy(Context); @@ -351,27 +367,27 @@ public: /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is /// specified, it will be added to the instruction. CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0) { + bool isVolatile = false, MDNode *TBAATag = nullptr) { return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); } CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0); + bool isVolatile = false, MDNode *TBAATag = nullptr); /// \brief Create and insert a memcpy between the specified pointers. /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is /// specified, it will be added to the instruction. CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0, - MDNode *TBAAStructTag = 0) { + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *TBAAStructTag = nullptr) { return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, TBAAStructTag); } CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0, - MDNode *TBAAStructTag = 0); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *TBAAStructTag = nullptr); /// \brief Create and insert a memmove between the specified /// pointers. @@ -379,22 +395,22 @@ public: /// If the pointers aren't i8*, they will be converted. If a TBAA tag is /// specified, it will be added to the instruction. CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0) { + bool isVolatile = false, MDNode *TBAATag = nullptr) { return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); } CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0); + bool isVolatile = false, MDNode *TBAATag = nullptr); /// \brief Create a lifetime.start intrinsic. /// /// If the pointer isn't i8* it will be converted. - CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = 0); + CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = nullptr); /// \brief Create a lifetime.end intrinsic. /// /// If the pointer isn't i8* it will be converted. - CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = 0); + CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr); private: Value *getCastedInt8PtrValue(Value *Ptr); @@ -422,43 +438,44 @@ class IRBuilder : public IRBuilderBase, public Inserter { T Folder; public: IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(), - MDNode *FPMathTag = 0) + MDNode *FPMathTag = nullptr) : IRBuilderBase(C, FPMathTag), Inserter(I), Folder(F) { } - explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) + explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr) : IRBuilderBase(C, FPMathTag), Folder() { } - explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0) + explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = nullptr) : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) { SetInsertPoint(TheBB); } - explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0) + explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr) : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() { SetInsertPoint(TheBB); } - explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0) + explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr) : IRBuilderBase(IP->getContext(), FPMathTag), Folder() { SetInsertPoint(IP); SetCurrentDebugLocation(IP->getDebugLoc()); } - explicit IRBuilder(Use &U, MDNode *FPMathTag = 0) + explicit IRBuilder(Use &U, MDNode *FPMathTag = nullptr) : IRBuilderBase(U->getContext(), FPMathTag), Folder() { SetInsertPoint(U); SetCurrentDebugLocation(cast<Instruction>(U.getUser())->getDebugLoc()); } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F, - MDNode *FPMathTag = 0) + MDNode *FPMathTag = nullptr) : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) { SetInsertPoint(TheBB, IP); } - IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0) + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, + MDNode *FPMathTag = nullptr) : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() { SetInsertPoint(TheBB, IP); } @@ -530,7 +547,7 @@ public: /// \brief Create a conditional 'br Cond, TrueDest, FalseDest' /// instruction. BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, - MDNode *BranchWeights = 0) { + MDNode *BranchWeights = nullptr) { return Insert(addBranchWeights(BranchInst::Create(True, False, Cond), BranchWeights)); } @@ -539,7 +556,7 @@ public: /// and with a hint for the number of cases that will be added (for efficient /// allocation). SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10, - MDNode *BranchWeights = 0) { + MDNode *BranchWeights = nullptr) { return Insert(addBranchWeights(SwitchInst::Create(V, Dest, NumCases), BranchWeights)); } @@ -627,7 +644,7 @@ public: return CreateAdd(LHS, RHS, Name, true, false); } Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFAdd(LC, RC), Name); @@ -638,7 +655,7 @@ public: bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateSub(LC, RC), Name); + return Insert(Folder.CreateSub(LC, RC, HasNUW, HasNSW), Name); return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, HasNUW, HasNSW); } @@ -649,7 +666,7 @@ public: return CreateSub(LHS, RHS, Name, true, false); } Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFSub(LC, RC), Name); @@ -660,7 +677,7 @@ public: bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateMul(LC, RC), Name); + return Insert(Folder.CreateMul(LC, RC, HasNUW, HasNSW), Name); return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, HasNUW, HasNSW); } @@ -671,7 +688,7 @@ public: return CreateMul(LHS, RHS, Name, true, false); } Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFMul(LC, RC), Name); @@ -703,7 +720,7 @@ public: return CreateSDiv(LHS, RHS, Name, true); } Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFDiv(LC, RC), Name); @@ -723,7 +740,7 @@ public: return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); } Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFRem(LC, RC), Name); @@ -832,11 +849,15 @@ public: } Value *CreateBinOp(Instruction::BinaryOps Opc, - Value *LHS, Value *RHS, const Twine &Name = "") { + Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateBinOp(Opc, LC, RC), Name); - return Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); + llvm::Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS); + if (isa<FPMathOperator>(BinOp)) + BinOp = AddFPMathAttributes(BinOp, FPMathTag, FMF); + return Insert(BinOp, Name); } Value *CreateNeg(Value *V, const Twine &Name = "", @@ -854,7 +875,8 @@ public: Value *CreateNUWNeg(Value *V, const Twine &Name = "") { return CreateNeg(V, Name, true, false); } - Value *CreateFNeg(Value *V, const Twine &Name = "", MDNode *FPMathTag = 0) { + Value *CreateFNeg(Value *V, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { if (Constant *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateFNeg(VC), Name); return Insert(AddFPMathAttributes(BinaryOperator::CreateFNeg(V), @@ -870,7 +892,7 @@ public: // Instruction creation methods: Memory Instructions //===--------------------------------------------------------------------===// - AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = 0, + AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = nullptr, const Twine &Name = "") { return Insert(new AllocaInst(Ty, ArraySize), Name); } @@ -883,7 +905,7 @@ public: return Insert(new LoadInst(Ptr), Name); } LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") { - return Insert(new LoadInst(Ptr, 0, isVolatile), Name); + return Insert(new LoadInst(Ptr, nullptr, isVolatile), Name); } StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { return Insert(new StoreInst(Val, Ptr, isVolatile)); @@ -915,13 +937,17 @@ public: return SI; } FenceInst *CreateFence(AtomicOrdering Ordering, - SynchronizationScope SynchScope = CrossThread) { - return Insert(new FenceInst(Context, Ordering, SynchScope)); - } - AtomicCmpXchgInst *CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, - AtomicOrdering Ordering, - SynchronizationScope SynchScope = CrossThread) { - return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope)); + SynchronizationScope SynchScope = CrossThread, + const Twine &Name = "") { + return Insert(new FenceInst(Context, Ordering, SynchScope), Name); + } + AtomicCmpXchgInst * + CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope = CrossThread) { + return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering, + FailureOrdering, SynchScope)); } AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, AtomicOrdering Ordering, @@ -1177,6 +1203,21 @@ public: return Insert(Folder.CreatePointerCast(VC, DestTy), Name); return Insert(CastInst::CreatePointerCast(V, DestTy), Name); } + + Value *CreatePointerBitCastOrAddrSpaceCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + + if (Constant *VC = dyn_cast<Constant>(V)) { + return Insert(Folder.CreatePointerBitCastOrAddrSpaceCast(VC, DestTy), + Name); + } + + return Insert(CastInst::CreatePointerBitCastOrAddrSpaceCast(V, DestTy), + Name); + } + Value *CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name = "") { if (V->getType() == DestTy) @@ -1443,6 +1484,30 @@ public: Value *Zeros = ConstantAggregateZero::get(VectorType::get(I32Ty, NumElts)); return CreateShuffleVector(V, Undef, Zeros, Name + ".splat"); } + + /// \brief Return a value that has been extracted from a larger integer type. + Value *CreateExtractInteger(const DataLayout &DL, Value *From, + IntegerType *ExtractedTy, uint64_t Offset, + const Twine &Name) { + IntegerType *IntTy = cast<IntegerType>(From->getType()); + assert(DL.getTypeStoreSize(ExtractedTy) + Offset <= + DL.getTypeStoreSize(IntTy) && + "Element extends past full value"); + uint64_t ShAmt = 8 * Offset; + Value *V = From; + if (DL.isBigEndian()) + ShAmt = 8 * (DL.getTypeStoreSize(IntTy) - + DL.getTypeStoreSize(ExtractedTy) - Offset); + if (ShAmt) { + V = CreateLShr(V, ShAmt, Name + ".shift"); + } + assert(ExtractedTy->getBitWidth() <= IntTy->getBitWidth() && + "Cannot extract to a larger integer!"); + if (ExtractedTy != IntTy) { + V = CreateTrunc(V, ExtractedTy, Name + ".trunc"); + } + return V; + } }; // Create wrappers for C Binding types (see CBindingWrapping.h). diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h new file mode 100644 index 000000000000..2f78c83165eb --- /dev/null +++ b/include/llvm/IR/IRPrintingPasses.h @@ -0,0 +1,85 @@ +//===- IRPrintingPasses.h - Passes to print out IR constructs ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file defines passes to print out IR in various granularities. The +/// PrintModulePass pass simply prints out the entire module when it is +/// executed. The PrintFunctionPass class is designed to be pipelined with +/// other FunctionPass's, and prints out the functions of the module as they +/// are processed. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_IR_PRINTING_PASSES_H +#define LLVM_IR_IR_PRINTING_PASSES_H + +#include "llvm/ADT/StringRef.h" +#include <string> + +namespace llvm { +class BasicBlockPass; +class Function; +class FunctionPass; +class Module; +class ModulePass; +class PreservedAnalyses; +class raw_ostream; + +/// \brief Create and return a pass that writes the module to the specified +/// \c raw_ostream. +ModulePass *createPrintModulePass(raw_ostream &OS, + const std::string &Banner = ""); + +/// \brief Create and return a pass that prints functions to the specified +/// \c raw_ostream as they are processed. +FunctionPass *createPrintFunctionPass(raw_ostream &OS, + const std::string &Banner = ""); + +/// \brief Create and return a pass that writes the BB to the specified +/// \c raw_ostream. +BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS, + const std::string &Banner = ""); + +/// \brief Pass for printing a Module as LLVM's text IR assembly. +/// +/// Note: This pass is for use with the new pass manager. Use the create...Pass +/// functions above to create passes for use with the legacy pass manager. +class PrintModulePass { + raw_ostream &OS; + std::string Banner; + +public: + PrintModulePass(); + PrintModulePass(raw_ostream &OS, const std::string &Banner = ""); + + PreservedAnalyses run(Module *M); + + static StringRef name() { return "PrintModulePass"; } +}; + +/// \brief Pass for printing a Function as LLVM's text IR assembly. +/// +/// Note: This pass is for use with the new pass manager. Use the create...Pass +/// functions above to create passes for use with the legacy pass manager. +class PrintFunctionPass { + raw_ostream &OS; + std::string Banner; + +public: + PrintFunctionPass(); + PrintFunctionPass(raw_ostream &OS, const std::string &Banner = ""); + + PreservedAnalyses run(Function *F); + + static StringRef name() { return "PrintFunctionPass"; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index 3398a83e365e..ac190892bab0 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -164,9 +164,6 @@ public: ///Default constructor. ConstraintInfo(); - /// Copy constructor. - ConstraintInfo(const ConstraintInfo &other); - /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the /// fields in this structure. If the constraint string is not understood, /// return true, otherwise return false. @@ -197,7 +194,7 @@ public: // These are helper methods for dealing with flags in the INLINEASM SDNode // in the backend. - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Fixed operands on an INLINEASM SDNode. Op_InputChain = 0, Op_AsmString = 1, diff --git a/include/llvm/Support/InstIterator.h b/include/llvm/IR/InstIterator.h index ac936a11a62d..75e93bd2ff8c 100644 --- a/include/llvm/Support/InstIterator.h +++ b/include/llvm/IR/InstIterator.h @@ -1,4 +1,4 @@ -//===- llvm/Support/InstIterator.h - Classes for inst iteration -*- C++ -*-===// +//===- InstIterator.h - Classes for inst iteration --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_INSTITERATOR_H -#define LLVM_SUPPORT_INSTITERATOR_H +#ifndef LLVM_IR_INSTITERATOR_H +#define LLVM_IR_INSTITERATOR_H #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Function.h" diff --git a/include/llvm/InstVisitor.h b/include/llvm/IR/InstVisitor.h index de7206da6b5f..1cdcd55448c9 100644 --- a/include/llvm/InstVisitor.h +++ b/include/llvm/IR/InstVisitor.h @@ -1,4 +1,4 @@ -//===- llvm/InstVisitor.h - Instruction visitor templates -------*- C++ -*-===// +//===- InstVisitor.h - Instruction visitor templates ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -8,15 +8,15 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_INSTVISITOR_H -#define LLVM_INSTVISITOR_H +#ifndef LLVM_IR_INSTVISITOR_H +#define LLVM_IR_INSTVISITOR_H +#include "llvm/IR/CallSite.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" -#include "llvm/Support/CallSite.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index e12bb03a403f..981aad852b29 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -36,7 +36,7 @@ class TerminatorInst : public Instruction { protected: TerminatorInst(Type *Ty, Instruction::TermOps iType, Use *Ops, unsigned NumOps, - Instruction *InsertBefore = 0) + Instruction *InsertBefore = nullptr) : Instruction(Ty, iType, Ops, NumOps, InsertBefore) {} TerminatorInst(Type *Ty, Instruction::TermOps iType, @@ -51,7 +51,7 @@ protected: virtual BasicBlock *getSuccessorV(unsigned idx) const = 0; virtual unsigned getNumSuccessorsV() const = 0; virtual void setSuccessorV(unsigned idx, BasicBlock *B) = 0; - virtual TerminatorInst *clone_impl() const = 0; + TerminatorInst *clone_impl() const override = 0; public: /// getNumSuccessors - Return the number of successors that this terminator @@ -91,7 +91,7 @@ class UnaryInstruction : public Instruction { protected: UnaryInstruction(Type *Ty, unsigned iType, Value *V, - Instruction *IB = 0) + Instruction *IB = nullptr) : Instruction(Ty, iType, &Op<0>(), 1, IB) { Op<0>() = V; } @@ -143,7 +143,7 @@ protected: const Twine &Name, Instruction *InsertBefore); BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd); - virtual BinaryOperator *clone_impl() const LLVM_OVERRIDE; + BinaryOperator *clone_impl() const override; public: // allocate space for exactly two operands void *operator new(size_t s) { @@ -160,7 +160,7 @@ public: /// static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name = Twine(), - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); /// Create() - Construct a binary instruction, given the opcode and the two /// operands. Also automatically insert this instruction to the end of the @@ -285,23 +285,23 @@ public: /// instructions out of SUB and XOR instructions. /// static BinaryOperator *CreateNeg(Value *Op, const Twine &Name = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); static BinaryOperator *CreateNeg(Value *Op, const Twine &Name, BasicBlock *InsertAtEnd); static BinaryOperator *CreateNSWNeg(Value *Op, const Twine &Name = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); static BinaryOperator *CreateNSWNeg(Value *Op, const Twine &Name, BasicBlock *InsertAtEnd); static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); static BinaryOperator *CreateNUWNeg(Value *Op, const Twine &Name, BasicBlock *InsertAtEnd); static BinaryOperator *CreateFNeg(Value *Op, const Twine &Name = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); static BinaryOperator *CreateFNeg(Value *Op, const Twine &Name, BasicBlock *InsertAtEnd); static BinaryOperator *CreateNot(Value *Op, const Twine &Name = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); static BinaryOperator *CreateNot(Value *Op, const Twine &Name, BasicBlock *InsertAtEnd); @@ -385,11 +385,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) /// if (isa<CastInst>(Instr)) { ... } /// @brief Base class of casting instructions. class CastInst : public UnaryInstruction { - virtual void anchor() LLVM_OVERRIDE; + void anchor() override; protected: /// @brief Constructor with insert-before-instruction semantics for subclasses CastInst(Type *Ty, unsigned iType, Value *S, - const Twine &NameStr = "", Instruction *InsertBefore = 0) + const Twine &NameStr = "", Instruction *InsertBefore = nullptr) : UnaryInstruction(Ty, iType, S, InsertBefore) { setName(NameStr); } @@ -411,7 +411,7 @@ public: Value *S, ///< The value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = 0 ///< Place to insert the instruction + Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); /// Provides a way to construct any of the CastInst subclasses using an /// opcode instead of the subclass's constructor. The opcode must be in the @@ -432,7 +432,7 @@ public: Value *S, ///< The value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = 0 ///< Place to insert the instruction + Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); /// @brief Create a ZExt or BitCast cast instruction @@ -448,7 +448,7 @@ public: Value *S, ///< The value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = 0 ///< Place to insert the instruction + Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); /// @brief Create a SExt or BitCast cast instruction @@ -459,7 +459,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Create a BitCast or a PtrToInt cast instruction + /// @brief Create a BitCast AddrSpaceCast, or a PtrToInt cast instruction. static CastInst *CreatePointerCast( Value *S, ///< The pointer value to be casted (operand 0) Type *Ty, ///< The type to which operand is casted @@ -467,11 +467,27 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Create a BitCast or a PtrToInt cast instruction + /// @brief Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction. static CastInst *CreatePointerCast( Value *S, ///< The pointer value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = nullptr ///< Place to insert the instruction + ); + + /// @brief Create a BitCast or an AddrSpaceCast cast instruction. + static CastInst *CreatePointerBitCastOrAddrSpaceCast( + Value *S, ///< The pointer value to be casted (operand 0) + Type *Ty, ///< The type to which operand is casted + const Twine &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a BitCast or an AddrSpaceCast cast instruction. + static CastInst *CreatePointerBitCastOrAddrSpaceCast( + Value *S, ///< The pointer value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction Instruction *InsertBefore = 0 ///< Place to insert the instruction ); @@ -481,7 +497,7 @@ public: Type *Ty, ///< The type to which cast should be made bool isSigned, ///< Whether to regard S as signed or not const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = 0 ///< Place to insert the instruction + Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. @@ -498,7 +514,7 @@ public: Value *S, ///< The floating point value to be casted Type *Ty, ///< The floating point type to cast to const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = 0 ///< Place to insert the instruction + Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts @@ -514,7 +530,7 @@ public: Value *S, ///< The value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made const Twine &Name = "", ///< Name for the instruction - Instruction *InsertBefore = 0 ///< Place to insert the instruction + Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); /// @brief Create a Trunc or BitCast cast instruction @@ -582,6 +598,11 @@ public: Type *IntPtrTy ///< Integer type corresponding to pointer ) const; + /// @brief Determine if this cast is a no-op cast. + bool isNoopCast( + const DataLayout *DL ///< DataLayout to get the Int Ptr type from. + ) const; + /// Determine how a pair of casts can be eliminated, if they can be at all. /// This is a helper function for both CastInst and ConstantExpr. /// @returns 0 if the CastInst pair can't be eliminated, otherwise @@ -636,13 +657,13 @@ class CmpInst : public Instruction { protected: CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, const Twine &Name = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); CmpInst(Type *ty, Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, const Twine &Name, BasicBlock *InsertAtEnd); - virtual void anchor() LLVM_OVERRIDE; // Out of line virtual method. + void anchor() override; // Out of line virtual method. public: /// This enumeration lists the possible predicates for CmpInst subclasses. /// Values in the range 0-31 are reserved for FCmpInst, while values in the @@ -696,7 +717,7 @@ public: static CmpInst *Create(OtherOps Op, unsigned short predicate, Value *S1, Value *S2, const Twine &Name = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); /// Construct a compare instruction, given the opcode, the predicate and the /// two operands. Also automatically insert this instruction to the end of diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index 5721d8f2f3fb..bac6a95b1b71 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -15,9 +15,10 @@ #ifndef LLVM_IR_INSTRUCTION_H #define LLVM_IR_INSTRUCTION_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/User.h" -#include "llvm/Support/DebugLoc.h" namespace llvm { @@ -44,14 +45,16 @@ public: // Out of line virtual method, so the vtable, etc has a home. ~Instruction(); - /// use_back - Specialize the methods defined in Value, as we know that an + /// user_back - Specialize the methods defined in Value, as we know that an /// instruction can only be used by other instructions. - Instruction *use_back() { return cast<Instruction>(*use_begin());} - const Instruction *use_back() const { return cast<Instruction>(*use_begin());} + Instruction *user_back() { return cast<Instruction>(*user_begin());} + const Instruction *user_back() const { return cast<Instruction>(*user_begin());} inline const BasicBlock *getParent() const { return Parent; } inline BasicBlock *getParent() { return Parent; } + const DataLayout *getDataLayout() const; + /// removeFromParent - This method unlinks 'this' from the containing basic /// block, but does not delete it. /// @@ -138,14 +141,14 @@ public: /// getMetadata - Get the metadata of given kind attached to this Instruction. /// If the metadata is not found then return null. MDNode *getMetadata(unsigned KindID) const { - if (!hasMetadata()) return 0; + if (!hasMetadata()) return nullptr; return getMetadataImpl(KindID); } /// getMetadata - Get the metadata of given kind attached to this Instruction. /// If the metadata is not found then return null. MDNode *getMetadata(StringRef Kind) const { - if (!hasMetadata()) return 0; + if (!hasMetadata()) return nullptr; return getMetadataImpl(Kind); } @@ -171,6 +174,21 @@ public: void setMetadata(unsigned KindID, MDNode *Node); void setMetadata(StringRef Kind, MDNode *Node); + /// \brief Drop unknown metadata. + /// Passes are required to drop metadata they don't understand. This is a + /// convenience method for passes to do so. + void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs); + void dropUnknownMetadata() { + return dropUnknownMetadata(ArrayRef<unsigned>()); + } + void dropUnknownMetadata(unsigned ID1) { + return dropUnknownMetadata(makeArrayRef(ID1)); + } + void dropUnknownMetadata(unsigned ID1, unsigned ID2) { + unsigned IDs[] = {ID1, ID2}; + return dropUnknownMetadata(IDs); + } + /// setDebugLoc - Set the debug location information for this instruction. void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } @@ -443,7 +461,7 @@ protected: } Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd); virtual Instruction *clone_impl() const = 0; diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 0843d8fca3e2..308467f7aa17 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -17,6 +17,7 @@ #define LLVM_IR_INSTRUCTIONS_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" @@ -57,18 +58,19 @@ enum SynchronizationScope { /// class AllocaInst : public UnaryInstruction { protected: - virtual AllocaInst *clone_impl() const; + AllocaInst *clone_impl() const override; public: - explicit AllocaInst(Type *Ty, Value *ArraySize = 0, - const Twine &Name = "", Instruction *InsertBefore = 0); + explicit AllocaInst(Type *Ty, Value *ArraySize = nullptr, + const Twine &Name = "", + Instruction *InsertBefore = nullptr); AllocaInst(Type *Ty, Value *ArraySize, const Twine &Name, BasicBlock *InsertAtEnd); - AllocaInst(Type *Ty, const Twine &Name, Instruction *InsertBefore = 0); + AllocaInst(Type *Ty, const Twine &Name, Instruction *InsertBefore = nullptr); AllocaInst(Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd); AllocaInst(Type *Ty, Value *ArraySize, unsigned Align, - const Twine &Name = "", Instruction *InsertBefore = 0); + const Twine &Name = "", Instruction *InsertBefore = nullptr); AllocaInst(Type *Ty, Value *ArraySize, unsigned Align, const Twine &Name, BasicBlock *InsertAtEnd); @@ -101,7 +103,7 @@ public: /// by the instruction. /// unsigned getAlignment() const { - return (1u << getSubclassDataFromInstruction()) >> 1; + return (1u << (getSubclassDataFromInstruction() & 31)) >> 1; } void setAlignment(unsigned Align); @@ -110,6 +112,20 @@ public: /// into the prolog/epilog code, so it is basically free. bool isStaticAlloca() const; + /// \brief Return true if this alloca is used as an inalloca argument to a + /// call. Such allocas are never considered static even if they are in the + /// entry block. + bool isUsedWithInAlloca() const { + return getSubclassDataFromInstruction() & 32; + } + + /// \brief Specify whether this alloca is used to represent a the arguments to + /// a call. + void setUsedWithInAlloca(bool V) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~32) | + (V ? 32 : 0)); + } + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return (I->getOpcode() == Instruction::Alloca); @@ -136,22 +152,22 @@ private: class LoadInst : public UnaryInstruction { void AssertOK(); protected: - virtual LoadInst *clone_impl() const; + LoadInst *clone_impl() const override; public: LoadInst(Value *Ptr, const Twine &NameStr, Instruction *InsertBefore); LoadInst(Value *Ptr, const Twine &NameStr, BasicBlock *InsertAtEnd); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, BasicBlock *InsertAtEnd); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, - unsigned Align, Instruction *InsertBefore = 0); + unsigned Align, Instruction *InsertBefore = nullptr); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, BasicBlock *InsertAtEnd); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread, - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, AtomicOrdering Order, SynchronizationScope SynchScope, @@ -159,8 +175,9 @@ public: LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore); LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd); - explicit LoadInst(Value *Ptr, const char *NameStr = 0, - bool isVolatile = false, Instruction *InsertBefore = 0); + explicit LoadInst(Value *Ptr, const char *NameStr = nullptr, + bool isVolatile = false, + Instruction *InsertBefore = nullptr); LoadInst(Value *Ptr, const char *NameStr, bool isVolatile, BasicBlock *InsertAtEnd); @@ -256,7 +273,7 @@ class StoreInst : public Instruction { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; void AssertOK(); protected: - virtual StoreInst *clone_impl() const; + StoreInst *clone_impl() const override; public: // allocate space for exactly two operands void *operator new(size_t s) { @@ -265,16 +282,16 @@ public: StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore); StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd); StoreInst(Value *Val, Value *Ptr, bool isVolatile = false, - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd); StoreInst(Value *Val, Value *Ptr, bool isVolatile, - unsigned Align, Instruction *InsertBefore = 0); + unsigned Align, Instruction *InsertBefore = nullptr); StoreInst(Value *Val, Value *Ptr, bool isVolatile, unsigned Align, BasicBlock *InsertAtEnd); StoreInst(Value *Val, Value *Ptr, bool isVolatile, unsigned Align, AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread, - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); StoreInst(Value *Val, Value *Ptr, bool isVolatile, unsigned Align, AtomicOrdering Order, SynchronizationScope SynchScope, @@ -383,7 +400,7 @@ class FenceInst : public Instruction { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); protected: - virtual FenceInst *clone_impl() const; + FenceInst *clone_impl() const override; public: // allocate space for exactly zero operands void *operator new(size_t s) { @@ -394,7 +411,7 @@ public: // SequentiallyConsistent. FenceInst(LLVMContext &C, AtomicOrdering Ordering, SynchronizationScope SynchScope = CrossThread, - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); FenceInst(LLVMContext &C, AtomicOrdering Ordering, SynchronizationScope SynchScope, BasicBlock *InsertAtEnd); @@ -449,19 +466,24 @@ private: class AtomicCmpXchgInst : public Instruction { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; void Init(Value *Ptr, Value *Cmp, Value *NewVal, - AtomicOrdering Ordering, SynchronizationScope SynchScope); + AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope); protected: - virtual AtomicCmpXchgInst *clone_impl() const; + AtomicCmpXchgInst *clone_impl() const override; public: // allocate space for exactly three operands void *operator new(size_t s) { return User::operator new(s, 3); } AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal, - AtomicOrdering Ordering, SynchronizationScope SynchScope, - Instruction *InsertBefore = 0); + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope, + Instruction *InsertBefore = nullptr); AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal, - AtomicOrdering Ordering, SynchronizationScope SynchScope, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope, BasicBlock *InsertAtEnd); /// isVolatile - Return true if this is a cmpxchg from a volatile memory @@ -478,17 +500,34 @@ public: (unsigned)V); } + /// Return true if this cmpxchg may spuriously fail. + bool isWeak() const { + return getSubclassDataFromInstruction() & 0x100; + } + + void setWeak(bool IsWeak) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~0x100) | + (IsWeak << 8)); + } + /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); /// Set the ordering constraint on this cmpxchg. - void setOrdering(AtomicOrdering Ordering) { + void setSuccessOrdering(AtomicOrdering Ordering) { assert(Ordering != NotAtomic && "CmpXchg instructions can only be atomic."); - setInstructionSubclassData((getSubclassDataFromInstruction() & 3) | + setInstructionSubclassData((getSubclassDataFromInstruction() & ~0x1c) | (Ordering << 2)); } + void setFailureOrdering(AtomicOrdering Ordering) { + assert(Ordering != NotAtomic && + "CmpXchg instructions can only be atomic."); + setInstructionSubclassData((getSubclassDataFromInstruction() & ~0xe0) | + (Ordering << 5)); + } + /// Specify whether this cmpxchg is atomic and orders other operations with /// respect to all concurrently executing threads, or only with respect to /// signal handlers executing in the same thread. @@ -498,8 +537,13 @@ public: } /// Returns the ordering constraint on this cmpxchg. - AtomicOrdering getOrdering() const { - return AtomicOrdering(getSubclassDataFromInstruction() >> 2); + AtomicOrdering getSuccessOrdering() const { + return AtomicOrdering((getSubclassDataFromInstruction() >> 2) & 7); + } + + /// Returns the ordering constraint on this cmpxchg. + AtomicOrdering getFailureOrdering() const { + return AtomicOrdering((getSubclassDataFromInstruction() >> 5) & 7); } /// Returns whether this cmpxchg is atomic between threads or only within a @@ -523,6 +567,28 @@ public: return getPointerOperand()->getType()->getPointerAddressSpace(); } + /// \brief Returns the strongest permitted ordering on failure, given the + /// desired ordering on success. + /// + /// If the comparison in a cmpxchg operation fails, there is no atomic store + /// so release semantics cannot be provided. So this function drops explicit + /// Release requests from the AtomicOrdering. A SequentiallyConsistent + /// operation would remain SequentiallyConsistent. + static AtomicOrdering + getStrongestFailureOrdering(AtomicOrdering SuccessOrdering) { + switch (SuccessOrdering) { + default: llvm_unreachable("invalid cmpxchg success ordering"); + case Release: + case Monotonic: + return Monotonic; + case AcquireRelease: + case Acquire: + return Acquire; + case SequentiallyConsistent: + return SequentiallyConsistent; + } + } + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::AtomicCmpXchg; @@ -556,7 +622,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) class AtomicRMWInst : public Instruction { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; protected: - virtual AtomicRMWInst *clone_impl() const; + AtomicRMWInst *clone_impl() const override; public: /// This enumeration lists the possible modifications atomicrmw can make. In /// the descriptions, 'p' is the pointer to the instruction's memory location, @@ -597,7 +663,7 @@ public: } AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val, AtomicOrdering Ordering, SynchronizationScope SynchScope, - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val, AtomicOrdering Ordering, SynchronizationScope SynchScope, BasicBlock *InsertAtEnd); @@ -721,11 +787,11 @@ class GetElementPtrInst : public Instruction { unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - virtual GetElementPtrInst *clone_impl() const; + GetElementPtrInst *clone_impl() const override; public: static GetElementPtrInst *Create(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { unsigned Values = 1 + unsigned(IdxList.size()); return new(Values) GetElementPtrInst(Ptr, IdxList, Values, NameStr, InsertBefore); @@ -743,7 +809,7 @@ public: static GetElementPtrInst *CreateInBounds(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr){ GetElementPtrInst *GEP = Create(Ptr, IdxList, NameStr, InsertBefore); GEP->setIsInBounds(true); return GEP; @@ -923,7 +989,7 @@ class ICmpInst: public CmpInst { protected: /// \brief Clone an identical ICmpInst - virtual ICmpInst *clone_impl() const; + ICmpInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics. ICmpInst( @@ -1055,7 +1121,7 @@ public: class FCmpInst: public CmpInst { protected: /// \brief Clone an identical FCmpInst - virtual FCmpInst *clone_impl() const; + FCmpInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics. FCmpInst( @@ -1174,20 +1240,16 @@ class CallInst : public Instruction { inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, BasicBlock *InsertAtEnd); - CallInst(Value *F, Value *Actual, const Twine &NameStr, - Instruction *InsertBefore); - CallInst(Value *F, Value *Actual, const Twine &NameStr, - BasicBlock *InsertAtEnd); explicit CallInst(Value *F, const Twine &NameStr, Instruction *InsertBefore); CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - virtual CallInst *clone_impl() const; + CallInst *clone_impl() const override; public: static CallInst *Create(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { return new(unsigned(Args.size() + 1)) CallInst(Func, Args, NameStr, InsertBefore); } @@ -1198,7 +1260,7 @@ public: CallInst(Func, Args, NameStr, InsertAtEnd); } static CallInst *Create(Value *F, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { return new(1) CallInst(F, NameStr, InsertBefore); } static CallInst *Create(Value *F, const Twine &NameStr, @@ -1213,13 +1275,13 @@ public: /// 3. Bitcast the result of the malloc call to the specified type. static Instruction *CreateMalloc(Instruction *InsertBefore, Type *IntPtrTy, Type *AllocTy, - Value *AllocSize, Value *ArraySize = 0, - Function* MallocF = 0, + Value *AllocSize, Value *ArraySize = nullptr, + Function* MallocF = nullptr, const Twine &Name = ""); static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, Type *IntPtrTy, Type *AllocTy, - Value *AllocSize, Value *ArraySize = 0, - Function* MallocF = 0, + Value *AllocSize, Value *ArraySize = nullptr, + Function* MallocF = nullptr, const Twine &Name = ""); /// CreateFree - Generate the IR for a call to the builtin free function. static Instruction* CreateFree(Value* Source, Instruction *InsertBefore); @@ -1227,10 +1289,24 @@ public: ~CallInst(); - bool isTailCall() const { return getSubclassDataFromInstruction() & 1; } + // Note that 'musttail' implies 'tail'. + enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 }; + TailCallKind getTailCallKind() const { + return TailCallKind(getSubclassDataFromInstruction() & 3); + } + bool isTailCall() const { + return (getSubclassDataFromInstruction() & 3) != TCK_None; + } + bool isMustTailCall() const { + return (getSubclassDataFromInstruction() & 3) == TCK_MustTail; + } void setTailCall(bool isTC = true) { - setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) | - unsigned(isTC)); + setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | + unsigned(isTC ? TCK_Tail : TCK_None)); + } + void setTailCallKind(TailCallKind TCK) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | + unsigned(TCK)); } /// Provide fast operand accessors @@ -1245,14 +1321,30 @@ public: Value *getArgOperand(unsigned i) const { return getOperand(i); } void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } + /// arg_operands - iteration adapter for range-for loops. + iterator_range<op_iterator> arg_operands() { + // The last operand in the op list is the callee - it's not one of the args + // so we don't want to iterate over it. + return iterator_range<op_iterator>(op_begin(), op_end() - 1); + } + + /// arg_operands - iteration adapter for range-for loops. + iterator_range<const_op_iterator> arg_operands() const { + return iterator_range<const_op_iterator>(op_begin(), op_end() - 1); + } + + /// \brief Wrappers for getting the \c Use of a call argument. + const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); } + Use &getArgOperandUse(unsigned i) { return getOperandUse(i); } + /// getCallingConv/setCallingConv - Get or set the calling convention of this /// function call. CallingConv::ID getCallingConv() const { - return static_cast<CallingConv::ID>(getSubclassDataFromInstruction() >> 1); + return static_cast<CallingConv::ID>(getSubclassDataFromInstruction() >> 2); } void setCallingConv(CallingConv::ID CC) { - setInstructionSubclassData((getSubclassDataFromInstruction() & 1) | - (static_cast<unsigned>(CC) << 1)); + setInstructionSubclassData((getSubclassDataFromInstruction() & 3) | + (static_cast<unsigned>(CC) << 2)); } /// getAttributes - Return the parameter attributes for this call. @@ -1284,6 +1376,12 @@ public: return AttributeList.getParamAlignment(i); } + /// \brief Extract the number of dereferenceable bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableBytes(unsigned i) const { + return AttributeList.getDereferenceableBytes(i); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -1450,11 +1548,11 @@ class SelectInst : public Instruction { setName(NameStr); } protected: - virtual SelectInst *clone_impl() const; + SelectInst *clone_impl() const override; public: static SelectInst *Create(Value *C, Value *S1, Value *S2, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { return new(3) SelectInst(C, S1, S2, NameStr, InsertBefore); } static SelectInst *Create(Value *C, Value *S1, Value *S2, @@ -1505,11 +1603,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectInst, Value) /// class VAArgInst : public UnaryInstruction { protected: - virtual VAArgInst *clone_impl() const; + VAArgInst *clone_impl() const override; public: VAArgInst(Value *List, Type *Ty, const Twine &NameStr = "", - Instruction *InsertBefore = 0) + Instruction *InsertBefore = nullptr) : UnaryInstruction(Ty, VAArg, List, InsertBefore) { setName(NameStr); } @@ -1541,16 +1639,16 @@ public: /// class ExtractElementInst : public Instruction { ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - virtual ExtractElementInst *clone_impl() const; + ExtractElementInst *clone_impl() const override; public: static ExtractElementInst *Create(Value *Vec, Value *Idx, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { return new(2) ExtractElementInst(Vec, Idx, NameStr, InsertBefore); } static ExtractElementInst *Create(Value *Vec, Value *Idx, @@ -1602,16 +1700,16 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementInst, Value) class InsertElementInst : public Instruction { InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, const Twine &NameStr = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - virtual InsertElementInst *clone_impl() const; + InsertElementInst *clone_impl() const override; public: static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { return new(3) InsertElementInst(Vec, NewElt, Idx, NameStr, InsertBefore); } static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, @@ -1659,7 +1757,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value) /// class ShuffleVectorInst : public Instruction { protected: - virtual ShuffleVectorInst *clone_impl() const; + ShuffleVectorInst *clone_impl() const override; public: // allocate space for exactly three operands @@ -1668,7 +1766,7 @@ public: } ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, const Twine &NameStr = "", - Instruction *InsertBefor = 0); + Instruction *InsertBefor = nullptr); ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, const Twine &NameStr, BasicBlock *InsertAtEnd); @@ -1760,13 +1858,13 @@ class ExtractValueInst : public UnaryInstruction { return User::operator new(s, 1); } protected: - virtual ExtractValueInst *clone_impl() const; + ExtractValueInst *clone_impl() const override; public: static ExtractValueInst *Create(Value *Agg, ArrayRef<unsigned> Idxs, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { return new ExtractValueInst(Agg, Idxs, NameStr, InsertBefore); } @@ -1867,11 +1965,11 @@ class InsertValueInst : public Instruction { /// and two index insertvalue instructions are so common. InsertValueInst(Value *Agg, Value *Val, unsigned Idx, const Twine &NameStr = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); InsertValueInst(Value *Agg, Value *Val, unsigned Idx, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - virtual InsertValueInst *clone_impl() const; + InsertValueInst *clone_impl() const override; public: // allocate space for exactly two operands void *operator new(size_t s) { @@ -1881,7 +1979,7 @@ public: static InsertValueInst *Create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { return new InsertValueInst(Agg, Val, Idxs, NameStr, InsertBefore); } static InsertValueInst *Create(Value *Agg, Value *Val, @@ -1986,8 +2084,9 @@ class PHINode : public Instruction { return User::operator new(s, 0); } explicit PHINode(Type *Ty, unsigned NumReservedValues, - const Twine &NameStr = "", Instruction *InsertBefore = 0) - : Instruction(Ty, Instruction::PHI, 0, 0, InsertBefore), + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) + : Instruction(Ty, Instruction::PHI, nullptr, 0, InsertBefore), ReservedSpace(NumReservedValues) { setName(NameStr); OperandList = allocHungoffUses(ReservedSpace); @@ -1995,7 +2094,7 @@ class PHINode : public Instruction { PHINode(Type *Ty, unsigned NumReservedValues, const Twine &NameStr, BasicBlock *InsertAtEnd) - : Instruction(Ty, Instruction::PHI, 0, 0, InsertAtEnd), + : Instruction(Ty, Instruction::PHI, nullptr, 0, InsertAtEnd), ReservedSpace(NumReservedValues) { setName(NameStr); OperandList = allocHungoffUses(ReservedSpace); @@ -2006,13 +2105,13 @@ protected: // values and pointers to the incoming blocks, all in one allocation. Use *allocHungoffUses(unsigned) const; - virtual PHINode *clone_impl() const; + PHINode *clone_impl() const override; public: /// Constructors - NumReservedValues is a hint for the number of incoming /// edges that this phi node will have (use 0 if you really have no idea). static PHINode *Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { return new PHINode(Ty, NumReservedValues, NameStr, InsertBefore); } static PHINode *Create(Type *Ty, unsigned NumReservedValues, @@ -2086,8 +2185,7 @@ public: /// getIncomingBlock - Return incoming basic block corresponding /// to value use iterator. /// - template <typename U> - BasicBlock *getIncomingBlock(value_use_iterator<U> I) const { + BasicBlock *getIncomingBlock(Value::const_user_iterator I) const { return getIncomingBlock(I.getUse()); } @@ -2198,14 +2296,14 @@ private: unsigned NumReservedValues, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - virtual LandingPadInst *clone_impl() const; + LandingPadInst *clone_impl() const override; public: /// Constructors - NumReservedClauses is a hint for the number of incoming /// clauses that this landingpad will have (use 0 if you really have no idea). static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, unsigned NumReservedClauses, const Twine &NameStr = "", - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, unsigned NumReservedClauses, const Twine &NameStr, BasicBlock *InsertAtEnd); @@ -2229,12 +2327,14 @@ public: (V ? 1 : 0)); } - /// addClause - Add a catch or filter clause to the landing pad. - void addClause(Value *ClauseVal); + /// Add a catch or filter clause to the landing pad. + void addClause(Constant *ClauseVal); - /// getClause - Get the value of the clause at index Idx. Use isCatch/isFilter - /// to determine what type of clause this is. - Value *getClause(unsigned Idx) const { return OperandList[Idx + 1]; } + /// Get the value of the clause at index Idx. Use isCatch/isFilter to + /// determine what type of clause this is. + Constant *getClause(unsigned Idx) const { + return cast<Constant>(OperandList[Idx + 1]); + } /// isCatch - Return 'true' if the clause and index Idx is a catch clause. bool isCatch(unsigned Idx) const { @@ -2291,15 +2391,15 @@ private: // // NOTE: If the Value* passed is of type void then the constructor behaves as // if it was passed NULL. - explicit ReturnInst(LLVMContext &C, Value *retVal = 0, - Instruction *InsertBefore = 0); + explicit ReturnInst(LLVMContext &C, Value *retVal = nullptr, + Instruction *InsertBefore = nullptr); ReturnInst(LLVMContext &C, Value *retVal, BasicBlock *InsertAtEnd); explicit ReturnInst(LLVMContext &C, BasicBlock *InsertAtEnd); protected: - virtual ReturnInst *clone_impl() const; + ReturnInst *clone_impl() const override; public: - static ReturnInst* Create(LLVMContext &C, Value *retVal = 0, - Instruction *InsertBefore = 0) { + static ReturnInst* Create(LLVMContext &C, Value *retVal = nullptr, + Instruction *InsertBefore = nullptr) { return new(!!retVal) ReturnInst(C, retVal, InsertBefore); } static ReturnInst* Create(LLVMContext &C, Value *retVal, @@ -2316,7 +2416,7 @@ public: /// Convenience accessor. Returns null if there is no return value. Value *getReturnValue() const { - return getNumOperands() != 0 ? getOperand(0) : 0; + return getNumOperands() != 0 ? getOperand(0) : nullptr; } unsigned getNumSuccessors() const { return 0; } @@ -2329,9 +2429,9 @@ public: return isa<Instruction>(V) && classof(cast<Instruction>(V)); } private: - virtual BasicBlock *getSuccessorV(unsigned idx) const; - virtual unsigned getNumSuccessorsV() const; - virtual void setSuccessorV(unsigned idx, BasicBlock *B); + BasicBlock *getSuccessorV(unsigned idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned idx, BasicBlock *B) override; }; template <> @@ -2361,20 +2461,21 @@ class BranchInst : public TerminatorInst { // BranchInst(BB* T, BB *F, Value *C, Inst *I) - 'br C, T, F', insert before I // BranchInst(BB* B, BB *I) - 'br B' insert at end // BranchInst(BB* T, BB *F, Value *C, BB *I) - 'br C, T, F', insert at end - explicit BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore = 0); + explicit BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore = nullptr); BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, - Instruction *InsertBefore = 0); + Instruction *InsertBefore = nullptr); BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd); BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, BasicBlock *InsertAtEnd); protected: - virtual BranchInst *clone_impl() const; + BranchInst *clone_impl() const override; public: - static BranchInst *Create(BasicBlock *IfTrue, Instruction *InsertBefore = 0) { + static BranchInst *Create(BasicBlock *IfTrue, + Instruction *InsertBefore = nullptr) { return new(1) BranchInst(IfTrue, InsertBefore); } static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *IfFalse, - Value *Cond, Instruction *InsertBefore = 0) { + Value *Cond, Instruction *InsertBefore = nullptr) { return new(3) BranchInst(IfTrue, IfFalse, Cond, InsertBefore); } static BranchInst *Create(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) { @@ -2428,9 +2529,9 @@ public: return isa<Instruction>(V) && classof(cast<Instruction>(V)); } private: - virtual BasicBlock *getSuccessorV(unsigned idx) const; - virtual unsigned getNumSuccessorsV() const; - virtual void setSuccessorV(unsigned idx, BasicBlock *B); + BasicBlock *getSuccessorV(unsigned idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned idx, BasicBlock *B) override; }; template <> @@ -2474,7 +2575,7 @@ class SwitchInst : public TerminatorInst { SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, BasicBlock *InsertAtEnd); protected: - virtual SwitchInst *clone_impl() const; + SwitchInst *clone_impl() const override; public: // -2 @@ -2566,6 +2667,9 @@ public: assert(RHS.SI == SI && "Incompatible operators."); return RHS.Index != Index; } + Self &operator*() { + return *this; + } }; typedef CaseIteratorT<const SwitchInst, const ConstantInt, const BasicBlock> @@ -2593,7 +2697,8 @@ public: }; static SwitchInst *Create(Value *Value, BasicBlock *Default, - unsigned NumCases, Instruction *InsertBefore = 0) { + unsigned NumCases, + Instruction *InsertBefore = nullptr) { return new SwitchInst(Value, Default, NumCases, InsertBefore); } static SwitchInst *Create(Value *Value, BasicBlock *Default, @@ -2645,6 +2750,17 @@ public: ConstCaseIt case_end() const { return ConstCaseIt(this, getNumCases()); } + + /// cases - iteration adapter for range-for loops. + iterator_range<CaseIt> cases() { + return iterator_range<CaseIt>(case_begin(), case_end()); + } + + /// cases - iteration adapter for range-for loops. + iterator_range<ConstCaseIt> cases() const { + return iterator_range<ConstCaseIt>(case_begin(), case_end()); + } + /// Returns an iterator that points to the default case. /// Note: this iterator allows to resolve successor only. Attempt /// to resolve case value causes an assertion. @@ -2677,12 +2793,12 @@ public: /// findCaseDest - Finds the unique case value for a given successor. Returns /// null if the successor is not found, not unique, or is the default case. ConstantInt *findCaseDest(BasicBlock *BB) { - if (BB == getDefaultDest()) return NULL; + if (BB == getDefaultDest()) return nullptr; - ConstantInt *CI = NULL; + ConstantInt *CI = nullptr; for (CaseIt i = case_begin(), e = case_end(); i != e; ++i) { if (i.getCaseSuccessor() == BB) { - if (CI) return NULL; // Multiple cases lead to BB. + if (CI) return nullptr; // Multiple cases lead to BB. else CI = i.getCaseValue(); } } @@ -2721,9 +2837,9 @@ public: return isa<Instruction>(V) && classof(cast<Instruction>(V)); } private: - virtual BasicBlock *getSuccessorV(unsigned idx) const; - virtual unsigned getNumSuccessorsV() const; - virtual void setSuccessorV(unsigned idx, BasicBlock *B); + BasicBlock *getSuccessorV(unsigned idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned idx, BasicBlock *B) override; }; template <> @@ -2766,10 +2882,10 @@ class IndirectBrInst : public TerminatorInst { /// autoinserts at the end of the specified BasicBlock. IndirectBrInst(Value *Address, unsigned NumDests, BasicBlock *InsertAtEnd); protected: - virtual IndirectBrInst *clone_impl() const; + IndirectBrInst *clone_impl() const override; public: static IndirectBrInst *Create(Value *Address, unsigned NumDests, - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { return new IndirectBrInst(Address, NumDests, InsertBefore); } static IndirectBrInst *Create(Value *Address, unsigned NumDests, @@ -2819,9 +2935,9 @@ public: return isa<Instruction>(V) && classof(cast<Instruction>(V)); } private: - virtual BasicBlock *getSuccessorV(unsigned idx) const; - virtual unsigned getNumSuccessorsV() const; - virtual void setSuccessorV(unsigned idx, BasicBlock *B); + BasicBlock *getSuccessorV(unsigned idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned idx, BasicBlock *B) override; }; template <> @@ -2858,12 +2974,12 @@ class InvokeInst : public TerminatorInst { ArrayRef<Value *> Args, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - virtual InvokeInst *clone_impl() const; + InvokeInst *clone_impl() const override; public: static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, const Twine &NameStr = "", - Instruction *InsertBefore = 0) { + Instruction *InsertBefore = nullptr) { unsigned Values = unsigned(Args.size()) + 3; return new(Values) InvokeInst(Func, IfNormal, IfException, Args, Values, NameStr, InsertBefore); @@ -2889,6 +3005,20 @@ public: Value *getArgOperand(unsigned i) const { return getOperand(i); } void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } + /// arg_operands - iteration adapter for range-for loops. + iterator_range<op_iterator> arg_operands() { + return iterator_range<op_iterator>(op_begin(), op_end() - 3); + } + + /// arg_operands - iteration adapter for range-for loops. + iterator_range<const_op_iterator> arg_operands() const { + return iterator_range<const_op_iterator>(op_begin(), op_end() - 3); + } + + /// \brief Wrappers for getting the \c Use of a invoke argument. + const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); } + Use &getArgOperandUse(unsigned i) { return getOperandUse(i); } + /// getCallingConv/setCallingConv - Get or set the calling convention of this /// function call. CallingConv::ID getCallingConv() const { @@ -2927,6 +3057,12 @@ public: return AttributeList.getParamAlignment(i); } + /// \brief Extract the number of dereferenceable bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableBytes(unsigned i) const { + return AttributeList.getDereferenceableBytes(i); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -2970,6 +3106,12 @@ public: addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); } + /// \brief Determine if the invoke cannot be duplicated. + bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); } + void setCannotDuplicate() { + addAttribute(AttributeSet::FunctionIndex, Attribute::NoDuplicate); + } + /// \brief Determine if the call returns a structure through first /// pointer argument. bool hasStructRetAttr() const { @@ -3038,9 +3180,9 @@ public: } private: - virtual BasicBlock *getSuccessorV(unsigned idx) const; - virtual unsigned getNumSuccessorsV() const; - virtual void setSuccessorV(unsigned idx, BasicBlock *B); + BasicBlock *getSuccessorV(unsigned idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned idx, BasicBlock *B) override; bool hasFnAttrImpl(Attribute::AttrKind A) const; @@ -3090,12 +3232,12 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value) class ResumeInst : public TerminatorInst { ResumeInst(const ResumeInst &RI); - explicit ResumeInst(Value *Exn, Instruction *InsertBefore=0); + explicit ResumeInst(Value *Exn, Instruction *InsertBefore=nullptr); ResumeInst(Value *Exn, BasicBlock *InsertAtEnd); protected: - virtual ResumeInst *clone_impl() const; + ResumeInst *clone_impl() const override; public: - static ResumeInst *Create(Value *Exn, Instruction *InsertBefore = 0) { + static ResumeInst *Create(Value *Exn, Instruction *InsertBefore = nullptr) { return new(1) ResumeInst(Exn, InsertBefore); } static ResumeInst *Create(Value *Exn, BasicBlock *InsertAtEnd) { @@ -3118,9 +3260,9 @@ public: return isa<Instruction>(V) && classof(cast<Instruction>(V)); } private: - virtual BasicBlock *getSuccessorV(unsigned idx) const; - virtual unsigned getNumSuccessorsV() const; - virtual void setSuccessorV(unsigned idx, BasicBlock *B); + BasicBlock *getSuccessorV(unsigned idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned idx, BasicBlock *B) override; }; template <> @@ -3142,14 +3284,14 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) class UnreachableInst : public TerminatorInst { void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; protected: - virtual UnreachableInst *clone_impl() const; + UnreachableInst *clone_impl() const override; public: // allocate space for exactly zero operands void *operator new(size_t s) { return User::operator new(s, 0); } - explicit UnreachableInst(LLVMContext &C, Instruction *InsertBefore = 0); + explicit UnreachableInst(LLVMContext &C, Instruction *InsertBefore = nullptr); explicit UnreachableInst(LLVMContext &C, BasicBlock *InsertAtEnd); unsigned getNumSuccessors() const { return 0; } @@ -3162,9 +3304,9 @@ public: return isa<Instruction>(V) && classof(cast<Instruction>(V)); } private: - virtual BasicBlock *getSuccessorV(unsigned idx) const; - virtual unsigned getNumSuccessorsV() const; - virtual void setSuccessorV(unsigned idx, BasicBlock *B); + BasicBlock *getSuccessorV(unsigned idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned idx, BasicBlock *B) override; }; //===----------------------------------------------------------------------===// @@ -3175,21 +3317,21 @@ private: class TruncInst : public CastInst { protected: /// \brief Clone an identical TruncInst - virtual TruncInst *clone_impl() const; + TruncInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics TruncInst( - Value *S, ///< The value to be truncated - Type *Ty, ///< The (smaller) type to truncate to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be truncated + Type *Ty, ///< The (smaller) type to truncate to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics TruncInst( Value *S, ///< The value to be truncated - Type *Ty, ///< The (smaller) type to truncate to + Type *Ty, ///< The (smaller) type to truncate to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -3211,21 +3353,21 @@ public: class ZExtInst : public CastInst { protected: /// \brief Clone an identical ZExtInst - virtual ZExtInst *clone_impl() const; + ZExtInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics ZExtInst( - Value *S, ///< The value to be zero extended - Type *Ty, ///< The type to zero extend to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be zero extended + Type *Ty, ///< The type to zero extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end semantics. ZExtInst( Value *S, ///< The value to be zero extended - Type *Ty, ///< The type to zero extend to + Type *Ty, ///< The type to zero extend to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -3247,21 +3389,21 @@ public: class SExtInst : public CastInst { protected: /// \brief Clone an identical SExtInst - virtual SExtInst *clone_impl() const; + SExtInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics SExtInst( - Value *S, ///< The value to be sign extended - Type *Ty, ///< The type to sign extend to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be sign extended + Type *Ty, ///< The type to sign extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics SExtInst( Value *S, ///< The value to be sign extended - Type *Ty, ///< The type to sign extend to + Type *Ty, ///< The type to sign extend to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -3283,21 +3425,21 @@ public: class FPTruncInst : public CastInst { protected: /// \brief Clone an identical FPTruncInst - virtual FPTruncInst *clone_impl() const; + FPTruncInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics FPTruncInst( - Value *S, ///< The value to be truncated - Type *Ty, ///< The type to truncate to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be truncated + Type *Ty, ///< The type to truncate to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-before-instruction semantics FPTruncInst( Value *S, ///< The value to be truncated - Type *Ty, ///< The type to truncate to + Type *Ty, ///< The type to truncate to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -3319,21 +3461,21 @@ public: class FPExtInst : public CastInst { protected: /// \brief Clone an identical FPExtInst - virtual FPExtInst *clone_impl() const; + FPExtInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics FPExtInst( - Value *S, ///< The value to be extended - Type *Ty, ///< The type to extend to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be extended + Type *Ty, ///< The type to extend to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics FPExtInst( Value *S, ///< The value to be extended - Type *Ty, ///< The type to extend to + Type *Ty, ///< The type to extend to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -3355,21 +3497,21 @@ public: class UIToFPInst : public CastInst { protected: /// \brief Clone an identical UIToFPInst - virtual UIToFPInst *clone_impl() const; + UIToFPInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics UIToFPInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics UIToFPInst( Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -3391,21 +3533,21 @@ public: class SIToFPInst : public CastInst { protected: /// \brief Clone an identical SIToFPInst - virtual SIToFPInst *clone_impl() const; + SIToFPInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics SIToFPInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics SIToFPInst( Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -3427,21 +3569,21 @@ public: class FPToUIInst : public CastInst { protected: /// \brief Clone an identical FPToUIInst - virtual FPToUIInst *clone_impl() const; + FPToUIInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics FPToUIInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics FPToUIInst( Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< Where to insert the new instruction ); @@ -3463,21 +3605,21 @@ public: class FPToSIInst : public CastInst { protected: /// \brief Clone an identical FPToSIInst - virtual FPToSIInst *clone_impl() const; + FPToSIInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics FPToSIInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics FPToSIInst( Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -3500,22 +3642,22 @@ class IntToPtrInst : public CastInst { public: /// \brief Constructor with insert-before-instruction semantics IntToPtrInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics IntToPtrInst( Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); /// \brief Clone an identical IntToPtrInst - virtual IntToPtrInst *clone_impl() const; + IntToPtrInst *clone_impl() const override; /// \brief Returns the address space of this instruction's pointer type. unsigned getAddressSpace() const { @@ -3539,21 +3681,21 @@ public: class PtrToIntInst : public CastInst { protected: /// \brief Clone an identical PtrToIntInst - virtual PtrToIntInst *clone_impl() const; + PtrToIntInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics PtrToIntInst( - Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be converted + Type *Ty, ///< The type to convert to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics PtrToIntInst( Value *S, ///< The value to be converted - Type *Ty, ///< The type to convert to + Type *Ty, ///< The type to convert to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -3587,21 +3729,21 @@ public: class BitCastInst : public CastInst { protected: /// \brief Clone an identical BitCastInst - virtual BitCastInst *clone_impl() const; + BitCastInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics BitCastInst( - Value *S, ///< The value to be casted - Type *Ty, ///< The type to casted to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be casted + Type *Ty, ///< The type to casted to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics BitCastInst( Value *S, ///< The value to be casted - Type *Ty, ///< The type to casted to + Type *Ty, ///< The type to casted to const Twine &NameStr, ///< A name for the new instruction BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); @@ -3624,15 +3766,15 @@ public: class AddrSpaceCastInst : public CastInst { protected: /// \brief Clone an identical AddrSpaceCastInst - virtual AddrSpaceCastInst *clone_impl() const; + AddrSpaceCastInst *clone_impl() const override; public: /// \brief Constructor with insert-before-instruction semantics AddrSpaceCastInst( - Value *S, ///< The value to be casted - Type *Ty, ///< The type to casted to - const Twine &NameStr = "", ///< A name for the new instruction - Instruction *InsertBefore = 0 ///< Where to insert the new instruction + Value *S, ///< The value to be casted + Type *Ty, ///< The type to casted to + const Twine &NameStr = "", ///< A name for the new instruction + Instruction *InsertBefore = nullptr ///< Where to insert the new instruction ); /// \brief Constructor with insert-at-end-of-block semantics diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index 8344c56680aa..e053f7867c53 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -118,8 +118,13 @@ namespace llvm { class MemIntrinsic : public IntrinsicInst { public: Value *getRawDest() const { return const_cast<Value*>(getArgOperand(0)); } + const Use &getRawDestUse() const { return getArgOperandUse(0); } + Use &getRawDestUse() { return getArgOperandUse(0); } Value *getLength() const { return const_cast<Value*>(getArgOperand(2)); } + const Use &getLengthUse() const { return getArgOperandUse(2); } + Use &getLengthUse() { return getArgOperandUse(2); } + ConstantInt *getAlignmentCst() const { return cast<ConstantInt>(const_cast<Value*>(getArgOperand(3))); } @@ -192,6 +197,8 @@ namespace llvm { /// get* - Return the arguments to the instruction. /// Value *getValue() const { return const_cast<Value*>(getArgOperand(1)); } + const Use &getValueUse() const { return getArgOperandUse(1); } + Use &getValueUse() { return getArgOperandUse(1); } void setValue(Value *Val) { assert(getValue()->getType() == Val->getType() && @@ -215,6 +222,8 @@ namespace llvm { /// get* - Return the arguments to the instruction. /// Value *getRawSource() const { return const_cast<Value*>(getArgOperand(1)); } + const Use &getRawSourceUse() const { return getArgOperandUse(1); } + Use &getRawSourceUse() { return getArgOperandUse(1); } /// getSource - This is just like getRawSource, but it strips off any cast /// instructions that feed it, giving the original input. The returned diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index 473e525d9b94..b0d746bd4127 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -71,6 +71,9 @@ namespace Intrinsic { /// Map a GCC builtin name to an intrinsic ID. ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName); + + /// Map a MS builtin name to an intrinsic ID. + ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName); /// IITDescriptor - This is a type descriptor which explains the type /// requirements of an intrinsic. This is returned by @@ -79,7 +82,7 @@ namespace Intrinsic { enum IITDescriptorKind { Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, - Argument, ExtendVecArgument, TruncVecArgument + Argument, ExtendArgument, TruncArgument, HalfVecArgument } Kind; union { @@ -98,13 +101,13 @@ namespace Intrinsic { AK_AnyPointer }; unsigned getArgumentNumber() const { - assert(Kind == Argument || Kind == ExtendVecArgument || - Kind == TruncVecArgument); + assert(Kind == Argument || Kind == ExtendArgument || + Kind == TruncArgument || Kind == HalfVecArgument); return Argument_Info >> 2; } ArgKind getArgumentKind() const { - assert(Kind == Argument || Kind == ExtendVecArgument || - Kind == TruncVecArgument); + assert(Kind == Argument || Kind == ExtendArgument || + Kind == TruncArgument || Kind == HalfVecArgument); return (ArgKind)(Argument_Info&3); } diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index ded6cc12bf19..0b8f64fc7984 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -69,6 +69,10 @@ class ReadNone<int argNo> : IntrinsicProperty { def IntrNoReturn : IntrinsicProperty; +// IntrNoduplicate - Calls to this intrinsic cannot be duplicated. +// Parallels the noduplicate attribute on LLVM IR functions. +def IntrNoDuplicate : IntrinsicProperty; + //===----------------------------------------------------------------------===// // Types used by intrinsics. //===----------------------------------------------------------------------===// @@ -102,12 +106,16 @@ class LLVMMatchType<int num> int Number = num; } -// Match the type of another intrinsic parameter that is expected to be -// an integral vector type, but change the element size to be twice as wide -// or half as wide as the other type. This is only useful when the intrinsic -// is overloaded, so the matched type should be declared as iAny. -class LLVMExtendedElementVectorType<int num> : LLVMMatchType<num>; -class LLVMTruncatedElementVectorType<int num> : LLVMMatchType<num>; +// Match the type of another intrinsic parameter that is expected to be based on +// an integral type (i.e. either iN or <N x iM>), but change the scalar size to +// be twice as wide or half as wide as the other type. This is only useful when +// the intrinsic is overloaded, so the matched type should be declared as iAny. +class LLVMExtendedType<int num> : LLVMMatchType<num>; +class LLVMTruncatedType<int num> : LLVMMatchType<num>; + +// Match the type of another intrinsic parameter that is expected to be a +// vector type, but change the element count to be half as many +class LLVMHalfElementsVectorType<int num> : LLVMMatchType<num>; def llvm_void_ty : LLVMType<isVoid>; def llvm_anyint_ty : LLVMType<iAny>; @@ -218,6 +226,10 @@ class GCCBuiltin<string name> { string GCCBuiltinName = name; } +class MSBuiltin<string name> { + string MSBuiltinName = name; +} + //===--------------- Variable Argument Handling Intrinsics ----------------===// // @@ -242,6 +254,10 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], + [IntrNoMem], "llvm.read_register">; +def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], + [], "llvm.write_register">; // Note: we treat stacksave/stackrestore as writemem because we don't otherwise // model their dependencies on allocas. @@ -285,10 +301,17 @@ def int_memset : Intrinsic<[], llvm_i32_ty, llvm_i1_ty], [IntrReadWriteArgMem, NoCapture<0>]>; -// These functions do not actually read memory, but they are sensitive to the -// rounding mode. This needs to be modelled separately; in the meantime -// declaring them as reading memory is conservatively correct. -let Properties = [IntrReadMem] in { +let Properties = [IntrNoMem] in { + def int_fma : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>]>; + def int_fmuladd : Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>]>; + + // These functions do not read memory, but are sensitive to the + // rounding mode. LLVM purposely does not model changes to the FP + // environment so they can be treated as readnone. def int_sqrt : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_powi : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty]>; def int_sin : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; @@ -311,16 +334,6 @@ let Properties = [IntrReadMem] in { def int_round : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; } -let Properties = [IntrNoMem] in { - def int_fma : Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>]>; - - def int_fmuladd : Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>]>; -} - // NOTE: these are internal interfaces. def int_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; def int_longjmp : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [IntrNoReturn]>; @@ -458,13 +471,14 @@ def int_invariant_end : Intrinsic<[], //===------------------------ Stackmap Intrinsics -------------------------===// // def int_experimental_stackmap : Intrinsic<[], - [llvm_i32_ty, llvm_i32_ty, llvm_vararg_ty]>; + [llvm_i64_ty, llvm_i32_ty, llvm_vararg_ty], + [Throws]>; def int_experimental_patchpoint_void : Intrinsic<[], - [llvm_i32_ty, llvm_i32_ty, + [llvm_i64_ty, llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_vararg_ty]>; def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], - [llvm_i32_ty, llvm_i32_ty, + [llvm_i64_ty, llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_vararg_ty]>; @@ -482,10 +496,8 @@ def int_donothing : Intrinsic<[], [], [IntrNoMem]>; // Intrisics to support half precision floating point format let Properties = [IntrNoMem] in { -def int_convert_to_fp16 : Intrinsic<[llvm_i16_ty], [llvm_float_ty]>, - GCCBuiltin<"__gnu_f2h_ieee">; -def int_convert_from_fp16 : Intrinsic<[llvm_float_ty], [llvm_i16_ty]>, - GCCBuiltin<"__gnu_h2f_ieee">; +def int_convert_to_fp16 : Intrinsic<[llvm_i16_ty], [llvm_anyfloat_ty]>; +def int_convert_from_fp16 : Intrinsic<[llvm_anyfloat_ty], [llvm_i16_ty]>; } // These convert intrinsics are to support various conversions between @@ -511,6 +523,11 @@ def int_convertus : Intrinsic<[llvm_anyint_ty], def int_convertuu : Intrinsic<[llvm_anyint_ty], [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; +// Clear cache intrinsic, default to ignore (ie. emit nothing) +// maps to void __clear_cache() on supporting platforms +def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], + [], "llvm.clear_cache">; + //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td index 68af8c1164ec..7d69ed52171c 100644 --- a/include/llvm/IR/IntrinsicsAArch64.td +++ b/include/llvm/IR/IntrinsicsAArch64.td @@ -1,4 +1,4 @@ -//===- IntrinsicsAArch64.td - Defines AArch64 intrinsics -----------*- tablegen -*-===// +//===- IntrinsicsAARCH64.td - Defines AARCH64 intrinsics ---*- tablegen -*-===// // // The LLVM Compiler Infrastructure // @@ -7,382 +7,649 @@ // //===----------------------------------------------------------------------===// // -// This file defines all of the AArch64-specific intrinsics. +// This file defines all of the AARCH64-specific intrinsics. // //===----------------------------------------------------------------------===// +let TargetPrefix = "aarch64" in { + +def int_aarch64_ldxr : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty]>; +def int_aarch64_ldaxr : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty]>; +def int_aarch64_stxr : Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_anyptr_ty]>; +def int_aarch64_stlxr : Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_anyptr_ty]>; + +def int_aarch64_ldxp : Intrinsic<[llvm_i64_ty, llvm_i64_ty], [llvm_ptr_ty]>; +def int_aarch64_ldaxp : Intrinsic<[llvm_i64_ty, llvm_i64_ty], [llvm_ptr_ty]>; +def int_aarch64_stxp : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_ptr_ty]>; +def int_aarch64_stlxp : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_ptr_ty]>; + +def int_aarch64_clrex : Intrinsic<[]>; + +def int_aarch64_sdiv : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, + LLVMMatchType<0>], [IntrNoMem]>; +def int_aarch64_udiv : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, + LLVMMatchType<0>], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// HINT + +def int_aarch64_hint : Intrinsic<[], [llvm_i32_ty]>; + +//===----------------------------------------------------------------------===// +// RBIT + +def int_aarch64_rbit : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], + [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Data Barrier Instructions + +def int_aarch64_dmb : GCCBuiltin<"__builtin_arm_dmb">, Intrinsic<[], [llvm_i32_ty]>; +def int_aarch64_dsb : GCCBuiltin<"__builtin_arm_dsb">, Intrinsic<[], [llvm_i32_ty]>; +def int_aarch64_isb : GCCBuiltin<"__builtin_arm_isb">, Intrinsic<[], [llvm_i32_ty]>; + +} + //===----------------------------------------------------------------------===// // Advanced SIMD (NEON) let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". + class AdvSIMD_2Scalar_Float_Intrinsic + : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + + class AdvSIMD_FPToIntRounding_Intrinsic + : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty], [IntrNoMem]>; + + class AdvSIMD_1IntArg_Intrinsic + : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], [IntrNoMem]>; + class AdvSIMD_1FloatArg_Intrinsic + : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + class AdvSIMD_1VectorArg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; + class AdvSIMD_1VectorArg_Expand_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; + class AdvSIMD_1VectorArg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMTruncatedType<0>], [IntrNoMem]>; + class AdvSIMD_1IntArg_Narrow_Intrinsic + : Intrinsic<[llvm_anyint_ty], [llvm_anyint_ty], [IntrNoMem]>; + class AdvSIMD_1VectorArg_Narrow_Intrinsic + : Intrinsic<[llvm_anyint_ty], [LLVMExtendedType<0>], [IntrNoMem]>; + class AdvSIMD_1VectorArg_Int_Across_Intrinsic + : Intrinsic<[llvm_anyint_ty], [llvm_anyvector_ty], [IntrNoMem]>; + class AdvSIMD_1VectorArg_Float_Across_Intrinsic + : Intrinsic<[llvm_anyfloat_ty], [llvm_anyvector_ty], [IntrNoMem]>; + + class AdvSIMD_2IntArg_Intrinsic + : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + class AdvSIMD_2FloatArg_Intrinsic + : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + class AdvSIMD_2VectorArg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + class AdvSIMD_2VectorArg_Compare_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, LLVMMatchType<1>], + [IntrNoMem]>; + class AdvSIMD_2Arg_FloatCompare_Intrinsic + : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, LLVMMatchType<1>], + [IntrNoMem]>; + class AdvSIMD_2VectorArg_Long_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMTruncatedType<0>, LLVMTruncatedType<0>], + [IntrNoMem]>; + class AdvSIMD_2VectorArg_Wide_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMTruncatedType<0>], + [IntrNoMem]>; + class AdvSIMD_2VectorArg_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMExtendedType<0>, LLVMExtendedType<0>], + [IntrNoMem]>; + class AdvSIMD_2Arg_Scalar_Narrow_Intrinsic + : Intrinsic<[llvm_anyint_ty], + [LLVMExtendedType<0>, llvm_i32_ty], + [IntrNoMem]>; + class AdvSIMD_2VectorArg_Scalar_Expand_BySize_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty], + [IntrNoMem]>; + class AdvSIMD_2VectorArg_Scalar_Wide_BySize_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMTruncatedType<0>], + [IntrNoMem]>; + class AdvSIMD_2VectorArg_Scalar_Wide_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMTruncatedType<0>, llvm_i32_ty], + [IntrNoMem]>; + class AdvSIMD_2VectorArg_Tied_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMHalfElementsVectorType<0>, llvm_anyvector_ty], + [IntrNoMem]>; + + class AdvSIMD_3VectorArg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + class AdvSIMD_3VectorArg_Scalar_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem]>; + class AdvSIMD_3VectorArg_Tied_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMHalfElementsVectorType<0>, llvm_anyvector_ty, + LLVMMatchType<1>], [IntrNoMem]>; + class AdvSIMD_3VectorArg_Scalar_Tied_Narrow_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMHalfElementsVectorType<0>, llvm_anyvector_ty, llvm_i32_ty], + [IntrNoMem]>; + class AdvSIMD_CvtFxToFP_Intrinsic + : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], + [IntrNoMem]>; + class AdvSIMD_CvtFPToFx_Intrinsic + : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], + [IntrNoMem]>; +} + +// Arithmetic ops -// Vector Absolute Compare (Floating Point) -def int_aarch64_neon_vacgeq : - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; -def int_aarch64_neon_vacgtq : - Intrinsic<[llvm_v2i64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - -// Vector saturating accumulate -def int_aarch64_neon_suqadd : Neon_2Arg_Intrinsic; -def int_aarch64_neon_usqadd : Neon_2Arg_Intrinsic; - -// Vector Bitwise reverse -def int_aarch64_neon_rbit : Neon_1Arg_Intrinsic; - -// Vector extract and narrow -def int_aarch64_neon_xtn : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; - -// Vector floating-point convert -def int_aarch64_neon_frintn : Neon_1Arg_Intrinsic; -def int_aarch64_neon_fsqrt : Neon_1Arg_Intrinsic; -def int_aarch64_neon_fcvtxn : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtns : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtnu : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtps : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtpu : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtms : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtmu : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtas : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtau : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtzs : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtzu : - Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; - -// Vector maxNum (Floating Point) -def int_aarch64_neon_vmaxnm : Neon_2Arg_Intrinsic; - -// Vector minNum (Floating Point) -def int_aarch64_neon_vminnm : Neon_2Arg_Intrinsic; - -// Vector Pairwise maxNum (Floating Point) -def int_aarch64_neon_vpmaxnm : Neon_2Arg_Intrinsic; - -// Vector Pairwise minNum (Floating Point) -def int_aarch64_neon_vpminnm : Neon_2Arg_Intrinsic; - -// Vector Multiply Extended and Scalar Multiply Extended (Floating Point) -def int_aarch64_neon_vmulx : - Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; - -class Neon_N2V_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem]>; -class Neon_N3V_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem]>; -class Neon_N2V_Narrow_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMExtendedElementVectorType<0>, llvm_i32_ty], - [IntrNoMem]>; - -// Vector rounding shift right by immediate (Signed) -def int_aarch64_neon_vsrshr : Neon_N2V_Intrinsic; -def int_aarch64_neon_vurshr : Neon_N2V_Intrinsic; -def int_aarch64_neon_vsqshlu : Neon_N2V_Intrinsic; - -def int_aarch64_neon_vsri : Neon_N3V_Intrinsic; -def int_aarch64_neon_vsli : Neon_N3V_Intrinsic; - -def int_aarch64_neon_vsqshrun : Neon_N2V_Narrow_Intrinsic; -def int_aarch64_neon_vrshrn : Neon_N2V_Narrow_Intrinsic; -def int_aarch64_neon_vsqrshrun : Neon_N2V_Narrow_Intrinsic; -def int_aarch64_neon_vsqshrn : Neon_N2V_Narrow_Intrinsic; -def int_aarch64_neon_vuqshrn : Neon_N2V_Narrow_Intrinsic; -def int_aarch64_neon_vsqrshrn : Neon_N2V_Narrow_Intrinsic; -def int_aarch64_neon_vuqrshrn : Neon_N2V_Narrow_Intrinsic; - -// Vector across -class Neon_Across_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; - -class Neon_2Arg_Across_Float_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [llvm_v4f32_ty], [IntrNoMem]>; - -def int_aarch64_neon_saddlv : Neon_Across_Intrinsic; -def int_aarch64_neon_uaddlv : Neon_Across_Intrinsic; -def int_aarch64_neon_smaxv : Neon_Across_Intrinsic; -def int_aarch64_neon_umaxv : Neon_Across_Intrinsic; -def int_aarch64_neon_sminv : Neon_Across_Intrinsic; -def int_aarch64_neon_uminv : Neon_Across_Intrinsic; -def int_aarch64_neon_vaddv : Neon_Across_Intrinsic; -def int_aarch64_neon_vmaxv : Neon_Across_Intrinsic; -def int_aarch64_neon_vminv : Neon_Across_Intrinsic; -def int_aarch64_neon_vmaxnmv : Neon_Across_Intrinsic; -def int_aarch64_neon_vminnmv : Neon_Across_Intrinsic; - -// Vector Table Lookup. -def int_aarch64_neon_vtbl1 : - Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; - -def int_aarch64_neon_vtbl2 : - Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<0>], - [IntrNoMem]>; - -def int_aarch64_neon_vtbl3 : - Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, - LLVMMatchType<0>], [IntrNoMem]>; - -def int_aarch64_neon_vtbl4 : - Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, - LLVMMatchType<1>, LLVMMatchType<0>], [IntrNoMem]>; - -// Vector Table Extension. -// Some elements of the destination vector may not be updated, so the original -// value of that vector is passed as the first argument. The next 1-4 -// arguments after that are the table. -def int_aarch64_neon_vtbx1 : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], - [IntrNoMem]>; - -def int_aarch64_neon_vtbx2 : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, - LLVMMatchType<0>], [IntrNoMem]>; - -def int_aarch64_neon_vtbx3 : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, - LLVMMatchType<1>, LLVMMatchType<0>], [IntrNoMem]>; - -def int_aarch64_neon_vtbx4 : - Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, - LLVMMatchType<1>, LLVMMatchType<1>, LLVMMatchType<0>], - [IntrNoMem]>; - -// Vector Load/store -def int_aarch64_neon_vld1x2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], - [llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; -def int_aarch64_neon_vld1x3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>], - [llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; -def int_aarch64_neon_vld1x4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, - LLVMMatchType<0>, LLVMMatchType<0>], - [llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; - -def int_aarch64_neon_vst1x2 : Intrinsic<[], - [llvm_ptr_ty, llvm_anyvector_ty, - LLVMMatchType<0>, llvm_i32_ty], - [IntrReadWriteArgMem]>; -def int_aarch64_neon_vst1x3 : Intrinsic<[], - [llvm_ptr_ty, llvm_anyvector_ty, - LLVMMatchType<0>, LLVMMatchType<0>, - llvm_i32_ty], [IntrReadWriteArgMem]>; -def int_aarch64_neon_vst1x4 : Intrinsic<[], - [llvm_ptr_ty, llvm_anyvector_ty, - LLVMMatchType<0>, LLVMMatchType<0>, - LLVMMatchType<0>, llvm_i32_ty], - [IntrReadWriteArgMem]>; - -// Scalar Add -def int_aarch64_neon_vaddds : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; -def int_aarch64_neon_vadddu : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; - - -// Scalar Sub -def int_aarch64_neon_vsubds : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; -def int_aarch64_neon_vsubdu : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; - - -// Scalar Shift -// Scalar Shift Left -def int_aarch64_neon_vshlds : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; -def int_aarch64_neon_vshldu : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; - -// Scalar Saturating Shift Left -def int_aarch64_neon_vqshls : Neon_2Arg_Intrinsic; -def int_aarch64_neon_vqshlu : Neon_2Arg_Intrinsic; - -// Scalar Shift Rouding Left -def int_aarch64_neon_vrshlds : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; -def int_aarch64_neon_vrshldu : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; - -// Scalar Saturating Rounding Shift Left -def int_aarch64_neon_vqrshls : Neon_2Arg_Intrinsic; -def int_aarch64_neon_vqrshlu : Neon_2Arg_Intrinsic; - -// Scalar Reduce Pairwise Add. -def int_aarch64_neon_vpadd : - Intrinsic<[llvm_v1i64_ty], [llvm_v2i64_ty],[IntrNoMem]>; -def int_aarch64_neon_vpfadd : - Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; -def int_aarch64_neon_vpfaddq : - Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -// Scalar Reduce Pairwise Floating Point Max/Min. -def int_aarch64_neon_vpmax : - Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; -def int_aarch64_neon_vpmaxq : - Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -def int_aarch64_neon_vpmin : - Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; -def int_aarch64_neon_vpminq : - Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -// Scalar Reduce Pairwise Floating Point Maxnm/Minnm. -def int_aarch64_neon_vpfmaxnm : - Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; -def int_aarch64_neon_vpfmaxnmq : - Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; -def int_aarch64_neon_vpfminnm : - Intrinsic<[llvm_v1f32_ty], [llvm_v2f32_ty], [IntrNoMem]>; -def int_aarch64_neon_vpfminnmq : - Intrinsic<[llvm_v1f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - -// Scalar Signed Integer Convert To Floating-point -def int_aarch64_neon_vcvtf32_s32 : - Intrinsic<[llvm_float_ty], [llvm_v1i32_ty], [IntrNoMem]>; -def int_aarch64_neon_vcvtf64_s64 : - Intrinsic<[llvm_double_ty], [llvm_v1i64_ty], [IntrNoMem]>; - -// Scalar Unsigned Integer Convert To Floating-point -def int_aarch64_neon_vcvtf32_u32 : - Intrinsic<[llvm_float_ty], [llvm_v1i32_ty], [IntrNoMem]>; -def int_aarch64_neon_vcvtf64_u64 : - Intrinsic<[llvm_double_ty], [llvm_v1i64_ty], [IntrNoMem]>; - -// Scalar Floating-point Reciprocal Exponent -def int_aarch64_neon_vrecpx : Neon_1Arg_Intrinsic; - -class Neon_Cmp_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_anyvector_ty], - [IntrNoMem]>; - -// Scalar Compare Equal -def int_aarch64_neon_vceq : Neon_Cmp_Intrinsic; - -// Scalar Compare Greater-Than or Equal -def int_aarch64_neon_vcge : Neon_Cmp_Intrinsic; -def int_aarch64_neon_vchs : Neon_Cmp_Intrinsic; - -// Scalar Compare Less-Than or Equal -def int_aarch64_neon_vclez : Neon_Cmp_Intrinsic; - -// Scalar Compare Less-Than -def int_aarch64_neon_vcltz : Neon_Cmp_Intrinsic; - -// Scalar Compare Greater-Than -def int_aarch64_neon_vcgt : Neon_Cmp_Intrinsic; -def int_aarch64_neon_vchi : Neon_Cmp_Intrinsic; - -// Scalar Compare Bitwise Test Bits -def int_aarch64_neon_vtstd : Neon_Cmp_Intrinsic; - -// Scalar Floating-point Absolute Compare Greater Than Or Equal -def int_aarch64_neon_vcage : Neon_Cmp_Intrinsic; - -// Scalar Floating-point Absolute Compare Greater Than -def int_aarch64_neon_vcagt : Neon_Cmp_Intrinsic; - -// Scalar Signed Saturating Accumulated of Unsigned Value -def int_aarch64_neon_vuqadd : Neon_2Arg_Intrinsic; - -// Scalar Unsigned Saturating Accumulated of Signed Value -def int_aarch64_neon_vsqadd : Neon_2Arg_Intrinsic; - -// Scalar Absolute Value -def int_aarch64_neon_vabs : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty], [IntrNoMem]>; - -// Scalar Absolute Difference -def int_aarch64_neon_vabd : Neon_2Arg_Intrinsic; - -// Scalar Negate Value -def int_aarch64_neon_vneg : - Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty], [IntrNoMem]>; - -// Signed Saturating Doubling Multiply-Add Long -def int_aarch64_neon_vqdmlal : Neon_3Arg_Long_Intrinsic; - -// Signed Saturating Doubling Multiply-Subtract Long -def int_aarch64_neon_vqdmlsl : Neon_3Arg_Long_Intrinsic; - -class Neon_2Arg_ShiftImm_Intrinsic - : Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; - -class Neon_3Arg_ShiftImm_Intrinsic - : Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_v1i64_ty, llvm_i32_ty], - [IntrNoMem]>; - -// Scalar Shift Right (Immediate) -def int_aarch64_neon_vshrds_n : Neon_2Arg_ShiftImm_Intrinsic; -def int_aarch64_neon_vshrdu_n : Neon_2Arg_ShiftImm_Intrinsic; - -// Scalar Shift Right and Accumulate (Immediate) -def int_aarch64_neon_vsrads_n : Neon_3Arg_ShiftImm_Intrinsic; -def int_aarch64_neon_vsradu_n : Neon_3Arg_ShiftImm_Intrinsic; - -// Scalar Rounding Shift Right and Accumulate (Immediate) -def int_aarch64_neon_vrsrads_n : Neon_3Arg_ShiftImm_Intrinsic; -def int_aarch64_neon_vrsradu_n : Neon_3Arg_ShiftImm_Intrinsic; - -// Scalar Shift Left (Immediate) -def int_aarch64_neon_vshld_n : Neon_2Arg_ShiftImm_Intrinsic; - -// Scalar Saturating Shift Left (Immediate) -def int_aarch64_neon_vqshls_n : Neon_N2V_Intrinsic; -def int_aarch64_neon_vqshlu_n : Neon_N2V_Intrinsic; - -// Scalar Signed Saturating Shift Left Unsigned (Immediate) -def int_aarch64_neon_vqshlus_n : Neon_N2V_Intrinsic; - -// Scalar Signed Fixed-point Convert To Floating-Point (Immediate) -def int_aarch64_neon_vcvtf32_n_s32 : - Intrinsic<[llvm_float_ty], [llvm_v1i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_aarch64_neon_vcvtf64_n_s64 : - Intrinsic<[llvm_double_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; +let Properties = [IntrNoMem] in { + // Vector Add Across Lanes + def int_aarch64_neon_saddv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_aarch64_neon_uaddv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_aarch64_neon_faddv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; + + // Vector Long Add Across Lanes + def int_aarch64_neon_saddlv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_aarch64_neon_uaddlv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + + // Vector Halving Add + def int_aarch64_neon_shadd : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_uhadd : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Rounding Halving Add + def int_aarch64_neon_srhadd : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_urhadd : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Saturating Add + def int_aarch64_neon_sqadd : AdvSIMD_2IntArg_Intrinsic; + def int_aarch64_neon_suqadd : AdvSIMD_2IntArg_Intrinsic; + def int_aarch64_neon_usqadd : AdvSIMD_2IntArg_Intrinsic; + def int_aarch64_neon_uqadd : AdvSIMD_2IntArg_Intrinsic; + + // Vector Add High-Half + // FIXME: this is a legacy intrinsic for aarch64_simd.h. Remove it when that + // header is no longer supported. + def int_aarch64_neon_addhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; + + // Vector Rounding Add High-Half + def int_aarch64_neon_raddhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; + + // Vector Saturating Doubling Multiply High + def int_aarch64_neon_sqdmulh : AdvSIMD_2IntArg_Intrinsic; + + // Vector Saturating Rounding Doubling Multiply High + def int_aarch64_neon_sqrdmulh : AdvSIMD_2IntArg_Intrinsic; + + // Vector Polynominal Multiply + def int_aarch64_neon_pmul : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Long Multiply + def int_aarch64_neon_smull : AdvSIMD_2VectorArg_Long_Intrinsic; + def int_aarch64_neon_umull : AdvSIMD_2VectorArg_Long_Intrinsic; + def int_aarch64_neon_pmull : AdvSIMD_2VectorArg_Long_Intrinsic; + + // 64-bit polynomial multiply really returns an i128, which is not legal. Fake + // it with a v16i8. + def int_aarch64_neon_pmull64 : + Intrinsic<[llvm_v16i8_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + + // Vector Extending Multiply + def int_aarch64_neon_fmulx : AdvSIMD_2FloatArg_Intrinsic { + let Properties = [IntrNoMem, Commutative]; + } + + // Vector Saturating Doubling Long Multiply + def int_aarch64_neon_sqdmull : AdvSIMD_2VectorArg_Long_Intrinsic; + def int_aarch64_neon_sqdmulls_scalar + : Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + + // Vector Halving Subtract + def int_aarch64_neon_shsub : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_uhsub : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Saturating Subtract + def int_aarch64_neon_sqsub : AdvSIMD_2IntArg_Intrinsic; + def int_aarch64_neon_uqsub : AdvSIMD_2IntArg_Intrinsic; + + // Vector Subtract High-Half + // FIXME: this is a legacy intrinsic for aarch64_simd.h. Remove it when that + // header is no longer supported. + def int_aarch64_neon_subhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; + + // Vector Rounding Subtract High-Half + def int_aarch64_neon_rsubhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; + + // Vector Compare Absolute Greater-than-or-equal + def int_aarch64_neon_facge : AdvSIMD_2Arg_FloatCompare_Intrinsic; + + // Vector Compare Absolute Greater-than + def int_aarch64_neon_facgt : AdvSIMD_2Arg_FloatCompare_Intrinsic; + + // Vector Absolute Difference + def int_aarch64_neon_sabd : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_uabd : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_fabd : AdvSIMD_2VectorArg_Intrinsic; + + // Scalar Absolute Difference + def int_aarch64_sisd_fabd : AdvSIMD_2Scalar_Float_Intrinsic; + + // Vector Max + def int_aarch64_neon_smax : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_umax : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_fmax : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_fmaxnmp : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Max Across Lanes + def int_aarch64_neon_smaxv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_aarch64_neon_umaxv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_aarch64_neon_fmaxv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; + def int_aarch64_neon_fmaxnmv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; + + // Vector Min + def int_aarch64_neon_smin : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_umin : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_fmin : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_fminnmp : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Min/Max Number + def int_aarch64_neon_fminnm : AdvSIMD_2FloatArg_Intrinsic; + def int_aarch64_neon_fmaxnm : AdvSIMD_2FloatArg_Intrinsic; + + // Vector Min Across Lanes + def int_aarch64_neon_sminv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_aarch64_neon_uminv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_aarch64_neon_fminv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; + def int_aarch64_neon_fminnmv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; + + // Pairwise Add + def int_aarch64_neon_addp : AdvSIMD_2VectorArg_Intrinsic; + + // Long Pairwise Add + // FIXME: In theory, we shouldn't need intrinsics for saddlp or + // uaddlp, but tblgen's type inference currently can't handle the + // pattern fragments this ends up generating. + def int_aarch64_neon_saddlp : AdvSIMD_1VectorArg_Expand_Intrinsic; + def int_aarch64_neon_uaddlp : AdvSIMD_1VectorArg_Expand_Intrinsic; -// Scalar Unsigned Fixed-point Convert To Floating-Point (Immediate) -def int_aarch64_neon_vcvtf32_n_u32 : - Intrinsic<[llvm_float_ty], [llvm_v1i32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_aarch64_neon_vcvtf64_n_u64 : - Intrinsic<[llvm_double_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; + // Folding Maximum + def int_aarch64_neon_smaxp : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_umaxp : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_fmaxp : AdvSIMD_2VectorArg_Intrinsic; + + // Folding Minimum + def int_aarch64_neon_sminp : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_uminp : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_fminp : AdvSIMD_2VectorArg_Intrinsic; + + // Reciprocal Estimate/Step + def int_aarch64_neon_frecps : AdvSIMD_2FloatArg_Intrinsic; + def int_aarch64_neon_frsqrts : AdvSIMD_2FloatArg_Intrinsic; + + // Reciprocal Exponent + def int_aarch64_neon_frecpx : AdvSIMD_1FloatArg_Intrinsic; + + // Vector Saturating Shift Left + def int_aarch64_neon_sqshl : AdvSIMD_2IntArg_Intrinsic; + def int_aarch64_neon_uqshl : AdvSIMD_2IntArg_Intrinsic; + + // Vector Rounding Shift Left + def int_aarch64_neon_srshl : AdvSIMD_2IntArg_Intrinsic; + def int_aarch64_neon_urshl : AdvSIMD_2IntArg_Intrinsic; + + // Vector Saturating Rounding Shift Left + def int_aarch64_neon_sqrshl : AdvSIMD_2IntArg_Intrinsic; + def int_aarch64_neon_uqrshl : AdvSIMD_2IntArg_Intrinsic; + + // Vector Signed->Unsigned Shift Left by Constant + def int_aarch64_neon_sqshlu : AdvSIMD_2IntArg_Intrinsic; + + // Vector Signed->Unsigned Narrowing Saturating Shift Right by Constant + def int_aarch64_neon_sqshrun : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + + // Vector Signed->Unsigned Rounding Narrowing Saturating Shift Right by Const + def int_aarch64_neon_sqrshrun : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + + // Vector Narrowing Shift Right by Constant + def int_aarch64_neon_sqshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + def int_aarch64_neon_uqshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + + // Vector Rounding Narrowing Shift Right by Constant + def int_aarch64_neon_rshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + + // Vector Rounding Narrowing Saturating Shift Right by Constant + def int_aarch64_neon_sqrshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + def int_aarch64_neon_uqrshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + + // Vector Shift Left + def int_aarch64_neon_sshl : AdvSIMD_2IntArg_Intrinsic; + def int_aarch64_neon_ushl : AdvSIMD_2IntArg_Intrinsic; + + // Vector Widening Shift Left by Constant + def int_aarch64_neon_shll : AdvSIMD_2VectorArg_Scalar_Wide_BySize_Intrinsic; + def int_aarch64_neon_sshll : AdvSIMD_2VectorArg_Scalar_Wide_Intrinsic; + def int_aarch64_neon_ushll : AdvSIMD_2VectorArg_Scalar_Wide_Intrinsic; + + // Vector Shift Right by Constant and Insert + def int_aarch64_neon_vsri : AdvSIMD_3VectorArg_Scalar_Intrinsic; + + // Vector Shift Left by Constant and Insert + def int_aarch64_neon_vsli : AdvSIMD_3VectorArg_Scalar_Intrinsic; + + // Vector Saturating Narrow + def int_aarch64_neon_scalar_sqxtn: AdvSIMD_1IntArg_Narrow_Intrinsic; + def int_aarch64_neon_scalar_uqxtn : AdvSIMD_1IntArg_Narrow_Intrinsic; + def int_aarch64_neon_sqxtn : AdvSIMD_1VectorArg_Narrow_Intrinsic; + def int_aarch64_neon_uqxtn : AdvSIMD_1VectorArg_Narrow_Intrinsic; + + // Vector Saturating Extract and Unsigned Narrow + def int_aarch64_neon_scalar_sqxtun : AdvSIMD_1IntArg_Narrow_Intrinsic; + def int_aarch64_neon_sqxtun : AdvSIMD_1VectorArg_Narrow_Intrinsic; + + // Vector Absolute Value + def int_aarch64_neon_abs : AdvSIMD_1IntArg_Intrinsic; + + // Vector Saturating Absolute Value + def int_aarch64_neon_sqabs : AdvSIMD_1IntArg_Intrinsic; + + // Vector Saturating Negation + def int_aarch64_neon_sqneg : AdvSIMD_1IntArg_Intrinsic; + + // Vector Count Leading Sign Bits + def int_aarch64_neon_cls : AdvSIMD_1VectorArg_Intrinsic; + + // Vector Reciprocal Estimate + def int_aarch64_neon_urecpe : AdvSIMD_1VectorArg_Intrinsic; + def int_aarch64_neon_frecpe : AdvSIMD_1FloatArg_Intrinsic; + + // Vector Square Root Estimate + def int_aarch64_neon_ursqrte : AdvSIMD_1VectorArg_Intrinsic; + def int_aarch64_neon_frsqrte : AdvSIMD_1FloatArg_Intrinsic; + + // Vector Bitwise Reverse + def int_aarch64_neon_rbit : AdvSIMD_1VectorArg_Intrinsic; + + // Vector Conversions Between Half-Precision and Single-Precision. + def int_aarch64_neon_vcvtfp2hf + : Intrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_aarch64_neon_vcvthf2fp + : Intrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>; -// Scalar Floating-point Convert To Signed Fixed-point (Immediate) -def int_aarch64_neon_vcvts_n_s32_f32 : - Intrinsic<[llvm_v1i32_ty], [llvm_v1f32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_aarch64_neon_vcvtd_n_s64_f64 : - Intrinsic<[llvm_v1i64_ty], [llvm_v1f64_ty, llvm_i32_ty], [IntrNoMem]>; + // Vector Conversions Between Floating-point and Fixed-point. + def int_aarch64_neon_vcvtfp2fxs : AdvSIMD_CvtFPToFx_Intrinsic; + def int_aarch64_neon_vcvtfp2fxu : AdvSIMD_CvtFPToFx_Intrinsic; + def int_aarch64_neon_vcvtfxs2fp : AdvSIMD_CvtFxToFP_Intrinsic; + def int_aarch64_neon_vcvtfxu2fp : AdvSIMD_CvtFxToFP_Intrinsic; -// Scalar Floating-point Convert To Unsigned Fixed-point (Immediate) -def int_aarch64_neon_vcvts_n_u32_f32 : - Intrinsic<[llvm_v1i32_ty], [llvm_v1f32_ty, llvm_i32_ty], [IntrNoMem]>; -def int_aarch64_neon_vcvtd_n_u64_f64 : - Intrinsic<[llvm_v1i64_ty], [llvm_v1f64_ty, llvm_i32_ty], [IntrNoMem]>; + // Vector FP->Int Conversions + def int_aarch64_neon_fcvtas : AdvSIMD_FPToIntRounding_Intrinsic; + def int_aarch64_neon_fcvtau : AdvSIMD_FPToIntRounding_Intrinsic; + def int_aarch64_neon_fcvtms : AdvSIMD_FPToIntRounding_Intrinsic; + def int_aarch64_neon_fcvtmu : AdvSIMD_FPToIntRounding_Intrinsic; + def int_aarch64_neon_fcvtns : AdvSIMD_FPToIntRounding_Intrinsic; + def int_aarch64_neon_fcvtnu : AdvSIMD_FPToIntRounding_Intrinsic; + def int_aarch64_neon_fcvtps : AdvSIMD_FPToIntRounding_Intrinsic; + def int_aarch64_neon_fcvtpu : AdvSIMD_FPToIntRounding_Intrinsic; + def int_aarch64_neon_fcvtzs : AdvSIMD_FPToIntRounding_Intrinsic; + def int_aarch64_neon_fcvtzu : AdvSIMD_FPToIntRounding_Intrinsic; -class Neon_SHA_Intrinsic - : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v1i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; + // Vector FP Rounding: only ties to even is unrepresented by a normal + // intrinsic. + def int_aarch64_neon_frintn : AdvSIMD_1FloatArg_Intrinsic; -def int_aarch64_neon_sha1c : Neon_SHA_Intrinsic; -def int_aarch64_neon_sha1m : Neon_SHA_Intrinsic; -def int_aarch64_neon_sha1p : Neon_SHA_Intrinsic; + // Scalar FP->Int conversions + + // Vector FP Inexact Narrowing + def int_aarch64_neon_fcvtxn : AdvSIMD_1VectorArg_Expand_Intrinsic; + + // Scalar FP Inexact Narrowing + def int_aarch64_sisd_fcvtxn : Intrinsic<[llvm_float_ty], [llvm_double_ty], + [IntrNoMem]>; +} + +let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". + class AdvSIMD_2Vector2Index_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [llvm_anyvector_ty, llvm_i64_ty, LLVMMatchType<0>, llvm_i64_ty], + [IntrNoMem]>; +} + +// Vector element to element moves +def int_aarch64_neon_vcopy_lane: AdvSIMD_2Vector2Index_Intrinsic; + +let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". + class AdvSIMD_1Vec_Load_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [LLVMAnyPointerType<LLVMMatchType<0>>], + [IntrReadArgMem]>; + class AdvSIMD_1Vec_Store_Lane_Intrinsic + : Intrinsic<[], [llvm_anyvector_ty, llvm_i64_ty, llvm_anyptr_ty], + [IntrReadWriteArgMem, NoCapture<2>]>; + + class AdvSIMD_2Vec_Load_Intrinsic + : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], + [IntrReadArgMem]>; + class AdvSIMD_2Vec_Load_Lane_Intrinsic + : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i64_ty, llvm_anyptr_ty], + [IntrReadArgMem]>; + class AdvSIMD_2Vec_Store_Intrinsic + : Intrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>, + LLVMAnyPointerType<LLVMMatchType<0>>], + [IntrReadWriteArgMem, NoCapture<2>]>; + class AdvSIMD_2Vec_Store_Lane_Intrinsic + : Intrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>, + llvm_i64_ty, llvm_anyptr_ty], + [IntrReadWriteArgMem, NoCapture<3>]>; + + class AdvSIMD_3Vec_Load_Intrinsic + : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], + [IntrReadArgMem]>; + class AdvSIMD_3Vec_Load_Lane_Intrinsic + : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i64_ty, llvm_anyptr_ty], + [IntrReadArgMem]>; + class AdvSIMD_3Vec_Store_Intrinsic + : Intrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMAnyPointerType<LLVMMatchType<0>>], + [IntrReadWriteArgMem, NoCapture<3>]>; + class AdvSIMD_3Vec_Store_Lane_Intrinsic + : Intrinsic<[], [llvm_anyvector_ty, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i64_ty, llvm_anyptr_ty], + [IntrReadWriteArgMem, NoCapture<4>]>; + + class AdvSIMD_4Vec_Load_Intrinsic + : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], + [IntrReadArgMem]>; + class AdvSIMD_4Vec_Load_Lane_Intrinsic + : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [LLVMMatchType<0>, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i64_ty, llvm_anyptr_ty], + [IntrReadArgMem]>; + class AdvSIMD_4Vec_Store_Intrinsic + : Intrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + LLVMAnyPointerType<LLVMMatchType<0>>], + [IntrReadWriteArgMem, NoCapture<4>]>; + class AdvSIMD_4Vec_Store_Lane_Intrinsic + : Intrinsic<[], [llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>, + llvm_i64_ty, llvm_anyptr_ty], + [IntrReadWriteArgMem, NoCapture<5>]>; +} + +// Memory ops + +def int_aarch64_neon_ld1x2 : AdvSIMD_2Vec_Load_Intrinsic; +def int_aarch64_neon_ld1x3 : AdvSIMD_3Vec_Load_Intrinsic; +def int_aarch64_neon_ld1x4 : AdvSIMD_4Vec_Load_Intrinsic; + +def int_aarch64_neon_st1x2 : AdvSIMD_2Vec_Store_Intrinsic; +def int_aarch64_neon_st1x3 : AdvSIMD_3Vec_Store_Intrinsic; +def int_aarch64_neon_st1x4 : AdvSIMD_4Vec_Store_Intrinsic; + +def int_aarch64_neon_ld2 : AdvSIMD_2Vec_Load_Intrinsic; +def int_aarch64_neon_ld3 : AdvSIMD_3Vec_Load_Intrinsic; +def int_aarch64_neon_ld4 : AdvSIMD_4Vec_Load_Intrinsic; + +def int_aarch64_neon_ld2lane : AdvSIMD_2Vec_Load_Lane_Intrinsic; +def int_aarch64_neon_ld3lane : AdvSIMD_3Vec_Load_Lane_Intrinsic; +def int_aarch64_neon_ld4lane : AdvSIMD_4Vec_Load_Lane_Intrinsic; + +def int_aarch64_neon_ld2r : AdvSIMD_2Vec_Load_Intrinsic; +def int_aarch64_neon_ld3r : AdvSIMD_3Vec_Load_Intrinsic; +def int_aarch64_neon_ld4r : AdvSIMD_4Vec_Load_Intrinsic; + +def int_aarch64_neon_st2 : AdvSIMD_2Vec_Store_Intrinsic; +def int_aarch64_neon_st3 : AdvSIMD_3Vec_Store_Intrinsic; +def int_aarch64_neon_st4 : AdvSIMD_4Vec_Store_Intrinsic; + +def int_aarch64_neon_st2lane : AdvSIMD_2Vec_Store_Lane_Intrinsic; +def int_aarch64_neon_st3lane : AdvSIMD_3Vec_Store_Lane_Intrinsic; +def int_aarch64_neon_st4lane : AdvSIMD_4Vec_Store_Lane_Intrinsic; + +let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". + class AdvSIMD_Tbl1_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_v16i8_ty, LLVMMatchType<0>], + [IntrNoMem]>; + class AdvSIMD_Tbl2_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, LLVMMatchType<0>], [IntrNoMem]>; + class AdvSIMD_Tbl3_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, + LLVMMatchType<0>], + [IntrNoMem]>; + class AdvSIMD_Tbl4_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, + LLVMMatchType<0>], + [IntrNoMem]>; + + class AdvSIMD_Tbx1_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_v16i8_ty, LLVMMatchType<0>], + [IntrNoMem]>; + class AdvSIMD_Tbx2_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_v16i8_ty, llvm_v16i8_ty, + LLVMMatchType<0>], + [IntrNoMem]>; + class AdvSIMD_Tbx3_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, LLVMMatchType<0>], + [IntrNoMem]>; + class AdvSIMD_Tbx4_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_v16i8_ty, LLVMMatchType<0>], + [IntrNoMem]>; +} +def int_aarch64_neon_tbl1 : AdvSIMD_Tbl1_Intrinsic; +def int_aarch64_neon_tbl2 : AdvSIMD_Tbl2_Intrinsic; +def int_aarch64_neon_tbl3 : AdvSIMD_Tbl3_Intrinsic; +def int_aarch64_neon_tbl4 : AdvSIMD_Tbl4_Intrinsic; + +def int_aarch64_neon_tbx1 : AdvSIMD_Tbx1_Intrinsic; +def int_aarch64_neon_tbx2 : AdvSIMD_Tbx2_Intrinsic; +def int_aarch64_neon_tbx3 : AdvSIMD_Tbx3_Intrinsic; +def int_aarch64_neon_tbx4 : AdvSIMD_Tbx4_Intrinsic; + +let TargetPrefix = "aarch64" in { + class Crypto_AES_DataKey_Intrinsic + : Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + + class Crypto_AES_Data_Intrinsic + : Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>; + + // SHA intrinsic taking 5 words of the hash (v4i32, i32) and 4 of the schedule + // (v4i32). + class Crypto_SHA_5Hash4Schedule_Intrinsic + : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + // SHA intrinsic taking 5 words of the hash (v4i32, i32) and 4 of the schedule + // (v4i32). + class Crypto_SHA_1Hash_Intrinsic + : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; + + // SHA intrinsic taking 8 words of the schedule + class Crypto_SHA_8Schedule_Intrinsic + : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + + // SHA intrinsic taking 12 words of the schedule + class Crypto_SHA_12Schedule_Intrinsic + : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + // SHA intrinsic taking 8 words of the hash and 4 of the schedule. + class Crypto_SHA_8Hash4Schedule_Intrinsic + : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +} + +// AES +def int_aarch64_crypto_aese : Crypto_AES_DataKey_Intrinsic; +def int_aarch64_crypto_aesd : Crypto_AES_DataKey_Intrinsic; +def int_aarch64_crypto_aesmc : Crypto_AES_Data_Intrinsic; +def int_aarch64_crypto_aesimc : Crypto_AES_Data_Intrinsic; + +// SHA1 +def int_aarch64_crypto_sha1c : Crypto_SHA_5Hash4Schedule_Intrinsic; +def int_aarch64_crypto_sha1p : Crypto_SHA_5Hash4Schedule_Intrinsic; +def int_aarch64_crypto_sha1m : Crypto_SHA_5Hash4Schedule_Intrinsic; +def int_aarch64_crypto_sha1h : Crypto_SHA_1Hash_Intrinsic; + +def int_aarch64_crypto_sha1su0 : Crypto_SHA_12Schedule_Intrinsic; +def int_aarch64_crypto_sha1su1 : Crypto_SHA_8Schedule_Intrinsic; + +// SHA256 +def int_aarch64_crypto_sha256h : Crypto_SHA_8Hash4Schedule_Intrinsic; +def int_aarch64_crypto_sha256h2 : Crypto_SHA_8Hash4Schedule_Intrinsic; +def int_aarch64_crypto_sha256su0 : Crypto_SHA_8Schedule_Intrinsic; +def int_aarch64_crypto_sha256su1 : Crypto_SHA_12Schedule_Intrinsic; + +//===----------------------------------------------------------------------===// +// CRC32 + +let TargetPrefix = "aarch64" in { + +def int_aarch64_crc32b : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_aarch64_crc32cb : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_aarch64_crc32h : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_aarch64_crc32ch : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_aarch64_crc32w : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_aarch64_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_aarch64_crc32x : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; +def int_aarch64_crc32cx : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; } diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index 0b50d64aebc3..a02d7072d720 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -38,16 +38,28 @@ def int_arm_usat : GCCBuiltin<"__builtin_arm_usat">, def int_arm_ldrex : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty]>; def int_arm_strex : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyptr_ty]>; + +def int_arm_ldaex : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty]>; +def int_arm_stlex : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyptr_ty]>; + def int_arm_clrex : Intrinsic<[]>; def int_arm_strexd : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty]>; def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty]>; +def int_arm_stlexd : Intrinsic<[llvm_i32_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty]>; +def int_arm_ldaexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty]>; + //===----------------------------------------------------------------------===// // Data barrier instructions -def int_arm_dmb : GCCBuiltin<"__builtin_arm_dmb">, Intrinsic<[], [llvm_i32_ty]>; -def int_arm_dsb : GCCBuiltin<"__builtin_arm_dsb">, Intrinsic<[], [llvm_i32_ty]>; +def int_arm_dmb : GCCBuiltin<"__builtin_arm_dmb">, MSBuiltin<"__dmb">, + Intrinsic<[], [llvm_i32_ty]>; +def int_arm_dsb : GCCBuiltin<"__builtin_arm_dsb">, MSBuiltin<"__dsb">, + Intrinsic<[], [llvm_i32_ty]>; +def int_arm_isb : GCCBuiltin<"__builtin_arm_isb">, MSBuiltin<"__isb">, + Intrinsic<[], [llvm_i32_ty]>; //===----------------------------------------------------------------------===// // VFP @@ -66,17 +78,21 @@ def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], // Move to coprocessor def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">, + MSBuiltin<"_MoveToCoprocessor">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; def int_arm_mcr2 : GCCBuiltin<"__builtin_arm_mcr2">, + MSBuiltin<"_MoveToCoprocessor2">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; // Move from coprocessor def int_arm_mrc : GCCBuiltin<"__builtin_arm_mrc">, + MSBuiltin<"_MoveFromCoprocessor">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; def int_arm_mrc2 : GCCBuiltin<"__builtin_arm_mrc2">, + MSBuiltin<"_MoveFromCoprocessor2">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; @@ -114,7 +130,18 @@ def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], //===----------------------------------------------------------------------===// // HINT -def int_arm_sevl : Intrinsic<[], []>; + +def int_arm_hint : Intrinsic<[], [llvm_i32_ty]>; + +//===----------------------------------------------------------------------===// +// RBIT + +def int_arm_rbit : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// UND (reserved undefined sequence) + +def int_arm_undefined : Intrinsic<[], [llvm_i32_ty]>; //===----------------------------------------------------------------------===// // Advanced SIMD (NEON) @@ -123,20 +150,15 @@ def int_arm_sevl : Intrinsic<[], []>; class Neon_1Arg_Intrinsic : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem]>; class Neon_1Arg_Narrow_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMExtendedElementVectorType<0>], [IntrNoMem]>; + : Intrinsic<[llvm_anyvector_ty], [LLVMExtendedType<0>], [IntrNoMem]>; class Neon_2Arg_Intrinsic : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; class Neon_2Arg_Narrow_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMExtendedElementVectorType<0>, - LLVMExtendedElementVectorType<0>], + : Intrinsic<[llvm_anyvector_ty], [LLVMExtendedType<0>, LLVMExtendedType<0>], [IntrNoMem]>; class Neon_2Arg_Long_Intrinsic - : Intrinsic<[llvm_anyvector_ty], - [LLVMTruncatedElementVectorType<0>, - LLVMTruncatedElementVectorType<0>], + : Intrinsic<[llvm_anyvector_ty], [LLVMTruncatedType<0>, LLVMTruncatedType<0>], [IntrNoMem]>; class Neon_3Arg_Intrinsic : Intrinsic<[llvm_anyvector_ty], @@ -144,9 +166,7 @@ class Neon_3Arg_Intrinsic [IntrNoMem]>; class Neon_3Arg_Long_Intrinsic : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, - LLVMTruncatedElementVectorType<0>, - LLVMTruncatedElementVectorType<0>], + [LLVMMatchType<0>, LLVMTruncatedType<0>, LLVMTruncatedType<0>], [IntrNoMem]>; class Neon_CvtFxToFP_Intrinsic : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; @@ -155,6 +175,10 @@ class Neon_CvtFPToFx_Intrinsic class Neon_CvtFPtoInt_1Arg_Intrinsic : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; +class Neon_Compare_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, LLVMMatchType<1>], + [IntrNoMem]>; + // The table operands for VTBL and VTBX consist of 1 to 4 v8i8 vectors. // Besides the table, VTBL has one other v8i8 argument and VTBX has two. // Overall, the classes range from 2 to 6 v8i8 arguments. @@ -224,18 +248,8 @@ def int_arm_neon_vqsubu : Neon_2Arg_Intrinsic; def int_arm_neon_vrsubhn : Neon_2Arg_Narrow_Intrinsic; // Vector Absolute Compare. -def int_arm_neon_vacged : Intrinsic<[llvm_v2i32_ty], - [llvm_v2f32_ty, llvm_v2f32_ty], - [IntrNoMem]>; -def int_arm_neon_vacgeq : Intrinsic<[llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; -def int_arm_neon_vacgtd : Intrinsic<[llvm_v2i32_ty], - [llvm_v2f32_ty, llvm_v2f32_ty], - [IntrNoMem]>; -def int_arm_neon_vacgtq : Intrinsic<[llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; +def int_arm_neon_vacge : Neon_Compare_Intrinsic; +def int_arm_neon_vacgt : Neon_Compare_Intrinsic; // Vector Absolute Differences. def int_arm_neon_vabds : Neon_2Arg_Intrinsic; @@ -293,9 +307,6 @@ def int_arm_neon_vpminu : Neon_2Arg_Intrinsic; // Vector Shift. def int_arm_neon_vshifts : Neon_2Arg_Intrinsic; def int_arm_neon_vshiftu : Neon_2Arg_Intrinsic; -def int_arm_neon_vshiftls : Neon_2Arg_Long_Intrinsic; -def int_arm_neon_vshiftlu : Neon_2Arg_Long_Intrinsic; -def int_arm_neon_vshiftn : Neon_2Arg_Narrow_Intrinsic; // Vector Rounding Shift. def int_arm_neon_vrshifts : Neon_2Arg_Intrinsic; @@ -472,19 +483,37 @@ def int_arm_neon_vbsl : Intrinsic<[llvm_anyvector_ty], // Crypto instructions -def int_arm_neon_aesd : Neon_2Arg_Intrinsic; -def int_arm_neon_aese : Neon_2Arg_Intrinsic; -def int_arm_neon_aesimc : Neon_1Arg_Intrinsic; -def int_arm_neon_aesmc : Neon_1Arg_Intrinsic; -def int_arm_neon_sha1h : Neon_1Arg_Intrinsic; -def int_arm_neon_sha1su1 : Neon_2Arg_Intrinsic; -def int_arm_neon_sha256su0 : Neon_2Arg_Intrinsic; -def int_arm_neon_sha1c : Neon_3Arg_Intrinsic; -def int_arm_neon_sha1m : Neon_3Arg_Intrinsic; -def int_arm_neon_sha1p : Neon_3Arg_Intrinsic; -def int_arm_neon_sha1su0: Neon_3Arg_Intrinsic; -def int_arm_neon_sha256h: Neon_3Arg_Intrinsic; -def int_arm_neon_sha256h2: Neon_3Arg_Intrinsic; -def int_arm_neon_sha256su1: Neon_3Arg_Intrinsic; +class AES_1Arg_Intrinsic : Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty], [IntrNoMem]>; +class AES_2Arg_Intrinsic : Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +class SHA_1Arg_Intrinsic : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], + [IntrNoMem]>; +class SHA_2Arg_Intrinsic : Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +class SHA_3Arg_i32_Intrinsic : Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; +class SHA_3Arg_v4i32_Intrinsic : Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + +def int_arm_neon_aesd : AES_2Arg_Intrinsic; +def int_arm_neon_aese : AES_2Arg_Intrinsic; +def int_arm_neon_aesimc : AES_1Arg_Intrinsic; +def int_arm_neon_aesmc : AES_1Arg_Intrinsic; +def int_arm_neon_sha1h : SHA_1Arg_Intrinsic; +def int_arm_neon_sha1su1 : SHA_2Arg_Intrinsic; +def int_arm_neon_sha256su0 : SHA_2Arg_Intrinsic; +def int_arm_neon_sha1c : SHA_3Arg_i32_Intrinsic; +def int_arm_neon_sha1m : SHA_3Arg_i32_Intrinsic; +def int_arm_neon_sha1p : SHA_3Arg_i32_Intrinsic; +def int_arm_neon_sha1su0: SHA_3Arg_v4i32_Intrinsic; +def int_arm_neon_sha256h: SHA_3Arg_v4i32_Intrinsic; +def int_arm_neon_sha256h2: SHA_3Arg_v4i32_Intrinsic; +def int_arm_neon_sha256su1: SHA_3Arg_v4i32_Intrinsic; } // end TargetPrefix diff --git a/include/llvm/IR/IntrinsicsMips.td b/include/llvm/IR/IntrinsicsMips.td index 42c58214151d..34557612cb96 100644 --- a/include/llvm/IR/IntrinsicsMips.td +++ b/include/llvm/IR/IntrinsicsMips.td @@ -26,22 +26,26 @@ let TargetPrefix = "mips" in { // All intrinsics start with "llvm.mips.". // Addition/subtraction def int_mips_addu_qb : GCCBuiltin<"__builtin_mips_addu_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], + [Commutative, IntrNoMem]>; def int_mips_addu_s_qb : GCCBuiltin<"__builtin_mips_addu_s_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [Commutative]>; + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], + [Commutative, IntrNoMem]>; def int_mips_subu_qb : GCCBuiltin<"__builtin_mips_subu_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], []>; + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; def int_mips_subu_s_qb : GCCBuiltin<"__builtin_mips_subu_s_qb">, - Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], []>; + Intrinsic<[llvm_v4i8_ty], [llvm_v4i8_ty, llvm_v4i8_ty], [IntrNoMem]>; def int_mips_addq_ph : GCCBuiltin<"__builtin_mips_addq_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], + [Commutative, IntrNoMem]>; def int_mips_addq_s_ph : GCCBuiltin<"__builtin_mips_addq_s_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [Commutative]>; + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], + [Commutative, IntrNoMem]>; def int_mips_subq_ph : GCCBuiltin<"__builtin_mips_subq_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], []>; + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; def int_mips_subq_s_ph : GCCBuiltin<"__builtin_mips_subq_s_ph">, - Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], []>; + Intrinsic<[mips_v2q15_ty], [mips_v2q15_ty, mips_v2q15_ty], [IntrNoMem]>; def int_mips_madd: GCCBuiltin<"__builtin_mips_madd">, Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], @@ -833,6 +837,12 @@ def int_mips_div_u_w : GCCBuiltin<"__builtin_msa_div_u_w">, def int_mips_div_u_d : GCCBuiltin<"__builtin_msa_div_u_d">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; +// This instruction is part of the MSA spec but it does not share the +// __builtin_msa prefix because it operates on GP registers. +def int_mips_dlsa : GCCBuiltin<"__builtin_mips_dlsa">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_mips_dotp_s_h : GCCBuiltin<"__builtin_msa_dotp_s_h">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; def int_mips_dotp_s_w : GCCBuiltin<"__builtin_msa_dotp_s_w">, @@ -1544,22 +1554,26 @@ def int_mips_shf_w : GCCBuiltin<"__builtin_msa_shf_w">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; def int_mips_sld_b : GCCBuiltin<"__builtin_msa_sld_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_mips_sld_h : GCCBuiltin<"__builtin_msa_sld_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; def int_mips_sld_w : GCCBuiltin<"__builtin_msa_sld_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; def int_mips_sld_d : GCCBuiltin<"__builtin_msa_sld_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; def int_mips_sldi_b : GCCBuiltin<"__builtin_msa_sldi_b">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; def int_mips_sldi_h : GCCBuiltin<"__builtin_msa_sldi_h">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; def int_mips_sldi_w : GCCBuiltin<"__builtin_msa_sldi_w">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; def int_mips_sldi_d : GCCBuiltin<"__builtin_msa_sldi_d">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; def int_mips_sll_b : GCCBuiltin<"__builtin_msa_sll_b">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td index a372c22e4347..cd512841a1af 100644 --- a/include/llvm/IR/IntrinsicsNVVM.td +++ b/include/llvm/IR/IntrinsicsNVVM.td @@ -730,15 +730,15 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64* // Bar.Sync def int_cuda_syncthreads : GCCBuiltin<"__syncthreads">, - Intrinsic<[], [], []>; + Intrinsic<[], [], [IntrNoDuplicate]>; def int_nvvm_barrier0 : GCCBuiltin<"__nvvm_bar0">, - Intrinsic<[], [], []>; + Intrinsic<[], [], [IntrNoDuplicate]>; def int_nvvm_barrier0_popc : GCCBuiltin<"__nvvm_bar0_popc">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>; def int_nvvm_barrier0_and : GCCBuiltin<"__nvvm_bar0_and">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>; def int_nvvm_barrier0_or : GCCBuiltin<"__nvvm_bar0_or">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; + Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>; // Membar def int_nvvm_membar_cta : GCCBuiltin<"__nvvm_membar_cta">, @@ -796,26 +796,25 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64* // Generated within nvvm. Use for ldu on sm_20 or later -// @TODO: Revisit this, Changed LLVMAnyPointerType to LLVMPointerType def int_nvvm_ldu_global_i : Intrinsic<[llvm_anyint_ty], - [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.i">; def int_nvvm_ldu_global_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.f">; def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty], - [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.p">; // Generated within nvvm. Use for ldg on sm_35 or later def int_nvvm_ldg_global_i : Intrinsic<[llvm_anyint_ty], - [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.i">; def int_nvvm_ldg_global_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.f">; def int_nvvm_ldg_global_p : Intrinsic<[llvm_anyptr_ty], - [LLVMPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.p">; // Use for generic pointers @@ -875,12 +874,2791 @@ def int_nvvm_move_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty], [IntrNoMem, NoCapture<0>], "llvm.nvvm.move.ptr">; +// For getting the handle from a texture or surface variable +def int_nvvm_texsurf_handle + : Intrinsic<[llvm_i64_ty], [llvm_metadata_ty, llvm_anyi64ptr_ty], + [IntrNoMem], "llvm.nvvm.texsurf.handle">; +def int_nvvm_texsurf_handle_internal + : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty], + [IntrNoMem], "llvm.nvvm.texsurf.handle.internal">; + /// Error / Warn def int_nvvm_compiler_error : Intrinsic<[], [llvm_anyptr_ty], [], "llvm.nvvm.compiler.error">; def int_nvvm_compiler_warn : Intrinsic<[], [llvm_anyptr_ty], [], "llvm.nvvm.compiler.warn">; +def int_nvvm_reflect : + Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty], [IntrNoMem], "llvm.nvvm.reflect">; + +// isspacep.{const, global, local, shared} +def int_nvvm_isspacep_const + : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem], + "llvm.nvvm.isspacep.const">, + GCCBuiltin<"__nvvm_isspacep_const">; +def int_nvvm_isspacep_global + : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem], + "llvm.nvvm.isspacep.global">, + GCCBuiltin<"__nvvm_isspacep_global">; +def int_nvvm_isspacep_local + : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem], + "llvm.nvvm.isspacep.local">, + GCCBuiltin<"__nvvm_isspacep_local">; +def int_nvvm_isspacep_shared + : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem], + "llvm.nvvm.isspacep.shared">, + GCCBuiltin<"__nvvm_isspacep_shared">; + +// Environment register read +def int_nvvm_read_ptx_sreg_envreg0 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg0">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg0">; +def int_nvvm_read_ptx_sreg_envreg1 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg1">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg1">; +def int_nvvm_read_ptx_sreg_envreg2 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg2">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg2">; +def int_nvvm_read_ptx_sreg_envreg3 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg3">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg3">; +def int_nvvm_read_ptx_sreg_envreg4 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg4">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg4">; +def int_nvvm_read_ptx_sreg_envreg5 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg5">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg5">; +def int_nvvm_read_ptx_sreg_envreg6 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg6">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg6">; +def int_nvvm_read_ptx_sreg_envreg7 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg7">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg7">; +def int_nvvm_read_ptx_sreg_envreg8 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg8">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg8">; +def int_nvvm_read_ptx_sreg_envreg9 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg9">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg9">; +def int_nvvm_read_ptx_sreg_envreg10 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg10">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg10">; +def int_nvvm_read_ptx_sreg_envreg11 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg11">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg11">; +def int_nvvm_read_ptx_sreg_envreg12 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg12">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg12">; +def int_nvvm_read_ptx_sreg_envreg13 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg13">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg13">; +def int_nvvm_read_ptx_sreg_envreg14 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg14">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg14">; +def int_nvvm_read_ptx_sreg_envreg15 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg15">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg15">; +def int_nvvm_read_ptx_sreg_envreg16 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg16">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg16">; +def int_nvvm_read_ptx_sreg_envreg17 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg17">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg17">; +def int_nvvm_read_ptx_sreg_envreg18 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg18">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg18">; +def int_nvvm_read_ptx_sreg_envreg19 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg19">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg19">; +def int_nvvm_read_ptx_sreg_envreg20 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg20">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg20">; +def int_nvvm_read_ptx_sreg_envreg21 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg21">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg21">; +def int_nvvm_read_ptx_sreg_envreg22 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg22">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg22">; +def int_nvvm_read_ptx_sreg_envreg23 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg23">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg23">; +def int_nvvm_read_ptx_sreg_envreg24 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg24">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg24">; +def int_nvvm_read_ptx_sreg_envreg25 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg25">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg25">; +def int_nvvm_read_ptx_sreg_envreg26 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg26">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg26">; +def int_nvvm_read_ptx_sreg_envreg27 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg27">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg27">; +def int_nvvm_read_ptx_sreg_envreg28 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg28">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg28">; +def int_nvvm_read_ptx_sreg_envreg29 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg29">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg29">; +def int_nvvm_read_ptx_sreg_envreg30 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg30">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg30">; +def int_nvvm_read_ptx_sreg_envreg31 + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem], + "llvm.nvvm.read.ptx.sreg.envreg31">, + GCCBuiltin<"__nvvm_read_ptx_sreg_envreg31">; + + +// Texture Fetch +// texmode_independent +def int_nvvm_tex_1d_v4f32_s32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.1d.v4f32.s32">; +def int_nvvm_tex_1d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.v4f32.f32">; +def int_nvvm_tex_1d_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.level.v4f32.f32">; +def int_nvvm_tex_1d_grad_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.1d.grad.v4f32.f32">; +def int_nvvm_tex_1d_v4s32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.1d.v4s32.s32">; +def int_nvvm_tex_1d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.v4s32.f32">; +def int_nvvm_tex_1d_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.level.v4s32.f32">; +def int_nvvm_tex_1d_grad_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.1d.grad.v4s32.f32">; +def int_nvvm_tex_1d_v4u32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.1d.v4u32.s32">; +def int_nvvm_tex_1d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.v4u32.f32">; +def int_nvvm_tex_1d_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.level.v4u32.f32">; +def int_nvvm_tex_1d_grad_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.1d.grad.v4u32.f32">; + +def int_nvvm_tex_1d_array_v4f32_s32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.1d.array.v4f32.s32">; +def int_nvvm_tex_1d_array_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.array.v4f32.f32">; +def int_nvvm_tex_1d_array_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.1d.array.level.v4f32.f32">; +def int_nvvm_tex_1d_array_grad_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.array.grad.v4f32.f32">; +def int_nvvm_tex_1d_array_v4s32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.1d.array.v4s32.s32">; +def int_nvvm_tex_1d_array_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.array.v4s32.f32">; +def int_nvvm_tex_1d_array_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.1d.array.level.v4s32.f32">; +def int_nvvm_tex_1d_array_grad_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.array.grad.v4s32.f32">; +def int_nvvm_tex_1d_array_v4u32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.1d.array.v4u32.s32">; +def int_nvvm_tex_1d_array_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.array.v4u32.f32">; +def int_nvvm_tex_1d_array_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.1d.array.level.v4u32.f32">; +def int_nvvm_tex_1d_array_grad_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.1d.array.grad.v4u32.f32">; + +def int_nvvm_tex_2d_v4f32_s32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.2d.v4f32.s32">; +def int_nvvm_tex_2d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.2d.v4f32.f32">; +def int_nvvm_tex_2d_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.2d.level.v4f32.f32">; +def int_nvvm_tex_2d_grad_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.2d.grad.v4f32.f32">; +def int_nvvm_tex_2d_v4s32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.2d.v4s32.s32">; +def int_nvvm_tex_2d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.2d.v4s32.f32">; +def int_nvvm_tex_2d_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.2d.level.v4s32.f32">; +def int_nvvm_tex_2d_grad_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.2d.grad.v4s32.f32">; +def int_nvvm_tex_2d_v4u32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.2d.v4u32.s32">; +def int_nvvm_tex_2d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.2d.v4u32.f32">; +def int_nvvm_tex_2d_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.2d.level.v4u32.f32">; +def int_nvvm_tex_2d_grad_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.2d.grad.v4u32.f32">; + +def int_nvvm_tex_2d_array_v4f32_s32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], [], + "llvm.nvvm.tex.2d.array.v4f32.s32">; +def int_nvvm_tex_2d_array_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.2d.array.v4f32.f32">; +def int_nvvm_tex_2d_array_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.2d.array.level.v4f32.f32">; +def int_nvvm_tex_2d_array_grad_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.2d.array.grad.v4f32.f32">; +def int_nvvm_tex_2d_array_v4s32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], [], + "llvm.nvvm.tex.2d.array.v4s32.s32">; +def int_nvvm_tex_2d_array_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.2d.array.v4s32.f32">; +def int_nvvm_tex_2d_array_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.2d.array.level.v4s32.f32">; +def int_nvvm_tex_2d_array_grad_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.2d.array.grad.v4s32.f32">; +def int_nvvm_tex_2d_array_v4u32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], [], + "llvm.nvvm.tex.2d.array.v4u32.s32">; +def int_nvvm_tex_2d_array_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.2d.array.v4u32.f32">; +def int_nvvm_tex_2d_array_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.2d.array.level.v4u32.f32">; +def int_nvvm_tex_2d_array_grad_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.2d.array.grad.v4u32.f32">; + +def int_nvvm_tex_3d_v4f32_s32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [], "llvm.nvvm.tex.3d.v4f32.s32">; +def int_nvvm_tex_3d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.3d.v4f32.f32">; +def int_nvvm_tex_3d_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.3d.level.v4f32.f32">; +def int_nvvm_tex_3d_grad_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.3d.grad.v4f32.f32">; +def int_nvvm_tex_3d_v4s32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [], "llvm.nvvm.tex.3d.v4s32.s32">; +def int_nvvm_tex_3d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.3d.v4s32.f32">; +def int_nvvm_tex_3d_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.3d.level.v4s32.f32">; +def int_nvvm_tex_3d_grad_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.3d.grad.v4s32.f32">; +def int_nvvm_tex_3d_v4u32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [], "llvm.nvvm.tex.3d.v4u32.s32">; +def int_nvvm_tex_3d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.3d.v4u32.f32">; +def int_nvvm_tex_3d_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.3d.level.v4u32.f32">; +def int_nvvm_tex_3d_grad_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.3d.grad.v4u32.f32">; + +def int_nvvm_tex_cube_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.v4f32.f32">; +def int_nvvm_tex_cube_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.level.v4f32.f32">; +def int_nvvm_tex_cube_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.v4s32.f32">; +def int_nvvm_tex_cube_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.level.v4s32.f32">; +def int_nvvm_tex_cube_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.v4u32.f32">; +def int_nvvm_tex_cube_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.level.v4u32.f32">; + +def int_nvvm_tex_cube_array_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.array.v4f32.f32">; +def int_nvvm_tex_cube_array_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.array.level.v4f32.f32">; +def int_nvvm_tex_cube_array_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.array.v4s32.f32">; +def int_nvvm_tex_cube_array_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.array.level.v4s32.f32">; +def int_nvvm_tex_cube_array_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.array.v4u32.f32">; +def int_nvvm_tex_cube_array_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.cube.array.level.v4u32.f32">; + +def int_nvvm_tld4_r_2d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.r.2d.v4f32.f32">; +def int_nvvm_tld4_g_2d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.g.2d.v4f32.f32">; +def int_nvvm_tld4_b_2d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.b.2d.v4f32.f32">; +def int_nvvm_tld4_a_2d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.a.2d.v4f32.f32">; +def int_nvvm_tld4_r_2d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.r.2d.v4s32.f32">; +def int_nvvm_tld4_g_2d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.g.2d.v4s32.f32">; +def int_nvvm_tld4_b_2d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.b.2d.v4s32.f32">; +def int_nvvm_tld4_a_2d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.a.2d.v4s32.f32">; +def int_nvvm_tld4_r_2d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.r.2d.v4u32.f32">; +def int_nvvm_tld4_g_2d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.g.2d.v4u32.f32">; +def int_nvvm_tld4_b_2d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.b.2d.v4u32.f32">; +def int_nvvm_tld4_a_2d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.a.2d.v4u32.f32">; + + +// texmode_unified +def int_nvvm_tex_unified_1d_v4f32_s32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.unified.1d.v4f32.s32">; +def int_nvvm_tex_unified_1d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.v4f32.f32">; +def int_nvvm_tex_unified_1d_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.level.v4f32.f32">; +def int_nvvm_tex_unified_1d_grad_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.grad.v4f32.f32">; +def int_nvvm_tex_unified_1d_v4s32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.unified.1d.v4s32.s32">; +def int_nvvm_tex_unified_1d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.v4s32.f32">; +def int_nvvm_tex_unified_1d_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.level.v4s32.f32">; +def int_nvvm_tex_unified_1d_grad_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.grad.v4s32.f32">; +def int_nvvm_tex_unified_1d_v4u32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.unified.1d.v4u32.s32">; +def int_nvvm_tex_unified_1d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.v4u32.f32">; +def int_nvvm_tex_unified_1d_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.level.v4u32.f32">; +def int_nvvm_tex_unified_1d_grad_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.grad.v4u32.f32">; + +def int_nvvm_tex_unified_1d_array_v4f32_s32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.unified.1d.array.v4f32.s32">; +def int_nvvm_tex_unified_1d_array_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.array.v4f32.f32">; +def int_nvvm_tex_unified_1d_array_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.array.level.v4f32.f32">; +def int_nvvm_tex_unified_1d_array_grad_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.array.grad.v4f32.f32">; +def int_nvvm_tex_unified_1d_array_v4s32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.unified.1d.array.v4s32.s32">; +def int_nvvm_tex_unified_1d_array_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.array.v4s32.f32">; +def int_nvvm_tex_unified_1d_array_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.array.level.v4s32.f32">; +def int_nvvm_tex_unified_1d_array_grad_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.array.grad.v4s32.f32">; +def int_nvvm_tex_unified_1d_array_v4u32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.unified.1d.array.v4u32.s32">; +def int_nvvm_tex_unified_1d_array_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.array.v4u32.f32">; +def int_nvvm_tex_unified_1d_array_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.array.level.v4u32.f32">; +def int_nvvm_tex_unified_1d_array_grad_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.1d.array.grad.v4u32.f32">; + +def int_nvvm_tex_unified_2d_v4f32_s32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.unified.2d.v4f32.s32">; +def int_nvvm_tex_unified_2d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.v4f32.f32">; +def int_nvvm_tex_unified_2d_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.level.v4f32.f32">; +def int_nvvm_tex_unified_2d_grad_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.grad.v4f32.f32">; +def int_nvvm_tex_unified_2d_v4s32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.unified.2d.v4s32.s32">; +def int_nvvm_tex_unified_2d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.v4s32.f32">; +def int_nvvm_tex_unified_2d_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.level.v4s32.f32">; +def int_nvvm_tex_unified_2d_grad_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.grad.v4s32.f32">; +def int_nvvm_tex_unified_2d_v4u32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.tex.unified.2d.v4u32.s32">; +def int_nvvm_tex_unified_2d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.v4u32.f32">; +def int_nvvm_tex_unified_2d_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.level.v4u32.f32">; +def int_nvvm_tex_unified_2d_grad_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.grad.v4u32.f32">; + +def int_nvvm_tex_unified_2d_array_v4f32_s32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], [], + "llvm.nvvm.tex.unified.2d.array.v4f32.s32">; +def int_nvvm_tex_unified_2d_array_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.array.v4f32.f32">; +def int_nvvm_tex_unified_2d_array_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.array.level.v4f32.f32">; +def int_nvvm_tex_unified_2d_array_grad_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.array.grad.v4f32.f32">; +def int_nvvm_tex_unified_2d_array_v4s32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], [], + "llvm.nvvm.tex.unified.2d.array.v4s32.s32">; +def int_nvvm_tex_unified_2d_array_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.array.v4s32.f32">; +def int_nvvm_tex_unified_2d_array_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.array.level.v4s32.f32">; +def int_nvvm_tex_unified_2d_array_grad_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.array.grad.v4s32.f32">; +def int_nvvm_tex_unified_2d_array_v4u32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty], [], + "llvm.nvvm.tex.unified.2d.array.v4u32.s32">; +def int_nvvm_tex_unified_2d_array_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.array.v4u32.f32">; +def int_nvvm_tex_unified_2d_array_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.array.level.v4u32.f32">; +def int_nvvm_tex_unified_2d_array_grad_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.2d.array.grad.v4u32.f32">; + +def int_nvvm_tex_unified_3d_v4f32_s32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [], "llvm.nvvm.tex.unified.3d.v4f32.s32">; +def int_nvvm_tex_unified_3d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.3d.v4f32.f32">; +def int_nvvm_tex_unified_3d_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.3d.level.v4f32.f32">; +def int_nvvm_tex_unified_3d_grad_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.3d.grad.v4f32.f32">; +def int_nvvm_tex_unified_3d_v4s32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [], "llvm.nvvm.tex.unified.3d.v4s32.s32">; +def int_nvvm_tex_unified_3d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.3d.v4s32.f32">; +def int_nvvm_tex_unified_3d_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.3d.level.v4s32.f32">; +def int_nvvm_tex_unified_3d_grad_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.3d.grad.v4s32.f32">; +def int_nvvm_tex_unified_3d_v4u32_s32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [], "llvm.nvvm.tex.unified.3d.v4u32.s32">; +def int_nvvm_tex_unified_3d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty], [], + "llvm.nvvm.tex.unified.3d.v4u32.f32">; +def int_nvvm_tex_unified_3d_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.3d.level.v4u32.f32">; +def int_nvvm_tex_unified_3d_grad_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.3d.grad.v4u32.f32">; + +def int_nvvm_tex_unified_cube_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.v4f32.f32">; +def int_nvvm_tex_unified_cube_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.level.v4f32.f32">; +def int_nvvm_tex_unified_cube_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.v4s32.f32">; +def int_nvvm_tex_unified_cube_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.level.v4s32.f32">; +def int_nvvm_tex_unified_cube_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.v4u32.f32">; +def int_nvvm_tex_unified_cube_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.level.v4u32.f32">; + +def int_nvvm_tex_unified_cube_array_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.array.v4f32.f32">; +def int_nvvm_tex_unified_cube_array_level_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.array.level.v4f32.f32">; +def int_nvvm_tex_unified_cube_array_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.array.v4s32.f32">; +def int_nvvm_tex_unified_cube_array_level_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.array.level.v4s32.f32">; +def int_nvvm_tex_unified_cube_array_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.array.v4u32.f32">; +def int_nvvm_tex_unified_cube_array_level_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, + llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tex.unified.cube.array.level.v4u32.f32">; + +def int_nvvm_tld4_unified_r_2d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.r.2d.v4f32.f32">; +def int_nvvm_tld4_unified_g_2d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.g.2d.v4f32.f32">; +def int_nvvm_tld4_unified_b_2d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.b.2d.v4f32.f32">; +def int_nvvm_tld4_unified_a_2d_v4f32_f32 + : Intrinsic<[llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_float_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.a.2d.v4f32.f32">; +def int_nvvm_tld4_unified_r_2d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.r.2d.v4s32.f32">; +def int_nvvm_tld4_unified_g_2d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.g.2d.v4s32.f32">; +def int_nvvm_tld4_unified_b_2d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.b.2d.v4s32.f32">; +def int_nvvm_tld4_unified_a_2d_v4s32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.a.2d.v4s32.f32">; +def int_nvvm_tld4_unified_r_2d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.r.2d.v4u32.f32">; +def int_nvvm_tld4_unified_g_2d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.g.2d.v4u32.f32">; +def int_nvvm_tld4_unified_b_2d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.b.2d.v4u32.f32">; +def int_nvvm_tld4_unified_a_2d_v4u32_f32 + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_float_ty, llvm_float_ty], [], + "llvm.nvvm.tld4.unified.a.2d.v4u32.f32">; + + +//=== Surface Load +// .clamp variants +def int_nvvm_suld_1d_i8_clamp + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i8.clamp">; +def int_nvvm_suld_1d_i16_clamp + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i16.clamp">; +def int_nvvm_suld_1d_i32_clamp + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i32.clamp">; +def int_nvvm_suld_1d_i64_clamp + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i64.clamp">; +def int_nvvm_suld_1d_v2i8_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i8.clamp">; +def int_nvvm_suld_1d_v2i16_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i16.clamp">; +def int_nvvm_suld_1d_v2i32_clamp + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i32.clamp">; +def int_nvvm_suld_1d_v2i64_clamp + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i64.clamp">; +def int_nvvm_suld_1d_v4i8_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v4i8.clamp">; +def int_nvvm_suld_1d_v4i16_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v4i16.clamp">; +def int_nvvm_suld_1d_v4i32_clamp + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v4i32.clamp">; + +def int_nvvm_suld_1d_array_i8_clamp + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i8.clamp">; +def int_nvvm_suld_1d_array_i16_clamp + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i16.clamp">; +def int_nvvm_suld_1d_array_i32_clamp + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i32.clamp">; +def int_nvvm_suld_1d_array_i64_clamp + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i64.clamp">; +def int_nvvm_suld_1d_array_v2i8_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i8.clamp">; +def int_nvvm_suld_1d_array_v2i16_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i16.clamp">; +def int_nvvm_suld_1d_array_v2i32_clamp + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i32.clamp">; +def int_nvvm_suld_1d_array_v2i64_clamp + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i64.clamp">; +def int_nvvm_suld_1d_array_v4i8_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v4i8.clamp">; +def int_nvvm_suld_1d_array_v4i16_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v4i16.clamp">; +def int_nvvm_suld_1d_array_v4i32_clamp + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v4i32.clamp">; + +def int_nvvm_suld_2d_i8_clamp + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i8.clamp">; +def int_nvvm_suld_2d_i16_clamp + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i16.clamp">; +def int_nvvm_suld_2d_i32_clamp + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i32.clamp">; +def int_nvvm_suld_2d_i64_clamp + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i64.clamp">; +def int_nvvm_suld_2d_v2i8_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i8.clamp">; +def int_nvvm_suld_2d_v2i16_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i16.clamp">; +def int_nvvm_suld_2d_v2i32_clamp + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i32.clamp">; +def int_nvvm_suld_2d_v2i64_clamp + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i64.clamp">; +def int_nvvm_suld_2d_v4i8_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v4i8.clamp">; +def int_nvvm_suld_2d_v4i16_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v4i16.clamp">; +def int_nvvm_suld_2d_v4i32_clamp + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v4i32.clamp">; + +def int_nvvm_suld_2d_array_i8_clamp + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i8.clamp">; +def int_nvvm_suld_2d_array_i16_clamp + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i16.clamp">; +def int_nvvm_suld_2d_array_i32_clamp + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i32.clamp">; +def int_nvvm_suld_2d_array_i64_clamp + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i64.clamp">; +def int_nvvm_suld_2d_array_v2i8_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i8.clamp">; +def int_nvvm_suld_2d_array_v2i16_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i16.clamp">; +def int_nvvm_suld_2d_array_v2i32_clamp + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i32.clamp">; +def int_nvvm_suld_2d_array_v2i64_clamp + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i64.clamp">; +def int_nvvm_suld_2d_array_v4i8_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v4i8.clamp">; +def int_nvvm_suld_2d_array_v4i16_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v4i16.clamp">; +def int_nvvm_suld_2d_array_v4i32_clamp + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v4i32.clamp">; + +def int_nvvm_suld_3d_i8_clamp + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i8.clamp">; +def int_nvvm_suld_3d_i16_clamp + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i16.clamp">; +def int_nvvm_suld_3d_i32_clamp + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i32.clamp">; +def int_nvvm_suld_3d_i64_clamp + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i64.clamp">; +def int_nvvm_suld_3d_v2i8_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i8.clamp">; +def int_nvvm_suld_3d_v2i16_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i16.clamp">; +def int_nvvm_suld_3d_v2i32_clamp + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i32.clamp">; +def int_nvvm_suld_3d_v2i64_clamp + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i64.clamp">; +def int_nvvm_suld_3d_v4i8_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v4i8.clamp">; +def int_nvvm_suld_3d_v4i16_clamp + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v4i16.clamp">; +def int_nvvm_suld_3d_v4i32_clamp + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v4i32.clamp">; + +// .trap variants +def int_nvvm_suld_1d_i8_trap + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i8.trap">; +def int_nvvm_suld_1d_i16_trap + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i16.trap">; +def int_nvvm_suld_1d_i32_trap + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i32.trap">; +def int_nvvm_suld_1d_i64_trap + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i64.trap">; +def int_nvvm_suld_1d_v2i8_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i8.trap">; +def int_nvvm_suld_1d_v2i16_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i16.trap">; +def int_nvvm_suld_1d_v2i32_trap + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i32.trap">; +def int_nvvm_suld_1d_v2i64_trap + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i64.trap">; +def int_nvvm_suld_1d_v4i8_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v4i8.trap">; +def int_nvvm_suld_1d_v4i16_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v4i16.trap">; +def int_nvvm_suld_1d_v4i32_trap + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v4i32.trap">; + +def int_nvvm_suld_1d_array_i8_trap + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i8.trap">; +def int_nvvm_suld_1d_array_i16_trap + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i16.trap">; +def int_nvvm_suld_1d_array_i32_trap + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i32.trap">; +def int_nvvm_suld_1d_array_i64_trap + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i64.trap">; +def int_nvvm_suld_1d_array_v2i8_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i8.trap">; +def int_nvvm_suld_1d_array_v2i16_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i16.trap">; +def int_nvvm_suld_1d_array_v2i32_trap + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i32.trap">; +def int_nvvm_suld_1d_array_v2i64_trap + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i64.trap">; +def int_nvvm_suld_1d_array_v4i8_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v4i8.trap">; +def int_nvvm_suld_1d_array_v4i16_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v4i16.trap">; +def int_nvvm_suld_1d_array_v4i32_trap + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v4i32.trap">; + +def int_nvvm_suld_2d_i8_trap + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i8.trap">; +def int_nvvm_suld_2d_i16_trap + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i16.trap">; +def int_nvvm_suld_2d_i32_trap + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i32.trap">; +def int_nvvm_suld_2d_i64_trap + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i64.trap">; +def int_nvvm_suld_2d_v2i8_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i8.trap">; +def int_nvvm_suld_2d_v2i16_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i16.trap">; +def int_nvvm_suld_2d_v2i32_trap + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i32.trap">; +def int_nvvm_suld_2d_v2i64_trap + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i64.trap">; +def int_nvvm_suld_2d_v4i8_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v4i8.trap">; +def int_nvvm_suld_2d_v4i16_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v4i16.trap">; +def int_nvvm_suld_2d_v4i32_trap + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v4i32.trap">; + +def int_nvvm_suld_2d_array_i8_trap + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i8.trap">; +def int_nvvm_suld_2d_array_i16_trap + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i16.trap">; +def int_nvvm_suld_2d_array_i32_trap + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i32.trap">; +def int_nvvm_suld_2d_array_i64_trap + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i64.trap">; +def int_nvvm_suld_2d_array_v2i8_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i8.trap">; +def int_nvvm_suld_2d_array_v2i16_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i16.trap">; +def int_nvvm_suld_2d_array_v2i32_trap + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i32.trap">; +def int_nvvm_suld_2d_array_v2i64_trap + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i64.trap">; +def int_nvvm_suld_2d_array_v4i8_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v4i8.trap">; +def int_nvvm_suld_2d_array_v4i16_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v4i16.trap">; +def int_nvvm_suld_2d_array_v4i32_trap + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v4i32.trap">; + +def int_nvvm_suld_3d_i8_trap + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i8.trap">; +def int_nvvm_suld_3d_i16_trap + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i16.trap">; +def int_nvvm_suld_3d_i32_trap + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i32.trap">; +def int_nvvm_suld_3d_i64_trap + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i64.trap">; +def int_nvvm_suld_3d_v2i8_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i8.trap">; +def int_nvvm_suld_3d_v2i16_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i16.trap">; +def int_nvvm_suld_3d_v2i32_trap + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i32.trap">; +def int_nvvm_suld_3d_v2i64_trap + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i64.trap">; +def int_nvvm_suld_3d_v4i8_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v4i8.trap">; +def int_nvvm_suld_3d_v4i16_trap + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v4i16.trap">; +def int_nvvm_suld_3d_v4i32_trap + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v4i32.trap">; + +// .zero variants +def int_nvvm_suld_1d_i8_zero + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i8.zero">; +def int_nvvm_suld_1d_i16_zero + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i16.zero">; +def int_nvvm_suld_1d_i32_zero + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i32.zero">; +def int_nvvm_suld_1d_i64_zero + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.i64.zero">; +def int_nvvm_suld_1d_v2i8_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i8.zero">; +def int_nvvm_suld_1d_v2i16_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i16.zero">; +def int_nvvm_suld_1d_v2i32_zero + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i32.zero">; +def int_nvvm_suld_1d_v2i64_zero + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v2i64.zero">; +def int_nvvm_suld_1d_v4i8_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v4i8.zero">; +def int_nvvm_suld_1d_v4i16_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v4i16.zero">; +def int_nvvm_suld_1d_v4i32_zero + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.v4i32.zero">; + +def int_nvvm_suld_1d_array_i8_zero + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i8.zero">; +def int_nvvm_suld_1d_array_i16_zero + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i16.zero">; +def int_nvvm_suld_1d_array_i32_zero + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i32.zero">; +def int_nvvm_suld_1d_array_i64_zero + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.i64.zero">; +def int_nvvm_suld_1d_array_v2i8_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i8.zero">; +def int_nvvm_suld_1d_array_v2i16_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i16.zero">; +def int_nvvm_suld_1d_array_v2i32_zero + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i32.zero">; +def int_nvvm_suld_1d_array_v2i64_zero + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v2i64.zero">; +def int_nvvm_suld_1d_array_v4i8_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v4i8.zero">; +def int_nvvm_suld_1d_array_v4i16_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v4i16.zero">; +def int_nvvm_suld_1d_array_v4i32_zero + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.1d.array.v4i32.zero">; + +def int_nvvm_suld_2d_i8_zero + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i8.zero">; +def int_nvvm_suld_2d_i16_zero + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i16.zero">; +def int_nvvm_suld_2d_i32_zero + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i32.zero">; +def int_nvvm_suld_2d_i64_zero + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.i64.zero">; +def int_nvvm_suld_2d_v2i8_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i8.zero">; +def int_nvvm_suld_2d_v2i16_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i16.zero">; +def int_nvvm_suld_2d_v2i32_zero + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i32.zero">; +def int_nvvm_suld_2d_v2i64_zero + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v2i64.zero">; +def int_nvvm_suld_2d_v4i8_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v4i8.zero">; +def int_nvvm_suld_2d_v4i16_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v4i16.zero">; +def int_nvvm_suld_2d_v4i32_zero + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.v4i32.zero">; + +def int_nvvm_suld_2d_array_i8_zero + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i8.zero">; +def int_nvvm_suld_2d_array_i16_zero + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i16.zero">; +def int_nvvm_suld_2d_array_i32_zero + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i32.zero">; +def int_nvvm_suld_2d_array_i64_zero + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.i64.zero">; +def int_nvvm_suld_2d_array_v2i8_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i8.zero">; +def int_nvvm_suld_2d_array_v2i16_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i16.zero">; +def int_nvvm_suld_2d_array_v2i32_zero + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i32.zero">; +def int_nvvm_suld_2d_array_v2i64_zero + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v2i64.zero">; +def int_nvvm_suld_2d_array_v4i8_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v4i8.zero">; +def int_nvvm_suld_2d_array_v4i16_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v4i16.zero">; +def int_nvvm_suld_2d_array_v4i32_zero + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.2d.array.v4i32.zero">; + +def int_nvvm_suld_3d_i8_zero + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i8.zero">; +def int_nvvm_suld_3d_i16_zero + : Intrinsic<[llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i16.zero">; +def int_nvvm_suld_3d_i32_zero + : Intrinsic<[llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i32.zero">; +def int_nvvm_suld_3d_i64_zero + : Intrinsic<[llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.i64.zero">; +def int_nvvm_suld_3d_v2i8_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i8.zero">; +def int_nvvm_suld_3d_v2i16_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i16.zero">; +def int_nvvm_suld_3d_v2i32_zero + : Intrinsic<[llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i32.zero">; +def int_nvvm_suld_3d_v2i64_zero + : Intrinsic<[llvm_i64_ty, llvm_i64_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v2i64.zero">; +def int_nvvm_suld_3d_v4i8_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v4i8.zero">; +def int_nvvm_suld_3d_v4i16_zero + : Intrinsic<[llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v4i16.zero">; +def int_nvvm_suld_3d_v4i32_zero + : Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.suld.3d.v4i32.zero">; + +//===- Texture Query ------------------------------------------------------===// + +def int_nvvm_txq_channel_order + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.txq.channel.order">, + GCCBuiltin<"__nvvm_txq_channel_order">; +def int_nvvm_txq_channel_data_type + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.txq.channel.data.type">, + GCCBuiltin<"__nvvm_txq_channel_data_type">; +def int_nvvm_txq_width + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.txq.width">, + GCCBuiltin<"__nvvm_txq_width">; +def int_nvvm_txq_height + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.txq.height">, + GCCBuiltin<"__nvvm_txq_height">; +def int_nvvm_txq_depth + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.txq.depth">, + GCCBuiltin<"__nvvm_txq_depth">; +def int_nvvm_txq_array_size + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.txq.array.size">, + GCCBuiltin<"__nvvm_txq_array_size">; +def int_nvvm_txq_num_samples + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.txq.num.samples">, + GCCBuiltin<"__nvvm_txq_num_samples">; +def int_nvvm_txq_num_mipmap_levels + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.txq.num.mipmap.levels">, + GCCBuiltin<"__nvvm_txq_num_mipmap_levels">; + +//===- Surface Query ------------------------------------------------------===// + +def int_nvvm_suq_channel_order + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.suq.channel.order">, + GCCBuiltin<"__nvvm_suq_channel_order">; +def int_nvvm_suq_channel_data_type + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.suq.channel.data.type">, + GCCBuiltin<"__nvvm_suq_channel_data_type">; +def int_nvvm_suq_width + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.suq.width">, + GCCBuiltin<"__nvvm_suq_width">; +def int_nvvm_suq_height + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.suq.height">, + GCCBuiltin<"__nvvm_suq_height">; +def int_nvvm_suq_depth + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.suq.depth">, + GCCBuiltin<"__nvvm_suq_depth">; +def int_nvvm_suq_array_size + : Intrinsic<[llvm_i32_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.suq.array.size">, + GCCBuiltin<"__nvvm_suq_array_size">; + + +//===- Handle Query -------------------------------------------------------===// + +def int_nvvm_istypep_sampler + : Intrinsic<[llvm_i1_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.istypep.sampler">, + GCCBuiltin<"__nvvm_istypep_sampler">; +def int_nvvm_istypep_surface + : Intrinsic<[llvm_i1_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.istypep.surface">, + GCCBuiltin<"__nvvm_istypep_surface">; +def int_nvvm_istypep_texture + : Intrinsic<[llvm_i1_ty], [llvm_i64_ty], [IntrNoMem], + "llvm.nvvm.istypep.texture">, + GCCBuiltin<"__nvvm_istypep_texture">; + + + +//===- Surface Stores -----------------------------------------------------===// + +// Unformatted +// .clamp variant +def int_nvvm_sust_b_1d_i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_i8_clamp">; +def int_nvvm_sust_b_1d_i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_i16_clamp">; +def int_nvvm_sust_b_1d_i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_i32_clamp">; +def int_nvvm_sust_b_1d_i64_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.i64.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_i64_clamp">; +def int_nvvm_sust_b_1d_v2i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v2i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i8_clamp">; +def int_nvvm_sust_b_1d_v2i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v2i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i16_clamp">; +def int_nvvm_sust_b_1d_v2i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.v2i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i32_clamp">; +def int_nvvm_sust_b_1d_v2i64_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.v2i64.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i64_clamp">; +def int_nvvm_sust_b_1d_v4i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v4i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_v4i8_clamp">; +def int_nvvm_sust_b_1d_v4i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v4i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_v4i16_clamp">; +def int_nvvm_sust_b_1d_v4i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.v4i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_v4i32_clamp">; + + +def int_nvvm_sust_b_1d_array_i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i8_clamp">; +def int_nvvm_sust_b_1d_array_i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i16_clamp">; +def int_nvvm_sust_b_1d_array_i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.array.i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i32_clamp">; +def int_nvvm_sust_b_1d_array_i64_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.array.i64.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i64_clamp">; +def int_nvvm_sust_b_1d_array_v2i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i8_clamp">; +def int_nvvm_sust_b_1d_array_v2i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i16_clamp">; +def int_nvvm_sust_b_1d_array_v2i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i32_clamp">; +def int_nvvm_sust_b_1d_array_v2i64_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i64.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i64_clamp">; +def int_nvvm_sust_b_1d_array_v4i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v4i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v4i8_clamp">; +def int_nvvm_sust_b_1d_array_v4i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v4i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v4i16_clamp">; +def int_nvvm_sust_b_1d_array_v4i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.array.v4i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v4i32_clamp">; + + +def int_nvvm_sust_b_2d_i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_i8_clamp">; +def int_nvvm_sust_b_2d_i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_i16_clamp">; +def int_nvvm_sust_b_2d_i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_i32_clamp">; +def int_nvvm_sust_b_2d_i64_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.i64.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_i64_clamp">; +def int_nvvm_sust_b_2d_v2i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v2i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i8_clamp">; +def int_nvvm_sust_b_2d_v2i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v2i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i16_clamp">; +def int_nvvm_sust_b_2d_v2i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.v2i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i32_clamp">; +def int_nvvm_sust_b_2d_v2i64_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.v2i64.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i64_clamp">; +def int_nvvm_sust_b_2d_v4i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v4i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_v4i8_clamp">; +def int_nvvm_sust_b_2d_v4i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v4i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_v4i16_clamp">; +def int_nvvm_sust_b_2d_v4i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.v4i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_v4i32_clamp">; + + +def int_nvvm_sust_b_2d_array_i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i8_clamp">; +def int_nvvm_sust_b_2d_array_i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i16_clamp">; +def int_nvvm_sust_b_2d_array_i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.array.i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i32_clamp">; +def int_nvvm_sust_b_2d_array_i64_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.array.i64.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i64_clamp">; +def int_nvvm_sust_b_2d_array_v2i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i8_clamp">; +def int_nvvm_sust_b_2d_array_v2i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i16_clamp">; +def int_nvvm_sust_b_2d_array_v2i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i32_clamp">; +def int_nvvm_sust_b_2d_array_v2i64_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i64.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i64_clamp">; +def int_nvvm_sust_b_2d_array_v4i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v4i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v4i8_clamp">; +def int_nvvm_sust_b_2d_array_v4i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v4i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v4i16_clamp">; +def int_nvvm_sust_b_2d_array_v4i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.array.v4i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v4i32_clamp">; + + +def int_nvvm_sust_b_3d_i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_i8_clamp">; +def int_nvvm_sust_b_3d_i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_i16_clamp">; +def int_nvvm_sust_b_3d_i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.3d.i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_i32_clamp">; +def int_nvvm_sust_b_3d_i64_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.3d.i64.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_i64_clamp">; +def int_nvvm_sust_b_3d_v2i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v2i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i8_clamp">; +def int_nvvm_sust_b_3d_v2i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v2i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i16_clamp">; +def int_nvvm_sust_b_3d_v2i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.3d.v2i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i32_clamp">; +def int_nvvm_sust_b_3d_v2i64_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.3d.v2i64.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i64_clamp">; +def int_nvvm_sust_b_3d_v4i8_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v4i8.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_v4i8_clamp">; +def int_nvvm_sust_b_3d_v4i16_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v4i16.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_v4i16_clamp">; +def int_nvvm_sust_b_3d_v4i32_clamp + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.3d.v4i32.clamp">, + GCCBuiltin<"__nvvm_sust_b_3d_v4i32_clamp">; + + +// .trap variant +def int_nvvm_sust_b_1d_i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.i8.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_i8_trap">; +def int_nvvm_sust_b_1d_i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.i16.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_i16_trap">; +def int_nvvm_sust_b_1d_i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.i32.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_i32_trap">; +def int_nvvm_sust_b_1d_i64_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.i64.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_i64_trap">; +def int_nvvm_sust_b_1d_v2i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v2i8.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i8_trap">; +def int_nvvm_sust_b_1d_v2i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v2i16.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i16_trap">; +def int_nvvm_sust_b_1d_v2i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.v2i32.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i32_trap">; +def int_nvvm_sust_b_1d_v2i64_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.v2i64.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i64_trap">; +def int_nvvm_sust_b_1d_v4i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v4i8.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_v4i8_trap">; +def int_nvvm_sust_b_1d_v4i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v4i16.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_v4i16_trap">; +def int_nvvm_sust_b_1d_v4i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.v4i32.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_v4i32_trap">; + + +def int_nvvm_sust_b_1d_array_i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.i8.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i8_trap">; +def int_nvvm_sust_b_1d_array_i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.i16.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i16_trap">; +def int_nvvm_sust_b_1d_array_i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.array.i32.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i32_trap">; +def int_nvvm_sust_b_1d_array_i64_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.array.i64.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i64_trap">; +def int_nvvm_sust_b_1d_array_v2i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i8.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i8_trap">; +def int_nvvm_sust_b_1d_array_v2i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i16.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i16_trap">; +def int_nvvm_sust_b_1d_array_v2i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i32.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i32_trap">; +def int_nvvm_sust_b_1d_array_v2i64_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i64.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i64_trap">; +def int_nvvm_sust_b_1d_array_v4i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v4i8.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v4i8_trap">; +def int_nvvm_sust_b_1d_array_v4i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v4i16.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v4i16_trap">; +def int_nvvm_sust_b_1d_array_v4i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.array.v4i32.trap">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v4i32_trap">; + + +def int_nvvm_sust_b_2d_i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.i8.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_i8_trap">; +def int_nvvm_sust_b_2d_i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.i16.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_i16_trap">; +def int_nvvm_sust_b_2d_i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.i32.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_i32_trap">; +def int_nvvm_sust_b_2d_i64_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.i64.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_i64_trap">; +def int_nvvm_sust_b_2d_v2i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v2i8.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i8_trap">; +def int_nvvm_sust_b_2d_v2i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v2i16.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i16_trap">; +def int_nvvm_sust_b_2d_v2i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.v2i32.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i32_trap">; +def int_nvvm_sust_b_2d_v2i64_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.v2i64.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i64_trap">; +def int_nvvm_sust_b_2d_v4i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v4i8.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_v4i8_trap">; +def int_nvvm_sust_b_2d_v4i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v4i16.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_v4i16_trap">; +def int_nvvm_sust_b_2d_v4i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.v4i32.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_v4i32_trap">; + + +def int_nvvm_sust_b_2d_array_i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.i8.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i8_trap">; +def int_nvvm_sust_b_2d_array_i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.i16.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i16_trap">; +def int_nvvm_sust_b_2d_array_i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.array.i32.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i32_trap">; +def int_nvvm_sust_b_2d_array_i64_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.array.i64.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i64_trap">; +def int_nvvm_sust_b_2d_array_v2i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i8.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i8_trap">; +def int_nvvm_sust_b_2d_array_v2i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i16.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i16_trap">; +def int_nvvm_sust_b_2d_array_v2i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i32.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i32_trap">; +def int_nvvm_sust_b_2d_array_v2i64_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i64.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i64_trap">; +def int_nvvm_sust_b_2d_array_v4i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v4i8.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v4i8_trap">; +def int_nvvm_sust_b_2d_array_v4i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v4i16.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v4i16_trap">; +def int_nvvm_sust_b_2d_array_v4i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.array.v4i32.trap">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v4i32_trap">; + + +def int_nvvm_sust_b_3d_i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.i8.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_i8_trap">; +def int_nvvm_sust_b_3d_i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.i16.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_i16_trap">; +def int_nvvm_sust_b_3d_i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.3d.i32.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_i32_trap">; +def int_nvvm_sust_b_3d_i64_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.3d.i64.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_i64_trap">; +def int_nvvm_sust_b_3d_v2i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v2i8.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i8_trap">; +def int_nvvm_sust_b_3d_v2i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v2i16.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i16_trap">; +def int_nvvm_sust_b_3d_v2i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.3d.v2i32.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i32_trap">; +def int_nvvm_sust_b_3d_v2i64_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.3d.v2i64.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i64_trap">; +def int_nvvm_sust_b_3d_v4i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v4i8.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_v4i8_trap">; +def int_nvvm_sust_b_3d_v4i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v4i16.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_v4i16_trap">; +def int_nvvm_sust_b_3d_v4i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.3d.v4i32.trap">, + GCCBuiltin<"__nvvm_sust_b_3d_v4i32_trap">; + + +// .zero variant +def int_nvvm_sust_b_1d_i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.i8.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_i8_zero">; +def int_nvvm_sust_b_1d_i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.i16.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_i16_zero">; +def int_nvvm_sust_b_1d_i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.i32.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_i32_zero">; +def int_nvvm_sust_b_1d_i64_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.i64.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_i64_zero">; +def int_nvvm_sust_b_1d_v2i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v2i8.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i8_zero">; +def int_nvvm_sust_b_1d_v2i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v2i16.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i16_zero">; +def int_nvvm_sust_b_1d_v2i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.v2i32.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i32_zero">; +def int_nvvm_sust_b_1d_v2i64_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.v2i64.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_v2i64_zero">; +def int_nvvm_sust_b_1d_v4i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v4i8.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_v4i8_zero">; +def int_nvvm_sust_b_1d_v4i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.v4i16.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_v4i16_zero">; +def int_nvvm_sust_b_1d_v4i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.v4i32.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_v4i32_zero">; + + +def int_nvvm_sust_b_1d_array_i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.i8.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i8_zero">; +def int_nvvm_sust_b_1d_array_i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.i16.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i16_zero">; +def int_nvvm_sust_b_1d_array_i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.array.i32.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i32_zero">; +def int_nvvm_sust_b_1d_array_i64_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.array.i64.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_i64_zero">; +def int_nvvm_sust_b_1d_array_v2i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i8.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i8_zero">; +def int_nvvm_sust_b_1d_array_v2i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i16.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i16_zero">; +def int_nvvm_sust_b_1d_array_v2i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i32.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i32_zero">; +def int_nvvm_sust_b_1d_array_v2i64_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.1d.array.v2i64.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v2i64_zero">; +def int_nvvm_sust_b_1d_array_v4i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v4i8.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v4i8_zero">; +def int_nvvm_sust_b_1d_array_v4i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.1d.array.v4i16.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v4i16_zero">; +def int_nvvm_sust_b_1d_array_v4i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.1d.array.v4i32.zero">, + GCCBuiltin<"__nvvm_sust_b_1d_array_v4i32_zero">; + + +def int_nvvm_sust_b_2d_i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.i8.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_i8_zero">; +def int_nvvm_sust_b_2d_i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.i16.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_i16_zero">; +def int_nvvm_sust_b_2d_i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.i32.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_i32_zero">; +def int_nvvm_sust_b_2d_i64_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.i64.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_i64_zero">; +def int_nvvm_sust_b_2d_v2i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v2i8.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i8_zero">; +def int_nvvm_sust_b_2d_v2i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v2i16.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i16_zero">; +def int_nvvm_sust_b_2d_v2i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.v2i32.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i32_zero">; +def int_nvvm_sust_b_2d_v2i64_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.v2i64.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_v2i64_zero">; +def int_nvvm_sust_b_2d_v4i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v4i8.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_v4i8_zero">; +def int_nvvm_sust_b_2d_v4i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.v4i16.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_v4i16_zero">; +def int_nvvm_sust_b_2d_v4i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.v4i32.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_v4i32_zero">; + + +def int_nvvm_sust_b_2d_array_i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.i8.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i8_zero">; +def int_nvvm_sust_b_2d_array_i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.i16.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i16_zero">; +def int_nvvm_sust_b_2d_array_i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.array.i32.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i32_zero">; +def int_nvvm_sust_b_2d_array_i64_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.array.i64.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_i64_zero">; +def int_nvvm_sust_b_2d_array_v2i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i8.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i8_zero">; +def int_nvvm_sust_b_2d_array_v2i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i16.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i16_zero">; +def int_nvvm_sust_b_2d_array_v2i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i32.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i32_zero">; +def int_nvvm_sust_b_2d_array_v2i64_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.2d.array.v2i64.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v2i64_zero">; +def int_nvvm_sust_b_2d_array_v4i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v4i8.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v4i8_zero">; +def int_nvvm_sust_b_2d_array_v4i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.2d.array.v4i16.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v4i16_zero">; +def int_nvvm_sust_b_2d_array_v4i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.2d.array.v4i32.zero">, + GCCBuiltin<"__nvvm_sust_b_2d_array_v4i32_zero">; + + +def int_nvvm_sust_b_3d_i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.i8.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_i8_zero">; +def int_nvvm_sust_b_3d_i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.i16.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_i16_zero">; +def int_nvvm_sust_b_3d_i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.3d.i32.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_i32_zero">; +def int_nvvm_sust_b_3d_i64_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.3d.i64.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_i64_zero">; +def int_nvvm_sust_b_3d_v2i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v2i8.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i8_zero">; +def int_nvvm_sust_b_3d_v2i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v2i16.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i16_zero">; +def int_nvvm_sust_b_3d_v2i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.3d.v2i32.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i32_zero">; +def int_nvvm_sust_b_3d_v2i64_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i64_ty, llvm_i64_ty], [], + "llvm.nvvm.sust.b.3d.v2i64.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_v2i64_zero">; +def int_nvvm_sust_b_3d_v4i8_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v4i8.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_v4i8_zero">; +def int_nvvm_sust_b_3d_v4i16_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.b.3d.v4i16.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_v4i16_zero">; +def int_nvvm_sust_b_3d_v4i32_zero + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.b.3d.v4i32.zero">, + GCCBuiltin<"__nvvm_sust_b_3d_v4i32_zero">; + + + +// Formatted + +def int_nvvm_sust_p_1d_i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.i8.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_i8_trap">; +def int_nvvm_sust_p_1d_i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.i16.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_i16_trap">; +def int_nvvm_sust_p_1d_i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.1d.i32.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_i32_trap">; +def int_nvvm_sust_p_1d_v2i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.v2i8.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_v2i8_trap">; +def int_nvvm_sust_p_1d_v2i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.v2i16.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_v2i16_trap">; +def int_nvvm_sust_p_1d_v2i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.1d.v2i32.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_v2i32_trap">; +def int_nvvm_sust_p_1d_v4i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.v4i8.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_v4i8_trap">; +def int_nvvm_sust_p_1d_v4i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.v4i16.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_v4i16_trap">; +def int_nvvm_sust_p_1d_v4i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.1d.v4i32.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_v4i32_trap">; + + +def int_nvvm_sust_p_1d_array_i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.array.i8.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_array_i8_trap">; +def int_nvvm_sust_p_1d_array_i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.array.i16.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_array_i16_trap">; +def int_nvvm_sust_p_1d_array_i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.1d.array.i32.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_array_i32_trap">; +def int_nvvm_sust_p_1d_array_v2i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.array.v2i8.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_array_v2i8_trap">; +def int_nvvm_sust_p_1d_array_v2i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.array.v2i16.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_array_v2i16_trap">; +def int_nvvm_sust_p_1d_array_v2i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.1d.array.v2i32.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_array_v2i32_trap">; +def int_nvvm_sust_p_1d_array_v4i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.array.v4i8.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_array_v4i8_trap">; +def int_nvvm_sust_p_1d_array_v4i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.1d.array.v4i16.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_array_v4i16_trap">; +def int_nvvm_sust_p_1d_array_v4i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.1d.array.v4i32.trap">, + GCCBuiltin<"__nvvm_sust_p_1d_array_v4i32_trap">; + + +def int_nvvm_sust_p_2d_i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.i8.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_i8_trap">; +def int_nvvm_sust_p_2d_i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.i16.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_i16_trap">; +def int_nvvm_sust_p_2d_i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.2d.i32.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_i32_trap">; +def int_nvvm_sust_p_2d_v2i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.v2i8.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_v2i8_trap">; +def int_nvvm_sust_p_2d_v2i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.v2i16.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_v2i16_trap">; +def int_nvvm_sust_p_2d_v2i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.2d.v2i32.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_v2i32_trap">; +def int_nvvm_sust_p_2d_v4i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.v4i8.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_v4i8_trap">; +def int_nvvm_sust_p_2d_v4i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.v4i16.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_v4i16_trap">; +def int_nvvm_sust_p_2d_v4i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.2d.v4i32.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_v4i32_trap">; + + +def int_nvvm_sust_p_2d_array_i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.array.i8.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_array_i8_trap">; +def int_nvvm_sust_p_2d_array_i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.array.i16.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_array_i16_trap">; +def int_nvvm_sust_p_2d_array_i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.2d.array.i32.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_array_i32_trap">; +def int_nvvm_sust_p_2d_array_v2i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.array.v2i8.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_array_v2i8_trap">; +def int_nvvm_sust_p_2d_array_v2i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.array.v2i16.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_array_v2i16_trap">; +def int_nvvm_sust_p_2d_array_v2i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.2d.array.v2i32.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_array_v2i32_trap">; +def int_nvvm_sust_p_2d_array_v4i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.array.v4i8.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_array_v4i8_trap">; +def int_nvvm_sust_p_2d_array_v4i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.2d.array.v4i16.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_array_v4i16_trap">; +def int_nvvm_sust_p_2d_array_v4i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.2d.array.v4i32.trap">, + GCCBuiltin<"__nvvm_sust_p_2d_array_v4i32_trap">; + + +def int_nvvm_sust_p_3d_i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.3d.i8.trap">, + GCCBuiltin<"__nvvm_sust_p_3d_i8_trap">; +def int_nvvm_sust_p_3d_i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.3d.i16.trap">, + GCCBuiltin<"__nvvm_sust_p_3d_i16_trap">; +def int_nvvm_sust_p_3d_i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.3d.i32.trap">, + GCCBuiltin<"__nvvm_sust_p_3d_i32_trap">; +def int_nvvm_sust_p_3d_v2i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.3d.v2i8.trap">, + GCCBuiltin<"__nvvm_sust_p_3d_v2i8_trap">; +def int_nvvm_sust_p_3d_v2i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.3d.v2i16.trap">, + GCCBuiltin<"__nvvm_sust_p_3d_v2i16_trap">; +def int_nvvm_sust_p_3d_v2i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.3d.v2i32.trap">, + GCCBuiltin<"__nvvm_sust_p_3d_v2i32_trap">; +def int_nvvm_sust_p_3d_v4i8_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.3d.v4i8.trap">, + GCCBuiltin<"__nvvm_sust_p_3d_v4i8_trap">; +def int_nvvm_sust_p_3d_v4i16_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], [], + "llvm.nvvm.sust.p.3d.v4i16.trap">, + GCCBuiltin<"__nvvm_sust_p_3d_v4i16_trap">; +def int_nvvm_sust_p_3d_v4i32_trap + : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, + llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [], + "llvm.nvvm.sust.p.3d.v4i32.trap">, + GCCBuiltin<"__nvvm_sust_p_3d_v4i32_trap">; + + +def int_nvvm_rotate_b32 + : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem], "llvm.nvvm.rotate.b32">, + GCCBuiltin<"__nvvm_rotate_b32">; + +def int_nvvm_rotate_b64 + :Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], + [IntrNoMem], "llvm.nvvm.rotate.b64">, + GCCBuiltin<"__nvvm_rotate_b64">; + +def int_nvvm_rotate_right_b64 + : Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], + [IntrNoMem], "llvm.nvvm.rotate.right.b64">, + GCCBuiltin<"__nvvm_rotate_right_b64">; + +def int_nvvm_swap_lo_hi_b64 + : Intrinsic<[llvm_i64_ty], [llvm_i64_ty], + [IntrNoMem], "llvm.nvvm.swap.lo.hi.b64">, + GCCBuiltin<"__nvvm_swap_lo_hi_b64">; + // Old PTX back-end intrinsics retained here for backwards-compatibility diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td index ecb5668d8e95..ba69eaae089f 100644 --- a/include/llvm/IR/IntrinsicsR600.td +++ b/include/llvm/IR/IntrinsicsR600.td @@ -33,4 +33,40 @@ defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz < "__builtin_r600_read_tgid">; defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz < "__builtin_r600_read_tidig">; + } // End TargetPrefix = "r600" + +let TargetPrefix = "AMDGPU" in { +def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">, + // 1st parameter: Numerator + // 2nd parameter: Denominator + // 3rd parameter: Constant to select select between first and + // second. (0 = first, 1 = second). + Intrinsic<[llvm_anyfloat_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], + [IntrNoMem]>; + +def int_AMDGPU_div_fmas : GCCBuiltin<"__builtin_amdgpu_div_fmas">, + Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_AMDGPU_div_fixup : GCCBuiltin<"__builtin_amdgpu_div_fixup">, + Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_AMDGPU_trig_preop : GCCBuiltin<"__builtin_amdgpu_trig_preop">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem]>; + +def int_AMDGPU_rcp : GCCBuiltin<"__builtin_amdgpu_rcp">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + +def int_AMDGPU_rsq : GCCBuiltin<"__builtin_amdgpu_rsq">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + +def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + +} // End TargetPrefix = "AMDGPU" diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 46c32ae2fd00..5de950813cd4 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -18,6 +18,21 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //===----------------------------------------------------------------------===// +// Read Time Stamp Counter. +let TargetPrefix = "x86" in { + def int_x86_rdtsc : GCCBuiltin<"__builtin_ia32_rdtsc">, + Intrinsic<[llvm_i64_ty], [], []>; + def int_x86_rdtscp : GCCBuiltin<"__builtin_ia32_rdtscp">, + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty], [IntrReadWriteArgMem]>; +} + +// Read Performance-Monitoring Counter. +let TargetPrefix = "x86" in { + def int_x86_rdpmc : GCCBuiltin<"__builtin_ia32_rdpmc">, + Intrinsic<[llvm_i64_ty], [llvm_i32_ty], []>; +} + +//===----------------------------------------------------------------------===// // 3DNow! let TargetPrefix = "x86" in { @@ -536,6 +551,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[], [], []>; def int_x86_sse2_mfence : GCCBuiltin<"__builtin_ia32_mfence">, Intrinsic<[], [], []>; + def int_x86_sse2_pause : GCCBuiltin<"__builtin_ia32_pause">, + Intrinsic<[], [], []>; } //===----------------------------------------------------------------------===// @@ -656,6 +673,15 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_ssse3_pshuf_b_128 : GCCBuiltin<"__builtin_ia32_pshufb128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pshuf_d : GCCBuiltin<"__builtin_ia32_pshufd">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse2_pshufl_w : GCCBuiltin<"__builtin_ia32_pshuflw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_sse2_pshufh_w : GCCBuiltin<"__builtin_ia32_pshufhw">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse_pshuf_w : GCCBuiltin<"__builtin_ia32_pshufw">, Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem]>; @@ -1118,6 +1144,27 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_vperm2f128_si256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt_d_512: + GCCBuiltin<"__builtin_ia32_vpermt2vard512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt_q_512: + GCCBuiltin<"__builtin_ia32_vpermt2varq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt_ps_512: + GCCBuiltin<"__builtin_ia32_vpermt2varps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, + llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt_pd_512: + GCCBuiltin<"__builtin_ia32_vpermt2varpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8i64_ty, + llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + } // Vector blend @@ -1246,6 +1293,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_ptestnzc_256 : GCCBuiltin<"__builtin_ia32_ptestnzc256">, Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ptestm_d_512 : GCCBuiltin<"__builtin_ia32_ptestmd512">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ptestm_q_512 : GCCBuiltin<"__builtin_ia32_ptestmq512">, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; } // Vector extract sign mask @@ -1266,15 +1319,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector load with broadcast let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_vbroadcast_ss : - GCCBuiltin<"__builtin_ia32_vbroadcastss">, - Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; - def int_x86_avx_vbroadcast_sd_256 : - GCCBuiltin<"__builtin_ia32_vbroadcastsd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; - def int_x86_avx_vbroadcast_ss_256 : - GCCBuiltin<"__builtin_ia32_vbroadcastss256">, - Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_x86_avx_vbroadcastf128_pd_256 : GCCBuiltin<"__builtin_ia32_vbroadcastf128_pd256">, Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; @@ -1313,6 +1357,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_maskload_ps_256 : GCCBuiltin<"__builtin_ia32_maskloadps256">, Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_loadu_ps_512 : GCCBuiltin<"__builtin_ia32_loadups512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadArgMem]>; + def int_x86_avx512_mask_loadu_pd_512 : GCCBuiltin<"__builtin_ia32_loadupd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadArgMem]>; } // Conditional store ops @@ -1331,6 +1381,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_maskstoreps256">, Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty, llvm_v8f32_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_storeu_ps_512 : + GCCBuiltin<"__builtin_ia32_storeups512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_storeu_pd_512 : + GCCBuiltin<"__builtin_ia32_storeupd512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; } //===----------------------------------------------------------------------===// @@ -1386,6 +1444,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw256">, Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem, Commutative]>; + def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Vector min, max @@ -1426,6 +1490,30 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pmins_d : GCCBuiltin<"__builtin_ia32_pminsd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem, Commutative]>; + def int_x86_avx512_mask_pmaxu_d_512 : GCCBuiltin<"__builtin_ia32_pmaxud512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_d_512 : GCCBuiltin<"__builtin_ia32_pmaxsd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_q_512 : GCCBuiltin<"__builtin_ia32_pmaxuq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_q_512 : GCCBuiltin<"__builtin_ia32_pmaxsq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_d_512 : GCCBuiltin<"__builtin_ia32_pminud512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_d_512 : GCCBuiltin<"__builtin_ia32_pminsd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_q_512 : GCCBuiltin<"__builtin_ia32_pminuq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_q_512 : GCCBuiltin<"__builtin_ia32_pminsq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Integer shift ops. @@ -1518,6 +1606,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; def int_x86_avx2_pabs_d : GCCBuiltin<"__builtin_ia32_pabsd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pabs_d_512 : GCCBuiltin<"__builtin_ia32_pabsd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pabs_q_512 : GCCBuiltin<"__builtin_ia32_pabsq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; } // Horizontal arithmetic ops @@ -1658,6 +1752,18 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pbroadcastq_256 : GCCBuiltin<"__builtin_ia32_pbroadcastq256">, Intrinsic<[llvm_v4i64_ty], [llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pbroadcast_d_gpr_512 : + GCCBuiltin<"__builtin_ia32_pbroadcastd512_gpr_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pbroadcast_q_gpr_512 : + GCCBuiltin<"__builtin_ia32_pbroadcastq512_gpr_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pbroadcast_q_mem_512 : + GCCBuiltin<"__builtin_ia32_pbroadcastq512_mem_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; } // Vector permutation @@ -1697,6 +1803,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_maskload_q_256 : GCCBuiltin<"__builtin_ia32_maskloadq256">, Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_loadu_d_512 : GCCBuiltin<"__builtin_ia32_loaddqusi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrReadArgMem]>; + def int_x86_avx512_mask_loadu_q_512 : GCCBuiltin<"__builtin_ia32_loaddqudi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadArgMem]>; } // Conditional store ops @@ -1715,6 +1827,14 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_maskstoreq256">, Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_storeu_d_512 : + GCCBuiltin<"__builtin_ia32_storedqusi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_storeu_q_512 : + GCCBuiltin<"__builtin_ia32_storedqudi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; } // Variable bit shift ops @@ -1834,6 +1954,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_i32_ty], [IntrNoMem, Commutative]>; def int_x86_avx2_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa256">, Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, + Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } //===----------------------------------------------------------------------===// @@ -2592,6 +2714,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_vcvtps2ph_256 : GCCBuiltin<"__builtin_ia32_vcvtps2ph256">, Intrinsic<[llvm_v8i16_ty], [llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_vcvtph2ps_512 : GCCBuiltin<"__builtin_ia32_vcvtph2ps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i16_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_vcvtps2ph_512 : GCCBuiltin<"__builtin_ia32_vcvtps2ph512_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16f32_ty, llvm_i32_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; } //===----------------------------------------------------------------------===// @@ -2641,37 +2769,30 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Mask instructions // 16-bit mask - def int_x86_kadd_v16i1 : GCCBuiltin<"__builtin_ia32_kaddw">, - Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], - [IntrNoMem]>; - def int_x86_kand_v16i1 : GCCBuiltin<"__builtin_ia32_kandw">, - Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + def int_x86_avx512_kand_w : GCCBuiltin<"__builtin_ia32_kandhi">, + Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_kandn_v16i1 : GCCBuiltin<"__builtin_ia32_kandnw">, - Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + def int_x86_avx512_kandn_w : GCCBuiltin<"__builtin_ia32_kandnhi">, + Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_knot_v16i1 : GCCBuiltin<"__builtin_ia32_knotw">, - Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty], [IntrNoMem]>; - def int_x86_kor_v16i1 : GCCBuiltin<"__builtin_ia32_korw">, - Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + def int_x86_avx512_knot_w : GCCBuiltin<"__builtin_ia32_knothi">, + Intrinsic<[llvm_i16_ty], [llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_kor_w : GCCBuiltin<"__builtin_ia32_korhi">, + Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_kxor_v16i1 : GCCBuiltin<"__builtin_ia32_kxorw">, - Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + def int_x86_avx512_kxor_w : GCCBuiltin<"__builtin_ia32_kxorhi">, + Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_kxnor_v16i1 : GCCBuiltin<"__builtin_ia32_kxnorw">, - Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + def int_x86_avx512_kxnor_w : GCCBuiltin<"__builtin_ia32_kxnorhi">, + Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_mask2int_v16i1 : GCCBuiltin<"__builtin_ia32_mask2intw">, - Intrinsic<[llvm_i32_ty], [llvm_v16i1_ty], [IntrNoMem]>; - def int_x86_int2mask_v16i1 : GCCBuiltin<"__builtin_ia32_int2maskw">, - Intrinsic<[llvm_v16i1_ty], [llvm_i32_ty], [IntrNoMem]>; - def int_x86_kunpck_v16i1 : GCCBuiltin<"__builtin_ia32_kunpckbw">, - Intrinsic<[llvm_v16i1_ty], [llvm_v8i1_ty, llvm_v8i1_ty], + def int_x86_avx512_kunpck_bw : GCCBuiltin<"__builtin_ia32_kunpckhi">, + Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_kortestz : GCCBuiltin<"__builtin_ia32_kortestz">, + def int_x86_avx512_kortestz_w : GCCBuiltin<"__builtin_ia32_kortestzhi">, Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_kortestc : GCCBuiltin<"__builtin_ia32_kortestc">, + def int_x86_avx512_kortestc_w : GCCBuiltin<"__builtin_ia32_kortestchi">, Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty], [IntrNoMem]>; } @@ -2707,20 +2828,55 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi642sd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i64_ty], [IntrNoMem]>; - - def int_x86_avx512_vcvtph2ps_512 : GCCBuiltin<"__builtin_ia32_vcvtph2ps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16i16_ty], [IntrNoMem]>; - def int_x86_avx512_vcvtps2ph_512 : GCCBuiltin<"__builtin_ia32_vcvtps2ph512">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16f32_ty, llvm_i32_ty], - [IntrNoMem]>; } // Vector convert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_cvt_ps2dq_512 : GCCBuiltin<"__builtin_ia32_cvtps2dq512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty], [IntrNoMem]>; - def int_x86_avx512_cvtdq2_ps_512 : GCCBuiltin<"__builtin_ia32_cvtdq2ps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvttps2dq_512: GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvttps2udq_512: GCCBuiltin<"__builtin_ia32_cvttps2udq512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvttpd2dq_512: GCCBuiltin<"__builtin_ia32_cvttpd2dq512_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvttpd2udq_512: GCCBuiltin<"__builtin_ia32_cvttpd2udq512_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_ps_512: GCCBuiltin<"__builtin_ia32_rndscaleps_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_pd_512: GCCBuiltin<"__builtin_ia32_rndscalepd_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvtps2dq_512: GCCBuiltin<"__builtin_ia32_cvtps2dq512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvtpd2dq_512: GCCBuiltin<"__builtin_ia32_cvtpd2dq512_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvtps2udq_512: GCCBuiltin<"__builtin_ia32_cvtps2udq512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvtpd2udq_512: GCCBuiltin<"__builtin_ia32_cvtpd2udq512_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvtdq2ps_512 : GCCBuiltin<"__builtin_ia32_cvtdq2ps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvtdq2pd_512 : GCCBuiltin<"__builtin_ia32_cvtdq2pd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8i32_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvtudq2ps_512 : GCCBuiltin<"__builtin_ia32_cvtudq2ps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvtudq2pd_512 : GCCBuiltin<"__builtin_ia32_cvtudq2pd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8i32_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cvtpd2ps_512 : GCCBuiltin<"__builtin_ia32_cvtpd2ps512_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f64_ty, llvm_v8f32_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; } // Vector load with broadcast @@ -2773,44 +2929,18 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, - llvm_v16f32_ty], [IntrNoMem]>; - def int_x86_avx512_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, - llvm_v8f64_ty], [IntrNoMem]>; - def int_x86_avx512_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, - llvm_v16f32_ty], [IntrNoMem]>; - def int_x86_avx512_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, - llvm_v8f64_ty], [IntrNoMem]>; - - def int_x86_avx512_pmaxu_d : GCCBuiltin<"__builtin_ia32_pmaxud512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v16i32_ty], [IntrNoMem]>; - def int_x86_avx512_pmaxu_q : GCCBuiltin<"__builtin_ia32_pmaxuq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v8i64_ty], [IntrNoMem]>; - def int_x86_avx512_pmaxs_d : GCCBuiltin<"__builtin_ia32_pmaxsd512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v16i32_ty], [IntrNoMem]>; - def int_x86_avx512_pmaxs_q : GCCBuiltin<"__builtin_ia32_pmaxsq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v8i64_ty], [IntrNoMem]>; - - def int_x86_avx512_pminu_d : GCCBuiltin<"__builtin_ia32_pminud512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v16i32_ty], [IntrNoMem]>; - def int_x86_avx512_pminu_q : GCCBuiltin<"__builtin_ia32_pminuq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v8i64_ty], [IntrNoMem]>; - def int_x86_avx512_pmins_d : GCCBuiltin<"__builtin_ia32_pminsd512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v16i32_ty], [IntrNoMem]>; - def int_x86_avx512_pmins_q : GCCBuiltin<"__builtin_ia32_pminsq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, @@ -2825,66 +2955,67 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_avx512_rndscale_ps_512 : GCCBuiltin<"__builtin_ia32_rndscaleps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rndscale_pd_512 : GCCBuiltin<"__builtin_ia32_rndscalepd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], [IntrNoMem]>; def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], [IntrNoMem]>; - def int_x86_avx512_rcp14_ps_512 : GCCBuiltin<"__builtin_ia32_rcp14ps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], - [IntrNoMem]>; - def int_x86_avx512_rcp14_pd_512 : GCCBuiltin<"__builtin_ia32_rcp14pd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], - [IntrNoMem]>; - def int_x86_avx512_rcp14_ss : GCCBuiltin<"__builtin_ia32_rcp14ss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_avx512_rcp14_sd : GCCBuiltin<"__builtin_ia32_rcp14sd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_avx512_rsqrt14_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt14ps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], - [IntrNoMem]>; - def int_x86_avx512_rsqrt14_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt14pd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], - [IntrNoMem]>; - def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_avx512_rsqrt14_sd : GCCBuiltin<"__builtin_ia32_rsqrt14sd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], - [IntrNoMem]>; - - def int_x86_avx512_rcp28_ps_512 : GCCBuiltin<"__builtin_ia32_rcp28ps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_rsqrt14_sd : GCCBuiltin<"__builtin_ia32_rsqrt14sd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_rsqrt14_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt14pd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_rsqrt14_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt14ps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_rcp14_ss : GCCBuiltin<"__builtin_ia32_rcp14ss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_rcp14_sd : GCCBuiltin<"__builtin_ia32_rcp14sd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_rcp14_pd_512 : GCCBuiltin<"__builtin_ia32_rcp14pd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_rcp14_ps_512 : GCCBuiltin<"__builtin_ia32_rcp14ps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + + def int_x86_avx512_rcp28_ps : GCCBuiltin<"__builtin_ia32_rcp28ps_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_rcp28_pd : GCCBuiltin<"__builtin_ia32_rcp28pd_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rcp28_pd_512 : GCCBuiltin<"__builtin_ia32_rcp28pd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], + def int_x86_avx512_rcp28_sd : GCCBuiltin<"__builtin_ia32_rcp28sd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], + def int_x86_avx512_rsqrt28_ps : GCCBuiltin<"__builtin_ia32_rsqrt28ps_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rcp28_sd : GCCBuiltin<"__builtin_ia32_rcp28sd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + def int_x86_avx512_rsqrt28_pd : GCCBuiltin<"__builtin_ia32_rsqrt28pd_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rsqrt28_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt28ps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], + def int_x86_avx512_rsqrt28_ss : GCCBuiltin<"__builtin_ia32_rsqrt28ss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_rsqrt28_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt28pd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], - [IntrNoMem]>; - def int_x86_avx512_rsqrt28_ss : GCCBuiltin<"__builtin_ia32_rsqrt28ss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_avx512_rsqrt28_sd : GCCBuiltin<"__builtin_ia32_rsqrt28sd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], + def int_x86_avx512_rsqrt28_sd : GCCBuiltin<"__builtin_ia32_rsqrt28sd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; } @@ -2906,201 +3037,174 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Gather and Scatter ops let TargetPrefix = "x86" in { - def int_x86_avx512_gather_dpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i8_ty, - llvm_v8i32_ty, llvm_ptr_ty, llvm_i32_ty], + def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gathersiv8df">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, + llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrReadArgMem]>; - def int_x86_avx512_gather_dps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i16_ty, - llvm_v16i32_ty, llvm_ptr_ty, llvm_i32_ty], + def int_x86_avx512_gather_dps_512 : GCCBuiltin<"__builtin_ia32_gathersiv16sf">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_ptr_ty, + llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], [IntrReadArgMem]>; - def int_x86_avx512_gather_qpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i8_ty, - llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + def int_x86_avx512_gather_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherdiv8df">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_ptr_ty, + llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], [IntrReadArgMem]>; - def int_x86_avx512_gather_qps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqps512">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i8_ty, - llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], + def int_x86_avx512_gather_qps_512 : GCCBuiltin<"__builtin_ia32_gatherdiv16sf">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, + llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], [IntrReadArgMem]>; - def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gatherdpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8i32_ty, llvm_ptr_ty, - llvm_i32_ty], - [IntrReadArgMem]>; - def int_x86_avx512_gather_dps_512 : GCCBuiltin<"__builtin_ia32_gatherdps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, llvm_ptr_ty, - llvm_i32_ty], - [IntrReadArgMem]>; - def int_x86_avx512_gather_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherqpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty], - [IntrReadArgMem]>; - def int_x86_avx512_gather_qps_512 : GCCBuiltin<"__builtin_ia32_gatherqps512">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty], - [IntrReadArgMem]>; - - def int_x86_avx512_gather_dpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i8_ty, - llvm_v8i32_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; - def int_x86_avx512_gather_dpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherdpi512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_i16_ty, - llvm_v16i32_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; - def int_x86_avx512_gather_qpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_i8_ty, - llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; - def int_x86_avx512_gather_qpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_gatherqpi512">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_i8_ty, - llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrReadArgMem]>; - def int_x86_avx512_gather_dpq_512 : GCCBuiltin<"__builtin_ia32_gatherdpq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty, llvm_ptr_ty, - llvm_i32_ty], + def int_x86_avx512_gather_dpq_512 : GCCBuiltin<"__builtin_ia32_gathersiv8di">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, + llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrReadArgMem]>; - def int_x86_avx512_gather_dpi_512 : GCCBuiltin<"__builtin_ia32_gatherdpi512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, - llvm_i32_ty], + def int_x86_avx512_gather_dpi_512 : GCCBuiltin<"__builtin_ia32_gathersiv16si">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_ptr_ty, + llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], [IntrReadArgMem]>; - def int_x86_avx512_gather_qpq_512 : GCCBuiltin<"__builtin_ia32_gatherqpq512">, + def int_x86_avx512_gather_qpq_512 : GCCBuiltin<"__builtin_ia32_gatherdiv8di">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty], + llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], [IntrReadArgMem]>; - def int_x86_avx512_gather_qpi_512 : GCCBuiltin<"__builtin_ia32_gatherqpi512">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i64_ty, llvm_ptr_ty, - llvm_i32_ty], + def int_x86_avx512_gather_qpi_512 : GCCBuiltin<"__builtin_ia32_gatherdiv16si">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, + llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], [IntrReadArgMem]>; + // scatter - def int_x86_avx512_scatter_dpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpd512">, + def int_x86_avx512_scatter_dpd_512 : GCCBuiltin<"__builtin_ia32_scattersiv8df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8f64_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_dps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdps512">, + def int_x86_avx512_scatter_dps_512 : GCCBuiltin<"__builtin_ia32_scattersiv16sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, llvm_v16i32_ty, llvm_v16f32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_qpd_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpd512">, + def int_x86_avx512_scatter_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterdiv8df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8f64_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_qps_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqps512">, + def int_x86_avx512_scatter_qps_512 : GCCBuiltin<"__builtin_ia32_scatterdiv16sf">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8f32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_dpd_512 : GCCBuiltin<"__builtin_ia32_scatterdpd512">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f64_ty, - llvm_i32_ty], - [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_dps_512 : GCCBuiltin<"__builtin_ia32_scatterdps512">, - Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, llvm_v16f32_ty, - llvm_i32_ty], - [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterqpd512">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8f64_ty, - llvm_i32_ty], - [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_qps_512 : GCCBuiltin<"__builtin_ia32_scatterqps512">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8f32_ty, - llvm_i32_ty], - [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_dpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpq512">, - Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, - llvm_v8i64_ty, llvm_i32_ty], + def int_x86_avx512_scatter_dpq_512 : GCCBuiltin<"__builtin_ia32_scattersiv8di">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, + llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_dpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterdpi512">, + def int_x86_avx512_scatter_dpi_512 : GCCBuiltin<"__builtin_ia32_scattersiv16si">, Intrinsic<[], [llvm_ptr_ty, llvm_i16_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_qpq_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpq512">, - Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, - llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], + def int_x86_avx512_scatter_qpq_512 : GCCBuiltin<"__builtin_ia32_scatterdiv8di">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty,llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_qpi_mask_512 : GCCBuiltin<"__builtin_ia32_mask_scatterqpi512">, - Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, - llvm_v8i64_ty, llvm_v8i32_ty, llvm_i32_ty], + def int_x86_avx512_scatter_qpi_512 : GCCBuiltin<"__builtin_ia32_scatterdiv16si">, + Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_v8i32_ty, + llvm_i32_ty], [IntrReadWriteArgMem]>; - def int_x86_avx512_scatter_dpq_512 : GCCBuiltin<"__builtin_ia32_scatterdpq512">, - Intrinsic<[], [llvm_ptr_ty, - llvm_v8i32_ty, llvm_v8i64_ty, llvm_i32_ty], - []>; - def int_x86_avx512_scatter_dpi_512 : GCCBuiltin<"__builtin_ia32_scatterdpi512">, - Intrinsic<[], [llvm_ptr_ty, - llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], - []>; - def int_x86_avx512_scatter_qpq_512 : GCCBuiltin<"__builtin_ia32_scatterqpq512">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i64_ty, - llvm_i32_ty], - []>; - def int_x86_avx512_scatter_qpi_512 : GCCBuiltin<"__builtin_ia32_scatterqpi512">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, llvm_v8i32_ty, - llvm_i32_ty], - []>; + // gather prefetch + def int_x86_avx512_gatherpf_dpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfdpd">, + Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_gatherpf_dps_512 : GCCBuiltin<"__builtin_ia32_gatherpfdps">, + Intrinsic<[], [llvm_i16_ty, llvm_v16i32_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_gatherpf_qpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfqpd">, + Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_gatherpf_qps_512 : GCCBuiltin<"__builtin_ia32_gatherpfqps">, + Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; + + // scatter prefetch + def int_x86_avx512_scatterpf_dpd_512 : GCCBuiltin<"__builtin_ia32_scatterpfdpd">, + Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_scatterpf_dps_512 : GCCBuiltin<"__builtin_ia32_scatterpfdps">, + Intrinsic<[], [llvm_i16_ty, llvm_v16i32_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_scatterpf_qpd_512 : GCCBuiltin<"__builtin_ia32_scatterpfqpd">, + Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_scatterpf_qps_512 : GCCBuiltin<"__builtin_ia32_scatterpfqps">, + Intrinsic<[], [llvm_i8_ty, llvm_v8i64_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], [IntrReadWriteArgMem]>; } // AVX-512 conflict detection let TargetPrefix = "x86" in { - def int_x86_avx512_conflict_d_512 : GCCBuiltin<"__builtin_ia32_conflictd512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty], - []>; - def int_x86_avx512_conflict_d_mask_512 : - GCCBuiltin<"__builtin_ia32_mask_conflictd512">, + def int_x86_avx512_mask_conflict_d_512 : + GCCBuiltin<"__builtin_ia32_vpconflictsi_512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v16i1_ty, llvm_v16i32_ty], - []>; - def int_x86_avx512_conflict_d_maskz_512: - GCCBuiltin<"__builtin_ia32_maskz_conflictd512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i1_ty, llvm_v16i32_ty], + llvm_v16i32_ty, llvm_i16_ty], []>; - - def int_x86_avx512_conflict_q_512 : GCCBuiltin<"__builtin_ia32_conflictq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty], - []>; - def int_x86_avx512_conflict_q_mask_512 : - GCCBuiltin<"__builtin_ia32_mask_conflictq512">, + def int_x86_avx512_mask_conflict_q_512 : + GCCBuiltin<"__builtin_ia32_vpconflictdi_512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v8i1_ty, llvm_v8i64_ty], + llvm_v8i64_ty, llvm_i8_ty], + []>; + def int_x86_avx512_mask_lzcnt_d_512 : + GCCBuiltin<"__builtin_ia32_vplzcntd_512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], []>; - def int_x86_avx512_conflict_q_maskz_512: - GCCBuiltin<"__builtin_ia32_maskz_conflictq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i1_ty, llvm_v8i64_ty], + def int_x86_avx512_mask_lzcnt_q_512 : + GCCBuiltin<"__builtin_ia32_vplzcntq_512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], []>; } // Vector blend let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_mskblend_ps_512 : GCCBuiltin<"__builtin_ia32_mskblendps512">, + def int_x86_avx512_mask_blend_ps_512 : GCCBuiltin<"__builtin_ia32_blendmps_512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16i1_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mskblend_pd_512 : GCCBuiltin<"__builtin_ia32_mskblendpd512">, + def int_x86_avx512_mask_blend_pd_512 : GCCBuiltin<"__builtin_ia32_blendmpd_512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8i1_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mskblend_d_512 : GCCBuiltin<"__builtin_ia32_mskblendd512">, + def int_x86_avx512_mask_blend_d_512 : GCCBuiltin<"__builtin_ia32_blendmd_512_mask">, Intrinsic<[llvm_v16i32_ty], - [llvm_v16i1_ty, llvm_v16i32_ty, llvm_v16i32_ty], + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mskblend_q_512 : GCCBuiltin<"__builtin_ia32_mskblendq512">, + def int_x86_avx512_mask_blend_q_512 : GCCBuiltin<"__builtin_ia32_blendmq_512_mask">, Intrinsic<[llvm_v8i64_ty], - [llvm_v8i1_ty, llvm_v8i64_ty, llvm_v8i64_ty], + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Misc. let TargetPrefix = "x86" in { - def int_x86_avx512_cmpeq_pi_512 : GCCBuiltin<"__builtin_ia32_cmpeqpi512">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty], + def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_pcmpeq_d_512 : GCCBuiltin<"__builtin_ia32_pcmpeqd512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_q_512 : GCCBuiltin<"__builtin_ia32_pcmpeqq512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_and_pi : GCCBuiltin<"__builtin_ia32_andpi512">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty], - [IntrNoMem]>; } //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/IntrinsicsXCore.td b/include/llvm/IR/IntrinsicsXCore.td index bf345d4d00c0..b614e1ed6ec0 100644 --- a/include/llvm/IR/IntrinsicsXCore.td +++ b/include/llvm/IR/IntrinsicsXCore.td @@ -67,6 +67,8 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". [NoCapture<0>]>; def int_xcore_setpt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty], [NoCapture<0>]>; + def int_xcore_clrpt : Intrinsic<[],[llvm_anyptr_ty], + [NoCapture<0>]>; def int_xcore_getts : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty], [NoCapture<0>]>; def int_xcore_syncr : Intrinsic<[],[llvm_anyptr_ty], @@ -78,6 +80,7 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". def int_xcore_setev : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty], [NoCapture<0>]>; def int_xcore_eeu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture<0>]>; + def int_xcore_edu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture<0>]>; def int_xcore_setclk : Intrinsic<[],[llvm_anyptr_ty, llvm_anyptr_ty], [NoCapture<0>, NoCapture<1>]>; def int_xcore_setrdy : Intrinsic<[],[llvm_anyptr_ty, llvm_anyptr_ty], diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index dd379ae5e72c..4d940d599b9a 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -15,9 +15,9 @@ #ifndef LLVM_IR_LLVMCONTEXT_H #define LLVM_IR_LLVMCONTEXT_H +#include "llvm-c/Core.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" -#include "llvm-c/Core.h" namespace llvm { @@ -27,7 +27,10 @@ class Twine; class Instruction; class Module; class SMDiagnostic; +class DiagnosticInfo; template <typename T> class SmallVectorImpl; +class Function; +class DebugLoc; /// This is an important class for using LLVM in a threaded context. It /// (opaquely) owns and manages the core "global" data of LLVM's core @@ -64,6 +67,15 @@ public: typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context, unsigned LocCookie); + /// Defines the type of a diagnostic handler. + /// \see LLVMContext::setDiagnosticHandler. + /// \see LLVMContext::diagnose. + typedef void (*DiagnosticHandlerTy)(const DiagnosticInfo &DI, void *Context); + + /// Defines the type of a yield callback. + /// \see LLVMContext::setYieldCallback. + typedef void (*YieldCallbackTy)(LLVMContext *Context, void *OpaqueHandle); + /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked /// when problems with inline asm are detected by the backend. The first /// argument is a function pointer and the second is a context pointer that @@ -72,7 +84,7 @@ public: /// LLVMContext doesn't take ownership or interpret either of these /// pointers. void setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, - void *DiagContext = 0); + void *DiagContext = nullptr); /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by /// setInlineAsmDiagnosticHandler. @@ -82,6 +94,59 @@ public: /// setInlineAsmDiagnosticHandler. void *getInlineAsmDiagnosticContext() const; + /// setDiagnosticHandler - This method sets a handler that is invoked + /// when the backend needs to report anything to the user. The first + /// argument is a function pointer and the second is a context pointer that + /// gets passed into the DiagHandler. + /// + /// LLVMContext doesn't take ownership or interpret either of these + /// pointers. + void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler, + void *DiagContext = nullptr); + + /// getDiagnosticHandler - Return the diagnostic handler set by + /// setDiagnosticHandler. + DiagnosticHandlerTy getDiagnosticHandler() const; + + /// getDiagnosticContext - Return the diagnostic context set by + /// setDiagnosticContext. + void *getDiagnosticContext() const; + + /// diagnose - Report a message to the currently installed diagnostic handler. + /// This function returns, in particular in the case of error reporting + /// (DI.Severity == RS_Error), so the caller should leave the compilation + /// process in a self-consistent state, even though the generated code + /// need not be correct. + /// The diagnostic message will be implicitly prefixed with a severity + /// keyword according to \p DI.getSeverity(), i.e., "error: " + /// for RS_Error, "warning: " for RS_Warning, and "note: " for RS_Note. + void diagnose(const DiagnosticInfo &DI); + + /// \brief Registers a yield callback with the given context. + /// + /// The yield callback function may be called by LLVM to transfer control back + /// to the client that invoked the LLVM compilation. This can be used to yield + /// control of the thread, or perform periodic work needed by the client. + /// There is no guaranteed frequency at which callbacks must occur; in fact, + /// the client is not guaranteed to ever receive this callback. It is at the + /// sole discretion of LLVM to do so and only if it can guarantee that + /// suspending the thread won't block any forward progress in other LLVM + /// contexts in the same process. + /// + /// At a suspend point, the state of the current LLVM context is intentionally + /// undefined. No assumptions about it can or should be made. Only LLVM + /// context API calls that explicitly state that they can be used during a + /// yield callback are allowed to be used. Any other API calls into the + /// context are not supported until the yield callback function returns + /// control to LLVM. Other LLVM contexts are unaffected by this restriction. + void setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle); + + /// \brief Calls the yield callback (if applicable). + /// + /// This transfers control of the current thread back to the client, which may + /// suspend the current thread. Only call this method when LLVM doesn't hold + /// any global mutex or cannot block the execution in another LLVM context. + void yield(); /// emitError - Emit an error message to the currently installed error handler /// with optional location information. This function returns, so code should diff --git a/include/llvm/Support/LeakDetector.h b/include/llvm/IR/LeakDetector.h index 501a9db72c15..cb18df875867 100644 --- a/include/llvm/Support/LeakDetector.h +++ b/include/llvm/IR/LeakDetector.h @@ -1,4 +1,4 @@ -//===-- llvm/Support/LeakDetector.h - Provide leak detection ----*- C++ -*-===// +//===- LeakDetector.h - Provide leak detection ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,8 +19,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_LEAKDETECTOR_H -#define LLVM_SUPPORT_LEAKDETECTOR_H +#ifndef LLVM_IR_LEAKDETECTOR_H +#define LLVM_IR_LEAKDETECTOR_H #include <string> diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index fa1436ec6324..c967a6bca8b2 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -55,7 +55,7 @@ public: /// the Pass to the PassManager. When the PassManager is destroyed, the pass /// will be destroyed as well, so there is no need to delete the pass. This /// implies that all passes MUST be allocated with 'new'. - void add(Pass *P); + void add(Pass *P) override; /// run - Execute all of the passes scheduled for execution. Keep track of /// whether any of the passes modifies the module, and if so, return true. @@ -80,7 +80,7 @@ public: /// PassManager_X is destroyed, the pass will be destroyed as well, so /// there is no need to delete the pass. /// This implies that all passes MUST be allocated with 'new'. - void add(Pass *P); + void add(Pass *P) override; /// run - Execute all of the passes scheduled for execution. Keep /// track of whether any of the passes modifies the function, and if diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h index d256a3e92ccf..f6065a4e21a6 100644 --- a/include/llvm/IR/LegacyPassManagers.h +++ b/include/llvm/IR/LegacyPassManagers.h @@ -101,15 +101,15 @@ namespace llvm { // enums for debugging strings enum PassDebuggingString { - EXECUTION_MSG, // "Executing Pass '" - MODIFICATION_MSG, // "' Made Modification '" - FREEING_MSG, // " Freeing Pass '" - ON_BASICBLOCK_MSG, // "' on BasicBlock '" + PassName + "'...\n" + EXECUTION_MSG, // "Executing Pass '" + PassName + MODIFICATION_MSG, // "Made Modification '" + PassName + FREEING_MSG, // " Freeing Pass '" + PassName + ON_BASICBLOCK_MSG, // "' on BasicBlock '" + InstructionName + "'...\n" ON_FUNCTION_MSG, // "' on Function '" + FunctionName + "'...\n" ON_MODULE_MSG, // "' on Module '" + ModuleName + "'...\n" - ON_REGION_MSG, // " 'on Region ...\n'" - ON_LOOP_MSG, // " 'on Loop ...\n'" - ON_CG_MSG // "' on Call Graph ...\n'" + ON_REGION_MSG, // "' on Region '" + Msg + "'...\n'" + ON_LOOP_MSG, // "' on Loop '" + Msg + "'...\n'" + ON_CG_MSG // "' on Call Graph Nodes '" + Msg + "'...\n'" }; /// PassManagerPrettyStackEntry - This is used to print informative information @@ -120,14 +120,14 @@ class PassManagerPrettyStackEntry : public PrettyStackTraceEntry { Module *M; public: explicit PassManagerPrettyStackEntry(Pass *p) - : P(p), V(0), M(0) {} // When P is releaseMemory'd. + : P(p), V(nullptr), M(nullptr) {} // When P is releaseMemory'd. PassManagerPrettyStackEntry(Pass *p, Value &v) - : P(p), V(&v), M(0) {} // When P is run on V + : P(p), V(&v), M(nullptr) {} // When P is run on V PassManagerPrettyStackEntry(Pass *p, Module &m) - : P(p), V(0), M(&m) {} // When P is run on M + : P(p), V(nullptr), M(&m) {} // When P is run on M /// print - Emit information about this stack frame to OS. - virtual void print(raw_ostream &OS) const; + void print(raw_ostream &OS) const override; }; @@ -263,7 +263,7 @@ private: class PMDataManager { public: - explicit PMDataManager() : TPM(NULL), Depth(0) { + explicit PMDataManager() : TPM(nullptr), Depth(0) { initializeAnalysisInfo(); } @@ -303,7 +303,7 @@ public: void initializeAnalysisInfo() { AvailableAnalysis.clear(); for (unsigned i = 0; i < PMT_Last; ++i) - InheritedAnalysis[i] = NULL; + InheritedAnalysis[i] = nullptr; } // Return true if P preserves high level analysis used by other @@ -414,7 +414,7 @@ public: /// run - Execute all of the passes scheduled for execution. Keep track of /// whether any of the passes modifies the module, and if so, return true. bool runOnFunction(Function &F); - bool runOnModule(Module &M); + bool runOnModule(Module &M) override; /// cleanup - After running all passes, clean up pass manager cache. void cleanup(); @@ -426,7 +426,7 @@ public: /// doInitialization - Run all of the initializers for the function passes. /// - bool doInitialization(Module &M); + bool doInitialization(Module &M) override; /// doFinalization - Overrides ModulePass doFinalization for global /// finalization tasks @@ -435,20 +435,20 @@ public: /// doFinalization - Run all of the finalizers for the function passes. /// - bool doFinalization(Module &M); + bool doFinalization(Module &M) override; - virtual PMDataManager *getAsPMDataManager() { return this; } - virtual Pass *getAsPass() { return this; } + PMDataManager *getAsPMDataManager() override { return this; } + Pass *getAsPass() override { return this; } /// Pass Manager itself does not invalidate any analysis info. - void getAnalysisUsage(AnalysisUsage &Info) const { + void getAnalysisUsage(AnalysisUsage &Info) const override { Info.setPreservesAll(); } // Print passes managed by this manager - void dumpPassStructure(unsigned Offset); + void dumpPassStructure(unsigned Offset) override; - virtual const char *getPassName() const { + const char *getPassName() const override { return "Function Pass Manager"; } @@ -458,7 +458,7 @@ public: return FP; } - virtual PassManagerType getPassManagerType() const { + PassManagerType getPassManagerType() const override { return PMT_FunctionPassManager; } }; diff --git a/include/llvm/Support/PassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h index c0914b1f2f08..e2e4912ef64e 100644 --- a/include/llvm/Support/PassNameParser.h +++ b/include/llvm/IR/LegacyPassNameParser.h @@ -1,4 +1,4 @@ -//===- llvm/Support/PassNameParser.h ----------------------------*- C++ -*-===// +//===- LegacyPassNameParser.h -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,10 +18,13 @@ // includes passes that have a PassType that are compatible with the filter // (which is the template argument). // +// Note that this is part of the legacy pass manager infrastructure and will be +// (eventually) going away. +// //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_PASSNAMEPARSER_H -#define LLVM_SUPPORT_PASSNAMEPARSER_H +#ifndef LLVM_IR_LEGACYPASSNAMEPARSER_H +#define LLVM_IR_LEGACYPASSNAMEPARSER_H #include "llvm/ADT/STLExtras.h" #include "llvm/Pass.h" @@ -40,7 +43,7 @@ class PassNameParser : public PassRegistrationListener, public cl::parser<const PassInfo*> { cl::Option *Opt; public: - PassNameParser() : Opt(0) {} + PassNameParser(); virtual ~PassNameParser(); void initialize(cl::Option &O) { @@ -59,26 +62,26 @@ public: inline bool ignorablePass(const PassInfo *P) const { // Ignore non-selectable and non-constructible passes! Ignore // non-optimizations. - return P->getPassArgument() == 0 || *P->getPassArgument() == 0 || - P->getNormalCtor() == 0 || ignorablePassImpl(P); + return P->getPassArgument() == nullptr || *P->getPassArgument() == 0 || + P->getNormalCtor() == nullptr || ignorablePassImpl(P); } // Implement the PassRegistrationListener callbacks used to populate our map // - virtual void passRegistered(const PassInfo *P) { + void passRegistered(const PassInfo *P) override { if (ignorablePass(P) || !Opt) return; if (findOption(P->getPassArgument()) != getNumOptions()) { errs() << "Two passes with the same argument (-" << P->getPassArgument() << ") attempted to be registered!\n"; - llvm_unreachable(0); + llvm_unreachable(nullptr); } addLiteralOption(P->getPassArgument(), P, P->getPassName()); } - virtual void passEnumerate(const PassInfo *P) { passRegistered(P); } + void passEnumerate(const PassInfo *P) override { passRegistered(P); } // printOptionInfo - Print out information about this option. Override the // default implementation to sort the table before we print... - virtual void printOptionInfo(const cl::Option &O, size_t GlobalWidth) const { + void printOptionInfo(const cl::Option &O, size_t GlobalWidth) const override { PassNameParser *PNP = const_cast<PassNameParser*>(this); array_pod_sort(PNP->Values.begin(), PNP->Values.end(), ValLessThan); cl::parser<const PassInfo*>::printOptionInfo(O, GlobalWidth); @@ -104,7 +107,9 @@ private: Filter filter; public: - bool ignorablePassImpl(const PassInfo *P) const { return !filter(*P); } + bool ignorablePassImpl(const PassInfo *P) const override { + return !filter(*P); + } }; ///===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index ce81b5498f52..37d263bf52a8 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -15,14 +15,17 @@ #ifndef LLVM_IR_MDBUILDER_H #define LLVM_IR_MDBUILDER_H -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Metadata.h" +#include "llvm/Support/DataTypes.h" +#include <utility> namespace llvm { class APInt; +template <typename T> class ArrayRef; class LLVMContext; +class MDNode; +class MDString; +class StringRef; class MDBuilder { LLVMContext &Context; @@ -31,9 +34,7 @@ public: MDBuilder(LLVMContext &context) : Context(context) {} /// \brief Return the given string as metadata. - MDString *createString(StringRef Str) { - return MDString::get(Context, Str); - } + MDString *createString(StringRef Str); //===------------------------------------------------------------------===// // FPMath metadata. @@ -42,55 +43,24 @@ public: /// \brief Return metadata with the given settings. The special value 0.0 /// for the Accuracy parameter indicates the default (maximal precision) /// setting. - MDNode *createFPMath(float Accuracy) { - if (Accuracy == 0.0) - return 0; - assert(Accuracy > 0.0 && "Invalid fpmath accuracy!"); - Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy); - return MDNode::get(Context, Op); - } + MDNode *createFPMath(float Accuracy); //===------------------------------------------------------------------===// // Prof metadata. //===------------------------------------------------------------------===// /// \brief Return metadata containing two branch weights. - MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight) { - uint32_t Weights[] = { TrueWeight, FalseWeight }; - return createBranchWeights(Weights); - } + MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight); /// \brief Return metadata containing a number of branch weights. - MDNode *createBranchWeights(ArrayRef<uint32_t> Weights) { - assert(Weights.size() >= 2 && "Need at least two branch weights!"); - - SmallVector<Value *, 4> Vals(Weights.size()+1); - Vals[0] = createString("branch_weights"); - - Type *Int32Ty = Type::getInt32Ty(Context); - for (unsigned i = 0, e = Weights.size(); i != e; ++i) - Vals[i+1] = ConstantInt::get(Int32Ty, Weights[i]); - - return MDNode::get(Context, Vals); - } + MDNode *createBranchWeights(ArrayRef<uint32_t> Weights); //===------------------------------------------------------------------===// // Range metadata. //===------------------------------------------------------------------===// /// \brief Return metadata describing the range [Lo, Hi). - MDNode *createRange(const APInt &Lo, const APInt &Hi) { - assert(Lo.getBitWidth() == Hi.getBitWidth() && "Mismatched bitwidths!"); - // If the range is everything then it is useless. - if (Hi == Lo) - return 0; - - // Return the range [Lo, Hi). - Type *Ty = IntegerType::get(Context, Lo.getBitWidth()); - Value *Range[2] = { ConstantInt::get(Ty, Lo), ConstantInt::get(Ty, Hi) }; - return MDNode::get(Context, Range); - } - + MDNode *createRange(const APInt &Lo, const APInt &Hi); //===------------------------------------------------------------------===// // TBAA metadata. @@ -99,41 +69,17 @@ public: /// \brief Return metadata appropriate for a TBAA root node. Each returned /// node is distinct from all other metadata and will never be identified /// (uniqued) with anything else. - MDNode *createAnonymousTBAARoot() { - // To ensure uniqueness the root node is self-referential. - MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value*>()); - MDNode *Root = MDNode::get(Context, Dummy); - // At this point we have - // !0 = metadata !{} <- dummy - // !1 = metadata !{metadata !0} <- root - // Replace the dummy operand with the root node itself and delete the dummy. - Root->replaceOperandWith(0, Root); - MDNode::deleteTemporary(Dummy); - // We now have - // !1 = metadata !{metadata !1} <- self-referential root - return Root; - } + MDNode *createAnonymousTBAARoot(); /// \brief Return metadata appropriate for a TBAA root node with the given /// name. This may be identified (uniqued) with other roots with the same /// name. - MDNode *createTBAARoot(StringRef Name) { - return MDNode::get(Context, createString(Name)); - } + MDNode *createTBAARoot(StringRef Name); /// \brief Return metadata for a non-root TBAA node with the given name, /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. MDNode *createTBAANode(StringRef Name, MDNode *Parent, - bool isConstant = false) { - if (isConstant) { - Constant *Flags = ConstantInt::get(Type::getInt64Ty(Context), 1); - Value *Ops[3] = { createString(Name), Parent, Flags }; - return MDNode::get(Context, Ops); - } else { - Value *Ops[2] = { createString(Name), Parent }; - return MDNode::get(Context, Ops); - } - } + bool isConstant = false); struct TBAAStructField { uint64_t Offset; @@ -145,52 +91,23 @@ public: /// \brief Return metadata for a tbaa.struct node with the given /// struct field descriptions. - MDNode *createTBAAStructNode(ArrayRef<TBAAStructField> Fields) { - SmallVector<Value *, 4> Vals(Fields.size() * 3); - Type *Int64 = IntegerType::get(Context, 64); - for (unsigned i = 0, e = Fields.size(); i != e; ++i) { - Vals[i * 3 + 0] = ConstantInt::get(Int64, Fields[i].Offset); - Vals[i * 3 + 1] = ConstantInt::get(Int64, Fields[i].Size); - Vals[i * 3 + 2] = Fields[i].TBAA; - } - return MDNode::get(Context, Vals); - } + MDNode *createTBAAStructNode(ArrayRef<TBAAStructField> Fields); /// \brief Return metadata for a TBAA struct node in the type DAG /// with the given name, a list of pairs (offset, field type in the type DAG). - MDNode *createTBAAStructTypeNode(StringRef Name, - ArrayRef<std::pair<MDNode*, uint64_t> > Fields) { - SmallVector<Value *, 4> Ops(Fields.size() * 2 + 1); - Type *Int64 = IntegerType::get(Context, 64); - Ops[0] = createString(Name); - for (unsigned i = 0, e = Fields.size(); i != e; ++i) { - Ops[i * 2 + 1] = Fields[i].first; - Ops[i * 2 + 2] = ConstantInt::get(Int64, Fields[i].second); - } - return MDNode::get(Context, Ops); - } + MDNode * + createTBAAStructTypeNode(StringRef Name, + ArrayRef<std::pair<MDNode *, uint64_t>> Fields); /// \brief Return metadata for a TBAA scalar type node with the /// given name, an offset and a parent in the TBAA type DAG. MDNode *createTBAAScalarTypeNode(StringRef Name, MDNode *Parent, - uint64_t Offset = 0) { - SmallVector<Value *, 4> Ops(3); - Type *Int64 = IntegerType::get(Context, 64); - Ops[0] = createString(Name); - Ops[1] = Parent; - Ops[2] = ConstantInt::get(Int64, Offset); - return MDNode::get(Context, Ops); - } + uint64_t Offset = 0); /// \brief Return metadata for a TBAA tag node with the given /// base type, access type and offset relative to the base type. MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, - uint64_t Offset) { - Type *Int64 = IntegerType::get(Context, 64); - Value *Ops[3] = { BaseType, AccessType, ConstantInt::get(Int64, Offset) }; - return MDNode::get(Context, Ops); - } - + uint64_t Offset); }; } // end namespace llvm diff --git a/include/llvm/Target/Mangler.h b/include/llvm/IR/Mangler.h index eee7bf6d6979..c1ba5858a612 100644 --- a/include/llvm/Target/Mangler.h +++ b/include/llvm/IR/Mangler.h @@ -1,4 +1,4 @@ -//===-- llvm/Target/Mangler.h - Self-contained name mangler -----*- C++ -*-===// +//===-- llvm/IR/Mangler.h - Self-contained name mangler ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,13 +15,13 @@ #define LLVM_TARGET_MANGLER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { +class DataLayout; class GlobalValue; -class MCContext; template <typename T> class SmallVectorImpl; -class TargetMachine; class Twine; class Mangler { @@ -33,33 +33,35 @@ public: }; private: - const TargetMachine *TM; + const DataLayout *DL; /// AnonGlobalIDs - We need to give global values the same name every time /// they are mangled. This keeps track of the number we give to anonymous /// ones. /// - DenseMap<const GlobalValue*, unsigned> AnonGlobalIDs; + mutable DenseMap<const GlobalValue*, unsigned> AnonGlobalIDs; /// NextAnonGlobalID - This simple counter is used to unique value names. /// - unsigned NextAnonGlobalID; + mutable unsigned NextAnonGlobalID; public: - Mangler(const TargetMachine *TM) : TM(TM), NextAnonGlobalID(1) {} + Mangler(const DataLayout *DL) : DL(DL), NextAnonGlobalID(1) {} - /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix - /// and the specified global variable's name. If the global variable doesn't - /// have a name, this fills in a unique name for the global. + /// Print the appropriate prefix and the specified global variable's name. + /// If the global variable doesn't have a name, this fills in a unique name + /// for the global. + void getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, + bool CannotUsePrivateLabel) const; void getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV, - bool isImplicitlyPrivate, bool UseGlobalPrefix = true); + bool CannotUsePrivateLabel) const; - /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix - /// and the specified name as the global variable name. GVName must not be - /// empty. + /// Print the appropriate prefix and the specified name as the global variable + /// name. GVName must not be empty. + void getNameWithPrefix(raw_ostream &OS, const Twine &GVName, + ManglerPrefixTy PrefixTy = Mangler::Default) const; void getNameWithPrefix(SmallVectorImpl<char> &OutName, const Twine &GVName, - ManglerPrefixTy PrefixTy = Mangler::Default, - bool UseGlobalPrefix = true); + ManglerPrefixTy PrefixTy = Mangler::Default) const; }; } // End llvm namespace diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 9659c2e05c38..7a0ca887201b 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -19,6 +19,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Value.h" namespace llvm { @@ -28,7 +29,7 @@ template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; -enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) { +enum LLVMConstants : uint32_t { DEBUG_METADATA_VERSION = 1 // Current debug info version number. }; @@ -207,6 +208,42 @@ class NamedMDNode : public ilist_node<NamedMDNode> { explicit NamedMDNode(const Twine &N); + template<class T1, class T2> + class op_iterator_impl : + public std::iterator<std::bidirectional_iterator_tag, T2> { + const NamedMDNode *Node; + unsigned Idx; + op_iterator_impl(const NamedMDNode *N, unsigned i) : Node(N), Idx(i) { } + + friend class NamedMDNode; + + public: + op_iterator_impl() : Node(nullptr), Idx(0) { } + + bool operator==(const op_iterator_impl &o) const { return Idx == o.Idx; } + bool operator!=(const op_iterator_impl &o) const { return Idx != o.Idx; } + op_iterator_impl &operator++() { + ++Idx; + return *this; + } + op_iterator_impl operator++(int) { + op_iterator_impl tmp(*this); + operator++(); + return tmp; + } + op_iterator_impl &operator--() { + --Idx; + return *this; + } + op_iterator_impl operator--(int) { + op_iterator_impl tmp(*this); + operator--(); + return tmp; + } + + T1 operator*() const { return Node->getOperand(Idx); } + }; + public: /// eraseFromParent - Drop all references and remove the node from parent /// module. @@ -235,10 +272,28 @@ public: StringRef getName() const; /// print - Implement operator<< on NamedMDNode. - void print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW = 0) const; + void print(raw_ostream &ROS) const; /// dump() - Allow printing of NamedMDNodes from the debugger. void dump() const; + + // --------------------------------------------------------------------------- + // Operand Iterator interface... + // + typedef op_iterator_impl<MDNode*, MDNode> op_iterator; + op_iterator op_begin() { return op_iterator(this, 0); } + op_iterator op_end() { return op_iterator(this, getNumOperands()); } + + typedef op_iterator_impl<const MDNode*, MDNode> const_op_iterator; + const_op_iterator op_begin() const { return const_op_iterator(this, 0); } + const_op_iterator op_end() const { return const_op_iterator(this, getNumOperands()); } + + inline iterator_range<op_iterator> operands() { + return iterator_range<op_iterator>(op_begin(), op_end()); + } + inline iterator_range<const_op_iterator> operands() const { + return iterator_range<const_op_iterator>(op_begin(), op_end()); + } }; } // end llvm namespace diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index b30a9a3d1abf..26f62db9db53 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -15,19 +15,22 @@ #ifndef LLVM_IR_MODULE_H #define LLVM_IR_MODULE_H -#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Comdat.h" +#include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Metadata.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/DataTypes.h" +#include <system_error> namespace llvm { - class FunctionType; class GVMaterializer; class LLVMContext; +class RandomNumberGenerator; class StructType; template<typename T> struct DenseMapInfo; template<typename KeyT, typename ValueT, typename KeyInfoT> class DenseMap; @@ -121,6 +124,8 @@ public: typedef iplist<GlobalAlias> AliasListType; /// The type for the list of named metadata. typedef ilist<NamedMDNode> NamedMDListType; + /// The type of the comdat "symbol" table. + typedef StringMap<Comdat> ComdatSymTabType; /// The Global Variable iterator. typedef GlobalListType::iterator global_iterator; @@ -142,12 +147,6 @@ public: /// The named metadata constant interators. typedef NamedMDListType::const_iterator const_named_metadata_iterator; - /// An enumeration for describing the endianess of the target machine. - enum Endianness { AnyEndianness, LittleEndian, BigEndian }; - - /// An enumeration for describing the size of a pointer on the target machine. - enum PointerSize { AnyPointerSize, Pointer32, Pointer64 }; - /// This enumeration defines the supported behaviors of module flags. enum ModFlagBehavior { /// Emits an error if two values disagree, otherwise the resulting value is @@ -156,7 +155,7 @@ public: /// Emits a warning if two values disagree. The result value will be the /// operand for the flag from the first module being linked. - Warning = 2, + Warning = 2, /// Adds a requirement that another module flag be present and have a /// specified value after linking is performed. The value must be a metadata @@ -201,11 +200,22 @@ private: NamedMDListType NamedMDList; ///< The named metadata in the module std::string GlobalScopeAsm; ///< Inline Asm at global scope. ValueSymbolTable *ValSymTab; ///< Symbol table for values - OwningPtr<GVMaterializer> Materializer; ///< Used to materialize GlobalValues + ComdatSymTabType ComdatSymTab; ///< Symbol table for COMDATs + std::unique_ptr<GVMaterializer> + Materializer; ///< Used to materialize GlobalValues std::string ModuleID; ///< Human readable identifier for the module std::string TargetTriple; ///< Platform target triple Module compiled on - std::string DataLayout; ///< Target data description void *NamedMDSymTab; ///< NamedMDNode names. + // Allow lazy initialization in const method. + mutable RandomNumberGenerator *RNG; ///< The random number generator for this module. + + // We need to keep the string because the C API expects us to own the string + // representation. + // Since we have it, we also use an empty string to represent a module without + // a DataLayout. If it has a DataLayout, these variables are in sync and the + // string is just a cache of getDataLayout()->getStringRepresentation(). + std::string DataLayoutStr; + DataLayout DL; friend class Constant; @@ -227,23 +237,17 @@ public: /// @returns the module identifier as a string const std::string &getModuleIdentifier() const { return ModuleID; } - /// Get the data layout string for the module's target platform. This encodes - /// the type sizes and alignments expected by this module. - /// @returns the data layout as a string - const std::string &getDataLayout() const { return DataLayout; } + /// Get the data layout string for the module's target platform. This is + /// equivalent to getDataLayout()->getStringRepresentation(). + const std::string &getDataLayoutStr() const { return DataLayoutStr; } + + /// Get the data layout for the module's target platform. + const DataLayout *getDataLayout() const; /// Get the target triple which is a string describing the target host. /// @returns a string containing the target triple. const std::string &getTargetTriple() const { return TargetTriple; } - /// Get the target endian information. - /// @returns Endianess - an enumeration for the endianess of the target - Endianness getEndianness() const; - - /// Get the target pointer size. - /// @returns PointerSize - an enumeration for the size of the target's pointer - PointerSize getPointerSize() const; - /// Get the global data context. /// @returns LLVMContext - a container for LLVM's global information LLVMContext &getContext() const { return Context; } @@ -252,6 +256,11 @@ public: /// @returns a string containing the module-scope inline assembly blocks. const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } + /// Get the RandomNumberGenerator for this module. The RNG can be + /// seeded via -rng-seed=<uint64> and is salted with the ModuleID. + /// The returned RNG should not be shared across threads. + RandomNumberGenerator &getRNG() const; + /// @} /// @name Module Level Mutators /// @{ @@ -260,7 +269,8 @@ public: void setModuleIdentifier(StringRef ID) { ModuleID = ID; } /// Set the data layout - void setDataLayout(StringRef DL) { DataLayout = DL; } + void setDataLayout(StringRef Desc); + void setDataLayout(const DataLayout *Other); /// Set the target triple. void setTargetTriple(StringRef T) { TargetTriple = T; } @@ -286,33 +296,29 @@ public: /// @name Generic Value Accessors /// @{ - /// getNamedValue - Return the global value in the module with - /// the specified name, of arbitrary type. This method returns null - /// if a global with the specified name is not found. + /// Return the global value in the module with the specified name, of + /// arbitrary type. This method returns null if a global with the specified + /// name is not found. GlobalValue *getNamedValue(StringRef Name) const; - /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. - /// This ID is uniqued across modules in the current LLVMContext. + /// Return a unique non-zero ID for the specified metadata kind. This ID is + /// uniqued across modules in the current LLVMContext. unsigned getMDKindID(StringRef Name) const; - /// getMDKindNames - Populate client supplied SmallVector with the name for - /// custom metadata IDs registered in this LLVMContext. + /// Populate client supplied SmallVector with the name for custom metadata IDs + /// registered in this LLVMContext. void getMDKindNames(SmallVectorImpl<StringRef> &Result) const; - - typedef DenseMap<StructType*, unsigned, DenseMapInfo<StructType*> > - NumeredTypesMapTy; - - /// getTypeByName - Return the type with the specified name, or null if there - /// is none by that name. + /// Return the type with the specified name, or null if there is none by that + /// name. StructType *getTypeByName(StringRef Name) const; /// @} /// @name Function Accessors /// @{ - /// getOrInsertFunction - Look up the specified function in the module symbol - /// table. Four possibilities: + /// Look up the specified function in the module symbol table. Four + /// possibilities: /// 1. If it does not exist, add a prototype for the function and return it. /// 2. If it exists, and has a local linkage, the existing function is /// renamed and a new one is inserted. @@ -325,33 +331,32 @@ public: Constant *getOrInsertFunction(StringRef Name, FunctionType *T); - /// getOrInsertFunction - Look up the specified function in the module symbol - /// table. If it does not exist, add a prototype for the function and return - /// it. This function guarantees to return a constant of pointer to the - /// specified function type or a ConstantExpr BitCast of that type if the - /// named function has a different type. This version of the method takes a - /// null terminated list of function arguments, which makes it easier for - /// clients to use. + /// Look up the specified function in the module symbol table. If it does not + /// exist, add a prototype for the function and return it. This function + /// guarantees to return a constant of pointer to the specified function type + /// or a ConstantExpr BitCast of that type if the named function has a + /// different type. This version of the method takes a null terminated list of + /// function arguments, which makes it easier for clients to use. Constant *getOrInsertFunction(StringRef Name, AttributeSet AttributeList, Type *RetTy, ...) END_WITH_NULL; - /// getOrInsertFunction - Same as above, but without the attributes. + /// Same as above, but without the attributes. Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...) END_WITH_NULL; - /// getFunction - Look up the specified function in the module symbol table. - /// If it does not exist, return null. + /// Look up the specified function in the module symbol table. If it does not + /// exist, return null. Function *getFunction(StringRef Name) const; /// @} /// @name Global Variable Accessors /// @{ - /// getGlobalVariable - Look up the specified global variable in the module - /// symbol table. If it does not exist, return null. If AllowInternal is set - /// to true, this function will return types that have InternalLinkage. By - /// default, these types are not returned. + /// Look up the specified global variable in the module symbol table. If it + /// does not exist, return null. If AllowInternal is set to true, this + /// function will return types that have InternalLinkage. By default, these + /// types are not returned. const GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal = false) const { return const_cast<Module *>(this)->getGlobalVariable(Name, AllowInternal); @@ -359,9 +364,9 @@ public: GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal = false); - /// getNamedGlobal - Return the global variable in the module with the - /// specified name, of arbitrary type. This method returns null if a global - /// with the specified name is not found. + /// Return the global variable in the module with the specified name, of + /// arbitrary type. This method returns null if a global with the specified + /// name is not found. GlobalVariable *getNamedGlobal(StringRef Name) { return getGlobalVariable(Name, true); } @@ -369,8 +374,7 @@ public: return const_cast<Module *>(this)->getNamedGlobal(Name); } - /// getOrInsertGlobal - Look up the specified global in the module symbol - /// table. + /// Look up the specified global in the module symbol table. /// 1. If it does not exist, add a declaration of the global and return it. /// 2. Else, the global exists but has the wrong type: return the function /// with a constantexpr cast to the right type. @@ -382,53 +386,57 @@ public: /// @name Global Alias Accessors /// @{ - /// getNamedAlias - Return the global alias in the module with the - /// specified name, of arbitrary type. This method returns null if a global - /// with the specified name is not found. + /// Return the global alias in the module with the specified name, of + /// arbitrary type. This method returns null if a global with the specified + /// name is not found. GlobalAlias *getNamedAlias(StringRef Name) const; /// @} /// @name Named Metadata Accessors /// @{ - /// getNamedMetadata - Return the first NamedMDNode in the module with the - /// specified name. This method returns null if a NamedMDNode with the - /// specified name is not found. + /// Return the first NamedMDNode in the module with the specified name. This + /// method returns null if a NamedMDNode with the specified name is not found. NamedMDNode *getNamedMetadata(const Twine &Name) const; - /// getOrInsertNamedMetadata - Return the named MDNode in the module - /// with the specified name. This method returns a new NamedMDNode if a - /// NamedMDNode with the specified name is not found. + /// Return the named MDNode in the module with the specified name. This method + /// returns a new NamedMDNode if a NamedMDNode with the specified name is not + /// found. NamedMDNode *getOrInsertNamedMetadata(StringRef Name); - /// eraseNamedMetadata - Remove the given NamedMDNode from this module - /// and delete it. + /// Remove the given NamedMDNode from this module and delete it. void eraseNamedMetadata(NamedMDNode *NMD); /// @} +/// @name Comdat Accessors +/// @{ + + /// Return the Comdat in the module with the specified name. It is created + /// if it didn't already exist. + Comdat *getOrInsertComdat(StringRef Name); + +/// @} /// @name Module Flags Accessors /// @{ - /// getModuleFlagsMetadata - Returns the module flags in the provided vector. + /// Returns the module flags in the provided vector. void getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const; /// Return the corresponding value if Key appears in module flags, otherwise /// return null. Value *getModuleFlag(StringRef Key) const; - /// getModuleFlagsMetadata - Returns the NamedMDNode in the module that - /// represents module-level flags. This method returns null if there are no - /// module-level flags. + /// Returns the NamedMDNode in the module that represents module-level flags. + /// This method returns null if there are no module-level flags. NamedMDNode *getModuleFlagsMetadata() const; - /// getOrInsertModuleFlagsMetadata - Returns the NamedMDNode in the module - /// that represents module-level flags. If module-level flags aren't found, - /// it creates the named metadata that contains them. + /// Returns the NamedMDNode in the module that represents module-level flags. + /// If module-level flags aren't found, it creates the named metadata that + /// contains them. NamedMDNode *getOrInsertModuleFlagsMetadata(); - /// addModuleFlag - Add a module-level flag to the module-level flags - /// metadata. It will create the module-level flags named metadata if it - /// doesn't already exist. + /// Add a module-level flag to the module-level flags metadata. It will create + /// the module-level flags named metadata if it doesn't already exist. void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Value *Val); void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val); void addModuleFlag(MDNode *Node); @@ -437,45 +445,40 @@ public: /// @name Materialization /// @{ - /// setMaterializer - Sets the GVMaterializer to GVM. This module must not - /// yet have a Materializer. To reset the materializer for a module that - /// already has one, call MaterializeAllPermanently first. Destroying this - /// module will destroy its materializer without materializing any more - /// GlobalValues. Without destroying the Module, there is no way to detach or - /// destroy a materializer without materializing all the GVs it controls, to - /// avoid leaving orphan unmaterialized GVs. + /// Sets the GVMaterializer to GVM. This module must not yet have a + /// Materializer. To reset the materializer for a module that already has one, + /// call MaterializeAllPermanently first. Destroying this module will destroy + /// its materializer without materializing any more GlobalValues. Without + /// destroying the Module, there is no way to detach or destroy a materializer + /// without materializing all the GVs it controls, to avoid leaving orphan + /// unmaterialized GVs. void setMaterializer(GVMaterializer *GVM); - /// getMaterializer - Retrieves the GVMaterializer, if any, for this Module. + /// Retrieves the GVMaterializer, if any, for this Module. GVMaterializer *getMaterializer() const { return Materializer.get(); } - /// isMaterializable - True if the definition of GV has yet to be materialized - /// from the GVMaterializer. + /// True if the definition of GV has yet to be materializedfrom the + /// GVMaterializer. bool isMaterializable(const GlobalValue *GV) const; - /// isDematerializable - Returns true if this GV was loaded from this Module's - /// GVMaterializer and the GVMaterializer knows how to dematerialize the GV. + /// Returns true if this GV was loaded from this Module's GVMaterializer and + /// the GVMaterializer knows how to dematerialize the GV. bool isDematerializable(const GlobalValue *GV) const; - /// Materialize - Make sure the GlobalValue is fully read. If the module is - /// corrupt, this returns true and fills in the optional string with - /// information about the problem. If successful, this returns false. - bool Materialize(GlobalValue *GV, std::string *ErrInfo = 0); - /// Dematerialize - If the GlobalValue is read in, and if the GVMaterializer - /// supports it, release the memory for the function, and set it up to be - /// materialized lazily. If !isDematerializable(), this method is a noop. + /// Make sure the GlobalValue is fully read. If the module is corrupt, this + /// returns true and fills in the optional string with information about the + /// problem. If successful, this returns false. + bool Materialize(GlobalValue *GV, std::string *ErrInfo = nullptr); + /// If the GlobalValue is read in, and if the GVMaterializer supports it, + /// release the memory for the function, and set it up to be materialized + /// lazily. If !isDematerializable(), this method is a noop. void Dematerialize(GlobalValue *GV); - /// MaterializeAll - Make sure all GlobalValues in this Module are fully read. - /// If the module is corrupt, this returns true and fills in the optional - /// string with information about the problem. If successful, this returns - /// false. - bool MaterializeAll(std::string *ErrInfo = 0); + /// Make sure all GlobalValues in this Module are fully read. + std::error_code materializeAll(); - /// MaterializeAllPermanently - Make sure all GlobalValues in this Module are - /// fully read and clear the Materializer. If the module is corrupt, this - /// returns true, fills in the optional string with information about the - /// problem, and DOES NOT clear the old Materializer. If successful, this - /// returns false. - bool MaterializeAllPermanently(std::string *ErrInfo = 0); + /// Make sure all GlobalValues in this Module are fully read and clear the + /// Materializer. If the module is corrupt, this DOES NOT clear the old + /// Materializer. + std::error_code materializeAllPermanently(bool ReleaseBuffer = false); /// @} /// @name Direct access to the globals list, functions list, and symbol table @@ -513,6 +516,10 @@ public: const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; } /// Get the Module's symbol table of global variable and function identifiers. ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; } + /// Get the Module's symbol table for COMDATs (constant). + const ComdatSymTabType &getComdatSymbolTable() const { return ComdatSymTab; } + /// Get the Module's symbol table for COMDATs. + ComdatSymTabType &getComdatSymbolTable() { return ComdatSymTab; } /// @} /// @name Global Variable Iteration @@ -524,6 +531,13 @@ public: const_global_iterator global_end () const { return GlobalList.end(); } bool global_empty() const { return GlobalList.empty(); } + iterator_range<global_iterator> globals() { + return iterator_range<global_iterator>(global_begin(), global_end()); + } + iterator_range<const_global_iterator> globals() const { + return iterator_range<const_global_iterator>(global_begin(), global_end()); + } + /// @} /// @name Function Iteration /// @{ @@ -546,6 +560,12 @@ public: size_t alias_size () const { return AliasList.size(); } bool alias_empty() const { return AliasList.empty(); } + iterator_range<alias_iterator> aliases() { + return iterator_range<alias_iterator>(alias_begin(), alias_end()); + } + iterator_range<const_alias_iterator> aliases() const { + return iterator_range<const_alias_iterator>(alias_begin(), alias_end()); + } /// @} /// @name Named Metadata Iteration @@ -564,6 +584,14 @@ public: size_t named_metadata_size() const { return NamedMDList.size(); } bool named_metadata_empty() const { return NamedMDList.empty(); } + iterator_range<named_metadata_iterator> named_metadata() { + return iterator_range<named_metadata_iterator>(named_metadata_begin(), + named_metadata_end()); + } + iterator_range<const_named_metadata_iterator> named_metadata() const { + return iterator_range<const_named_metadata_iterator>(named_metadata_begin(), + named_metadata_end()); + } /// @} /// @name Utility functions for printing and dumping Module objects @@ -583,12 +611,20 @@ public: /// is delete'd for real. Note that no operations are valid on an object /// that has "dropped all references", except operator delete. void dropAllReferences(); + +/// @} +/// @name Utility functions for querying Debug information. +/// @{ + + /// \brief Returns the Dwarf Version by checking module flags. + unsigned getDwarfVersion() const; + /// @} }; /// An raw_ostream inserter for modules. inline raw_ostream &operator<<(raw_ostream &O, const Module &M) { - M.print(O, 0); + M.print(O, nullptr); return O; } diff --git a/include/llvm/Support/NoFolder.h b/include/llvm/IR/NoFolder.h index ecfbbaa78247..a9cdfc36fb4a 100644 --- a/include/llvm/Support/NoFolder.h +++ b/include/llvm/IR/NoFolder.h @@ -1,4 +1,4 @@ -//======-- llvm/Support/NoFolder.h - Constant folding helper -*- C++ -*-======// +//===- NoFolder.h - Constant folding helper ---------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,8 +19,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_NOFOLDER_H -#define LLVM_SUPPORT_NOFOLDER_H +#ifndef LLVM_IR_NOFOLDER_H +#define LLVM_IR_NOFOLDER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/Constants.h" diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 5b9bee7fc60f..888cabffe378 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -18,9 +18,9 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Type.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" namespace llvm { @@ -210,6 +210,10 @@ public: setNoSignedZeros(); setAllowReciprocal(); } + + void operator&=(const FastMathFlags &OtherFlags) { + Flags &= OtherFlags.Flags; + } }; @@ -473,6 +477,36 @@ public: }; +class PtrToIntOperator + : public ConcreteOperator<Operator, Instruction::PtrToInt> { + friend class PtrToInt; + friend class ConstantExpr; + +public: + Value *getPointerOperand() { + return getOperand(0); + } + const Value *getPointerOperand() const { + return getOperand(0); + } + static unsigned getPointerOperandIndex() { + return 0U; // get index for modifying correct operand + } + + /// getPointerOperandType - Method to return the pointer operand as a + /// PointerType. + Type *getPointerOperandType() const { + return getPointerOperand()->getType(); + } + + /// getPointerAddressSpace - Method to return the address space of the + /// pointer operand. + unsigned getPointerAddressSpace() const { + return cast<PointerType>(getPointerOperandType())->getAddressSpace(); + } +}; + + } // End llvm namespace #endif diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 833547a23acc..cc2a80b9ff7d 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -35,12 +35,17 @@ /// //===----------------------------------------------------------------------===// +#ifndef LLVM_IR_PASS_MANAGER_H +#define LLVM_IR_PASS_MANAGER_H + #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/polymorphic_ptr.h" -#include "llvm/Support/type_traits.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/Support/type_traits.h" #include <list> +#include <memory> #include <vector> namespace llvm { @@ -48,317 +53,747 @@ namespace llvm { class Module; class Function; +/// \brief An abstract set of preserved analyses following a transformation pass +/// run. +/// +/// When a transformation pass is run, it can return a set of analyses whose +/// results were preserved by that transformation. The default set is "none", +/// and preserving analyses must be done explicitly. +/// +/// There is also an explicit all state which can be used (for example) when +/// the IR is not mutated at all. +class PreservedAnalyses { +public: + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PreservedAnalyses() {} + PreservedAnalyses(const PreservedAnalyses &Arg) + : PreservedPassIDs(Arg.PreservedPassIDs) {} + PreservedAnalyses(PreservedAnalyses &&Arg) + : PreservedPassIDs(std::move(Arg.PreservedPassIDs)) {} + friend void swap(PreservedAnalyses &LHS, PreservedAnalyses &RHS) { + using std::swap; + swap(LHS.PreservedPassIDs, RHS.PreservedPassIDs); + } + PreservedAnalyses &operator=(PreservedAnalyses RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief Convenience factory function for the empty preserved set. + static PreservedAnalyses none() { return PreservedAnalyses(); } + + /// \brief Construct a special preserved set that preserves all passes. + static PreservedAnalyses all() { + PreservedAnalyses PA; + PA.PreservedPassIDs.insert((void *)AllPassesID); + return PA; + } + + /// \brief Mark a particular pass as preserved, adding it to the set. + template <typename PassT> void preserve() { + if (!areAllPreserved()) + PreservedPassIDs.insert(PassT::ID()); + } + + /// \brief Intersect this set with another in place. + /// + /// This is a mutating operation on this preserved set, removing all + /// preserved passes which are not also preserved in the argument. + void intersect(const PreservedAnalyses &Arg) { + if (Arg.areAllPreserved()) + return; + if (areAllPreserved()) { + PreservedPassIDs = Arg.PreservedPassIDs; + return; + } + for (SmallPtrSet<void *, 2>::const_iterator I = PreservedPassIDs.begin(), + E = PreservedPassIDs.end(); + I != E; ++I) + if (!Arg.PreservedPassIDs.count(*I)) + PreservedPassIDs.erase(*I); + } + + /// \brief Intersect this set with a temporary other set in place. + /// + /// This is a mutating operation on this preserved set, removing all + /// preserved passes which are not also preserved in the argument. + void intersect(PreservedAnalyses &&Arg) { + if (Arg.areAllPreserved()) + return; + if (areAllPreserved()) { + PreservedPassIDs = std::move(Arg.PreservedPassIDs); + return; + } + for (SmallPtrSet<void *, 2>::const_iterator I = PreservedPassIDs.begin(), + E = PreservedPassIDs.end(); + I != E; ++I) + if (!Arg.PreservedPassIDs.count(*I)) + PreservedPassIDs.erase(*I); + } + + /// \brief Query whether a pass is marked as preserved by this set. + template <typename PassT> bool preserved() const { + return preserved(PassT::ID()); + } + + /// \brief Query whether an abstract pass ID is marked as preserved by this + /// set. + bool preserved(void *PassID) const { + return PreservedPassIDs.count((void *)AllPassesID) || + PreservedPassIDs.count(PassID); + } + +private: + // Note that this must not be -1 or -2 as those are already used by the + // SmallPtrSet. + static const uintptr_t AllPassesID = (intptr_t)(-3); + + bool areAllPreserved() const { + return PreservedPassIDs.count((void *)AllPassesID); + } + + SmallPtrSet<void *, 2> PreservedPassIDs; +}; + /// \brief Implementation details of the pass manager interfaces. namespace detail { /// \brief Template for the abstract base class used to dispatch /// polymorphically over pass objects. -template <typename T> struct PassConcept { +template <typename IRUnitT, typename AnalysisManagerT> struct PassConcept { // Boiler plate necessary for the container of derived classes. virtual ~PassConcept() {} - virtual PassConcept *clone() = 0; /// \brief The polymorphic API which runs the pass over a given IR entity. - virtual bool run(T Arg) = 0; + /// + /// Note that actual pass object can omit the analysis manager argument if + /// desired. Also that the analysis manager may be null if there is no + /// analysis manager in the pass pipeline. + virtual PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c PassT has a run method +/// accepting an \c AnalysisManagerT. +template <typename IRUnitT, typename AnalysisManagerT, typename PassT, + typename ResultT> +class PassRunAcceptsAnalysisManager { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template <typename T, ResultT (T::*)(IRUnitT, AnalysisManagerT *)> + struct Checker; + + template <typename T> static SmallType f(Checker<T, &T::run> *); + template <typename T> static BigType f(...); + +public: + enum { Value = sizeof(f<PassT>(nullptr)) == sizeof(SmallType) }; }; /// \brief A template wrapper used to implement the polymorphic API. /// -/// Can be instantiated for any object which provides a \c run method -/// accepting a \c T. It requires the pass to be a copyable -/// object. -template <typename T, typename PassT> struct PassModel : PassConcept<T> { - PassModel(PassT Pass) : Pass(llvm_move(Pass)) {} - virtual PassModel *clone() { return new PassModel(Pass); } - virtual bool run(T Arg) { return Pass.run(Arg); } +/// Can be instantiated for any object which provides a \c run method accepting +/// an \c IRUnitT. It requires the pass to be a copyable object. When the +/// \c run method also accepts an \c AnalysisManagerT*, we pass it along. +template <typename IRUnitT, typename AnalysisManagerT, typename PassT, + bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager< + IRUnitT, AnalysisManagerT, PassT, PreservedAnalyses>::Value> +struct PassModel; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template <typename IRUnitT, typename AnalysisManagerT, typename PassT> +struct PassModel<IRUnitT, AnalysisManagerT, PassT, true> + : PassConcept<IRUnitT, AnalysisManagerT> { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { + return Pass.run(IR, AM); + } + StringRef name() override { return PassT::name(); } PassT Pass; }; -} +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template <typename IRUnitT, typename AnalysisManagerT, typename PassT> +struct PassModel<IRUnitT, AnalysisManagerT, PassT, false> + : PassConcept<IRUnitT, AnalysisManagerT> { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { + return Pass.run(IR); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; -class AnalysisManager; +/// \brief Abstract concept of an analysis result. +/// +/// This concept is parameterized over the IR unit that this result pertains +/// to. +template <typename IRUnitT> struct AnalysisResultConcept { + virtual ~AnalysisResultConcept() {} + + /// \brief Method to try and mark a result as invalid. + /// + /// When the outer analysis manager detects a change in some underlying + /// unit of the IR, it will call this method on all of the results cached. + /// + /// This method also receives a set of preserved analyses which can be used + /// to avoid invalidation because the pass which changed the underlying IR + /// took care to update or preserve the analysis result in some way. + /// + /// \returns true if the result is indeed invalid (the default). + virtual bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c ResultT provides an +/// \c invalidate member function. +template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template <typename T, bool (T::*)(IRUnitT, const PreservedAnalyses &)> + struct Checker; + + template <typename T> static SmallType f(Checker<T, &T::invalidate> *); + template <typename T> static BigType f(...); + +public: + enum { Value = sizeof(f<ResultT>(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief Wrapper to model the analysis result concept. +/// +/// By default, this will implement the invalidate method with a trivial +/// implementation so that the actual analysis result doesn't need to provide +/// an invalidation handler. It is only selected when the invalidation handler +/// is not part of the ResultT's interface. +template <typename IRUnitT, typename PassT, typename ResultT, + bool HasInvalidateHandler = + ResultHasInvalidateMethod<IRUnitT, ResultT>::Value> +struct AnalysisResultModel; + +/// \brief Specialization of \c AnalysisResultModel which provides the default +/// invalidate functionality. +template <typename IRUnitT, typename PassT, typename ResultT> +struct AnalysisResultModel<IRUnitT, PassT, ResultT, false> + : AnalysisResultConcept<IRUnitT> { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model bases invalidation solely on being in the preserved set. + // + // FIXME: We should actually use two different concepts for analysis results + // rather than two different models, and avoid the indirect function call for + // ones that use the trivial behavior. + bool invalidate(IRUnitT, const PreservedAnalyses &PA) override { + return !PA.preserved(PassT::ID()); + } + + ResultT Result; +}; + +/// \brief Specialization of \c AnalysisResultModel which delegates invalidate +/// handling to \c ResultT. +template <typename IRUnitT, typename PassT, typename ResultT> +struct AnalysisResultModel<IRUnitT, PassT, ResultT, true> + : AnalysisResultConcept<IRUnitT> { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model delegates to the \c ResultT method. + bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) override { + return Result.invalidate(IR, PA); + } + + ResultT Result; +}; + +/// \brief Abstract concept of an analysis pass. +/// +/// This concept is parameterized over the IR unit that it can run over and +/// produce an analysis result. +template <typename IRUnitT, typename AnalysisManagerT> +struct AnalysisPassConcept { + virtual ~AnalysisPassConcept() {} + + /// \brief Method to run this analysis over a unit of IR. + /// \returns A unique_ptr to the analysis result object to be queried by + /// users. + virtual std::unique_ptr<AnalysisResultConcept<IRUnitT>> + run(IRUnitT IR, AnalysisManagerT *AM) = 0; +}; + +/// \brief Wrapper to model the analysis pass concept. +/// +/// Can wrap any type which implements a suitable \c run method. The method +/// must accept the IRUnitT as an argument and produce an object which can be +/// wrapped in a \c AnalysisResultModel. +template <typename IRUnitT, typename AnalysisManagerT, typename PassT, + bool AcceptsAnalysisManager = PassRunAcceptsAnalysisManager< + IRUnitT, AnalysisManagerT, PassT, typename PassT::Result>::Value> +struct AnalysisPassModel; + +/// \brief Specialization of \c AnalysisPassModel which passes an +/// \c AnalysisManager to PassT's run method. +template <typename IRUnitT, typename AnalysisManagerT, typename PassT> +struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, true> + : AnalysisPassConcept<IRUnitT, AnalysisManagerT> { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + std::unique_ptr<AnalysisResultConcept<IRUnitT>> + run(IRUnitT IR, AnalysisManagerT *AM) override { + return make_unique<ResultModelT>(Pass.run(IR, AM)); + } + + PassT Pass; +}; + +/// \brief Specialization of \c AnalysisPassModel which does not pass an +/// \c AnalysisManager to PassT's run method. +template <typename IRUnitT, typename AnalysisManagerT, typename PassT> +struct AnalysisPassModel<IRUnitT, AnalysisManagerT, PassT, false> + : AnalysisPassConcept<IRUnitT, AnalysisManagerT> { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + std::unique_ptr<AnalysisResultConcept<IRUnitT>> + run(IRUnitT IR, AnalysisManagerT *) override { + return make_unique<ResultModelT>(Pass.run(IR)); + } + + PassT Pass; +}; + +} // End namespace detail + +class ModuleAnalysisManager; class ModulePassManager { public: - ModulePassManager(Module *M, AnalysisManager *AM = 0) : M(M), AM(AM) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + ModulePassManager() {} + ModulePassManager(ModulePassManager &&Arg) : Passes(std::move(Arg.Passes)) {} + ModulePassManager &operator=(ModulePassManager &&RHS) { + Passes = std::move(RHS.Passes); + return *this; + } + + /// \brief Run all of the module passes in this module pass manager over + /// a module. + /// + /// This method should only be called for a single module as there is the + /// expectation that the lifetime of a pass is bounded to that of a module. + PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM = nullptr); template <typename ModulePassT> void addPass(ModulePassT Pass) { - Passes.push_back(new ModulePassModel<ModulePassT>(llvm_move(Pass))); + Passes.emplace_back(new ModulePassModel<ModulePassT>(std::move(Pass))); } - void run(); + static StringRef name() { return "ModulePassManager"; } private: // Pull in the concept type and model template specialized for modules. - typedef detail::PassConcept<Module *> ModulePassConcept; + typedef detail::PassConcept<Module *, ModuleAnalysisManager> + ModulePassConcept; template <typename PassT> - struct ModulePassModel : detail::PassModel<Module *, PassT> { - ModulePassModel(PassT Pass) : detail::PassModel<Module *, PassT>(Pass) {} + struct ModulePassModel + : detail::PassModel<Module *, ModuleAnalysisManager, PassT> { + ModulePassModel(PassT Pass) + : detail::PassModel<Module *, ModuleAnalysisManager, PassT>( + std::move(Pass)) {} }; - Module *M; - AnalysisManager *AM; - std::vector<polymorphic_ptr<ModulePassConcept> > Passes; + ModulePassManager(const ModulePassManager &) LLVM_DELETED_FUNCTION; + ModulePassManager &operator=(const ModulePassManager &) LLVM_DELETED_FUNCTION; + + std::vector<std::unique_ptr<ModulePassConcept>> Passes; }; +class FunctionAnalysisManager; + class FunctionPassManager { public: - FunctionPassManager(AnalysisManager *AM = 0) : AM(AM) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + FunctionPassManager() {} + FunctionPassManager(FunctionPassManager &&Arg) + : Passes(std::move(Arg.Passes)) {} + FunctionPassManager &operator=(FunctionPassManager &&RHS) { + Passes = std::move(RHS.Passes); + return *this; + } template <typename FunctionPassT> void addPass(FunctionPassT Pass) { - Passes.push_back(new FunctionPassModel<FunctionPassT>(llvm_move(Pass))); + Passes.emplace_back(new FunctionPassModel<FunctionPassT>(std::move(Pass))); } - bool run(Module *M); + PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM = nullptr); + + static StringRef name() { return "FunctionPassManager"; } private: // Pull in the concept type and model template specialized for functions. - typedef detail::PassConcept<Function *> FunctionPassConcept; + typedef detail::PassConcept<Function *, FunctionAnalysisManager> + FunctionPassConcept; template <typename PassT> - struct FunctionPassModel : detail::PassModel<Function *, PassT> { + struct FunctionPassModel + : detail::PassModel<Function *, FunctionAnalysisManager, PassT> { FunctionPassModel(PassT Pass) - : detail::PassModel<Function *, PassT>(Pass) {} + : detail::PassModel<Function *, FunctionAnalysisManager, PassT>( + std::move(Pass)) {} }; - AnalysisManager *AM; - std::vector<polymorphic_ptr<FunctionPassConcept> > Passes; + FunctionPassManager(const FunctionPassManager &) LLVM_DELETED_FUNCTION; + FunctionPassManager & + operator=(const FunctionPassManager &) LLVM_DELETED_FUNCTION; + + std::vector<std::unique_ptr<FunctionPassConcept>> Passes; }; +namespace detail { -/// \brief An analysis manager to coordinate and cache analyses run over -/// a module. +/// \brief A CRTP base used to implement analysis managers. /// -/// The analysis manager is typically used by passes in a pass pipeline -/// (consisting potentially of several individual pass managers) over a module -/// of IR. It provides registration of available analyses, declaring -/// requirements on support for specific analyses, running of an specific -/// analysis over a specific unit of IR to compute an analysis result, and -/// caching of the analysis results to reuse them across multiple passes. +/// This class template serves as the boiler plate of an analysis manager. Any +/// analysis manager can be implemented on top of this base class. Any +/// implementation will be required to provide specific hooks: /// -/// It is the responsibility of callers to use the invalidation API to -/// invalidate analysis results when the IR they correspond to changes. The -/// \c ModulePassManager and \c FunctionPassManager do this automatically. -class AnalysisManager { -public: - AnalysisManager(Module *M) : M(M) {} +/// - getResultImpl +/// - getCachedResultImpl +/// - invalidateImpl +/// +/// The details of the call pattern are within. +template <typename DerivedT, typename IRUnitT> class AnalysisManagerBase { + DerivedT *derived_this() { return static_cast<DerivedT *>(this); } + const DerivedT *derived_this() const { + return static_cast<const DerivedT *>(this); + } + + AnalysisManagerBase(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + AnalysisManagerBase & + operator=(const AnalysisManagerBase &) LLVM_DELETED_FUNCTION; + +protected: + typedef detail::AnalysisResultConcept<IRUnitT> ResultConceptT; + typedef detail::AnalysisPassConcept<IRUnitT, DerivedT> PassConceptT; + + // FIXME: Provide template aliases for the models when we're using C++11 in + // a mode supporting them. + + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisManagerBase() {} + AnalysisManagerBase(AnalysisManagerBase &&Arg) + : AnalysisPasses(std::move(Arg.AnalysisPasses)) {} + AnalysisManagerBase &operator=(AnalysisManagerBase &&RHS) { + AnalysisPasses = std::move(RHS.AnalysisPasses); + return *this; + } +public: /// \brief Get the result of an analysis pass for this module. /// /// If there is not a valid cached result in the manager already, this will /// re-run the analysis to produce a valid result. - /// - /// The module passed in must be the same module as the analysis manager was - /// constructed around. - template <typename PassT> - const typename PassT::Result &getResult(Module *M) { - assert(ModuleAnalysisPasses.count(PassT::ID()) && + template <typename PassT> typename PassT::Result &getResult(IRUnitT IR) { + assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); - const AnalysisResultConcept<Module> &ResultConcept = - getResultImpl(PassT::ID(), M); - typedef AnalysisResultModel<Module, typename PassT::Result> ResultModelT; - return static_cast<const ResultModelT &>(ResultConcept).Result; + ResultConceptT &ResultConcept = + derived_this()->getResultImpl(PassT::ID(), IR); + typedef detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> + ResultModelT; + return static_cast<ResultModelT &>(ResultConcept).Result; } - /// \brief Get the result of an analysis pass for a function. + /// \brief Get the cached result of an analysis pass for this module. /// - /// If there is not a valid cached result in the manager already, this will - /// re-run the analysis to produce a valid result. + /// This method never runs the analysis. + /// + /// \returns null if there is no cached result. template <typename PassT> - const typename PassT::Result &getResult(Function *F) { - assert(FunctionAnalysisPasses.count(PassT::ID()) && + typename PassT::Result *getCachedResult(IRUnitT IR) const { + assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); - const AnalysisResultConcept<Function> &ResultConcept = - getResultImpl(PassT::ID(), F); - typedef AnalysisResultModel<Function, typename PassT::Result> ResultModelT; - return static_cast<const ResultModelT &>(ResultConcept).Result; + ResultConceptT *ResultConcept = + derived_this()->getCachedResultImpl(PassT::ID(), IR); + if (!ResultConcept) + return nullptr; + + typedef detail::AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> + ResultModelT; + return &static_cast<ResultModelT *>(ResultConcept)->Result; } /// \brief Register an analysis pass with the manager. /// - /// This provides an initialized and set-up analysis pass to the - /// analysis - /// manager. Whomever is setting up analysis passes must use this to - /// populate + /// This provides an initialized and set-up analysis pass to the analysis + /// manager. Whomever is setting up analysis passes must use this to populate /// the manager with all of the analysis passes available. - template <typename PassT> void registerAnalysisPass(PassT Pass) { - registerAnalysisPassImpl<PassT>(llvm_move(Pass)); + template <typename PassT> void registerPass(PassT Pass) { + assert(!AnalysisPasses.count(PassT::ID()) && + "Registered the same analysis pass twice!"); + typedef detail::AnalysisPassModel<IRUnitT, DerivedT, PassT> PassModelT; + AnalysisPasses[PassT::ID()].reset(new PassModelT(std::move(Pass))); } /// \brief Invalidate a specific analysis pass for an IR module. /// /// Note that the analysis result can disregard invalidation. template <typename PassT> void invalidate(Module *M) { - invalidateImpl(PassT::ID(), M); + assert(AnalysisPasses.count(PassT::ID()) && + "This analysis pass was not registered prior to being invalidated"); + derived_this()->invalidateImpl(PassT::ID(), M); } - /// \brief Invalidate a specific analysis pass for an IR function. + /// \brief Invalidate analyses cached for an IR unit. /// - /// Note that the analysis result can disregard invalidation. - template <typename PassT> void invalidate(Function *F) { - invalidateImpl(PassT::ID(), F); + /// Walk through all of the analyses pertaining to this unit of IR and + /// invalidate them unless they are preserved by the PreservedAnalyses set. + void invalidate(IRUnitT IR, const PreservedAnalyses &PA) { + derived_this()->invalidateImpl(IR, PA); } - /// \brief Invalidate analyses cached for an IR Module. - /// - /// Note that specific analysis results can disregard invalidation by - /// overriding their invalidate method. - /// - /// The module must be the module this analysis manager was constructed - /// around. - void invalidateAll(Module *M); +protected: + /// \brief Lookup a registered analysis pass. + PassConceptT &lookupPass(void *PassID) { + typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(PassID); + assert(PI != AnalysisPasses.end() && + "Analysis passes must be registered prior to being queried!"); + return *PI->second; + } - /// \brief Invalidate analyses cached for an IR Function. - /// - /// Note that specific analysis results can disregard invalidation by - /// overriding the invalidate method. - void invalidateAll(Function *F); + /// \brief Lookup a registered analysis pass. + const PassConceptT &lookupPass(void *PassID) const { + typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(PassID); + assert(PI != AnalysisPasses.end() && + "Analysis passes must be registered prior to being queried!"); + return *PI->second; + } private: - /// \brief Abstract concept of an analysis result. - /// - /// This concept is parameterized over the IR unit that this result pertains - /// to. - template <typename IRUnitT> struct AnalysisResultConcept { - virtual ~AnalysisResultConcept() {} - virtual AnalysisResultConcept *clone() = 0; - - /// \brief Method to try and mark a result as invalid. - /// - /// When the outer \c AnalysisManager detects a change in some underlying - /// unit of the IR, it will call this method on all of the results cached. - /// - /// \returns true if the result should indeed be invalidated (the default). - virtual bool invalidate(IRUnitT *IR) = 0; - }; - - /// \brief Wrapper to model the analysis result concept. - /// - /// Can wrap any type which implements a suitable invalidate member and model - /// the AnalysisResultConcept for the AnalysisManager. - template <typename IRUnitT, typename ResultT> - struct AnalysisResultModel : AnalysisResultConcept<IRUnitT> { - AnalysisResultModel(ResultT Result) : Result(llvm_move(Result)) {} - virtual AnalysisResultModel *clone() { - return new AnalysisResultModel(Result); - } - - /// \brief The model delegates to the \c ResultT method. - virtual bool invalidate(IRUnitT *IR) { return Result.invalidate(IR); } - - ResultT Result; - }; - - /// \brief Abstract concept of an analysis pass. - /// - /// This concept is parameterized over the IR unit that it can run over and - /// produce an analysis result. - template <typename IRUnitT> struct AnalysisPassConcept { - virtual ~AnalysisPassConcept() {} - virtual AnalysisPassConcept *clone() = 0; - - /// \brief Method to run this analysis over a unit of IR. - /// \returns The analysis result object to be queried by users, the caller - /// takes ownership. - virtual AnalysisResultConcept<IRUnitT> *run(IRUnitT *IR) = 0; - }; - - /// \brief Wrapper to model the analysis pass concept. - /// - /// Can wrap any type which implements a suitable \c run method. The method - /// must accept the IRUnitT as an argument and produce an object which can be - /// wrapped in a \c AnalysisResultModel. - template <typename PassT> - struct AnalysisPassModel : AnalysisPassConcept<typename PassT::IRUnitT> { - AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {} - virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); } + /// \brief Map type from module analysis pass ID to pass concept pointer. + typedef DenseMap<void *, std::unique_ptr<PassConceptT>> AnalysisPassMapT; - // FIXME: Replace PassT::IRUnitT with type traits when we use C++11. - typedef typename PassT::IRUnitT IRUnitT; + /// \brief Collection of module analysis passes, indexed by ID. + AnalysisPassMapT AnalysisPasses; +}; - // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel<IRUnitT, typename PassT::Result> ResultModelT; +} // End namespace detail - /// \brief The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - virtual ResultModelT *run(IRUnitT *IR) { - return new ResultModelT(Pass.run(IR)); - } +/// \brief A module analysis pass manager with lazy running and caching of +/// results. +class ModuleAnalysisManager + : public detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> { + friend class detail::AnalysisManagerBase<ModuleAnalysisManager, Module *>; + typedef detail::AnalysisManagerBase<ModuleAnalysisManager, Module *> BaseT; + typedef BaseT::ResultConceptT ResultConceptT; + typedef BaseT::PassConceptT PassConceptT; - PassT Pass; - }; +public: + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + ModuleAnalysisManager() {} + ModuleAnalysisManager(ModuleAnalysisManager &&Arg) + : BaseT(std::move(static_cast<BaseT &>(Arg))), + ModuleAnalysisResults(std::move(Arg.ModuleAnalysisResults)) {} + ModuleAnalysisManager &operator=(ModuleAnalysisManager &&RHS) { + BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); + ModuleAnalysisResults = std::move(RHS.ModuleAnalysisResults); + return *this; + } +private: + ModuleAnalysisManager(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; + ModuleAnalysisManager & + operator=(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; /// \brief Get a module pass result, running the pass if necessary. - const AnalysisResultConcept<Module> &getResultImpl(void *PassID, Module *M); + ResultConceptT &getResultImpl(void *PassID, Module *M); - /// \brief Get a function pass result, running the pass if necessary. - const AnalysisResultConcept<Function> &getResultImpl(void *PassID, - Function *F); + /// \brief Get a cached module pass result or return null. + ResultConceptT *getCachedResultImpl(void *PassID, Module *M) const; /// \brief Invalidate a module pass result. void invalidateImpl(void *PassID, Module *M); - /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, Function *F); + /// \brief Invalidate results across a module. + void invalidateImpl(Module *M, const PreservedAnalyses &PA); + /// \brief Map type from module analysis pass ID to pass result concept + /// pointer. + typedef DenseMap<void *, + std::unique_ptr<detail::AnalysisResultConcept<Module *>>> + ModuleAnalysisResultMapT; - /// \brief Module pass specific implementation of registration. - template <typename PassT> - typename enable_if<is_same<typename PassT::IRUnitT, Module> >::type - registerAnalysisPassImpl(PassT Pass) { - assert(!ModuleAnalysisPasses.count(PassT::ID()) && - "Registered the same analysis pass twice!"); - ModuleAnalysisPasses[PassT::ID()] = - new AnalysisPassModel<PassT>(llvm_move(Pass)); - } + /// \brief Cache of computed module analysis results for this module. + ModuleAnalysisResultMapT ModuleAnalysisResults; +}; - /// \brief Function pass specific implementation of registration. - template <typename PassT> - typename enable_if<is_same<typename PassT::IRUnitT, Function> >::type - registerAnalysisPassImpl(PassT Pass) { - assert(!FunctionAnalysisPasses.count(PassT::ID()) && - "Registered the same analysis pass twice!"); - FunctionAnalysisPasses[PassT::ID()] = - new AnalysisPassModel<PassT>(llvm_move(Pass)); - } +/// \brief A function analysis manager to coordinate and cache analyses run over +/// a module. +class FunctionAnalysisManager + : public detail::AnalysisManagerBase<FunctionAnalysisManager, Function *> { + friend class detail::AnalysisManagerBase<FunctionAnalysisManager, Function *>; + typedef detail::AnalysisManagerBase<FunctionAnalysisManager, Function *> + BaseT; + typedef BaseT::ResultConceptT ResultConceptT; + typedef BaseT::PassConceptT PassConceptT; +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. + FunctionAnalysisManager() {} + FunctionAnalysisManager(FunctionAnalysisManager &&Arg) + : BaseT(std::move(static_cast<BaseT &>(Arg))), + FunctionAnalysisResults(std::move(Arg.FunctionAnalysisResults)) {} + FunctionAnalysisManager &operator=(FunctionAnalysisManager &&RHS) { + BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); + FunctionAnalysisResults = std::move(RHS.FunctionAnalysisResults); + return *this; + } - /// \brief Map type from module analysis pass ID to pass concept pointer. - typedef DenseMap<void *, polymorphic_ptr<AnalysisPassConcept<Module> > > - ModuleAnalysisPassMapT; + /// \brief Returns true if the analysis manager has an empty results cache. + bool empty() const; - /// \brief Collection of module analysis passes, indexed by ID. - ModuleAnalysisPassMapT ModuleAnalysisPasses; + /// \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(); - /// \brief Map type from module analysis pass ID to pass result concept pointer. - typedef DenseMap<void *, polymorphic_ptr<AnalysisResultConcept<Module> > > - ModuleAnalysisResultMapT; +private: + FunctionAnalysisManager(const FunctionAnalysisManager &) + LLVM_DELETED_FUNCTION; + FunctionAnalysisManager & + operator=(const FunctionAnalysisManager &) LLVM_DELETED_FUNCTION; - /// \brief Cache of computed module analysis results for this module. - ModuleAnalysisResultMapT ModuleAnalysisResults; + /// \brief Get a function pass result, running the pass if necessary. + ResultConceptT &getResultImpl(void *PassID, Function *F); + /// \brief Get a cached function pass result or return null. + ResultConceptT *getCachedResultImpl(void *PassID, Function *F) const; - /// \brief Map type from function analysis pass ID to pass concept pointer. - typedef DenseMap<void *, polymorphic_ptr<AnalysisPassConcept<Function> > > - FunctionAnalysisPassMapT; + /// \brief Invalidate a function pass result. + void invalidateImpl(void *PassID, Function *F); - /// \brief Collection of function analysis passes, indexed by ID. - FunctionAnalysisPassMapT FunctionAnalysisPasses; + /// \brief Invalidate the results for a function.. + void invalidateImpl(Function *F, 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 *, polymorphic_ptr<AnalysisResultConcept<Function> > > > - FunctionAnalysisResultListT; + typedef std::list<std::pair< + void *, std::unique_ptr<detail::AnalysisResultConcept<Function *>>>> + FunctionAnalysisResultListT; /// \brief Map type from function pointer to our custom list type. - typedef DenseMap<Function *, FunctionAnalysisResultListT> FunctionAnalysisResultListMapT; + typedef DenseMap<Function *, FunctionAnalysisResultListT> + FunctionAnalysisResultListMapT; /// \brief Map from function to a list of function analysis results. /// @@ -370,14 +805,230 @@ private: /// iterator into a particular result list. typedef DenseMap<std::pair<void *, Function *>, FunctionAnalysisResultListT::iterator> - FunctionAnalysisResultMapT; + FunctionAnalysisResultMapT; /// \brief Map from an analysis ID and function to a particular cached /// analysis result. FunctionAnalysisResultMapT FunctionAnalysisResults; +}; + +/// \brief A module analysis which acts as a proxy for a function analysis +/// manager. +/// +/// This primarily proxies invalidation information from the module analysis +/// manager and module pass manager to a function analysis manager. You should +/// never use a function analysis manager from within (transitively) a module +/// pass manager unless your parent module pass has received a proxy result +/// object for it. +class FunctionAnalysisManagerModuleProxy { +public: + class Result; + + static void *ID() { return (void *)&PassID; } + + explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM) + : FAM(&FAM) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + FunctionAnalysisManagerModuleProxy( + const FunctionAnalysisManagerModuleProxy &Arg) + : FAM(Arg.FAM) {} + FunctionAnalysisManagerModuleProxy(FunctionAnalysisManagerModuleProxy &&Arg) + : FAM(std::move(Arg.FAM)) {} + FunctionAnalysisManagerModuleProxy & + operator=(FunctionAnalysisManagerModuleProxy RHS) { + std::swap(FAM, RHS.FAM); + return *this; + } + + /// \brief Run the analysis pass and create our proxy result object. + /// + /// This doesn't do any interesting work, it is primarily used to insert our + /// proxy result object into the module analysis cache so that we can proxy + /// invalidation to the function analysis manager. + /// + /// In debug builds, it will also assert that the analysis manager is empty + /// as no queries should arrive at the function analysis manager prior to + /// this analysis being requested. + Result run(Module *M); + +private: + static char PassID; + + FunctionAnalysisManager *FAM; +}; + +/// \brief The result proxy object for the +/// \c FunctionAnalysisManagerModuleProxy. +/// +/// See its documentation for more information. +class FunctionAnalysisManagerModuleProxy::Result { +public: + explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + Result(const Result &Arg) : FAM(Arg.FAM) {} + Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {} + Result &operator=(Result RHS) { + std::swap(FAM, RHS.FAM); + return *this; + } + ~Result(); + + /// \brief Accessor for the \c FunctionAnalysisManager. + FunctionAnalysisManager &getManager() { return *FAM; } + + /// \brief Handler for invalidation of the module. + /// + /// If this analysis itself is preserved, then we assume that the set of \c + /// Function objects in the \c Module hasn't changed and thus we don't need + /// to invalidate *all* cached data associated with a \c Function* in the \c + /// FunctionAnalysisManager. + /// + /// Regardless of whether this analysis is marked as preserved, all of the + /// analyses in the \c FunctionAnalysisManager are potentially invalidated + /// based on the set of preserved analyses. + bool invalidate(Module *M, const PreservedAnalyses &PA); + +private: + FunctionAnalysisManager *FAM; +}; + +/// \brief A function analysis which acts as a proxy for a module analysis +/// manager. +/// +/// This primarily provides an accessor to a parent module analysis manager to +/// function passes. Only the const interface of the module analysis manager is +/// provided to indicate that once inside of a function analysis pass you +/// cannot request a module analysis to actually run. Instead, the user must +/// rely on the \c getCachedResult API. +/// +/// This proxy *doesn't* manage the invalidation in any way. That is handled by +/// the recursive return path of each layer of the pass manager and the +/// returned PreservedAnalysis set. +class ModuleAnalysisManagerFunctionProxy { +public: + /// \brief Result proxy object for \c ModuleAnalysisManagerFunctionProxy. + class Result { + public: + explicit Result(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} + // We have to explicitly define all the special member functions because + // MSVC refuses to generate them. + Result(const Result &Arg) : MAM(Arg.MAM) {} + Result(Result &&Arg) : MAM(std::move(Arg.MAM)) {} + Result &operator=(Result RHS) { + std::swap(MAM, RHS.MAM); + return *this; + } + + const ModuleAnalysisManager &getManager() const { return *MAM; } + + /// \brief Handle invalidation by ignoring it, this pass is immutable. + bool invalidate(Function *) { return false; } + + private: + const ModuleAnalysisManager *MAM; + }; - /// \brief Module handle for the \c AnalysisManager. - Module *M; + static void *ID() { return (void *)&PassID; } + + ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM) + : MAM(&MAM) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + ModuleAnalysisManagerFunctionProxy( + const ModuleAnalysisManagerFunctionProxy &Arg) + : MAM(Arg.MAM) {} + ModuleAnalysisManagerFunctionProxy(ModuleAnalysisManagerFunctionProxy &&Arg) + : MAM(std::move(Arg.MAM)) {} + ModuleAnalysisManagerFunctionProxy & + operator=(ModuleAnalysisManagerFunctionProxy RHS) { + std::swap(MAM, RHS.MAM); + return *this; + } + + /// \brief Run the analysis pass and create our proxy result object. + /// Nothing to see here, it just forwards the \c MAM reference into the + /// result. + Result run(Function *) { return Result(*MAM); } + +private: + static char PassID; + + const ModuleAnalysisManager *MAM; }; +/// \brief Trivial adaptor that maps from a module to its functions. +/// +/// Designed to allow composition of a FunctionPass(Manager) and +/// a ModulePassManager. Note that if this pass is constructed with a pointer +/// to a \c ModuleAnalysisManager it will run the +/// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function +/// pass over the module to enable a \c FunctionAnalysisManager to be used +/// within this run safely. +template <typename FunctionPassT> class ModuleToFunctionPassAdaptor { +public: + explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass) + : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + ModuleToFunctionPassAdaptor(const ModuleToFunctionPassAdaptor &Arg) + : Pass(Arg.Pass) {} + ModuleToFunctionPassAdaptor(ModuleToFunctionPassAdaptor &&Arg) + : Pass(std::move(Arg.Pass)) {} + friend void swap(ModuleToFunctionPassAdaptor &LHS, ModuleToFunctionPassAdaptor &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + ModuleToFunctionPassAdaptor &operator=(ModuleToFunctionPassAdaptor RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief Runs the function pass across every function in the module. + PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + FunctionAnalysisManager *FAM = nullptr; + if (AM) + // Setup the function analysis manager from its proxy. + FAM = &AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); + + PreservedAnalyses PA = PreservedAnalyses::all(); + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { + PreservedAnalyses PassPA = Pass.run(I, FAM); + + // 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. + if (FAM) + FAM->invalidate(I, PassPA); + + // Then intersect the preserved set so that invalidation of module + // analyses will eventually occur when the module pass completes. + PA.intersect(std::move(PassPA)); + } + + // By definition we preserve the proxy. This precludes *any* invalidation + // of function analyses by the proxy, but that's OK because we've taken + // care to invalidate analyses in the function analysis manager + // incrementally above. + PA.preserve<FunctionAnalysisManagerModuleProxy>(); + return PA; + } + + static StringRef name() { return "ModuleToFunctionPassAdaptor"; } + +private: + FunctionPassT Pass; +}; + +/// \brief A function to deduce a function pass type and wrap it in the +/// templated adaptor. +template <typename FunctionPassT> +ModuleToFunctionPassAdaptor<FunctionPassT> +createModuleToFunctionPassAdaptor(FunctionPassT Pass) { + return std::move(ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); } + +} + +#endif diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 240bb81d31a7..2efb29489473 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -1,4 +1,4 @@ -//===-- llvm/Support/PatternMatch.h - Match on the LLVM IR ------*- C++ -*-===// +//===- PatternMatch.h - Match on the LLVM IR --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -26,14 +26,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_PATTERNMATCH_H -#define LLVM_SUPPORT_PATTERNMATCH_H +#ifndef LLVM_IR_PATTERNMATCH_H +#define LLVM_IR_PATTERNMATCH_H +#include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Operator.h" -#include "llvm/Support/CallSite.h" namespace llvm { namespace PatternMatch { @@ -498,6 +498,96 @@ m_AShr(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R); } +template<typename LHS_t, typename RHS_t, unsigned Opcode, unsigned WrapFlags = 0> +struct OverflowingBinaryOp_match { + LHS_t L; + RHS_t R; + + OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template<typename OpTy> + bool match(OpTy *V) { + if (OverflowingBinaryOperator *Op = dyn_cast<OverflowingBinaryOperator>(V)) { + if (Op->getOpcode() != Opcode) + return false; + if (WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap && + !Op->hasNoUnsignedWrap()) + return false; + if (WrapFlags & OverflowingBinaryOperator::NoSignedWrap && + !Op->hasNoSignedWrap()) + return false; + return L.match(Op->getOperand(0)) && R.match(Op->getOperand(1)); + } + return false; + } +}; + +template <typename LHS, typename RHS> +inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Add, + OverflowingBinaryOperator::NoSignedWrap> +m_NSWAdd(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match<LHS, RHS, Instruction::Add, + OverflowingBinaryOperator::NoSignedWrap>( + L, R); +} +template <typename LHS, typename RHS> +inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Sub, + OverflowingBinaryOperator::NoSignedWrap> +m_NSWSub(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match<LHS, RHS, Instruction::Sub, + OverflowingBinaryOperator::NoSignedWrap>( + L, R); +} +template <typename LHS, typename RHS> +inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Mul, + OverflowingBinaryOperator::NoSignedWrap> +m_NSWMul(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match<LHS, RHS, Instruction::Mul, + OverflowingBinaryOperator::NoSignedWrap>( + L, R); +} +template <typename LHS, typename RHS> +inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Shl, + OverflowingBinaryOperator::NoSignedWrap> +m_NSWShl(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match<LHS, RHS, Instruction::Shl, + OverflowingBinaryOperator::NoSignedWrap>( + L, R); +} + +template <typename LHS, typename RHS> +inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Add, + OverflowingBinaryOperator::NoUnsignedWrap> +m_NUWAdd(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match<LHS, RHS, Instruction::Add, + OverflowingBinaryOperator::NoUnsignedWrap>( + L, R); +} +template <typename LHS, typename RHS> +inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Sub, + OverflowingBinaryOperator::NoUnsignedWrap> +m_NUWSub(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match<LHS, RHS, Instruction::Sub, + OverflowingBinaryOperator::NoUnsignedWrap>( + L, R); +} +template <typename LHS, typename RHS> +inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Mul, + OverflowingBinaryOperator::NoUnsignedWrap> +m_NUWMul(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match<LHS, RHS, Instruction::Mul, + OverflowingBinaryOperator::NoUnsignedWrap>( + L, R); +} +template <typename LHS, typename RHS> +inline OverflowingBinaryOp_match<LHS, RHS, Instruction::Shl, + OverflowingBinaryOperator::NoUnsignedWrap> +m_NUWShl(const LHS &L, const RHS &R) { + return OverflowingBinaryOp_match<LHS, RHS, Instruction::Shl, + OverflowingBinaryOperator::NoUnsignedWrap>( + L, R); +} + //===----------------------------------------------------------------------===// // Class that matches two different binary ops. // diff --git a/include/llvm/Support/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h index c5fb78050106..02bc583a255a 100644 --- a/include/llvm/Support/PredIteratorCache.h +++ b/include/llvm/IR/PredIteratorCache.h @@ -1,4 +1,4 @@ -//===- llvm/Support/PredIteratorCache.h - pred_iterator Cache ---*- C++ -*-===// +//===- PredIteratorCache.h - pred_iterator Cache ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,11 +13,11 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/CFG.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/CFG.h" -#ifndef LLVM_SUPPORT_PREDITERATORCACHE_H -#define LLVM_SUPPORT_PREDITERATORCACHE_H +#ifndef LLVM_IR_PREDITERATORCACHE_H +#define LLVM_IR_PREDITERATORCACHE_H namespace llvm { @@ -44,7 +44,7 @@ namespace llvm { if (Entry) return Entry; SmallVector<BasicBlock*, 32> PredCache(pred_begin(BB), pred_end(BB)); - PredCache.push_back(0); // null terminator. + PredCache.push_back(nullptr); // null terminator. BlockToPredCountMap[BB] = PredCache.size()-1; diff --git a/include/llvm/IR/SymbolTableListTraits.h b/include/llvm/IR/SymbolTableListTraits.h index 561ce010c0e0..0a5149c3d938 100644 --- a/include/llvm/IR/SymbolTableListTraits.h +++ b/include/llvm/IR/SymbolTableListTraits.h @@ -46,19 +46,19 @@ public: /// getListOwner - Return the object that owns this list. If this is a list /// of instructions, it returns the BasicBlock that owns them. ItemParentClass *getListOwner() { - size_t Offset(size_t(&((ItemParentClass*)0->*ItemParentClass:: - getSublistAccess(static_cast<ValueSubClass*>(0))))); + size_t Offset(size_t(&((ItemParentClass*)nullptr->*ItemParentClass:: + getSublistAccess(static_cast<ValueSubClass*>(nullptr))))); iplist<ValueSubClass>* Anchor(static_cast<iplist<ValueSubClass>*>(this)); return reinterpret_cast<ItemParentClass*>(reinterpret_cast<char*>(Anchor)- Offset); } static iplist<ValueSubClass> &getList(ItemParentClass *Par) { - return Par->*(Par->getSublistAccess((ValueSubClass*)0)); + return Par->*(Par->getSublistAccess((ValueSubClass*)nullptr)); } static ValueSymbolTable *getSymTab(ItemParentClass *Par) { - return Par ? toPtr(Par->getValueSymbolTable()) : 0; + return Par ? toPtr(Par->getValueSymbolTable()) : nullptr; } void addNodeToList(ValueSubClass *V); diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index 3cfb84edd824..7955587e3c76 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -15,12 +15,13 @@ #ifndef LLVM_IR_TYPE_H #define LLVM_IR_TYPE_H +#include "llvm-c/Core.h" #include "llvm/ADT/APFloat.h" -#include "llvm/Support/Casting.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm-c/Core.h" namespace llvm { @@ -70,11 +71,7 @@ public: StructTyID, ///< 12: Structures ArrayTyID, ///< 13: Arrays PointerTyID, ///< 14: Pointers - VectorTyID, ///< 15: SIMD 'packed' format, or other vector type - - NumTypeIDs, // Must remain as last defined ID - LastPrimitiveTyID = X86_MMXTyID, - FirstDerivedTyID = IntegerTyID + VectorTyID ///< 15: SIMD 'packed' format, or other vector type }; private: @@ -91,7 +88,7 @@ protected: friend class LLVMContextImpl; explicit Type(LLVMContext &C, TypeID tid) : Context(C), IDAndSubclassData(0), - NumContainedTys(0), ContainedTys(0) { + NumContainedTys(0), ContainedTys(nullptr) { setTypeID(tid); } ~Type() {} @@ -239,12 +236,6 @@ public: /// elements or all its elements are empty. bool isEmptyTy() const; - /// Here are some useful little methods to query what type derived types are - /// Note that all other types can just compare to see if this == Type::xxxTy; - /// - bool isPrimitiveType() const { return getTypeID() <= LastPrimitiveTyID; } - bool isDerivedType() const { return getTypeID() >= FirstDerivedTyID; } - /// isFirstClassType - Return true if the type is "first class", meaning it /// is a valid type for a Value. /// @@ -257,9 +248,8 @@ public: /// and array types. /// bool isSingleValueType() const { - return (getTypeID() != VoidTyID && isPrimitiveType()) || - getTypeID() == IntegerTyID || getTypeID() == PointerTyID || - getTypeID() == VectorTyID; + return isFloatingPointTy() || isX86_MMXTy() || isIntegerTy() || + isPointerTy() || isVectorTy(); } /// isAggregateType - Return true if the type is an aggregate type. This @@ -275,7 +265,7 @@ public: /// get the actual size for a particular target, it is reasonable to use the /// DataLayout subsystem to do this. /// - bool isSized() const { + bool isSized(SmallPtrSet<const Type*, 4> *Visited = nullptr) const { // If it's a primitive, it is always sized. if (getTypeID() == IntegerTyID || isFloatingPointTy() || getTypeID() == PointerTyID || @@ -287,7 +277,7 @@ public: getTypeID() != VectorTyID) return false; // Otherwise we have to try harder to decide. - return isSizedDerivedType(); + return isSizedDerivedType(Visited); } /// getPrimitiveSizeInBits - Return the basic size of this type if it is a @@ -300,12 +290,12 @@ public: /// instance of the type is stored to memory. The DataLayout class provides /// additional query functions to provide this information. /// - unsigned getPrimitiveSizeInBits() const; + unsigned getPrimitiveSizeInBits() const LLVM_READONLY; /// getScalarSizeInBits - If this is a vector type, return the /// getPrimitiveSizeInBits value for the element type. Otherwise return the /// getPrimitiveSizeInBits value for this type. - unsigned getScalarSizeInBits(); + unsigned getScalarSizeInBits() const LLVM_READONLY; /// getFPMantissaWidth - Return the width of the mantissa of this type. This /// is only valid on floating point types. If the FP type does not @@ -314,8 +304,8 @@ public: /// getScalarType - If this is a vector type, return the element type, /// otherwise return 'this'. - const Type *getScalarType() const; - Type *getScalarType(); + const Type *getScalarType() const LLVM_READONLY; + Type *getScalarType() LLVM_READONLY; //===--------------------------------------------------------------------===// // Type Iteration support. @@ -429,7 +419,7 @@ private: /// isSizedDerivedType - Derived types like structures and arrays are sized /// iff all of the members of the type are sized as well. Since asking for /// their size is relatively uncommon, move this operation out of line. - bool isSizedDerivedType() const; + bool isSizedDerivedType(SmallPtrSet<const Type*, 4> *Visited = nullptr) const; }; // Printing of types. diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 12cd150af4c8..033cd3e2f5da 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -6,29 +6,29 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This defines the Use class. The Use class represents the operand of an -// instruction or some other User instance which refers to a Value. The Use -// class keeps the "use list" of the referenced value up to date. -// -// Pointer tagging is used to efficiently find the User corresponding -// to a Use without having to store a User pointer in every Use. A -// User is preceded in memory by all the Uses corresponding to its -// operands, and the low bits of one of the fields (Prev) of the Use -// class are used to encode offsets to be able to find that User given -// a pointer to any Use. For details, see: -// -// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout -// +/// \file +/// +/// This defines the Use class. The Use class represents the operand of an +/// instruction or some other User instance which refers to a Value. The Use +/// class keeps the "use list" of the referenced value up to date. +/// +/// Pointer tagging is used to efficiently find the User corresponding to a Use +/// without having to store a User pointer in every Use. A User is preceded in +/// memory by all the Uses corresponding to its operands, and the low bits of +/// one of the fields (Prev) of the Use class are used to encode offsets to be +/// able to find that User given a pointer to any Use. For details, see: +/// +/// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout +/// //===----------------------------------------------------------------------===// #ifndef LLVM_IR_USE_H #define LLVM_IR_USE_H +#include "llvm-c/Core.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" -#include "llvm-c/Core.h" #include <cstddef> #include <iterator> @@ -37,64 +37,67 @@ namespace llvm { class Value; class User; class Use; -template<typename> -struct simplify_type; +template <typename> struct simplify_type; // Use** is only 4-byte aligned. -template<> -class PointerLikeTypeTraits<Use**> { +template <> class PointerLikeTypeTraits<Use **> { public: - static inline void *getAsVoidPointer(Use** P) { return P; } + static inline void *getAsVoidPointer(Use **P) { return P; } static inline Use **getFromVoidPointer(void *P) { - return static_cast<Use**>(P); + return static_cast<Use **>(P); } enum { NumLowBitsAvailable = 2 }; }; -//===----------------------------------------------------------------------===// -// Use Class -//===----------------------------------------------------------------------===// - -/// Use is here to make keeping the "use" list of a Value up-to-date really -/// easy. +/// \brief A Use represents the edge between a Value definition and its users. +/// +/// This is notionally a two-dimensional linked list. It supports traversing +/// all of the uses for a particular value definition. It also supports jumping +/// directly to the used value when we arrive from the User's operands, and +/// jumping directly to the User when we arrive from the Value's uses. +/// +/// The pointer to the used Value is explicit, and the pointer to the User is +/// implicit. The implicit pointer is found via a waymarking algorithm +/// described in the programmer's manual: +/// +/// http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm +/// +/// This is essentially the single most memory intensive object in LLVM because +/// of the number of uses in the system. At the same time, the constant time +/// operations it allows are essential to many optimizations having reasonable +/// time complexity. class Use { public: - /// swap - provide a fast substitute to std::swap<Use> + /// \brief Provide a fast substitute to std::swap<Use> /// that also works with less standard-compliant compilers void swap(Use &RHS); // A type for the word following an array of hung-off Uses in memory, which is // a pointer back to their User with the bottom bit set. - typedef PointerIntPair<User*, 1, unsigned> UserRef; + typedef PointerIntPair<User *, 1, unsigned> UserRef; private: Use(const Use &U) LLVM_DELETED_FUNCTION; /// Destructor - Only for zap() ~Use() { - if (Val) removeFromList(); + if (Val) + removeFromList(); } - enum PrevPtrTag { zeroDigitTag - , oneDigitTag - , stopTag - , fullStopTag }; + enum PrevPtrTag { zeroDigitTag, oneDigitTag, stopTag, fullStopTag }; /// Constructor - Use(PrevPtrTag tag) : Val(0) { - Prev.setInt(tag); - } + Use(PrevPtrTag tag) : Val(nullptr) { Prev.setInt(tag); } public: - /// Normally Use will just implicitly convert to a Value* that it holds. - operator Value*() const { return Val; } - - /// If implicit conversion to Value* doesn't work, the get() method returns - /// the Value*. + operator Value *() const { return Val; } Value *get() const { return Val; } - - /// getUser - This returns the User that contains this Use. For an - /// instruction operand, for example, this will return the instruction. + + /// \brief Returns the User that contains this Use. + /// + /// For an instruction operand, for example, this will return the + /// instruction. User *getUser() const; inline void set(Value *Val); @@ -108,116 +111,63 @@ public: return *this; } - Value *operator->() { return Val; } + Value *operator->() { return Val; } const Value *operator->() const { return Val; } Use *getNext() const { return Next; } - - /// initTags - initialize the waymarking tags on an array of Uses, so that - /// getUser() can find the User from any of those Uses. + /// \brief Return the operand # of this use in its User. + unsigned getOperandNo() const; + + /// \brief Initializes the waymarking tags on an array of Uses. + /// + /// This sets up the array of Uses such that getUser() can find the User from + /// any of those Uses. static Use *initTags(Use *Start, Use *Stop); - /// zap - This is used to destroy Use operands when the number of operands of + /// \brief Destroys Use operands when the number of operands of /// a User changes. static void zap(Use *Start, const Use *Stop, bool del = false); private: - const Use* getImpliedUser() const; - + const Use *getImpliedUser() const; + Value *Val; Use *Next; - PointerIntPair<Use**, 2, PrevPtrTag> Prev; + PointerIntPair<Use **, 2, PrevPtrTag> Prev; - void setPrev(Use **NewPrev) { - Prev.setPointer(NewPrev); - } + void setPrev(Use **NewPrev) { Prev.setPointer(NewPrev); } void addToList(Use **List) { Next = *List; - if (Next) Next->setPrev(&Next); + if (Next) + Next->setPrev(&Next); setPrev(List); *List = this; } void removeFromList() { Use **StrippedPrev = Prev.getPointer(); *StrippedPrev = Next; - if (Next) Next->setPrev(StrippedPrev); + if (Next) + Next->setPrev(StrippedPrev); } friend class Value; }; -// simplify_type - Allow clients to treat uses just like values when using -// casting operators. -template<> struct simplify_type<Use> { - typedef Value* SimpleType; - static SimpleType getSimplifiedValue(Use &Val) { - return Val.get(); - } +/// \brief Allow clients to treat uses just like values when using +/// casting operators. +template <> struct simplify_type<Use> { + typedef Value *SimpleType; + static SimpleType getSimplifiedValue(Use &Val) { return Val.get(); } }; -template<> struct simplify_type<const Use> { - typedef /*const*/ Value* SimpleType; - static SimpleType getSimplifiedValue(const Use &Val) { - return Val.get(); - } -}; - - - -template<typename UserTy> // UserTy == 'User' or 'const User' -class value_use_iterator : public std::iterator<std::forward_iterator_tag, - UserTy*, ptrdiff_t> { - typedef std::iterator<std::forward_iterator_tag, UserTy*, ptrdiff_t> super; - typedef value_use_iterator<UserTy> _Self; - - Use *U; - explicit value_use_iterator(Use *u) : U(u) {} - friend class Value; -public: - typedef typename super::reference reference; - typedef typename super::pointer pointer; - - value_use_iterator() {} - - bool operator==(const _Self &x) const { - return U == x.U; - } - bool operator!=(const _Self &x) const { - return !operator==(x); - } - - /// atEnd - return true if this iterator is equal to use_end() on the value. - bool atEnd() const { return U == 0; } - - // Iterator traversal: forward iteration only - _Self &operator++() { // Preincrement - assert(U && "Cannot increment end iterator!"); - U = U->getNext(); - return *this; - } - _Self operator++(int) { // Postincrement - _Self tmp = *this; ++*this; return tmp; - } - - // Retrieve a pointer to the current User. - UserTy *operator*() const { - assert(U && "Cannot dereference end iterator!"); - return U->getUser(); - } - - UserTy *operator->() const { return operator*(); } - - Use &getUse() const { return *U; } - - /// getOperandNo - Return the operand # of this use in its User. Defined in - /// User.h - /// - unsigned getOperandNo() const; +template <> struct simplify_type<const Use> { + typedef /*const*/ Value *SimpleType; + static SimpleType getSimplifiedValue(const Use &Val) { return Val.get(); } }; // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef) -} // End llvm namespace +} #endif diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index 505bdeb178e9..848adae9ceca 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -19,6 +19,8 @@ #ifndef LLVM_IR_USER_H #define LLVM_IR_USER_H +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Value.h" #include "llvm/Support/ErrorHandling.h" @@ -37,6 +39,10 @@ class User : public Value { friend struct HungoffOperandTraits; virtual void anchor(); protected: + /// NumOperands - The number of values used by this User. + /// + unsigned NumOperands; + /// OperandList - This is a pointer to the array of Uses for this User. /// For nodes of fixed arity (e.g. a binary operator) this array will live /// prefixed to some derived class instance. For nodes of resizable variable @@ -44,17 +50,13 @@ protected: /// allocated and should be destroyed by the classes' virtual dtor. Use *OperandList; - /// NumOperands - The number of values used by this User. - /// - unsigned NumOperands; - void *operator new(size_t s, unsigned Us); User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps) - : Value(ty, vty), OperandList(OpList), NumOperands(NumOps) {} + : Value(ty, vty), NumOperands(NumOps), OperandList(OpList) {} Use *allocHungoffUses(unsigned) const; void dropHungoffUses() { Use::zap(OperandList, OperandList + NumOperands, true); - OperandList = 0; + OperandList = nullptr; // Reset NumOperands so User::operator delete() does the right thing. NumOperands = 0; } @@ -112,41 +114,29 @@ public: // typedef Use* op_iterator; typedef const Use* const_op_iterator; + typedef iterator_range<op_iterator> op_range; + typedef iterator_range<const_op_iterator> const_op_range; inline op_iterator op_begin() { return OperandList; } inline const_op_iterator op_begin() const { return OperandList; } inline op_iterator op_end() { return OperandList+NumOperands; } inline const_op_iterator op_end() const { return OperandList+NumOperands; } + inline op_range operands() { + return op_range(op_begin(), op_end()); + } + inline const_op_range operands() const { + return const_op_range(op_begin(), op_end()); + } /// Convenience iterator for directly iterating over the Values in the /// OperandList - class value_op_iterator : public std::iterator<std::forward_iterator_tag, - Value*> { - op_iterator OI; - public: - explicit value_op_iterator(Use *U) : OI(U) {} - - bool operator==(const value_op_iterator &x) const { - return OI == x.OI; - } - bool operator!=(const value_op_iterator &x) const { - return !operator==(x); - } - - /// Iterator traversal: forward iteration only - value_op_iterator &operator++() { // Preincrement - ++OI; - return *this; - } - value_op_iterator operator++(int) { // Postincrement - value_op_iterator tmp = *this; ++*this; return tmp; - } - - /// Retrieve a pointer to the current Value. - Value *operator*() const { - return *OI; - } + struct value_op_iterator + : iterator_adaptor_base<value_op_iterator, op_iterator, + std::random_access_iterator_tag, Value *, + ptrdiff_t, Value *, Value *> { + explicit value_op_iterator(Use *U = nullptr) : iterator_adaptor_base(U) {} + Value *operator*() const { return *I; } Value *operator->() const { return operator*(); } }; @@ -156,6 +146,9 @@ public: inline value_op_iterator value_op_end() { return value_op_iterator(op_end()); } + inline iterator_range<value_op_iterator> operand_values() { + return iterator_range<value_op_iterator>(value_op_begin(), value_op_end()); + } // dropAllReferences() - This function is in charge of "letting go" of all // objects that this User refers to. This allows one to @@ -166,8 +159,8 @@ public: // delete. // void dropAllReferences() { - for (op_iterator i = op_begin(), e = op_end(); i != e; ++i) - i->set(0); + for (Use &U : operands()) + U.set(nullptr); } /// replaceUsesOfWith - Replaces all references to the "From" definition with @@ -194,12 +187,6 @@ template<> struct simplify_type<User::const_op_iterator> { } }; -// value_use_iterator::getOperandNo - Requires the definition of the User class. -template<typename UserTy> -unsigned value_use_iterator<UserTy>::getOperandNo() const { - return U - U->getUser()->op_begin(); -} - } // End llvm namespace #endif diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index e1361fef351e..b5bbc96eac2a 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -7,18 +7,19 @@ // //===----------------------------------------------------------------------===// // -// This file declares the Value class. +// This file declares the Value class. // //===----------------------------------------------------------------------===// #ifndef LLVM_IR_VALUE_H #define LLVM_IR_VALUE_H +#include "llvm-c/Core.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Use.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" -#include "llvm-c/Core.h" namespace llvm { @@ -30,12 +31,14 @@ class Constant; class DataLayout; class Function; class GlobalAlias; +class GlobalObject; class GlobalValue; class GlobalVariable; class InlineAsm; class Instruction; class LLVMContext; class MDNode; +class Module; class StringRef; class Twine; class Type; @@ -50,7 +53,7 @@ typedef StringMapEntry<Value*> ValueName; // Value Class //===----------------------------------------------------------------------===// -/// This is a very important LLVM class. It is the base class of all values +/// This is a very important LLVM class. It is the base class of all values /// computed by a program that may be used as operands to other values. Value is /// the super class of other important classes such as Instruction and Function. /// All Values have a Type. Type is not a subclass of Value. Some values can @@ -60,10 +63,17 @@ typedef StringMapEntry<Value*> ValueName; /// Every value has a "use list" that keeps track of which other Values are /// using this Value. A Value can also have an arbitrary number of ValueHandle /// objects that watch it and listen to RAUW and Destroy events. See -/// llvm/Support/ValueHandle.h for details. +/// llvm/IR/ValueHandle.h for details. /// /// @brief LLVM Value Representation class Value { + Type *VTy; + Use *UseList; + + friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class ValueHandleBase; + ValueName *Name; + const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? protected: @@ -79,21 +89,100 @@ private: /// This field is initialized to zero by the ctor. unsigned short SubclassData; - Type *VTy; - Use *UseList; + template <typename UseT> // UseT == 'Use' or 'const Use' + class use_iterator_impl + : public std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> { + typedef std::iterator<std::forward_iterator_tag, UseT *, ptrdiff_t> super; + + UseT *U; + explicit use_iterator_impl(UseT *u) : U(u) {} + friend class Value; + + public: + typedef typename super::reference reference; + typedef typename super::pointer pointer; + + use_iterator_impl() : U() {} + + bool operator==(const use_iterator_impl &x) const { return U == x.U; } + bool operator!=(const use_iterator_impl &x) const { return !operator==(x); } + + use_iterator_impl &operator++() { // Preincrement + assert(U && "Cannot increment end iterator!"); + U = U->getNext(); + return *this; + } + use_iterator_impl operator++(int) { // Postincrement + auto tmp = *this; + ++*this; + return tmp; + } + + UseT &operator*() const { + assert(U && "Cannot dereference end iterator!"); + return *U; + } + + UseT *operator->() const { return &operator*(); } + + operator use_iterator_impl<const UseT>() const { + return use_iterator_impl<const UseT>(U); + } + }; - friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. - friend class ValueHandleBase; - ValueName *Name; + template <typename UserTy> // UserTy == 'User' or 'const User' + class user_iterator_impl + : public std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> { + typedef std::iterator<std::forward_iterator_tag, UserTy *, ptrdiff_t> super; + + use_iterator_impl<Use> UI; + explicit user_iterator_impl(Use *U) : UI(U) {} + friend class Value; + + public: + typedef typename super::reference reference; + typedef typename super::pointer pointer; + + user_iterator_impl() {} + + bool operator==(const user_iterator_impl &x) const { return UI == x.UI; } + bool operator!=(const user_iterator_impl &x) const { return !operator==(x); } + + /// \brief Returns true if this iterator is equal to user_end() on the value. + bool atEnd() const { return *this == user_iterator_impl(); } + + user_iterator_impl &operator++() { // Preincrement + ++UI; + return *this; + } + user_iterator_impl operator++(int) { // Postincrement + auto tmp = *this; + ++*this; + return tmp; + } + + // Retrieve a pointer to the current User. + UserTy *operator*() const { + return UI->getUser(); + } + + UserTy *operator->() const { return operator*(); } + + operator user_iterator_impl<const UserTy>() const { + return user_iterator_impl<const UserTy>(*UI); + } + + Use &getUse() const { return *UI; } + + /// \brief Return the operand # of this use in its User. + /// FIXME: Replace all callers with a direct call to Use::getOperandNo. + unsigned getOperandNo() const { return UI->getOperandNo(); } + }; void operator=(const Value &) LLVM_DELETED_FUNCTION; Value(const Value &) LLVM_DELETED_FUNCTION; protected: - /// printCustom - Value subclasses can override this to implement custom - /// printing behavior. - virtual void printCustom(raw_ostream &O) const; - Value(Type *Ty, unsigned scid); public: virtual ~Value(); @@ -104,7 +193,15 @@ public: /// print - Implement operator<< on Value. /// - void print(raw_ostream &O, AssemblyAnnotationWriter *AAW = 0) const; + void print(raw_ostream &O) const; + + /// \brief Print the name of this Value out to the specified raw_ostream. + /// This is useful when you just want to print 'int %reg126', not the + /// instruction that generated it. If you specify a Module for context, then + /// even constanst get pretty-printed; for example, the type of a null + /// pointer is printed symbolically. + void printAsOperand(raw_ostream &O, bool PrintType = true, + const Module *M = nullptr) const; /// All values are typed, get the type of this value. /// @@ -114,10 +211,10 @@ public: LLVMContext &getContext() const; // All values can potentially be named. - bool hasName() const { return Name != 0 && SubclassID != MDStringVal; } + bool hasName() const { return Name != nullptr && SubclassID != MDStringVal; } ValueName *getValueName() const { return Name; } void setValueName(ValueName *VN) { Name = VN; } - + /// getName() - Return a constant reference to the value's name. This is cheap /// and guaranteed to return the same reference as long as the value is not /// modified. @@ -129,9 +226,9 @@ public: /// \param Name The new name; or "" if the value's name should be removed. void setName(const Twine &Name); - + /// takeName - transfer the name from V to this value, setting V's name to - /// empty. It is an error to call V->takeName(V). + /// empty. It is an error to call V->takeName(V). void takeName(Value *V); /// replaceAllUsesWith - Go through the uses list for this definition and make @@ -143,16 +240,35 @@ public: //---------------------------------------------------------------------- // Methods for handling the chain of uses of this Value. // - typedef value_use_iterator<User> use_iterator; - typedef value_use_iterator<const User> const_use_iterator; + bool use_empty() const { return UseList == nullptr; } - bool use_empty() const { return UseList == 0; } + typedef use_iterator_impl<Use> use_iterator; + typedef use_iterator_impl<const Use> const_use_iterator; use_iterator use_begin() { return use_iterator(UseList); } const_use_iterator use_begin() const { return const_use_iterator(UseList); } - use_iterator use_end() { return use_iterator(0); } - const_use_iterator use_end() const { return const_use_iterator(0); } - User *use_back() { return *use_begin(); } - const User *use_back() const { return *use_begin(); } + use_iterator use_end() { return use_iterator(); } + const_use_iterator use_end() const { return const_use_iterator(); } + iterator_range<use_iterator> uses() { + return iterator_range<use_iterator>(use_begin(), use_end()); + } + iterator_range<const_use_iterator> uses() const { + return iterator_range<const_use_iterator>(use_begin(), use_end()); + } + + typedef user_iterator_impl<User> user_iterator; + typedef user_iterator_impl<const User> const_user_iterator; + user_iterator user_begin() { return user_iterator(UseList); } + const_user_iterator user_begin() const { return const_user_iterator(UseList); } + user_iterator user_end() { return user_iterator(); } + const_user_iterator user_end() const { return const_user_iterator(); } + User *user_back() { return *user_begin(); } + const User *user_back() const { return *user_begin(); } + iterator_range<user_iterator> users() { + return iterator_range<user_iterator>(user_begin(), user_end()); + } + iterator_range<const_user_iterator> users() const { + return iterator_range<const_user_iterator>(user_begin(), user_end()); + } /// hasOneUse - Return true if there is exactly one user of this value. This /// is specialized because it is a common request and does not require @@ -185,7 +301,7 @@ public: void addUse(Use &U) { U.addToList(&UseList); } /// An enumeration for keeping track of the concrete subclass of Value that - /// is actually instantiated. Values of this enumeration are kept in the + /// is actually instantiated. Values of this enumeration are kept in the /// Value classes SubclassID field. They are used for concrete type /// identification. enum ValueTy { @@ -209,9 +325,6 @@ public: MDNodeVal, // This is an instance of MDNode MDStringVal, // This is an instance of MDString InlineAsmVal, // This is an instance of InlineAsm - PseudoSourceValueVal, // This is an instance of PseudoSourceValue - FixedStackPseudoSourceValueVal, // This is an instance of - // FixedStackPseudoSourceValue InstructionVal, // This is an instance of Instruction // Enum values starting at InstructionVal are used for Instructions; // don't add new values here! @@ -317,8 +430,8 @@ public: /// isDereferenceablePointer - Test if this value is always a pointer to /// allocated and suitably aligned memory for a simple load or store. - bool isDereferenceablePointer() const; - + bool isDereferenceablePointer(const DataLayout *DL = nullptr) const; + /// DoPHITranslation - If this value is a PHI node with CurBB as its parent, /// return the value in the PHI node corresponding to PredBB. If not, return /// ourself. This is useful if you want to know the value something has in a @@ -329,11 +442,11 @@ public: const BasicBlock *PredBB) const{ return const_cast<Value*>(this)->DoPHITranslation(CurBB, PredBB); } - + /// MaximumAlignment - This is the greatest alignment value supported by /// load, store, and alloca instructions, and global values. static const unsigned MaximumAlignment = 1u << 29; - + /// mutateType - Mutate the type of this Value to be of the specified type. /// Note that this is an extremely dangerous operation which can create /// completely invalid IR very easily. It is strongly recommended that you @@ -342,7 +455,7 @@ public: void mutateType(Type *Ty) { VTy = Ty; } - + protected: unsigned short getSubclassDataFromValue() const { return SubclassData; } void setValueSubclassData(unsigned short D) { SubclassData = D; } @@ -352,7 +465,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Value &V) { V.print(OS); return OS; } - + void Use::set(Value *V) { if (Val) removeFromList(); Val = V; @@ -376,55 +489,60 @@ template <> struct isa_impl<Argument, Value> { } }; -template <> struct isa_impl<InlineAsm, Value> { +template <> struct isa_impl<InlineAsm, Value> { static inline bool doit(const Value &Val) { return Val.getValueID() == Value::InlineAsmVal; } }; -template <> struct isa_impl<Instruction, Value> { +template <> struct isa_impl<Instruction, Value> { static inline bool doit(const Value &Val) { return Val.getValueID() >= Value::InstructionVal; } }; -template <> struct isa_impl<BasicBlock, Value> { +template <> struct isa_impl<BasicBlock, Value> { static inline bool doit(const Value &Val) { return Val.getValueID() == Value::BasicBlockVal; } }; -template <> struct isa_impl<Function, Value> { +template <> struct isa_impl<Function, Value> { static inline bool doit(const Value &Val) { return Val.getValueID() == Value::FunctionVal; } }; -template <> struct isa_impl<GlobalVariable, Value> { +template <> struct isa_impl<GlobalVariable, Value> { static inline bool doit(const Value &Val) { return Val.getValueID() == Value::GlobalVariableVal; } }; -template <> struct isa_impl<GlobalAlias, Value> { +template <> struct isa_impl<GlobalAlias, Value> { static inline bool doit(const Value &Val) { return Val.getValueID() == Value::GlobalAliasVal; } }; -template <> struct isa_impl<GlobalValue, Value> { +template <> struct isa_impl<GlobalValue, Value> { + static inline bool doit(const Value &Val) { + return isa<GlobalObject>(Val) || isa<GlobalAlias>(Val); + } +}; + +template <> struct isa_impl<GlobalObject, Value> { static inline bool doit(const Value &Val) { - return isa<GlobalVariable>(Val) || isa<Function>(Val) || - isa<GlobalAlias>(Val); + return isa<GlobalVariable>(Val) || isa<Function>(Val); } }; -template <> struct isa_impl<MDNode, Value> { +template <> struct isa_impl<MDNode, Value> { static inline bool doit(const Value &Val) { return Val.getValueID() == Value::MDNodeVal; } }; - + // Value* is only 4-byte aligned. template<> class PointerLikeTypeTraits<Value*> { @@ -441,7 +559,7 @@ public: DEFINE_ISA_CONVERSION_FUNCTIONS(Value, LLVMValueRef) /* Specialized opaque value conversions. - */ + */ inline Value **unwrap(LLVMValueRef *Vals) { return reinterpret_cast<Value**>(Vals); } diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/IR/ValueHandle.h index bc02ba31b9b9..aa29b2ed6906 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -1,4 +1,4 @@ -//===- llvm/Support/ValueHandle.h - Value Smart Pointer classes -*- C++ -*-===// +//===- ValueHandle.h - Value Smart Pointer classes --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_VALUEHANDLE_H -#define LLVM_SUPPORT_VALUEHANDLE_H +#ifndef LLVM_IR_VALUEHANDLE_H +#define LLVM_IR_VALUEHANDLE_H #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/PointerIntPair.h" @@ -64,14 +64,14 @@ private: ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; public: explicit ValueHandleBase(HandleBaseKind Kind) - : PrevPair(0, Kind), Next(0), VP(0, 0) {} + : PrevPair(nullptr, Kind), Next(nullptr), VP(nullptr, 0) {} ValueHandleBase(HandleBaseKind Kind, Value *V) - : PrevPair(0, Kind), Next(0), VP(V, 0) { + : PrevPair(nullptr, Kind), Next(nullptr), VP(V, 0) { if (isValid(VP.getPointer())) AddToUseList(); } ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) - : PrevPair(0, Kind), Next(0), VP(RHS.VP) { + : PrevPair(nullptr, Kind), Next(nullptr), VP(RHS.VP) { if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr()); } @@ -214,7 +214,7 @@ public: AssertingVH(ValueTy *P) : ValueHandleBase(Assert, GetAsValue(P)) {} AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} #else - AssertingVH() : ThePtr(0) {} + AssertingVH() : ThePtr(nullptr) {} AssertingVH(ValueTy *P) : ThePtr(P) {} #endif @@ -366,7 +366,7 @@ public: /// /// All implementations must remove the reference from this object to the /// Value that's being destroyed. - virtual void deleted() { setValPtr(NULL); } + virtual void deleted() { setValPtr(nullptr); } /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, /// _before_ any of the uses have actually been replaced. If WeakVH were diff --git a/include/llvm/ADT/ValueMap.h b/include/llvm/IR/ValueMap.h index b4fed7a0ebd2..43a79c7db2b9 100644 --- a/include/llvm/ADT/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -1,4 +1,4 @@ -//===- llvm/ADT/ValueMap.h - Safe map from Values to data -------*- C++ -*-===// +//===- ValueMap.h - Safe map from Values to data ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -23,12 +23,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_VALUEMAP_H -#define LLVM_ADT_VALUEMAP_H +#ifndef LLVM_IR_VALUEMAP_H +#define LLVM_IR_VALUEMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Mutex.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Support/type_traits.h" #include <iterator> @@ -45,8 +45,10 @@ class ValueMapConstIterator; /// This class defines the default behavior for configurable aspects of /// ValueMap<>. User Configs should inherit from this class to be as compatible /// as possible with future versions of ValueMap. -template<typename KeyT> +template<typename KeyT, typename MutexT = sys::Mutex> struct ValueMapConfig { + typedef MutexT mutex_type; + /// If FollowRAUW is true, the ValueMap will update mappings on RAUW. If it's /// false, the ValueMap will leave the original mapping in place. enum { FollowRAUW = true }; @@ -67,7 +69,7 @@ struct ValueMapConfig { /// and onDelete) and not inside other ValueMap methods. NULL means that no /// mutex is necessary. template<typename ExtraDataT> - static sys::Mutex *getMutex(const ExtraDataT &/*Data*/) { return NULL; } + static mutex_type *getMutex(const ExtraDataT &/*Data*/) { return nullptr; } }; /// See the file comment. @@ -85,6 +87,7 @@ public: typedef KeyT key_type; typedef ValueT mapped_type; typedef std::pair<KeyT, ValueT> value_type; + typedef unsigned size_type; explicit ValueMap(unsigned NumInitBuckets = 64) : Map(NumInitBuckets), Data() {} @@ -101,16 +104,16 @@ public: inline const_iterator end() const { return const_iterator(Map.end()); } bool empty() const { return Map.empty(); } - unsigned size() const { return Map.size(); } + size_type size() const { return Map.size(); } /// Grow the map so that it has at least Size buckets. Does not shrink void resize(size_t Size) { Map.resize(Size); } void clear() { Map.clear(); } - /// count - Return true if the specified key is in the map. - bool count(const KeyT &Val) const { - return Map.find_as(Val) != Map.end(); + /// Return 1 if the specified key is in the map, 0 otherwise.
+ size_type count(const KeyT &Val) const { + return Map.find_as(Val) == Map.end() ? 0 : 1; } iterator find(const KeyT &Val) { @@ -198,7 +201,7 @@ class ValueMapCallbackVH : public CallbackVH { friend class ValueMap<KeyT, ValueT, Config>; friend struct DenseMapInfo<ValueMapCallbackVH>; typedef ValueMap<KeyT, ValueT, Config> ValueMapT; - typedef typename llvm::remove_pointer<KeyT>::type KeySansPointerT; + typedef typename std::remove_pointer<KeyT>::type KeySansPointerT; ValueMapT *Map; @@ -209,10 +212,10 @@ class ValueMapCallbackVH : public CallbackVH { public: KeyT Unwrap() const { return cast_or_null<KeySansPointerT>(getValPtr()); } - virtual void deleted() { + void deleted() override { // Make a copy that won't get changed even when *this is destroyed. ValueMapCallbackVH Copy(*this); - sys::Mutex *M = Config::getMutex(Copy.Map->Data); + typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data); if (M) M->acquire(); Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this. @@ -220,12 +223,12 @@ public: if (M) M->release(); } - virtual void allUsesReplacedWith(Value *new_key) { + void allUsesReplacedWith(Value *new_key) override { assert(isa<KeySansPointerT>(new_key) && "Invalid RAUW on key of ValueMap<>"); // Make a copy that won't get changed even when *this is destroyed. ValueMapCallbackVH Copy(*this); - sys::Mutex *M = Config::getMutex(Copy.Map->Data); + typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data); if (M) M->acquire(); @@ -253,10 +256,10 @@ struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config> > { typedef DenseMapInfo<KeyT> PointerInfo; static inline VH getEmptyKey() { - return VH(PointerInfo::getEmptyKey(), NULL); + return VH(PointerInfo::getEmptyKey(), nullptr); } static inline VH getTombstoneKey() { - return VH(PointerInfo::getTombstoneKey(), NULL); + return VH(PointerInfo::getTombstoneKey(), nullptr); } static unsigned getHashValue(const VH &Val) { return PointerInfo::getHashValue(Val.Unwrap()); diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h new file mode 100644 index 000000000000..0272e206f37a --- /dev/null +++ b/include/llvm/IR/Verifier.h @@ -0,0 +1,88 @@ +//===- Verifier.h - LLVM IR Verifier ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the function verifier interface, that can be used for some +// sanity checking of input to the system, and for checking that transformations +// haven't done something bad. +// +// Note that this does not provide full 'java style' security and verifications, +// instead it just tries to ensure that code is well formed. +// +// To see what specifically is checked, look at the top of Verifier.cpp +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_VERIFIER_H +#define LLVM_IR_VERIFIER_H + +#include "llvm/ADT/StringRef.h" +#include <string> + +namespace llvm { + +class Function; +class FunctionPass; +class ModulePass; +class Module; +class PreservedAnalyses; +class raw_ostream; + +/// \brief Check a function for errors, useful for use when debugging a +/// pass. +/// +/// If there are no errors, the function returns false. If an error is found, +/// a message describing the error is written to OS (if non-null) and true is +/// returned. +bool verifyFunction(const Function &F, raw_ostream *OS = nullptr); + +/// \brief Check a module for errors. +/// +/// If there are no errors, the function returns false. If an error is found, +/// a message describing the error is written to OS (if non-null) and true is +/// returned. +bool verifyModule(const Module &M, raw_ostream *OS = nullptr); + +/// \brief Create a verifier pass. +/// +/// Check a module or function for validity. This is essentially a pass wrapped +/// around the above verifyFunction and verifyModule routines and +/// functionality. When the pass detects a verification error it is always +/// printed to stderr, and by default they are fatal. You can override that by +/// passing \c false to \p FatalErrors. +/// +/// Note that this creates a pass suitable for the legacy pass manager. It has nothing to do with \c VerifierPass. +FunctionPass *createVerifierPass(bool FatalErrors = true); + +/// \brief Create a debug-info verifier pass. +/// +/// Check a module for validity of debug info. This is essentially a pass +/// wrapped around the debug-info parts of \a verifyModule(). When the pass +/// detects a verification error it is always printed to stderr, and by default +/// they are fatal. You can override that by passing \c false to \p +/// FatalErrors. +/// +/// Note that this creates a pass suitable for the legacy pass manager. It has +/// nothing to do with \c VerifierPass. +ModulePass *createDebugInfoVerifierPass(bool FatalErrors = true); + +class VerifierPass { + bool FatalErrors; + +public: + explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {} + + PreservedAnalyses run(Module *M); + PreservedAnalyses run(Function *F); + + static StringRef name() { return "VerifierPass"; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IRReader/IRReader.h b/include/llvm/IRReader/IRReader.h index e2ae5f7164b2..59ffc095f47f 100644 --- a/include/llvm/IRReader/IRReader.h +++ b/include/llvm/IRReader/IRReader.h @@ -24,13 +24,6 @@ class MemoryBuffer; class SMDiagnostic; class LLVMContext; -/// If the given MemoryBuffer holds a bitcode image, return a Module for it -/// which does lazy deserialization of function bodies. Otherwise, attempt to -/// parse it as LLVM Assembly and return a fully populated Module. This -/// function *always* takes ownership of the given MemoryBuffer. -Module *getLazyIRModule(MemoryBuffer *Buffer, SMDiagnostic &Err, - LLVMContext &Context); - /// If the given file holds a bitcode image, return a Module /// for it which does lazy deserialization of function bodies. Otherwise, /// attempt to parse it as LLVM Assembly and return a fully populated @@ -40,8 +33,7 @@ Module *getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err, /// If the given MemoryBuffer holds a bitcode image, return a Module /// for it. Otherwise, attempt to parse it as LLVM Assembly and return -/// a Module for it. This function *always* takes ownership of the given -/// MemoryBuffer. +/// a Module for it. This function *never* takes ownership of Buffer. Module *ParseIR(MemoryBuffer *Buffer, SMDiagnostic &Err, LLVMContext &Context); /// If the given file holds a bitcode image, return a Module for it. diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index aefb3c065b8f..02f4259a51ac 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -63,6 +63,7 @@ void initializeCodeGen(PassRegistry&); void initializeTarget(PassRegistry&); void initializeAAEvalPass(PassRegistry&); +void initializeAddDiscriminatorsPass(PassRegistry&); void initializeADCEPass(PassRegistry&); void initializeAliasAnalysisAnalysisGroup(PassRegistry&); void initializeAliasAnalysisCounterPass(PassRegistry&); @@ -70,10 +71,11 @@ void initializeAliasDebuggerPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlwaysInlinerPass(PassRegistry&); void initializeArgPromotionPass(PassRegistry&); +void initializeAtomicExpandLoadLinkedPass(PassRegistry&); void initializeSampleProfileLoaderPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); -void initializeCallGraphPass(PassRegistry&); +void initializeCallGraphWrapperPassPass(PassRegistry &); void initializeBasicTTIPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoPass(PassRegistry&); @@ -90,6 +92,7 @@ void initializeCFGSimplifyPassPass(PassRegistry&); void initializeFlattenCFGPassPass(PassRegistry&); void initializeStructurizeCFGPass(PassRegistry&); void initializeCFGViewerPass(PassRegistry&); +void initializeConstantHoistingPass(PassRegistry&); void initializeCodeGenPreparePass(PassRegistry&); void initializeConstantMergePass(PassRegistry&); void initializeConstantPropagationPass(PassRegistry&); @@ -101,6 +104,7 @@ void initializeDAHPass(PassRegistry&); void initializeDCEPass(PassRegistry&); void initializeDSEPass(PassRegistry&); void initializeDebugIRPass(PassRegistry&); +void initializeDebugInfoVerifierLegacyPassPass(PassRegistry &); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); void initializeDelinearizationPass(PassRegistry &); @@ -110,7 +114,7 @@ void initializeDomOnlyViewerPass(PassRegistry&); void initializeDomPrinterPass(PassRegistry&); void initializeDomViewerPass(PassRegistry&); void initializeDominanceFrontierPass(PassRegistry&); -void initializeDominatorTreePass(PassRegistry&); +void initializeDominatorTreeWrapperPassPass(PassRegistry&); void initializeEarlyIfConverterPass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); @@ -120,6 +124,7 @@ void initializeAddressSanitizerModulePass(PassRegistry&); void initializeMemorySanitizerPass(PassRegistry&); void initializeThreadSanitizerPass(PassRegistry&); void initializeDataFlowSanitizerPass(PassRegistry&); +void initializeScalarizerPass(PassRegistry&); void initializeEarlyCSEPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); void initializeFindUsedTypesPass(PassRegistry&); @@ -141,6 +146,8 @@ void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); void initializeInternalizePassPass(PassRegistry&); void initializeIntervalPartitionPass(PassRegistry&); +void initializeJumpInstrTableInfoPass(PassRegistry&); +void initializeJumpInstrTablesPass(PassRegistry&); void initializeJumpThreadingPass(PassRegistry&); void initializeLCSSAPass(PassRegistry&); void initializeLICMPass(PassRegistry&); @@ -177,10 +184,12 @@ void initializeMachineBlockPlacementStatsPass(PassRegistry&); void initializeMachineBranchProbabilityInfoPass(PassRegistry&); void initializeMachineCSEPass(PassRegistry&); void initializeMachineDominatorTreePass(PassRegistry&); +void initializeMachineDominanceFrontierPass(PassRegistry&); void initializeMachinePostDominatorTreePass(PassRegistry&); void initializeMachineLICMPass(PassRegistry&); void initializeMachineLoopInfoPass(PassRegistry&); void initializeMachineModuleInfoPass(PassRegistry&); +void initializeMachineRegionInfoPassPass(PassRegistry&); void initializeMachineSchedulerPass(PassRegistry&); void initializeMachineSinkingPass(PassRegistry&); void initializeMachineTraceMetricsPass(PassRegistry&); @@ -188,6 +197,7 @@ void initializeMachineVerifierPassPass(PassRegistry&); void initializeMemCpyOptPass(PassRegistry&); void initializeMemDepPrinterPass(PassRegistry&); void initializeMemoryDependenceAnalysisPass(PassRegistry&); +void initializeMergedLoadStoreMotionPass(PassRegistry &); void initializeMetaRenamerPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); @@ -209,16 +219,16 @@ void initializePostDomPrinterPass(PassRegistry&); void initializePostDomViewerPass(PassRegistry&); void initializePostDominatorTreePass(PassRegistry&); void initializePostRASchedulerPass(PassRegistry&); -void initializePreVerifierPass(PassRegistry&); -void initializePrintFunctionPassPass(PassRegistry&); -void initializePrintModulePassPass(PassRegistry&); +void initializePostMachineSchedulerPass(PassRegistry&); +void initializePrintFunctionPassWrapperPass(PassRegistry&); +void initializePrintModulePassWrapperPass(PassRegistry&); void initializePrintBasicBlockPassPass(PassRegistry&); void initializeProcessImplicitDefsPass(PassRegistry&); void initializePromotePassPass(PassRegistry&); void initializePruneEHPass(PassRegistry&); void initializeReassociatePass(PassRegistry&); void initializeRegToMemPass(PassRegistry&); -void initializeRegionInfoPass(PassRegistry&); +void initializeRegionInfoPassPass(PassRegistry&); void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); @@ -233,6 +243,7 @@ void initializeSimpleInlinerPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); +void initializeSeparateConstOffsetFromGEPPass(PassRegistry &); void initializeSlotIndexesPass(PassRegistry&); void initializeSpillPlacementPass(PassRegistry&); void initializeStackProtectorPass(PassRegistry&); @@ -246,7 +257,7 @@ void initializeStripSymbolsPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); -void initializeDataLayoutPass(PassRegistry&); +void initializeDataLayoutPassPass(PassRegistry &); void initializeTargetTransformInfoAnalysisGroup(PassRegistry&); void initializeNoTTIPass(PassRegistry&); void initializeTargetLibraryInfoPass(PassRegistry&); @@ -255,7 +266,7 @@ void initializeTypeBasedAliasAnalysisPass(PassRegistry&); void initializeUnifyFunctionExitNodesPass(PassRegistry&); void initializeUnreachableBlockElimPass(PassRegistry&); void initializeUnreachableMachineBlockElimPass(PassRegistry&); -void initializeVerifierPass(PassRegistry&); +void initializeVerifierLegacyPassPass(PassRegistry&); void initializeVirtRegMapPass(PassRegistry&); void initializeVirtRegRewriterPass(PassRegistry&); void initializeInstSimplifierPass(PassRegistry&); @@ -265,6 +276,8 @@ void initializeLoopVectorizePass(PassRegistry&); void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); +void initializeStackMapLivenessPass(PassRegistry&); +void initializeLoadCombinePass(PassRegistry&); } #endif diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index c478bd980d4f..b19b2325f73b 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -9,7 +9,7 @@ // // This file declares the LTOCodeGenerator class. // -// LTO compilation consists of three phases: Pre-IPO, IPO and Post-IPO. +// LTO compilation consists of three phases: Pre-IPO, IPO and Post-IPO. // // The Pre-IPO phase compiles source code into bitcode file. The resulting // bitcode files, along with object files and libraries, will be fed to the @@ -21,12 +21,12 @@ // The IPO phase perform inter-procedural analyses and optimizations, and // the Post-IPO consists two sub-phases: intra-procedural scalar optimizations // (SOPT), and intra-procedural target-dependent code generator (CG). -// +// // As of this writing, we don't separate IPO and the Post-IPO SOPT. They // are intermingled together, and are driven by a single pass manager (see // PassManagerBuilder::populateLTOPassManager()). -// -// The "LTOCodeGenerator" is the driver for the IPO and Post-IPO stages. +// +// The "LTOCodeGenerator" is the driver for the IPO and Post-IPO stages. // The "CodeGenerator" here is bit confusing. Don't confuse the "CodeGenerator" // with the machine specific code generator. // @@ -36,27 +36,26 @@ #define LTO_CODE_GENERATOR_H #include "llvm-c/lto.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Linker.h" +#include "llvm/Linker/Linker.h" #include "llvm/Target/TargetOptions.h" #include <string> #include <vector> namespace llvm { class LLVMContext; + class DiagnosticInfo; class GlobalValue; class Mangler; class MemoryBuffer; class TargetLibraryInfo; class TargetMachine; class raw_ostream; -} //===----------------------------------------------------------------------===// -/// LTOCodeGenerator - C++ class which implements the opaque lto_code_gen_t -/// type. +/// C++ class which implements the opaque lto_code_gen_t type. /// struct LTOCodeGenerator { static const char *getVersionString(); @@ -67,11 +66,12 @@ struct LTOCodeGenerator { // Merge given module, return true on success. bool addModule(struct LTOModule*, std::string &errMsg); - void setTargetOptions(llvm::TargetOptions options); + void setTargetOptions(TargetOptions options); void setDebugInfo(lto_debug_model); void setCodePICModel(lto_codegen_model); void setCpu(const char *mCpu) { MCpu = mCpu; } + void setAttr(const char *mAttr) { MAttr = mAttr; } void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; } @@ -79,9 +79,8 @@ struct LTOCodeGenerator { // not necessarily for debugging purpose (The function name is misleading). // This function should be called before LTOCodeGenerator::compilexxx(), // and LTOCodeGenerator::writeMergedModules(). - // void setCodeGenDebugOptions(const char *opts); - + // Parse the options set in setCodeGenDebugOptions. Like // setCodeGenDebugOptions, this must be called before // LTOCodeGenerator::compilexxx() and LTOCodeGenerator::writeMergedModules() @@ -98,7 +97,6 @@ struct LTOCodeGenerator { // NOTE that it is up to the linker to remove the intermediate object file. // Do not try to remove the object file in LTOCodeGenerator's destructor // as we don't who (LTOCodeGenerator or the obj file) will last longer. - // bool compile_to_file(const char **name, bool disableOpt, bool disableInline, @@ -109,45 +107,49 @@ struct LTOCodeGenerator { // single object file. Instead of returning the object-file-path to the caller // (linker), it brings the object to a buffer, and return the buffer to the // caller. This function should delete intermediate object file once its content - // is brought to memory. Return NULL if the compilation was not successful. - // + // is brought to memory. Return NULL if the compilation was not successful. const void *compile(size_t *length, bool disableOpt, bool disableInline, bool disableGVNLoadPRE, std::string &errMsg); + void setDiagnosticHandler(lto_diagnostic_handler_t, void *); + private: void initializeLTOPasses(); - bool generateObjectFile(llvm::raw_ostream &out, - bool disableOpt, - bool disableInline, - bool disableGVNLoadPRE, - std::string &errMsg); + bool generateObjectFile(raw_ostream &out, bool disableOpt, bool disableInline, + bool disableGVNLoadPRE, std::string &errMsg); void applyScopeRestrictions(); - void applyRestriction(llvm::GlobalValue &GV, - const llvm::ArrayRef<llvm::StringRef> &Libcalls, - std::vector<const char*> &MustPreserveList, - llvm::SmallPtrSet<llvm::GlobalValue*, 8> &AsmUsed, - llvm::Mangler &Mangler); + void applyRestriction(GlobalValue &GV, const ArrayRef<StringRef> &Libcalls, + std::vector<const char *> &MustPreserveList, + SmallPtrSet<GlobalValue *, 8> &AsmUsed, + Mangler &Mangler); bool determineTarget(std::string &errMsg); - typedef llvm::StringMap<uint8_t> StringSet; + static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context); + + void DiagnosticHandler2(const DiagnosticInfo &DI); - llvm::LLVMContext &Context; - llvm::Linker Linker; - llvm::TargetMachine *TargetMach; + typedef StringMap<uint8_t> StringSet; + + LLVMContext &Context; + Linker IRLinker; + TargetMachine *TargetMach; bool EmitDwarfDebugInfo; bool ScopeRestrictionsDone; lto_codegen_model CodeModel; StringSet MustPreserveSymbols; StringSet AsmUndefinedRefs; - llvm::MemoryBuffer *NativeObjectFile; + MemoryBuffer *NativeObjectFile; std::vector<char *> CodegenOptions; std::string MCpu; + std::string MAttr; std::string NativeObjectPath; - llvm::TargetOptions Options; + TargetOptions Options; + lto_diagnostic_handler_t DiagHandler; + void *DiagContext; }; - +} #endif // LTO_CODE_GENERATOR_H diff --git a/include/llvm/LTO/LTOModule.h b/include/llvm/LTO/LTOModule.h index f4693c8d2260..c43846a64050 100644 --- a/include/llvm/LTO/LTOModule.h +++ b/include/llvm/LTO/LTOModule.h @@ -15,11 +15,11 @@ #define LTO_MODULE_H #include "llvm-c/lto.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCContext.h" -#include "llvm/Target/Mangler.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/Object/IRObjectFile.h" #include "llvm/Target/TargetMachine.h" #include <string> #include <vector> @@ -31,166 +31,181 @@ namespace llvm { class MemoryBuffer; class TargetOptions; class Value; -} //===----------------------------------------------------------------------===// -/// LTOModule - C++ class which implements the opaque lto_module_t type. +/// C++ class which implements the opaque lto_module_t type. /// struct LTOModule { private: - typedef llvm::StringMap<uint8_t> StringSet; + typedef StringMap<uint8_t> StringSet; struct NameAndAttributes { const char *name; uint32_t attributes; bool isFunction; - const llvm::GlobalValue *symbol; + const GlobalValue *symbol; }; - llvm::OwningPtr<llvm::Module> _module; - llvm::OwningPtr<llvm::TargetMachine> _target; + std::unique_ptr<object::IRObjectFile> IRFile; + std::unique_ptr<TargetMachine> _target; + StringSet _linkeropt_strings; + std::vector<const char *> _deplibs; + std::vector<const char *> _linkeropts; std::vector<NameAndAttributes> _symbols; // _defines and _undefines only needed to disambiguate tentative definitions StringSet _defines; - llvm::StringMap<NameAndAttributes> _undefines; + StringMap<NameAndAttributes> _undefines; std::vector<const char*> _asm_undefines; - llvm::MCContext _context; - // Use mangler to add GlobalPrefix to names to match linker names. - llvm::Mangler _mangler; + LTOModule(std::unique_ptr<object::IRObjectFile> Obj, TargetMachine *TM); - LTOModule(llvm::Module *m, llvm::TargetMachine *t); public: - /// isBitcodeFile - Returns 'true' if the file or memory contents is LLVM - /// bitcode. + /// Returns 'true' if the file or memory contents is LLVM bitcode. static bool isBitcodeFile(const void *mem, size_t length); static bool isBitcodeFile(const char *path); - /// isBitcodeFileForTarget - Returns 'true' if the file or memory contents - /// is LLVM bitcode for the specified triple. - static bool isBitcodeFileForTarget(const void *mem, - size_t length, - const char *triplePrefix); - static bool isBitcodeFileForTarget(const char *path, - const char *triplePrefix); - - /// makeLTOModule - Create an LTOModule. N.B. These methods take ownership - /// of the buffer. The caller must have initialized the Targets, the - /// TargetMCs, the AsmPrinters, and the AsmParsers by calling: + /// Returns 'true' if the memory buffer is LLVM bitcode for the specified + /// triple. + static bool isBitcodeForTarget(MemoryBuffer *memBuffer, + StringRef triplePrefix); + + /// Create a MemoryBuffer from a memory range with an optional name. + static MemoryBuffer *makeBuffer(const void *mem, size_t length, + StringRef name = ""); + + /// Create an LTOModule. N.B. These methods take ownership of the buffer. The + /// caller must have initialized the Targets, the TargetMCs, the AsmPrinters, + /// and the AsmParsers by calling: /// /// InitializeAllTargets(); /// InitializeAllTargetMCs(); /// InitializeAllAsmPrinters(); /// InitializeAllAsmParsers(); - static LTOModule *makeLTOModule(const char* path, - llvm::TargetOptions options, - std::string &errMsg); - static LTOModule *makeLTOModule(int fd, const char *path, - size_t size, llvm::TargetOptions options, - std::string &errMsg); - static LTOModule *makeLTOModule(int fd, const char *path, - size_t map_size, - off_t offset, llvm::TargetOptions options, - std::string& errMsg); - static LTOModule *makeLTOModule(const void *mem, size_t length, - llvm::TargetOptions options, - std::string &errMsg); - - /// getTargetTriple - Return the Module's target triple. - const char *getTargetTriple() { - return _module->getTargetTriple().c_str(); + static LTOModule *createFromFile(const char *path, TargetOptions options, + std::string &errMsg); + static LTOModule *createFromOpenFile(int fd, const char *path, size_t size, + TargetOptions options, + std::string &errMsg); + static LTOModule *createFromOpenFileSlice(int fd, const char *path, + size_t map_size, off_t offset, + TargetOptions options, + std::string &errMsg); + static LTOModule *createFromBuffer(const void *mem, size_t length, + TargetOptions options, std::string &errMsg, + StringRef path = ""); + + const Module &getModule() const { + return const_cast<LTOModule*>(this)->getModule(); + } + Module &getModule() { + return IRFile->getModule(); + } + + /// Return the Module's target triple. + const std::string &getTargetTriple() { + return getModule().getTargetTriple(); } - /// setTargetTriple - Set the Module's target triple. - void setTargetTriple(const char *triple) { - _module->setTargetTriple(triple); + /// Set the Module's target triple. + void setTargetTriple(StringRef Triple) { + getModule().setTargetTriple(Triple); } - /// getSymbolCount - Get the number of symbols + /// Get the number of symbols uint32_t getSymbolCount() { return _symbols.size(); } - /// getSymbolAttributes - Get the attributes for a symbol at the specified - /// index. + /// Get the attributes for a symbol at the specified index. lto_symbol_attributes getSymbolAttributes(uint32_t index) { if (index < _symbols.size()) return lto_symbol_attributes(_symbols[index].attributes); return lto_symbol_attributes(0); } - /// getSymbolName - Get the name of the symbol at the specified index. + /// Get the name of the symbol at the specified index. const char *getSymbolName(uint32_t index) { if (index < _symbols.size()) return _symbols[index].name; - return NULL; + return nullptr; } - /// getLLVVMModule - Return the Module. - llvm::Module *getLLVVMModule() { return _module.get(); } + /// Get the number of dependent libraries + uint32_t getDependentLibraryCount() { + return _deplibs.size(); + } + + /// Get the dependent library at the specified index. + const char *getDependentLibrary(uint32_t index) { + if (index < _deplibs.size()) + return _deplibs[index]; + return nullptr; + } + + /// Get the number of linker options + uint32_t getLinkerOptCount() { + return _linkeropts.size(); + } + + /// Get the linker option at the specified index. + const char *getLinkerOpt(uint32_t index) { + if (index < _linkeropts.size()) + return _linkeropts[index]; + return nullptr; + } - /// getAsmUndefinedRefs - const std::vector<const char*> &getAsmUndefinedRefs() { return _asm_undefines; } private: - /// parseSymbols - Parse the symbols from the module and model-level ASM and - /// add them to either the defined or undefined lists. - bool parseSymbols(std::string &errMsg); + /// Parse metadata from the module + // FIXME: it only parses "Linker Options" metadata at the moment + void parseMetadata(); - /// addPotentialUndefinedSymbol - Add a symbol which isn't defined just yet - /// to a list to be resolved later. - void addPotentialUndefinedSymbol(const llvm::GlobalValue *dcl, bool isFunc); + /// Parse the symbols from the module and model-level ASM and add them to + /// either the defined or undefined lists. + bool parseSymbols(std::string &errMsg); - /// addDefinedSymbol - Add a defined symbol to the list. - void addDefinedSymbol(const llvm::GlobalValue *def, bool isFunction); + /// Add a symbol which isn't defined just yet to a list to be resolved later. + void addPotentialUndefinedSymbol(const object::BasicSymbolRef &Sym, + bool isFunc); - /// addDefinedFunctionSymbol - Add a function symbol as defined to the list. - void addDefinedFunctionSymbol(const llvm::Function *f); + /// Add a defined symbol to the list. + void addDefinedSymbol(const char *Name, const GlobalValue *def, + bool isFunction); - /// addDefinedDataSymbol - Add a data symbol as defined to the list. - void addDefinedDataSymbol(const llvm::GlobalValue *v); + /// Add a data symbol as defined to the list. + void addDefinedDataSymbol(const object::BasicSymbolRef &Sym); + void addDefinedDataSymbol(const char*Name, const GlobalValue *v); - /// addAsmGlobalSymbols - Add global symbols from module-level ASM to the - /// defined or undefined lists. - bool addAsmGlobalSymbols(std::string &errMsg); + /// Add a function symbol as defined to the list. + void addDefinedFunctionSymbol(const object::BasicSymbolRef &Sym); + void addDefinedFunctionSymbol(const char *Name, const Function *F); - /// addAsmGlobalSymbol - Add a global symbol from module-level ASM to the - /// defined list. + /// Add a global symbol from module-level ASM to the defined list. void addAsmGlobalSymbol(const char *, lto_symbol_attributes scope); - /// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to - /// the undefined list. + /// Add a global symbol from module-level ASM to the undefined list. void addAsmGlobalSymbolUndef(const char *); - /// addObjCClass - Parse i386/ppc ObjC class data structure. - void addObjCClass(const llvm::GlobalVariable *clgv); + /// Parse i386/ppc ObjC class data structure. + void addObjCClass(const GlobalVariable *clgv); - /// addObjCCategory - Parse i386/ppc ObjC category data structure. - void addObjCCategory(const llvm::GlobalVariable *clgv); + /// Parse i386/ppc ObjC category data structure. + void addObjCCategory(const GlobalVariable *clgv); - /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. - void addObjCClassRef(const llvm::GlobalVariable *clgv); + /// Parse i386/ppc ObjC class list data structure. + void addObjCClassRef(const GlobalVariable *clgv); - /// objcClassNameFromExpression - Get string that the data pointer points - /// to. - bool objcClassNameFromExpression(const llvm::Constant* c, std::string &name); + /// Get string that the data pointer points to. + bool objcClassNameFromExpression(const Constant *c, std::string &name); - /// isTargetMatch - Returns 'true' if the memory buffer is for the specified - /// target triple. - static bool isTargetMatch(llvm::MemoryBuffer *memBuffer, - const char *triplePrefix); - - /// makeLTOModule - Create an LTOModule (private version). N.B. This - /// method takes ownership of the buffer. - static LTOModule *makeLTOModule(llvm::MemoryBuffer *buffer, - llvm::TargetOptions options, - std::string &errMsg); - - /// makeBuffer - Create a MemoryBuffer from a memory range. - static llvm::MemoryBuffer *makeBuffer(const void *mem, size_t length); + /// Create an LTOModule (private version). N.B. This method takes ownership of + /// the buffer. + static LTOModule *makeLTOModule(std::unique_ptr<MemoryBuffer> Buffer, + TargetOptions options, std::string &errMsg); }; - +} #endif // LTO_MODULE_H diff --git a/include/llvm/LineEditor/LineEditor.h b/include/llvm/LineEditor/LineEditor.h new file mode 100644 index 000000000000..1a9a69106032 --- /dev/null +++ b/include/llvm/LineEditor/LineEditor.h @@ -0,0 +1,153 @@ +//===-- llvm/LineEditor/LineEditor.h - line editor --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LINEEDITOR_LINEEDITOR_H +#define LLVM_LINEEDITOR_LINEEDITOR_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include <cstdio> +#include <memory> +#include <string> +#include <vector> + +namespace llvm { + +class LineEditor { +public: + /// Create a LineEditor object. + /// + /// \param ProgName The name of the current program. Used to form a default + /// prompt. + /// \param HistoryPath Path to the file in which to store history data, if + /// possible. + /// \param In The input stream used by the editor. + /// \param Out The output stream used by the editor. + /// \param Err The error stream used by the editor. + LineEditor(StringRef ProgName, StringRef HistoryPath = "", FILE *In = stdin, + FILE *Out = stdout, FILE *Err = stderr); + ~LineEditor(); + + /// Reads a line. + /// + /// \return The line, or llvm::Optional<std::string>() on EOF. + llvm::Optional<std::string> readLine() const; + + void saveHistory(); + void loadHistory(); + + static std::string getDefaultHistoryPath(StringRef ProgName); + + /// The action to perform upon a completion request. + struct CompletionAction { + enum ActionKind { + /// Insert Text at the cursor position. + AK_Insert, + /// Show Completions, or beep if the list is empty. + AK_ShowCompletions + }; + + ActionKind Kind; + + /// The text to insert. + std::string Text; + + /// The list of completions to show. + std::vector<std::string> Completions; + }; + + /// A possible completion at a given cursor position. + struct Completion { + Completion() {} + Completion(const std::string &TypedText, const std::string &DisplayText) + : TypedText(TypedText), DisplayText(DisplayText) {} + + /// The text to insert. If the user has already input some of the + /// completion, this should only include the rest of the text. + std::string TypedText; + + /// A description of this completion. This may be the completion itself, or + /// maybe a summary of its type or arguments. + std::string DisplayText; + }; + + /// Set the completer for this LineEditor. A completer is a function object + /// which takes arguments of type StringRef (the string to complete) and + /// size_t (the zero-based cursor position in the StringRef) and returns a + /// CompletionAction. + template <typename T> void setCompleter(T Comp) { + Completer.reset(new CompleterModel<T>(Comp)); + } + + /// Set the completer for this LineEditor to the given list completer. + /// A list completer is a function object which takes arguments of type + /// StringRef (the string to complete) and size_t (the zero-based cursor + /// position in the StringRef) and returns a std::vector<Completion>. + template <typename T> void setListCompleter(T Comp) { + Completer.reset(new ListCompleterModel<T>(Comp)); + } + + /// Use the current completer to produce a CompletionAction for the given + /// completion request. If the current completer is a list completer, this + /// will return an AK_Insert CompletionAction if each completion has a common + /// prefix, or an AK_ShowCompletions CompletionAction otherwise. + /// + /// \param Buffer The string to complete + /// \param Pos The zero-based cursor position in the StringRef + CompletionAction getCompletionAction(StringRef Buffer, size_t Pos) const; + + const std::string &getPrompt() const { return Prompt; } + void setPrompt(const std::string &P) { Prompt = P; } + + // Public so callbacks in LineEditor.cpp can use it. + struct InternalData; + +private: + std::string Prompt; + std::string HistoryPath; + std::unique_ptr<InternalData> Data; + + struct CompleterConcept { + virtual ~CompleterConcept(); + virtual CompletionAction complete(StringRef Buffer, size_t Pos) const = 0; + }; + + struct ListCompleterConcept : CompleterConcept { + ~ListCompleterConcept(); + CompletionAction complete(StringRef Buffer, size_t Pos) const override; + static std::string getCommonPrefix(const std::vector<Completion> &Comps); + virtual std::vector<Completion> getCompletions(StringRef Buffer, + size_t Pos) const = 0; + }; + + template <typename T> + struct CompleterModel : CompleterConcept { + CompleterModel(T Value) : Value(Value) {} + CompletionAction complete(StringRef Buffer, size_t Pos) const override { + return Value(Buffer, Pos); + } + T Value; + }; + + template <typename T> + struct ListCompleterModel : ListCompleterConcept { + ListCompleterModel(T Value) : Value(Value) {} + std::vector<Completion> getCompletions(StringRef Buffer, + size_t Pos) const override { + return Value(Buffer, Pos); + } + T Value; + }; + + std::unique_ptr<const CompleterConcept> Completer; +}; + +} + +#endif diff --git a/include/llvm/LinkAllIR.h b/include/llvm/LinkAllIR.h index 4c1aaca7a385..2b0604aee067 100644 --- a/include/llvm/LinkAllIR.h +++ b/include/llvm/LinkAllIR.h @@ -16,12 +16,12 @@ #ifndef LLVM_LINKALLIR_H #define LLVM_LINKALLIR_H -#include "llvm/Analysis/Verifier.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/MathExtras.h" diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 8183fa2992a6..e06560ca0b64 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -26,9 +26,9 @@ #include "llvm/Analysis/RegionPass.h" #include "llvm/Analysis/RegionPrinter.h" #include "llvm/Analysis/ScalarEvolution.h" -#include "llvm/Assembly/PrintModulePass.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Function.h" +#include "llvm/IR/IRPrintingPasses.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" @@ -53,7 +53,7 @@ namespace { (void) llvm::createAliasDebugger(); (void) llvm::createArgumentPromotionPass(); (void) llvm::createBasicAliasAnalysisPass(); - (void) llvm::createLibCallAliasAnalysisPass(0); + (void) llvm::createLibCallAliasAnalysisPass(nullptr); (void) llvm::createScalarEvolutionAliasAnalysisPass(); (void) llvm::createTypeBasedAliasAnalysisPass(); (void) llvm::createBoundsCheckingPass(); @@ -85,6 +85,8 @@ namespace { (void) llvm::createIndVarSimplifyPass(); (void) llvm::createInstructionCombiningPass(); (void) llvm::createInternalizePass(); + (void) llvm::createJumpInstrTableInfoPass(); + (void) llvm::createJumpInstrTablesPass(); (void) llvm::createLCSSAPass(); (void) llvm::createLICMPass(); (void) llvm::createLazyValueInfoPass(); @@ -129,8 +131,10 @@ namespace { (void) llvm::createJumpThreadingPass(); (void) llvm::createUnifyFunctionExitNodesPass(); (void) llvm::createInstCountPass(); + (void) llvm::createConstantHoistingPass(); (void) llvm::createCodeGenPreparePass(); (void) llvm::createEarlyCSEPass(); + (void)llvm::createMergedLoadStoreMotionPass(); (void) llvm::createGVNPass(); (void) llvm::createMemCpyOptPass(); (void) llvm::createLoopDeletionPass(); @@ -139,9 +143,9 @@ namespace { (void) llvm::createMetaRenamerPass(); (void) llvm::createFunctionAttrsPass(); (void) llvm::createMergeFunctionsPass(); - (void) llvm::createPrintModulePass(0); - (void) llvm::createPrintFunctionPass("", 0); - (void) llvm::createPrintBasicBlockPass(0); + (void) llvm::createPrintModulePass(*(llvm::raw_ostream*)nullptr); + (void) llvm::createPrintFunctionPass(*(llvm::raw_ostream*)nullptr); + (void) llvm::createPrintBasicBlockPass(*(llvm::raw_ostream*)nullptr); (void) llvm::createModuleDebugInfoPrinterPass(); (void) llvm::createPartialInliningPass(); (void) llvm::createLintPass(); @@ -154,15 +158,17 @@ namespace { (void) llvm::createSLPVectorizerPass(); (void) llvm::createBBVectorizePass(); (void) llvm::createPartiallyInlineLibCallsPass(); + (void) llvm::createScalarizerPass(); + (void) llvm::createSeparateConstOffsetFromGEPPass(); (void)new llvm::IntervalPartition(); (void)new llvm::FindUsedTypes(); (void)new llvm::ScalarEvolution(); - ((llvm::Function*)0)->viewCFGOnly(); + ((llvm::Function*)nullptr)->viewCFGOnly(); llvm::RGPassManager RGM; - ((llvm::RegionPass*)0)->runOnRegion((llvm::Region*)0, RGM); - llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)0); - X.add((llvm::Value*)0, 0, 0); // for -print-alias-sets + ((llvm::RegionPass*)nullptr)->runOnRegion((llvm::Region*)nullptr, RGM); + llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)nullptr); + X.add((llvm::Value*)nullptr, 0, nullptr); // for -print-alias-sets } } ForcePassLinking; // Force link by creating a global definition. } diff --git a/include/llvm/Linker.h b/include/llvm/Linker/Linker.h index 4f37459eb403..6254bbb6d6d5 100644 --- a/include/llvm/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -1,4 +1,4 @@ -//===- llvm/Linker.h - Module Linker Interface ------------------*- C++ -*-===// +//===- Linker.h - Module Linker Interface -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,14 +7,16 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LINKER_H -#define LLVM_LINKER_H +#ifndef LLVM_LINKER_LINKER_H +#define LLVM_LINKER_LINKER_H #include "llvm/ADT/SmallPtrSet.h" #include <string> namespace llvm { +class Comdat; +class GlobalValue; class Module; class StringRef; class StructType; @@ -30,7 +32,7 @@ class Linker { PreserveSource = 1 // Preserve the source module. }; - Linker(Module *M); + Linker(Module *M, bool SuppressWarnings=false); ~Linker(); Module *getModule() const { return Composite; } @@ -52,6 +54,8 @@ class Linker { private: Module *Composite; SmallPtrSet<StructType*, 32> IdentifiedStructTypes; + + bool SuppressWarnings; }; } // End llvm namespace diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h new file mode 100644 index 000000000000..2e76074db774 --- /dev/null +++ b/include/llvm/MC/ConstantPools.h @@ -0,0 +1,92 @@ +//===- ConstantPool.h - Keep track of assembler-generated ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the ConstantPool and AssemblerConstantPools classes. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_MC_CONSTANTPOOL_H +#define LLVM_MC_CONSTANTPOOL_H + +#include "llvm/ADT/SmallVector.h" +namespace llvm { +class MCContext; +class MCExpr; +class MCSection; +class MCStreamer; +class MCSymbol; + +struct ConstantPoolEntry { + ConstantPoolEntry(MCSymbol *L, const MCExpr *Val, unsigned Sz) + : Label(L), Value(Val), Size(Sz) {} + MCSymbol *Label; + const MCExpr *Value; + unsigned Size; +}; + +// A class to keep track of assembler-generated constant pools that are use to +// implement the ldr-pseudo. +class ConstantPool { + typedef SmallVector<ConstantPoolEntry, 4> EntryVecTy; + EntryVecTy Entries; + +public: + // Initialize a new empty constant pool + ConstantPool() {} + + // Add a new entry to the constant pool in the next slot. + // \param Value is the new entry to put in the constant pool. + // \param Size is the size in bytes of the entry + // + // \returns a MCExpr that references the newly inserted value + const MCExpr *addEntry(const MCExpr *Value, MCContext &Context, + unsigned Size); + + // Emit the contents of the constant pool using the provided streamer. + void emitEntries(MCStreamer &Streamer); + + // Return true if the constant pool is empty + bool empty(); +}; + +class AssemblerConstantPools { + // Map type used to keep track of per-Section constant pools used by the + // ldr-pseudo opcode. The map associates a section to its constant pool. The + // constant pool is a vector of (label, value) pairs. When the ldr + // pseudo is parsed we insert a new (label, value) pair into the constant pool + // for the current section and add MCSymbolRefExpr to the new label as + // an opcode to the ldr. After we have parsed all the user input we + // output the (label, value) pairs in each constant pool at the end of the + // section. + // + // We use the MapVector for the map type to ensure stable iteration of + // the sections at the end of the parse. We need to iterate over the + // sections in a stable order to ensure that we have print the + // constant pools in a deterministic order when printing an assembly + // file. + typedef MapVector<const MCSection *, ConstantPool> ConstantPoolMapTy; + ConstantPoolMapTy ConstantPools; + +public: + AssemblerConstantPools() {} + ~AssemblerConstantPools() {} + + void emitAll(MCStreamer &Streamer); + void emitForCurrentSection(MCStreamer &Streamer); + const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr, + unsigned Size); + +private: + ConstantPool *getConstantPool(const MCSection *Section); + ConstantPool &getOrCreateConstantPool(const MCSection *Section); +}; +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCAtom.h b/include/llvm/MC/MCAnalysis/MCAtom.h index eab32d691fa8..33f3431a59a9 100644 --- a/include/llvm/MC/MCAtom.h +++ b/include/llvm/MC/MCAnalysis/MCAtom.h @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCAtom.h ----------------------------------------*- C++ -*-===// +//===-- MCAtom.h ------------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCATOM_H -#define LLVM_MC_MCATOM_H +#ifndef LLVM_MC_MCANALYSIS_MCATOM_H +#define LLVM_MC_MCANALYSIS_MCATOM_H #include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCInst.h" @@ -145,8 +145,8 @@ public: /// \name Atom type specific split/truncate logic. /// @{ - MCTextAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; - void truncate(uint64_t TruncPt) LLVM_OVERRIDE; + MCTextAtom *split(uint64_t SplitPt) override; + void truncate(uint64_t TruncPt) override; /// @} // Class hierarchy. @@ -179,8 +179,8 @@ public: /// \name Atom type specific split/truncate logic. /// @{ - MCDataAtom *split(uint64_t SplitPt) LLVM_OVERRIDE; - void truncate(uint64_t TruncPt) LLVM_OVERRIDE; + MCDataAtom *split(uint64_t SplitPt) override; + void truncate(uint64_t TruncPt) override; /// @} // Class hierarchy. diff --git a/include/llvm/MC/MCFunction.h b/include/llvm/MC/MCAnalysis/MCFunction.h index 22c9192ac4b5..44fa4503b8e0 100644 --- a/include/llvm/MC/MCFunction.h +++ b/include/llvm/MC/MCAnalysis/MCFunction.h @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCFunction.h ------------------------------------*- C++ -*-===// +//===-- MCFunction.h --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,11 +12,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCFUNCTION_H -#define LLVM_MC_MCFUNCTION_H +#ifndef LLVM_MC_MCANALYSIS_MCFUNCTION_H +#define LLVM_MC_MCANALYSIS_MCFUNCTION_H #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCInst.h" +#include <memory> #include <string> #include <vector> @@ -88,13 +89,12 @@ class MCFunction { std::string Name; MCModule *ParentModule; - typedef std::vector<MCBasicBlock*> BasicBlockListTy; + typedef std::vector<std::unique_ptr<MCBasicBlock>> BasicBlockListTy; BasicBlockListTy Blocks; // MCModule owns the function. friend class MCModule; MCFunction(StringRef Name, MCModule *Parent); - ~MCFunction(); public: /// \brief Create an MCBasicBlock backed by Insts and add it to this function. @@ -126,10 +126,10 @@ public: const_iterator end() const { return Blocks.end(); } iterator end() { return Blocks.end(); } - const MCBasicBlock* front() const { return Blocks.front(); } - MCBasicBlock* front() { return Blocks.front(); } - const MCBasicBlock* back() const { return Blocks.back(); } - MCBasicBlock* back() { return Blocks.back(); } + const MCBasicBlock* front() const { return Blocks.front().get(); } + MCBasicBlock* front() { return Blocks.front().get(); } + const MCBasicBlock* back() const { return Blocks.back().get(); } + MCBasicBlock* back() { return Blocks.back().get(); } /// \brief Find the basic block, if any, that starts at \p StartAddr. const MCBasicBlock *find(uint64_t StartAddr) const; diff --git a/include/llvm/MC/MCModule.h b/include/llvm/MC/MCAnalysis/MCModule.h index 63635c7478ce..cf7e2c0a645e 100644 --- a/include/llvm/MC/MCModule.h +++ b/include/llvm/MC/MCAnalysis/MCModule.h @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCModule.h - MCModule class ---------------------*- C++ -*-===// +//===-- MCModule.h - MCModule class -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,12 +12,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCMODULE_H -#define LLVM_MC_MCMODULE_H +#ifndef LLVM_MC_MCANALYSIS_MCMODULE_H +#define LLVM_MC_MCANALYSIS_MCMODULE_H #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include <memory> #include <vector> namespace llvm { @@ -73,7 +74,7 @@ class MCModule { /// \name Function tracking /// @{ - typedef std::vector<MCFunction*> FunctionListTy; + typedef std::vector<std::unique_ptr<MCFunction>> FunctionListTy; FunctionListTy Functions; /// @} @@ -87,7 +88,7 @@ class MCModule { friend class MCObjectDisassembler; public: - MCModule() : Entrypoint(0) { } + MCModule(); ~MCModule(); /// \name Create a new MCAtom covering the specified offset range. diff --git a/include/llvm/MC/MCModuleYAML.h b/include/llvm/MC/MCAnalysis/MCModuleYAML.h index 281e3d8dc912..48562777677b 100644 --- a/include/llvm/MC/MCModuleYAML.h +++ b/include/llvm/MC/MCAnalysis/MCModuleYAML.h @@ -13,12 +13,11 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCMODULEYAML_H -#define LLVM_MC_MCMODULEYAML_H +#ifndef LLVM_MC_MCANALYSIS_MCMODULEYAML_H +#define LLVM_MC_MCANALYSIS_MCMODULEYAML_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCModule.h" +#include "llvm/MC/MCAnalysis/MCModule.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -33,7 +32,7 @@ StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, /// \brief Creates a new module and returns it in \p MCM. /// \returns The empty string on success, an error message on failure. -StringRef yaml2mcmodule(OwningPtr<MCModule> &MCM, StringRef YamlContent, +StringRef yaml2mcmodule(std::unique_ptr<MCModule> &MCM, StringRef YamlContent, const MCInstrInfo &MII, const MCRegisterInfo &MRI); } // end namespace llvm diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index f946f41981c8..82b65fdaf5c8 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -38,7 +38,6 @@ class MCAsmBackend { protected: // Can only create subclasses. MCAsmBackend(); - unsigned HasReliableSymbolDifference : 1; unsigned HasDataInCodeSupport : 1; public: @@ -58,20 +57,6 @@ public: "backend"); } - /// hasReliableSymbolDifference - Check whether this target implements - /// accurate relocations for differences between symbols. If not, differences - /// between symbols will always be relocatable expressions and any references - /// to temporary symbols will be assumed to be in the same atom, unless they - /// reside in a different section. - /// - /// This should always be true (since it results in fewer relocations with no - /// loss of functionality), but is currently supported as a way to maintain - /// exact object compatibility with Darwin 'as' (on non-x86_64). It should - /// eventually should be eliminated. - bool hasReliableSymbolDifference() const { - return HasReliableSymbolDifference; - } - /// hasDataInCodeSupport - Check whether this target implements data-in-code /// markers. If not, data region directives will be ignored. bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } @@ -105,16 +90,14 @@ public: virtual void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, - MCValue &Target, uint64_t &Value, + const MCValue &Target, uint64_t &Value, bool &IsResolved) {} - /// @} - /// applyFixup - Apply the \p Value for given \p Fixup into the provided /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const = 0; + uint64_t Value, bool IsPCRel) const = 0; /// @} diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 9845623d4716..06e473d6b625 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -23,536 +23,496 @@ #include <vector> namespace llvm { - class MCExpr; - class MCSection; - class MCStreamer; - class MCSymbol; - class MCContext; - - namespace ExceptionHandling { - enum ExceptionsType { None, DwarfCFI, SjLj, ARM, Win64 }; - } +class MCExpr; +class MCSection; +class MCStreamer; +class MCSymbol; +class MCContext; + +namespace WinEH { +enum class EncodingType { + ET_Invalid, /// Invalid + ET_Alpha, /// Windows Alpha + ET_Alpha64, /// Windows AXP64 + ET_ARM, /// Windows NT (Windows on ARM) + ET_CE, /// Windows CE ARM, PowerPC, SH3, SH4 + ET_Itanium, /// Windows x64, Windows Itanium (IA-64) + ET_MIPS = ET_Alpha, +}; +} + +enum class ExceptionHandling { + None, /// No exception support + DwarfCFI, /// DWARF-like instruction based exceptions + SjLj, /// setjmp/longjmp based exceptions + ARM, /// ARM EHABI + WinEH, /// Windows Exception Handling +}; + +namespace LCOMM { +enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment }; +} + +/// This class is intended to be used as a base class for asm +/// properties and features specific to the target. +class MCAsmInfo { +protected: + //===------------------------------------------------------------------===// + // Properties to be set by the target writer, used to configure asm printer. + // + + /// Pointer size in bytes. Default is 4. + unsigned PointerSize; + + /// Size of the stack slot reserved for callee-saved registers, in bytes. + /// Default is same as pointer size. + unsigned CalleeSaveStackSlotSize; + + /// True if target is little endian. Default is true. + bool IsLittleEndian; + + /// True if target stack grow up. Default is false. + bool StackGrowsUp; + + /// True if this target has the MachO .subsections_via_symbols directive. + /// Default is false. + bool HasSubsectionsViaSymbols; + + /// True if this is a MachO target that supports the macho-specific .zerofill + /// directive for emitting BSS Symbols. Default is false. + bool HasMachoZeroFillDirective; + + /// True if this is a MachO target that supports the macho-specific .tbss + /// directive for emitting thread local BSS Symbols. Default is false. + bool HasMachoTBSSDirective; + + /// True if the compiler should emit a ".reference .constructors_used" or + /// ".reference .destructors_used" directive after the a static ctor/dtor + /// list. This directive is only emitted in Static relocation model. Default + /// is false. + bool HasStaticCtorDtorReferenceInStaticMode; + + /// True if the linker has a bug and requires that the debug_line section be + /// of a minimum size. In practice such a linker requires a non-empty line + /// sequence if a file is present. Default to false. + bool LinkerRequiresNonEmptyDwarfLines; + + /// This is the maximum possible length of an instruction, which is needed to + /// compute the size of an inline asm. Defaults to 4. + unsigned MaxInstLength; + + /// Every possible instruction length is a multiple of this value. Factored + /// out in .debug_frame and .debug_line. Defaults to 1. + unsigned MinInstAlignment; + + /// The '$' token, when not referencing an identifier or constant, refers to + /// the current PC. Defaults to false. + bool DollarIsPC; + + /// This string, if specified, is used to separate instructions from each + /// other when on the same line. Defaults to ';' + const char *SeparatorString; + + /// This indicates the comment character used by the assembler. Defaults to + /// "#" + const char *CommentString; + + /// This is appended to emitted labels. Defaults to ":" + const char *LabelSuffix; + + // Print the EH begin symbol with an assignment. Defaults to false. + bool UseAssignmentForEHBegin; + + /// This prefix is used for globals like constant pool entries that are + /// completely private to the .s file and should not have names in the .o + /// file. Defaults to "L" + const char *PrivateGlobalPrefix; + + /// This prefix is used for symbols that should be passed through the + /// assembler but be removed by the linker. This is 'l' on Darwin, currently + /// used for some ObjC metadata. The default of "" meast that for this system + /// a plain private symbol should be used. Defaults to "". + const char *LinkerPrivateGlobalPrefix; + + /// If these are nonempty, they contain a directive to emit before and after + /// an inline assembly statement. Defaults to "#APP\n", "#NO_APP\n" + const char *InlineAsmStart; + const char *InlineAsmEnd; + + /// These are assembly directives that tells the assembler to interpret the + /// following instructions differently. Defaults to ".code16", ".code32", + /// ".code64". + const char *Code16Directive; + const char *Code32Directive; + const char *Code64Directive; + + /// Which dialect of an assembler variant to use. Defaults to 0 + unsigned AssemblerDialect; + + /// This is true if the assembler allows @ characters in symbol names. + /// Defaults to false. + bool AllowAtInName; + + /// This is true if data region markers should be printed as + /// ".data_region/.end_data_region" directives. If false, use "$d/$a" labels + /// instead. + bool UseDataRegionDirectives; + + //===--- Data Emission Directives -------------------------------------===// + + /// This should be set to the directive used to get some number of zero bytes + /// emitted to the current section. Common cases are "\t.zero\t" and + /// "\t.space\t". If this is set to null, the Data*bitsDirective's will be + /// used to emit zero bytes. Defaults to "\t.zero\t" + const char *ZeroDirective; + + /// This directive allows emission of an ascii string with the standard C + /// escape characters embedded into it. Defaults to "\t.ascii\t" + const char *AsciiDirective; + + /// If not null, this allows for special handling of zero terminated strings + /// on this target. This is commonly supported as ".asciz". If a target + /// doesn't support this, it can be set to null. Defaults to "\t.asciz\t" + const char *AscizDirective; + + /// These directives are used to output some unit of integer data to the + /// current section. If a data directive is set to null, smaller data + /// directives will be used to emit the large sizes. Defaults to "\t.byte\t", + /// "\t.short\t", "\t.long\t", "\t.quad\t" + const char *Data8bitsDirective; + const char *Data16bitsDirective; + const char *Data32bitsDirective; + const char *Data64bitsDirective; + + /// If non-null, a directive that is used to emit a word which should be + /// relocated as a 64-bit GP-relative offset, e.g. .gpdword on Mips. Defaults + /// to NULL. + const char *GPRel64Directive; + + /// If non-null, a directive that is used to emit a word which should be + /// relocated as a 32-bit GP-relative offset, e.g. .gpword on Mips or .gprel32 + /// on Alpha. Defaults to NULL. + const char *GPRel32Directive; + + /// This is true if this target uses "Sun Style" syntax for section switching + /// ("#alloc,#write" etc) instead of the normal ELF syntax (,"a,w") in + /// .section directives. Defaults to false. + bool SunStyleELFSectionSwitchSyntax; + + /// This is true if this target uses ELF '.section' directive before the + /// '.bss' one. It's used for PPC/Linux which doesn't support the '.bss' + /// directive only. Defaults to false. + bool UsesELFSectionDirectiveForBSS; + + bool NeedsDwarfSectionOffsetDirective; + + //===--- Alignment Information ----------------------------------------===// + + /// If this is true (the default) then the asmprinter emits ".align N" + /// directives, where N is the number of bytes to align to. Otherwise, it + /// emits ".align log2(N)", e.g. 3 to align to an 8 byte boundary. Defaults + /// to true. + bool AlignmentIsInBytes; + + /// If non-zero, this is used to fill the executable space created as the + /// result of a alignment directive. Defaults to 0 + unsigned TextAlignFillValue; + + //===--- Global Variable Emission Directives --------------------------===// + + /// This is the directive used to declare a global entity. Defaults to NULL. + const char *GlobalDirective; + + /// True if the assembler supports the .set directive. Defaults to true. + bool HasSetDirective; + + /// False if the assembler requires that we use + /// \code + /// Lc = a - b + /// .long Lc + /// \endcode + // + /// instead of + // + /// \code + /// .long a - b + /// \endcode + /// + /// Defaults to true. + bool HasAggressiveSymbolFolding; + + /// True is .comm's and .lcomms optional alignment is to be specified in bytes + /// instead of log2(n). Defaults to true. + bool COMMDirectiveAlignmentIsInBytes; + + /// Describes if the .lcomm directive for the target supports an alignment + /// argument and how it is interpreted. Defaults to NoAlignment. + LCOMM::LCOMMType LCOMMDirectiveAlignmentType; + + /// True if the target has .type and .size directives, this is true for most + /// ELF targets. Defaults to true. + bool HasDotTypeDotSizeDirective; + + /// True if the target has a single parameter .file directive, this is true + /// for ELF targets. Defaults to true. + bool HasSingleParameterDotFile; + + /// True if the target has a .ident directive, this is true for ELF targets. + /// Defaults to false. + bool HasIdentDirective; + + /// True if this target supports the MachO .no_dead_strip directive. Defaults + /// to false. + bool HasNoDeadStrip; + + /// This directive, if non-null, is used to declare a global as being a weak + /// undefined symbol. Defaults to NULL. + const char *WeakRefDirective; + + /// True if we have a directive to declare a global as being a weak defined + /// symbol. Defaults to false. + bool HasWeakDefDirective; + + /// True if we have a directive to declare a global as being a weak defined + /// symbol that can be hidden (unexported). Defaults to false. + bool HasWeakDefCanBeHiddenDirective; + + /// True if we have a .linkonce directive. This is used on cygwin/mingw. + /// Defaults to false. + bool HasLinkOnceDirective; + + /// This attribute, if not MCSA_Invalid, is used to declare a symbol as having + /// hidden visibility. Defaults to MCSA_Hidden. + MCSymbolAttr HiddenVisibilityAttr; + + /// This attribute, if not MCSA_Invalid, is used to declare an undefined + /// symbol as having hidden visibility. Defaults to MCSA_Hidden. + MCSymbolAttr HiddenDeclarationVisibilityAttr; + + /// This attribute, if not MCSA_Invalid, is used to declare a symbol as having + /// protected visibility. Defaults to MCSA_Protected + MCSymbolAttr ProtectedVisibilityAttr; + + //===--- Dwarf Emission Directives -----------------------------------===// + + /// True if target asm supports leb128 directives. Defaults to false. + bool HasLEB128; + + /// True if target supports emission of debugging information. Defaults to + /// false. + bool SupportsDebugInformation; + + /// Exception handling format for the target. Defaults to None. + ExceptionHandling ExceptionsType; + + /// Windows exception handling data (.pdata) encoding. Defaults to Invalid. + WinEH::EncodingType WinEHEncodingType; - namespace LCOMM { - enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment }; + /// True if Dwarf2 output generally uses relocations for references to other + /// .debug_* sections. + bool DwarfUsesRelocationsAcrossSections; + + /// True if DWARF FDE symbol reference relocations should be replaced by an + /// absolute difference. + bool DwarfFDESymbolsUseAbsDiff; + + /// True if dwarf register numbers are printed instead of symbolic register + /// names in .cfi_* directives. Defaults to false. + bool DwarfRegNumForCFI; + + /// True if target uses parens to indicate the symbol variant instead of @. + /// For example, foo(plt) instead of foo@plt. Defaults to false. + bool UseParensForSymbolVariant; + + //===--- Prologue State ----------------------------------------------===// + + std::vector<MCCFIInstruction> InitialFrameState; + + //===--- Integrated Assembler State ----------------------------------===// + + /// Should we use the integrated assembler? + /// The integrated assembler should be enabled by default (by the + /// constructors) when failing to parse a valid piece of assembly (inline + /// or otherwise) is considered a bug. It may then be overridden after + /// construction (see LLVMTargetMachine::initAsmInfo()). + bool UseIntegratedAssembler; + + /// Compress DWARF debug sections. Defaults to false. + bool CompressDebugSections; + +public: + explicit MCAsmInfo(); + virtual ~MCAsmInfo(); + + /// Get the pointer size in bytes. + unsigned getPointerSize() const { return PointerSize; } + + /// Get the callee-saved register stack slot + /// size in bytes. + unsigned getCalleeSaveStackSlotSize() const { + return CalleeSaveStackSlotSize; } - /// MCAsmInfo - This class is intended to be used as a base class for asm - /// properties and features specific to the target. - class MCAsmInfo { - protected: - //===------------------------------------------------------------------===// - // Properties to be set by the target writer, used to configure asm printer. - // - - /// PointerSize - Pointer size in bytes. - /// Default is 4. - unsigned PointerSize; - - /// CalleeSaveStackSlotSize - Size of the stack slot reserved for - /// callee-saved registers, in bytes. - /// Default is same as pointer size. - unsigned CalleeSaveStackSlotSize; - - /// IsLittleEndian - True if target is little endian. - /// Default is true. - bool IsLittleEndian; - - /// StackGrowsUp - True if target stack grow up. - /// Default is false. - bool StackGrowsUp; - - /// HasSubsectionsViaSymbols - True if this target has the MachO - /// .subsections_via_symbols directive. - bool HasSubsectionsViaSymbols; // Default is false. - - /// HasMachoZeroFillDirective - True if this is a MachO target that supports - /// the macho-specific .zerofill directive for emitting BSS Symbols. - bool HasMachoZeroFillDirective; // Default is false. - - /// HasMachoTBSSDirective - True if this is a MachO target that supports - /// the macho-specific .tbss directive for emitting thread local BSS Symbols - bool HasMachoTBSSDirective; // Default is false. - - /// HasStaticCtorDtorReferenceInStaticMode - True if the compiler should - /// emit a ".reference .constructors_used" or ".reference .destructors_used" - /// directive after the a static ctor/dtor list. This directive is only - /// emitted in Static relocation model. - bool HasStaticCtorDtorReferenceInStaticMode; // Default is false. - - /// LinkerRequiresNonEmptyDwarfLines - True if the linker has a bug and - /// requires that the debug_line section be of a minimum size. In practice - /// such a linker requires a non empty line sequence if a file is present. - bool LinkerRequiresNonEmptyDwarfLines; // Default to false. - - /// MaxInstLength - This is the maximum possible length of an instruction, - /// which is needed to compute the size of an inline asm. - unsigned MaxInstLength; // Defaults to 4. - - /// MinInstAlignment - Every possible instruction length is a multiple of - /// this value. Factored out in .debug_frame and .debug_line. - unsigned MinInstAlignment; // Defaults to 1. - - /// DollarIsPC - The '$' token, when not referencing an identifier or - /// constant, refers to the current PC. - bool DollarIsPC; // Defaults to false. - - /// SeparatorString - This string, if specified, is used to separate - /// instructions from each other when on the same line. - const char *SeparatorString; // Defaults to ';' - - /// CommentColumn - This indicates the comment num (zero-based) at - /// which asm comments should be printed. - unsigned CommentColumn; // Defaults to 40 - - /// CommentString - This indicates the comment character used by the - /// assembler. - const char *CommentString; // Defaults to "#" - - /// LabelSuffix - This is appended to emitted labels. - const char *LabelSuffix; // Defaults to ":" - - /// LabelSuffix - This is appended to emitted labels. - const char *DebugLabelSuffix; // Defaults to ":" - - /// GlobalPrefix - If this is set to a non-empty string, it is prepended - /// onto all global symbols. This is often used for "_" or ".". - const char *GlobalPrefix; // Defaults to "" - - /// PrivateGlobalPrefix - This prefix is used for globals like constant - /// pool entries that are completely private to the .s file and should not - /// have names in the .o file. This is often "." or "L". - const char *PrivateGlobalPrefix; // Defaults to "." - - /// LinkerPrivateGlobalPrefix - This prefix is used for symbols that should - /// be passed through the assembler but be removed by the linker. This - /// is "l" on Darwin, currently used for some ObjC metadata. - const char *LinkerPrivateGlobalPrefix; // Defaults to "" - - /// InlineAsmStart/End - If these are nonempty, they contain a directive to - /// emit before and after an inline assembly statement. - const char *InlineAsmStart; // Defaults to "#APP\n" - const char *InlineAsmEnd; // Defaults to "#NO_APP\n" - - /// Code16Directive, Code32Directive, Code64Directive - These are assembly - /// directives that tells the assembler to interpret the following - /// instructions differently. - const char *Code16Directive; // Defaults to ".code16" - const char *Code32Directive; // Defaults to ".code32" - const char *Code64Directive; // Defaults to ".code64" - - /// AssemblerDialect - Which dialect of an assembler variant to use. - unsigned AssemblerDialect; // Defaults to 0 - - /// \brief This is true if the assembler allows @ characters in symbol - /// names. Defaults to false. - bool AllowAtInName; - - /// UseDataRegionDirectives - This is true if data region markers should - /// be printed as ".data_region/.end_data_region" directives. If false, - /// use "$d/$a" labels instead. - bool UseDataRegionDirectives; - - //===--- Data Emission Directives -------------------------------------===// - - /// ZeroDirective - this should be set to the directive used to get some - /// number of zero bytes emitted to the current section. Common cases are - /// "\t.zero\t" and "\t.space\t". If this is set to null, the - /// Data*bitsDirective's will be used to emit zero bytes. - const char *ZeroDirective; // Defaults to "\t.zero\t" - - /// AsciiDirective - This directive allows emission of an ascii string with - /// the standard C escape characters embedded into it. - const char *AsciiDirective; // Defaults to "\t.ascii\t" - - /// AscizDirective - If not null, this allows for special handling of - /// zero terminated strings on this target. This is commonly supported as - /// ".asciz". If a target doesn't support this, it can be set to null. - const char *AscizDirective; // Defaults to "\t.asciz\t" - - /// DataDirectives - These directives are used to output some unit of - /// integer data to the current section. If a data directive is set to - /// null, smaller data directives will be used to emit the large sizes. - const char *Data8bitsDirective; // Defaults to "\t.byte\t" - const char *Data16bitsDirective; // Defaults to "\t.short\t" - const char *Data32bitsDirective; // Defaults to "\t.long\t" - const char *Data64bitsDirective; // Defaults to "\t.quad\t" - - /// GPRel64Directive - if non-null, a directive that is used to emit a word - /// which should be relocated as a 64-bit GP-relative offset, e.g. .gpdword - /// on Mips. - const char *GPRel64Directive; // Defaults to NULL. - - /// GPRel32Directive - if non-null, a directive that is used to emit a word - /// which should be relocated as a 32-bit GP-relative offset, e.g. .gpword - /// on Mips or .gprel32 on Alpha. - const char *GPRel32Directive; // Defaults to NULL. - - /// SunStyleELFSectionSwitchSyntax - This is true if this target uses "Sun - /// Style" syntax for section switching ("#alloc,#write" etc) instead of the - /// normal ELF syntax (,"a,w") in .section directives. - bool SunStyleELFSectionSwitchSyntax; // Defaults to false. - - /// UsesELFSectionDirectiveForBSS - This is true if this target uses ELF - /// '.section' directive before the '.bss' one. It's used for PPC/Linux - /// which doesn't support the '.bss' directive only. - bool UsesELFSectionDirectiveForBSS; // Defaults to false. - - /// HasMicrosoftFastStdCallMangling - True if this target uses microsoft - /// style mangling for functions with X86_StdCall/X86_FastCall calling - /// convention. - bool HasMicrosoftFastStdCallMangling; // Defaults to false. - - bool NeedsDwarfSectionOffsetDirective; - - //===--- Alignment Information ----------------------------------------===// - - /// AlignDirective - The directive used to emit round up to an alignment - /// boundary. - /// - const char *AlignDirective; // Defaults to "\t.align\t" - - /// AlignmentIsInBytes - If this is true (the default) then the asmprinter - /// emits ".align N" directives, where N is the number of bytes to align to. - /// Otherwise, it emits ".align log2(N)", e.g. 3 to align to an 8 byte - /// boundary. - bool AlignmentIsInBytes; // Defaults to true + /// True if the target is little endian. + bool isLittleEndian() const { return IsLittleEndian; } - /// TextAlignFillValue - If non-zero, this is used to fill the executable - /// space created as the result of a alignment directive. - unsigned TextAlignFillValue; // Defaults to 0 + /// True if target stack grow up. + bool isStackGrowthDirectionUp() const { return StackGrowsUp; } - //===--- Global Variable Emission Directives --------------------------===// + bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } - /// GlobalDirective - This is the directive used to declare a global entity. - /// - const char *GlobalDirective; // Defaults to NULL. + // Data directive accessors. - /// HasSetDirective - True if the assembler supports the .set directive. - bool HasSetDirective; // Defaults to true. + const char *getData8bitsDirective() const { return Data8bitsDirective; } + const char *getData16bitsDirective() const { return Data16bitsDirective; } + const char *getData32bitsDirective() const { return Data32bitsDirective; } + const char *getData64bitsDirective() const { return Data64bitsDirective; } + const char *getGPRel64Directive() const { return GPRel64Directive; } + const char *getGPRel32Directive() const { return GPRel32Directive; } + + /// Targets can implement this method to specify a section to switch to if the + /// translation unit doesn't have any trampolines that require an executable + /// stack. + virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const { + return nullptr; + } - /// HasAggressiveSymbolFolding - False if the assembler requires that we use - /// Lc = a - b - /// .long Lc - /// instead of - /// .long a - b - bool HasAggressiveSymbolFolding; // Defaults to true. + virtual const MCExpr *getExprForPersonalitySymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; - /// COMMDirectiveAlignmentIsInBytes - True is .comm's and .lcomms optional - /// alignment is to be specified in bytes instead of log2(n). - bool COMMDirectiveAlignmentIsInBytes; // Defaults to true; + virtual const MCExpr *getExprForFDESymbol(const MCSymbol *Sym, + unsigned Encoding, + MCStreamer &Streamer) const; - /// LCOMMDirectiveAlignment - Describes if the .lcomm directive for the - /// target supports an alignment argument and how it is interpreted. - LCOMM::LCOMMType LCOMMDirectiveAlignmentType; // Defaults to NoAlignment. - - /// HasDotTypeDotSizeDirective - True if the target has .type and .size - /// directives, this is true for most ELF targets. - bool HasDotTypeDotSizeDirective; // Defaults to true. + bool usesSunStyleELFSectionSwitchSyntax() const { + return SunStyleELFSectionSwitchSyntax; + } + + bool usesELFSectionDirectiveForBSS() const { + return UsesELFSectionDirectiveForBSS; + } - /// HasSingleParameterDotFile - True if the target has a single parameter - /// .file directive, this is true for ELF targets. - bool HasSingleParameterDotFile; // Defaults to true. - - /// hasIdentDirective - True if the target has a .ident directive, this is - /// true for ELF targets. - bool HasIdentDirective; // Defaults to false. - - /// HasNoDeadStrip - True if this target supports the MachO .no_dead_strip - /// directive. - bool HasNoDeadStrip; // Defaults to false. - - /// WeakRefDirective - This directive, if non-null, is used to declare a - /// global as being a weak undefined symbol. - const char *WeakRefDirective; // Defaults to NULL. - - /// True if we have a directive to declare a global as being a weak - /// defined symbol. - bool HasWeakDefDirective; // Defaults to false. - - /// True if we have a directive to declare a global as being a weak - /// defined symbol that can be hidden (unexported). - bool HasWeakDefCanBeHiddenDirective; // Defaults to false. - - /// True if we have a .linkonce directive. This is used on cygwin/mingw. - bool HasLinkOnceDirective; // Defaults to false. - - /// HiddenVisibilityAttr - This attribute, if not MCSA_Invalid, is used to - /// declare a symbol as having hidden visibility. - MCSymbolAttr HiddenVisibilityAttr; // Defaults to MCSA_Hidden. - - /// HiddenDeclarationVisibilityAttr - This attribute, if not MCSA_Invalid, - /// is used to declare an undefined symbol as having hidden visibility. - MCSymbolAttr HiddenDeclarationVisibilityAttr; // Defaults to MCSA_Hidden. - - - /// ProtectedVisibilityAttr - This attribute, if not MCSA_Invalid, is used - /// to declare a symbol as having protected visibility. - MCSymbolAttr ProtectedVisibilityAttr; // Defaults to MCSA_Protected - - //===--- Dwarf Emission Directives -----------------------------------===// - - /// HasLEB128 - True if target asm supports leb128 directives. - bool HasLEB128; // Defaults to false. - - /// SupportsDebugInformation - True if target supports emission of debugging - /// information. - bool SupportsDebugInformation; // Defaults to false. - - /// SupportsExceptionHandling - True if target supports exception handling. - ExceptionHandling::ExceptionsType ExceptionsType; // Defaults to None - - /// DwarfUsesRelocationsAcrossSections - True if Dwarf2 output generally - /// uses relocations for references to other .debug_* sections. - bool DwarfUsesRelocationsAcrossSections; - - /// DwarfFDESymbolsUseAbsDiff - true if DWARF FDE symbol reference - /// relocations should be replaced by an absolute difference. - bool DwarfFDESymbolsUseAbsDiff; - - /// DwarfRegNumForCFI - True if dwarf register numbers are printed - /// instead of symbolic register names in .cfi_* directives. - bool DwarfRegNumForCFI; // Defaults to false; - - //===--- Prologue State ----------------------------------------------===// - - std::vector<MCCFIInstruction> InitialFrameState; - - public: - explicit MCAsmInfo(); - virtual ~MCAsmInfo(); - - // FIXME: move these methods to DwarfPrinter when the JIT stops using them. - static unsigned getSLEB128Size(int64_t Value); - static unsigned getULEB128Size(uint64_t Value); - - /// getPointerSize - Get the pointer size in bytes. - unsigned getPointerSize() const { - return PointerSize; - } - - /// getCalleeSaveStackSlotSize - Get the callee-saved register stack slot - /// size in bytes. - unsigned getCalleeSaveStackSlotSize() const { - return CalleeSaveStackSlotSize; - } - - /// isLittleEndian - True if the target is little endian. - bool isLittleEndian() const { - return IsLittleEndian; - } - - /// isStackGrowthDirectionUp - True if target stack grow up. - bool isStackGrowthDirectionUp() const { - return StackGrowsUp; - } - - bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } - - // Data directive accessors. - // - const char *getData8bitsDirective() const { - return Data8bitsDirective; - } - const char *getData16bitsDirective() const { - return Data16bitsDirective; - } - const char *getData32bitsDirective() const { - return Data32bitsDirective; - } - const char *getData64bitsDirective() const { - return Data64bitsDirective; - } - const char *getGPRel64Directive() const { return GPRel64Directive; } - const char *getGPRel32Directive() const { return GPRel32Directive; } - - /// getNonexecutableStackSection - Targets can implement this method to - /// specify a section to switch to if the translation unit doesn't have any - /// trampolines that require an executable stack. - virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const{ - return 0; - } - - virtual const MCExpr * - getExprForPersonalitySymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const; - - const MCExpr * - getExprForFDESymbol(const MCSymbol *Sym, - unsigned Encoding, - MCStreamer &Streamer) const; - - bool usesSunStyleELFSectionSwitchSyntax() const { - return SunStyleELFSectionSwitchSyntax; - } - - bool usesELFSectionDirectiveForBSS() const { - return UsesELFSectionDirectiveForBSS; - } - - bool hasMicrosoftFastStdCallMangling() const { - return HasMicrosoftFastStdCallMangling; - } - - bool needsDwarfSectionOffsetDirective() const { - return NeedsDwarfSectionOffsetDirective; - } - - // Accessors. - // - bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } - bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } - bool hasStaticCtorDtorReferenceInStaticMode() const { - return HasStaticCtorDtorReferenceInStaticMode; - } - bool getLinkerRequiresNonEmptyDwarfLines() const { - return LinkerRequiresNonEmptyDwarfLines; - } - unsigned getMaxInstLength() const { - return MaxInstLength; - } - unsigned getMinInstAlignment() const { - return MinInstAlignment; - } - bool getDollarIsPC() const { - return DollarIsPC; - } - const char *getSeparatorString() const { - return SeparatorString; - } - unsigned getCommentColumn() const { - return CommentColumn; - } - const char *getCommentString() const { - return CommentString; - } - const char *getLabelSuffix() const { - return LabelSuffix; - } - - const char *getDebugLabelSuffix() const { - return DebugLabelSuffix; - } - - const char *getGlobalPrefix() const { - return GlobalPrefix; - } - const char *getPrivateGlobalPrefix() const { - return PrivateGlobalPrefix; - } - const char *getLinkerPrivateGlobalPrefix() const { + bool needsDwarfSectionOffsetDirective() const { + return NeedsDwarfSectionOffsetDirective; + } + + // Accessors. + + bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } + bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } + bool hasStaticCtorDtorReferenceInStaticMode() const { + return HasStaticCtorDtorReferenceInStaticMode; + } + bool getLinkerRequiresNonEmptyDwarfLines() const { + return LinkerRequiresNonEmptyDwarfLines; + } + unsigned getMaxInstLength() const { return MaxInstLength; } + unsigned getMinInstAlignment() const { return MinInstAlignment; } + bool getDollarIsPC() const { return DollarIsPC; } + const char *getSeparatorString() const { return SeparatorString; } + + /// This indicates the column (zero-based) at which asm comments should be + /// printed. + unsigned getCommentColumn() const { return 40; } + + const char *getCommentString() const { return CommentString; } + const char *getLabelSuffix() const { return LabelSuffix; } + + bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; } + const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } + bool hasLinkerPrivateGlobalPrefix() const { + return LinkerPrivateGlobalPrefix[0] != '\0'; + } + const char *getLinkerPrivateGlobalPrefix() const { + if (hasLinkerPrivateGlobalPrefix()) return LinkerPrivateGlobalPrefix; - } - const char *getInlineAsmStart() const { - return InlineAsmStart; - } - const char *getInlineAsmEnd() const { - return InlineAsmEnd; - } - const char *getCode16Directive() const { - return Code16Directive; - } - const char *getCode32Directive() const { - return Code32Directive; - } - const char *getCode64Directive() const { - return Code64Directive; - } - unsigned getAssemblerDialect() const { - return AssemblerDialect; - } - bool doesAllowAtInName() const { - return AllowAtInName; - } - bool doesSupportDataRegionDirectives() const { - return UseDataRegionDirectives; - } - const char *getZeroDirective() const { - return ZeroDirective; - } - const char *getAsciiDirective() const { - return AsciiDirective; - } - const char *getAscizDirective() const { - return AscizDirective; - } - const char *getAlignDirective() const { - return AlignDirective; - } - bool getAlignmentIsInBytes() const { - return AlignmentIsInBytes; - } - unsigned getTextAlignFillValue() const { - return TextAlignFillValue; - } - const char *getGlobalDirective() const { - return GlobalDirective; - } - bool hasSetDirective() const { return HasSetDirective; } - bool hasAggressiveSymbolFolding() const { - return HasAggressiveSymbolFolding; - } - bool getCOMMDirectiveAlignmentIsInBytes() const { - return COMMDirectiveAlignmentIsInBytes; - } - LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const { - return LCOMMDirectiveAlignmentType; - } - bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} - bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } - bool hasIdentDirective() const { return HasIdentDirective; } - bool hasNoDeadStrip() const { return HasNoDeadStrip; } - const char *getWeakRefDirective() const { return WeakRefDirective; } - bool hasWeakDefDirective() const { return HasWeakDefDirective; } - bool hasWeakDefCanBeHiddenDirective() const { - return HasWeakDefCanBeHiddenDirective; - } - bool hasLinkOnceDirective() const { return HasLinkOnceDirective; } - - MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;} - MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { - return HiddenDeclarationVisibilityAttr; - } - MCSymbolAttr getProtectedVisibilityAttr() const { - return ProtectedVisibilityAttr; - } - bool hasLEB128() const { - return HasLEB128; - } - bool doesSupportDebugInformation() const { - return SupportsDebugInformation; - } - bool doesSupportExceptionHandling() const { - return ExceptionsType != ExceptionHandling::None; - } - ExceptionHandling::ExceptionsType getExceptionHandlingType() const { - return ExceptionsType; - } - bool isExceptionHandlingDwarf() const { - return - (ExceptionsType == ExceptionHandling::DwarfCFI || - ExceptionsType == ExceptionHandling::ARM || - ExceptionsType == ExceptionHandling::Win64); - } - bool doesDwarfUseRelocationsAcrossSections() const { - return DwarfUsesRelocationsAcrossSections; - } - bool doDwarfFDESymbolsUseAbsDiff() const { - return DwarfFDESymbolsUseAbsDiff; - } - bool useDwarfRegNumForCFI() const { - return DwarfRegNumForCFI; - } - - void addInitialFrameState(const MCCFIInstruction &Inst) { - InitialFrameState.push_back(Inst); - } - - const std::vector<MCCFIInstruction> &getInitialFrameState() const { - return InitialFrameState; - } - }; + return getPrivateGlobalPrefix(); + } + const char *getInlineAsmStart() const { return InlineAsmStart; } + const char *getInlineAsmEnd() const { return InlineAsmEnd; } + const char *getCode16Directive() const { return Code16Directive; } + const char *getCode32Directive() const { return Code32Directive; } + const char *getCode64Directive() const { return Code64Directive; } + unsigned getAssemblerDialect() const { return AssemblerDialect; } + bool doesAllowAtInName() const { return AllowAtInName; } + bool doesSupportDataRegionDirectives() const { + return UseDataRegionDirectives; + } + const char *getZeroDirective() const { return ZeroDirective; } + const char *getAsciiDirective() const { return AsciiDirective; } + const char *getAscizDirective() const { return AscizDirective; } + bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; } + unsigned getTextAlignFillValue() const { return TextAlignFillValue; } + const char *getGlobalDirective() const { return GlobalDirective; } + bool hasSetDirective() const { return HasSetDirective; } + bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; } + bool getCOMMDirectiveAlignmentIsInBytes() const { + return COMMDirectiveAlignmentIsInBytes; + } + LCOMM::LCOMMType getLCOMMDirectiveAlignmentType() const { + return LCOMMDirectiveAlignmentType; + } + bool hasDotTypeDotSizeDirective() const { return HasDotTypeDotSizeDirective; } + bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } + bool hasIdentDirective() const { return HasIdentDirective; } + bool hasNoDeadStrip() const { return HasNoDeadStrip; } + const char *getWeakRefDirective() const { return WeakRefDirective; } + bool hasWeakDefDirective() const { return HasWeakDefDirective; } + bool hasWeakDefCanBeHiddenDirective() const { + return HasWeakDefCanBeHiddenDirective; + } + bool hasLinkOnceDirective() const { return HasLinkOnceDirective; } + + MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr; } + MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { + return HiddenDeclarationVisibilityAttr; + } + MCSymbolAttr getProtectedVisibilityAttr() const { + return ProtectedVisibilityAttr; + } + bool hasLEB128() const { return HasLEB128; } + bool doesSupportDebugInformation() const { return SupportsDebugInformation; } + bool doesSupportExceptionHandling() const { + return ExceptionsType != ExceptionHandling::None; + } + ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } + WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } + bool isExceptionHandlingDwarf() const { + return (ExceptionsType == ExceptionHandling::DwarfCFI || + ExceptionsType == ExceptionHandling::ARM || + // Windows handler data still uses DWARF LSDA encoding. + ExceptionsType == ExceptionHandling::WinEH); + } + bool doesDwarfUseRelocationsAcrossSections() const { + return DwarfUsesRelocationsAcrossSections; + } + bool doDwarfFDESymbolsUseAbsDiff() const { return DwarfFDESymbolsUseAbsDiff; } + bool useDwarfRegNumForCFI() const { return DwarfRegNumForCFI; } + bool useParensForSymbolVariant() const { return UseParensForSymbolVariant; } + + void addInitialFrameState(const MCCFIInstruction &Inst) { + InitialFrameState.push_back(Inst); + } + + const std::vector<MCCFIInstruction> &getInitialFrameState() const { + return InitialFrameState; + } + + /// Return true if assembly (inline or otherwise) should be parsed. + bool useIntegratedAssembler() const { return UseIntegratedAssembler; } + + /// Set whether assembly (inline or otherwise) should be parsed. + virtual void setUseIntegratedAssembler(bool Value) { + UseIntegratedAssembler = Value; + } + + bool compressDebugSections() const { return CompressDebugSections; } + + void setCompressDebugSections(bool CompressDebugSections) { + this->CompressDebugSections = CompressDebugSections; + } +}; } #endif diff --git a/include/llvm/MC/MCAsmInfoCOFF.h b/include/llvm/MC/MCAsmInfoCOFF.h index 7286151760c0..56444f3c7cf5 100644 --- a/include/llvm/MC/MCAsmInfoCOFF.h +++ b/include/llvm/MC/MCAsmInfoCOFF.h @@ -20,13 +20,13 @@ namespace llvm { }; class MCAsmInfoMicrosoft : public MCAsmInfoCOFF { - virtual void anchor(); + void anchor() override; protected: explicit MCAsmInfoMicrosoft(); }; class MCAsmInfoGNUCOFF : public MCAsmInfoCOFF { - virtual void anchor(); + void anchor() override; protected: explicit MCAsmInfoGNUCOFF(); }; diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index 3058b7b48742..f048e34671db 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -17,6 +17,7 @@ namespace llvm { class MCAssembler; class MCFragment; class MCSectionData; +class MCSymbol; class MCSymbolData; /// Encapsulates the layout of an assembly file at a particular point in time. @@ -102,8 +103,15 @@ public: /// \brief Get the offset of the given symbol, as computed in the current /// layout. + /// \result True on success. + bool getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const; + + /// \brief Variant that reports a fatal error if the offset is not computable. uint64_t getSymbolOffset(const MCSymbolData *SD) const; + /// \brief If this symbol is equivalent to A + Constant, return A. + const MCSymbol *getBaseSymbol(const MCSymbol &Symbol) const; + /// @} }; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 8735a55ce044..1cb34c2fe33b 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -15,8 +15,11 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCLinkerOptimizationHint.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" #include <algorithm> @@ -33,6 +36,7 @@ class MCFragment; class MCObjectWriter; class MCSection; class MCSectionData; +class MCSubtargetInfo; class MCSymbol; class MCSymbolData; class MCValue; @@ -64,8 +68,7 @@ private: MCSectionData *Parent; /// Atom - The atom this fragment is in, as represented by it's defining - /// symbol. Atom's are only used by backends which set - /// \see MCAsmBackend::hasReliableSymbolDifference(). + /// symbol. MCSymbolData *Atom; /// @name Assembler Backend Data @@ -83,7 +86,7 @@ private: /// @} protected: - MCFragment(FragmentType _Kind, MCSectionData *_Parent = 0); + MCFragment(FragmentType _Kind, MCSectionData *_Parent = nullptr); public: // Only for sentinel. @@ -134,7 +137,7 @@ class MCEncodedFragment : public MCFragment { uint8_t BundlePadding; public: - MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = 0) + MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = nullptr) : MCFragment(FType, SD), BundlePadding(0) { } @@ -143,11 +146,11 @@ public: virtual SmallVectorImpl<char> &getContents() = 0; virtual const SmallVectorImpl<char> &getContents() const = 0; - virtual uint8_t getBundlePadding() const { + uint8_t getBundlePadding() const override { return BundlePadding; } - virtual void setBundlePadding(uint8_t N) { + void setBundlePadding(uint8_t N) override { BundlePadding = N; } @@ -168,11 +171,11 @@ public: /// data and also have fixups registered. /// class MCEncodedFragmentWithFixups : public MCEncodedFragment { - virtual void anchor(); + void anchor() override; public: MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, - MCSectionData *SD = 0) + MCSectionData *SD = nullptr) : MCEncodedFragment(FType, SD) { } @@ -199,7 +202,7 @@ public: /// Fragment for data and encoded instructions. /// class MCDataFragment : public MCEncodedFragmentWithFixups { - virtual void anchor(); + void anchor() override; /// \brief Does this fragment contain encoded instructions anywhere in it? bool HasInstructions; @@ -212,34 +215,36 @@ class MCDataFragment : public MCEncodedFragmentWithFixups { /// Fixups - The list of fixups in this fragment. SmallVector<MCFixup, 4> Fixups; public: - MCDataFragment(MCSectionData *SD = 0) + MCDataFragment(MCSectionData *SD = nullptr) : MCEncodedFragmentWithFixups(FT_Data, SD), HasInstructions(false), AlignToBundleEnd(false) { } - virtual SmallVectorImpl<char> &getContents() { return Contents; } - virtual const SmallVectorImpl<char> &getContents() const { return Contents; } + SmallVectorImpl<char> &getContents() override { return Contents; } + const SmallVectorImpl<char> &getContents() const override { + return Contents; + } - SmallVectorImpl<MCFixup> &getFixups() { + SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; } - const SmallVectorImpl<MCFixup> &getFixups() const { + const SmallVectorImpl<MCFixup> &getFixups() const override { return Fixups; } - virtual bool hasInstructions() const { return HasInstructions; } + bool hasInstructions() const override { return HasInstructions; } virtual void setHasInstructions(bool V) { HasInstructions = V; } - virtual bool alignToBundleEnd() const { return AlignToBundleEnd; } - virtual void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } + bool alignToBundleEnd() const override { return AlignToBundleEnd; } + void setAlignToBundleEnd(bool V) override { AlignToBundleEnd = V; } - fixup_iterator fixup_begin() { return Fixups.begin(); } - const_fixup_iterator fixup_begin() const { return Fixups.begin(); } + fixup_iterator fixup_begin() override { return Fixups.begin(); } + const_fixup_iterator fixup_begin() const override { return Fixups.begin(); } - fixup_iterator fixup_end() {return Fixups.end();} - const_fixup_iterator fixup_end() const {return Fixups.end();} + fixup_iterator fixup_end() override {return Fixups.end();} + const_fixup_iterator fixup_end() const override {return Fixups.end();} static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Data; @@ -252,27 +257,27 @@ public: /// consumption. /// class MCCompactEncodedInstFragment : public MCEncodedFragment { - virtual void anchor(); + void anchor() override; /// \brief Should this fragment be aligned to the end of a bundle? bool AlignToBundleEnd; SmallVector<char, 4> Contents; public: - MCCompactEncodedInstFragment(MCSectionData *SD = 0) + MCCompactEncodedInstFragment(MCSectionData *SD = nullptr) : MCEncodedFragment(FT_CompactEncodedInst, SD), AlignToBundleEnd(false) { } - virtual bool hasInstructions() const { + bool hasInstructions() const override { return true; } - virtual SmallVectorImpl<char> &getContents() { return Contents; } - virtual const SmallVectorImpl<char> &getContents() const { return Contents; } + SmallVectorImpl<char> &getContents() override { return Contents; } + const SmallVectorImpl<char> &getContents() const override { return Contents; } - virtual bool alignToBundleEnd() const { return AlignToBundleEnd; } - virtual void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } + bool alignToBundleEnd() const override { return AlignToBundleEnd; } + void setAlignToBundleEnd(bool V) override { AlignToBundleEnd = V; } static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_CompactEncodedInst; @@ -283,11 +288,16 @@ public: /// relaxed during the assembler layout and relaxation stage. /// class MCRelaxableFragment : public MCEncodedFragmentWithFixups { - virtual void anchor(); + void anchor() override; /// Inst - The instruction this is a fragment for. MCInst Inst; + /// STI - The MCSubtargetInfo in effect when the instruction was encoded. + /// Keep a copy instead of a reference to make sure that updates to STI + /// in the assembler are not seen here. + const MCSubtargetInfo STI; + /// Contents - Binary data for the currently encoded instruction. SmallVector<char, 8> Contents; @@ -295,31 +305,35 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups { SmallVector<MCFixup, 1> Fixups; public: - MCRelaxableFragment(const MCInst &_Inst, MCSectionData *SD = 0) - : MCEncodedFragmentWithFixups(FT_Relaxable, SD), Inst(_Inst) { + MCRelaxableFragment(const MCInst &_Inst, + const MCSubtargetInfo &_STI, + MCSectionData *SD = nullptr) + : MCEncodedFragmentWithFixups(FT_Relaxable, SD), Inst(_Inst), STI(_STI) { } - virtual SmallVectorImpl<char> &getContents() { return Contents; } - virtual const SmallVectorImpl<char> &getContents() const { return Contents; } + SmallVectorImpl<char> &getContents() override { return Contents; } + const SmallVectorImpl<char> &getContents() const override { return Contents; } const MCInst &getInst() const { return Inst; } void setInst(const MCInst& Value) { Inst = Value; } - SmallVectorImpl<MCFixup> &getFixups() { + const MCSubtargetInfo &getSubtargetInfo() { return STI; } + + SmallVectorImpl<MCFixup> &getFixups() override { return Fixups; } - const SmallVectorImpl<MCFixup> &getFixups() const { + const SmallVectorImpl<MCFixup> &getFixups() const override { return Fixups; } - virtual bool hasInstructions() const { return true; } + bool hasInstructions() const override { return true; } - fixup_iterator fixup_begin() { return Fixups.begin(); } - const_fixup_iterator fixup_begin() const { return Fixups.begin(); } + fixup_iterator fixup_begin() override { return Fixups.begin(); } + const_fixup_iterator fixup_begin() const override { return Fixups.begin(); } - fixup_iterator fixup_end() {return Fixups.end();} - const_fixup_iterator fixup_end() const {return Fixups.end();} + fixup_iterator fixup_end() override {return Fixups.end();} + const_fixup_iterator fixup_end() const override {return Fixups.end();} static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Relaxable; @@ -349,7 +363,7 @@ class MCAlignFragment : public MCFragment { public: MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, - unsigned _MaxBytesToEmit, MCSectionData *SD = 0) + unsigned _MaxBytesToEmit, MCSectionData *SD = nullptr) : MCFragment(FT_Align, SD), Alignment(_Alignment), Value(_Value),ValueSize(_ValueSize), MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false) {} @@ -390,7 +404,7 @@ class MCFillFragment : public MCFragment { public: MCFillFragment(int64_t _Value, unsigned _ValueSize, uint64_t _Size, - MCSectionData *SD = 0) + MCSectionData *SD = nullptr) : MCFragment(FT_Fill, SD), Value(_Value), ValueSize(_ValueSize), Size(_Size) { assert((!ValueSize || (Size % ValueSize) == 0) && @@ -423,7 +437,8 @@ class MCOrgFragment : public MCFragment { int8_t Value; public: - MCOrgFragment(const MCExpr &_Offset, int8_t _Value, MCSectionData *SD = 0) + MCOrgFragment(const MCExpr &_Offset, int8_t _Value, + MCSectionData *SD = nullptr) : MCFragment(FT_Org, SD), Offset(&_Offset), Value(_Value) {} @@ -452,7 +467,8 @@ class MCLEBFragment : public MCFragment { SmallString<8> Contents; public: - MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD = 0) + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, + MCSectionData *SD = nullptr) : MCFragment(FT_LEB, SD), Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } @@ -488,7 +504,7 @@ class MCDwarfLineAddrFragment : public MCFragment { public: MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta, - MCSectionData *SD = 0) + MCSectionData *SD = nullptr) : MCFragment(FT_Dwarf, SD), LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); } @@ -519,7 +535,8 @@ class MCDwarfCallFrameFragment : public MCFragment { SmallString<8> Contents; public: - MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD = 0) + MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, + MCSectionData *SD = nullptr) : MCFragment(FT_DwarfFrame, SD), AddrDelta(&_AddrDelta) { Contents.push_back(0); } @@ -600,7 +617,7 @@ private: public: // Only for use as sentinel. MCSectionData(); - MCSectionData(const MCSection &Section, MCAssembler *A = 0); + MCSectionData(const MCSection &Section, MCAssembler *A = nullptr); const MCSection &getSection() const { return *Section; } @@ -710,7 +727,7 @@ public: // Only for use as sentinel. MCSymbolData(); MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, - MCAssembler *A = 0); + MCAssembler *A = nullptr); /// @name Accessors /// @{ @@ -785,7 +802,7 @@ public: /// @} - void dump(); + void dump() const; }; // FIXME: This really doesn't belong here. See comments below. @@ -817,6 +834,9 @@ public: typedef SymbolDataListType::const_iterator const_symbol_iterator; typedef SymbolDataListType::iterator symbol_iterator; + typedef iterator_range<symbol_iterator> symbol_range; + typedef iterator_range<const_symbol_iterator> const_symbol_range; + typedef std::vector<std::string> FileNameVectorType; typedef FileNameVectorType::const_iterator const_file_name_iterator; @@ -828,6 +848,15 @@ public: const_data_region_iterator; typedef std::vector<DataRegionData>::iterator data_region_iterator; + /// MachO specific deployment target version info. + // A Major version of 0 indicates that no version information was supplied + // and so the corresponding load command should not be emitted. + typedef struct { + MCVersionMinType Kind; + unsigned Major; + unsigned Minor; + unsigned Update; + } VersionMinInfoType; private: MCAssembler(const MCAssembler&) LLVM_DELETED_FUNCTION; void operator=(const MCAssembler&) LLVM_DELETED_FUNCTION; @@ -873,7 +902,7 @@ private: // here. Maybe when the relocation stuff moves to target specific, // this can go with it? The streamer would need some target specific // refactoring too. - SmallPtrSet<const MCSymbol*, 64> ThumbFuncs; + mutable SmallPtrSet<const MCSymbol*, 64> ThumbFuncs; /// \brief The bundle alignment size currently set in the assembler. /// @@ -890,6 +919,12 @@ private: // Access to the flags is necessary in cases where assembler directives affect // which flags to be set. unsigned ELFHeaderEFlags; + + /// Used to communicate Linker Optimization Hint information between + /// the Streamer and the .o writer + MCLOHContainer LOHContainer; + + VersionMinInfoType VersionMinInfo; private: /// Evaluate a fixup to a relocatable expression and the value which should be /// placed into the fixup. @@ -936,8 +971,8 @@ private: /// finishLayout - Finalize a layout, including fragment lowering. void finishLayout(MCAsmLayout &Layout); - uint64_t handleFixup(const MCAsmLayout &Layout, - MCFragment &F, const MCFixup &Fixup); + std::pair<uint64_t, bool> handleFixup(const MCAsmLayout &Layout, + MCFragment &F, const MCFixup &Fixup); public: /// Compute the effective fragment size assuming it is laid out at the given @@ -960,9 +995,7 @@ public: const MCAsmLayout &Layout) const; /// Check whether a given symbol has been flagged with .thumb_func. - bool isThumbFunc(const MCSymbol *Func) const { - return ThumbFuncs.count(Func); - } + bool isThumbFunc(const MCSymbol *Func) const; /// Flag a function symbol as the target of a .thumb_func directive. void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); } @@ -971,6 +1004,16 @@ public: unsigned getELFHeaderEFlags() const {return ELFHeaderEFlags;} void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags;} + /// MachO deployment target version information. + const VersionMinInfoType &getVersionMinInfo() const { return VersionMinInfo; } + void setVersionMinInfo(MCVersionMinType Kind, unsigned Major, unsigned Minor, + unsigned Update) { + VersionMinInfo.Kind = Kind; + VersionMinInfo.Major = Major; + VersionMinInfo.Minor = Minor; + VersionMinInfo.Update = Update; + } + public: /// Construct a new assembler instance. /// @@ -1057,6 +1100,9 @@ public: symbol_iterator symbol_end() { return Symbols.end(); } const_symbol_iterator symbol_end() const { return Symbols.end(); } + symbol_range symbols() { return make_range(symbol_begin(), symbol_end()); } + const_symbol_range symbols() const { return make_range(symbol_begin(), symbol_end()); } + size_t symbol_size() const { return Symbols.size(); } /// @} @@ -1122,6 +1168,19 @@ public: size_t data_region_size() const { return DataRegions.size(); } /// @} + /// @name Data Region List Access + /// @{ + + // FIXME: This is a total hack, this should not be here. Once things are + // factored so that the streamer has direct access to the .o writer, it can + // disappear. + MCLOHContainer & getLOHContainer() { + return LOHContainer; + } + const MCLOHContainer & getLOHContainer() const { + return const_cast<MCAssembler *>(this)->getLOHContainer(); + } + /// @} /// @name Backend Data Access /// @{ @@ -1132,7 +1191,7 @@ public: } MCSectionData &getOrCreateSectionData(const MCSection &Section, - bool *Created = 0) { + bool *Created = nullptr) { MCSectionData *&Entry = SectionMap[&Section]; if (Created) *Created = !Entry; @@ -1142,19 +1201,28 @@ public: return *Entry; } - MCSymbolData &getSymbolData(const MCSymbol &Symbol) const { + bool hasSymbolData(const MCSymbol &Symbol) const { + return SymbolMap.lookup(&Symbol) != nullptr; + } + + MCSymbolData &getSymbolData(const MCSymbol &Symbol) { + return const_cast<MCSymbolData &>( + static_cast<const MCAssembler &>(*this).getSymbolData(Symbol)); + } + + const MCSymbolData &getSymbolData(const MCSymbol &Symbol) const { MCSymbolData *Entry = SymbolMap.lookup(&Symbol); assert(Entry && "Missing symbol data!"); return *Entry; } MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol, - bool *Created = 0) { + bool *Created = nullptr) { MCSymbolData *&Entry = SymbolMap[&Symbol]; if (Created) *Created = !Entry; if (!Entry) - Entry = new MCSymbolData(Symbol, 0, 0, this); + Entry = new MCSymbolData(Symbol, nullptr, 0, this); return *Entry; } diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index 9bfa08eb5d01..d3b56177d50a 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -15,6 +15,7 @@ namespace llvm { class MCFixup; class MCInst; +class MCSubtargetInfo; class raw_ostream; template<typename T> class SmallVectorImpl; @@ -35,7 +36,8 @@ public: /// EncodeInstruction - Encode the given \p Inst to bytes on the output /// stream \p OS. virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const = 0; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const = 0; }; } // End llvm namespace diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index c8b66261bfea..eb0340f7421a 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -11,15 +11,18 @@ #define LLVM_MC_MCCONTEXT_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include <map> +#include <tuple> #include <vector> // FIXME: Shouldn't be needed. namespace llvm { @@ -28,7 +31,7 @@ namespace llvm { class MCSection; class MCSymbol; class MCLabel; - class MCDwarfFile; + struct MCDwarfFile; class MCDwarfLoc; class MCObjectFileInfo; class MCRegisterInfo; @@ -70,6 +73,14 @@ namespace llvm { /// Symbols - Bindings of names to symbols. SymbolTable Symbols; + /// A maping from a local label number and an instance count to a symbol. + /// For example, in the assembly + /// 1: + /// 2: + /// 1: + /// We have three labels represented by the pairs (1, 0), (2, 0) and (1, 1) + DenseMap<std::pair<unsigned, unsigned>, MCSymbol*> LocalSymbols; + /// UsedNames - Keeps tracks of names that were used both for used declared /// and artificial symbols. StringMap<bool, BumpPtrAllocator&> UsedNames; @@ -82,10 +93,10 @@ namespace llvm { DenseMap<unsigned, MCLabel *> Instances; /// NextInstance() creates the next instance of the directional local label /// for the LocalLabelVal and adds it to the map if needed. - unsigned NextInstance(int64_t LocalLabelVal); + unsigned NextInstance(unsigned LocalLabelVal); /// GetInstance() gets the current instance of the directional local label /// for the LocalLabelVal and adds it to the map if needed. - unsigned GetInstance(int64_t LocalLabelVal); + unsigned GetInstance(unsigned LocalLabelVal); /// The file name of the log file from the environment variable /// AS_SECURE_LOG_FILE. Which must be set before the .secure_log_unique @@ -108,9 +119,7 @@ namespace llvm { /// We now emit a line table for each compile unit. To reduce the prologue /// size of each line table, the files and directories used by each compile /// unit are separated. - typedef std::map<unsigned, SmallVector<MCDwarfFile *, 4> > MCDwarfFilesMap; - MCDwarfFilesMap MCDwarfFilesCUMap; - std::map<unsigned, SmallVector<StringRef, 4> > MCDwarfDirsCUMap; + std::map<unsigned, MCDwarfLineTable> MCDwarfLineTablesCUMap; /// The current dwarf line information from the last dwarf .loc directive. MCDwarfLoc CurrentDwarfLoc; @@ -123,15 +132,14 @@ namespace llvm { /// assembly source files. unsigned GenDwarfFileNumber; - /// The default initial text section that we generate dwarf debugging line - /// info for when generating dwarf assembly source files. - const MCSection *GenDwarfSection; - /// Symbols created for the start and end of this section. - MCSymbol *GenDwarfSectionStartSym, *GenDwarfSectionEndSym; + /// Symbols created for the start and end of each section, used for + /// generating the .debug_ranges and .debug_aranges sections. + MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> > + SectionStartEndSyms; /// The information gathered from labels that will have dwarf label /// entries when generating dwarf assembly source files. - std::vector<const MCGenDwarfLabelEntry *> MCGenDwarfLabelEntries; + std::vector<MCGenDwarfLabelEntry> MCGenDwarfLabelEntries; /// The string to embed in the debug information for the compile unit, if /// non-empty. @@ -141,33 +149,36 @@ namespace llvm { /// non-empty. StringRef DwarfDebugProducer; + /// The maximum version of dwarf that we should emit. + uint16_t DwarfVersion; + /// Honor temporary labels, this is useful for debugging semantic /// differences between temporary and non-temporary labels (primarily on /// Darwin). bool AllowTemporaryLabels; - /// The dwarf line information from the .loc directives for the sections - /// with assembled machine instructions have after seeing .loc directives. - DenseMap<const MCSection *, MCLineSection *> MCLineSections; - /// We need a deterministic iteration order, so we remember the order - /// the elements were added. - std::vector<const MCSection *> MCLineSectionOrder; /// The Compile Unit ID that we are currently processing. unsigned DwarfCompileUnitID; - /// The line table start symbol for each Compile Unit. - DenseMap<unsigned, MCSymbol *> MCLineTableSymbols; - void *MachOUniquingMap, *ELFUniquingMap, *COFFUniquingMap; + typedef std::pair<std::string, std::string> SectionGroupPair; + typedef std::tuple<std::string, std::string, int> SectionGroupTriple; + + StringMap<const MCSectionMachO*> MachOUniquingMap; + std::map<SectionGroupPair, const MCSectionELF *> ELFUniquingMap; + std::map<SectionGroupTriple, const MCSectionCOFF *> COFFUniquingMap; /// Do automatic reset in destructor bool AutoReset; MCSymbol *CreateSymbol(StringRef Name); + MCSymbol *getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal, + unsigned Instance); + public: explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI, - const MCObjectFileInfo *MOFI, const SourceMgr *Mgr = 0, - bool DoAutoReset = true); + const MCObjectFileInfo *MOFI, + const SourceMgr *Mgr = nullptr, bool DoAutoReset = true); ~MCContext(); const SourceMgr *getSourceManager() const { return SrcMgr; } @@ -192,6 +203,10 @@ namespace llvm { /// @name Symbol Management /// @{ + /// CreateLinkerPrivateTempSymbol - Create and return a new linker temporary + /// symbol with a unique but unspecified name. + MCSymbol *CreateLinkerPrivateTempSymbol(); + /// CreateTempSymbol - Create and return a new assembler temporary symbol /// with a unique but unspecified name. MCSymbol *CreateTempSymbol(); @@ -200,13 +215,13 @@ namespace llvm { /// symbol names. unsigned getUniqueSymbolID() { return NextUniqueID++; } - /// CreateDirectionalLocalSymbol - Create the definition of a directional - /// local symbol for numbered label (used for "1:" definitions). - MCSymbol *CreateDirectionalLocalSymbol(int64_t LocalLabelVal); + /// Create the definition of a directional local symbol for numbered label + /// (used for "1:" definitions). + MCSymbol *CreateDirectionalLocalSymbol(unsigned LocalLabelVal); - /// GetDirectionalLocalSymbol - Create and return a directional local - /// symbol for numbered label (used for "1b" or 1f" references). - MCSymbol *GetDirectionalLocalSymbol(int64_t LocalLabelVal, int bORf); + /// Create and return a directional local symbol for numbered label (used + /// for "1b" or 1f" references). + MCSymbol *GetDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before); /// GetOrCreateSymbol - Lookup the symbol inside with the specified /// @p Name. If it exists, return it. If not, create a forward @@ -254,14 +269,14 @@ namespace llvm { unsigned Flags, SectionKind Kind, unsigned EntrySize, StringRef Group); + void renameELFSection(const MCSectionELF *Section, StringRef Name); + const MCSectionELF *CreateELFGroupSection(); const MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, SectionKind Kind, - StringRef COMDATSymName, - int Selection, - const MCSectionCOFF *Assoc = 0); + StringRef COMDATSymName, int Selection); const MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, @@ -278,6 +293,7 @@ namespace llvm { /// This can be overridden by clients which want to control the reported /// compilation directory and have it be something other than the current /// working directory. + /// Returns an empty string if the current directory cannot be determined. StringRef getCompilationDir() const { return CompilationDir; } /// \brief Set the compilation directory for DW_AT_comp_dir @@ -290,7 +306,7 @@ namespace llvm { const std::string &getMainFileName() const { return MainFileName; } /// \brief Set the main file name and override the default. - void setMainFileName(StringRef S) { MainFileName = S.str(); } + void setMainFileName(StringRef S) { MainFileName = S; } /// GetDwarfFile - creates an entry in the dwarf file and directory tables. unsigned GetDwarfFile(StringRef Directory, StringRef FileName, @@ -298,33 +314,32 @@ namespace llvm { bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0); - bool hasDwarfFiles() const { - // Traverse MCDwarfFilesCUMap and check whether each entry is empty. - MCDwarfFilesMap::const_iterator MapB, MapE; - for (MapB = MCDwarfFilesCUMap.begin(), MapE = MCDwarfFilesCUMap.end(); - MapB != MapE; MapB++) - if (!MapB->second.empty()) - return true; - return false; + const std::map<unsigned, MCDwarfLineTable> &getMCDwarfLineTables() const { + return MCDwarfLineTablesCUMap; } - const SmallVectorImpl<MCDwarfFile *> &getMCDwarfFiles(unsigned CUID = 0) { - return MCDwarfFilesCUMap[CUID]; + MCDwarfLineTable &getMCDwarfLineTable(unsigned CUID) { + return MCDwarfLineTablesCUMap[CUID]; } - const SmallVectorImpl<StringRef> &getMCDwarfDirs(unsigned CUID = 0) { - return MCDwarfDirsCUMap[CUID]; + + const MCDwarfLineTable &getMCDwarfLineTable(unsigned CUID) const { + auto I = MCDwarfLineTablesCUMap.find(CUID); + assert(I != MCDwarfLineTablesCUMap.end()); + return I->second; } - const DenseMap<const MCSection *, MCLineSection *> - &getMCLineSections() const { - return MCLineSections; + const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles(unsigned CUID = 0) { + return getMCDwarfLineTable(CUID).getMCDwarfFiles(); } - const std::vector<const MCSection *> &getMCLineSectionOrder() const { - return MCLineSectionOrder; + const SmallVectorImpl<std::string> &getMCDwarfDirs(unsigned CUID = 0) { + return getMCDwarfLineTable(CUID).getMCDwarfDirs(); } - void addMCLineSection(const MCSection *Sec, MCLineSection *Line) { - MCLineSections[Sec] = Line; - MCLineSectionOrder.push_back(Sec); + + bool hasMCLineSections() const { + for (const auto &Table : MCDwarfLineTablesCUMap) + if (!Table.second.getMCDwarfFiles().empty() || Table.second.getLabel()) + return true; + return false; } unsigned getDwarfCompileUnitID() { return DwarfCompileUnitID; @@ -332,18 +347,8 @@ namespace llvm { void setDwarfCompileUnitID(unsigned CUIndex) { DwarfCompileUnitID = CUIndex; } - const DenseMap<unsigned, MCSymbol *> &getMCLineTableSymbols() const { - return MCLineTableSymbols; - } - MCSymbol *getMCLineTableSymbol(unsigned ID) const { - DenseMap<unsigned, MCSymbol *>::const_iterator CIter = - MCLineTableSymbols.find(ID); - if (CIter == MCLineTableSymbols.end()) - return NULL; - return CIter->second; - } - void setMCLineTableSymbol(MCSymbol *Sym, unsigned ID) { - MCLineTableSymbols[ID] = Sym; + void setMCLineTableCompilationDir(unsigned CUID, StringRef CompilationDir) { + getMCDwarfLineTable(CUID).setCompilationDir(CompilationDir); } /// setCurrentDwarfLoc - saves the information from the currently parsed @@ -369,22 +374,25 @@ namespace llvm { bool getGenDwarfForAssembly() { return GenDwarfForAssembly; } void setGenDwarfForAssembly(bool Value) { GenDwarfForAssembly = Value; } unsigned getGenDwarfFileNumber() { return GenDwarfFileNumber; } - unsigned nextGenDwarfFileNumber() { return ++GenDwarfFileNumber; } - const MCSection *getGenDwarfSection() { return GenDwarfSection; } - void setGenDwarfSection(const MCSection *Sec) { GenDwarfSection = Sec; } - MCSymbol *getGenDwarfSectionStartSym() { return GenDwarfSectionStartSym; } - void setGenDwarfSectionStartSym(MCSymbol *Sym) { - GenDwarfSectionStartSym = Sym; + void setGenDwarfFileNumber(unsigned FileNumber) { + GenDwarfFileNumber = FileNumber; + } + MapVector<const MCSection *, std::pair<MCSymbol *, MCSymbol *> > & + getGenDwarfSectionSyms() { + return SectionStartEndSyms; } - MCSymbol *getGenDwarfSectionEndSym() { return GenDwarfSectionEndSym; } - void setGenDwarfSectionEndSym(MCSymbol *Sym) { - GenDwarfSectionEndSym = Sym; + std::pair<MapVector<const MCSection *, + std::pair<MCSymbol *, MCSymbol *> >::iterator, + bool> + addGenDwarfSection(const MCSection *Sec) { + return SectionStartEndSyms.insert( + std::make_pair(Sec, std::make_pair(nullptr, nullptr))); } - const std::vector<const MCGenDwarfLabelEntry *> - &getMCGenDwarfLabelEntries() const { + void finalizeDwarfSections(MCStreamer &MCOS); + const std::vector<MCGenDwarfLabelEntry> &getMCGenDwarfLabelEntries() const { return MCGenDwarfLabelEntries; } - void addMCGenDwarfLabelEntry(const MCGenDwarfLabelEntry *E) { + void addMCGenDwarfLabelEntry(const MCGenDwarfLabelEntry &E) { MCGenDwarfLabelEntries.push_back(E); } @@ -394,6 +402,9 @@ namespace llvm { void setDwarfDebugProducer(StringRef S) { DwarfDebugProducer = S; } StringRef getDwarfDebugProducer() { return DwarfDebugProducer; } + void setDwarfVersion(uint16_t v) { DwarfVersion = v; } + uint16_t getDwarfVersion() const { return DwarfVersion; } + /// @} char *getSecureLogFile() { return SecureLogFile; } @@ -415,7 +426,7 @@ namespace llvm { // Unrecoverable error has occurred. Display the best diagnostic we can // and bail via exit(1). For now, most MC backend errors are unrecoverable. // FIXME: We should really do something about that. - LLVM_ATTRIBUTE_NORETURN void FatalError(SMLoc L, const Twine &Msg); + LLVM_ATTRIBUTE_NORETURN void FatalError(SMLoc L, const Twine &Msg) const; }; } // end namespace llvm diff --git a/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h index 0461766c2fd3..f9d66e0b15d7 100644 --- a/include/llvm/MC/MCDirectives.h +++ b/include/llvm/MC/MCDirectives.h @@ -60,6 +60,11 @@ enum MCDataRegionType { MCDR_DataRegionEnd ///< .end_data_region }; +enum MCVersionMinType { + MCVM_IOSVersionMin, ///< .ios_version_min + MCVM_OSXVersionMin ///< .macosx_version_min +}; + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index 83f26ef3edb9..9d441bbd88fb 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -10,9 +10,8 @@ #define LLVM_MC_MCDISASSEMBLER_H #include "llvm-c/Disassembler.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/MC/MCSymbolizer.h" #include "llvm/MC/MCRelocationInfo.h" +#include "llvm/MC/MCSymbolizer.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -56,10 +55,8 @@ public: }; /// Constructor - Performs initial setup for the disassembler. - MCDisassembler(const MCSubtargetInfo &STI) : GetOpInfo(0), SymbolLookUp(0), - DisInfo(0), Ctx(0), - STI(STI), Symbolizer(0), - CommentStream(0) {} + MCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) + : Ctx(Ctx), STI(STI), Symbolizer(), CommentStream(nullptr) {} virtual ~MCDisassembler(); @@ -86,23 +83,12 @@ public: raw_ostream &vStream, raw_ostream &cStream) const = 0; private: - // - // Hooks for symbolic disassembly via the public 'C' interface. - // - // The function to get the symbolic information for operands. - LLVMOpInfoCallback GetOpInfo; - // The function to lookup a symbol name. - LLVMSymbolLookupCallback SymbolLookUp; - // The pointer to the block of symbolic information for above call back. - void *DisInfo; - // The assembly context for creating symbols and MCExprs in place of - // immediate operands when there is symbolic information. - MCContext *Ctx; + MCContext &Ctx; protected: // Subtarget information, for instruction decoding predicates if required. const MCSubtargetInfo &STI; - OwningPtr<MCSymbolizer> Symbolizer; + std::unique_ptr<MCSymbolizer> Symbolizer; public: // Helpers around MCSymbolizer @@ -115,21 +101,9 @@ public: /// Set \p Symzer as the current symbolizer. /// This takes ownership of \p Symzer, and deletes the previously set one. - void setSymbolizer(OwningPtr<MCSymbolizer> &Symzer); - - /// Sets up an external symbolizer that uses the C API callbacks. - void setupForSymbolicDisassembly(LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - void *DisInfo, - MCContext *Ctx, - OwningPtr<MCRelocationInfo> &RelInfo); - - LLVMOpInfoCallback getLLVMOpInfoCallback() const { return GetOpInfo; } - LLVMSymbolLookupCallback getLLVMSymbolLookupCallback() const { - return SymbolLookUp; - } - void *getDisInfoBlock() const { return DisInfo; } - MCContext *getMCContext() const { return Ctx; } + void setSymbolizer(std::unique_ptr<MCSymbolizer> Symzer); + + MCContext& getContext() const { return Ctx; } const MCSubtargetInfo& getSubtargetInfo() const { return STI; } diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 65b920bf232e..6cd9a9a21e21 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -15,16 +15,22 @@ #ifndef LLVM_MC_MCDWARF_H #define LLVM_MC_MCDWARF_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/raw_ostream.h" #include <map> #include <vector> +#include <string> +#include <utility> namespace llvm { class MCAsmBackend; class MCContext; +class MCObjectStreamer; class MCSection; class MCStreamer; class MCSymbol; @@ -36,41 +42,15 @@ class SMLoc; /// and MCDwarfFile's are created and unique'd by the MCContext class where /// the file number for each is its index into the vector of DwarfFiles (note /// index 0 is not used and not a valid dwarf file number). -class MCDwarfFile { +struct MCDwarfFile { // Name - the base name of the file without its directory path. // The StringRef references memory allocated in the MCContext. - StringRef Name; + std::string Name; // DirIndex - the index into the list of directory names for this file name. unsigned DirIndex; - -private: // MCContext creates and uniques these. - friend class MCContext; - MCDwarfFile(StringRef name, unsigned dirIndex) - : Name(name), DirIndex(dirIndex) {} - - MCDwarfFile(const MCDwarfFile &) LLVM_DELETED_FUNCTION; - void operator=(const MCDwarfFile &) LLVM_DELETED_FUNCTION; - -public: - /// getName - Get the base name of this MCDwarfFile. - StringRef getName() const { return Name; } - - /// getDirIndex - Get the dirIndex of this MCDwarfFile. - unsigned getDirIndex() const { return DirIndex; } - - /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS) const; - - /// dump - Print the value to stderr. - void dump() const; }; -inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile) { - DwarfFile.print(OS); - return OS; -} - /// MCDwarfLoc - Instances of this class represent the information from a /// dwarf .loc directive. class MCDwarfLoc { @@ -168,62 +148,111 @@ public: // This is called when an instruction is assembled into the specified // section and if there is information from the last .loc directive that // has yet to have a line entry made for it is made. - static void Make(MCStreamer *MCOS, const MCSection *Section); + static void Make(MCObjectStreamer *MCOS, const MCSection *Section); }; /// MCLineSection - Instances of this class represent the line information -/// for a section where machine instructions have been assembled after seeing +/// for a compile unit where machine instructions have been assembled after seeing /// .loc directives. This is the information used to build the dwarf line /// table for a section. class MCLineSection { - -private: - MCLineSection(const MCLineSection &) LLVM_DELETED_FUNCTION; - void operator=(const MCLineSection &) LLVM_DELETED_FUNCTION; - public: - // Constructor to create an MCLineSection with an empty MCLineEntries - // vector. - MCLineSection() {} - // addLineEntry - adds an entry to this MCLineSection's line entries - void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) { - MCLineDivisions[CUID].push_back(LineEntry); + void addLineEntry(const MCLineEntry &LineEntry, const MCSection *Sec) { + MCLineDivisions[Sec].push_back(LineEntry); } typedef std::vector<MCLineEntry> MCLineEntryCollection; typedef MCLineEntryCollection::iterator iterator; typedef MCLineEntryCollection::const_iterator const_iterator; - typedef std::map<unsigned, MCLineEntryCollection> MCLineDivisionMap; + typedef MapVector<const MCSection *, MCLineEntryCollection> MCLineDivisionMap; private: - // A collection of MCLineEntry for each Compile Unit ID. + // A collection of MCLineEntry for each section. MCLineDivisionMap MCLineDivisions; public: - // Returns whether MCLineSection contains entries for a given Compile - // Unit ID. - bool containEntriesForID(unsigned CUID) const { - return MCLineDivisions.count(CUID); - } // Returns the collection of MCLineEntry for a given Compile Unit ID. - const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { - MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); - assert(CIter != MCLineDivisions.end()); - return CIter->second; + const MCLineDivisionMap &getMCLineEntries() const { + return MCLineDivisions; } }; -class MCDwarfFileTable { +struct MCDwarfLineTableHeader { + MCSymbol *Label; + SmallVector<std::string, 3> MCDwarfDirs; + SmallVector<MCDwarfFile, 3> MCDwarfFiles; + StringMap<unsigned> SourceIdMap; + StringRef CompilationDir; + + MCDwarfLineTableHeader() : Label(nullptr) {} + unsigned getFile(StringRef &Directory, StringRef &FileName, + unsigned FileNumber = 0); + std::pair<MCSymbol *, MCSymbol *> Emit(MCStreamer *MCOS) const; + std::pair<MCSymbol *, MCSymbol *> + Emit(MCStreamer *MCOS, ArrayRef<char> SpecialOpcodeLengths) const; +}; + +class MCDwarfDwoLineTable { + MCDwarfLineTableHeader Header; +public: + void setCompilationDir(StringRef CompilationDir) { + Header.CompilationDir = CompilationDir; + } + unsigned getFile(StringRef Directory, StringRef FileName) { + return Header.getFile(Directory, FileName); + } + void Emit(MCStreamer &MCOS) const; +}; + +class MCDwarfLineTable { + MCDwarfLineTableHeader Header; + MCLineSection MCLineSections; + public: - // // This emits the Dwarf file and the line tables for all Compile Units. - // - static const MCSymbol *Emit(MCStreamer *MCOS); - // + static void Emit(MCObjectStreamer *MCOS); + // This emits the Dwarf file and the line tables for a given Compile Unit. - // - static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); + void EmitCU(MCObjectStreamer *MCOS) const; + + unsigned getFile(StringRef &Directory, StringRef &FileName, + unsigned FileNumber = 0); + + MCSymbol *getLabel() const { + return Header.Label; + } + + void setLabel(MCSymbol *Label) { + Header.Label = Label; + } + + void setCompilationDir(StringRef CompilationDir) { + Header.CompilationDir = CompilationDir; + } + + const SmallVectorImpl<std::string> &getMCDwarfDirs() const { + return Header.MCDwarfDirs; + } + + SmallVectorImpl<std::string> &getMCDwarfDirs() { + return Header.MCDwarfDirs; + } + + const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const { + return Header.MCDwarfFiles; + } + + SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() { + return Header.MCDwarfFiles; + } + + const MCLineSection &getMCLineSections() const { + return MCLineSections; + } + MCLineSection &getMCLineSections() { + return MCLineSections; + } }; class MCDwarfLineAddr { @@ -242,7 +271,7 @@ public: // When generating dwarf for assembly source files this emits the Dwarf // sections. // - static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); + static void Emit(MCStreamer *MCOS); }; // When generating dwarf for assembly source files this is the info that is @@ -436,19 +465,19 @@ public: struct MCDwarfFrameInfo { MCDwarfFrameInfo() - : Begin(0), End(0), Personality(0), Lsda(0), Function(0), Instructions(), - PersonalityEncoding(), LsdaEncoding(0), CompactUnwindEncoding(0), - IsSignalFrame(false) {} + : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr), + Instructions(), PersonalityEncoding(), LsdaEncoding(0), + CompactUnwindEncoding(0), IsSignalFrame(false), IsSimple(false) {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *Personality; const MCSymbol *Lsda; - const MCSymbol *Function; std::vector<MCCFIInstruction> Instructions; unsigned PersonalityEncoding; unsigned LsdaEncoding; uint32_t CompactUnwindEncoding; bool IsSignalFrame; + bool IsSimple; }; class MCDwarfFrameEmitter { @@ -456,9 +485,8 @@ public: // // This emits the frame info section. // - static void Emit(MCStreamer &streamer, MCAsmBackend *MAB, - bool usingCFI, bool isEH); - static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); + static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH); + static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta); static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, raw_ostream &OS); }; diff --git a/include/llvm/MC/MCELF.h b/include/llvm/MC/MCELF.h index 7e59911a89c3..294a51bf7c76 100644 --- a/include/llvm/MC/MCELF.h +++ b/include/llvm/MC/MCELF.h @@ -27,9 +27,9 @@ class MCELF { static void SetType(MCSymbolData &SD, unsigned Type); static unsigned GetType(const MCSymbolData &SD); static void SetVisibility(MCSymbolData &SD, unsigned Visibility); - static unsigned GetVisibility(MCSymbolData &SD); + static unsigned GetVisibility(const MCSymbolData &SD); static void setOther(MCSymbolData &SD, unsigned Other); - static unsigned getOther(MCSymbolData &SD); + static unsigned getOther(const MCSymbolData &SD); }; } diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 92ad1b1a46fe..421e7a0b2c19 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -20,30 +20,11 @@ class MCAssembler; class MCFixup; class MCFragment; class MCObjectWriter; +class MCSectionData; class MCSymbol; +class MCSymbolData; class MCValue; -/// @name Relocation Data -/// @{ - -struct ELFRelocationEntry { - // Make these big enough for both 32-bit and 64-bit - uint64_t r_offset; - int Index; - unsigned Type; - const MCSymbol *Symbol; - uint64_t r_addend; - const MCFixup *Fixup; - - ELFRelocationEntry() - : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0), Fixup(0) {} - - ELFRelocationEntry(uint64_t RelocOffset, int Idx, unsigned RelType, - const MCSymbol *Sym, uint64_t Addend, const MCFixup &Fixup) - : r_offset(RelocOffset), Index(Idx), Type(RelType), Symbol(Sym), - r_addend(Addend), Fixup(&Fixup) {} -}; - class MCELFObjectTargetWriter { const uint8_t OSABI; const uint16_t EMachine; @@ -72,19 +53,10 @@ public: virtual ~MCELFObjectTargetWriter() {} virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, bool IsRelocWithSymbol, - int64_t Addend) const = 0; - virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const; - virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target, - const MCFixup &Fixup, - bool IsPCRel) const; - - virtual void sortRelocs(const MCAssembler &Asm, - std::vector<ELFRelocationEntry> &Relocs); + bool IsPCRel) const = 0; + + virtual bool needsRelocateWithSymbol(const MCSymbolData &SD, + unsigned Type) const; /// @name Accessors /// @{ @@ -107,16 +79,16 @@ public: #define R_SSYM_MASK 0x00ffffff // N64 relocation type accessors - unsigned getRType(uint32_t Type) const { + uint8_t getRType(uint32_t Type) const { return (unsigned)((Type >> R_TYPE_SHIFT) & 0xff); } - unsigned getRType2(uint32_t Type) const { + uint8_t getRType2(uint32_t Type) const { return (unsigned)((Type >> R_TYPE2_SHIFT) & 0xff); } - unsigned getRType3(uint32_t Type) const { + uint8_t getRType3(uint32_t Type) const { return (unsigned)((Type >> R_TYPE3_SHIFT) & 0xff); } - unsigned getRSsym(uint32_t Type) const { + uint8_t getRSsym(uint32_t Type) const { return (unsigned)((Type >> R_SSYM_SHIFT) & 0xff); } diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index 4e24dcfacd50..66729fe0147e 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -29,70 +29,66 @@ class raw_ostream; class MCELFStreamer : public MCObjectStreamer { public: - MCELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, - MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TargetStreamer, TAB, OS, Emitter), - SeenIdent(false) {} + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *Emitter) + : MCObjectStreamer(Context, TAB, OS, Emitter), + SeenIdent(false) {} - MCELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, - MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, - MCAssembler *Assembler) - : MCObjectStreamer(Context, TargetStreamer, TAB, OS, Emitter, Assembler), - SeenIdent(false) {} + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCCodeEmitter *Emitter, MCAssembler *Assembler) + : MCObjectStreamer(Context, TAB, OS, Emitter, Assembler), + SeenIdent(false) {} virtual ~MCELFStreamer(); /// @name MCStreamer Interface /// @{ - virtual void InitSections(); - virtual void InitToTextSection(); - virtual void ChangeSection(const MCSection *Section, - const MCExpr *Subsection); - virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitDebugLabel(MCSymbol *Symbol); - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); - virtual void EmitThumbFunc(MCSymbol *Func); - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); - virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); - virtual void EmitCOFFSymbolStorageClass(int StorageClass); - virtual void EmitCOFFSymbolType(int Type); - virtual void EndCOFFSymbolDef(); + void InitSections() override; + void ChangeSection(const MCSection *Section, + const MCExpr *Subsection) override; + void EmitLabel(MCSymbol *Symbol) override; + void EmitAssemblerFlag(MCAssemblerFlag Flag) override; + void EmitThumbFunc(MCSymbol *Func) override; + void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void BeginCOFFSymbolDef(const MCSymbol *Symbol) override; + void EmitCOFFSymbolStorageClass(int StorageClass) override; + void EmitCOFFSymbolType(int Type) override; + void EndCOFFSymbolDef() override; - virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); + void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); + void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0) override; + void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) override; + void EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc = SMLoc()) override; - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - uint64_t Size = 0, unsigned ByteAlignment = 0); - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); + void EmitFileDirective(StringRef Filename) override; - virtual void EmitFileDirective(StringRef Filename); + void EmitIdent(StringRef IdentString) override; - virtual void EmitIdent(StringRef IdentString); + void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned) override; - virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned); + void Flush() override; - virtual void Flush(); + void FinishImpl() override; - virtual void FinishImpl(); + void EmitBundleAlignMode(unsigned AlignPow2) override; + void EmitBundleLock(bool AlignToEnd) override; + void EmitBundleUnlock() override; private: - virtual void EmitInstToFragment(const MCInst &Inst); - virtual void EmitInstToData(const MCInst &Inst); - - virtual void EmitBundleAlignMode(unsigned AlignPow2); - virtual void EmitBundleLock(bool AlignToEnd); - virtual void EmitBundleUnlock(); + void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override; + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; void fixSymbolsInTLSFixups(const MCExpr *expr); @@ -107,13 +103,6 @@ private: std::vector<LocalCommon> LocalCommons; SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet; - - - void SetSection(StringRef Section, unsigned Type, unsigned Flags, - SectionKind Kind); - void SetSectionData(); - void SetSectionText(); - void SetSectionBss(); }; MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, diff --git a/include/llvm/MC/MCELFSymbolFlags.h b/include/llvm/MC/MCELFSymbolFlags.h index d0e1dace99d1..297c44269a8f 100644 --- a/include/llvm/MC/MCELFSymbolFlags.h +++ b/include/llvm/MC/MCELFSymbolFlags.h @@ -21,10 +21,10 @@ namespace llvm { enum { - ELF_STT_Shift = 0, // Shift value for STT_* flags. - ELF_STB_Shift = 4, // Shift value for STB_* flags. - ELF_STV_Shift = 8, // Shift value for STV_* flags. - ELF_Other_Shift = 10 // Shift value for other flags. + ELF_STT_Shift = 0, // Shift value for STT_* flags. + ELF_STB_Shift = 4, // Shift value for STB_* flags. + ELF_STV_Shift = 8, // Shift value for STV_* flags. + ELF_STO_Shift = 10 // Shift value for STO_* flags. }; enum ELFSymbolFlags { @@ -41,16 +41,14 @@ namespace llvm { ELF_STT_File = (ELF::STT_FILE << ELF_STT_Shift), ELF_STT_Common = (ELF::STT_COMMON << ELF_STT_Shift), ELF_STT_Tls = (ELF::STT_TLS << ELF_STT_Shift), + ELF_STT_GnuIFunc = (ELF::STT_GNU_IFUNC << ELF_STT_Shift), ELF_STT_Loproc = (ELF::STT_LOPROC << ELF_STT_Shift), ELF_STT_Hiproc = (ELF::STT_HIPROC << ELF_STT_Shift), ELF_STV_Default = (ELF::STV_DEFAULT << ELF_STV_Shift), ELF_STV_Internal = (ELF::STV_INTERNAL << ELF_STV_Shift), ELF_STV_Hidden = (ELF::STV_HIDDEN << ELF_STV_Shift), - ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift), - - ELF_Other_Weakref = (1 << ELF_Other_Shift), - ELF_Other_ThumbFunc = (2 << ELF_Other_Shift) + ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift) }; } // end namespace llvm diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 5d559744da97..e96ecb4be175 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -15,11 +15,13 @@ #include "llvm/Support/DataTypes.h" namespace llvm { +class MCAsmInfo; class MCAsmLayout; class MCAssembler; class MCContext; class MCSection; class MCSectionData; +class MCStreamer; class MCSymbol; class MCValue; class raw_ostream; @@ -52,8 +54,9 @@ protected: bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, - const SectionAddrMap *Addrs, - bool InSet) const; + const SectionAddrMap *Addrs, bool InSet, + bool ForceVarExpansion) const; + public: /// @name Accessors /// @{ @@ -90,7 +93,15 @@ public: /// @param Res - The relocatable value, if evaluation succeeds. /// @param Layout - The assembler layout object to use for evaluating values. /// @result - True on success. - bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout &Layout) const; + bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout) const; + + /// \brief Try to evaluate the expression to the form (a - b + constant) where + /// neither a nor b are variables. + /// + /// This is a more aggressive variant of EvaluateAsRelocatable. The intended + /// use is for when relocations are not available, like the symbol value in + /// the symbol table. + bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout) const; /// FindAssociatedSection - Find the "associated section" for this expression, /// which is currently defined as the absolute section for constants, or @@ -157,19 +168,24 @@ public: VK_TLSLDM, VK_TPOFF, VK_DTPOFF, - VK_TLVP, // Mach-O thread local variable relocation + VK_TLVP, // Mach-O thread local variable relocations + VK_TLVPPAGE, + VK_TLVPPAGEOFF, + VK_PAGE, + VK_PAGEOFF, + VK_GOTPAGE, + VK_GOTPAGEOFF, VK_SECREL, - // FIXME: We'd really like to use the generic Kinds listed above for these. + VK_WEAKREF, // The link between the symbols in .weakref foo, bar + VK_ARM_NONE, - VK_ARM_PLT, // ARM-style PLT references. i.e., (PLT) instead of @PLT - VK_ARM_TLSGD, // ditto for TLSGD, GOT, GOTOFF, TPOFF and GOTTPOFF - VK_ARM_GOT, - VK_ARM_GOTOFF, - VK_ARM_TPOFF, - VK_ARM_GOTTPOFF, VK_ARM_TARGET1, VK_ARM_TARGET2, VK_ARM_PREL31, + VK_ARM_TLSLDO, // symbol(tlsldo) + VK_ARM_TLSCALL, // symbol(tlscall) + VK_ARM_TLSDESC, // symbol(tlsdesc) + VK_ARM_TLSDESCSEQ, VK_PPC_LO, // symbol@l VK_PPC_HI, // symbol@h @@ -247,6 +263,8 @@ public: VK_Mips_GOT_LO16, VK_Mips_CALL_HI16, VK_Mips_CALL_LO16, + VK_Mips_PCREL_HI16, + VK_Mips_PCREL_LO16, VK_COFF_IMGREL32 // symbol@imgrel (image-relative) }; @@ -258,9 +276,14 @@ private: /// The symbol reference modifier. const VariantKind Kind; - explicit MCSymbolRefExpr(const MCSymbol *_Symbol, VariantKind _Kind) - : MCExpr(MCExpr::SymbolRef), Symbol(_Symbol), Kind(_Kind) { + /// MCAsmInfo that is used to print symbol variants correctly. + const MCAsmInfo *MAI; + + explicit MCSymbolRefExpr(const MCSymbol *_Symbol, VariantKind _Kind, + const MCAsmInfo *_MAI) + : MCExpr(MCExpr::SymbolRef), Symbol(_Symbol), Kind(_Kind), MAI(_MAI) { assert(Symbol); + assert(MAI); } public: @@ -281,6 +304,7 @@ public: /// @{ const MCSymbol &getSymbol() const { return *Symbol; } + const MCAsmInfo &getMCAsmInfo() const { return *MAI; } VariantKind getKind() const { return Kind; } @@ -501,7 +525,7 @@ public: virtual void PrintImpl(raw_ostream &OS) const = 0; virtual bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout) const = 0; - virtual void AddValueSymbols(MCAssembler *) const = 0; + virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; virtual const MCSection *FindAssociatedSection() const = 0; virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0; diff --git a/include/llvm/MC/MCExternalSymbolizer.h b/include/llvm/MC/MCExternalSymbolizer.h index c942adca3b4d..2c7d23707c95 100644 --- a/include/llvm/MC/MCExternalSymbolizer.h +++ b/include/llvm/MC/MCExternalSymbolizer.h @@ -18,6 +18,7 @@ #include "llvm-c/Disassembler.h" #include "llvm/MC/MCSymbolizer.h" +#include <memory> namespace llvm { @@ -25,7 +26,7 @@ namespace llvm { /// /// See llvm-c/Disassembler.h. class MCExternalSymbolizer : public MCSymbolizer { - +protected: /// \name Hooks for symbolic disassembly via the public 'C' interface. /// @{ /// The function to get the symbolic information for operands. @@ -38,19 +39,18 @@ class MCExternalSymbolizer : public MCSymbolizer { public: MCExternalSymbolizer(MCContext &Ctx, - OwningPtr<MCRelocationInfo> &RelInfo, + std::unique_ptr<MCRelocationInfo> RelInfo, LLVMOpInfoCallback getOpInfo, - LLVMSymbolLookupCallback symbolLookUp, - void *disInfo) - : MCSymbolizer(Ctx, RelInfo), - GetOpInfo(getOpInfo), SymbolLookUp(symbolLookUp), DisInfo(disInfo) {} + LLVMSymbolLookupCallback symbolLookUp, void *disInfo) + : MCSymbolizer(Ctx, std::move(RelInfo)), GetOpInfo(getOpInfo), + SymbolLookUp(symbolLookUp), DisInfo(disInfo) {} bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &CommentStream, - int64_t Value, - uint64_t Address, bool IsBranch, - uint64_t Offset, uint64_t InstSize); + int64_t Value, uint64_t Address, bool IsBranch, + uint64_t Offset, uint64_t InstSize) override; void tryAddingPcLoadReferenceComment(raw_ostream &CommentStream, - int64_t Value, uint64_t Address); + int64_t Value, + uint64_t Address) override; }; } diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h index 16e9eb730b4e..98a1419a1934 100644 --- a/include/llvm/MC/MCFixup.h +++ b/include/llvm/MC/MCFixup.h @@ -10,6 +10,7 @@ #ifndef LLVM_MC_MCFIXUP_H #define LLVM_MC_MCFIXUP_H +#include "llvm/MC/MCExpr.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SMLoc.h" diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 4766815da556..6918280a4219 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -184,18 +184,18 @@ public: /// \brief Dump the MCInst as prettily as possible using the additional MC /// structures, if given. Operators are separated by the \p Separator /// string. - void dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI = 0, - const MCInstPrinter *Printer = 0, + void dump_pretty(raw_ostream &OS, const MCAsmInfo *MAI = nullptr, + const MCInstPrinter *Printer = nullptr, StringRef Separator = " ") const; }; inline raw_ostream& operator<<(raw_ostream &OS, const MCOperand &MO) { - MO.print(OS, 0); + MO.print(OS, nullptr); return OS; } inline raw_ostream& operator<<(raw_ostream &OS, const MCInst &MI) { - MI.print(OS, 0); + MI.print(OS, nullptr); return OS; } diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index b4258bef04ce..7f55b29f8ee0 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -57,8 +57,9 @@ protected: public: MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri) - : CommentStream(0), MAI(mai), MII(mii), MRI(mri), AvailableFeatures(0), - UseMarkup(0), PrintImmHex(0), PrintHexStyle(HexStyle::C) {} + : CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri), + AvailableFeatures(0), UseMarkup(0), PrintImmHex(0), + PrintHexStyle(HexStyle::C) {} virtual ~MCInstPrinter(); diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h index 17bfd1582ae5..e921f768ac45 100644 --- a/include/llvm/MC/MCInstrAnalysis.h +++ b/include/llvm/MC/MCInstrAnalysis.h @@ -12,6 +12,9 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_MC_MCINSTRANALYSIS_H +#define LLVM_MC_MCINSTRANALYSIS_H + #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" @@ -63,4 +66,6 @@ public: uint64_t &Target) const; }; -} +} // End llvm namespace + +#endif diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 214b593f4ad6..5896de7f76df 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -504,7 +504,7 @@ public: /// \brief Return the number of implicit uses this instruction has. unsigned getNumImplicitUses() const { - if (ImplicitUses == 0) return 0; + if (!ImplicitUses) return 0; unsigned i = 0; for (; ImplicitUses[i]; ++i) /*empty*/; return i; @@ -526,7 +526,7 @@ public: /// \brief Return the number of implicit defs this instruct has. unsigned getNumImplicitDefs() const { - if (ImplicitDefs == 0) return 0; + if (!ImplicitDefs) return 0; unsigned i = 0; for (; ImplicitDefs[i]; ++i) /*empty*/; return i; @@ -544,7 +544,7 @@ public: /// \brief Return true if this instruction implicitly /// defines the specified physical register. bool hasImplicitDefOfPhysReg(unsigned Reg, - const MCRegisterInfo *MRI = 0) const { + const MCRegisterInfo *MRI = nullptr) const { if (const uint16_t *ImpDefs = ImplicitDefs) for (; *ImpDefs; ++ImpDefs) if (*ImpDefs == Reg || (MRI && MRI->isSubRegister(Reg, *ImpDefs))) diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index c4f9e1c32ab1..5104345e1abb 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -119,8 +119,8 @@ public: /// Ctors. /// InstrItineraryData() : SchedModel(&MCSchedModel::DefaultSchedModel), - Stages(0), OperandCycles(0), - Forwardings(0), Itineraries(0) {} + Stages(nullptr), OperandCycles(nullptr), + Forwardings(nullptr), Itineraries(nullptr) {} InstrItineraryData(const MCSchedModel *SM, const InstrStage *S, const unsigned *OS, const unsigned *F) @@ -129,7 +129,7 @@ public: /// isEmpty - Returns true if there are no itineraries. /// - bool isEmpty() const { return Itineraries == 0; } + bool isEmpty() const { return Itineraries == nullptr; } /// isEndMarker - Returns true if the index is for the end marker /// itinerary. diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h new file mode 100644 index 000000000000..50fd527ffe2a --- /dev/null +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -0,0 +1,205 @@ +//===- MCLinkerOptimizationHint.h - LOH interface ---------------*- C++ -*-===// +// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares some helpers classes to handle Linker Optimization Hint +// (LOH). +// +// FIXME: LOH interface supports only MachO format at the moment. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCLINKEROPTIMIZATIONHINT_H +#define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCMachObjectWriter.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +// Forward declarations. +class MCAsmLayout; +class MCSymbol; + +/// Linker Optimization Hint Type. +enum MCLOHType { + MCLOH_AdrpAdrp = 0x1u, ///< Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE. + MCLOH_AdrpLdr = 0x2u, ///< Adrp _v@PAGE -> Ldr _v@PAGEOFF. + MCLOH_AdrpAddLdr = 0x3u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr. + MCLOH_AdrpLdrGotLdr = 0x4u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr. + MCLOH_AdrpAddStr = 0x5u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Str. + MCLOH_AdrpLdrGotStr = 0x6u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str. + MCLOH_AdrpAdd = 0x7u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF. + MCLOH_AdrpLdrGot = 0x8u ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF. +}; + +static inline StringRef MCLOHDirectiveName() { + return StringRef(".loh"); +} + +static inline bool isValidMCLOHType(MCLOHType Kind) { + return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot; +} + +static inline int MCLOHNameToId(StringRef Name) { +#define MCLOHCaseNameToId(Name) .Case(#Name, MCLOH_ ## Name) + return StringSwitch<int>(Name) + MCLOHCaseNameToId(AdrpAdrp) + MCLOHCaseNameToId(AdrpLdr) + MCLOHCaseNameToId(AdrpAddLdr) + MCLOHCaseNameToId(AdrpLdrGotLdr) + MCLOHCaseNameToId(AdrpAddStr) + MCLOHCaseNameToId(AdrpLdrGotStr) + MCLOHCaseNameToId(AdrpAdd) + MCLOHCaseNameToId(AdrpLdrGot) + .Default(-1); +} + +static inline StringRef MCLOHIdToName(MCLOHType Kind) { +#define MCLOHCaseIdToName(Name) case MCLOH_ ## Name: return StringRef(#Name); + switch (Kind) { + MCLOHCaseIdToName(AdrpAdrp); + MCLOHCaseIdToName(AdrpLdr); + MCLOHCaseIdToName(AdrpAddLdr); + MCLOHCaseIdToName(AdrpLdrGotLdr); + MCLOHCaseIdToName(AdrpAddStr); + MCLOHCaseIdToName(AdrpLdrGotStr); + MCLOHCaseIdToName(AdrpAdd); + MCLOHCaseIdToName(AdrpLdrGot); + } + return StringRef(); +} + +static inline int MCLOHIdToNbArgs(MCLOHType Kind) { + switch (Kind) { + // LOH with two arguments + case MCLOH_AdrpAdrp: + case MCLOH_AdrpLdr: + case MCLOH_AdrpAdd: + case MCLOH_AdrpLdrGot: + return 2; + // LOH with three arguments + case MCLOH_AdrpAddLdr: + case MCLOH_AdrpLdrGotLdr: + case MCLOH_AdrpAddStr: + case MCLOH_AdrpLdrGotStr: + return 3; + } + return -1; +} + +/// Store Linker Optimization Hint information (LOH). +class MCLOHDirective { + MCLOHType Kind; + + /// Arguments of this directive. Order matters. + SmallVector<MCSymbol *, 3> Args; + + /// Emit this directive in @p OutStream using the information available + /// in the given @p ObjWriter and @p Layout to get the address of the + /// arguments within the object file. + void Emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter, + const MCAsmLayout &Layout) const; + +public: + typedef SmallVectorImpl<MCSymbol *> LOHArgs; + + MCLOHDirective(MCLOHType Kind, const LOHArgs &Args) + : Kind(Kind), Args(Args.begin(), Args.end()) { + assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!"); + } + + MCLOHType getKind() const { return Kind; } + + const LOHArgs &getArgs() const { return Args; } + + /// Emit this directive as: + /// <kind, numArgs, addr1, ..., addrN> + void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { + raw_ostream &OutStream = ObjWriter.getStream(); + Emit_impl(OutStream, ObjWriter, Layout); + } + + /// Get the size in bytes of this directive if emitted in @p ObjWriter with + /// the given @p Layout. + uint64_t getEmitSize(const MachObjectWriter &ObjWriter, + const MCAsmLayout &Layout) const { + class raw_counting_ostream : public raw_ostream { + uint64_t Count; + + void write_impl(const char *, size_t size) override { Count += size; } + + uint64_t current_pos() const override { return Count; } + + public: + raw_counting_ostream() : Count(0) {} + ~raw_counting_ostream() { flush(); } + }; + + raw_counting_ostream OutStream; + Emit_impl(OutStream, ObjWriter, Layout); + return OutStream.tell(); + } +}; + +class MCLOHContainer { + /// Keep track of the emit size of all the LOHs. + mutable uint64_t EmitSize; + + /// Keep track of all LOH directives. + SmallVector<MCLOHDirective, 32> Directives; + +public: + typedef SmallVectorImpl<MCLOHDirective> LOHDirectives; + + MCLOHContainer() : EmitSize(0) {}; + + /// Const accessor to the directives. + const LOHDirectives &getDirectives() const { + return Directives; + } + + /// Add the directive of the given kind @p Kind with the given arguments + /// @p Args to the container. + void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) { + Directives.push_back(MCLOHDirective(Kind, Args)); + } + + /// Get the size of the directives if emitted. + uint64_t getEmitSize(const MachObjectWriter &ObjWriter, + const MCAsmLayout &Layout) const { + if (!EmitSize) { + for (const MCLOHDirective &D : Directives) + EmitSize += D.getEmitSize(ObjWriter, Layout); + } + return EmitSize; + } + + /// Emit all Linker Optimization Hint in one big table. + /// Each line of the table is emitted by LOHDirective::Emit. + void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { + for (const MCLOHDirective &D : Directives) + D.Emit(ObjWriter, Layout); + } + + void reset() { + Directives.clear(); + EmitSize = 0; + } +}; + +// Add types for specialized template using MCSymbol. +typedef MCLOHDirective::LOHArgs MCLOHArgs; +typedef MCLOHContainer::LOHDirectives MCLOHDirectives; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 3ba6e651007c..12a7f0ee7bb5 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -11,7 +11,6 @@ #define LLVM_MC_MCMACHOBJECTWRITER_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" @@ -92,7 +91,7 @@ class MachObjectWriter : public MCObjectWriter { }; /// The target specific Mach-O writer instance. - llvm::OwningPtr<MCMachObjectTargetWriter> TargetObjectWriter; + std::unique_ptr<MCMachObjectTargetWriter> TargetObjectWriter; /// @name Relocation Data /// @{ @@ -112,6 +111,8 @@ class MachObjectWriter : public MCObjectWriter { /// @} + MachSymbolData *findSymbolData(const MCSymbol &Sym); + public: MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS, bool _IsLittleEndian) @@ -121,7 +122,7 @@ public: /// @name Lifetime management Methods /// @{ - virtual void reset(); + void reset() override; /// @} @@ -154,9 +155,9 @@ public: /// @{ bool is64Bit() const { return TargetObjectWriter->is64Bit(); } - bool isARM() const { - uint32_t CPUType = TargetObjectWriter->getCPUType() & ~MachO::CPU_ARCH_MASK; - return CPUType == MachO::CPU_TYPE_ARM; + bool isX86_64() const { + uint32_t CPUType = TargetObjectWriter->getCPUType(); + return CPUType == MachO::CPU_TYPE_X86_64; } /// @} @@ -231,7 +232,8 @@ public: void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, - MCValue Target, uint64_t &FixedValue); + MCValue Target, bool &IsPCRel, + uint64_t &FixedValue) override; void BindIndirectSymbols(MCAssembler &Asm); @@ -248,15 +250,16 @@ public: void markAbsoluteVariableSymbols(MCAssembler &Asm, const MCAsmLayout &Layout); - void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout); + void ExecutePostLayoutBinding(MCAssembler &Asm, + const MCAsmLayout &Layout) override; - virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, - bool IsPCRel) const; + bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const override; - void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); + void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; }; diff --git a/include/llvm/MC/MCObjectDisassembler.h b/include/llvm/MC/MCObjectDisassembler.h index 0d87d33bab98..5b935db59585 100644 --- a/include/llvm/MC/MCObjectDisassembler.h +++ b/include/llvm/MC/MCObjectDisassembler.h @@ -16,7 +16,6 @@ #define LLVM_MC_MCOBJECTDISASSEMBLER_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MemoryObject.h" @@ -67,8 +66,8 @@ public: /// \brief Set the region on which to fallback if disassembly was requested /// somewhere not accessible in the object file. /// This is used for dynamic disassembly (see RawMemoryObject). - void setFallbackRegion(OwningPtr<MemoryObject> &Region) { - FallbackRegion.reset(Region.take()); + void setFallbackRegion(std::unique_ptr<MemoryObject> &Region) { + FallbackRegion.reset(Region.release()); } /// \brief Set the symbolizer to use to get information on external functions. @@ -113,7 +112,7 @@ protected: MCObjectSymbolizer *MOS; /// \brief The fallback memory region, outside the object file. - OwningPtr<MemoryObject> FallbackRegion; + std::unique_ptr<MemoryObject> FallbackRegion; /// \brief Return a memory region suitable for reading starting at \p Addr. /// In most cases, this returns a StringRefMemoryObject backed by the @@ -162,12 +161,12 @@ public: uint64_t HeaderLoadAddress); protected: - uint64_t getEffectiveLoadAddr(uint64_t Addr) LLVM_OVERRIDE; - uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr) LLVM_OVERRIDE; - uint64_t getEntrypoint() LLVM_OVERRIDE; + uint64_t getEffectiveLoadAddr(uint64_t Addr) override; + uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr) override; + uint64_t getEntrypoint() override; - ArrayRef<uint64_t> getStaticInitFunctions() LLVM_OVERRIDE; - ArrayRef<uint64_t> getStaticExitFunctions() LLVM_OVERRIDE; + ArrayRef<uint64_t> getStaticInitFunctions() override; + ArrayRef<uint64_t> getStaticExitFunctions() override; }; } diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index c48dcb021620..4d1715eccf5a 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -14,13 +14,13 @@ #ifndef LLVM_MC_MCBJECTFILEINFO_H #define LLVM_MC_MCBJECTFILEINFO_H +#include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" namespace llvm { class MCContext; class MCSection; class StringRef; - class Triple; class MCObjectFileInfo { protected: @@ -33,17 +33,15 @@ protected: /// weak_definition of constant 0 for an omitted EH frame. bool SupportsWeakOmittedEHFrame; - /// IsFunctionEHFrameSymbolPrivate - This flag is set to true if the - /// "EH_frame" symbol for EH information should be an assembler temporary (aka - /// private linkage, aka an L or .L label) or false if it should be a normal - /// non-.globl label. This defaults to true. - bool IsFunctionEHFrameSymbolPrivate; + /// SupportsCompactUnwindWithoutEHFrame - True if the target object file + /// supports emitting a compact unwind section without an associated EH frame + /// section. + bool SupportsCompactUnwindWithoutEHFrame; - /// PersonalityEncoding, LSDAEncoding, FDEEncoding, TTypeEncoding - Some - /// encoding values for EH. + /// PersonalityEncoding, LSDAEncoding, TTypeEncoding - Some encoding values + /// for EH. unsigned PersonalityEncoding; unsigned LSDAEncoding; - unsigned FDEEncoding; unsigned FDECFIEncoding; unsigned TTypeEncoding; @@ -129,6 +127,8 @@ protected: const MCSection *DwarfGnuPubNamesSection; const MCSection *DwarfGnuPubTypesSection; + const MCSection *COFFDebugSymbolsSection; + // Extra TLS Variable Data section. If the target needs to put additional // information for a TLS variable, it'll go here. const MCSection *TLSExtraDataSection; @@ -195,21 +195,19 @@ public: void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, MCContext &ctx); - bool isFunctionEHFrameSymbolPrivate() const { - return IsFunctionEHFrameSymbolPrivate; - } bool getSupportsWeakOmittedEHFrame() const { return SupportsWeakOmittedEHFrame; } + bool getSupportsCompactUnwindWithoutEHFrame() const { + return SupportsCompactUnwindWithoutEHFrame; + } bool getCommDirectiveSupportsAlignment() const { return CommDirectiveSupportsAlignment; } unsigned getPersonalityEncoding() const { return PersonalityEncoding; } unsigned getLSDAEncoding() const { return LSDAEncoding; } - unsigned getFDEEncoding(bool CFI) const { - return CFI ? FDECFIEncoding : FDEEncoding; - } + unsigned getFDEEncoding() const { return FDECFIEncoding; } unsigned getTTypeEncoding() const { return TTypeEncoding; } unsigned getCompactUnwindDwarfEHFrameOnly() const { @@ -262,6 +260,8 @@ public: const MCSection *getDwarfInfoDWOSection() const { return DwarfInfoDWOSection; } + const MCSection *getDwarfTypesSection(uint64_t Hash) const; + const MCSection *getDwarfTypesDWOSection(uint64_t Hash) const; const MCSection *getDwarfAbbrevDWOSection() const { return DwarfAbbrevDWOSection; } @@ -281,6 +281,10 @@ public: return DwarfAddrSection; } + const MCSection *getCOFFDebugSymbolsSection() const { + return COFFDebugSymbolsSection; + } + const MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; } @@ -353,12 +357,21 @@ public: return EHFrameSection; } -private: enum Environment { IsMachO, IsELF, IsCOFF }; + Environment getObjectFileType() const { + return Env; + } + + Reloc::Model getRelocM() const { + return RelocM; + } + +private: Environment Env; Reloc::Model RelocM; CodeModel::Model CMModel; MCContext *Ctx; + Triple TT; void InitMachOMCObjectFileInfo(Triple T); void InitELFMCObjectFileInfo(Triple T); @@ -367,6 +380,9 @@ private: /// InitEHFrameSection - Initialize EHFrameSection on demand. /// void InitEHFrameSection(); + +public: + const Triple &getTargetTriple() const { return TT; } }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 56675443015e..8d37c85b0585 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -17,6 +17,7 @@ namespace llvm { class MCAssembler; class MCCodeEmitter; class MCSectionData; +class MCSubtargetInfo; class MCExpr; class MCFragment; class MCDataFragment; @@ -34,23 +35,32 @@ class MCObjectStreamer : public MCStreamer { MCAssembler *Assembler; MCSectionData *CurSectionData; MCSectionData::iterator CurInsertionPoint; + bool EmitEHFrame; + bool EmitDebugFrame; - virtual void EmitInstToData(const MCInst &Inst) = 0; - virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); - virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame); + virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0; + void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; + void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; protected: - MCObjectStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, - MCAsmBackend &TAB, raw_ostream &_OS, + MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter); - MCObjectStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, - MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, - MCAssembler *_Assembler); + MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, + MCCodeEmitter *_Emitter, MCAssembler *_Assembler); ~MCObjectStreamer(); public: /// state management - virtual void reset(); + void reset() override; + + /// Object streamers require the integrated assembler. + bool isIntegratedAssemblerRequired() const override { return true; } + + MCSymbolData &getOrCreateSymbolData(const MCSymbol *Symbol) { + return getAssembler().getOrCreateSymbolData(*Symbol); + } + void EmitFrames(MCAsmBackend *MAB); + void EmitCFISections(bool EH, bool Debug) override; protected: MCSectionData *getCurrentSectionData() const { @@ -68,55 +78,57 @@ protected: /// fragment is not a data fragment. MCDataFragment *getOrCreateDataFragment() const; - const MCExpr *AddValueSymbols(const MCExpr *Value); - public: + void visitUsedSymbol(const MCSymbol &Sym) override; + MCAssembler &getAssembler() { return *Assembler; } /// @name MCStreamer Interface /// @{ - virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitDebugLabel(MCSymbol *Symbol); - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); - virtual void EmitULEB128Value(const MCExpr *Value); - virtual void EmitSLEB128Value(const MCExpr *Value); - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual void ChangeSection(const MCSection *Section, - const MCExpr *Subsection); - virtual void EmitInstruction(const MCInst &Inst); + void EmitLabel(MCSymbol *Symbol) override; + void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; + void EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc = SMLoc()) override; + void EmitULEB128Value(const MCExpr *Value) override; + void EmitSLEB128Value(const MCExpr *Value) override; + void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; + void ChangeSection(const MCSection *Section, + const MCExpr *Subsection) override; + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo& STI) override; /// \brief Emit an instruction to a special fragment, because this instruction /// can change its size during relaxation. - virtual void EmitInstToFragment(const MCInst &Inst); - - virtual void EmitBundleAlignMode(unsigned AlignPow2); - virtual void EmitBundleLock(bool AlignToEnd); - virtual void EmitBundleUnlock(); - virtual void EmitBytes(StringRef Data); - virtual void EmitValueToAlignment(unsigned ByteAlignment, - int64_t Value = 0, - unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0); - virtual void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0); - virtual bool EmitValueToOffset(const MCExpr *Offset, unsigned char Value); - virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, - unsigned Column, unsigned Flags, - unsigned Isa, unsigned Discriminator, - StringRef FileName); - virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize); - virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, - const MCSymbol *Label); - virtual void EmitGPRel32Value(const MCExpr *Value); - virtual void EmitGPRel64Value(const MCExpr *Value); - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); - virtual void EmitZeros(uint64_t NumBytes); - virtual void FinishImpl(); + virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &); + + void EmitBundleAlignMode(unsigned AlignPow2) override; + void EmitBundleLock(bool AlignToEnd) override; + void EmitBundleUnlock() override; + void EmitBytes(StringRef Data) override; + void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, + unsigned ValueSize = 1, + unsigned MaxBytesToEmit = 0) override; + void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0) override; + bool EmitValueToOffset(const MCExpr *Offset, unsigned char Value) override; + void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName) override; + void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, + const MCSymbol *Label, + unsigned PointerSize); + void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label); + void EmitGPRel32Value(const MCExpr *Value) override; + void EmitGPRel64Value(const MCExpr *Value) override; + void EmitFill(uint64_t NumBytes, uint8_t FillValue) override; + void EmitZeros(uint64_t NumBytes) override; + void FinishImpl() override; + + virtual bool mayHaveInstructions() const { + return getCurrentSectionData()->hasInstructions(); + } }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectSymbolizer.h b/include/llvm/MC/MCObjectSymbolizer.h index 64b932ebe4f9..f75b7f58a141 100644 --- a/include/llvm/MC/MCObjectSymbolizer.h +++ b/include/llvm/MC/MCObjectSymbolizer.h @@ -41,7 +41,7 @@ protected: const object::RelocationRef *findRelocationAt(uint64_t Addr); const object::SectionRef *findSectionContaining(uint64_t Addr); - MCObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, + MCObjectSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> RelInfo, const object::ObjectFile *Obj); public: @@ -50,10 +50,11 @@ public: bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, int64_t Value, uint64_t Address, bool IsBranch, uint64_t Offset, - uint64_t InstSize); + uint64_t InstSize) override; void tryAddingPcLoadReferenceComment(raw_ostream &cStream, - int64_t Value, uint64_t Address); + int64_t Value, + uint64_t Address) override; /// @} /// \brief Look for an external function symbol at \p Addr. @@ -63,8 +64,9 @@ public: /// \brief Create an object symbolizer for \p Obj. static MCObjectSymbolizer * - createObjectSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo, - const object::ObjectFile *Obj); + createObjectSymbolizer(MCContext &Ctx, + std::unique_ptr<MCRelocationInfo> RelInfo, + const object::ObjectFile *Obj); private: typedef DenseMap<uint64_t, object::RelocationRef> AddrToRelocMap; diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 4939a3f1fb07..55c828c6c179 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -80,6 +80,7 @@ public: const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) = 0; /// \brief Check whether the difference (A - B) between two symbol diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 1b3ab577519b..0b550ba627e9 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -28,7 +28,7 @@ class AsmLexer : public MCAsmLexer { const MCAsmInfo &MAI; const char *CurPtr; - const MemoryBuffer *CurBuf; + StringRef CurBuf; bool isAtStartOfLine; void operator=(const AsmLexer&) LLVM_DELETED_FUNCTION; @@ -36,17 +36,19 @@ class AsmLexer : public MCAsmLexer { protected: /// LexToken - Read the next token and return its code. - virtual AsmToken LexToken(); + AsmToken LexToken() override; public: AsmLexer(const MCAsmInfo &MAI); ~AsmLexer(); - void setBuffer(const MemoryBuffer *buf, const char *ptr = NULL); + void setBuffer(StringRef Buf, const char *ptr = nullptr); - virtual StringRef LexUntilEndOfStatement(); + StringRef LexUntilEndOfStatement() override; StringRef LexUntilEndOfLine(); + const AsmToken peekTok(bool ShouldSkipSpace = true) override; + bool isAtStartOfComment(char Char); bool isAtStatementSeparator(const char *Ptr); diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index 53b380f12f71..e3d4181e086f 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -10,6 +10,7 @@ #ifndef LLVM_MC_MCPARSER_MCASMLEXER_H #define LLVM_MC_MCPARSER_MCASMLEXER_H +#include "llvm/ADT/APInt.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" @@ -30,6 +31,7 @@ public: // Integer values. Integer, + BigNum, // larger than 64 bits // Real values. Real, @@ -57,12 +59,14 @@ private: /// a memory buffer owned by the source manager. StringRef Str; - int64_t IntVal; + APInt IntVal; public: AsmToken() {} - AsmToken(TokenKind _Kind, StringRef _Str, int64_t _IntVal = 0) + AsmToken(TokenKind _Kind, StringRef _Str, APInt _IntVal) : Kind(_Kind), Str(_Str), IntVal(_IntVal) {} + AsmToken(TokenKind _Kind, StringRef _Str, int64_t _IntVal = 0) + : Kind(_Kind), Str(_Str), IntVal(64, _IntVal, true) {} TokenKind getKind() const { return Kind; } bool is(TokenKind K) const { return Kind == K; } @@ -99,6 +103,12 @@ public: // as a single token, then diagnose as an invalid number). int64_t getIntVal() const { assert(Kind == Integer && "This token isn't an integer!"); + return IntVal.getZExtValue(); + } + + APInt getAPIntVal() const { + assert((Kind == Integer || Kind == BigNum) && + "This token isn't an integer!"); return IntVal; } }; @@ -118,6 +128,7 @@ class MCAsmLexer { protected: // Can only create subclasses. const char *TokStart; bool SkipSpace; + bool AllowAtInIdentifier; MCAsmLexer(); @@ -149,6 +160,9 @@ public: return CurTok; } + /// peekTok - Look ahead at the next token to be lexed. + virtual const AsmToken peekTok(bool ShouldSkipSpace = true) = 0; + /// getErrLoc - Get the current error location const SMLoc &getErrLoc() { return ErrLoc; @@ -170,6 +184,9 @@ public: /// setSkipSpace - Set whether spaces should be ignored by the lexer void setSkipSpace(bool val) { SkipSpace = val; } + + bool getAllowAtInIdentifier() { return AllowAtInIdentifier; } + void setAllowAtInIdentifier(bool v) { AllowAtInIdentifier = v; } }; } // End llvm namespace diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 1d1553429994..9836795450ff 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -30,23 +30,24 @@ class SMRange; class SourceMgr; class Twine; +class InlineAsmIdentifierInfo { +public: + void *OpDecl; + bool IsVarDecl; + unsigned Length, Size, Type; + + void clear() { + OpDecl = nullptr; + IsVarDecl = false; + Length = 1; + Size = 0; + Type = 0; + } +}; + /// MCAsmParserSemaCallback - Generic Sema callback for assembly parser. class MCAsmParserSemaCallback { public: - typedef struct { - void *OpDecl; - bool IsVarDecl; - unsigned Length, Size, Type; - - void clear() { - OpDecl = 0; - IsVarDecl = false; - Length = 1; - Size = 0; - Type = 0; - } - } InlineAsmIdentifierInfo; - virtual ~MCAsmParserSemaCallback(); virtual void *LookupInlineAsmIdentifier(StringRef &LineBuf, InlineAsmIdentifierInfo &Info, @@ -56,9 +57,6 @@ public: unsigned &Offset) = 0; }; -typedef MCAsmParserSemaCallback::InlineAsmIdentifierInfo - InlineAsmIdentifierInfo; - /// MCAsmParser - Generic assembler parser interface, for use by target specific /// assembly parsers. class MCAsmParser { @@ -118,6 +116,10 @@ public: const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0; + /// Note - Emit a note at the location \p L, with the message \p Msg. + virtual void Note(SMLoc L, const Twine &Msg, + ArrayRef<SMRange> Ranges = None) = 0; + /// Warning - Emit a warning at the location \p L, with the message \p Msg. /// /// \return The return value is true, if warnings are fatal. diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 818fbbd6c6c8..e8740aa10aa2 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -38,7 +38,7 @@ public: unsigned getMCOperandNum() { return MCOperandNum; } virtual StringRef getSymName() { return StringRef(); } - virtual void *getOpDecl() { return 0; } + virtual void *getOpDecl() { return nullptr; } /// isToken - Is this a token operand? virtual bool isToken() const = 0; diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index 3fa89c109c1c..766f63182925 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -159,7 +159,7 @@ private: const MCRegisterClass *Classes; // Pointer to the regclass array unsigned NumClasses; // Number of entries in the array unsigned NumRegUnits; // Number of regunits. - const uint16_t (*RegUnitRoots)[2]; // Pointer to regunit root table. + const MCPhysReg (*RegUnitRoots)[2]; // Pointer to regunit root table. const MCPhysReg *DiffLists; // Pointer to the difflists array const char *RegStrings; // Pointer to the string table. const uint16_t *SubRegIndices; // Pointer to the subreg lookup @@ -191,7 +191,7 @@ public: protected: /// Create an invalid iterator. Call init() to point to something useful. - DiffListIterator() : Val(0), List(0) {} + DiffListIterator() : Val(0), List(nullptr) {} /// init - Point the iterator to InitVal, decoding subsequent values from /// DiffList. The iterator will initially point to InitVal, sub-classes are @@ -223,7 +223,7 @@ public: void operator++() { // The end of the list is encoded as a 0 differential. if (!advance()) - List = 0; + List = nullptr; } }; @@ -239,7 +239,7 @@ public: void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA, unsigned PC, const MCRegisterClass *C, unsigned NC, - const uint16_t (*RURoots)[2], + const MCPhysReg (*RURoots)[2], unsigned NRU, const MCPhysReg *DL, const char *Strings, diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index 6881e1d05ac3..43b8672265c6 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -32,11 +32,16 @@ struct MCProcResourceDesc { // Number of resources that may be buffered. // - // Buffered resources (BufferSize > 0 || BufferSize == -1) may be consumed at - // some indeterminate cycle after dispatch (e.g. for instructions that may - // issue out-of-order). Unbuffered resources (BufferSize == 0) always consume - // their resource some fixed number of cycles after dispatch (e.g. for - // instruction interlocking that may stall the pipeline). + // Buffered resources (BufferSize != 0) may be consumed at some indeterminate + // cycle after dispatch. This should be used for out-of-order cpus when + // instructions that use this resource can be buffered in a reservaton + // station. + // + // Unbuffered resources (BufferSize == 0) always consume their resource some + // fixed number of cycles after dispatch. If a resource is unbuffered, then + // the scheduler will avoid scheduling instructions with conflicting resources + // in the same cycle. This is for in-order cpus, or the in-order portion of + // an out-of-order cpus. int BufferSize; bool operator==(const MCProcResourceDesc &Other) const { @@ -149,11 +154,19 @@ public: // but we balance those stalls against other heuristics. // // "> 1" means the processor is out-of-order. This is a machine independent - // estimate of highly machine specific characteristics such are the register + // estimate of highly machine specific characteristics such as the register // renaming pool and reorder buffer. unsigned MicroOpBufferSize; static const unsigned DefaultMicroOpBufferSize = 0; + // LoopMicroOpBufferSize is the number of micro-ops that the processor may + // buffer for optimized loop execution. More generally, this represents the + // optimal number of micro-ops in a loop body. A loop may be partially + // unrolled to bring the count of micro-ops in the loop body closer to this + // number. + unsigned LoopMicroOpBufferSize; + static const unsigned DefaultLoopMicroOpBufferSize = 0; + // LoadLatency is the expected latency of load instructions. // // If MinLatency >= 0, this may be overriden for individual load opcodes by @@ -173,6 +186,8 @@ public: // takes to recover from a branch misprediction. unsigned MispredictPenalty; static const unsigned DefaultMispredictPenalty = 10; + + bool PostRAScheduler; // default value is false bool CompleteModel; @@ -193,24 +208,27 @@ public: // MCSchedModel instead of using a generated itinerary. MCSchedModel(): IssueWidth(DefaultIssueWidth), MicroOpBufferSize(DefaultMicroOpBufferSize), + LoopMicroOpBufferSize(DefaultLoopMicroOpBufferSize), LoadLatency(DefaultLoadLatency), HighLatency(DefaultHighLatency), MispredictPenalty(DefaultMispredictPenalty), - CompleteModel(true), - ProcID(0), ProcResourceTable(0), SchedClassTable(0), - NumProcResourceKinds(0), NumSchedClasses(0), - InstrItineraries(0) { + PostRAScheduler(false), CompleteModel(true), + ProcID(0), ProcResourceTable(nullptr), + SchedClassTable(nullptr), NumProcResourceKinds(0), + NumSchedClasses(0), InstrItineraries(nullptr) { (void)NumProcResourceKinds; (void)NumSchedClasses; } // Table-gen driven ctor. - MCSchedModel(unsigned iw, int mbs, unsigned ll, unsigned hl, - unsigned mp, bool cm, unsigned pi, const MCProcResourceDesc *pr, - const MCSchedClassDesc *sc, unsigned npr, unsigned nsc, - const InstrItinerary *ii): - IssueWidth(iw), MicroOpBufferSize(mbs), LoadLatency(ll), HighLatency(hl), - MispredictPenalty(mp), CompleteModel(cm), ProcID(pi), + MCSchedModel(unsigned iw, int mbs, int lmbs, unsigned ll, unsigned hl, + unsigned mp, bool postRASched, bool cm, unsigned pi, + const MCProcResourceDesc *pr, const MCSchedClassDesc *sc, + unsigned npr, unsigned nsc, const InstrItinerary *ii): + IssueWidth(iw), MicroOpBufferSize(mbs), LoopMicroOpBufferSize(lmbs), + LoadLatency(ll), HighLatency(hl), + MispredictPenalty(mp), PostRAScheduler(postRASched), + CompleteModel(cm), ProcID(pi), ProcResourceTable(pr), SchedClassTable(sc), NumProcResourceKinds(npr), NumSchedClasses(nsc), InstrItineraries(ii) {} diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 45c84ae71eeb..0bbf3696686e 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -36,30 +36,21 @@ class MCSymbol; /// The COMDAT symbol of this section. Only valid if this is a COMDAT /// section. Two COMDAT sections are merged if they have the same /// COMDAT symbol. - const MCSymbol *COMDATSymbol; + MCSymbol *COMDATSymbol; /// Selection - This is the Selection field for the section symbol, if /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 mutable int Selection; - /// Assoc - This is name of the associated section, if it is a COMDAT - /// section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 with an - /// associative Selection (IMAGE_COMDAT_SELECT_ASSOCIATIVE). - mutable const MCSectionCOFF *Assoc; - private: friend class MCContext; MCSectionCOFF(StringRef Section, unsigned Characteristics, - const MCSymbol *COMDATSymbol, int Selection, - const MCSectionCOFF *Assoc, SectionKind K) + MCSymbol *COMDATSymbol, int Selection, SectionKind K) : MCSection(SV_COFF, K), SectionName(Section), Characteristics(Characteristics), COMDATSymbol(COMDATSymbol), - Selection(Selection), Assoc(Assoc) { + Selection(Selection) { assert ((Characteristics & 0x00F00000) == 0 && "alignment must not be set upon section creation"); - assert ((Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) == - (Assoc != 0) && - "associative COMDAT section must have an associated section"); } ~MCSectionCOFF(); @@ -69,23 +60,22 @@ class MCSymbol; bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; StringRef getSectionName() const { return SectionName; } - virtual std::string getLabelBeginName() const { + std::string getLabelBeginName() const override { return SectionName.str() + "_begin"; } - virtual std::string getLabelEndName() const { + std::string getLabelEndName() const override { return SectionName.str() + "_end"; } unsigned getCharacteristics() const { return Characteristics; } + MCSymbol *getCOMDATSymbol() const { return COMDATSymbol; } int getSelection() const { return Selection; } - const MCSectionCOFF *getAssocSection() const { return Assoc; } - void setSelection(int Selection, const MCSectionCOFF *Assoc = 0) const; + void setSelection(int Selection) const; - virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS, - const MCExpr *Subsection) const; - virtual bool UseCodeAlign() const; - virtual bool isVirtualSection() const; + void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, + const MCExpr *Subsection) const override; + bool UseCodeAlign() const override; + bool isVirtualSection() const override; static bool classof(const MCSection *S) { return S->getVariant() == SV_COFF; diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 59799158ad3c..5ec23f1afad2 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -14,8 +14,9 @@ #ifndef LLVM_MC_MCSECTIONELF_H #define LLVM_MC_MCSECTIONELF_H -#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" @@ -52,6 +53,9 @@ private: : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags), EntrySize(entrySize), Group(group) {} ~MCSectionELF(); + + void setSectionName(StringRef Name) { SectionName = Name; } + public: /// ShouldOmitSectionDirective - Decides whether a '.section' directive @@ -59,9 +63,14 @@ public: bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; StringRef getSectionName() const { return SectionName; } - virtual std::string getLabelBeginName() const { - return SectionName.str() + "_begin"; } - virtual std::string getLabelEndName() const { + std::string getLabelBeginName() const override { + if (Group) + return (SectionName.str() + '_' + Group->getName() + "_begin").str(); + return SectionName.str() + "_begin"; + } + std::string getLabelEndName() const override { + if (Group) + return (SectionName.str() + '_' + Group->getName() + "_end").str(); return SectionName.str() + "_end"; } unsigned getType() const { return Type; } @@ -69,15 +78,14 @@ public: unsigned getEntrySize() const { return EntrySize; } const MCSymbol *getGroup() const { return Group; } - void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS, - const MCExpr *Subsection) const; - virtual bool UseCodeAlign() const; - virtual bool isVirtualSection() const; + void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, + const MCExpr *Subsection) const override; + bool UseCodeAlign() const override; + bool isVirtualSection() const override; /// isBaseAddressKnownZero - We know that non-allocatable sections (like /// debug info) have a base of zero. - virtual bool isBaseAddressKnownZero() const { + bool isBaseAddressKnownZero() const override { return (getFlags() & ELF::SHF_ALLOC) == 0; } diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index d7e88ea56124..a5a2089a2974 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCSection.h" +#include "llvm/Support/MachO.h" namespace llvm { @@ -39,99 +40,6 @@ class MCSectionMachO : public MCSection { friend class MCContext; public: - /// These are the section type and attributes fields. A MachO section can - /// have only one Type, but can have any of the attributes specified. - enum LLVM_ENUM_INT_TYPE(uint32_t) { - // TypeAndAttributes bitmasks. - SECTION_TYPE = 0x000000FFU, - SECTION_ATTRIBUTES = 0xFFFFFF00U, - - // Valid section types. - - /// S_REGULAR - Regular section. - S_REGULAR = 0x00U, - /// S_ZEROFILL - Zero fill on demand section. - S_ZEROFILL = 0x01U, - /// S_CSTRING_LITERALS - Section with literal C strings. - S_CSTRING_LITERALS = 0x02U, - /// S_4BYTE_LITERALS - Section with 4 byte literals. - S_4BYTE_LITERALS = 0x03U, - /// S_8BYTE_LITERALS - Section with 8 byte literals. - S_8BYTE_LITERALS = 0x04U, - /// S_LITERAL_POINTERS - Section with pointers to literals. - S_LITERAL_POINTERS = 0x05U, - /// S_NON_LAZY_SYMBOL_POINTERS - Section with non-lazy symbol pointers. - S_NON_LAZY_SYMBOL_POINTERS = 0x06U, - /// S_LAZY_SYMBOL_POINTERS - Section with lazy symbol pointers. - S_LAZY_SYMBOL_POINTERS = 0x07U, - /// S_SYMBOL_STUBS - Section with symbol stubs, byte size of stub in - /// the Reserved2 field. - S_SYMBOL_STUBS = 0x08U, - /// S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for - /// initialization. - S_MOD_INIT_FUNC_POINTERS = 0x09U, - /// S_MOD_TERM_FUNC_POINTERS - Section with only function pointers for - /// termination. - S_MOD_TERM_FUNC_POINTERS = 0x0AU, - /// S_COALESCED - Section contains symbols that are to be coalesced. - S_COALESCED = 0x0BU, - /// S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4 - /// gigabytes). - S_GB_ZEROFILL = 0x0CU, - /// S_INTERPOSING - Section with only pairs of function pointers for - /// interposing. - S_INTERPOSING = 0x0DU, - /// S_16BYTE_LITERALS - Section with only 16 byte literals. - S_16BYTE_LITERALS = 0x0EU, - /// S_DTRACE_DOF - Section contains DTrace Object Format. - S_DTRACE_DOF = 0x0FU, - /// S_LAZY_DYLIB_SYMBOL_POINTERS - Section with lazy symbol pointers to - /// lazy loaded dylibs. - S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10U, - /// S_THREAD_LOCAL_REGULAR - Section with .... - S_THREAD_LOCAL_REGULAR = 0x11U, - /// S_THREAD_LOCAL_ZEROFILL - Thread local zerofill section. - S_THREAD_LOCAL_ZEROFILL = 0x12U, - /// S_THREAD_LOCAL_VARIABLES - Section with thread local variable structure - /// data. - S_THREAD_LOCAL_VARIABLES = 0x13U, - /// S_THREAD_LOCAL_VARIABLE_POINTERS - Section with .... - S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14U, - /// S_THREAD_LOCAL_INIT_FUNCTION_POINTERS - Section with thread local - /// variable initialization pointers to functions. - S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15U, - - LAST_KNOWN_SECTION_TYPE = S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, - - - // Valid section attributes. - - /// S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine - /// instructions. - S_ATTR_PURE_INSTRUCTIONS = 1U << 31, - /// S_ATTR_NO_TOC - Section contains coalesced symbols that are not to be - /// in a ranlib table of contents. - S_ATTR_NO_TOC = 1U << 30, - /// S_ATTR_STRIP_STATIC_SYMS - Ok to strip static symbols in this section - /// in files with the MY_DYLDLINK flag. - S_ATTR_STRIP_STATIC_SYMS = 1U << 29, - /// S_ATTR_NO_DEAD_STRIP - No dead stripping. - S_ATTR_NO_DEAD_STRIP = 1U << 28, - /// S_ATTR_LIVE_SUPPORT - Blocks are live if they reference live blocks. - S_ATTR_LIVE_SUPPORT = 1U << 27, - /// S_ATTR_SELF_MODIFYING_CODE - Used with i386 code stubs written on by - /// dyld. - S_ATTR_SELF_MODIFYING_CODE = 1U << 26, - /// S_ATTR_DEBUG - A debug section. - S_ATTR_DEBUG = 1U << 25, - /// S_ATTR_SOME_INSTRUCTIONS - Section contains some machine instructions. - S_ATTR_SOME_INSTRUCTIONS = 1U << 10, - /// S_ATTR_EXT_RELOC - Section has external relocation entries. - S_ATTR_EXT_RELOC = 1U << 9, - /// S_ATTR_LOC_RELOC - Section has local relocation entries. - S_ATTR_LOC_RELOC = 1U << 8 - }; - StringRef getSegmentName() const { // SegmentName is not necessarily null terminated! if (SegmentName[15]) @@ -145,18 +53,21 @@ public: return StringRef(SectionName); } - virtual std::string getLabelBeginName() const { + std::string getLabelBeginName() const override { return StringRef(getSegmentName().str() + getSectionName().str() + "_begin"); } - virtual std::string getLabelEndName() const { + std::string getLabelEndName() const override { return StringRef(getSegmentName().str() + getSectionName().str() + "_end"); } unsigned getTypeAndAttributes() const { return TypeAndAttributes; } unsigned getStubSize() const { return Reserved2; } - unsigned getType() const { return TypeAndAttributes & SECTION_TYPE; } + MachO::SectionType getType() const { + return static_cast<MachO::SectionType>(TypeAndAttributes & + MachO::SECTION_TYPE); + } bool hasAttribute(unsigned Value) const { return (TypeAndAttributes & Value) != 0; } @@ -174,11 +85,10 @@ public: bool &TAAParsed, // Out. unsigned &StubSize); // Out. - virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS, - const MCExpr *Subsection) const; - virtual bool UseCodeAlign() const; - virtual bool isVirtualSection() const; + void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, + const MCExpr *Subsection) const override; + bool UseCodeAlign() const override; + bool isVirtualSection() const override; static bool classof(const MCSection *S) { return S->getVariant() == SV_MachO; diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 0b1fe6ec0129..63a43d08c3f2 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -19,6 +19,7 @@ #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCWin64EH.h" #include "llvm/Support/DataTypes.h" #include <string> @@ -33,10 +34,13 @@ class MCInstPrinter; class MCSection; class MCStreamer; class MCSymbol; +class MCSymbolRefExpr; +class MCSubtargetInfo; class StringRef; class Twine; class raw_ostream; class formatted_raw_ostream; +class AssemblerConstantPools; typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; @@ -66,34 +70,93 @@ typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; /// be treated differently. Callers should always talk to a FooTargetStreamer. class MCTargetStreamer { protected: - MCStreamer *Streamer; + MCStreamer &Streamer; public: + MCTargetStreamer(MCStreamer &S); virtual ~MCTargetStreamer(); - void setStreamer(MCStreamer *S) { Streamer = S; } + + const MCStreamer &getStreamer() { return Streamer; } + + // Allow a target to add behavior to the EmitLabel of MCStreamer. + virtual void emitLabel(MCSymbol *Symbol); + // Allow a target to add behavior to the emitAssignment of MCStreamer. + virtual void emitAssignment(MCSymbol *Symbol, const MCExpr *Value); + + virtual void finish(); +}; + +class AArch64TargetStreamer : public MCTargetStreamer { +public: + AArch64TargetStreamer(MCStreamer &S); + ~AArch64TargetStreamer(); + + + void finish() override; + + /// Callback used to implement the ldr= pseudo. + /// Add a new entry to the constant pool for the current section and return an + /// MCExpr that can be used to refer to the constant pool location. + const MCExpr *addConstantPoolEntry(const MCExpr *, unsigned Size); + + /// Callback used to implemnt the .ltorg directive. + /// Emit contents of constant pool for the current section. + void emitCurrentConstantPool(); + +private: + std::unique_ptr<AssemblerConstantPools> ConstantPools; }; // FIXME: declared here because it is used from // lib/CodeGen/AsmPrinter/ARMException.cpp. class ARMTargetStreamer : public MCTargetStreamer { - virtual void anchor(); public: - virtual void emitFnStart() = 0; - virtual void emitFnEnd() = 0; - virtual void emitCantUnwind() = 0; - virtual void emitPersonality(const MCSymbol *Personality) = 0; - virtual void emitHandlerData() = 0; + ARMTargetStreamer(MCStreamer &S); + ~ARMTargetStreamer(); + + virtual void emitFnStart(); + virtual void emitFnEnd(); + virtual void emitCantUnwind(); + virtual void emitPersonality(const MCSymbol *Personality); + virtual void emitPersonalityIndex(unsigned Index); + virtual void emitHandlerData(); virtual void emitSetFP(unsigned FpReg, unsigned SpReg, - int64_t Offset = 0) = 0; - virtual void emitPad(int64_t Offset) = 0; + int64_t Offset = 0); + virtual void emitMovSP(unsigned Reg, int64_t Offset = 0); + virtual void emitPad(int64_t Offset); virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList, - bool isVector) = 0; - - virtual void switchVendor(StringRef Vendor) = 0; - virtual void emitAttribute(unsigned Attribute, unsigned Value) = 0; - virtual void emitTextAttribute(unsigned Attribute, StringRef String) = 0; - virtual void emitFPU(unsigned FPU) = 0; - virtual void finishAttributeSection() = 0; + bool isVector); + virtual void emitUnwindRaw(int64_t StackOffset, + const SmallVectorImpl<uint8_t> &Opcodes); + + virtual void switchVendor(StringRef Vendor); + virtual void emitAttribute(unsigned Attribute, unsigned Value); + virtual void emitTextAttribute(unsigned Attribute, StringRef String); + virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, + StringRef StringValue = ""); + virtual void emitFPU(unsigned FPU); + virtual void emitArch(unsigned Arch); + virtual void emitObjectArch(unsigned Arch); + virtual void finishAttributeSection(); + virtual void emitInst(uint32_t Inst, char Suffix = '\0'); + + virtual void AnnotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE); + + virtual void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value); + + void finish() override; + + /// Callback used to implement the ldr= pseudo. + /// Add a new entry to the constant pool for the current section and return an + /// MCExpr that can be used to refer to the constant pool location. + const MCExpr *addConstantPoolEntry(const MCExpr *); + + /// Callback used to implemnt the .ltorg directive. + /// Emit contents of constant pool for the current section. + void emitCurrentConstantPool(); + +private: + std::unique_ptr<AssemblerConstantPools> ConstantPools; }; /// MCStreamer - Streaming machine code generation interface. This interface @@ -107,25 +170,20 @@ public: /// class MCStreamer { MCContext &Context; - OwningPtr<MCTargetStreamer> TargetStreamer; + std::unique_ptr<MCTargetStreamer> TargetStreamer; MCStreamer(const MCStreamer &) LLVM_DELETED_FUNCTION; MCStreamer &operator=(const MCStreamer &) LLVM_DELETED_FUNCTION; - bool EmitEHFrame; - bool EmitDebugFrame; + std::vector<MCDwarfFrameInfo> DwarfFrameInfos; + MCDwarfFrameInfo *getCurrentDwarfFrameInfo(); + void EnsureValidDwarfFrame(); - std::vector<MCDwarfFrameInfo> FrameInfos; - MCDwarfFrameInfo *getCurrentFrameInfo(); MCSymbol *EmitCFICommon(); - void EnsureValidFrame(); - - std::vector<MCWin64EHUnwindInfo *> W64UnwindInfos; - MCWin64EHUnwindInfo *CurrentW64UnwindInfo; - void setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame); - void EnsureValidW64UnwindInfo(); - MCSymbol *LastSymbol; + std::vector<MCWinFrameInfo *> WinFrameInfos; + MCWinFrameInfo *CurrentWinFrameInfo; + void EnsureValidWinFrameInfo(); // SymbolOrdering - Tracks an index to represent the order // a symbol was emitted in. Zero means we did not emit that symbol. @@ -135,53 +193,53 @@ class MCStreamer { /// values saved by PushSection. SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; - bool AutoInitSections; - protected: - MCStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer); + MCStreamer(MCContext &Ctx); const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, const MCSymbol *B); const MCExpr *ForceExpAbs(const MCExpr *Expr); - void RecordProcStart(MCDwarfFrameInfo &Frame); virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); - void RecordProcEnd(MCDwarfFrameInfo &Frame); virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); - void EmitFrames(MCAsmBackend *MAB, bool usingCFI); - MCWin64EHUnwindInfo *getCurrentW64UnwindInfo() { - return CurrentW64UnwindInfo; + MCWinFrameInfo *getCurrentWinFrameInfo() { + return CurrentWinFrameInfo; } - void EmitW64Tables(); + + void EmitWindowsUnwindTables(); virtual void EmitRawTextImpl(StringRef String); public: virtual ~MCStreamer(); + void visitUsedExpr(const MCExpr &Expr); + virtual void visitUsedSymbol(const MCSymbol &Sym); + + void setTargetStreamer(MCTargetStreamer *TS) { + TargetStreamer.reset(TS); + } + /// State management /// virtual void reset(); MCContext &getContext() const { return Context; } - MCTargetStreamer &getTargetStreamer() { - assert(TargetStreamer); - return *TargetStreamer; + MCTargetStreamer *getTargetStreamer() { + return TargetStreamer.get(); } - unsigned getNumFrameInfos() { return FrameInfos.size(); } - - const MCDwarfFrameInfo &getFrameInfo(unsigned i) { return FrameInfos[i]; } - - ArrayRef<MCDwarfFrameInfo> getFrameInfos() const { return FrameInfos; } - - unsigned getNumW64UnwindInfos() { return W64UnwindInfos.size(); } + unsigned getNumFrameInfos() { return DwarfFrameInfos.size(); } + ArrayRef<MCDwarfFrameInfo> getDwarfFrameInfos() const { + return DwarfFrameInfos; + } - MCWin64EHUnwindInfo &getW64UnwindInfo(unsigned i) { - return *W64UnwindInfos[i]; + unsigned getNumWinFrameInfos() { return WinFrameInfos.size(); } + ArrayRef<MCWinFrameInfo *> getWinFrameInfos() const { + return WinFrameInfos; } void generateCompactUnwindEncodings(MCAsmBackend *MAB); @@ -197,6 +255,10 @@ public: /// unformatted text to the .s file with EmitRawText. virtual bool hasRawTextSupport() const { return false; } + /// Is the integrated assembler required for this streamer to function + /// correctly? + virtual bool isIntegratedAssemblerRequired() const { return false; } + /// AddComment - Add a comment that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler /// more readable. This only affects the MCAsmStreamer, and only when @@ -211,6 +273,12 @@ public: /// use this method. virtual raw_ostream &GetCommentOS(); + /// Print T and prefix it with the comment string (normally #) and optionally + /// a tab. This prints the comment immediately, not at the end of the + /// current line. It is basically a safe version of EmitRawText: since it + /// only prints comments, the object streamer ignores it instead of asserting. + virtual void emitRawComment(const Twine &T, bool TabPrefix = true); + /// AddBlankLine - Emit a blank line to a .s file to pretty it up. virtual void AddBlankLine() {} @@ -245,7 +313,7 @@ public: /// /// This is called by PopSection and SwitchSection, if the current /// section changes. - virtual void ChangeSection(const MCSection *, const MCExpr *) = 0; + virtual void ChangeSection(const MCSection *, const MCExpr *); /// pushSection - Save the current and previous section on the /// section stack. @@ -281,7 +349,8 @@ public: /// @p Section. This is required to update CurSection. /// /// This corresponds to assembler directives like .section, .text, etc. - void SwitchSection(const MCSection *Section, const MCExpr *Subsection = 0) { + void SwitchSection(const MCSection *Section, + const MCExpr *Subsection = nullptr) { assert(Section && "Cannot switch to a null section!"); MCSectionSubPair curSection = SectionStack.back().first; SectionStack.back().second = curSection; @@ -295,7 +364,7 @@ public: /// emitted to @p Section. This is required to update CurSection. This /// version does not call ChangeSection. void SwitchSectionNoChange(const MCSection *Section, - const MCExpr *Subsection = 0) { + const MCExpr *Subsection = nullptr) { assert(Section && "Cannot switch to a null section!"); MCSectionSubPair curSection = SectionStack.back().first; SectionStack.back().second = curSection; @@ -303,22 +372,8 @@ public: SectionStack.back().first = MCSectionSubPair(Section, Subsection); } - /// Initialize the streamer. - void InitStreamer() { - if (AutoInitSections) - InitSections(); - } - - /// Tell this MCStreamer to call InitSections upon initialization. - void setAutoInitSections(bool AutoInitSections) { - this->AutoInitSections = AutoInitSections; - } - - /// InitSections - Create the default sections and set the initial one. - virtual void InitSections() = 0; - - /// InitToTextSection - Create a text section and switch the streamer to it. - virtual void InitToTextSection() = 0; + /// Create the default sections and set the initial one. + virtual void InitSections(); /// AssignSection - Sets the symbol's section. /// @@ -334,14 +389,14 @@ public: /// @param Symbol - The symbol to emit. A given symbol should only be /// emitted as a label once, and symbols emitted as a label should never be /// used in an assignment. + // FIXME: These emission are non-const because we mutate the symbol to + // add the section we're emitting it to later. virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitDebugLabel(MCSymbol *Symbol); - virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); /// EmitAssemblerFlag - Note in the output the specified @p Flag. - virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0; + virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); /// EmitLinkerOptions - Emit the given list @p Options of strings as linker /// options into the output. @@ -350,12 +405,13 @@ public: /// EmitDataRegion - Note in the output the specified region @p Kind. virtual void EmitDataRegion(MCDataRegionType Kind) {} + /// EmitVersionMin - Specify the MachO minimum deployment target version. + virtual void EmitVersionMin(MCVersionMinType, unsigned Major, unsigned Minor, + unsigned Update) {} + /// EmitThumbFunc - Note in the output that the specified @p Func is /// a Thumb mode function (ARM target only). - virtual void EmitThumbFunc(MCSymbol *Func) = 0; - - /// getOrCreateSymbolData - Get symbol data for given symbol. - virtual MCSymbolData &getOrCreateSymbolData(MCSymbol *Symbol); + virtual void EmitThumbFunc(MCSymbol *Func); /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. /// @@ -368,7 +424,7 @@ public: /// /// @param Symbol - The symbol being assigned to. /// @param Value - The value for the symbol. - virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) = 0; + virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. /// @@ -377,7 +433,7 @@ public: /// /// @param Alias - The alias that is being created. /// @param Symbol - The symbol being aliased. - virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) = 0; + virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. virtual bool EmitSymbolAttribute(MCSymbol *Symbol, @@ -387,29 +443,34 @@ public: /// /// @param Symbol - The symbol to have its n_desc field set. /// @param DescValue - The value to set into the n_desc field. - virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; + virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); /// BeginCOFFSymbolDef - Start emitting COFF symbol definition /// /// @param Symbol - The symbol to have its External & Type fields set. - virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) = 0; + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. /// /// @param StorageClass - The storage class the symbol should have. - virtual void EmitCOFFSymbolStorageClass(int StorageClass) = 0; + virtual void EmitCOFFSymbolStorageClass(int StorageClass); /// EmitCOFFSymbolType - Emit the type of the symbol. /// /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) - virtual void EmitCOFFSymbolType(int Type) = 0; + virtual void EmitCOFFSymbolType(int Type); /// EndCOFFSymbolDef - Marks the end of the symbol definition. - virtual void EndCOFFSymbolDef() = 0; + virtual void EndCOFFSymbolDef(); + + /// EmitCOFFSectionIndex - Emits a COFF section index. + /// + /// @param Symbol - Symbol the section number relocation should point to. + virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol); /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. /// - /// @param Symbol - Symbol the section relative realocation should point to. + /// @param Symbol - Symbol the section relative relocation should point to. virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); /// EmitELFSize - Emit an ELF .size directive. @@ -417,7 +478,11 @@ public: /// This corresponds to an assembler statement such as: /// .size symbol, expression /// - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); + + /// \brief Emit a Linker Optimization Hint (LOH) directive. + /// \param Args - Arguments of the LOH. + virtual void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {} /// EmitCommonSymbol - Emit a common symbol. /// @@ -434,7 +499,7 @@ public: /// @param Size - The size of the common symbol. /// @param ByteAlignment - The alignment of the common symbol in bytes. virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) = 0; + unsigned ByteAlignment); /// EmitZerofill - Emit the zerofill section and an optional symbol. /// @@ -443,8 +508,9 @@ public: /// @param Size - The size of the zerofill symbol. /// @param ByteAlignment - The alignment of the zerofill symbol if /// non-zero. This must be a power of 2 on some targets. - virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, - uint64_t Size = 0, unsigned ByteAlignment = 0) = 0; + virtual void EmitZerofill(const MCSection *Section, + MCSymbol *Symbol = nullptr, uint64_t Size = 0, + unsigned ByteAlignment = 0) = 0; /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. /// @@ -454,7 +520,7 @@ public: /// @param ByteAlignment - The alignment of the thread local common symbol /// if non-zero. This must be a power of 2 on some targets. virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) = 0; + uint64_t Size, unsigned ByteAlignment = 0); /// @} /// @name Generating Data @@ -464,7 +530,7 @@ public: /// /// This is used to implement assembler directives such as .byte, .ascii, /// etc. - virtual void EmitBytes(StringRef Data) = 0; + virtual void EmitBytes(StringRef Data); /// EmitValue - Emit the expression @p Value into the output as a native /// integer of the given @p Size bytes. @@ -475,9 +541,12 @@ public: /// @param Value - The value to emit. /// @param Size - The size of the integer (in bytes) to emit. This must /// match a native machine width. - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) = 0; + /// @param Loc - The location of the expression for error reporting. + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, + const SMLoc &Loc = SMLoc()); - void EmitValue(const MCExpr *Value, unsigned Size); + void EmitValue(const MCExpr *Value, unsigned Size, + const SMLoc &Loc = SMLoc()); /// EmitIntValue - Special case of EmitValue that avoids the client having /// to pass in a MCExpr for constant integers. @@ -489,9 +558,9 @@ public: /// .long foo void EmitAbsValue(const MCExpr *Value, unsigned Size); - virtual void EmitULEB128Value(const MCExpr *Value) = 0; + virtual void EmitULEB128Value(const MCExpr *Value); - virtual void EmitSLEB128Value(const MCExpr *Value) = 0; + virtual void EmitSLEB128Value(const MCExpr *Value); /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. @@ -503,7 +572,8 @@ public: /// EmitSymbolValue - Special case of EmitValue that avoids the client /// having to pass in a MCExpr for MCSymbols. - void EmitSymbolValue(const MCSymbol *Sym, unsigned Size); + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, + bool IsSectionRelative = false); /// EmitGPRel64Value - Emit the expression @p Value into the output as a /// gprel64 (64-bit GP relative) value. @@ -546,7 +616,7 @@ public: /// emitted. virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, - unsigned MaxBytesToEmit = 0) = 0; + unsigned MaxBytesToEmit = 0); /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment /// is reached. @@ -560,7 +630,7 @@ public: /// the alignment cannot be reached in this many bytes, no bytes are /// emitted. virtual void EmitCodeAlignment(unsigned ByteAlignment, - unsigned MaxBytesToEmit = 0) = 0; + unsigned MaxBytesToEmit = 0); /// EmitValueToOffset - Emit some number of copies of @p Value until the /// byte offset @p Offset is reached. @@ -572,13 +642,13 @@ public: /// @param Value - The value to use when filling bytes. /// @return false on success, true if the offset was invalid. virtual bool EmitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0) = 0; + unsigned char Value = 0); /// @} /// EmitFileDirective - Switch to a new logical file. This is used to /// implement the '.file "foo.c"' assembler directive. - virtual void EmitFileDirective(StringRef Filename) = 0; + virtual void EmitFileDirective(StringRef Filename); /// Emit the "identifiers" directive. This implements the /// '.ident "version foo"' assembler directive. @@ -587,8 +657,9 @@ public: /// EmitDwarfFileDirective - Associate a filename with a specified logical /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler /// directive. - virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, unsigned CUID = 0); + virtual unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, + StringRef Filename, + unsigned CUID = 0); /// EmitDwarfLocDirective - This implements the DWARF2 // '.loc fileno lineno ...' assembler directive. @@ -597,20 +668,14 @@ public: unsigned Isa, unsigned Discriminator, StringRef FileName); - virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, - const MCSymbol *LastLabel, - const MCSymbol *Label, - unsigned PointerSize) = 0; - - virtual void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, - const MCSymbol *Label) {} + virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID); void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, int PointerSize); virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); virtual void EmitCFISections(bool EH, bool Debug); - void EmitCFIStartProc(); + void EmitCFIStartProc(bool IsSimple); void EmitCFIEndProc(); virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); virtual void EmitCFIDefCfaOffset(int64_t Offset); @@ -630,38 +695,38 @@ public: virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); virtual void EmitCFIWindowSave(); - virtual void EmitWin64EHStartProc(const MCSymbol *Symbol); - virtual void EmitWin64EHEndProc(); - virtual void EmitWin64EHStartChained(); - virtual void EmitWin64EHEndChained(); - virtual void EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, - bool Except); - virtual void EmitWin64EHHandlerData(); - virtual void EmitWin64EHPushReg(unsigned Register); - virtual void EmitWin64EHSetFrame(unsigned Register, unsigned Offset); - virtual void EmitWin64EHAllocStack(unsigned Size); - virtual void EmitWin64EHSaveReg(unsigned Register, unsigned Offset); - virtual void EmitWin64EHSaveXMM(unsigned Register, unsigned Offset); - virtual void EmitWin64EHPushFrame(bool Code); - virtual void EmitWin64EHEndProlog(); + virtual void EmitWinCFIStartProc(const MCSymbol *Symbol); + virtual void EmitWinCFIEndProc(); + virtual void EmitWinCFIStartChained(); + virtual void EmitWinCFIEndChained(); + virtual void EmitWinCFIPushReg(unsigned Register); + virtual void EmitWinCFISetFrame(unsigned Register, unsigned Offset); + virtual void EmitWinCFIAllocStack(unsigned Size); + virtual void EmitWinCFISaveReg(unsigned Register, unsigned Offset); + virtual void EmitWinCFISaveXMM(unsigned Register, unsigned Offset); + virtual void EmitWinCFIPushFrame(bool Code); + virtual void EmitWinCFIEndProlog(); + + virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except); + virtual void EmitWinEHHandlerData(); /// EmitInstruction - Emit the given @p Instruction into the current /// section. - virtual void EmitInstruction(const MCInst &Inst) = 0; + virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI); /// \brief Set the bundle alignment mode from now on in the section. /// The argument is the power of 2 to which the alignment is set. The /// value 0 means turn the bundle alignment off. - virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0; + virtual void EmitBundleAlignMode(unsigned AlignPow2); /// \brief The following instructions are a bundle-locked group. /// /// \param AlignToEnd - If true, the bundle-locked group will be aligned to /// the end of a bundle. - virtual void EmitBundleLock(bool AlignToEnd) = 0; + virtual void EmitBundleLock(bool AlignToEnd); /// \brief Ends a bundle-locked group. - virtual void EmitBundleUnlock() = 0; + virtual void EmitBundleUnlock(); /// EmitRawText - If this file is backed by a assembly streamer, this dumps /// the specified string in the output .s file. This capability is @@ -672,9 +737,11 @@ public: virtual void Flush() {} /// FinishImpl - Streamer specific finalization. - virtual void FinishImpl() = 0; + virtual void FinishImpl(); /// Finish - Finish emission of machine code. void Finish(); + + virtual bool mayHaveInstructions() const { return true; } }; /// createNullStreamer - Create a dummy machine code streamer, which does @@ -698,12 +765,10 @@ MCStreamer *createNullStreamer(MCContext &Ctx); /// /// \param ShowInst - Whether to show the MCInst representation inline with /// the assembly. -MCStreamer *createAsmStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer, - formatted_raw_ostream &OS, bool isVerboseAsm, - bool useLoc, bool useCFI, bool useDwarfDirectory, - MCInstPrinter *InstPrint = 0, - MCCodeEmitter *CE = 0, MCAsmBackend *TAB = 0, - bool ShowInst = false); +MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, bool useDwarfDirectory, + MCInstPrinter *InstPrint, MCCodeEmitter *CE, + MCAsmBackend *TAB, bool ShowInst); /// createMachOStreamer - Create a machine code streamer which will generate /// Mach-O format object files. @@ -711,30 +776,15 @@ MCStreamer *createAsmStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer, /// Takes ownership of \p TAB and \p CE. MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll = false); - -/// createWinCOFFStreamer - Create a machine code streamer which will -/// generate Microsoft COFF format object files. -/// -/// Takes ownership of \p TAB and \p CE. -MCStreamer *createWinCOFFStreamer(MCContext &Ctx, MCAsmBackend &TAB, - MCCodeEmitter &CE, raw_ostream &OS, - bool RelaxAll = false); + bool RelaxAll = false, + bool LabelSections = false); /// createELFStreamer - Create a machine code streamer which will generate /// ELF format object files. -MCStreamer *createELFStreamer(MCContext &Ctx, MCTargetStreamer *TargetStreamer, - MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *CE, bool RelaxAll, +MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll, bool NoExecStack); -/// createPureStreamer - Create a machine code streamer which will generate -/// "pure" MC object files, for use with MC-JIT and testing tools. -/// -/// Takes ownership of \p TAB and \p CE. -MCStreamer *createPureStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE); - } // end namespace llvm #endif diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 01e8236482f7..088c5e7470d6 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -28,8 +28,8 @@ class StringRef; /// class MCSubtargetInfo { std::string TargetTriple; // Target triple - const SubtargetFeatureKV *ProcFeatures; // Processor feature list - const SubtargetFeatureKV *ProcDesc; // Processor descriptions + ArrayRef<SubtargetFeatureKV> ProcFeatures; // Processor feature list + ArrayRef<SubtargetFeatureKV> ProcDesc; // Processor descriptions // Scheduler machine model const SubtargetInfoKV *ProcSchedModels; @@ -41,21 +41,18 @@ class MCSubtargetInfo { const InstrStage *Stages; // Instruction itinerary stages const unsigned *OperandCycles; // Itinerary operand cycles const unsigned *ForwardingPaths; // Forwarding paths - unsigned NumFeatures; // Number of processor features - unsigned NumProcs; // Number of processors uint64_t FeatureBits; // Feature bits for current CPU + FS public: void InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS, - const SubtargetFeatureKV *PF, - const SubtargetFeatureKV *PD, + ArrayRef<SubtargetFeatureKV> PF, + ArrayRef<SubtargetFeatureKV> PD, const SubtargetInfoKV *ProcSched, const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA, const InstrStage *IS, - const unsigned *OC, const unsigned *FP, - unsigned NF, unsigned NP); + const unsigned *OC, const unsigned *FP); /// getTargetTriple - Return the target triple string. StringRef getTargetTriple() const { diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index fe927555c49b..0b3c3ceb210f 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -60,7 +60,7 @@ namespace llvm { friend class MCExpr; friend class MCContext; MCSymbol(StringRef name, bool isTemporary) - : Name(name), Section(0), Value(0), + : Name(name), Section(nullptr), Value(nullptr), IsTemporary(isTemporary), IsUsed(false) {} MCSymbol(const MCSymbol&) LLVM_DELETED_FUNCTION; @@ -87,7 +87,7 @@ namespace llvm { /// /// Defined symbols are either absolute or in some section. bool isDefined() const { - return Section != 0; + return Section != nullptr; } /// isInSection - Check if this symbol is defined in some section (i.e., it @@ -118,7 +118,7 @@ namespace llvm { /// setUndefined - Mark the symbol as undefined. void setUndefined() { - Section = 0; + Section = nullptr; } /// setAbsolute - Mark the symbol as absolute. @@ -130,7 +130,7 @@ namespace llvm { /// isVariable - Check if this is a variable symbol. bool isVariable() const { - return Value != 0; + return Value != nullptr; } /// getVariableValue() - Get the value for variable symbols. @@ -141,7 +141,7 @@ namespace llvm { } // AliasedSymbol() - If this is an alias (a = b), return the symbol - // we ultimately point to. For a non alias, this just returns the symbol + // we ultimately point to. For a non-alias, this just returns the symbol // itself. const MCSymbol &AliasedSymbol() const; diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCSymbolizer.h index e42a2146dc53..cbbb591f1b80 100644 --- a/include/llvm/MC/MCSymbolizer.h +++ b/include/llvm/MC/MCSymbolizer.h @@ -16,10 +16,11 @@ #ifndef LLVM_MC_MCSYMBOLIZER_H #define LLVM_MC_MCSYMBOLIZER_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/MC/MCRelocationInfo.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include <cassert> +#include <memory> namespace llvm { @@ -42,11 +43,14 @@ class MCSymbolizer { protected: MCContext &Ctx; - OwningPtr<MCRelocationInfo> RelInfo; + std::unique_ptr<MCRelocationInfo> RelInfo; public: /// \brief Construct an MCSymbolizer, taking ownership of \p RelInfo. - MCSymbolizer(MCContext &Ctx, OwningPtr<MCRelocationInfo> &RelInfo); + MCSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> RelInfo) + : Ctx(Ctx), RelInfo(std::move(RelInfo)) { + } + virtual ~MCSymbolizer(); /// \brief Try to add a symbolic operand instead of \p Value to the MCInst. diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index d132a732c416..9a5881b14b44 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -10,18 +10,23 @@ #ifndef LLVM_MC_TARGETPARSER_H #define LLVM_MC_TARGETPARSER_H -#include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCParser/MCAsmParserExtension.h" +#include "llvm/MC/MCTargetOptions.h" + +#include <memory> namespace llvm { -class MCStreamer; -class StringRef; -class SMLoc; class AsmToken; -class MCParsedAsmOperand; class MCInst; +class MCParsedAsmOperand; +class MCStreamer; +class SMLoc; +class StringRef; template <typename T> class SmallVectorImpl; +typedef SmallVectorImpl<std::unique_ptr<MCParsedAsmOperand>> OperandVector; + enum AsmRewriteKind { AOK_Delete = 0, // Rewrite should be ignored. AOK_Align, // Rewrite align as .align. @@ -63,7 +68,7 @@ struct ParseInstructionInfo { SmallVectorImpl<AsmRewrite> *AsmRewrites; - ParseInstructionInfo() : AsmRewrites(0) {} + ParseInstructionInfo() : AsmRewrites(nullptr) {} ParseInstructionInfo(SmallVectorImpl<AsmRewrite> *rewrites) : AsmRewrites(rewrites) {} @@ -97,6 +102,9 @@ protected: // Can only create subclasses. /// ms-style inline assembly. MCAsmParserSemaCallback *SemaCallback; + /// Set of options which affects instrumentation of inline assembly. + MCTargetOptions MCOptions; + public: virtual ~MCTargetAsmParser(); @@ -127,8 +135,7 @@ public: /// ownership of them to the caller. /// \return True on failure. virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, - SMLoc NameLoc, - SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0; + SMLoc NameLoc, OperandVector &Operands) = 0; /// ParseDirective - Parse a target specific assembler directive /// @@ -152,17 +159,19 @@ public: /// /// On failure, the target parser is responsible for emitting a diagnostic /// explaining the match failure. - virtual bool - MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, - SmallVectorImpl<MCParsedAsmOperand*> &Operands, - MCStreamer &Out, unsigned &ErrorInfo, - bool MatchingInlineAsm) = 0; + virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + OperandVector &Operands, MCStreamer &Out, + unsigned &ErrorInfo, + bool MatchingInlineAsm) = 0; + + /// Allows targets to let registers opt out of clobber lists. + virtual bool OmitRegisterFromClobberLists(unsigned RegNo) { return false; } /// Allow a target to add special case operand matching for things that /// tblgen doesn't/can't handle effectively. For example, literal /// immediates on ARM. TableGen expects a token operand, but the parser /// will recognize them as immediates. - virtual unsigned validateTargetOperandClass(MCParsedAsmOperand *Op, + virtual unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind) { return Match_InvalidOperand; } @@ -174,12 +183,12 @@ public: } virtual void convertToMapAndConstraints(unsigned Kind, - const SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0; + const OperandVector &Operands) = 0; virtual const MCExpr *applyModifierToExpr(const MCExpr *E, MCSymbolRefExpr::VariantKind, MCContext &Ctx) { - return 0; + return nullptr; } virtual void onLabelParsed(MCSymbol *Symbol) { }; diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h new file mode 100644 index 000000000000..eb4348ed3ec2 --- /dev/null +++ b/include/llvm/MC/MCTargetOptions.h @@ -0,0 +1,56 @@ +//===- MCTargetOptions.h - MC Target Options -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCTARGETOPTIONS_H +#define LLVM_MC_MCTARGETOPTIONS_H + +namespace llvm { + +class MCTargetOptions { +public: + enum AsmInstrumentation { + AsmInstrumentationNone, + AsmInstrumentationAddress + }; + + /// Enables AddressSanitizer instrumentation at machine level. + bool SanitizeAddress : 1; + + bool MCRelaxAll : 1; + bool MCNoExecStack : 1; + bool MCSaveTempLabels : 1; + bool MCUseDwarfDirectory : 1; + bool ShowMCEncoding : 1; + bool ShowMCInst : 1; + bool AsmVerbose : 1; + int DwarfVersion; + MCTargetOptions(); +}; + +inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { +#define ARE_EQUAL(X) LHS.X == RHS.X + return (ARE_EQUAL(SanitizeAddress) && + ARE_EQUAL(MCRelaxAll) && + ARE_EQUAL(MCNoExecStack) && + ARE_EQUAL(MCSaveTempLabels) && + ARE_EQUAL(MCUseDwarfDirectory) && + ARE_EQUAL(ShowMCEncoding) && + ARE_EQUAL(ShowMCInst) && + ARE_EQUAL(AsmVerbose) && + ARE_EQUAL(DwarfVersion)); +#undef ARE_EQUAL +} + +inline bool operator!=(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { + return !(LHS == RHS); +} + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCTargetOptionsCommandFlags.h b/include/llvm/MC/MCTargetOptionsCommandFlags.h new file mode 100644 index 000000000000..6d4eb0ef5911 --- /dev/null +++ b/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -0,0 +1,53 @@ +//===-- MCTargetOptionsCommandFlags.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains machine code-specific flags that are shared between +// different command line tools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H +#define LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H + +#include "llvm/Support/CommandLine.h" +#include "llvm/MC/MCTargetOptions.h" +using namespace llvm; + +cl::opt<MCTargetOptions::AsmInstrumentation> AsmInstrumentation( + "asm-instrumentation", cl::desc("Instrumentation of inline assembly and " + "assembly source files"), + cl::init(MCTargetOptions::AsmInstrumentationNone), + cl::values(clEnumValN(MCTargetOptions::AsmInstrumentationNone, "none", + "no instrumentation at all"), + clEnumValN(MCTargetOptions::AsmInstrumentationAddress, "address", + "instrument instructions with memory arguments"), + clEnumValEnd)); + +cl::opt<bool> RelaxAll("mc-relax-all", + cl::desc("When used with filetype=obj, " + "relax all fixups in the emitted object file")); + +cl::opt<int> DwarfVersion("dwarf-version", cl::desc("Dwarf version"), + cl::init(0)); + +cl::opt<bool> ShowMCInst("asm-show-inst", + cl::desc("Emit internal instruction representation to " + "assembly file")); + +static inline MCTargetOptions InitMCTargetOptionsFromFlags() { + MCTargetOptions Options; + Options.SanitizeAddress = + (AsmInstrumentation == MCTargetOptions::AsmInstrumentationAddress); + Options.MCRelaxAll = RelaxAll; + Options.DwarfVersion = DwarfVersion; + Options.ShowMCInst = ShowMCInst; + return Options; +} + +#endif diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index a4e730111484..dd86979690cf 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -14,19 +14,25 @@ #ifndef LLVM_MC_MCVALUE_H #define LLVM_MC_MCVALUE_H +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { class MCAsmInfo; -class MCSymbol; -class MCSymbolRefExpr; class raw_ostream; -/// MCValue - This represents an "assembler immediate". In its most general -/// form, this can hold "SymbolA - SymbolB + imm64". Not all targets supports -/// relocations of this general form, but we need to represent this anyway. +/// MCValue - This represents an "assembler immediate". In its most +/// general form, this can hold ":Kind:(SymbolA - SymbolB + imm64)". +/// Not all targets supports relocations of this general form, but we +/// need to represent this anyway. +/// +/// In general both SymbolA and SymbolB will also have a modifier +/// analogous to the top-level Kind. Current targets are not expected +/// to make use of both though. The choice comes down to whether +/// relocation modifiers apply to the closest symbol or the whole +/// expression. /// /// In the general form, SymbolB can only be defined if SymbolA is, and both /// must be in the same (non-external) section. The latter constraint is not @@ -37,11 +43,13 @@ class raw_ostream; class MCValue { const MCSymbolRefExpr *SymA, *SymB; int64_t Cst; + uint32_t RefKind; public: int64_t getConstant() const { return Cst; } const MCSymbolRefExpr *getSymA() const { return SymA; } const MCSymbolRefExpr *getSymB() const { return SymB; } + uint32_t getRefKind() const { return RefKind; } /// isAbsolute - Is this an absolute (as opposed to relocatable) value. bool isAbsolute() const { return !SymA && !SymB; } @@ -52,21 +60,26 @@ public: /// dump - Print the value to stderr. void dump() const; - static MCValue get(const MCSymbolRefExpr *SymA, const MCSymbolRefExpr *SymB=0, - int64_t Val = 0) { + MCSymbolRefExpr::VariantKind getAccessVariant() const; + + static MCValue get(const MCSymbolRefExpr *SymA, + const MCSymbolRefExpr *SymB = nullptr, + int64_t Val = 0, uint32_t RefKind = 0) { MCValue R; assert((!SymB || SymA) && "Invalid relocatable MCValue!"); R.Cst = Val; R.SymA = SymA; R.SymB = SymB; + R.RefKind = RefKind; return R; } static MCValue get(int64_t Val) { MCValue R; R.Cst = Val; - R.SymA = 0; - R.SymB = 0; + R.SymA = nullptr; + R.SymB = nullptr; + R.RefKind = 0; return R; } diff --git a/include/llvm/MC/MCWin64EH.h b/include/llvm/MC/MCWin64EH.h index eb4665a2e994..3df0d0ab8c46 100644 --- a/include/llvm/MC/MCWin64EH.h +++ b/include/llvm/MC/MCWin64EH.h @@ -15,8 +15,8 @@ #ifndef LLVM_MC_MCWIN64EH_H #define LLVM_MC_MCWIN64EH_H +#include "llvm/MC/MCWinEH.h" #include "llvm/Support/Win64EH.h" -#include <cassert> #include <vector> namespace llvm { @@ -24,48 +24,42 @@ namespace llvm { class MCStreamer; class MCSymbol; - class MCWin64EHInstruction { - public: - typedef Win64EH::UnwindOpcodes OpType; - private: - OpType Operation; - MCSymbol *Label; - unsigned Offset; - unsigned Register; - public: - MCWin64EHInstruction(OpType Op, MCSymbol *L, unsigned Reg) - : Operation(Op), Label(L), Offset(0), Register(Reg) { - assert(Op == Win64EH::UOP_PushNonVol); - } - MCWin64EHInstruction(MCSymbol *L, unsigned Size) - : Operation(Size>128 ? Win64EH::UOP_AllocLarge : Win64EH::UOP_AllocSmall), - Label(L), Offset(Size) { } - MCWin64EHInstruction(OpType Op, MCSymbol *L, unsigned Reg, unsigned Off) - : Operation(Op), Label(L), Offset(Off), Register(Reg) { - assert(Op == Win64EH::UOP_SetFPReg || - Op == Win64EH::UOP_SaveNonVol || - Op == Win64EH::UOP_SaveNonVolBig || - Op == Win64EH::UOP_SaveXMM128 || - Op == Win64EH::UOP_SaveXMM128Big); - } - MCWin64EHInstruction(OpType Op, MCSymbol *L, bool Code) - : Operation(Op), Label(L), Offset(Code ? 1 : 0) { - assert(Op == Win64EH::UOP_PushMachFrame); - } - OpType getOperation() const { return Operation; } - MCSymbol *getLabel() const { return Label; } - unsigned getOffset() const { return Offset; } - unsigned getSize() const { return Offset; } - unsigned getRegister() const { return Register; } - bool isPushCodeFrame() const { return Offset == 1; } - }; +namespace Win64EH { +struct Instruction { + static WinEH::Instruction PushNonVol(MCSymbol *L, unsigned Reg) { + return WinEH::Instruction(Win64EH::UOP_PushNonVol, L, Reg, -1); + } + static WinEH::Instruction Alloc(MCSymbol *L, unsigned Size) { + return WinEH::Instruction(Size > 128 ? UOP_AllocLarge : UOP_AllocSmall, L, + -1, Size); + } + static WinEH::Instruction PushMachFrame(MCSymbol *L, bool Code) { + return WinEH::Instruction(UOP_PushMachFrame, L, -1, Code ? 1 : 0); + } + static WinEH::Instruction SaveNonVol(MCSymbol *L, unsigned Reg, + unsigned Offset) { + return WinEH::Instruction(Offset > 512 * 1024 - 8 ? UOP_SaveNonVolBig + : UOP_SaveNonVol, + L, Reg, Offset); + } + static WinEH::Instruction SaveXMM(MCSymbol *L, unsigned Reg, + unsigned Offset) { + return WinEH::Instruction(Offset > 512 * 1024 - 8 ? UOP_SaveXMM128Big + : UOP_SaveXMM128, + L, Reg, Offset); + } + static WinEH::Instruction SetFPReg(MCSymbol *L, unsigned Reg, unsigned Off) { + return WinEH::Instruction(UOP_SetFPReg, L, Reg, Off); + } +}; +} - struct MCWin64EHUnwindInfo { - MCWin64EHUnwindInfo() : Begin(0), End(0), ExceptionHandler(0), - Function(0), PrologEnd(0), Symbol(0), - HandlesUnwind(false), HandlesExceptions(false), - LastFrameInst(-1), ChainedParent(0), - Instructions() {} + struct MCWinFrameInfo { + MCWinFrameInfo() + : Begin(nullptr), End(nullptr),ExceptionHandler(nullptr), + Function(nullptr), PrologEnd(nullptr), Symbol(nullptr), + HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), + ChainedParent(nullptr), Instructions() {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *ExceptionHandler; @@ -75,8 +69,8 @@ namespace llvm { bool HandlesUnwind; bool HandlesExceptions; int LastFrameInst; - MCWin64EHUnwindInfo *ChainedParent; - std::vector<MCWin64EHInstruction> Instructions; + MCWinFrameInfo *ChainedParent; + std::vector<WinEH::Instruction> Instructions; }; class MCWin64EHUnwindEmitter { @@ -86,7 +80,7 @@ namespace llvm { // This emits the unwind info sections (.pdata and .xdata in PE/COFF). // static void Emit(MCStreamer &streamer); - static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info); + static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info); }; } // end namespace llvm diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index 213481c9090c..dad7bb597039 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -30,6 +30,7 @@ namespace llvm { virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsCrossSection) const = 0; + virtual bool recordRelocation(const MCFixup &) const { return true; } }; /// \brief Construct a new Win COFF writer instance. diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h new file mode 100644 index 000000000000..7d2d0e4f5560 --- /dev/null +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -0,0 +1,74 @@ +//===- MCWinCOFFStreamer.h - COFF Object File Interface ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCWINCOFFSTREAMER_H +#define LLVM_MC_MCWINCOFFSTREAMER_H + +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCObjectStreamer.h" + +namespace llvm { +class MCAsmBackend; +class MCContext; +class MCCodeEmitter; +class MCExpr; +class MCInst; +class MCSection; +class MCSubtargetInfo; +class MCSymbol; +class StringRef; +class raw_ostream; + +class MCWinCOFFStreamer : public MCObjectStreamer { +public: + MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE, + raw_ostream &OS); + + /// \name MCStreamer interface + /// \{ + + void InitSections() override; + void EmitLabel(MCSymbol *Symbol) override; + void EmitAssemblerFlag(MCAssemblerFlag Flag) override; + void EmitThumbFunc(MCSymbol *Func) override; + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; + void BeginCOFFSymbolDef(MCSymbol const *Symbol) override; + void EmitCOFFSymbolStorageClass(int StorageClass) override; + void EmitCOFFSymbolType(int Type) override; + void EndCOFFSymbolDef() override; + void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; + void EmitCOFFSecRel32(MCSymbol const *Symbol) override; + void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitFileDirective(StringRef Filename) override; + void EmitIdent(StringRef IdentString) override; + void EmitWinEHHandlerData() override; + void FinishImpl() override; + + /// \} + +protected: + const MCSymbol *CurSymbol; + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override; + +private: + LLVM_ATTRIBUTE_NORETURN void FatalError(const Twine &Msg) const; +}; +} + +#endif + diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h new file mode 100644 index 000000000000..1cd1b0f1b8ca --- /dev/null +++ b/include/llvm/MC/MCWinEH.h @@ -0,0 +1,29 @@ +//===- MCWinEH.h - Windows Unwinding Support --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCWINEH_H +#define LLVM_MC_MCWINEH_H + +namespace llvm { +class MCSymbol; + +namespace WinEH { +struct Instruction { + const MCSymbol *Label; + const unsigned Offset; + const unsigned Register; + const unsigned Operation; + + Instruction(unsigned Op, MCSymbol *L, unsigned Reg, unsigned Off) + : Label(L), Offset(Off), Register(Reg), Operation(Op) {} +}; +} +} + +#endif diff --git a/include/llvm/MC/MachineLocation.h b/include/llvm/MC/MachineLocation.h index b3fbee77021d..2a18615eff62 100644 --- a/include/llvm/MC/MachineLocation.h +++ b/include/llvm/MC/MachineLocation.h @@ -28,7 +28,7 @@ private: unsigned Register; // gcc/gdb register number. int Offset; // Displacement if not register. public: - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // The target register number for an abstract frame pointer. The value is // an arbitrary value that doesn't collide with any real target register. VirtualFP = ~0U @@ -73,6 +73,11 @@ public: void dump(); #endif }; + +inline bool operator!=(const MachineLocation &LHS, const MachineLocation &RHS) { + return !(LHS == RHS); +} + } // End llvm namespace #endif diff --git a/include/llvm/MC/StringTableBuilder.h b/include/llvm/MC/StringTableBuilder.h new file mode 100644 index 000000000000..065e9e06e2c9 --- /dev/null +++ b/include/llvm/MC/StringTableBuilder.h @@ -0,0 +1,59 @@ +//===-- StringTableBuilder.h - String table building utility ------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_STRINGTABLE_BUILDER_H +#define LLVM_MC_STRINGTABLE_BUILDER_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include <cassert> + +namespace llvm { + +/// \brief Utility for building string tables with deduplicated suffixes. +class StringTableBuilder { + SmallString<256> StringTable; + StringMap<size_t> StringIndexMap; + +public: + /// \brief Add a string to the builder. Returns a StringRef to the internal + /// copy of s. Can only be used before the table is finalized. + StringRef add(StringRef s) { + assert(!isFinalized()); + return StringIndexMap.GetOrCreateValue(s, 0).getKey(); + } + + /// \brief Analyze the strings and build the final table. No more strings can + /// be added after this point. + void finalize(); + + /// \brief Retrieve the string table data. Can only be used after the table + /// is finalized. + StringRef data() { + assert(isFinalized()); + return StringTable; + } + + /// \brief Get the offest of a string in the string table. Can only be used + /// after the table is finalized. + size_t getOffset(StringRef s) { + assert(isFinalized()); + assert(StringIndexMap.count(s) && "String is not in table!"); + return StringIndexMap[s]; + } + +private: + bool isFinalized() { + return !StringTable.empty(); + } +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index d0735ccd9fa3..c5d62a6cbae8 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -18,9 +18,9 @@ #ifndef LLVM_MC_SUBTARGETFEATURE_H #define LLVM_MC_SUBTARGETFEATURE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" -#include <vector> namespace llvm { class raw_ostream; @@ -78,20 +78,17 @@ public: std::string getString() const; /// Adding Features. - void AddFeature(const StringRef String, bool IsEnabled = true); + void AddFeature(const StringRef String); /// ToggleFeature - Toggle a feature and returns the newly updated feature /// bits. uint64_t ToggleFeature(uint64_t Bits, const StringRef String, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize); + ArrayRef<SubtargetFeatureKV> FeatureTable); /// Get feature bits of a CPU. uint64_t getFeatureBits(const StringRef CPU, - const SubtargetFeatureKV *CPUTable, - size_t CPUTableSize, - const SubtargetFeatureKV *FeatureTable, - size_t FeatureTableSize); + ArrayRef<SubtargetFeatureKV> CPUTable, + ArrayRef<SubtargetFeatureKV> FeatureTable); /// Print feature string. void print(raw_ostream &OS) const; diff --git a/include/llvm/Object/YAML.h b/include/llvm/MC/YAML.h index 89fe5047a86e..383cdc6785fa 100644 --- a/include/llvm/Object/YAML.h +++ b/include/llvm/MC/YAML.h @@ -1,26 +1,10 @@ -//===- YAML.h - YAMLIO utilities for object files ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares utility classes for handling the YAML representation of -// object files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_YAML_H -#define LLVM_OBJECT_YAML_H +#ifndef LLVM_MC_YAML_H +#define LLVM_MC_YAML_H #include "llvm/Support/YAMLTraits.h" namespace llvm { -namespace object { namespace yaml { - /// \brief Specialized YAMLIO scalar type for representing a binary blob. /// /// A typical use case would be to represent the content of a section in a @@ -100,17 +84,11 @@ inline bool operator==(const BinaryRef &LHS, const BinaryRef &RHS) { return LHS.DataIsHexString == RHS.DataIsHexString && LHS.Data == RHS.Data; } -} -} - -namespace yaml { -template <> struct ScalarTraits<object::yaml::BinaryRef> { - static void output(const object::yaml::BinaryRef &, void *, - llvm::raw_ostream &); - static StringRef input(StringRef, void *, object::yaml::BinaryRef &); +template <> struct ScalarTraits<BinaryRef> { + static void output(const BinaryRef &, void *, llvm::raw_ostream &); + static StringRef input(StringRef, void *, BinaryRef &); + static bool mustQuote(StringRef S) { return needsQuotes(S); } }; } - } - #endif diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index 1cba51954eca..af6c995c1d05 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -17,6 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/Binary.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" @@ -71,7 +72,7 @@ public: Child getNext() const; - error_code getName(StringRef &Result) const; + ErrorOr<StringRef> getName() const; StringRef getRawName() const { return getHeader()->getName(); } sys::TimeValue getLastModified() const { return getHeader()->getLastModified(); @@ -88,16 +89,17 @@ public: return StringRef(Data.data() + StartOfFile, getSize()); } - error_code getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, - bool FullPath = false) const; + ErrorOr<std::unique_ptr<MemoryBuffer>> + getMemoryBuffer(bool FullPath = false) const; - error_code getAsBinary(OwningPtr<Binary> &Result) const; + ErrorOr<std::unique_ptr<Binary>> + getAsBinary(LLVMContext *Context = nullptr) const; }; class child_iterator { Child child; public: - child_iterator() : child(Child(0, 0)) {} + child_iterator() : child(Child(nullptr, nullptr)) {} child_iterator(const Child &c) : child(c) {} const Child* operator->() const { return &child; @@ -135,8 +137,8 @@ public: : Parent(p) , SymbolIndex(symi) , StringIndex(stri) {} - error_code getName(StringRef &Result) const; - error_code getMember(child_iterator &Result) const; + StringRef getName() const; + ErrorOr<child_iterator> getMember() const; Symbol getNext() const; }; @@ -162,7 +164,8 @@ public: } }; - Archive(MemoryBuffer *source, error_code &ec); + Archive(std::unique_ptr<MemoryBuffer> Source, std::error_code &EC); + static ErrorOr<Archive *> create(std::unique_ptr<MemoryBuffer> Source); enum Kind { K_GNU, @@ -174,11 +177,11 @@ public: return Format; } - child_iterator begin_children(bool SkipInternal = true) const; - child_iterator end_children() const; + child_iterator child_begin(bool SkipInternal = true) const; + child_iterator child_end() const; - symbol_iterator begin_symbols() const; - symbol_iterator end_symbols() const; + symbol_iterator symbol_begin() const; + symbol_iterator symbol_end() const; // Cast methods. static inline bool classof(Binary const *v) { diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index a3f5625cc9b7..91984cb52715 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -14,11 +14,13 @@ #ifndef LLVM_OBJECT_BINARY_H #define LLVM_OBJECT_BINARY_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/Object/Error.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" namespace llvm { +class LLVMContext; class MemoryBuffer; class StringRef; @@ -32,13 +34,15 @@ private: unsigned int TypeID; protected: - MemoryBuffer *Data; + std::unique_ptr<MemoryBuffer> Data; - Binary(unsigned int Type, MemoryBuffer *Source); + Binary(unsigned int Type, std::unique_ptr<MemoryBuffer> Source); enum { ID_Archive, ID_MachOUniversalBinary, + ID_IR, // LLVM IR + // Object and children. ID_StartObjects, ID_COFF, @@ -74,6 +78,7 @@ public: virtual ~Binary(); StringRef getData() const; + MemoryBuffer *releaseBuffer() { return Data.release(); } StringRef getFileName() const; // Cast methods. @@ -84,6 +89,10 @@ public: return TypeID > ID_StartObjects && TypeID < ID_EndObjects; } + bool isSymbolic() const { + return isIR() || isObject(); + } + bool isArchive() const { return TypeID == ID_Archive; } @@ -104,6 +113,10 @@ public: return TypeID == ID_COFF; } + bool isIR() const { + return TypeID == ID_IR; + } + bool isLittleEndian() const { return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || TypeID == ID_MachO32B || TypeID == ID_MachO64B); @@ -112,14 +125,11 @@ public: /// @brief Create a Binary from Source, autodetecting the file type. /// -/// @param Source The data to create the Binary from. Ownership is transferred -/// to Result if successful. If an error is returned, Source is destroyed -/// by createBinary before returning. -/// @param Result A pointer to the resulting Binary if no error occured. -error_code createBinary(MemoryBuffer *Source, OwningPtr<Binary> &Result); - -error_code createBinary(StringRef Path, OwningPtr<Binary> &Result); +/// @param Source The data to create the Binary from. +ErrorOr<Binary *> createBinary(std::unique_ptr<MemoryBuffer> Source, + LLVMContext *Context = nullptr); +ErrorOr<Binary *> createBinary(StringRef Path); } } diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index e05ae6c654c7..e2da070d47bd 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -19,12 +19,13 @@ #include "llvm/Support/Endian.h" namespace llvm { - template <typename T> - class ArrayRef; +template <typename T> class ArrayRef; namespace object { class ImportDirectoryEntryRef; +class ExportDirectoryEntryRef; typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator; +typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator; /// The DOS compatible header at the front of all PE/COFF executables. struct dos_header { @@ -64,8 +65,8 @@ struct coff_file_header { /// The 32-bit PE header that follows the COFF header. struct pe32_header { support::ulittle16_t Magic; - uint8_t MajorLinkerVersion; - uint8_t MinorLinkerVersion; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; support::ulittle32_t SizeOfCode; support::ulittle32_t SizeOfInitializedData; support::ulittle32_t SizeOfUninitializedData; @@ -98,8 +99,8 @@ struct pe32_header { /// The 64-bit PE header that follows the COFF header. struct pe32plus_header { support::ulittle16_t Magic; - uint8_t MajorLinkerVersion; - uint8_t MinorLinkerVersion; + uint8_t MajorLinkerVersion; + uint8_t MinorLinkerVersion; support::ulittle32_t SizeOfCode; support::ulittle32_t SizeOfInitializedData; support::ulittle32_t SizeOfUninitializedData; @@ -157,6 +158,28 @@ struct import_lookup_table_entry32 { } }; +struct export_directory_table_entry { + support::ulittle32_t ExportFlags; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t NameRVA; + support::ulittle32_t OrdinalBase; + support::ulittle32_t AddressTableEntries; + support::ulittle32_t NumberOfNamePointers; + support::ulittle32_t ExportAddressTableRVA; + support::ulittle32_t NamePointerRVA; + support::ulittle32_t OrdinalTableRVA; +}; + +union export_address_table_entry { + support::ulittle32_t ExportRVA; + support::ulittle32_t ForwarderRVA; +}; + +typedef support::ulittle32_t export_name_pointer_table_entry; +typedef support::ulittle16_t export_ordinal_table_entry; + struct coff_symbol { struct StringTableOffset { support::ulittle32_t Zeroes; @@ -169,19 +192,50 @@ struct coff_symbol { } Name; support::ulittle32_t Value; - support::little16_t SectionNumber; + support::ulittle16_t SectionNumber; support::ulittle16_t Type; - support::ulittle8_t StorageClass; - support::ulittle8_t NumberOfAuxSymbols; + support::ulittle8_t StorageClass; + support::ulittle8_t NumberOfAuxSymbols; + + uint8_t getBaseType() const { return Type & 0x0F; } + + uint8_t getComplexType() const { return (Type & 0xF0) >> 4; } + + bool isFunctionDefinition() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && + getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && + !COFF::isReservedSectionNumber(SectionNumber); + } + + bool isFunctionLineInfo() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_FUNCTION; + } + + bool isWeakExternal() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL || + (StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + SectionNumber == COFF::IMAGE_SYM_UNDEFINED && Value == 0); + } + + bool isFileRecord() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_FILE; + } - uint8_t getBaseType() const { - return Type & 0x0F; + bool isSectionDefinition() const { + // C++/CLI creates external ABS symbols for non-const appdomain globals. + // These are also followed by an auxiliary section definition. + bool isAppdomainGlobal = StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + SectionNumber == COFF::IMAGE_SYM_ABSOLUTE; + bool isOrdinarySection = + StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && Value == 0; + return isAppdomainGlobal || isOrdinarySection; } - uint8_t getComplexType() const { - return (Type & 0xF0) >> 4; + bool isCLRToken() const { + return StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; } }; @@ -196,6 +250,13 @@ struct coff_section { support::ulittle16_t NumberOfRelocations; support::ulittle16_t NumberOfLinenumbers; support::ulittle32_t Characteristics; + + // Returns true if the actual number of relocations is stored in + // VirtualAddress field of the first relocation table entry. + bool hasExtendedRelocations() const { + return Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL && + NumberOfRelocations == UINT16_MAX; + }; }; struct coff_relocation { @@ -204,12 +265,32 @@ struct coff_relocation { support::ulittle16_t Type; }; +struct coff_aux_function_definition { + support::ulittle32_t TagIndex; + support::ulittle32_t TotalSize; + support::ulittle32_t PointerToLinenumber; + support::ulittle32_t PointerToNextFunction; + char Unused[2]; +}; + +struct coff_aux_bf_and_ef_symbol { + char Unused1[4]; + support::ulittle16_t Linenumber; + char Unused2[6]; + support::ulittle32_t PointerToNextFunction; + char Unused3[2]; +}; + struct coff_aux_weak_external { support::ulittle32_t TagIndex; support::ulittle32_t Characteristics; char Unused[10]; }; +struct coff_aux_file { + char FileName[18]; +}; + struct coff_aux_section_definition { support::ulittle32_t Length; support::ulittle16_t NumberOfRelocations; @@ -220,149 +301,222 @@ struct coff_aux_section_definition { char Unused[3]; }; +struct coff_aux_clr_token { + support::ulittle8_t AuxType; + support::ulittle8_t Reserved; + support::ulittle32_t SymbolTableIndex; + char Unused[12]; +}; + +struct coff_load_configuration32 { + support::ulittle32_t Characteristics; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t GlobalFlagsClear; + support::ulittle32_t GlobalFlagsSet; + support::ulittle32_t CriticalSectionDefaultTimeout; + support::ulittle32_t DeCommitFreeBlockThreshold; + support::ulittle32_t DeCommitTotalFreeThreshold; + support::ulittle32_t LockPrefixTable; + support::ulittle32_t MaximumAllocationSize; + support::ulittle32_t VirtualMemoryThreshold; + support::ulittle32_t ProcessAffinityMask; + support::ulittle32_t ProcessHeapFlags; + support::ulittle16_t CSDVersion; + uint16_t Reserved; + support::ulittle32_t EditList; + support::ulittle32_t SecurityCookie; + support::ulittle32_t SEHandlerTable; + support::ulittle32_t SEHandlerCount; +}; + +struct coff_runtime_function_x64 { + support::ulittle32_t BeginAddress; + support::ulittle32_t EndAddress; + support::ulittle32_t UnwindInformation; +}; + class COFFObjectFile : public ObjectFile { private: friend class ImportDirectoryEntryRef; + friend class ExportDirectoryEntryRef; const coff_file_header *COFFHeader; - const pe32_header *PE32Header; - const data_directory *DataDirectory; - const coff_section *SectionTable; - const coff_symbol *SymbolTable; - const char *StringTable; - uint32_t StringTableSize; + const pe32_header *PE32Header; + const pe32plus_header *PE32PlusHeader; + const data_directory *DataDirectory; + const coff_section *SectionTable; + const coff_symbol *SymbolTable; + const char *StringTable; + uint32_t StringTableSize; const import_directory_table_entry *ImportDirectory; - uint32_t NumberOfImportDirectory; + uint32_t NumberOfImportDirectory; + const export_directory_table_entry *ExportDirectory; - error_code getString(uint32_t offset, StringRef &Res) const; + std::error_code getString(uint32_t offset, StringRef &Res) const; - const coff_symbol *toSymb(DataRefImpl Symb) const; - const coff_section *toSec(DataRefImpl Sec) const; - const coff_relocation *toRel(DataRefImpl Rel) const; + const coff_symbol *toSymb(DataRefImpl Symb) const; + const coff_section *toSec(DataRefImpl Sec) const; + const coff_relocation *toRel(DataRefImpl Rel) const; - error_code initSymbolTablePtr(); - error_code initImportTablePtr(); + std::error_code initSymbolTablePtr(); + std::error_code initImportTablePtr(); + std::error_code initExportTablePtr(); protected: - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; - virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const; - virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - - virtual error_code getLibraryNext(DataRefImpl LibData, - LibraryRef &Result) const; - virtual error_code getLibraryPath(DataRefImpl LibData, - StringRef &Result) const; + void moveSymbolNext(DataRefImpl &Symb) const override; + std::error_code getSymbolName(DataRefImpl Symb, + StringRef &Res) const override; + std::error_code getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const override; + std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + std::error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + std::error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; + void moveSectionNext(DataRefImpl &Sec) const override; + std::error_code getSectionName(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + std::error_code getSectionContents(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionReadOnlyData(DataRefImpl Sec, + bool &Res) const override; + std::error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + std::error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + std::error_code getRelocationType(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code + getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + std::error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + + std::error_code getLibraryNext(DataRefImpl LibData, + LibraryRef &Result) const override; + std::error_code getLibraryPath(DataRefImpl LibData, + StringRef &Result) const override; public: - COFFObjectFile(MemoryBuffer *Object, error_code &ec); - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; - - const coff_section *getCOFFSection(section_iterator &It) const; - const coff_symbol *getCOFFSymbol(symbol_iterator &It) const; - const coff_relocation *getCOFFRelocation(relocation_iterator &It) const; - - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; - virtual StringRef getLoadName() const; + COFFObjectFile(std::unique_ptr<MemoryBuffer> Object, std::error_code &EC); + basic_symbol_iterator symbol_begin_impl() const override; + basic_symbol_iterator symbol_end_impl() const override; + library_iterator needed_library_begin() const override; + library_iterator needed_library_end() const override; + section_iterator section_begin() const override; + section_iterator section_end() const override; + + const coff_section *getCOFFSection(const SectionRef &Section) const; + const coff_symbol *getCOFFSymbol(const SymbolRef &Symbol) const; + const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; + + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + unsigned getArch() const override; + StringRef getLoadName() const override; import_directory_iterator import_directory_begin() const; import_directory_iterator import_directory_end() const; - - error_code getHeader(const coff_file_header *&Res) const; - error_code getCOFFHeader(const coff_file_header *&Res) const; - error_code getPE32Header(const pe32_header *&Res) const; - error_code getDataDirectory(uint32_t index, const data_directory *&Res) const; - error_code getSection(int32_t index, const coff_section *&Res) const; - error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; + export_directory_iterator export_directory_begin() const; + export_directory_iterator export_directory_end() const; + + std::error_code getHeader(const coff_file_header *&Res) const; + std::error_code getCOFFHeader(const coff_file_header *&Res) const; + std::error_code getPE32Header(const pe32_header *&Res) const; + std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const; + std::error_code getDataDirectory(uint32_t index, + const data_directory *&Res) const; + std::error_code getSection(int32_t index, const coff_section *&Res) const; + std::error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; template <typename T> - error_code getAuxSymbol(uint32_t index, const T *&Res) const { + std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { const coff_symbol *s; - error_code ec = getSymbol(index, s); - Res = reinterpret_cast<const T*>(s); + std::error_code ec = getSymbol(index, s); + Res = reinterpret_cast<const T *>(s); return ec; } - error_code getSymbolName(const coff_symbol *symbol, StringRef &Res) const; + std::error_code getSymbolName(const coff_symbol *symbol, + StringRef &Res) const; ArrayRef<uint8_t> getSymbolAuxData(const coff_symbol *symbol) const; - error_code getSectionName(const coff_section *Sec, StringRef &Res) const; - error_code getSectionContents(const coff_section *Sec, - ArrayRef<uint8_t> &Res) const; + std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; + std::error_code getSectionContents(const coff_section *Sec, + ArrayRef<uint8_t> &Res) const; - error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; - error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; + std::error_code getVaPtr(uint64_t VA, uintptr_t &Res) const; + std::error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const; + std::error_code getHintName(uint32_t Rva, uint16_t &Hint, + StringRef &Name) const; - static inline bool classof(const Binary *v) { - return v->isCOFF(); - } + static inline bool classof(const Binary *v) { return v->isCOFF(); } }; // The iterator for the import directory table. class ImportDirectoryEntryRef { public: - ImportDirectoryEntryRef() : OwningObject(0) {} - ImportDirectoryEntryRef(DataRefImpl ImportDirectory, + ImportDirectoryEntryRef() : OwningObject(nullptr) {} + ImportDirectoryEntryRef(const import_directory_table_entry *Table, uint32_t I, const COFFObjectFile *Owner) - : ImportDirectoryPimpl(ImportDirectory), OwningObject(Owner) {} + : ImportTable(Table), Index(I), OwningObject(Owner) {} bool operator==(const ImportDirectoryEntryRef &Other) const; - error_code getNext(ImportDirectoryEntryRef &Result) const; - error_code getName(StringRef &Result) const; + void moveNext(); + std::error_code getName(StringRef &Result) const; - error_code + std::error_code getImportTableEntry(const import_directory_table_entry *&Result) const; - error_code + std::error_code getImportLookupEntry(const import_lookup_table_entry32 *&Result) const; private: - DataRefImpl ImportDirectoryPimpl; + const import_directory_table_entry *ImportTable; + uint32_t Index; + const COFFObjectFile *OwningObject; +}; + +// The iterator for the export directory table entry. +class ExportDirectoryEntryRef { +public: + ExportDirectoryEntryRef() : OwningObject(nullptr) {} + ExportDirectoryEntryRef(const export_directory_table_entry *Table, uint32_t I, + const COFFObjectFile *Owner) + : ExportTable(Table), Index(I), OwningObject(Owner) {} + + bool operator==(const ExportDirectoryEntryRef &Other) const; + void moveNext(); + + std::error_code getDllName(StringRef &Result) const; + std::error_code getOrdinalBase(uint32_t &Result) const; + std::error_code getOrdinal(uint32_t &Result) const; + std::error_code getExportRVA(uint32_t &Result) const; + std::error_code getSymbolName(StringRef &Result) const; + +private: + const export_directory_table_entry *ExportTable; + uint32_t Index; const COFFObjectFile *OwningObject; }; } // end namespace object diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h index 3fa3ec6c124b..4aba08f75ddc 100644 --- a/include/llvm/Object/COFFYAML.h +++ b/include/llvm/Object/COFFYAML.h @@ -14,7 +14,8 @@ #ifndef LLVM_OBJECT_COFFYAML_H #define LLVM_OBJECT_COFFYAML_H -#include "llvm/Object/YAML.h" +#include "llvm/ADT/Optional.h" +#include "llvm/MC/YAML.h" #include "llvm/Support/COFF.h" namespace llvm { @@ -35,6 +36,10 @@ inline SectionCharacteristics operator|(SectionCharacteristics a, // The structure of the yaml files is not an exact 1:1 match to COFF. In order // to use yaml::IO, we use these structures which are closer to the source. namespace COFFYAML { + LLVM_YAML_STRONG_TYPEDEF(uint8_t, COMDATType) + LLVM_YAML_STRONG_TYPEDEF(uint32_t, WeakExternalCharacteristics) + LLVM_YAML_STRONG_TYPEDEF(uint8_t, AuxSymbolType) + struct Relocation { uint32_t VirtualAddress; uint16_t Type; @@ -44,7 +49,7 @@ namespace COFFYAML { struct Section { COFF::section Header; unsigned Alignment; - object::yaml::BinaryRef SectionData; + yaml::BinaryRef SectionData; std::vector<Relocation> Relocations; StringRef Name; Section(); @@ -54,7 +59,12 @@ namespace COFFYAML { COFF::symbol Header; COFF::SymbolBaseType SimpleType; COFF::SymbolComplexType ComplexType; - object::yaml::BinaryRef AuxiliaryData; + Optional<COFF::AuxiliaryFunctionDefinition> FunctionDefinition; + Optional<COFF::AuxiliarybfAndefSymbol> bfAndefSymbol; + Optional<COFF::AuxiliaryWeakExternal> WeakExternal; + StringRef File; + Optional<COFF::AuxiliarySectionDefinition> SectionDefinition; + Optional<COFF::AuxiliaryCLRToken> CLRToken; StringRef Name; Symbol(); }; @@ -76,6 +86,21 @@ namespace llvm { namespace yaml { template <> +struct ScalarEnumerationTraits<COFFYAML::WeakExternalCharacteristics> { + static void enumeration(IO &IO, COFFYAML::WeakExternalCharacteristics &Value); +}; + +template <> +struct ScalarEnumerationTraits<COFFYAML::AuxSymbolType> { + static void enumeration(IO &IO, COFFYAML::AuxSymbolType &Value); +}; + +template <> +struct ScalarEnumerationTraits<COFFYAML::COMDATType> { + static void enumeration(IO &IO, COFFYAML::COMDATType &Value); +}; + +template <> struct ScalarEnumerationTraits<COFF::MachineTypes> { static void enumeration(IO &IO, COFF::MachineTypes &Value); }; @@ -96,8 +121,13 @@ struct ScalarEnumerationTraits<COFF::SymbolComplexType> { }; template <> -struct ScalarEnumerationTraits<COFF::RelocationTypeX86> { - static void enumeration(IO &IO, COFF::RelocationTypeX86 &Value); +struct ScalarEnumerationTraits<COFF::RelocationTypeI386> { + static void enumeration(IO &IO, COFF::RelocationTypeI386 &Value); +}; + +template <> +struct ScalarEnumerationTraits<COFF::RelocationTypeAMD64> { + static void enumeration(IO &IO, COFF::RelocationTypeAMD64 &Value); }; template <> @@ -120,6 +150,26 @@ struct MappingTraits<COFF::header> { static void mapping(IO &IO, COFF::header &H); }; +template <> struct MappingTraits<COFF::AuxiliaryFunctionDefinition> { + static void mapping(IO &IO, COFF::AuxiliaryFunctionDefinition &AFD); +}; + +template <> struct MappingTraits<COFF::AuxiliarybfAndefSymbol> { + static void mapping(IO &IO, COFF::AuxiliarybfAndefSymbol &AAS); +}; + +template <> struct MappingTraits<COFF::AuxiliaryWeakExternal> { + static void mapping(IO &IO, COFF::AuxiliaryWeakExternal &AWE); +}; + +template <> struct MappingTraits<COFF::AuxiliarySectionDefinition> { + static void mapping(IO &IO, COFF::AuxiliarySectionDefinition &ASD); +}; + +template <> struct MappingTraits<COFF::AuxiliaryCLRToken> { + static void mapping(IO &IO, COFF::AuxiliaryCLRToken &ACT); +}; + template <> struct MappingTraits<COFFYAML::Symbol> { static void mapping(IO &IO, COFFYAML::Symbol &S); diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index a6774c115030..fbc48e6d7218 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -40,19 +40,20 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); // Subclasses of ELFFile may need this for template instantiation inline std::pair<unsigned char, unsigned char> -getElfArchType(MemoryBuffer *Object) { - if (Object->getBufferSize() < ELF::EI_NIDENT) - return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE); - return std::make_pair((uint8_t) Object->getBufferStart()[ELF::EI_CLASS], - (uint8_t) Object->getBufferStart()[ELF::EI_DATA]); +getElfArchType(StringRef Object) { + if (Object.size() < ELF::EI_NIDENT) + return std::make_pair((uint8_t)ELF::ELFCLASSNONE, + (uint8_t)ELF::ELFDATANONE); + return std::make_pair((uint8_t)Object[ELF::EI_CLASS], + (uint8_t)Object[ELF::EI_DATA]); } template <class ELFT> class ELFFile { public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - typedef typename conditional<ELFT::Is64Bits, - uint64_t, uint32_t>::type uintX_t; + typedef typename std::conditional<ELFT::Is64Bits, + uint64_t, uint32_t>::type uintX_t; /// \brief Iterate over constant sized entities. template <class EntT> @@ -60,12 +61,12 @@ public: public: typedef ptrdiff_t difference_type; typedef EntT value_type; - typedef std::random_access_iterator_tag iterator_category; + typedef std::forward_iterator_tag iterator_category; typedef value_type &reference; typedef value_type *pointer; /// \brief Default construct iterator. - ELFEntityIterator() : EntitySize(0), Current(0) {} + ELFEntityIterator() : EntitySize(0), Current(nullptr) {} ELFEntityIterator(uintX_t EntSize, const char *Start) : EntitySize(EntSize), Current(Start) {} @@ -133,9 +134,11 @@ public: typedef Elf_Vernaux_Impl<ELFT> Elf_Vernaux; typedef Elf_Versym_Impl<ELFT> Elf_Versym; typedef ELFEntityIterator<const Elf_Dyn> Elf_Dyn_Iter; + typedef iterator_range<Elf_Dyn_Iter> Elf_Dyn_Range; typedef ELFEntityIterator<const Elf_Rela> Elf_Rela_Iter; typedef ELFEntityIterator<const Elf_Rel> Elf_Rel_Iter; typedef ELFEntityIterator<const Elf_Shdr> Elf_Shdr_Iter; + typedef iterator_range<Elf_Shdr_Iter> Elf_Shdr_Range; /// \brief Archive files are 2 byte aligned, so we need this for /// PointerIntPair to work. @@ -228,10 +231,10 @@ private: typedef SmallVector<const Elf_Shdr *, 2> Sections_t; typedef DenseMap<unsigned, unsigned> IndexMap_t; - MemoryBuffer *Buf; + StringRef Buf; const uint8_t *base() const { - return reinterpret_cast<const uint8_t *>(Buf->getBufferStart()); + return reinterpret_cast<const uint8_t *>(Buf.data()); } const Elf_Ehdr *Header; @@ -249,7 +252,7 @@ private: /// \brief Represents a region described by entries in the .dynamic table. struct DynRegionInfo { - DynRegionInfo() : Addr(0), Size(0), EntSize(0) {} + DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {} /// \brief Address in current address space. const void *Addr; /// \brief Size in bytes of the region. @@ -273,19 +276,19 @@ private: public: // If the integer is 0, this is an Elf_Verdef*. // If the integer is 1, this is an Elf_Vernaux*. - VersionMapEntry() : PointerIntPair<const void*, 1>(NULL, 0) { } + VersionMapEntry() : PointerIntPair<const void*, 1>(nullptr, 0) { } VersionMapEntry(const Elf_Verdef *verdef) : PointerIntPair<const void*, 1>(verdef, 0) { } VersionMapEntry(const Elf_Vernaux *vernaux) : PointerIntPair<const void*, 1>(vernaux, 1) { } - bool isNull() const { return getPointer() == NULL; } + bool isNull() const { return getPointer() == nullptr; } bool isVerdef() const { return !isNull() && getInt() == 0; } bool isVernaux() const { return !isNull() && getInt() == 1; } const Elf_Verdef *getVerdef() const { - return isVerdef() ? (const Elf_Verdef*)getPointer() : NULL; + return isVerdef() ? (const Elf_Verdef*)getPointer() : nullptr; } const Elf_Vernaux *getVernaux() const { - return isVernaux() ? (const Elf_Vernaux*)getPointer() : NULL; + return isVernaux() ? (const Elf_Vernaux*)getPointer() : nullptr; } }; mutable SmallVector<VersionMapEntry, 16> VersionMap; @@ -315,7 +318,12 @@ public: std::pair<const Elf_Shdr *, const Elf_Sym *> getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const; - ELFFile(MemoryBuffer *Object, error_code &ec); + ELFFile(StringRef Object, std::error_code &ec); + + bool isMipsELF64() const { + return Header->e_machine == ELF::EM_MIPS && + Header->getFileClass() == ELF::ELFCLASS64; + } bool isMips64EL() const { return Header->e_machine == ELF::EM_MIPS && @@ -325,6 +333,9 @@ public: Elf_Shdr_Iter begin_sections() const; Elf_Shdr_Iter end_sections() const; + Elf_Shdr_Range sections() const { + return make_range(begin_sections(), end_sections()); + } Elf_Sym_Iter begin_symbols() const; Elf_Sym_Iter end_symbols() const; @@ -333,12 +344,15 @@ public: /// \param NULLEnd use one past the first DT_NULL entry as the end instead of /// the section size. Elf_Dyn_Iter end_dynamic_table(bool NULLEnd = false) const; + Elf_Dyn_Range dynamic_table(bool NULLEnd = false) const { + return make_range(begin_dynamic_table(), end_dynamic_table(NULLEnd)); + } Elf_Sym_Iter begin_dynamic_symbols() const { if (DynSymRegion.Addr) return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr, true); - return Elf_Sym_Iter(0, 0, true); + return Elf_Sym_Iter(0, nullptr, true); } Elf_Sym_Iter end_dynamic_symbols() const { @@ -346,7 +360,7 @@ public: return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr + DynSymRegion.Size, true); - return Elf_Sym_Iter(0, 0, true); + return Elf_Sym_Iter(0, nullptr, true); } Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const { @@ -478,7 +492,7 @@ void ELFFile<ELFT>::LoadVersionNeeds(const Elf_Shdr *sec) const { template <class ELFT> void ELFFile<ELFT>::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. - if (DynSymRegion.Addr == NULL || dot_gnu_version_sec == NULL) + if (!DynSymRegion.Addr || !dot_gnu_version_sec) return; // Has the VersionMap already been loaded? @@ -510,7 +524,7 @@ ELFFile<ELFT>::getSection(const Elf_Sym *symb) const { if (symb->st_shndx == ELF::SHN_XINDEX) return getSection(ExtendedSymbolTable.lookup(symb)); if (symb->st_shndx >= ELF::SHN_LORESERVE) - return 0; + return nullptr; return getSection(symb->st_shndx); } @@ -523,7 +537,7 @@ ELFFile<ELFT>::getSymbol(uint32_t Index) const { template <class ELFT> ErrorOr<ArrayRef<uint8_t> > ELFFile<ELFT>::getSectionContents(const Elf_Shdr *Sec) const { - if (Sec->sh_offset + Sec->sh_size > Buf->getBufferSize()) + if (Sec->sh_offset + Sec->sh_size > Buf.size()) return object_error::parse_failed; const uint8_t *Start = base() + Sec->sh_offset; return ArrayRef<uint8_t>(Start, Sec->sh_size); @@ -537,10 +551,16 @@ StringRef ELFFile<ELFT>::getRelocationTypeName(uint32_t Type) const { template <class ELFT> void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, SmallVectorImpl<char> &Result) const { - if (!isMips64EL()) { + if (!isMipsELF64()) { StringRef Name = getRelocationTypeName(Type); Result.append(Name.begin(), Name.end()); } else { + // The Mips N64 ABI allows up to three operations to be specified per + // relocation record. Unfortunately there's no easy way to test for the + // presence of N64 ELFs as they have no special flag that identifies them + // as being N64. We can safely assume at the moment that all Mips + // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough + // information to disambiguate between old vs new ABIs. uint8_t Type1 = (Type >> 0) & 0xFF; uint8_t Type2 = (Type >> 8) & 0xFF; uint8_t Type3 = (Type >> 16) & 0xFF; @@ -565,7 +585,7 @@ std::pair<const typename ELFFile<ELFT>::Elf_Shdr *, const typename ELFFile<ELFT>::Elf_Sym *> ELFFile<ELFT>::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const { if (!Sec->sh_link) - return std::make_pair((const Elf_Shdr *)0, (const Elf_Sym *)0); + return std::make_pair(nullptr, nullptr); const Elf_Shdr *SymTable = getSection(Sec->sh_link); return std::make_pair( SymTable, getEntry<Elf_Sym>(SymTable, Rel->getSymbol(isMips64EL()))); @@ -583,7 +603,7 @@ void ELFFile<ELFT>::VerifyStrTab(const Elf_Shdr *sh) const { template <class ELFT> uint64_t ELFFile<ELFT>::getNumSections() const { assert(Header && "Header not initialized!"); - if (Header->e_shnum == ELF::SHN_UNDEF) { + if (Header->e_shnum == ELF::SHN_UNDEF && Header->e_shoff > 0) { assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); return SectionHeaderTable->sh_size; } @@ -602,18 +622,13 @@ typename ELFFile<ELFT>::uintX_t ELFFile<ELFT>::getStringTableIndex() const { } template <class ELFT> -ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec) - : Buf(Object), - SectionHeaderTable(0), - dot_shstrtab_sec(0), - dot_strtab_sec(0), - dot_symtab_sec(0), - SymbolTableSectionHeaderIndex(0), - dot_gnu_version_sec(0), - dot_gnu_version_r_sec(0), - dot_gnu_version_d_sec(0), - dt_soname(0) { - const uint64_t FileSize = Buf->getBufferSize(); +ELFFile<ELFT>::ELFFile(StringRef Object, std::error_code &ec) + : Buf(Object), SectionHeaderTable(nullptr), dot_shstrtab_sec(nullptr), + dot_strtab_sec(nullptr), dot_symtab_sec(nullptr), + SymbolTableSectionHeaderIndex(nullptr), dot_gnu_version_sec(nullptr), + dot_gnu_version_r_sec(nullptr), dot_gnu_version_d_sec(nullptr), + dt_soname(nullptr) { + const uint64_t FileSize = Buf.size(); if (sizeof(Elf_Ehdr) > FileSize) // FIXME: Proper error handling. @@ -641,30 +656,29 @@ ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec) // Scan sections for special sections. - for (Elf_Shdr_Iter SecI = begin_sections(), SecE = end_sections(); - SecI != SecE; ++SecI) { - switch (SecI->sh_type) { + for (const Elf_Shdr &Sec : sections()) { + switch (Sec.sh_type) { case ELF::SHT_SYMTAB_SHNDX: if (SymbolTableSectionHeaderIndex) // FIXME: Proper error handling. report_fatal_error("More than one .symtab_shndx!"); - SymbolTableSectionHeaderIndex = &*SecI; + SymbolTableSectionHeaderIndex = &Sec; break; case ELF::SHT_SYMTAB: if (dot_symtab_sec) // FIXME: Proper error handling. report_fatal_error("More than one .symtab!"); - dot_symtab_sec = &*SecI; - dot_strtab_sec = getSection(SecI->sh_link); + dot_symtab_sec = &Sec; + dot_strtab_sec = getSection(Sec.sh_link); break; case ELF::SHT_DYNSYM: { if (DynSymRegion.Addr) // FIXME: Proper error handling. report_fatal_error("More than one .dynsym!"); - DynSymRegion.Addr = base() + SecI->sh_offset; - DynSymRegion.Size = SecI->sh_size; - DynSymRegion.EntSize = SecI->sh_entsize; - const Elf_Shdr *DynStr = getSection(SecI->sh_link); + DynSymRegion.Addr = base() + Sec.sh_offset; + DynSymRegion.Size = Sec.sh_size; + DynSymRegion.EntSize = Sec.sh_entsize; + const Elf_Shdr *DynStr = getSection(Sec.sh_link); DynStrRegion.Addr = base() + DynStr->sh_offset; DynStrRegion.Size = DynStr->sh_size; DynStrRegion.EntSize = DynStr->sh_entsize; @@ -674,27 +688,27 @@ ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec) if (DynamicRegion.Addr) // FIXME: Proper error handling. report_fatal_error("More than one .dynamic!"); - DynamicRegion.Addr = base() + SecI->sh_offset; - DynamicRegion.Size = SecI->sh_size; - DynamicRegion.EntSize = SecI->sh_entsize; + DynamicRegion.Addr = base() + Sec.sh_offset; + DynamicRegion.Size = Sec.sh_size; + DynamicRegion.EntSize = Sec.sh_entsize; break; case ELF::SHT_GNU_versym: - if (dot_gnu_version_sec != NULL) + if (dot_gnu_version_sec != nullptr) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version section!"); - dot_gnu_version_sec = &*SecI; + dot_gnu_version_sec = &Sec; break; case ELF::SHT_GNU_verdef: - if (dot_gnu_version_d_sec != NULL) + if (dot_gnu_version_d_sec != nullptr) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version_d section!"); - dot_gnu_version_d_sec = &*SecI; + dot_gnu_version_d_sec = &Sec; break; case ELF::SHT_GNU_verneed: - if (dot_gnu_version_r_sec != NULL) + if (dot_gnu_version_r_sec != nullptr) // FIXME: Proper error handling. report_fatal_error("More than one .gnu.version_r section!"); - dot_gnu_version_r_sec = &*SecI; + dot_gnu_version_r_sec = &Sec; break; } } @@ -730,7 +744,7 @@ ELFFile<ELFT>::ELFFile(MemoryBuffer *Object, error_code &ec) } } - ec = error_code::success(); + ec = std::error_code(); } // Get the symbol table index in the symtab section given a symbol @@ -761,7 +775,7 @@ typename ELFFile<ELFT>::Elf_Shdr_Iter ELFFile<ELFT>::end_sections() const { template <class ELFT> typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::begin_symbols() const { if (!dot_symtab_sec) - return Elf_Sym_Iter(0, 0, false); + return Elf_Sym_Iter(0, nullptr, false); return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, (const char *)base() + dot_symtab_sec->sh_offset, false); } @@ -769,7 +783,7 @@ typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::begin_symbols() const { template <class ELFT> typename ELFFile<ELFT>::Elf_Sym_Iter ELFFile<ELFT>::end_symbols() const { if (!dot_symtab_sec) - return Elf_Sym_Iter(0, 0, false); + return Elf_Sym_Iter(0, nullptr, false); return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, (const char *)base() + dot_symtab_sec->sh_offset + dot_symtab_sec->sh_size, @@ -782,14 +796,14 @@ ELFFile<ELFT>::begin_dynamic_table() const { if (DynamicRegion.Addr) return Elf_Dyn_Iter(DynamicRegion.EntSize, (const char *)DynamicRegion.Addr); - return Elf_Dyn_Iter(0, 0); + return Elf_Dyn_Iter(0, nullptr); } template <class ELFT> typename ELFFile<ELFT>::Elf_Dyn_Iter ELFFile<ELFT>::end_dynamic_table(bool NULLEnd) const { if (!DynamicRegion.Addr) - return Elf_Dyn_Iter(0, 0); + return Elf_Dyn_Iter(0, nullptr); Elf_Dyn_Iter Ret(DynamicRegion.EntSize, (const char *)DynamicRegion.Addr + DynamicRegion.Size); @@ -809,17 +823,13 @@ ELFFile<ELFT>::end_dynamic_table(bool NULLEnd) const { template <class ELFT> StringRef ELFFile<ELFT>::getLoadName() const { if (!dt_soname) { + dt_soname = ""; // Find the DT_SONAME entry - Elf_Dyn_Iter it = begin_dynamic_table(); - Elf_Dyn_Iter ie = end_dynamic_table(); - while (it != ie && it->getTag() != ELF::DT_SONAME) - ++it; - - if (it != ie) { - dt_soname = getDynamicString(it->getVal()); - } else { - dt_soname = ""; - } + for (const auto &Entry : dynamic_table()) + if (Entry.getTag() == ELF::DT_SONAME) { + dt_soname = getDynamicString(Entry.getVal()); + break; + } } return dt_soname; } @@ -842,7 +852,7 @@ template <class ELFT> const typename ELFFile<ELFT>::Elf_Shdr * ELFFile<ELFT>::getSection(uint32_t index) const { if (index == 0) - return 0; + return nullptr; if (!SectionHeaderTable || index >= getNumSections()) // FIXME: Proper error handling. report_fatal_error("Invalid section index!"); @@ -871,7 +881,7 @@ const char *ELFFile<ELFT>::getString(const Elf_Shdr *section, template <class ELFT> const char *ELFFile<ELFT>::getDynamicString(uintX_t Offset) const { if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size) - return 0; + return nullptr; return (const char *)DynStrRegion.Addr + Offset; } @@ -913,7 +923,7 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, const Elf_Sym *symb, bool &IsDefault) const { // Handle non-dynamic symbols. - if (section != DynSymRegion.Addr && section != 0) { + if (section != DynSymRegion.Addr && section != nullptr) { // Non-dynamic symbols can have versions in their names // A name of the form 'foo@V1' indicates version 'V1', non-default. // A name of the form 'foo@@V2' indicates version 'V2', default version. @@ -937,7 +947,7 @@ ErrorOr<StringRef> ELFFile<ELFT>::getSymbolVersion(const Elf_Shdr *section, } // This is a dynamic symbol. Look in the GNU symbol version table. - if (dot_gnu_version_sec == NULL) { + if (!dot_gnu_version_sec) { // No version table. IsDefault = false; return StringRef(""); diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 962a3e2a8655..069f38112def 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -44,6 +44,7 @@ public: typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr; + typedef typename ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr; typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel; typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela; typedef typename ELFFile<ELFT>::Elf_Dyn Elf_Dyn; @@ -55,53 +56,65 @@ public: protected: ELFFile<ELFT> EF; - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getLibraryNext(DataRefImpl Data, LibraryRef &Result) const; - virtual error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; - virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; - virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; - virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code + void moveSymbolNext(DataRefImpl &Symb) const override; + std::error_code getSymbolName(DataRefImpl Symb, + StringRef &Res) const override; + std::error_code getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const override; + std::error_code getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const override; + std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override; + std::error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + std::error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; + + std::error_code getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const override; + std::error_code getLibraryPath(DataRefImpl Data, + StringRef &Res) const override; + + void moveSectionNext(DataRefImpl &Sec) const override; + std::error_code getSectionName(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + std::error_code getSectionContents(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionReadOnlyData(DataRefImpl Sec, + bool &Res) const override; + std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + section_iterator getRelocatedSection(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + std::error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + std::error_code getRelocationType(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code + getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + std::error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; + SmallVectorImpl<char> &Result) const override; uint64_t getROffset(DataRefImpl Rel) const; StringRef getRelocationTypeName(uint32_t Type) const; @@ -165,31 +178,35 @@ protected: bool isDyldELFObject; public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); + ELFObjectFile(std::unique_ptr<MemoryBuffer> Object, std::error_code &EC); const Elf_Sym *getSymbol(DataRefImpl Symb) const; - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; + basic_symbol_iterator symbol_begin_impl() const override; + basic_symbol_iterator symbol_end_impl() const override; - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; + symbol_iterator dynamic_symbol_begin() const; + symbol_iterator dynamic_symbol_end() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; + section_iterator section_begin() const override; + section_iterator section_end() const override; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; + library_iterator needed_library_begin() const override; + library_iterator needed_library_end() const override; - error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; - error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const; + std::error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; + std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, + bool &IsDefault) const; - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual StringRef getObjectType() const { return "ELF"; } - virtual unsigned getArch() const; - virtual StringRef getLoadName() const; + uint8_t getBytesInAddress() const override; + StringRef getFileFormatName() const override; + unsigned getArch() const override; + StringRef getLoadName() const override; + + std::error_code getPlatformFlags(unsigned &Result) const override { + Result = EF.getHeader()->e_flags; + return object_error::success; + } const ELFFile<ELFT> *getELFFile() const { return &EF; } @@ -208,44 +225,40 @@ typedef ELFObjectFile<ELFType<support::big, 2, false> > ELF32BEObjectFile; typedef ELFObjectFile<ELFType<support::big, 2, true> > ELF64BEObjectFile; template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolNext(DataRefImpl Symb, - SymbolRef &Result) const { - Result = SymbolRef(toDRI(++toELFSymIter(Symb)), this); - return object_error::success; +void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Symb) const { + Symb = toDRI(++toELFSymIter(Symb)); } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { +std::error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb, + StringRef &Result) const { ErrorOr<StringRef> Name = EF.getSymbolName(toELFSymIter(Symb)); if (!Name) - return Name; + return Name.getError(); Result = *Name; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, - StringRef &Version, - bool &IsDefault) const { +std::error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, + StringRef &Version, + bool &IsDefault) const { DataRefImpl Symb = SymRef.getRawDataRefImpl(); const Elf_Sym *symb = getSymbol(Symb); ErrorOr<StringRef> Ver = EF.getSymbolVersion(EF.getSection(Symb.d.b), symb, IsDefault); if (!Ver) - return Ver; + return Ver.getError(); Version = *Ver; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Result) const { +std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, + uint64_t &Result) const { const Elf_Sym *ESym = getSymbol(Symb); - const Elf_Shdr *ESec; switch (EF.getSymbolTableIndex(ESym)) { case ELF::SHN_COMMON: - // Unintialized symbols have no offset in the object file case ELF::SHN_UNDEF: Result = UnknownAddressOrSize; return object_error::success; @@ -253,75 +266,25 @@ error_code ELFObjectFile<ELFT>::getSymbolFileOffset(DataRefImpl Symb, Result = ESym->st_value; return object_error::success; default: - ESec = EF.getSection(ESym); - } - - switch (ESym->getType()) { - case ELF::STT_SECTION: - Result = ESec ? ESec->sh_offset : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - Result = ESym->st_value + (ESec ? ESec->sh_offset : 0); - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; + break; } -} -template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { - const Elf_Sym *ESym = getSymbol(Symb); - const Elf_Shdr *ESec; - switch (EF.getSymbolTableIndex(ESym)) { - case ELF::SHN_COMMON: - case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; - case ELF::SHN_ABS: - Result = ESym->st_value; - return object_error::success; - default: - ESec = EF.getSection(ESym); - } + const Elf_Ehdr *Header = EF.getHeader(); + Result = ESym->st_value; - switch (ESym->getType()) { - case ELF::STT_SECTION: - Result = ESec ? ESec->sh_addr : UnknownAddressOrSize; - return object_error::success; - case ELF::STT_FUNC: - case ELF::STT_OBJECT: - case ELF::STT_NOTYPE: - bool IsRelocatable; - switch (EF.getHeader()->e_type) { - case ELF::ET_EXEC: - case ELF::ET_DYN: - IsRelocatable = false; - break; - default: - IsRelocatable = true; - } - Result = ESym->st_value; + // Clear the ARM/Thumb indicator flag. + if (Header->e_machine == ELF::EM_ARM && ESym->getType() == ELF::STT_FUNC) + Result &= ~1; - // Clear the ARM/Thumb indicator flag. - if (EF.getHeader()->e_machine == ELF::EM_ARM) - Result &= ~1; + if (Header->e_type == ELF::ET_REL) + Result += EF.getSection(ESym)->sh_addr; - if (IsRelocatable && ESec != 0) - Result += ESec->sh_addr; - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } + return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const { +std::error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const { Elf_Sym_Iter Sym = toELFSymIter(Symb); if (Sym->st_shndx == ELF::SHN_COMMON) Res = Sym->st_value; @@ -331,15 +294,23 @@ error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb, } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { +std::error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb, + uint64_t &Result) const { Result = toELFSymIter(Symb)->st_size; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { +std::error_code ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb, + uint8_t &Result) const { + Result = toELFSymIter(Symb)->st_other; + return object_error::success; +} + +template <class ELFT> +std::error_code +ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Result) const { const Elf_Sym *ESym = getSymbol(Symb); switch (ESym->getType()) { @@ -368,11 +339,11 @@ error_code ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb, } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, - uint32_t &Result) const { - const Elf_Sym *ESym = getSymbol(Symb); +uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb) const { + Elf_Sym_Iter EIter = toELFSymIter(Symb); + const Elf_Sym *ESym = &*EIter; - Result = SymbolRef::SF_None; + uint32_t Result = SymbolRef::SF_None; if (ESym->getBinding() != ELF::STB_LOCAL) Result |= SymbolRef::SF_Global; @@ -384,7 +355,7 @@ error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, Result |= SymbolRef::SF_Absolute; if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION || - ESym == &*EF.begin_symbols()) + EIter == EF.begin_symbols() || EIter == EF.begin_dynamic_symbols()) Result |= SymbolRef::SF_FormatSpecific; if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) @@ -394,19 +365,17 @@ error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) Result |= SymbolRef::SF_Common; - if (ESym->getType() == ELF::STT_TLS) - Result |= SymbolRef::SF_ThreadLocal; - - return object_error::success; + return Result; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { +std::error_code +ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { const Elf_Sym *ESym = getSymbol(Symb); const Elf_Shdr *ESec = EF.getSection(ESym); if (!ESec) - Res = end_sections(); + Res = section_end(); else { DataRefImpl Sec; Sec.p = reinterpret_cast<intptr_t>(ESec); @@ -416,69 +385,61 @@ error_code ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { - const Elf_Sym *ESym = getSymbol(Symb); - Val = ESym->st_value; - return object_error::success; -} - -template <class ELFT> -error_code ELFObjectFile<ELFT>::getSectionNext(DataRefImpl Sec, - SectionRef &Result) const { - Result = SectionRef(toDRI(++toELFShdrIter(Sec)), this); - return object_error::success; +void ELFObjectFile<ELFT>::moveSectionNext(DataRefImpl &Sec) const { + Sec = toDRI(++toELFShdrIter(Sec)); } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, - StringRef &Result) const { +std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec, + StringRef &Result) const { ErrorOr<StringRef> Name = EF.getSectionName(&*toELFShdrIter(Sec)); if (!Name) - return Name; + return Name.getError(); Result = *Name; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { +std::error_code ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec, + uint64_t &Result) const { Result = toELFShdrIter(Sec)->sh_addr; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { +std::error_code ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { Result = toELFShdrIter(Sec)->sh_size; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec, - StringRef &Result) const { +std::error_code +ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { +std::error_code +ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec, + uint64_t &Result) const { Result = toELFShdrIter(Sec)->sh_addralign; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec, + bool &Result) const { Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec, + bool &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && EShdr->sh_type == ELF::SHT_PROGBITS; @@ -486,8 +447,8 @@ error_code ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec, } template <class ELFT> -error_code ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec, + bool &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && EShdr->sh_type == ELF::SHT_NOBITS; @@ -495,7 +456,7 @@ error_code ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec, } template <class ELFT> -error_code +std::error_code ELFObjectFile<ELFT>::isSectionRequiredForExecution(DataRefImpl Sec, bool &Result) const { Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; @@ -503,31 +464,31 @@ ELFObjectFile<ELFT>::isSectionRequiredForExecution(DataRefImpl Sec, } template <class ELFT> -error_code ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile<ELFT>::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { +std::error_code ELFObjectFile<ELFT>::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); Result = !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { +std::error_code ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { Elf_Sym_Iter ESym = toELFSymIter(Symb); uintX_t Index = ESym->st_shndx; @@ -566,12 +527,12 @@ template <class ELFT> section_iterator ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { if (EF.getHeader()->e_type != ELF::ET_REL) - return end_sections(); + return section_end(); Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); uintX_t Type = EShdr->sh_type; if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) - return end_sections(); + return section_end(); const Elf_Shdr *R = EF.getSection(EShdr->sh_info); return section_iterator(SectionRef(toDRI(R), this)); @@ -579,11 +540,8 @@ ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const { // Relocations template <class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationNext(DataRefImpl Rel, - RelocationRef &Result) const { +void ELFObjectFile<ELFT>::moveRelocationNext(DataRefImpl &Rel) const { ++Rel.d.b; - Result = RelocationRef(Rel, this); - return object_error::success; } template <class ELFT> @@ -604,7 +562,7 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { } } if (!symbolIdx) - return end_symbols(); + return symbol_end(); const Elf_Shdr *SymSec = EF.getSection(sec->sh_link); @@ -624,15 +582,29 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { } template <class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { - Result = getROffset(Rel); +std::error_code +ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, + uint64_t &Result) const { + uint64_t ROffset = getROffset(Rel); + const Elf_Ehdr *Header = EF.getHeader(); + + if (Header->e_type == ELF::ET_REL) { + const Elf_Shdr *RelocationSec = getRelSection(Rel); + const Elf_Shdr *RelocatedSec = EF.getSection(RelocationSec->sh_info); + Result = ROffset + RelocatedSec->sh_addr; + } else { + Result = ROffset; + } + return object_error::success; } template <class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, - uint64_t &Result) const { +std::error_code +ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, + uint64_t &Result) const { + assert(EF.getHeader()->e_type == ELF::ET_REL && + "Only relocatable object files have relocation offsets"); Result = getROffset(Rel); return object_error::success; } @@ -651,8 +623,8 @@ uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const { } template <class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, - uint64_t &Result) const { +std::error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, + uint64_t &Result) const { const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default: @@ -675,7 +647,7 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { } template <class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationTypeName( +std::error_code ELFObjectFile<ELFT>::getRelocationTypeName( DataRefImpl Rel, SmallVectorImpl<char> &Result) const { const Elf_Shdr *sec = getRelSection(Rel); uint32_t type; @@ -697,8 +669,9 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( } template <class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel, - int64_t &Result) const { +std::error_code +ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel, + int64_t &Result) const { const Elf_Shdr *sec = getRelSection(Rel); switch (sec->sh_type) { default: @@ -715,7 +688,7 @@ error_code ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel, } template <class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationValueString( +std::error_code ELFObjectFile<ELFT>::getRelocationValueString( DataRefImpl Rel, SmallVectorImpl<char> &Result) const { const Elf_Shdr *sec = getRelSection(Rel); uint8_t type; @@ -743,7 +716,7 @@ error_code ELFObjectFile<ELFT>::getRelocationValueString( ErrorOr<StringRef> SymName = EF.getSymbolName(EF.getSection(sec->sh_link), symb); if (!SymName) - return SymName; + return SymName.getError(); switch (EF.getHeader()->e_machine) { case ELF::EM_X86_64: switch (type) { @@ -783,6 +756,7 @@ error_code ELFObjectFile<ELFT>::getRelocationValueString( } case ELF::EM_ARM: case ELF::EM_HEXAGON: + case ELF::EM_MIPS: res = *SymName; break; default: @@ -812,40 +786,41 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { } template <class ELFT> -ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) +ELFObjectFile<ELFT>::ELFObjectFile(std::unique_ptr<MemoryBuffer> Object, + std::error_code &EC) : ObjectFile(getELFType(static_cast<endianness>(ELFT::TargetEndianness) == support::little, ELFT::Is64Bits), - Object), - EF(Object, ec) {} + std::move(Object)), + EF(Data->getBuffer(), EC) {} template <class ELFT> -symbol_iterator ELFObjectFile<ELFT>::begin_symbols() const { - return symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); +basic_symbol_iterator ELFObjectFile<ELFT>::symbol_begin_impl() const { + return basic_symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); } template <class ELFT> -symbol_iterator ELFObjectFile<ELFT>::end_symbols() const { - return symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); +basic_symbol_iterator ELFObjectFile<ELFT>::symbol_end_impl() const { + return basic_symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); } template <class ELFT> -symbol_iterator ELFObjectFile<ELFT>::begin_dynamic_symbols() const { +symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_begin() const { return symbol_iterator(SymbolRef(toDRI(EF.begin_dynamic_symbols()), this)); } template <class ELFT> -symbol_iterator ELFObjectFile<ELFT>::end_dynamic_symbols() const { +symbol_iterator ELFObjectFile<ELFT>::dynamic_symbol_end() const { return symbol_iterator(SymbolRef(toDRI(EF.end_dynamic_symbols()), this)); } template <class ELFT> -section_iterator ELFObjectFile<ELFT>::begin_sections() const { +section_iterator ELFObjectFile<ELFT>::section_begin() const { return section_iterator(SectionRef(toDRI(EF.begin_sections()), this)); } template <class ELFT> -section_iterator ELFObjectFile<ELFT>::end_sections() const { +section_iterator ELFObjectFile<ELFT>::section_end() const { return section_iterator(SectionRef(toDRI(EF.end_sections()), this)); } @@ -863,7 +838,7 @@ StringRef ELFObjectFile<ELFT>::getLoadName() const { } template <class ELFT> -library_iterator ELFObjectFile<ELFT>::begin_libraries_needed() const { +library_iterator ELFObjectFile<ELFT>::needed_library_begin() const { Elf_Dyn_Iter DI = EF.begin_dynamic_table(); Elf_Dyn_Iter DE = EF.end_dynamic_table(); @@ -874,8 +849,8 @@ library_iterator ELFObjectFile<ELFT>::begin_libraries_needed() const { } template <class ELFT> -error_code ELFObjectFile<ELFT>::getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const { +std::error_code ELFObjectFile<ELFT>::getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const { Elf_Dyn_Iter DI = toELFDynIter(Data); Elf_Dyn_Iter DE = EF.end_dynamic_table(); @@ -889,14 +864,14 @@ error_code ELFObjectFile<ELFT>::getLibraryNext(DataRefImpl Data, } template <class ELFT> -error_code ELFObjectFile<ELFT>::getLibraryPath(DataRefImpl Data, - StringRef &Res) const { +std::error_code ELFObjectFile<ELFT>::getLibraryPath(DataRefImpl Data, + StringRef &Res) const { Res = EF.getDynamicString(toELFDynIter(Data)->getVal()); return object_error::success; } template <class ELFT> -library_iterator ELFObjectFile<ELFT>::end_libraries_needed() const { +library_iterator ELFObjectFile<ELFT>::needed_library_end() const { return library_iterator(LibraryRef(toDRI(EF.end_dynamic_table()), this)); } @@ -922,6 +897,9 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF32-mips"; case ELF::EM_PPC: return "ELF32-ppc"; + case ELF::EM_SPARC: + case ELF::EM_SPARC32PLUS: + return "ELF32-sparc"; default: return "ELF32-unknown"; } @@ -937,6 +915,10 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF64-ppc64"; case ELF::EM_S390: return "ELF64-s390"; + case ELF::EM_SPARCV9: + return "ELF64-sparc"; + case ELF::EM_MIPS: + return "ELF64-mips"; default: return "ELF64-unknown"; } @@ -948,6 +930,7 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { template <class ELFT> unsigned ELFObjectFile<ELFT>::getArch() const { + bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader()->e_machine) { case ELF::EM_386: return Triple::x86; @@ -960,13 +943,25 @@ unsigned ELFObjectFile<ELFT>::getArch() const { case ELF::EM_HEXAGON: return Triple::hexagon; case ELF::EM_MIPS: - return (ELFT::TargetEndianness == support::little) ? Triple::mipsel - : Triple::mips; + switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { + case ELF::ELFCLASS32: + return IsLittleEndian ? Triple::mipsel : Triple::mips; + case ELF::ELFCLASS64: + return IsLittleEndian ? Triple::mips64el : Triple::mips64; + default: + report_fatal_error("Invalid ELFCLASS!"); + } case ELF::EM_PPC64: - return (ELFT::TargetEndianness == support::little) ? Triple::ppc64le - : Triple::ppc64; + return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; case ELF::EM_S390: return Triple::systemz; + + case ELF::EM_SPARC: + case ELF::EM_SPARC32PLUS: + return Triple::sparc; + case ELF::EM_SPARCV9: + return Triple::sparcv9; + default: return Triple::UnknownArch; } @@ -974,8 +969,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const { /// FIXME: Maybe we should have a base ElfObjectFile that is not a template /// and make these member functions? -static inline error_code getELFRelocationAddend(const RelocationRef R, - int64_t &Addend) { +inline std::error_code getELFRelocationAddend(const RelocationRef R, + int64_t &Addend) { const ObjectFile *Obj = R.getObjectFile(); DataRefImpl DRI = R.getRawDataRefImpl(); // Little-endian 32-bit @@ -997,12 +992,31 @@ static inline error_code getELFRelocationAddend(const RelocationRef R, llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); } +inline std::pair<symbol_iterator, symbol_iterator> +getELFDynamicSymbolIterators(SymbolicFile *Obj) { + if (const ELF32LEObjectFile *ELF = dyn_cast<ELF32LEObjectFile>(Obj)) + return std::make_pair(ELF->dynamic_symbol_begin(), + ELF->dynamic_symbol_end()); + if (const ELF64LEObjectFile *ELF = dyn_cast<ELF64LEObjectFile>(Obj)) + return std::make_pair(ELF->dynamic_symbol_begin(), + ELF->dynamic_symbol_end()); + if (const ELF32BEObjectFile *ELF = dyn_cast<ELF32BEObjectFile>(Obj)) + return std::make_pair(ELF->dynamic_symbol_begin(), + ELF->dynamic_symbol_end()); + if (const ELF64BEObjectFile *ELF = cast<ELF64BEObjectFile>(Obj)) + return std::make_pair(ELF->dynamic_symbol_begin(), + ELF->dynamic_symbol_end()); + + llvm_unreachable( + "Object passed to getELFDynamicSymbolIterators() is not ELF"); +} + /// This is a generic interface for retrieving GNU symbol version /// information from an ELFObjectFile. -static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, - const SymbolRef &Sym, - StringRef &Version, - bool &IsDefault) { +inline std::error_code GetELFSymbolVersion(const ObjectFile *Obj, + const SymbolRef &Sym, + StringRef &Version, + bool &IsDefault) { // Little-endian 32-bit if (const ELF32LEObjectFile *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) return ELFObj->getSymbolVersion(Sym, Version, IsDefault); diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index fca965f3dbf2..fc8cc9581655 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -16,7 +16,7 @@ #ifndef LLVM_OBJECT_ELFYAML_H #define LLVM_OBJECT_ELFYAML_H -#include "llvm/Object/YAML.h" +#include "llvm/MC/YAML.h" #include "llvm/Support/ELF.h" namespace llvm { @@ -37,10 +37,14 @@ LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) +// Just use 64, since it can hold 32-bit values too. +LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_REL) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV) // For now, hardcode 64 bits everywhere that 32 or 64 would be needed // since 64-bit can hold 32-bit values too. @@ -50,6 +54,7 @@ struct FileHeader { ELF_ELFOSABI OSABI; ELF_ET Type; ELF_EM Machine; + ELF_EF Flags; llvm::yaml::Hex64 Entry; }; struct Symbol { @@ -58,6 +63,7 @@ struct Symbol { StringRef Section; llvm::yaml::Hex64 Value; llvm::yaml::Hex64 Size; + ELF_STV Visibility; }; struct LocalGlobalWeakSymbols { std::vector<Symbol> Local; @@ -65,17 +71,42 @@ struct LocalGlobalWeakSymbols { std::vector<Symbol> Weak; }; struct Section { + enum class SectionKind { RawContent, Relocation }; + SectionKind Kind; StringRef Name; ELF_SHT Type; ELF_SHF Flags; llvm::yaml::Hex64 Address; - object::yaml::BinaryRef Content; StringRef Link; llvm::yaml::Hex64 AddressAlign; + Section(SectionKind Kind) : Kind(Kind) {} + virtual ~Section(); +}; +struct RawContentSection : Section { + yaml::BinaryRef Content; + llvm::yaml::Hex64 Size; + RawContentSection() : Section(SectionKind::RawContent) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::RawContent; + } +}; +struct Relocation { + llvm::yaml::Hex64 Offset; + int64_t Addend; + ELF_REL Type; + StringRef Symbol; +}; +struct RelocationSection : Section { + StringRef Info; + std::vector<Relocation> Relocations; + RelocationSection() : Section(SectionKind::Relocation) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::Relocation; + } }; struct Object { FileHeader Header; - std::vector<Section> Sections; + std::vector<std::unique_ptr<Section>> Sections; // Although in reality the symbols reside in a section, it is a lot // cleaner and nicer if we read them from the YAML as a separate // top-level key, which automatically ensures that invariants like there @@ -86,8 +117,9 @@ struct Object { } // end namespace ELFYAML } // end namespace llvm -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Section) +LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::ELFYAML::Section>) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Relocation) namespace llvm { namespace yaml { @@ -118,6 +150,11 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI> { }; template <> +struct ScalarBitSetTraits<ELFYAML::ELF_EF> { + static void bitset(IO &IO, ELFYAML::ELF_EF &Value); +}; + +template <> struct ScalarEnumerationTraits<ELFYAML::ELF_SHT> { static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value); }; @@ -133,6 +170,16 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_STT> { }; template <> +struct ScalarEnumerationTraits<ELFYAML::ELF_STV> { + static void enumeration(IO &IO, ELFYAML::ELF_STV &Value); +}; + +template <> +struct ScalarEnumerationTraits<ELFYAML::ELF_REL> { + static void enumeration(IO &IO, ELFYAML::ELF_REL &Value); +}; + +template <> struct MappingTraits<ELFYAML::FileHeader> { static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); }; @@ -147,9 +194,14 @@ struct MappingTraits<ELFYAML::LocalGlobalWeakSymbols> { static void mapping(IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols); }; +template <> struct MappingTraits<ELFYAML::Relocation> { + static void mapping(IO &IO, ELFYAML::Relocation &Rel); +}; + template <> -struct MappingTraits<ELFYAML::Section> { - static void mapping(IO &IO, ELFYAML::Section &Section); +struct MappingTraits<std::unique_ptr<ELFYAML::Section>> { + static void mapping(IO &IO, std::unique_ptr<ELFYAML::Section> &Section); + static StringRef validate(IO &io, std::unique_ptr<ELFYAML::Section> &Section); }; template <> diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index 8b0570b02f8b..701da1272cd5 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -14,38 +14,32 @@ #ifndef LLVM_OBJECT_ERROR_H #define LLVM_OBJECT_ERROR_H -#include "llvm/Support/system_error.h" +#include <system_error> namespace llvm { namespace object { -const error_category &object_category(); +const std::error_category &object_category(); -struct object_error { - enum Impl { - success = 0, - arch_not_found, - invalid_file_type, - parse_failed, - unexpected_eof - }; - Impl V; - - object_error(Impl V) : V(V) {} - operator Impl() const { return V; } +enum class object_error { + success = 0, + arch_not_found, + invalid_file_type, + parse_failed, + unexpected_eof }; -inline error_code make_error_code(object_error e) { - return error_code(static_cast<int>(e), object_category()); +inline std::error_code make_error_code(object_error e) { + return std::error_code(static_cast<int>(e), object_category()); } } // end namespace object. -template <> struct is_error_code_enum<object::object_error> : true_type { }; - -template <> struct is_error_code_enum<object::object_error::Impl> : true_type { -}; - } // end namespace llvm. +namespace std { +template <> +struct is_error_code_enum<llvm::object::object_error> : std::true_type {}; +} + #endif diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h new file mode 100644 index 000000000000..b33cc263b9bd --- /dev/null +++ b/include/llvm/Object/IRObjectFile.h @@ -0,0 +1,59 @@ +//===- IRObjectFile.h - LLVM IR object file implementation ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the IRObjectFile template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_IR_OBJECT_FILE_H +#define LLVM_OBJECT_IR_OBJECT_FILE_H + +#include "llvm/Object/SymbolicFile.h" + +namespace llvm { +class Mangler; +class Module; +class GlobalValue; + +namespace object { +class IRObjectFile : public SymbolicFile { + std::unique_ptr<Module> M; + std::unique_ptr<Mangler> Mang; + std::vector<std::pair<std::string, uint32_t>> AsmSymbols; + +public: + IRObjectFile(std::unique_ptr<MemoryBuffer> Object, std::unique_ptr<Module> M); + ~IRObjectFile(); + void moveSymbolNext(DataRefImpl &Symb) const override; + std::error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + const GlobalValue *getSymbolGV(DataRefImpl Symb) const; + basic_symbol_iterator symbol_begin_impl() const override; + basic_symbol_iterator symbol_end_impl() const override; + + const Module &getModule() const { + return const_cast<IRObjectFile*>(this)->getModule(); + } + Module &getModule() { + return *M; + } + + static inline bool classof(const Binary *v) { + return v->isIR(); + } + + static ErrorOr<IRObjectFile *> + createIRObjectFile(std::unique_ptr<MemoryBuffer> Object, + LLVMContext &Context); +}; +} +} + +#endif diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 100613ac8ccb..4835eb80bd65 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -31,18 +31,18 @@ class DiceRef { const ObjectFile *OwningObject; public: - DiceRef() : OwningObject(NULL) { } + DiceRef() : OwningObject(nullptr) { } DiceRef(DataRefImpl DiceP, const ObjectFile *Owner); bool operator==(const DiceRef &Other) const; bool operator<(const DiceRef &Other) const; - error_code getNext(DiceRef &Result) const; + void moveNext(); - error_code getOffset(uint32_t &Result) const; - error_code getLength(uint16_t &Result) const; - error_code getKind(uint16_t &Result) const; + std::error_code getOffset(uint32_t &Result) const; + std::error_code getLength(uint16_t &Result) const; + std::error_code getKind(uint16_t &Result) const; DataRefImpl getRawDataRefImpl() const; const ObjectFile *getObjectFile() const; @@ -56,77 +56,97 @@ public: MachO::load_command C; // The command itself. }; - MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, - error_code &ec); - - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const; - virtual relocation_iterator section_rel_end(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; - virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const; - virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; - virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; - - virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; - virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; + MachOObjectFile(std::unique_ptr<MemoryBuffer> Object, bool IsLittleEndian, + bool Is64Bits, std::error_code &EC); + + void moveSymbolNext(DataRefImpl &Symb) const override; + std::error_code getSymbolName(DataRefImpl Symb, + StringRef &Res) const override; + + // MachO specific. + std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; + + std::error_code getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const override; + std::error_code getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const override; + std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + std::error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + std::error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; + + void moveSectionNext(DataRefImpl &Sec) const override; + std::error_code getSectionName(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + std::error_code getSectionContents(DataRefImpl Sec, + StringRef &Res) const override; + std::error_code getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const override; + std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + std::error_code isSectionReadOnlyData(DataRefImpl Sec, + bool &Res) const override; + std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const override; + relocation_iterator section_rel_begin(DataRefImpl Sec) const override; + relocation_iterator section_rel_end(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + std::error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + std::error_code getRelocationType(DataRefImpl Rel, + uint64_t &Res) const override; + std::error_code + getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + std::error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + std::error_code getRelocationHidden(DataRefImpl Rel, + bool &Result) const override; + + std::error_code getLibraryNext(DataRefImpl LibData, + LibraryRef &Res) const override; + std::error_code getLibraryPath(DataRefImpl LibData, + StringRef &Res) const override; + + // MachO specific. + std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &Res); // TODO: Would be useful to have an iterator based version // of the load command interface too. - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; + basic_symbol_iterator symbol_begin_impl() const override; + basic_symbol_iterator symbol_end_impl() const override; - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; + // MachO specific. + basic_symbol_iterator getSymbolByIndex(unsigned Index) const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; + section_iterator section_begin() const override; + section_iterator section_end() const override; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; + library_iterator needed_library_begin() const override; + library_iterator needed_library_end() const override; - virtual uint8_t getBytesInAddress() const; + uint8_t getBytesInAddress() const override; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; + StringRef getFileFormatName() const override; + unsigned getArch() const override; - virtual StringRef getLoadName() const; + StringRef getLoadName() const override; relocation_iterator section_rel_begin(unsigned Index) const; relocation_iterator section_rel_end(unsigned Index) const; @@ -179,6 +199,10 @@ public: getSegment64LoadCommand(const LoadCommandInfo &L) const; MachO::linker_options_command getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; + MachO::version_min_command + getVersionMinLoadCommand(const LoadCommandInfo &L) const; + MachO::dylib_command + getDylibIDLoadCommand(const LoadCommandInfo &L) const; MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; MachO::data_in_code_entry getDice(DataRefImpl Rel) const; @@ -197,7 +221,13 @@ public: bool is64Bit() const; void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; + static StringRef guessLibraryShortName(StringRef Name, bool &isFramework, + StringRef &Suffix); + static Triple::ArchType getArch(uint32_t CPUType); + static Triple getArch(uint32_t CPUType, uint32_t CPUSubType); + static Triple getArch(StringRef ArchFlag); + static Triple getHostArch(); static bool classof(const Binary *v) { return v->isMachO(); @@ -206,6 +236,10 @@ public: private: typedef SmallVector<const char*, 1> SectionList; SectionList Sections; + typedef SmallVector<const char*, 1> LibraryList; + LibraryList Libraries; + typedef SmallVector<StringRef, 1> LibraryShortName; + LibraryShortName LibrariesShortNames; const char *SymtabLoadCmd; const char *DysymtabLoadCmd; const char *DataInCodeLoadCmd; @@ -223,20 +257,17 @@ inline bool DiceRef::operator<(const DiceRef &Other) const { return DicePimpl < Other.DicePimpl; } -inline error_code DiceRef::getNext(DiceRef &Result) const { - DataRefImpl Rel = DicePimpl; +inline void DiceRef::moveNext() { const MachO::data_in_code_entry *P = - reinterpret_cast<const MachO::data_in_code_entry *>(Rel.p); - Rel.p = reinterpret_cast<uintptr_t>(P + 1); - Result = DiceRef(Rel, OwningObject); - return object_error::success; + reinterpret_cast<const MachO::data_in_code_entry *>(DicePimpl.p); + DicePimpl.p = reinterpret_cast<uintptr_t>(P + 1); } // Since a Mach-O data in code reference, a DiceRef, can only be created when // the OwningObject ObjectFile is a MachOObjectFile a static_cast<> is used for // the methods that get the values of the fields of the reference. -inline error_code DiceRef::getOffset(uint32_t &Result) const { +inline std::error_code DiceRef::getOffset(uint32_t &Result) const { const MachOObjectFile *MachOOF = static_cast<const MachOObjectFile *>(OwningObject); MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); @@ -244,7 +275,7 @@ inline error_code DiceRef::getOffset(uint32_t &Result) const { return object_error::success; } -inline error_code DiceRef::getLength(uint16_t &Result) const { +inline std::error_code DiceRef::getLength(uint16_t &Result) const { const MachOObjectFile *MachOOF = static_cast<const MachOObjectFile *>(OwningObject); MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); @@ -252,7 +283,7 @@ inline error_code DiceRef::getLength(uint16_t &Result) const { return object_error::success; } -inline error_code DiceRef::getKind(uint16_t &Result) const { +inline std::error_code DiceRef::getKind(uint16_t &Result) const { const MachOObjectFile *MachOOF = static_cast<const MachOObjectFile *>(OwningObject); MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl); diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index c5d1359256b0..e6677f5bf28b 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -14,10 +14,12 @@ #ifndef LLVM_OBJECT_MACHOUNIVERSAL_H #define LLVM_OBJECT_MACHOUNIVERSAL_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/Binary.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/MachO.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/MachO.h" namespace llvm { @@ -41,7 +43,7 @@ public: ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index); void clear() { - Parent = 0; + Parent = nullptr; Index = 0; } @@ -51,8 +53,14 @@ public: ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } uint32_t getCPUType() const { return Header.cputype; } + std::string getArchTypeName() const { + Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype); + return T.getArchName(); + } + + ErrorOr<std::unique_ptr<ObjectFile>> getAsObjectFile() const; - error_code getAsObjectFile(OwningPtr<ObjectFile> &Result) const; + std::error_code getAsArchive(std::unique_ptr<Archive> &Result) const; }; class object_iterator { @@ -76,13 +84,16 @@ public: } }; - MachOUniversalBinary(MemoryBuffer *Source, error_code &ec); + MachOUniversalBinary(std::unique_ptr<MemoryBuffer> Source, + std::error_code &ec); + static ErrorOr<MachOUniversalBinary *> + create(std::unique_ptr<MemoryBuffer> Source); object_iterator begin_objects() const { return ObjectForArch(this, 0); } object_iterator end_objects() const { - return ObjectForArch(0, 0); + return ObjectForArch(nullptr, 0); } uint32_t getNumberOfObjects() const { return NumberOfObjects; } @@ -92,8 +103,8 @@ public: return V->isMachOUniversalBinary(); } - error_code getObjectForArch(Triple::ArchType Arch, - OwningPtr<ObjectFile> &Result) const; + ErrorOr<std::unique_ptr<ObjectFile>> + getObjectForArch(Triple::ArchType Arch) const; }; } diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 9aea639ef058..a4370a3f30d0 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -15,9 +15,10 @@ #define LLVM_OBJECT_OBJECTFILE_H #include "llvm/ADT/StringRef.h" -#include "llvm/Object/Binary.h" +#include "llvm/Object/SymbolicFile.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include <cstring> #include <vector> @@ -27,65 +28,8 @@ namespace object { class ObjectFile; -union DataRefImpl { - // This entire union should probably be a - // char[max(8, sizeof(uintptr_t))] and require the impl to cast. - struct { - uint32_t a, b; - } d; - uintptr_t p; - DataRefImpl() { - std::memset(this, 0, sizeof(DataRefImpl)); - } -}; - -template<class content_type> -class content_iterator { - content_type Current; -public: - content_iterator(content_type symb) - : Current(symb) {} - - const content_type* operator->() const { - return &Current; - } - - const content_type &operator*() const { - return Current; - } - - bool operator==(const content_iterator &other) const { - return Current == other.Current; - } - - bool operator!=(const content_iterator &other) const { - return !(*this == other); - } - - content_iterator& increment(error_code &err) { - content_type next; - if (error_code ec = Current.getNext(next)) - err = ec; - else - Current = next; - return *this; - } -}; - -inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { - // Check bitwise identical. This is the only legal way to compare a union w/o - // knowing which member is in use. - return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; -} - -inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { - // Check bitwise identical. This is the only legal way to compare a union w/o - // knowing which member is in use. - return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; -} - class SymbolRef; -typedef content_iterator<SymbolRef> symbol_iterator; +class symbol_iterator; /// RelocationRef - This is a value type class that represents a single /// relocation in the list of relocations in the object file. @@ -94,34 +38,34 @@ class RelocationRef { const ObjectFile *OwningObject; public: - RelocationRef() : OwningObject(NULL) { } + RelocationRef() : OwningObject(nullptr) { } RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner); bool operator==(const RelocationRef &Other) const; - error_code getNext(RelocationRef &Result) const; + void moveNext(); - error_code getAddress(uint64_t &Result) const; - error_code getOffset(uint64_t &Result) const; + std::error_code getAddress(uint64_t &Result) const; + std::error_code getOffset(uint64_t &Result) const; symbol_iterator getSymbol() const; - error_code getType(uint64_t &Result) const; + std::error_code getType(uint64_t &Result) const; /// @brief Indicates whether this relocation should hidden when listing /// relocations, usually because it is the trailing part of a multipart /// relocation that will be printed as part of the leading relocation. - error_code getHidden(bool &Result) const; + std::error_code getHidden(bool &Result) const; /// @brief Get a string that represents the type of this relocation. /// /// This is for display purposes only. - error_code getTypeName(SmallVectorImpl<char> &Result) const; + std::error_code getTypeName(SmallVectorImpl<char> &Result) const; /// @brief Get a string that represents the calculation of the value of this /// relocation. /// /// This is for display purposes only. - error_code getValueString(SmallVectorImpl<char> &Result) const; + std::error_code getValueString(SmallVectorImpl<char> &Result) const; DataRefImpl getRawDataRefImpl() const; const ObjectFile *getObjectFile() const; @@ -138,36 +82,41 @@ class SectionRef { const ObjectFile *OwningObject; public: - SectionRef() : OwningObject(NULL) { } + SectionRef() : OwningObject(nullptr) { } SectionRef(DataRefImpl SectionP, const ObjectFile *Owner); bool operator==(const SectionRef &Other) const; + bool operator!=(const SectionRef &Other) const; bool operator<(const SectionRef &Other) const; - error_code getNext(SectionRef &Result) const; + void moveNext(); - error_code getName(StringRef &Result) const; - error_code getAddress(uint64_t &Result) const; - error_code getSize(uint64_t &Result) const; - error_code getContents(StringRef &Result) const; + std::error_code getName(StringRef &Result) const; + std::error_code getAddress(uint64_t &Result) const; + std::error_code getSize(uint64_t &Result) const; + std::error_code getContents(StringRef &Result) const; /// @brief Get the alignment of this section as the actual value (not log 2). - error_code getAlignment(uint64_t &Result) const; + std::error_code getAlignment(uint64_t &Result) const; // FIXME: Move to the normalization layer when it's created. - error_code isText(bool &Result) const; - error_code isData(bool &Result) const; - error_code isBSS(bool &Result) const; - error_code isRequiredForExecution(bool &Result) const; - error_code isVirtual(bool &Result) const; - error_code isZeroInit(bool &Result) const; - error_code isReadOnlyData(bool &Result) const; - - error_code containsSymbol(SymbolRef S, bool &Result) const; - - relocation_iterator begin_relocations() const; - relocation_iterator end_relocations() const; + std::error_code isText(bool &Result) const; + std::error_code isData(bool &Result) const; + std::error_code isBSS(bool &Result) const; + std::error_code isRequiredForExecution(bool &Result) const; + std::error_code isVirtual(bool &Result) const; + std::error_code isZeroInit(bool &Result) const; + std::error_code isReadOnlyData(bool &Result) const; + + std::error_code containsSymbol(SymbolRef S, bool &Result) const; + + relocation_iterator relocation_begin() const; + relocation_iterator relocation_end() const; + iterator_range<relocation_iterator> relocations() const { + return iterator_range<relocation_iterator>(relocation_begin(), + relocation_end()); + } section_iterator getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; @@ -175,13 +124,11 @@ public: /// SymbolRef - This is a value type class that represents a single symbol in /// the list of symbols in the object file. -class SymbolRef { +class SymbolRef : public BasicSymbolRef { friend class SectionRef; - DataRefImpl SymbolPimpl; - const ObjectFile *OwningObject; public: - SymbolRef() : OwningObject(NULL) { } + SymbolRef() : BasicSymbolRef() {} enum Type { ST_Unknown, // Type not specified @@ -192,46 +139,41 @@ public: ST_Other }; - enum Flags LLVM_ENUM_INT_TYPE(unsigned) { - SF_None = 0, - SF_Undefined = 1U << 0, // Symbol is defined in another object file - SF_Global = 1U << 1, // Global symbol - SF_Weak = 1U << 2, // Weak symbol - SF_Absolute = 1U << 3, // Absolute symbol - SF_ThreadLocal = 1U << 4, // Thread local symbol - SF_Common = 1U << 5, // Symbol has common linkage - SF_FormatSpecific = 1U << 31 // Specific to the object file format - // (e.g. section symbols) - }; - SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); - bool operator==(const SymbolRef &Other) const; - bool operator<(const SymbolRef &Other) const; - - error_code getNext(SymbolRef &Result) const; - - error_code getName(StringRef &Result) const; + std::error_code getName(StringRef &Result) const; /// Returns the symbol virtual address (i.e. address at which it will be /// mapped). - error_code getAddress(uint64_t &Result) const; - error_code getFileOffset(uint64_t &Result) const; + std::error_code getAddress(uint64_t &Result) const; /// @brief Get the alignment of this symbol as the actual value (not log 2). - error_code getAlignment(uint32_t &Result) const; - error_code getSize(uint64_t &Result) const; - error_code getType(SymbolRef::Type &Result) const; - - /// Get symbol flags (bitwise OR of SymbolRef::Flags) - error_code getFlags(uint32_t &Result) const; + std::error_code getAlignment(uint32_t &Result) const; + std::error_code getSize(uint64_t &Result) const; + std::error_code getType(SymbolRef::Type &Result) const; + std::error_code getOther(uint8_t &Result) const; /// @brief Get section this symbol is defined in reference to. Result is /// end_sections() if it is undefined or is an absolute symbol. - error_code getSection(section_iterator &Result) const; + std::error_code getSection(section_iterator &Result) const; - /// @brief Get value of the symbol in the symbol table. - error_code getValue(uint64_t &Val) const; + const ObjectFile *getObject() const; +}; - DataRefImpl getRawDataRefImpl() const; +class symbol_iterator : public basic_symbol_iterator { +public: + symbol_iterator(SymbolRef Sym) : basic_symbol_iterator(Sym) {} + symbol_iterator(const basic_symbol_iterator &B) + : basic_symbol_iterator(SymbolRef(B->getRawDataRefImpl(), + cast<ObjectFile>(B->getObject()))) {} + + const SymbolRef *operator->() const { + const BasicSymbolRef &P = basic_symbol_iterator::operator *(); + return static_cast<const SymbolRef*>(&P); + } + + const SymbolRef &operator*() const { + const BasicSymbolRef &P = basic_symbol_iterator::operator *(); + return static_cast<const SymbolRef&>(P); + } }; /// LibraryRef - This is a value type class that represents a single library in @@ -242,34 +184,32 @@ class LibraryRef { const ObjectFile *OwningObject; public: - LibraryRef() : OwningObject(NULL) { } + LibraryRef() : OwningObject(nullptr) { } LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner); bool operator==(const LibraryRef &Other) const; bool operator<(const LibraryRef &Other) const; - error_code getNext(LibraryRef &Result) const; + std::error_code getNext(LibraryRef &Result) const; // Get the path to this library, as stored in the object file. - error_code getPath(StringRef &Result) const; + std::error_code getPath(StringRef &Result) const; DataRefImpl getRawDataRefImpl() const; }; typedef content_iterator<LibraryRef> library_iterator; -const uint64_t UnknownAddressOrSize = ~0ULL; - /// ObjectFile - This class is the base class for all object file types. /// Concrete instances of this object are created by createObjectFile, which /// figures out which type to create. -class ObjectFile : public Binary { +class ObjectFile : public SymbolicFile { virtual void anchor(); ObjectFile() LLVM_DELETED_FUNCTION; ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; protected: - ObjectFile(unsigned int Type, MemoryBuffer *source); + ObjectFile(unsigned int Type, std::unique_ptr<MemoryBuffer> Source); const uint8_t *base() const { return reinterpret_cast<const uint8_t *>(Data->getBufferStart()); @@ -284,81 +224,102 @@ protected: // Implementations assume that the DataRefImpl is valid and has not been // modified externally. It's UB otherwise. friend class SymbolRef; - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const = 0; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const = 0; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res)const=0; - virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; - virtual error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const = 0; - virtual error_code getSymbolFlags(DataRefImpl Symb, - uint32_t &Res) const = 0; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const = 0; - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const = 0; + virtual std::error_code getSymbolName(DataRefImpl Symb, + StringRef &Res) const = 0; + std::error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const override; + virtual std::error_code getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const = 0; + virtual std::error_code getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const; + virtual std::error_code getSymbolSize(DataRefImpl Symb, + uint64_t &Res) const = 0; + virtual std::error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const = 0; + virtual std::error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const = 0; + virtual std::error_code getSymbolOther(DataRefImpl Symb, + uint8_t &Res) const { + return object_error::invalid_file_type; + } // Same as above for SectionRef. friend class SectionRef; - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const = 0; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const =0; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const = 0; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res)const=0; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res)const=0; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const = 0; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const = 0; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const = 0; + virtual void moveSectionNext(DataRefImpl &Sec) const = 0; + virtual std::error_code getSectionName(DataRefImpl Sec, + StringRef &Res) const = 0; + virtual std::error_code getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const = 0; + virtual std::error_code getSectionSize(DataRefImpl Sec, + uint64_t &Res) const = 0; + virtual std::error_code getSectionContents(DataRefImpl Sec, + StringRef &Res) const = 0; + virtual std::error_code getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const = 0; + virtual std::error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; + virtual std::error_code isSectionData(DataRefImpl Sec, bool &Res) const = 0; + virtual std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const = 0; + virtual std::error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const = 0; // A section is 'virtual' if its contents aren't present in the object image. - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const = 0; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const = 0; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const =0; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const = 0; + virtual std::error_code isSectionVirtual(DataRefImpl Sec, + bool &Res) const = 0; + virtual std::error_code isSectionZeroInit(DataRefImpl Sec, + bool &Res) const = 0; + virtual std::error_code isSectionReadOnlyData(DataRefImpl Sec, + bool &Res) const = 0; + virtual std::error_code sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const = 0; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; // Same as above for RelocationRef. friend class RelocationRef; - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const = 0; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const =0; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const =0; + virtual void moveRelocationNext(DataRefImpl &Rel) const = 0; + virtual std::error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const = 0; + virtual std::error_code getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const = 0; virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const = 0; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const = 0; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const = 0; - virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const { + virtual std::error_code getRelocationType(DataRefImpl Rel, + uint64_t &Res) const = 0; + virtual std::error_code + getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const = 0; + virtual std::error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const = 0; + virtual std::error_code getRelocationHidden(DataRefImpl Rel, + bool &Result) const { Result = false; return object_error::success; } // Same for LibraryRef friend class LibraryRef; - virtual error_code getLibraryNext(DataRefImpl Lib, LibraryRef &Res) const = 0; - virtual error_code getLibraryPath(DataRefImpl Lib, StringRef &Res) const = 0; + virtual std::error_code getLibraryNext(DataRefImpl Lib, + LibraryRef &Res) const = 0; + virtual std::error_code getLibraryPath(DataRefImpl Lib, + StringRef &Res) const = 0; public: + typedef iterator_range<symbol_iterator> symbol_iterator_range; + symbol_iterator_range symbols() const { + return symbol_iterator_range(symbol_begin(), symbol_end()); + } - virtual symbol_iterator begin_symbols() const = 0; - virtual symbol_iterator end_symbols() const = 0; - - virtual symbol_iterator begin_dynamic_symbols() const = 0; - virtual symbol_iterator end_dynamic_symbols() const = 0; + virtual section_iterator section_begin() const = 0; + virtual section_iterator section_end() const = 0; - virtual section_iterator begin_sections() const = 0; - virtual section_iterator end_sections() const = 0; + typedef iterator_range<section_iterator> section_iterator_range; + section_iterator_range sections() const { + return section_iterator_range(section_begin(), section_end()); + } - virtual library_iterator begin_libraries_needed() const = 0; - virtual library_iterator end_libraries_needed() const = 0; + virtual library_iterator needed_library_begin() const = 0; + virtual library_iterator needed_library_end() const = 0; /// @brief The number of bytes used to represent an address in this object /// file format. @@ -372,78 +333,74 @@ public: /// LC_ID_DYLIB (install name) on MachO. virtual StringRef getLoadName() const = 0; + /// Returns platform-specific object flags, if any. + virtual std::error_code getPlatformFlags(unsigned &Result) const { + Result = 0; + return object_error::invalid_file_type; + } + /// @returns Pointer to ObjectFile subclass to handle this type of object. /// @param ObjectPath The path to the object file. ObjectPath.isObject must /// return true. /// @brief Create ObjectFile from path. - static ObjectFile *createObjectFile(StringRef ObjectPath); - static ObjectFile *createObjectFile(MemoryBuffer *Object); + static ErrorOr<ObjectFile *> createObjectFile(StringRef ObjectPath); + static ErrorOr<ObjectFile *> + createObjectFile(std::unique_ptr<MemoryBuffer> &Object, + sys::fs::file_magic Type); + static ErrorOr<ObjectFile *> + createObjectFile(std::unique_ptr<MemoryBuffer> &Object) { + return createObjectFile(Object, sys::fs::file_magic::unknown); + } + static inline bool classof(const Binary *v) { return v->isObject(); } public: - static ObjectFile *createCOFFObjectFile(MemoryBuffer *Object); - static ObjectFile *createELFObjectFile(MemoryBuffer *Object); - static ObjectFile *createMachOObjectFile(MemoryBuffer *Object); + static ErrorOr<ObjectFile *> + createCOFFObjectFile(std::unique_ptr<MemoryBuffer> Object); + static ErrorOr<ObjectFile *> + createELFObjectFile(std::unique_ptr<MemoryBuffer> &Object); + static ErrorOr<ObjectFile *> + createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Object); }; // Inline function definitions. inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) - : SymbolPimpl(SymbolP) - , OwningObject(Owner) {} - -inline bool SymbolRef::operator==(const SymbolRef &Other) const { - return SymbolPimpl == Other.SymbolPimpl; -} + : BasicSymbolRef(SymbolP, Owner) {} -inline bool SymbolRef::operator<(const SymbolRef &Other) const { - return SymbolPimpl < Other.SymbolPimpl; +inline std::error_code SymbolRef::getName(StringRef &Result) const { + return getObject()->getSymbolName(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getNext(SymbolRef &Result) const { - return OwningObject->getSymbolNext(SymbolPimpl, Result); +inline std::error_code SymbolRef::getAddress(uint64_t &Result) const { + return getObject()->getSymbolAddress(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getName(StringRef &Result) const { - return OwningObject->getSymbolName(SymbolPimpl, Result); +inline std::error_code SymbolRef::getAlignment(uint32_t &Result) const { + return getObject()->getSymbolAlignment(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getAddress(uint64_t &Result) const { - return OwningObject->getSymbolAddress(SymbolPimpl, Result); +inline std::error_code SymbolRef::getSize(uint64_t &Result) const { + return getObject()->getSymbolSize(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getFileOffset(uint64_t &Result) const { - return OwningObject->getSymbolFileOffset(SymbolPimpl, Result); +inline std::error_code SymbolRef::getSection(section_iterator &Result) const { + return getObject()->getSymbolSection(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getAlignment(uint32_t &Result) const { - return OwningObject->getSymbolAlignment(SymbolPimpl, Result); +inline std::error_code SymbolRef::getType(SymbolRef::Type &Result) const { + return getObject()->getSymbolType(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getSize(uint64_t &Result) const { - return OwningObject->getSymbolSize(SymbolPimpl, Result); +inline std::error_code SymbolRef::getOther(uint8_t &Result) const { + return getObject()->getSymbolOther(getRawDataRefImpl(), Result); } -inline error_code SymbolRef::getFlags(uint32_t &Result) const { - return OwningObject->getSymbolFlags(SymbolPimpl, Result); -} - -inline error_code SymbolRef::getSection(section_iterator &Result) const { - return OwningObject->getSymbolSection(SymbolPimpl, Result); -} - -inline error_code SymbolRef::getType(SymbolRef::Type &Result) const { - return OwningObject->getSymbolType(SymbolPimpl, Result); -} - -inline error_code SymbolRef::getValue(uint64_t &Val) const { - return OwningObject->getSymbolValue(SymbolPimpl, Val); -} - -inline DataRefImpl SymbolRef::getRawDataRefImpl() const { - return SymbolPimpl; +inline const ObjectFile *SymbolRef::getObject() const { + const SymbolicFile *O = BasicSymbolRef::getObject(); + return cast<ObjectFile>(O); } @@ -457,72 +414,77 @@ inline bool SectionRef::operator==(const SectionRef &Other) const { return SectionPimpl == Other.SectionPimpl; } +inline bool SectionRef::operator!=(const SectionRef &Other) const { + return SectionPimpl != Other.SectionPimpl; +} + inline bool SectionRef::operator<(const SectionRef &Other) const { return SectionPimpl < Other.SectionPimpl; } -inline error_code SectionRef::getNext(SectionRef &Result) const { - return OwningObject->getSectionNext(SectionPimpl, Result); +inline void SectionRef::moveNext() { + return OwningObject->moveSectionNext(SectionPimpl); } -inline error_code SectionRef::getName(StringRef &Result) const { +inline std::error_code SectionRef::getName(StringRef &Result) const { return OwningObject->getSectionName(SectionPimpl, Result); } -inline error_code SectionRef::getAddress(uint64_t &Result) const { +inline std::error_code SectionRef::getAddress(uint64_t &Result) const { return OwningObject->getSectionAddress(SectionPimpl, Result); } -inline error_code SectionRef::getSize(uint64_t &Result) const { +inline std::error_code SectionRef::getSize(uint64_t &Result) const { return OwningObject->getSectionSize(SectionPimpl, Result); } -inline error_code SectionRef::getContents(StringRef &Result) const { +inline std::error_code SectionRef::getContents(StringRef &Result) const { return OwningObject->getSectionContents(SectionPimpl, Result); } -inline error_code SectionRef::getAlignment(uint64_t &Result) const { +inline std::error_code SectionRef::getAlignment(uint64_t &Result) const { return OwningObject->getSectionAlignment(SectionPimpl, Result); } -inline error_code SectionRef::isText(bool &Result) const { +inline std::error_code SectionRef::isText(bool &Result) const { return OwningObject->isSectionText(SectionPimpl, Result); } -inline error_code SectionRef::isData(bool &Result) const { +inline std::error_code SectionRef::isData(bool &Result) const { return OwningObject->isSectionData(SectionPimpl, Result); } -inline error_code SectionRef::isBSS(bool &Result) const { +inline std::error_code SectionRef::isBSS(bool &Result) const { return OwningObject->isSectionBSS(SectionPimpl, Result); } -inline error_code SectionRef::isRequiredForExecution(bool &Result) const { +inline std::error_code SectionRef::isRequiredForExecution(bool &Result) const { return OwningObject->isSectionRequiredForExecution(SectionPimpl, Result); } -inline error_code SectionRef::isVirtual(bool &Result) const { +inline std::error_code SectionRef::isVirtual(bool &Result) const { return OwningObject->isSectionVirtual(SectionPimpl, Result); } -inline error_code SectionRef::isZeroInit(bool &Result) const { +inline std::error_code SectionRef::isZeroInit(bool &Result) const { return OwningObject->isSectionZeroInit(SectionPimpl, Result); } -inline error_code SectionRef::isReadOnlyData(bool &Result) const { +inline std::error_code SectionRef::isReadOnlyData(bool &Result) const { return OwningObject->isSectionReadOnlyData(SectionPimpl, Result); } -inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { - return OwningObject->sectionContainsSymbol(SectionPimpl, S.SymbolPimpl, - Result); +inline std::error_code SectionRef::containsSymbol(SymbolRef S, + bool &Result) const { + return OwningObject->sectionContainsSymbol(SectionPimpl, + S.getRawDataRefImpl(), Result); } -inline relocation_iterator SectionRef::begin_relocations() const { +inline relocation_iterator SectionRef::relocation_begin() const { return OwningObject->section_rel_begin(SectionPimpl); } -inline relocation_iterator SectionRef::end_relocations() const { +inline relocation_iterator SectionRef::relocation_end() const { return OwningObject->section_rel_end(SectionPimpl); } @@ -544,15 +506,15 @@ inline bool RelocationRef::operator==(const RelocationRef &Other) const { return RelocationPimpl == Other.RelocationPimpl; } -inline error_code RelocationRef::getNext(RelocationRef &Result) const { - return OwningObject->getRelocationNext(RelocationPimpl, Result); +inline void RelocationRef::moveNext() { + return OwningObject->moveRelocationNext(RelocationPimpl); } -inline error_code RelocationRef::getAddress(uint64_t &Result) const { +inline std::error_code RelocationRef::getAddress(uint64_t &Result) const { return OwningObject->getRelocationAddress(RelocationPimpl, Result); } -inline error_code RelocationRef::getOffset(uint64_t &Result) const { +inline std::error_code RelocationRef::getOffset(uint64_t &Result) const { return OwningObject->getRelocationOffset(RelocationPimpl, Result); } @@ -560,21 +522,21 @@ inline symbol_iterator RelocationRef::getSymbol() const { return OwningObject->getRelocationSymbol(RelocationPimpl); } -inline error_code RelocationRef::getType(uint64_t &Result) const { +inline std::error_code RelocationRef::getType(uint64_t &Result) const { return OwningObject->getRelocationType(RelocationPimpl, Result); } -inline error_code RelocationRef::getTypeName(SmallVectorImpl<char> &Result) - const { +inline std::error_code +RelocationRef::getTypeName(SmallVectorImpl<char> &Result) const { return OwningObject->getRelocationTypeName(RelocationPimpl, Result); } -inline error_code RelocationRef::getValueString(SmallVectorImpl<char> &Result) - const { +inline std::error_code +RelocationRef::getValueString(SmallVectorImpl<char> &Result) const { return OwningObject->getRelocationValueString(RelocationPimpl, Result); } -inline error_code RelocationRef::getHidden(bool &Result) const { +inline std::error_code RelocationRef::getHidden(bool &Result) const { return OwningObject->getRelocationHidden(RelocationPimpl, Result); } @@ -599,11 +561,11 @@ inline bool LibraryRef::operator<(const LibraryRef &Other) const { return LibraryPimpl < Other.LibraryPimpl; } -inline error_code LibraryRef::getNext(LibraryRef &Result) const { +inline std::error_code LibraryRef::getNext(LibraryRef &Result) const { return OwningObject->getLibraryNext(LibraryPimpl, Result); } -inline error_code LibraryRef::getPath(StringRef &Result) const { +inline std::error_code LibraryRef::getPath(StringRef &Result) const { return OwningObject->getLibraryPath(LibraryPimpl, Result); } diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 97912fe52d81..5ca245057a55 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -17,8 +17,8 @@ #define LLVM_OBJECT_RELOCVISITOR_H #include "llvm/ADT/StringRef.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" @@ -33,7 +33,6 @@ struct RelocToApply { // The width of the value; how many bytes to touch when applying the // relocation. char Width; - RelocToApply(const RelocToApply &In) : Value(In.Value), Width(In.Width) {} RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {} RelocToApply() : Value(0), Width(0) {} }; @@ -103,6 +102,16 @@ public: HasError = true; return RelocToApply(); } + } else if (FileFormat == "ELF64-mips") { + switch (RelocType) { + case llvm::ELF::R_MIPS_32: + return visitELF_MIPS_32(R, Value); + case llvm::ELF::R_MIPS_64: + return visitELF_MIPS_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } } else if (FileFormat == "ELF64-aarch64") { switch (RelocType) { case llvm::ELF::R_AARCH64_ABS32: @@ -123,6 +132,35 @@ public: HasError = true; return RelocToApply(); } + } else if (FileFormat == "ELF32-sparc") { + switch (RelocType) { + case llvm::ELF::R_SPARC_32: + case llvm::ELF::R_SPARC_UA32: + return visitELF_SPARC_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } + } else if (FileFormat == "ELF64-sparc") { + switch (RelocType) { + case llvm::ELF::R_SPARC_32: + case llvm::ELF::R_SPARC_UA32: + return visitELF_SPARCV9_32(R, Value); + case llvm::ELF::R_SPARC_64: + case llvm::ELF::R_SPARC_UA64: + return visitELF_SPARCV9_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + } else if (FileFormat == "ELF32-arm") { + switch (RelocType) { + default: + HasError = true; + return RelocToApply(); + case llvm::ELF::R_ARM_ABS32: + return visitELF_ARM_ABS32(R, Value); + } } HasError = true; return RelocToApply(); @@ -215,12 +253,14 @@ private: /// PPC64 ELF RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend; + getELFRelocationAddend(R, Addend); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend; + getELFRelocationAddend(R, Addend); return RelocToApply(Value + Addend, 8); } @@ -239,6 +279,13 @@ private: return RelocToApply(Res, 4); } + RelocToApply visitELF_MIPS_64(RelocationRef R, uint64_t Value) { + int64_t Addend; + getELFRelocationAddend(R, Addend); + uint64_t Res = (Value + Addend); + return RelocToApply(Res, 8); + } + // AArch64 ELF RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { int64_t Addend = getAddend64LE(R); @@ -272,6 +319,27 @@ private: int64_t Addend = getAddend64BE(R); return RelocToApply(Value + Addend, 8); } + + RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) { + int32_t Addend = getAddend32BE(R); + return RelocToApply(Value + Addend, 4); + } + + RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) { + int32_t Addend = getAddend64BE(R); + return RelocToApply(Value + Addend, 4); + } + + RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend64BE(R); + return RelocToApply(Value + Addend, 8); + } + + RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend32LE(R); + return RelocToApply(Value + Addend, 4); + } + }; } diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h new file mode 100644 index 000000000000..77eef4a546aa --- /dev/null +++ b/include/llvm/Object/SymbolicFile.h @@ -0,0 +1,195 @@ +//===- SymbolicFile.h - Interface that only provides symbols ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SymbolicFile interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_SYMBOLIC_FILE_H +#define LLVM_OBJECT_SYMBOLIC_FILE_H + +#include "llvm/Object/Binary.h" + +namespace llvm { +namespace object { + +union DataRefImpl { + // This entire union should probably be a + // char[max(8, sizeof(uintptr_t))] and require the impl to cast. + struct { + uint32_t a, b; + } d; + uintptr_t p; + DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); } +}; + +inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0; +} + +inline bool operator!=(const DataRefImpl &a, const DataRefImpl &b) { + return !operator==(a, b); +} + +inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) { + // Check bitwise identical. This is the only legal way to compare a union w/o + // knowing which member is in use. + return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0; +} + +template <class content_type> class content_iterator { + content_type Current; + +public: + content_iterator(content_type symb) : Current(symb) {} + + const content_type *operator->() const { return &Current; } + + const content_type &operator*() const { return Current; } + + bool operator==(const content_iterator &other) const { + return Current == other.Current; + } + + bool operator!=(const content_iterator &other) const { + return !(*this == other); + } + + content_iterator &operator++() { // preincrement + Current.moveNext(); + return *this; + } +}; + +class SymbolicFile; + +/// This is a value type class that represents a single symbol in the list of +/// symbols in the object file. +class BasicSymbolRef { + DataRefImpl SymbolPimpl; + const SymbolicFile *OwningObject; + +public: + // FIXME: should we add a SF_Text? + enum Flags : unsigned { + SF_None = 0, + SF_Undefined = 1U << 0, // Symbol is defined in another object file + SF_Global = 1U << 1, // Global symbol + SF_Weak = 1U << 2, // Weak symbol + SF_Absolute = 1U << 3, // Absolute symbol + SF_Common = 1U << 4, // Symbol has common linkage + SF_Indirect = 1U << 5, // Symbol is an alias to another symbol + SF_FormatSpecific = 1U << 6 // Specific to the object file format + // (e.g. section symbols) + }; + + BasicSymbolRef() : OwningObject(nullptr) { } + BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner); + + bool operator==(const BasicSymbolRef &Other) const; + bool operator<(const BasicSymbolRef &Other) const; + + void moveNext(); + + std::error_code printName(raw_ostream &OS) const; + + /// Get symbol flags (bitwise OR of SymbolRef::Flags) + uint32_t getFlags() const; + + DataRefImpl getRawDataRefImpl() const; + const SymbolicFile *getObject() const; +}; + +typedef content_iterator<BasicSymbolRef> basic_symbol_iterator; + +const uint64_t UnknownAddressOrSize = ~0ULL; + +class SymbolicFile : public Binary { +public: + virtual ~SymbolicFile(); + SymbolicFile(unsigned int Type, std::unique_ptr<MemoryBuffer> Source); + + // virtual interface. + virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; + + virtual std::error_code printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const = 0; + + virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0; + + virtual basic_symbol_iterator symbol_begin_impl() const = 0; + + virtual basic_symbol_iterator symbol_end_impl() const = 0; + + // convenience wrappers. + basic_symbol_iterator symbol_begin() const { + return symbol_begin_impl(); + } + basic_symbol_iterator symbol_end() const { + return symbol_end_impl(); + } + typedef iterator_range<basic_symbol_iterator> basic_symbol_iterator_range; + basic_symbol_iterator_range symbols() const { + return basic_symbol_iterator_range(symbol_begin(), symbol_end()); + } + + // construction aux. + static ErrorOr<SymbolicFile *> + createSymbolicFile(std::unique_ptr<MemoryBuffer> &Object, + sys::fs::file_magic Type, LLVMContext *Context); + + static ErrorOr<SymbolicFile *> + createSymbolicFile(std::unique_ptr<MemoryBuffer> &Object) { + return createSymbolicFile(Object, sys::fs::file_magic::unknown, nullptr); + } + static ErrorOr<SymbolicFile *> createSymbolicFile(StringRef ObjectPath); + + static inline bool classof(const Binary *v) { + return v->isSymbolic(); + } +}; + +inline BasicSymbolRef::BasicSymbolRef(DataRefImpl SymbolP, + const SymbolicFile *Owner) + : SymbolPimpl(SymbolP), OwningObject(Owner) {} + +inline bool BasicSymbolRef::operator==(const BasicSymbolRef &Other) const { + return SymbolPimpl == Other.SymbolPimpl; +} + +inline bool BasicSymbolRef::operator<(const BasicSymbolRef &Other) const { + return SymbolPimpl < Other.SymbolPimpl; +} + +inline void BasicSymbolRef::moveNext() { + return OwningObject->moveSymbolNext(SymbolPimpl); +} + +inline std::error_code BasicSymbolRef::printName(raw_ostream &OS) const { + return OwningObject->printSymbolName(OS, SymbolPimpl); +} + +inline uint32_t BasicSymbolRef::getFlags() const { + return OwningObject->getSymbolFlags(SymbolPimpl); +} + +inline DataRefImpl BasicSymbolRef::getRawDataRefImpl() const { + return SymbolPimpl; +} + +inline const SymbolicFile *BasicSymbolRef::getObject() const { + return OwningObject; +} + +} +} + +#endif diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h index 6b8ed3f7d2b1..dcaa5405ba7c 100644 --- a/include/llvm/Option/Arg.h +++ b/include/llvm/Option/Arg.h @@ -27,10 +27,7 @@ class ArgList; /// \brief A concrete instance of a particular driver option. /// /// The Arg class encodes just enough information to be able to -/// derive the argument values efficiently. In addition, Arg -/// instances have an intrusive double linked list which is used by -/// ArgList to provide efficient iteration over all instances of a -/// particular option. +/// derive the argument values efficiently. class Arg { Arg(const Arg &) LLVM_DELETED_FUNCTION; void operator=(const Arg &) LLVM_DELETED_FUNCTION; @@ -63,14 +60,14 @@ private: public: Arg(const Option Opt, StringRef Spelling, unsigned Index, - const Arg *BaseArg = 0); + const Arg *BaseArg = nullptr); Arg(const Option Opt, StringRef Spelling, unsigned Index, - const char *Value0, const Arg *BaseArg = 0); + const char *Value0, const Arg *BaseArg = nullptr); Arg(const Option Opt, StringRef Spelling, unsigned Index, - const char *Value0, const char *Value1, const Arg *BaseArg = 0); + const char *Value0, const char *Value1, const Arg *BaseArg = nullptr); ~Arg(); - const Option getOption() const { return Opt; } + const Option &getOption() const { return Opt; } StringRef getSpelling() const { return Spelling; } unsigned getIndex() const { return Index; } diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index 06ba679c2b55..d46b0e892faf 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -15,6 +15,7 @@ #include "llvm/Option/OptSpecifier.h" #include "llvm/Option/Option.h" #include <list> +#include <memory> #include <string> #include <vector> @@ -105,10 +106,14 @@ private: arglist_type Args; protected: - ArgList(); + // Default ctor provided explicitly as it is not provided implicitly due to + // the presence of the (deleted) copy ctor above. + ArgList() { } + // Virtual to provide a vtable anchor and because -Wnon-virtua-dtor warns, not + // because this type is ever actually destroyed polymorphically. + virtual ~ArgList(); public: - virtual ~ArgList(); /// @name Arg Access /// @{ @@ -145,6 +150,12 @@ public: return arg_iterator(Args.end(), *this); } + iterator_range<arg_iterator> filtered(OptSpecifier Id0 = 0U, + OptSpecifier Id1 = 0U, + OptSpecifier Id2 = 0U) const { + return make_range(filtered_begin(Id0, Id1, Id2), filtered_end()); + } + /// @} /// @name Arg Removal /// @{ @@ -160,16 +171,16 @@ public: /// /// \p Claim Whether the argument should be claimed, if it exists. bool hasArgNoClaim(OptSpecifier Id) const { - return getLastArgNoClaim(Id) != 0; + return getLastArgNoClaim(Id) != nullptr; } bool hasArg(OptSpecifier Id) const { - return getLastArg(Id) != 0; + return getLastArg(Id) != nullptr; } bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const { - return getLastArg(Id0, Id1) != 0; + return getLastArg(Id0, Id1) != nullptr; } bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const { - return getLastArg(Id0, Id1, Id2) != 0; + return getLastArg(Id0, Id1, Id2) != nullptr; } /// getLastArg - Return the last argument matching \p Id, or null. @@ -307,11 +318,11 @@ public: InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); ~InputArgList(); - virtual const char *getArgString(unsigned Index) const { + const char *getArgString(unsigned Index) const override { return ArgStrings[Index]; } - virtual unsigned getNumInputArgStrings() const { + unsigned getNumInputArgStrings() const override { return NumInputArgStrings; } @@ -323,7 +334,8 @@ public: unsigned MakeIndex(StringRef String0) const; unsigned MakeIndex(StringRef String0, StringRef String1) const; - virtual const char *MakeArgString(StringRef Str) const; + using ArgList::MakeArgString; + const char *MakeArgString(StringRef Str) const override; /// @} }; @@ -334,18 +346,18 @@ class DerivedArgList : public ArgList { const InputArgList &BaseArgs; /// The list of arguments we synthesized. - mutable arglist_type SynthesizedArgs; + mutable SmallVector<std::unique_ptr<Arg>, 16> SynthesizedArgs; public: /// Construct a new derived arg list from \p BaseArgs. DerivedArgList(const InputArgList &BaseArgs); ~DerivedArgList(); - virtual const char *getArgString(unsigned Index) const { + const char *getArgString(unsigned Index) const override { return BaseArgs.getArgString(Index); } - virtual unsigned getNumInputArgStrings() const { + unsigned getNumInputArgStrings() const override { return BaseArgs.getNumInputArgStrings(); } @@ -358,11 +370,10 @@ public: /// AddSynthesizedArg - Add a argument to the list of synthesized arguments /// (to be freed). - void AddSynthesizedArg(Arg *A) { - SynthesizedArgs.push_back(A); - } + void AddSynthesizedArg(Arg *A); - virtual const char *MakeArgString(StringRef Str) const; + using ArgList::MakeArgString; + const char *MakeArgString(StringRef Str) const override; /// AddFlagArg - Construct a new FlagArg for the given option \p Id and /// append it to the argument list. diff --git a/include/llvm/Option/OptParser.td b/include/llvm/Option/OptParser.td index 963389f0bc6f..dbf240d74805 100644 --- a/include/llvm/Option/OptParser.td +++ b/include/llvm/Option/OptParser.td @@ -75,6 +75,7 @@ class OptionGroup<string name> { string Name = name; string HelpText = ?; OptionGroup Group = ?; + list<OptionFlag> Flags = []; } // Define the option class. diff --git a/include/llvm/Option/OptSpecifier.h b/include/llvm/Option/OptSpecifier.h index 02bc6b175edb..b7caa6e85a7d 100644 --- a/include/llvm/Option/OptSpecifier.h +++ b/include/llvm/Option/OptSpecifier.h @@ -10,6 +10,8 @@ #ifndef LLVM_OPTION_OPTSPECIFIER_H #define LLVM_OPTION_OPTSPECIFIER_H +#include "llvm/Support/Compiler.h" + namespace llvm { namespace opt { class Option; diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h index 03d4774829fb..b2cfacbaf344 100644 --- a/include/llvm/Option/Option.h +++ b/include/llvm/Option/Option.h @@ -73,7 +73,7 @@ public: ~Option(); bool isValid() const { - return Info != 0; + return Info != nullptr; } unsigned getID() const { diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index 35ec022516a5..c2b9f95956e8 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -87,7 +87,8 @@ class Pass { Pass(const Pass &) LLVM_DELETED_FUNCTION; public: - explicit Pass(PassKind K, char &pid) : Resolver(0), PassID(&pid), Kind(K) { } + explicit Pass(PassKind K, char &pid) + : Resolver(nullptr), PassID(&pid), Kind(K) { } virtual ~Pass(); @@ -235,17 +236,17 @@ public: class ModulePass : public Pass { public: /// createPrinterPass - Get a module printer pass. - Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const override; /// runOnModule - Virtual method overriden by subclasses to process the module /// being operated on. virtual bool runOnModule(Module &M) = 0; - virtual void assignPassManager(PMStack &PMS, - PassManagerType T); + void assignPassManager(PMStack &PMS, PassManagerType T) override; /// Return what kind of Pass Manager can manage this pass. - virtual PassManagerType getPotentialPassManagerType() const; + PassManagerType getPotentialPassManagerType() const override; explicit ModulePass(char &pid) : Pass(PT_Module, pid) {} // Force out-of-line virtual method. @@ -268,11 +269,11 @@ public: /// virtual void initializePass(); - virtual ImmutablePass *getAsImmutablePass() { return this; } + ImmutablePass *getAsImmutablePass() override { return this; } /// ImmutablePasses are never run. /// - bool runOnModule(Module &) { return false; } + bool runOnModule(Module &) override { return false; } explicit ImmutablePass(char &pid) : ModulePass(pid) {} @@ -295,18 +296,23 @@ public: explicit FunctionPass(char &pid) : Pass(PT_Function, pid) {} /// createPrinterPass - Get a function printer pass. - Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const override; /// runOnFunction - Virtual method overriden by subclasses to do the /// per-function processing of the pass. /// virtual bool runOnFunction(Function &F) = 0; - virtual void assignPassManager(PMStack &PMS, - PassManagerType T); + void assignPassManager(PMStack &PMS, PassManagerType T) override; /// Return what kind of Pass Manager can manage this pass. - virtual PassManagerType getPotentialPassManagerType() const; + PassManagerType getPotentialPassManagerType() const override; + +protected: + /// skipOptnoneFunction - This function has Attribute::OptimizeNone + /// and most transformation passes should skip it. + bool skipOptnoneFunction(const Function &F) const; }; @@ -326,7 +332,8 @@ public: explicit BasicBlockPass(char &pid) : Pass(PT_BasicBlock, pid) {} /// createPrinterPass - Get a basic block printer pass. - Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; + Pass *createPrinterPass(raw_ostream &O, + const std::string &Banner) const override; using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; @@ -346,11 +353,15 @@ public: /// virtual bool doFinalization(Function &); - virtual void assignPassManager(PMStack &PMS, - PassManagerType T); + void assignPassManager(PMStack &PMS, PassManagerType T) override; /// Return what kind of Pass Manager can manage this pass. - virtual PassManagerType getPotentialPassManagerType() const; + PassManagerType getPotentialPassManagerType() const override; + +protected: + /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone + /// and most transformation passes should skip it. + bool skipOptnoneFunction(const BasicBlock &BB) const; }; /// If the user specifies the -time-passes argument on an LLVM tool command line diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h index a581802c47c0..916430541809 100644 --- a/include/llvm/PassAnalysisSupport.h +++ b/include/llvm/PassAnalysisSupport.h @@ -129,7 +129,7 @@ public: // Find pass that is implementing PI. Pass *findImplPass(AnalysisID PI) { - Pass *ResultPass = 0; + Pass *ResultPass = nullptr; for (unsigned i = 0; i < AnalysisImpls.size() ; ++i) { if (AnalysisImpls[i].first == PI) { ResultPass = AnalysisImpls[i].second; @@ -182,7 +182,7 @@ AnalysisType *Pass::getAnalysisIfAvailable() const { const void *PI = &AnalysisType::ID; Pass *ResultPass = Resolver->getAnalysisIfAvailable(PI, true); - if (ResultPass == 0) return 0; + if (!ResultPass) return nullptr; // Because the AnalysisType may not be a subclass of pass (for // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially diff --git a/include/llvm/PassInfo.h b/include/llvm/PassInfo.h new file mode 100644 index 000000000000..d53daf1cf72c --- /dev/null +++ b/include/llvm/PassInfo.h @@ -0,0 +1,147 @@ +//===- llvm/PassInfo.h - Pass Info class ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines and implements the PassInfo class. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_PASSINFO_H +#define LLVM_PASSINFO_H + +#include <cassert> +#include <vector> + +namespace llvm { + +class Pass; +class TargetMachine; + +//===--------------------------------------------------------------------------- +/// PassInfo class - An instance of this class exists for every pass known by +/// the system, and can be obtained from a live Pass by calling its +/// getPassInfo() method. These objects are set up by the RegisterPass<> +/// template. +/// +class PassInfo { +public: + typedef Pass* (*NormalCtor_t)(); + typedef Pass *(*TargetMachineCtor_t)(TargetMachine *); + +private: + const char *const PassName; // Nice name for Pass + const char *const PassArgument; // Command Line argument to run this pass + const void *PassID; + const bool IsCFGOnlyPass; // Pass only looks at the CFG. + const bool IsAnalysis; // True if an analysis pass. + const bool IsAnalysisGroup; // True if an analysis group. + std::vector<const PassInfo*> ItfImpl;// Interfaces implemented by this pass + + NormalCtor_t NormalCtor; + TargetMachineCtor_t TargetMachineCtor; + +public: + /// PassInfo ctor - Do not call this directly, this should only be invoked + /// through RegisterPass. + PassInfo(const char *name, const char *arg, const void *pi, + NormalCtor_t normal, bool isCFGOnly, bool is_analysis, + TargetMachineCtor_t machine = nullptr) + : PassName(name), PassArgument(arg), PassID(pi), + IsCFGOnlyPass(isCFGOnly), + IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal), + TargetMachineCtor(machine) {} + /// PassInfo ctor - Do not call this directly, this should only be invoked + /// through RegisterPass. This version is for use by analysis groups; it + /// does not auto-register the pass. + PassInfo(const char *name, const void *pi) + : PassName(name), PassArgument(""), PassID(pi), + IsCFGOnlyPass(false), + IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(nullptr), + TargetMachineCtor(nullptr) {} + + /// getPassName - Return the friendly name for the pass, never returns null + /// + const char *getPassName() const { return PassName; } + + /// getPassArgument - Return the command line option that may be passed to + /// 'opt' that will cause this pass to be run. This will return null if there + /// is no argument. + /// + const char *getPassArgument() const { return PassArgument; } + + /// getTypeInfo - Return the id object for the pass... + /// TODO : Rename + const void *getTypeInfo() const { return PassID; } + + /// Return true if this PassID implements the specified ID pointer. + bool isPassID(const void *IDPtr) const { + return PassID == IDPtr; + } + + /// isAnalysisGroup - Return true if this is an analysis group, not a normal + /// pass. + /// + bool isAnalysisGroup() const { return IsAnalysisGroup; } + bool isAnalysis() const { return IsAnalysis; } + + /// isCFGOnlyPass - return true if this pass only looks at the CFG for the + /// function. + bool isCFGOnlyPass() const { return IsCFGOnlyPass; } + + /// getNormalCtor - Return a pointer to a function, that when called, creates + /// an instance of the pass and returns it. This pointer may be null if there + /// is no default constructor for the pass. + /// + NormalCtor_t getNormalCtor() const { + return NormalCtor; + } + void setNormalCtor(NormalCtor_t Ctor) { + NormalCtor = Ctor; + } + + /// getTargetMachineCtor - Return a pointer to a function, that when called + /// with a TargetMachine, creates an instance of the pass and returns it. + /// This pointer may be null if there is no constructor with a TargetMachine + /// for the pass. + /// + TargetMachineCtor_t getTargetMachineCtor() const { return TargetMachineCtor; } + void setTargetMachineCtor(TargetMachineCtor_t Ctor) { + TargetMachineCtor = Ctor; + } + + /// createPass() - Use this method to create an instance of this pass. + Pass *createPass() const { + assert((!isAnalysisGroup() || NormalCtor) && + "No default implementation found for analysis group!"); + assert(NormalCtor && + "Cannot call createPass on PassInfo without default ctor!"); + return NormalCtor(); + } + + /// addInterfaceImplemented - This method is called when this pass is + /// registered as a member of an analysis group with the RegisterAnalysisGroup + /// template. + /// + void addInterfaceImplemented(const PassInfo *ItfPI) { + ItfImpl.push_back(ItfPI); + } + + /// getInterfacesImplemented - Return a list of all of the analysis group + /// interfaces implemented by this pass. + /// + const std::vector<const PassInfo*> &getInterfacesImplemented() const { + return ItfImpl; + } + +private: + void operator=(const PassInfo &) LLVM_DELETED_FUNCTION; + PassInfo(const PassInfo &) LLVM_DELETED_FUNCTION; +}; + +} + +#endif diff --git a/include/llvm/PassRegistry.h b/include/llvm/PassRegistry.h index f49c953e44f2..1558c51bde48 100644 --- a/include/llvm/PassRegistry.h +++ b/include/llvm/PassRegistry.h @@ -17,9 +17,15 @@ #ifndef LLVM_PASSREGISTRY_H #define LLVM_PASSREGISTRY_H +#include "llvm-c/Core.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/PassInfo.h" #include "llvm/Support/CBindingWrapping.h" -#include "llvm-c/Core.h" +#include "llvm/Support/RWMutex.h" +#include <vector> namespace llvm { @@ -33,11 +39,26 @@ struct PassRegistrationListener; /// threads simultaneously, you will need to use a separate PassRegistry on /// each thread. class PassRegistry { - mutable void *pImpl; - void *getImpl() const; + mutable sys::SmartRWMutex<true> Lock; + + /// PassInfoMap - Keep track of the PassInfo object for each registered pass. + typedef DenseMap<const void*, const PassInfo*> MapType; + MapType PassInfoMap; + + typedef StringMap<const PassInfo*> StringMapType; + StringMapType PassInfoStringMap; + + /// AnalysisGroupInfo - Keep track of information for each analysis group. + struct AnalysisGroupInfo { + SmallPtrSet<const PassInfo *, 8> Implementations; + }; + DenseMap<const PassInfo*, AnalysisGroupInfo> AnalysisGroupInfoMap; + + std::vector<std::unique_ptr<const PassInfo>> ToFree; + std::vector<PassRegistrationListener*> Listeners; public: - PassRegistry() : pImpl(0) { } + PassRegistry() { } ~PassRegistry(); /// getPassRegistry - Access the global registry object, which is diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h index ccc79345e030..449bc9281084 100644 --- a/include/llvm/PassSupport.h +++ b/include/llvm/PassSupport.h @@ -23,6 +23,7 @@ #include "Pass.h" #include "llvm/InitializePasses.h" +#include "llvm/PassInfo.h" #include "llvm/PassRegistry.h" #include "llvm/Support/Atomic.h" #include "llvm/Support/Valgrind.h" @@ -30,105 +31,7 @@ namespace llvm { -//===--------------------------------------------------------------------------- -/// PassInfo class - An instance of this class exists for every pass known by -/// the system, and can be obtained from a live Pass by calling its -/// getPassInfo() method. These objects are set up by the RegisterPass<> -/// template, defined below. -/// -class PassInfo { -public: - typedef Pass* (*NormalCtor_t)(); - -private: - const char *const PassName; // Nice name for Pass - const char *const PassArgument; // Command Line argument to run this pass - const void *PassID; - const bool IsCFGOnlyPass; // Pass only looks at the CFG. - const bool IsAnalysis; // True if an analysis pass. - const bool IsAnalysisGroup; // True if an analysis group. - std::vector<const PassInfo*> ItfImpl;// Interfaces implemented by this pass - - NormalCtor_t NormalCtor; - -public: - /// PassInfo ctor - Do not call this directly, this should only be invoked - /// through RegisterPass. - PassInfo(const char *name, const char *arg, const void *pi, - NormalCtor_t normal, bool isCFGOnly, bool is_analysis) - : PassName(name), PassArgument(arg), PassID(pi), - IsCFGOnlyPass(isCFGOnly), - IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal) { } - /// PassInfo ctor - Do not call this directly, this should only be invoked - /// through RegisterPass. This version is for use by analysis groups; it - /// does not auto-register the pass. - PassInfo(const char *name, const void *pi) - : PassName(name), PassArgument(""), PassID(pi), - IsCFGOnlyPass(false), - IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(0) { } - - /// getPassName - Return the friendly name for the pass, never returns null - /// - const char *getPassName() const { return PassName; } - - /// getPassArgument - Return the command line option that may be passed to - /// 'opt' that will cause this pass to be run. This will return null if there - /// is no argument. - /// - const char *getPassArgument() const { return PassArgument; } - - /// getTypeInfo - Return the id object for the pass... - /// TODO : Rename - const void *getTypeInfo() const { return PassID; } - - /// Return true if this PassID implements the specified ID pointer. - bool isPassID(const void *IDPtr) const { - return PassID == IDPtr; - } - - /// isAnalysisGroup - Return true if this is an analysis group, not a normal - /// pass. - /// - bool isAnalysisGroup() const { return IsAnalysisGroup; } - bool isAnalysis() const { return IsAnalysis; } - - /// isCFGOnlyPass - return true if this pass only looks at the CFG for the - /// function. - bool isCFGOnlyPass() const { return IsCFGOnlyPass; } - - /// getNormalCtor - Return a pointer to a function, that when called, creates - /// an instance of the pass and returns it. This pointer may be null if there - /// is no default constructor for the pass. - /// - NormalCtor_t getNormalCtor() const { - return NormalCtor; - } - void setNormalCtor(NormalCtor_t Ctor) { - NormalCtor = Ctor; - } - - /// createPass() - Use this method to create an instance of this pass. - Pass *createPass() const; - - /// addInterfaceImplemented - This method is called when this pass is - /// registered as a member of an analysis group with the RegisterAnalysisGroup - /// template. - /// - void addInterfaceImplemented(const PassInfo *ItfPI) { - ItfImpl.push_back(ItfPI); - } - - /// getInterfacesImplemented - Return a list of all of the analysis group - /// interfaces implemented by this pass. - /// - const std::vector<const PassInfo*> &getInterfacesImplemented() const { - return ItfImpl; - } - -private: - void operator=(const PassInfo &) LLVM_DELETED_FUNCTION; - PassInfo(const PassInfo &) LLVM_DELETED_FUNCTION; -}; +class TargetMachine; #define CALL_ONCE_INITIALIZATION(function) \ static volatile sys::cas_flag initialized = 0; \ @@ -182,6 +85,10 @@ private: template<typename PassName> Pass *callDefaultCtor() { return new PassName(); } +template <typename PassName> Pass *callTargetMachineCtor(TargetMachine *TM) { + return new PassName(TM); +} + //===--------------------------------------------------------------------------- /// RegisterPass<t> template - This template class is used to notify the system /// that a Pass is available for use, and registers it into the internal @@ -236,7 +143,7 @@ class RegisterAGBase : public PassInfo { public: RegisterAGBase(const char *Name, const void *InterfaceID, - const void *PassID = 0, + const void *PassID = nullptr, bool isDefault = false); }; @@ -305,19 +212,12 @@ struct RegisterAnalysisGroup : public RegisterAGBase { /// clients that are interested in which passes get registered and unregistered /// at runtime (which can be because of the RegisterPass constructors being run /// as the program starts up, or may be because a shared object just got -/// loaded). Deriving from the PassRegistrationListener class automatically -/// registers your object to receive callbacks indicating when passes are loaded -/// and removed. +/// loaded). /// struct PassRegistrationListener { - /// PassRegistrationListener ctor - Add the current object to the list of - /// PassRegistrationListeners... - PassRegistrationListener(); - - /// dtor - Remove object from list of listeners... - /// - virtual ~PassRegistrationListener(); + PassRegistrationListener() {} + virtual ~PassRegistrationListener() {} /// Callback functions - These functions are invoked whenever a pass is loaded /// or removed from the current executable. diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h new file mode 100644 index 000000000000..eafb76886c83 --- /dev/null +++ b/include/llvm/ProfileData/InstrProf.h @@ -0,0 +1,51 @@ +//=-- InstrProf.h - Instrumented profiling format support ---------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Instrumentation-based profiling data is generated by instrumented +// binaries through library functions in compiler-rt, and read by the clang +// frontend to feed PGO. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_INSTRPROF_H_ +#define LLVM_PROFILEDATA_INSTRPROF_H_ + +#include <system_error> + +namespace llvm { +const std::error_category &instrprof_category(); + +enum class instrprof_error { + success = 0, + eof, + bad_magic, + bad_header, + unsupported_version, + unsupported_hash_type, + too_large, + truncated, + malformed, + unknown_function, + hash_mismatch, + count_mismatch, + counter_overflow +}; + +inline std::error_code make_error_code(instrprof_error E) { + return std::error_code(static_cast<int>(E), instrprof_category()); +} + +} // end namespace llvm + +namespace std { +template <> +struct is_error_code_enum<llvm::instrprof_error> : std::true_type {}; +} + +#endif // LLVM_PROFILEDATA_INSTRPROF_H_ diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h new file mode 100644 index 000000000000..7a5a71dc6a31 --- /dev/null +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -0,0 +1,302 @@ +//=-- InstrProfReader.h - Instrumented profiling readers ----------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for reading profiling data for instrumentation +// based PGO and coverage. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_INSTRPROF_READER_H_ +#define LLVM_PROFILEDATA_INSTRPROF_READER_H_ + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/OnDiskHashTable.h" + +#include <iterator> + +namespace llvm { + +class InstrProfReader; + +/// Profiling information for a single function. +struct InstrProfRecord { + InstrProfRecord() {} + InstrProfRecord(StringRef Name, uint64_t Hash, ArrayRef<uint64_t> Counts) + : Name(Name), Hash(Hash), Counts(Counts) {} + StringRef Name; + uint64_t Hash; + ArrayRef<uint64_t> Counts; +}; + +/// A file format agnostic iterator over profiling data. +class InstrProfIterator : public std::iterator<std::input_iterator_tag, + InstrProfRecord> { + InstrProfReader *Reader; + InstrProfRecord Record; + + void Increment(); +public: + InstrProfIterator() : Reader(nullptr) {} + InstrProfIterator(InstrProfReader *Reader) : Reader(Reader) { Increment(); } + + InstrProfIterator &operator++() { Increment(); return *this; } + bool operator==(const InstrProfIterator &RHS) { return Reader == RHS.Reader; } + bool operator!=(const InstrProfIterator &RHS) { return Reader != RHS.Reader; } + InstrProfRecord &operator*() { return Record; } + InstrProfRecord *operator->() { return &Record; } +}; + +/// Base class and interface for reading profiling data of any known instrprof +/// format. Provides an iterator over InstrProfRecords. +class InstrProfReader { + std::error_code LastError; + +public: + InstrProfReader() : LastError(instrprof_error::success) {} + virtual ~InstrProfReader() {} + + /// Read the header. Required before reading first record. + virtual std::error_code readHeader() = 0; + /// Read a single record. + virtual std::error_code readNextRecord(InstrProfRecord &Record) = 0; + /// Iterator over profile data. + InstrProfIterator begin() { return InstrProfIterator(this); } + InstrProfIterator end() { return InstrProfIterator(); } + +protected: + /// Set the current std::error_code and return same. + std::error_code error(std::error_code EC) { + LastError = EC; + return EC; + } + + /// Clear the current error code and return a successful one. + std::error_code success() { return error(instrprof_error::success); } + +public: + /// Return true if the reader has finished reading the profile data. + bool isEOF() { return LastError == instrprof_error::eof; } + /// Return true if the reader encountered an error reading profiling data. + bool hasError() { return LastError && !isEOF(); } + /// Get the current error code. + std::error_code getError() { return LastError; } + + /// Factory method to create an appropriately typed reader for the given + /// instrprof file. + static std::error_code create(std::string Path, + std::unique_ptr<InstrProfReader> &Result); +}; + +/// Reader for the simple text based instrprof format. +/// +/// This format is a simple text format that's suitable for test data. Records +/// are separated by one or more blank lines, and record fields are separated by +/// new lines. +/// +/// Each record consists of a function name, a function hash, a number of +/// counters, and then each counter value, in that order. +class TextInstrProfReader : public InstrProfReader { +private: + /// The profile data file contents. + std::unique_ptr<MemoryBuffer> DataBuffer; + /// Iterator over the profile data. + line_iterator Line; + /// The current set of counter values. + std::vector<uint64_t> Counts; + + TextInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION; + TextInstrProfReader &operator=(const TextInstrProfReader &) + LLVM_DELETED_FUNCTION; +public: + TextInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer_) + : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, '#') {} + + /// Read the header. + std::error_code readHeader() override { return success(); } + /// Read a single record. + std::error_code readNextRecord(InstrProfRecord &Record) override; +}; + +/// Reader for the raw instrprof binary format from runtime. +/// +/// This format is a raw memory dump of the instrumentation-baed profiling data +/// from the runtime. It has no index. +/// +/// Templated on the unsigned type whose size matches pointers on the platform +/// that wrote the profile. +template <class IntPtrT> +class RawInstrProfReader : public InstrProfReader { +private: + /// The profile data file contents. + std::unique_ptr<MemoryBuffer> DataBuffer; + /// The current set of counter values. + std::vector<uint64_t> Counts; + struct ProfileData { + const uint32_t NameSize; + const uint32_t NumCounters; + const uint64_t FuncHash; + const IntPtrT NamePtr; + const IntPtrT CounterPtr; + }; + struct RawHeader { + const uint64_t Magic; + const uint64_t Version; + const uint64_t DataSize; + const uint64_t CountersSize; + const uint64_t NamesSize; + const uint64_t CountersDelta; + const uint64_t NamesDelta; + }; + + bool ShouldSwapBytes; + uint64_t CountersDelta; + uint64_t NamesDelta; + const ProfileData *Data; + const ProfileData *DataEnd; + const uint64_t *CountersStart; + const char *NamesStart; + const char *ProfileEnd; + + RawInstrProfReader(const RawInstrProfReader &) LLVM_DELETED_FUNCTION; + RawInstrProfReader &operator=(const RawInstrProfReader &) + LLVM_DELETED_FUNCTION; +public: + RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) + : DataBuffer(std::move(DataBuffer)) { } + + static bool hasFormat(const MemoryBuffer &DataBuffer); + std::error_code readHeader() override; + std::error_code readNextRecord(InstrProfRecord &Record) override; + +private: + std::error_code readNextHeader(const char *CurrentPos); + std::error_code readHeader(const RawHeader &Header); + template <class IntT> + IntT swap(IntT Int) const { + return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int; + } + const uint64_t *getCounter(IntPtrT CounterPtr) const { + ptrdiff_t Offset = (swap(CounterPtr) - CountersDelta) / sizeof(uint64_t); + return CountersStart + Offset; + } + const char *getName(IntPtrT NamePtr) const { + ptrdiff_t Offset = (swap(NamePtr) - NamesDelta) / sizeof(char); + return NamesStart + Offset; + } +}; + +typedef RawInstrProfReader<uint32_t> RawInstrProfReader32; +typedef RawInstrProfReader<uint64_t> RawInstrProfReader64; + +namespace IndexedInstrProf { +enum class HashT : uint32_t; +} + +/// Trait for lookups into the on-disk hash table for the binary instrprof +/// format. +class InstrProfLookupTrait { + std::vector<uint64_t> CountBuffer; + IndexedInstrProf::HashT HashType; +public: + InstrProfLookupTrait(IndexedInstrProf::HashT HashType) : HashType(HashType) {} + + typedef InstrProfRecord data_type; + typedef StringRef internal_key_type; + typedef StringRef external_key_type; + typedef uint64_t hash_value_type; + typedef uint64_t offset_type; + + static bool EqualKey(StringRef A, StringRef B) { return A == B; } + static StringRef GetInternalKey(StringRef K) { return K; } + + hash_value_type ComputeHash(StringRef K); + + static std::pair<offset_type, offset_type> + ReadKeyDataLength(const unsigned char *&D) { + using namespace support; + offset_type KeyLen = endian::readNext<offset_type, little, unaligned>(D); + offset_type DataLen = endian::readNext<offset_type, little, unaligned>(D); + return std::make_pair(KeyLen, DataLen); + } + + StringRef ReadKey(const unsigned char *D, offset_type N) { + return StringRef((const char *)D, N); + } + + InstrProfRecord ReadData(StringRef K, const unsigned char *D, offset_type N) { + if (N < 2 * sizeof(uint64_t) || N % sizeof(uint64_t)) { + // The data is corrupt, don't try to read it. + CountBuffer.clear(); + return InstrProfRecord("", 0, CountBuffer); + } + + using namespace support; + + // The first stored value is the hash. + uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D); + // Each counter follows. + unsigned NumCounters = N / sizeof(uint64_t) - 1; + CountBuffer.clear(); + CountBuffer.reserve(NumCounters - 1); + for (unsigned I = 0; I < NumCounters; ++I) + CountBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D)); + + return InstrProfRecord(K, Hash, CountBuffer); + } +}; +typedef OnDiskIterableChainedHashTable<InstrProfLookupTrait> + InstrProfReaderIndex; + +/// Reader for the indexed binary instrprof format. +class IndexedInstrProfReader : public InstrProfReader { +private: + /// The profile data file contents. + std::unique_ptr<MemoryBuffer> DataBuffer; + /// The index into the profile data. + std::unique_ptr<InstrProfReaderIndex> Index; + /// Iterator over the profile data. + InstrProfReaderIndex::data_iterator RecordIterator; + /// The maximal execution count among all fucntions. + uint64_t MaxFunctionCount; + + IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION; + IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) + LLVM_DELETED_FUNCTION; +public: + IndexedInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) + : DataBuffer(std::move(DataBuffer)), Index(nullptr), + RecordIterator(InstrProfReaderIndex::data_iterator()) {} + + /// Return true if the given buffer is in an indexed instrprof format. + static bool hasFormat(const MemoryBuffer &DataBuffer); + + /// Read the file header. + std::error_code readHeader() override; + /// Read a single record. + std::error_code readNextRecord(InstrProfRecord &Record) override; + + /// Fill Counts with the profile data for the given function name. + std::error_code getFunctionCounts(StringRef FuncName, uint64_t &FuncHash, + std::vector<uint64_t> &Counts); + /// Return the maximum of all known function counts. + uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } + + /// Factory method to create an indexed reader. + static std::error_code + create(std::string Path, std::unique_ptr<IndexedInstrProfReader> &Result); +}; + +} // end namespace llvm + +#endif // LLVM_PROFILEDATA_INSTRPROF_READER_H_ diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h new file mode 100644 index 000000000000..6e68bee30eb8 --- /dev/null +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -0,0 +1,50 @@ +//=-- InstrProfWriter.h - Instrumented profiling writer -----------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing profiling data for instrumentation +// based PGO and coverage. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_INSTRPROF_WRITER_H_ +#define LLVM_PROFILEDATA_INSTRPROF_WRITER_H_ + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/raw_ostream.h" + +#include <vector> + +namespace llvm { + +/// Writer for instrumentation based profile data. +class InstrProfWriter { +public: + struct CounterData { + uint64_t Hash; + std::vector<uint64_t> Counts; + }; +private: + StringMap<CounterData> FunctionData; +public: + /// Add function counts for the given function. If there are already counts + /// for this function and the hash and number of counts match, each counter is + /// summed. + std::error_code addFunctionCounts(StringRef FunctionName, + uint64_t FunctionHash, + ArrayRef<uint64_t> Counters); + /// Ensure that all data is written to disk. + void write(raw_fd_ostream &OS); +}; + +} // end namespace llvm + +#endif // LLVM_PROFILE_INSTRPROF_WRITER_H_ diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h new file mode 100644 index 000000000000..f63e0a61f639 --- /dev/null +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -0,0 +1,217 @@ +//===-- ARMBuildAttributes.h - ARM Build Attributes -------------*- 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 enumerations and support routines for ARM build attributes +// as defined in ARM ABI addenda document (ABI release 2.08). +// +// ELF for the ARM Architecture r2.09 - November 30, 2012 +// +// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H +#define LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H + +namespace llvm { +class StringRef; + +namespace ARMBuildAttrs { + +enum SpecialAttr { + // This is for the .cpu asm attr. It translates into one or more + // AttrType (below) entries in the .ARM.attributes section in the ELF. + SEL_CPU +}; + +enum AttrType { + // Rest correspond to ELF/.ARM.attributes + File = 1, + CPU_raw_name = 4, + CPU_name = 5, + CPU_arch = 6, + CPU_arch_profile = 7, + ARM_ISA_use = 8, + THUMB_ISA_use = 9, + FP_arch = 10, + WMMX_arch = 11, + Advanced_SIMD_arch = 12, + PCS_config = 13, + ABI_PCS_R9_use = 14, + ABI_PCS_RW_data = 15, + ABI_PCS_RO_data = 16, + ABI_PCS_GOT_use = 17, + ABI_PCS_wchar_t = 18, + ABI_FP_rounding = 19, + ABI_FP_denormal = 20, + ABI_FP_exceptions = 21, + ABI_FP_user_exceptions = 22, + ABI_FP_number_model = 23, + ABI_align_needed = 24, + ABI_align_preserved = 25, + ABI_enum_size = 26, + ABI_HardFP_use = 27, + ABI_VFP_args = 28, + ABI_WMMX_args = 29, + ABI_optimization_goals = 30, + ABI_FP_optimization_goals = 31, + compatibility = 32, + CPU_unaligned_access = 34, + FP_HP_extension = 36, + ABI_FP_16bit_format = 38, + MPextension_use = 42, // recoded from 70 (ABI r2.08) + DIV_use = 44, + also_compatible_with = 65, + conformance = 67, + Virtualization_use = 68, + + /// Legacy Tags + Section = 2, // deprecated (ABI r2.09) + Symbol = 3, // deprecated (ABI r2.09) + ABI_align8_needed = 24, // renamed to ABI_align_needed (ABI r2.09) + ABI_align8_preserved = 25, // renamed to ABI_align_preserved (ABI r2.09) + nodefaults = 64, // deprecated (ABI r2.09) + T2EE_use = 66, // deprecated (ABI r2.09) + MPextension_use_old = 70 // recoded to MPextension_use (ABI r2.08) +}; + +StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix = true); +StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true); +int AttrTypeFromString(StringRef Tag); + +// Magic numbers for .ARM.attributes +enum AttrMagic { + Format_Version = 0x41 +}; + +// Legal Values for CPU_arch, (=6), uleb128 +enum CPUArch { + Pre_v4 = 0, + v4 = 1, // e.g. SA110 + v4T = 2, // e.g. ARM7TDMI + v5T = 3, // e.g. ARM9TDMI + v5TE = 4, // e.g. ARM946E_S + v5TEJ = 5, // e.g. ARM926EJ_S + v6 = 6, // e.g. ARM1136J_S + v6KZ = 7, // e.g. ARM1176JZ_S + v6T2 = 8, // e.g. ARM1156T2F_S + v6K = 9, // e.g. ARM1136J_S + v7 = 10, // e.g. Cortex A8, Cortex M3 + v6_M = 11, // e.g. Cortex M1 + v6S_M = 12, // v6_M with the System extensions + v7E_M = 13, // v7_M with DSP extensions + v8 = 14 // v8, AArch32 +}; + +enum CPUArchProfile { // (=7), uleb128 + Not_Applicable = 0, // pre v7, or cross-profile code + ApplicationProfile = (0x41), // 'A' (e.g. for Cortex A8) + RealTimeProfile = (0x52), // 'R' (e.g. for Cortex R4) + MicroControllerProfile = (0x4D), // 'M' (e.g. for Cortex M3) + SystemProfile = (0x53) // 'S' Application or real-time profile +}; + +// The following have a lot of common use cases +enum { + Not_Allowed = 0, + Allowed = 1, + + // Tag_ARM_ISA_use (=8), uleb128 + + // Tag_THUMB_ISA_use, (=9), uleb128 + AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions) + + // Tag_FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10) + AllowFPv2 = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA) + AllowFPv3A = 3, // v3 FP ISA permitted (implies use of the v2 FP ISA) + AllowFPv3B = 4, // v3 FP ISA permitted, but only D0-D15, S0-S31 + AllowFPv4A = 5, // v4 FP ISA permitted (implies use of v3 FP ISA) + AllowFPv4B = 6, // v4 FP ISA was permitted, but only D0-D15, S0-S31 + AllowFPARMv8A = 7, // Use of the ARM v8-A FP ISA was permitted + AllowFPARMv8B = 8, // Use of the ARM v8-A FP ISA was permitted, but only + // D0-D15, S0-S31 + + // Tag_WMMX_arch, (=11), uleb128 + AllowWMMXv1 = 1, // The user permitted this entity to use WMMX v1 + AllowWMMXv2 = 2, // The user permitted this entity to use WMMX v2 + + // Tag_Advanced_SIMD_arch, (=12), uleb128 + AllowNeon = 1, // SIMDv1 was permitted + AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations) + AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted + + // Tag_ABI_PCS_RW_data, (=15), uleb128 + AddressRWPCRel = 1, // Address RW static data PC-relative + AddressRWSBRel = 2, // Address RW static data SB-relative + AddressRWNone = 3, // No RW static data permitted + + // Tag_ABI_PCS_RO_data, (=14), uleb128 + AddressROPCRel = 1, // Address RO static data PC-relative + AddressRONone = 2, // No RO static data permitted + + // Tag_ABI_PCS_GOT_use, (=17), uleb128 + AddressDirect = 1, // Address imported data directly + AddressGOT = 2, // Address imported data indirectly (via GOT) + + // Tag_ABI_PCS_wchar_t, (=18), uleb128 + WCharProhibited = 0, // wchar_t is not used + WCharWidth2Bytes = 2, // sizeof(wchar_t) == 2 + WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4 + + // Tag_ABI_FP_denormal, (=20), uleb128 + PreserveFPSign = 2, // sign when flushed-to-zero is preserved + + // Tag_ABI_FP_number_model, (=23), uleb128 + AllowRTABI = 2, // numbers, infinities, and one quiet NaN (see [RTABI]) + AllowIEE754 = 3, // this code to use all the IEEE 754-defined FP encodings + + // Tag_ABI_enum_size, (=26), uleb128 + EnumProhibited = 0, // The user prohibited the use of enums when building + // this entity. + EnumSmallest = 1, // Enum is smallest container big enough to hold all + // values. + Enum32Bit = 2, // Enum is at least 32 bits. + Enum32BitABI = 3, // Every enumeration visible across an ABI-complying + // interface contains a value needing 32 bits to encode + // it; other enums can be containerized. + + // Tag_ABI_HardFP_use, (=27), uleb128 + HardFPImplied = 0, // FP use should be implied by Tag_FP_arch + HardFPSinglePrecision = 1, // Single-precision only + + // Tag_ABI_VFP_args, (=28), uleb128 + BaseAAPCS = 0, + HardFPAAPCS = 1, + + // Tag_FP_HP_extension, (=36), uleb128 + AllowHPFP = 1, // Allow use of Half Precision FP + + // Tag_MPextension_use, (=42), uleb128 + AllowMP = 1, // Allow use of MP extensions + + // Tag_DIV_use, (=44), uleb128 + // Note: AllowDIVExt must be emitted if and only if the permission to use + // hardware divide cannot be conveyed using AllowDIVIfExists or DisallowDIV + AllowDIVIfExists = 0, // Allow hardware divide if available in arch, or no + // info exists. + DisallowDIV = 1, // Hardware divide explicitly disallowed. + AllowDIVExt = 2, // Allow hardware divide as optional architecture + // extension above the base arch specified by + // Tag_CPU_arch and Tag_CPU_arch_profile. + + // Tag_Virtualization_use, (=68), uleb128 + AllowTZ = 1, + AllowVirtualization = 2, + AllowTZVirtualization = 3 +}; + +} // namespace ARMBuildAttrs +} // namespace llvm + +#endif // LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H diff --git a/include/llvm/Support/ARMEHABI.h b/include/llvm/Support/ARMEHABI.h new file mode 100644 index 000000000000..c7ac54aeb6de --- /dev/null +++ b/include/llvm/Support/ARMEHABI.h @@ -0,0 +1,134 @@ +//===--- ARMEHABI.h - ARM Exception Handling ABI ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the constants for the ARM unwind opcodes and exception +// handling table entry kinds. +// +// The enumerations and constants in this file reflect the ARM EHABI +// Specification as published by ARM. +// +// Exception Handling ABI for the ARM Architecture r2.09 - November 30, 2012 +// +// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ARM_EHABI_H +#define LLVM_SUPPORT_ARM_EHABI_H + +namespace llvm { +namespace ARM { +namespace EHABI { + /// ARM exception handling table entry kinds + enum EHTEntryKind { + EHT_GENERIC = 0x00, + EHT_COMPACT = 0x80 + }; + + enum { + /// Special entry for the function never unwind + EXIDX_CANTUNWIND = 0x1 + }; + + /// ARM-defined frame unwinding opcodes + enum UnwindOpcodes { + // Format: 00xxxxxx + // Purpose: vsp = vsp + ((x << 2) + 4) + UNWIND_OPCODE_INC_VSP = 0x00, + + // Format: 01xxxxxx + // Purpose: vsp = vsp - ((x << 2) + 4) + UNWIND_OPCODE_DEC_VSP = 0x40, + + // Format: 10000000 00000000 + // Purpose: refuse to unwind + UNWIND_OPCODE_REFUSE = 0x8000, + + // Format: 1000xxxx xxxxxxxx + // Purpose: pop r[15:12], r[11:4] + // Constraint: x != 0 + UNWIND_OPCODE_POP_REG_MASK_R4 = 0x8000, + + // Format: 1001xxxx + // Purpose: vsp = r[x] + // Constraint: x != 13 && x != 15 + UNWIND_OPCODE_SET_VSP = 0x90, + + // Format: 10100xxx + // Purpose: pop r[(4+x):4] + UNWIND_OPCODE_POP_REG_RANGE_R4 = 0xa0, + + // Format: 10101xxx + // Purpose: pop r14, r[(4+x):4] + UNWIND_OPCODE_POP_REG_RANGE_R4_R14 = 0xa8, + + // Format: 10110000 + // Purpose: finish + UNWIND_OPCODE_FINISH = 0xb0, + + // Format: 10110001 0000xxxx + // Purpose: pop r[3:0] + // Constraint: x != 0 + UNWIND_OPCODE_POP_REG_MASK = 0xb100, + + // Format: 10110010 x(uleb128) + // Purpose: vsp = vsp + ((x << 2) + 0x204) + UNWIND_OPCODE_INC_VSP_ULEB128 = 0xb2, + + // Format: 10110011 xxxxyyyy + // Purpose: pop d[(x+y):x] + UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDX = 0xb300, + + // Format: 10111xxx + // Purpose: pop d[(8+x):8] + UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDX_D8 = 0xb8, + + // Format: 11000xxx + // Purpose: pop wR[(10+x):10] + UNWIND_OPCODE_POP_WIRELESS_MMX_REG_RANGE_WR10 = 0xc0, + + // Format: 11000110 xxxxyyyy + // Purpose: pop wR[(x+y):x] + UNWIND_OPCODE_POP_WIRELESS_MMX_REG_RANGE = 0xc600, + + // Format: 11000111 0000xxxx + // Purpose: pop wCGR[3:0] + // Constraint: x != 0 + UNWIND_OPCODE_POP_WIRELESS_MMX_REG_MASK = 0xc700, + + // Format: 11001000 xxxxyyyy + // Purpose: pop d[(16+x+y):(16+x)] + UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16 = 0xc800, + + // Format: 11001001 xxxxyyyy + // Purpose: pop d[(x+y):x] + UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD = 0xc900, + + // Format: 11010xxx + // Purpose: pop d[(8+x):8] + UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D8 = 0xd0 + }; + + /// ARM-defined Personality Routine Index + enum PersonalityRoutineIndex { + // To make the exception handling table become more compact, ARM defined + // several personality routines in EHABI. There are 3 different + // personality routines in ARM EHABI currently. It is possible to have 16 + // pre-defined personality routines at most. + AEABI_UNWIND_CPP_PR0 = 0, + AEABI_UNWIND_CPP_PR1 = 1, + AEABI_UNWIND_CPP_PR2 = 2, + + NUM_PERSONALITY_INDEX + }; +} +} +} + +#endif // ARM_UNWIND_OP_H diff --git a/include/llvm/Support/ARMWinEH.h b/include/llvm/Support/ARMWinEH.h new file mode 100644 index 000000000000..78deb8d36a98 --- /dev/null +++ b/include/llvm/Support/ARMWinEH.h @@ -0,0 +1,384 @@ +//===-- llvm/Support/WinARMEH.h - Windows on ARM EH Constants ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WINARMEH_H +#define LLVM_SUPPORT_WINARMEH_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace ARM { +namespace WinEH { +enum class RuntimeFunctionFlag { + RFF_Unpacked, /// unpacked entry + RFF_Packed, /// packed entry + RFF_PackedFragment, /// packed entry representing a fragment + RFF_Reserved, /// reserved +}; + +enum class ReturnType { + RT_POP, /// return via pop {pc} (L flag must be set) + RT_B, /// 16-bit branch + RT_BW, /// 32-bit branch + RT_NoEpilogue, /// no epilogue (fragment) +}; + +/// RuntimeFunction - An entry in the table of procedure data (.pdata) +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +---------------------------------------------------------------+ +/// | Function Start RVA | +/// +-------------------+-+-+-+-----+-+---+---------------------+---+ +/// | Stack Adjust |C|L|R| Reg |H|Ret| Function Length |Flg| +/// +-------------------+-+-+-+-----+-+---+---------------------+---+ +/// +/// Flag : 2-bit field with the following meanings: +/// - 00 = packed unwind data not used; reamining bits point to .xdata record +/// - 01 = packed unwind data +/// - 10 = packed unwind data, function assumed to have no prologue; useful +/// for function fragments that are discontiguous with the start of the +/// function +/// - 11 = reserved +/// Function Length : 11-bit field providing the length of the entire function +/// in bytes, divided by 2; if the function is greater than +/// 4KB, a full .xdata record must be used instead +/// Ret : 2-bit field indicating how the function returns +/// - 00 = return via pop {pc} (the L bit must be set) +/// - 01 = return via 16-bit branch +/// - 10 = return via 32-bit branch +/// - 11 = no epilogue; useful for function fragments that may only contain a +/// prologue but the epilogue is elsewhere +/// H : 1-bit flag indicating whether the function "homes" the integer parameter +/// registers (r0-r3), allocating 16-bytes on the stack +/// Reg : 3-bit field indicating the index of the last saved non-volatile +/// register. If the R bit is set to 0, then only integer registers are +/// saved (r4-rN, where N is 4 + Reg). If the R bit is set to 1, then +/// only floating-point registers are being saved (d8-dN, where N is +/// 8 + Reg). The special case of the R bit being set to 1 and Reg equal +/// to 7 indicates that no registers are saved. +/// R : 1-bit flag indicating whether the non-volatile registers are integer or +/// floating-point. 0 indicates integer, 1 indicates floating-point. The +/// special case of the R-flag being set and Reg being set to 7 indicates +/// that no non-volatile registers are saved. +/// L : 1-bit flag indicating whether the function saves/restores the link +/// register (LR) +/// C : 1-bit flag indicating whether the function includes extra instructions +/// to setup a frame chain for fast walking. If this flag is set, r11 is +/// implicitly added to the list of saved non-volatile integer registers. +/// Stack Adjust : 10-bit field indicating the number of bytes of stack that are +/// allocated for this function. Only values between 0x000 and +/// 0x3f3 can be directly encoded. If the value is 0x3f4 or +/// greater, then the low 4 bits have special meaning as follows: +/// - Bit 0-1 +/// indicate the number of words' of adjustment (1-4), minus 1 +/// - Bit 2 +/// indicates if the prologue combined adjustment into push +/// - Bit 3 +/// indicates if the epilogue combined adjustment into pop +/// +/// RESTRICTIONS: +/// - IF C is SET: +/// + L flag must be set since frame chaining requires r11 and lr +/// + r11 must NOT be included in the set of registers described by Reg +/// - IF Ret is 0: +/// + L flag must be set + +// NOTE: RuntimeFunction is meant to be a simple class that provides raw access +// to all fields in the structure. The accessor methods reflect the names of +// the bitfields that they correspond to. Although some obvious simplifications +// are possible via merging of methods, it would prevent the use of this class +// to fully inspect the contents of the data structure which is particularly +// useful for scenarios such as llvm-readobj to aid in testing. + +class RuntimeFunction { +public: + const support::ulittle32_t BeginAddress; + const support::ulittle32_t UnwindData; + + RuntimeFunction(const support::ulittle32_t *Data) + : BeginAddress(Data[0]), UnwindData(Data[1]) {} + + RuntimeFunction(const support::ulittle32_t BeginAddress, + const support::ulittle32_t UnwindData) + : BeginAddress(BeginAddress), UnwindData(UnwindData) {} + + RuntimeFunctionFlag Flag() const { + return RuntimeFunctionFlag(UnwindData & 0x3); + } + + uint32_t ExceptionInformationRVA() const { + assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked && + "unpacked form required for this operation"); + return (UnwindData & ~0x3); + } + + uint32_t PackedUnwindData() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return (UnwindData & ~0x3); + } + uint32_t FunctionLength() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return (((UnwindData & 0x00001ffc) >> 2) << 1); + } + ReturnType Ret() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + assert(((UnwindData & 0x00006000) || L()) && "L must be set to 1"); + return ReturnType((UnwindData & 0x00006000) >> 13); + } + bool H() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00008000) >> 15); + } + uint8_t Reg() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00070000) >> 16); + } + bool R() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00080000) >> 19); + } + bool L() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00100000) >> 20); + } + bool C() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + assert(((~UnwindData & 0x00200000) || L()) && + "L flag must be set, chaining requires r11 and LR"); + assert(((~UnwindData & 0x00200000) || (Reg() < 7) || R()) && + "r11 must not be included in Reg; C implies r11"); + return ((UnwindData & 0x00200000) >> 21); + } + uint16_t StackAdjust() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0xffc00000) >> 22); + } +}; + +/// PrologueFolding - pseudo-flag derived from Stack Adjust indicating that the +/// prologue has stack adjustment combined into the push +inline bool PrologueFolding(const RuntimeFunction &RF) { + return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x4); +} +/// Epilogue - pseudo-flag derived from Stack Adjust indicating that the +/// epilogue has stack adjustment combined into the pop +inline bool EpilogueFolding(const RuntimeFunction &RF) { + return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x8); +} +/// StackAdjustment - calculated stack adjustment in words. The stack +/// adjustment should be determined via this function to account for the special +/// handling the special encoding when the value is >= 0x3f4. +inline uint16_t StackAdjustment(const RuntimeFunction &RF) { + uint16_t Adjustment = RF.StackAdjust(); + if (Adjustment >= 0x3f4) + return (Adjustment & 0x3) ? ((Adjustment & 0x3) << 2) - 1 : 0; + return Adjustment; +} + +/// SavedRegisterMask - Utility function to calculate the set of saved general +/// purpose (r0-r15) and VFP (d0-d31) registers. +std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF); + +/// ExceptionDataRecord - An entry in the table of exception data (.xdata) +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +-------+---------+-+-+-+---+-----------------------------------+ +/// | C Wrd | Epi Cnt |F|E|X|Ver| Function Length | +/// +-------+--------+'-'-'-'---'---+-------------------------------+ +/// | Reserved |Ex. Code Words| (Extended Epilogue Count) | +/// +-------+--------+--------------+-------------------------------+ +/// +/// Function Length : 18-bit field indicating the total length of the function +/// in bytes divided by 2. If a function is larger than +/// 512KB, then multiple pdata and xdata records must be used. +/// Vers : 2-bit field describing the version of the remaining structure. Only +/// version 0 is currently defined (values 1-3 are not permitted). +/// X : 1-bit field indicating the presence of exception data +/// E : 1-bit field indicating that the single epilogue is packed into the +/// header +/// F : 1-bit field indicating that the record describes a function fragment +/// (implies that no prologue is present, and prologue processing should be +/// skipped) +/// Epilogue Count : 5-bit field that differs in meaning based on the E field. +/// +/// If E is set, then this field specifies the index of the +/// first unwind code describing the (only) epilogue. +/// +/// Otherwise, this field indicates the number of exception +/// scopes. If more than 31 scopes exist, then this field and +/// the Code Words field must both be set to 0 to indicate that +/// an extension word is required. +/// Code Words : 4-bit field that species the number of 32-bit words needed to +/// contain all the unwind codes. If more than 15 words (63 code +/// bytes) are required, then this field and the Epilogue Count +/// field must both be set to 0 to indicate that an extension word +/// is required. +/// Extended Epilogue Count, Extended Code Words : +/// Valid only if Epilog Count and Code Words are both +/// set to 0. Provides an 8-bit extended code word +/// count and 16-bits for epilogue count +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +----------------+------+---+---+-------------------------------+ +/// | Ep Start Idx | Cond |Res| Epilogue Start Offset | +/// +----------------+------+---+-----------------------------------+ +/// +/// If the E bit is unset in the header, the header is followed by a series of +/// epilogue scopes, which are sorted by their offset. +/// +/// Epilogue Start Offset: 18-bit field encoding the offset of epilogue relative +/// to the start of the function in bytes divided by two +/// Res : 2-bit field reserved for future expansion (must be set to 0) +/// Condition : 4-bit field providing the condition under which the epilogue is +/// executed. Unconditional epilogues should set this field to 0xe. +/// Epilogues must be entirely conditional or unconditional, and in +/// Thumb-2 mode. The epilogue beings with the first instruction +/// after the IT opcode. +/// Epilogue Start Index : 8-bit field indicating the byte index of the first +/// unwind code describing the epilogue +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +---------------+---------------+---------------+---------------+ +/// | Unwind Code 3 | Unwind Code 2 | Unwind Code 1 | Unwind Code 0 | +/// +---------------+---------------+---------------+---------------+ +/// +/// Following the epilogue scopes, the byte code describing the unwinding +/// follows. This is padded to align up to word alignment. Bytes are stored in +/// little endian. +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +---------------------------------------------------------------+ +/// | Exception Handler RVA (requires X = 1) | +/// +---------------------------------------------------------------+ +/// | (possibly followed by data required for exception handler) | +/// +---------------------------------------------------------------+ +/// +/// If the X bit is set in the header, the unwind byte code is followed by the +/// exception handler information. This constants of one Exception Handler RVA +/// which is the address to the exception handler, followed immediately by the +/// variable length data associated with the exception handler. +/// + +struct EpilogueScope { + const support::ulittle32_t ES; + + EpilogueScope(const support::ulittle32_t Data) : ES(Data) {} + uint32_t EpilogueStartOffset() const { + return (ES & 0x0003ffff); + } + uint8_t Res() const { + return ((ES & 0x000c0000) >> 18); + } + uint8_t Condition() const { + return ((ES & 0x00f00000) >> 20); + } + uint8_t EpilogueStartIndex() const { + return ((ES & 0xff000000) >> 24); + } +}; + +struct ExceptionDataRecord; +inline size_t HeaderWords(const ExceptionDataRecord &XR); + +struct ExceptionDataRecord { + const support::ulittle32_t *Data; + + ExceptionDataRecord(const support::ulittle32_t *Data) : Data(Data) {} + + uint32_t FunctionLength() const { + return (Data[0] & 0x0003ffff); + } + + uint8_t Vers() const { + return (Data[0] & 0x000C0000) >> 18; + } + + bool X() const { + return ((Data[0] & 0x00100000) >> 20); + } + + bool E() const { + return ((Data[0] & 0x00200000) >> 21); + } + + bool F() const { + return ((Data[0] & 0x00400000) >> 22); + } + + uint8_t EpilogueCount() const { + if (HeaderWords(*this) == 1) + return (Data[0] & 0x0f800000) >> 23; + return Data[1] & 0x0000ffff; + } + + uint8_t CodeWords() const { + if (HeaderWords(*this) == 1) + return (Data[0] & 0xf0000000) >> 28; + return (Data[1] & 0x00ff0000) >> 16; + } + + ArrayRef<support::ulittle32_t> EpilogueScopes() const { + assert(E() == 0 && "epilogue scopes are only present when the E bit is 0"); + size_t Offset = HeaderWords(*this); + return ArrayRef<support::ulittle32_t>(&Data[Offset], EpilogueCount()); + } + + ArrayRef<support::ulittle8_t> UnwindByteCode() const { + const size_t Offset = HeaderWords(*this) + + (E() ? 0 : EpilogueCount()); + const support::ulittle8_t *ByteCode = + reinterpret_cast<const support::ulittle8_t *>(&Data[Offset]); + return ArrayRef<support::ulittle8_t>(ByteCode, + CodeWords() * sizeof(uint32_t)); + } + + uint32_t ExceptionHandlerRVA() const { + assert(X() && "Exception Handler RVA is only valid if the X bit is set"); + return Data[HeaderWords(*this) + EpilogueCount() + CodeWords()]; + } + + uint32_t ExceptionHandlerParameter() const { + assert(X() && "Exception Handler RVA is only valid if the X bit is set"); + return Data[HeaderWords(*this) + EpilogueCount() + CodeWords() + 1]; + } +}; + +inline size_t HeaderWords(const ExceptionDataRecord &XR) { + return (XR.Data[0] & 0xff800000) ? 1 : 2; +} +} +} +} + +#endif + diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index bba34248569a..061d5acf2322 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -170,19 +170,22 @@ LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) namespace detail { template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char, - typename T5 = char, typename T6 = char, typename T7 = char> + typename T5 = char, typename T6 = char, typename T7 = char, + typename T8 = char, typename T9 = char, typename T10 = char> class AlignerImpl { - T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; + T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10; AlignerImpl(); // Never defined or instantiated. }; template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char, - typename T5 = char, typename T6 = char, typename T7 = char> + typename T5 = char, typename T6 = char, typename T7 = char, + typename T8 = char, typename T9 = char, typename T10 = char> union SizerImpl { char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)], - arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)]; + arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)], + arr9[sizeof(T9)], arr10[sizeof(T10)]; }; } // end namespace detail @@ -195,10 +198,13 @@ union SizerImpl { /// be added at the cost of more boiler plate. template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char, - typename T5 = char, typename T6 = char, typename T7 = char> + typename T5 = char, typename T6 = char, typename T7 = char, + typename T8 = char, typename T9 = char, typename T10 = char> struct AlignedCharArrayUnion : llvm::AlignedCharArray< - AlignOf<detail::AlignerImpl<T1, T2, T3, T4, T5, T6, T7> >::Alignment, - sizeof(detail::SizerImpl<T1, T2, T3, T4, T5, T6, T7>)> { + AlignOf<detail::AlignerImpl<T1, T2, T3, T4, T5, + T6, T7, T8, T9, T10> >::Alignment, + sizeof(detail::SizerImpl<T1, T2, T3, T4, T5, + T6, T7, T8, T9, T10>)> { }; } // end namespace llvm #endif diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index 397f50fbe360..7a7e4c0a13e2 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -6,227 +6,408 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the MallocAllocator and BumpPtrAllocator interfaces. -// +/// \file +/// +/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both +/// of these conform to an LLVM "Allocator" concept which consists of an +/// Allocate method accepting a size and alignment, and a Deallocate accepting +/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of +/// Allocate and Deallocate for setting size and alignment based on the final +/// type. These overloads are typically provided by a base class template \c +/// AllocatorBase. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_ALLOCATOR_H #define LLVM_SUPPORT_ALLOCATOR_H +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Memory.h" #include <algorithm> #include <cassert> #include <cstddef> #include <cstdlib> namespace llvm { -template <typename T> struct ReferenceAdder { typedef T& result; }; -template <typename T> struct ReferenceAdder<T&> { typedef T result; }; -class MallocAllocator { +/// \brief CRTP base class providing obvious overloads for the core \c +/// Allocate() methods of LLVM-style allocators. +/// +/// This base class both documents the full public interface exposed by all +/// LLVM-style allocators, and redirects all of the overloads to a single core +/// set of methods which the derived class must define. +template <typename DerivedT> class AllocatorBase { public: - MallocAllocator() {} - ~MallocAllocator() {} + /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method + /// must be implemented by \c DerivedT. + void *Allocate(size_t Size, size_t Alignment) { +#ifdef __clang__ + static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>( + &AllocatorBase::Allocate) != + static_cast<void *(DerivedT::*)(size_t, size_t)>( + &DerivedT::Allocate), + "Class derives from AllocatorBase without implementing the " + "core Allocate(size_t, size_t) overload!"); +#endif + return static_cast<DerivedT *>(this)->Allocate(Size, Alignment); + } + + /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this + /// allocator. + void Deallocate(const void *Ptr, size_t Size) { +#ifdef __clang__ + static_assert(static_cast<void (AllocatorBase::*)(const void *, size_t)>( + &AllocatorBase::Deallocate) != + static_cast<void (DerivedT::*)(const void *, size_t)>( + &DerivedT::Deallocate), + "Class derives from AllocatorBase without implementing the " + "core Deallocate(void *) overload!"); +#endif + return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size); + } + + // The rest of these methods are helpers that redirect to one of the above + // core methods. + + /// \brief Allocate space for a sequence of objects without constructing them. + template <typename T> T *Allocate(size_t Num = 1) { + return static_cast<T *>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment)); + } + /// \brief Deallocate space for a sequence of objects without constructing them. + template <typename T> + typename std::enable_if< + !std::is_same<typename std::remove_cv<T>::type, void>::value, void>::type + Deallocate(T *Ptr, size_t Num = 1) { + Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T)); + } +}; + +class MallocAllocator : public AllocatorBase<MallocAllocator> { +public: void Reset() {} void *Allocate(size_t Size, size_t /*Alignment*/) { return malloc(Size); } - template <typename T> - T *Allocate() { return static_cast<T*>(malloc(sizeof(T))); } + // Pull in base class overloads. + using AllocatorBase<MallocAllocator>::Allocate; - template <typename T> - T *Allocate(size_t Num) { - return static_cast<T*>(malloc(sizeof(T)*Num)); + void Deallocate(const void *Ptr, size_t /*Size*/) { + free(const_cast<void *>(Ptr)); } - void Deallocate(const void *Ptr) { free(const_cast<void*>(Ptr)); } + // Pull in base class overloads. + using AllocatorBase<MallocAllocator>::Deallocate; void PrintStats() const {} }; -/// MemSlab - This structure lives at the beginning of every slab allocated by -/// the bump allocator. -class MemSlab { +namespace detail { + +// We call out to an external function to actually print the message as the +// printing code uses Allocator.h in its implementation. +void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, + size_t TotalMemory); +} // End namespace detail. + +/// \brief Allocate memory in an ever growing pool, as if by bump-pointer. +/// +/// This isn't strictly a bump-pointer allocator as it uses backing slabs of +/// memory rather than relying on boundless contiguous heap. However, it has +/// bump-pointer semantics in that is a monotonically growing pool of memory +/// where every allocation is found by merely allocating the next N bytes in +/// the slab, or the next N bytes in the next slab. +/// +/// Note that this also has a threshold for forcing allocations above a certain +/// size into their own slab. +/// +/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator +/// object, which wraps malloc, to allocate memory, but it can be changed to +/// use a custom allocator. +template <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096, + size_t SizeThreshold = SlabSize> +class BumpPtrAllocatorImpl + : public AllocatorBase< + BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>> { public: - size_t Size; - MemSlab *NextPtr; -}; + static_assert(SizeThreshold <= SlabSize, + "The SizeThreshold must be at most the SlabSize to ensure " + "that objects larger than a slab go into their own memory " + "allocation."); -/// SlabAllocator - This class can be used to parameterize the underlying -/// allocation strategy for the bump allocator. In particular, this is used -/// by the JIT to allocate contiguous swathes of executable memory. The -/// interface uses MemSlab's instead of void *'s so that the allocator -/// doesn't have to remember the size of the pointer it allocated. -class SlabAllocator { -public: - virtual ~SlabAllocator(); - virtual MemSlab *Allocate(size_t Size) = 0; - virtual void Deallocate(MemSlab *Slab) = 0; -}; + BumpPtrAllocatorImpl() + : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {} + template <typename T> + BumpPtrAllocatorImpl(T &&Allocator) + : CurPtr(nullptr), End(nullptr), BytesAllocated(0), + Allocator(std::forward<T &&>(Allocator)) {} + + // Manually implement a move constructor as we must clear the old allocators + // slabs as a matter of correctness. + BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) + : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), + CustomSizedSlabs(std::move(Old.CustomSizedSlabs)), + BytesAllocated(Old.BytesAllocated), + Allocator(std::move(Old.Allocator)) { + Old.CurPtr = Old.End = nullptr; + Old.BytesAllocated = 0; + Old.Slabs.clear(); + Old.CustomSizedSlabs.clear(); + } -/// MallocSlabAllocator - The default slab allocator for the bump allocator -/// is an adapter class for MallocAllocator that just forwards the method -/// calls and translates the arguments. -class MallocSlabAllocator : public SlabAllocator { - /// Allocator - The underlying allocator that we forward to. - /// - MallocAllocator Allocator; + ~BumpPtrAllocatorImpl() { + DeallocateSlabs(Slabs.begin(), Slabs.end()); + DeallocateCustomSizedSlabs(); + } -public: - MallocSlabAllocator() : Allocator() { } - virtual ~MallocSlabAllocator(); - virtual MemSlab *Allocate(size_t Size) LLVM_OVERRIDE; - virtual void Deallocate(MemSlab *Slab) LLVM_OVERRIDE; -}; + BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) { + DeallocateSlabs(Slabs.begin(), Slabs.end()); + DeallocateCustomSizedSlabs(); + + CurPtr = RHS.CurPtr; + End = RHS.End; + BytesAllocated = RHS.BytesAllocated; + Slabs = std::move(RHS.Slabs); + CustomSizedSlabs = std::move(RHS.CustomSizedSlabs); + Allocator = std::move(RHS.Allocator); + + RHS.CurPtr = RHS.End = nullptr; + RHS.BytesAllocated = 0; + RHS.Slabs.clear(); + RHS.CustomSizedSlabs.clear(); + return *this; + } -/// BumpPtrAllocator - This allocator is useful for containers that need -/// very simple memory allocation strategies. In particular, this just keeps -/// allocating memory, and never deletes it until the entire block is dead. This -/// makes allocation speedy, but must only be used when the trade-off is ok. -class BumpPtrAllocator { - BumpPtrAllocator(const BumpPtrAllocator &) LLVM_DELETED_FUNCTION; - void operator=(const BumpPtrAllocator &) LLVM_DELETED_FUNCTION; + /// \brief Deallocate all but the current slab and reset the current pointer + /// to the beginning of it, freeing all memory allocated so far. + void Reset() { + if (Slabs.empty()) + return; + + // Reset the state. + BytesAllocated = 0; + CurPtr = (char *)Slabs.front(); + End = CurPtr + SlabSize; + + // Deallocate all but the first slab, and all custome sized slabs. + DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); + Slabs.erase(std::next(Slabs.begin()), Slabs.end()); + DeallocateCustomSizedSlabs(); + CustomSizedSlabs.clear(); + } - /// SlabSize - Allocate data into slabs of this size unless we get an - /// allocation above SizeThreshold. - size_t SlabSize; + /// \brief Allocate space at the specified alignment. + void *Allocate(size_t Size, size_t Alignment) { + if (!CurPtr) // Start a new slab if we haven't allocated one already. + StartNewSlab(); + + // Keep track of how many bytes we've allocated. + BytesAllocated += Size; + + // 0-byte alignment means 1-byte alignment. + if (Alignment == 0) + Alignment = 1; + + // Allocate the aligned space, going forwards from CurPtr. + char *Ptr = alignPtr(CurPtr, Alignment); + + // Check if we can hold it. + if (Ptr + Size <= End) { + CurPtr = Ptr + Size; + // Update the allocation point of this memory block in MemorySanitizer. + // Without this, MemorySanitizer messages for values originated from here + // will point to the allocation of the entire slab. + __msan_allocated_memory(Ptr, Size); + return Ptr; + } - /// SizeThreshold - For any allocation larger than this threshold, we should - /// allocate a separate slab. - size_t SizeThreshold; + // If Size is really big, allocate a separate slab for it. + size_t PaddedSize = Size + Alignment - 1; + if (PaddedSize > SizeThreshold) { + void *NewSlab = Allocator.Allocate(PaddedSize, 0); + CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize)); - /// \brief the default allocator used if one is not provided - MallocSlabAllocator DefaultSlabAllocator; + Ptr = alignPtr((char *)NewSlab, Alignment); + assert((uintptr_t)Ptr + Size <= (uintptr_t)NewSlab + PaddedSize); + __msan_allocated_memory(Ptr, Size); + return Ptr; + } - /// Allocator - The underlying allocator we use to get slabs of memory. This - /// defaults to MallocSlabAllocator, which wraps malloc, but it could be - /// changed to use a custom allocator. - SlabAllocator &Allocator; + // Otherwise, start a new slab and try again. + StartNewSlab(); + Ptr = alignPtr(CurPtr, Alignment); + CurPtr = Ptr + Size; + assert(CurPtr <= End && "Unable to allocate memory!"); + __msan_allocated_memory(Ptr, Size); + return Ptr; + } - /// CurSlab - The slab that we are currently allocating into. - /// - MemSlab *CurSlab; + // Pull in base class overloads. + using AllocatorBase<BumpPtrAllocatorImpl>::Allocate; - /// CurPtr - The current pointer into the current slab. This points to the - /// next free byte in the slab. - char *CurPtr; + void Deallocate(const void * /*Ptr*/, size_t /*Size*/) {} - /// End - The end of the current slab. - /// - char *End; + // Pull in base class overloads. + using AllocatorBase<BumpPtrAllocatorImpl>::Deallocate; - /// BytesAllocated - This field tracks how many bytes we've allocated, so - /// that we can compute how much space was wasted. - size_t BytesAllocated; + size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); } - /// AlignPtr - Align Ptr to Alignment bytes, rounding up. Alignment should - /// be a power of two. This method rounds up, so AlignPtr(7, 4) == 8 and - /// AlignPtr(8, 4) == 8. - static char *AlignPtr(char *Ptr, size_t Alignment); + size_t getTotalMemory() const { + size_t TotalMemory = 0; + for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I) + TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I)); + for (auto &PtrAndSize : CustomSizedSlabs) + TotalMemory += PtrAndSize.second; + return TotalMemory; + } - /// StartNewSlab - Allocate a new slab and move the bump pointers over into - /// the new slab. Modifies CurPtr and End. - void StartNewSlab(); + void PrintStats() const { + detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated, + getTotalMemory()); + } - /// DeallocateSlabs - Deallocate all memory slabs after and including this - /// one. - void DeallocateSlabs(MemSlab *Slab); +private: + /// \brief The current pointer into the current slab. + /// + /// This points to the next free byte in the slab. + char *CurPtr; - template<typename T> friend class SpecificBumpPtrAllocator; -public: - BumpPtrAllocator(size_t size = 4096, size_t threshold = 4096); - BumpPtrAllocator(size_t size, size_t threshold, SlabAllocator &allocator); - ~BumpPtrAllocator(); + /// \brief The end of the current slab. + char *End; - /// Reset - Deallocate all but the current slab and reset the current pointer - /// to the beginning of it, freeing all memory allocated so far. - void Reset(); + /// \brief The slabs allocated so far. + SmallVector<void *, 4> Slabs; - /// Allocate - Allocate space at the specified alignment. - /// - void *Allocate(size_t Size, size_t Alignment); + /// \brief Custom-sized slabs allocated for too-large allocation requests. + SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs; - /// Allocate space, but do not construct, one object. + /// \brief How many bytes we've allocated. /// - template <typename T> - T *Allocate() { - return static_cast<T*>(Allocate(sizeof(T),AlignOf<T>::Alignment)); - } + /// Used so that we can compute how much space was wasted. + size_t BytesAllocated; - /// Allocate space for an array of objects. This does not construct the - /// objects though. - template <typename T> - T *Allocate(size_t Num) { - return static_cast<T*>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment)); + /// \brief The allocator instance we use to get slabs of memory. + AllocatorT Allocator; + + static size_t computeSlabSize(unsigned SlabIdx) { + // Scale the actual allocated slab size based on the number of slabs + // allocated. Every 128 slabs allocated, we double the allocated size to + // reduce allocation frequency, but saturate at multiplying the slab size by + // 2^30. + return SlabSize * ((size_t)1 << std::min<size_t>(30, SlabIdx / 128)); } - /// Allocate space for a specific count of elements and with a specified - /// alignment. - template <typename T> - T *Allocate(size_t Num, size_t Alignment) { - // Round EltSize up to the specified alignment. - size_t EltSize = (sizeof(T)+Alignment-1)&(-Alignment); - return static_cast<T*>(Allocate(Num * EltSize, Alignment)); + /// \brief Allocate a new slab and move the bump pointers over into the new + /// slab, modifying CurPtr and End. + void StartNewSlab() { + size_t AllocatedSlabSize = computeSlabSize(Slabs.size()); + + void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0); + Slabs.push_back(NewSlab); + CurPtr = (char *)(NewSlab); + End = ((char *)NewSlab) + AllocatedSlabSize; } - void Deallocate(const void * /*Ptr*/) {} + /// \brief Deallocate a sequence of slabs. + void DeallocateSlabs(SmallVectorImpl<void *>::iterator I, + SmallVectorImpl<void *>::iterator E) { + for (; I != E; ++I) { + size_t AllocatedSlabSize = + computeSlabSize(std::distance(Slabs.begin(), I)); +#ifndef NDEBUG + // Poison the memory so stale pointers crash sooner. Note we must + // preserve the Size and NextPtr fields at the beginning. + sys::Memory::setRangeWritable(*I, AllocatedSlabSize); + memset(*I, 0xCD, AllocatedSlabSize); +#endif + Allocator.Deallocate(*I, AllocatedSlabSize); + } + } - unsigned GetNumSlabs() const; + /// \brief Deallocate all memory for custom sized slabs. + void DeallocateCustomSizedSlabs() { + for (auto &PtrAndSize : CustomSizedSlabs) { + void *Ptr = PtrAndSize.first; + size_t Size = PtrAndSize.second; +#ifndef NDEBUG + // Poison the memory so stale pointers crash sooner. Note we must + // preserve the Size and NextPtr fields at the beginning. + sys::Memory::setRangeWritable(Ptr, Size); + memset(Ptr, 0xCD, Size); +#endif + Allocator.Deallocate(Ptr, Size); + } + } - void PrintStats() const; - - /// Compute the total physical memory allocated by this allocator. - size_t getTotalMemory() const; + template <typename T> friend class SpecificBumpPtrAllocator; }; -/// SpecificBumpPtrAllocator - Same as BumpPtrAllocator but allows only -/// elements of one type to be allocated. This allows calling the destructor -/// in DestroyAll() and when the allocator is destroyed. -template <typename T> -class SpecificBumpPtrAllocator { +/// \brief The standard BumpPtrAllocator which just uses the default template +/// paramaters. +typedef BumpPtrAllocatorImpl<> BumpPtrAllocator; + +/// \brief A BumpPtrAllocator that allows only elements of a specific type to be +/// allocated. +/// +/// This allows calling the destructor in DestroyAll() and when the allocator is +/// destroyed. +template <typename T> class SpecificBumpPtrAllocator { BumpPtrAllocator Allocator; -public: - SpecificBumpPtrAllocator(size_t size = 4096, size_t threshold = 4096) - : Allocator(size, threshold) {} - SpecificBumpPtrAllocator(size_t size, size_t threshold, - SlabAllocator &allocator) - : Allocator(size, threshold, allocator) {} - ~SpecificBumpPtrAllocator() { - DestroyAll(); +public: + SpecificBumpPtrAllocator() : Allocator() {} + SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old) + : Allocator(std::move(Old.Allocator)) {} + ~SpecificBumpPtrAllocator() { DestroyAll(); } + + SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) { + Allocator = std::move(RHS.Allocator); + return *this; } /// Call the destructor of each allocated object and deallocate all but the /// current slab and reset the current pointer to the beginning of it, freeing /// all memory allocated so far. void DestroyAll() { - MemSlab *Slab = Allocator.CurSlab; - while (Slab) { - char *End = Slab == Allocator.CurSlab ? Allocator.CurPtr : - (char *)Slab + Slab->Size; - for (char *Ptr = (char*)(Slab+1); Ptr < End; Ptr += sizeof(T)) { - Ptr = Allocator.AlignPtr(Ptr, alignOf<T>()); - if (Ptr + sizeof(T) <= End) - reinterpret_cast<T*>(Ptr)->~T(); - } - Slab = Slab->NextPtr; + auto DestroyElements = [](char *Begin, char *End) { + assert(Begin == alignPtr(Begin, alignOf<T>())); + for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T)) + reinterpret_cast<T *>(Ptr)->~T(); + }; + + for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E; + ++I) { + size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize( + std::distance(Allocator.Slabs.begin(), I)); + char *Begin = alignPtr((char *)*I, alignOf<T>()); + char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr + : (char *)*I + AllocatedSlabSize; + + DestroyElements(Begin, End); + } + + for (auto &PtrAndSize : Allocator.CustomSizedSlabs) { + void *Ptr = PtrAndSize.first; + size_t Size = PtrAndSize.second; + DestroyElements(alignPtr((char *)Ptr, alignOf<T>()), (char *)Ptr + Size); } + Allocator.Reset(); } - /// Allocate space for a specific count of elements. - T *Allocate(size_t num = 1) { - return Allocator.Allocate<T>(num); - } + /// \brief Allocate space for an array of objects without constructing them. + T *Allocate(size_t num = 1) { return Allocator.Allocate<T>(num); } }; } // end namespace llvm -inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) { +template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold> +void *operator new(size_t Size, + llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, + SizeThreshold> &Allocator) { struct S { char c; union { @@ -236,10 +417,13 @@ inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) { void *P; } x; }; - return Allocator.Allocate(Size, std::min((size_t)llvm::NextPowerOf2(Size), - offsetof(S, x))); + return Allocator.Allocate( + Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x))); } -inline void operator delete(void *, llvm::BumpPtrAllocator &) {} +template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold> +void operator delete( + void *, llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold> &) { +} #endif // LLVM_SUPPORT_ALLOCATOR_H diff --git a/include/llvm/Support/ArrayRecycler.h b/include/llvm/Support/ArrayRecycler.h index c7e0cba279e6..36f644af2880 100644 --- a/include/llvm/Support/ArrayRecycler.h +++ b/include/llvm/Support/ArrayRecycler.h @@ -16,12 +16,11 @@ #define LLVM_SUPPORT_ARRAYRECYCLER_H #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/MathExtras.h" namespace llvm { -class BumpPtrAllocator; - /// Recycle small arrays allocated from a BumpPtrAllocator. /// /// Arrays are allocated in a small number of fixed sizes. For each supported @@ -35,6 +34,9 @@ class ArrayRecycler { FreeList *Next; }; + static_assert(Align >= AlignOf<FreeList>::Alignment, "Object underaligned"); + static_assert(sizeof(T) >= sizeof(FreeList), "Objects are too small"); + // Keep a free list for each array size. SmallVector<FreeList*, 8> Bucket; @@ -42,10 +44,10 @@ class ArrayRecycler { // Return NULL if no entries are available. T *pop(unsigned Idx) { if (Idx >= Bucket.size()) - return 0; + return nullptr; FreeList *Entry = Bucket[Idx]; if (!Entry) - return 0; + return nullptr; Bucket[Idx] = Entry->Next; return reinterpret_cast<T*>(Entry); } @@ -53,8 +55,6 @@ class ArrayRecycler { // Add an entry to the free list at Bucket[Idx]. void push(unsigned Idx, T *Ptr) { assert(Ptr && "Cannot recycle NULL pointer"); - assert(sizeof(T) >= sizeof(FreeList) && "Objects are too small"); - assert(Align >= AlignOf<FreeList>::Alignment && "Object underaligned"); FreeList *Entry = reinterpret_cast<FreeList*>(Ptr); if (Idx >= Bucket.size()) Bucket.resize(size_t(Idx) + 1); diff --git a/include/llvm/Support/BlockFrequency.h b/include/llvm/Support/BlockFrequency.h index 21879e7cbe41..4304a253b287 100644 --- a/include/llvm/Support/BlockFrequency.h +++ b/include/llvm/Support/BlockFrequency.h @@ -23,21 +23,11 @@ class BranchProbability; // This class represents Block Frequency as a 64-bit value. class BlockFrequency { - uint64_t Frequency; - static const int64_t ENTRY_FREQ = 1 << 14; - - /// \brief Scale the given BlockFrequency by N/D. Return the remainder from - /// the division by D. Upon overflow, the routine will saturate and - /// additionally will return the remainder set to D. - uint32_t scale(uint32_t N, uint32_t D); public: BlockFrequency(uint64_t Freq = 0) : Frequency(Freq) { } - /// \brief Returns the frequency of the entry block of the function. - static uint64_t getEntryFrequency() { return ENTRY_FREQ; } - /// \brief Returns the maximum possible frequency, the saturation value. static uint64_t getMaxFrequency() { return -1ULL; } @@ -59,9 +49,8 @@ public: BlockFrequency &operator+=(const BlockFrequency &Freq); const BlockFrequency operator+(const BlockFrequency &Freq) const; - /// \brief Scale the given BlockFrequency by N/D. Return the remainder from - /// the division by D. Upon overflow, the routine will saturate. - uint32_t scale(const BranchProbability &Prob); + /// \brief Shift block frequency to the right by count digits saturating to 1. + BlockFrequency &operator>>=(const unsigned count); bool operator<(const BlockFrequency &RHS) const { return Frequency < RHS.Frequency; @@ -78,12 +67,8 @@ public: bool operator>=(const BlockFrequency &RHS) const { return Frequency >= RHS.Frequency; } - - void print(raw_ostream &OS) const; }; -raw_ostream &operator<<(raw_ostream &OS, const BlockFrequency &Freq); - } #endif diff --git a/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h index eedf69247ef5..9aab6ace6e3f 100644 --- a/include/llvm/Support/BranchProbability.h +++ b/include/llvm/Support/BranchProbability.h @@ -46,10 +46,26 @@ public: return BranchProbability(D - N, D); } - void print(raw_ostream &OS) const; + raw_ostream &print(raw_ostream &OS) const; void dump() const; + /// \brief Scale a large integer. + /// + /// Scales \c Num. Guarantees full precision. Returns the floor of the + /// result. + /// + /// \return \c Num times \c this. + uint64_t scale(uint64_t Num) const; + + /// \brief Scale a large integer by the inverse. + /// + /// Scales \c Num by the inverse of \c this. Guarantees full precision. + /// Returns the floor of the result. + /// + /// \return \c Num divided by \c this. + uint64_t scaleByInverse(uint64_t Num) const; + bool operator==(BranchProbability RHS) const { return (uint64_t)N * RHS.D == (uint64_t)D * RHS.N; } @@ -59,18 +75,14 @@ public: bool operator<(BranchProbability RHS) const { return (uint64_t)N * RHS.D < (uint64_t)D * RHS.N; } - bool operator>(BranchProbability RHS) const { - return RHS < *this; - } - bool operator<=(BranchProbability RHS) const { - return (uint64_t)N * RHS.D <= (uint64_t)D * RHS.N; - } - bool operator>=(BranchProbability RHS) const { - return RHS <= *this; - } + bool operator>(BranchProbability RHS) const { return RHS < *this; } + bool operator<=(BranchProbability RHS) const { return !(RHS < *this); } + bool operator>=(BranchProbability RHS) const { return !(*this < RHS); } }; -raw_ostream &operator<<(raw_ostream &OS, const BranchProbability &Prob); +inline raw_ostream &operator<<(raw_ostream &OS, const BranchProbability &Prob) { + return Prob.print(OS); +} } diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 9cc3989df043..e09ef07d81db 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -30,6 +30,9 @@ namespace llvm { namespace COFF { + // The maximum number of sections that a COFF object can have (inclusive). + const int MaxNumberOfSections = 65299; + // The PE signature bytes that follows the DOS stub header. static const char PEMagic[] = { 'P', 'E', '\0', '\0' }; @@ -59,7 +62,7 @@ namespace COFF { IMAGE_FILE_MACHINE_AM33 = 0x13, IMAGE_FILE_MACHINE_AMD64 = 0x8664, IMAGE_FILE_MACHINE_ARM = 0x1C0, - IMAGE_FILE_MACHINE_ARMV7 = 0x1C4, + IMAGE_FILE_MACHINE_ARMNT = 0x1C4, IMAGE_FILE_MACHINE_EBC = 0xEBC, IMAGE_FILE_MACHINE_I386 = 0x14C, IMAGE_FILE_MACHINE_IA64 = 0x200, @@ -138,8 +141,8 @@ namespace COFF { }; enum SymbolSectionNumber { - IMAGE_SYM_DEBUG = -2, - IMAGE_SYM_ABSOLUTE = -1, + IMAGE_SYM_DEBUG = 0xFFFE, + IMAGE_SYM_ABSOLUTE = 0xFFFF, IMAGE_SYM_UNDEFINED = 0 }; @@ -209,6 +212,10 @@ namespace COFF { SCT_COMPLEX_TYPE_SHIFT = 4 }; + enum AuxSymbolType { + IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF = 1 + }; + struct section { char Name[NameSize]; uint32_t VirtualSize; @@ -222,7 +229,7 @@ namespace COFF { uint32_t Characteristics; }; - enum SectionCharacteristics LLVM_ENUM_INT_TYPE(uint32_t) { + enum SectionCharacteristics : uint32_t { SC_Invalid = 0xffffffff, IMAGE_SCN_TYPE_NO_PAD = 0x00000008, @@ -268,7 +275,7 @@ namespace COFF { uint16_t Type; }; - enum RelocationTypeX86 { + enum RelocationTypeI386 { IMAGE_REL_I386_ABSOLUTE = 0x0000, IMAGE_REL_I386_DIR16 = 0x0001, IMAGE_REL_I386_REL16 = 0x0002, @@ -279,8 +286,10 @@ namespace COFF { IMAGE_REL_I386_SECREL = 0x000B, IMAGE_REL_I386_TOKEN = 0x000C, IMAGE_REL_I386_SECREL7 = 0x000D, - IMAGE_REL_I386_REL32 = 0x0014, + IMAGE_REL_I386_REL32 = 0x0014 + }; + enum RelocationTypeAMD64 { IMAGE_REL_AMD64_ABSOLUTE = 0x0000, IMAGE_REL_AMD64_ADDR64 = 0x0001, IMAGE_REL_AMD64_ADDR32 = 0x0002, @@ -334,7 +343,7 @@ namespace COFF { uint32_t TotalSize; uint32_t PointerToLinenumber; uint32_t PointerToNextFunction; - uint8_t unused[2]; + char unused[2]; }; struct AuxiliarybfAndefSymbol { @@ -369,7 +378,14 @@ namespace COFF { uint32_t CheckSum; uint16_t Number; uint8_t Selection; - uint8_t unused[3]; + char unused[3]; + }; + + struct AuxiliaryCLRToken { + uint8_t AuxType; + uint8_t unused1; + uint32_t SymbolTableIndex; + char unused2[12]; }; union Auxiliary { @@ -450,7 +466,12 @@ namespace COFF { uint32_t AddressOfNewExeHeader; }; - struct PEHeader { + struct PE32Header { + enum { + PE32 = 0x10b, + PE32_PLUS = 0x20b + }; + uint16_t Magic; uint8_t MajorLinkerVersion; uint8_t MinorLinkerVersion; @@ -460,7 +481,7 @@ namespace COFF { uint32_t AddressOfEntryPoint; // RVA uint32_t BaseOfCode; // RVA uint32_t BaseOfData; // RVA - uint64_t ImageBase; + uint32_t ImageBase; uint32_t SectionAlignment; uint32_t FileAlignment; uint16_t MajorOperatingSystemVersion; @@ -475,10 +496,10 @@ namespace COFF { uint32_t CheckSum; uint16_t Subsystem; uint16_t DLLCharacteristics; - uint64_t SizeOfStackReserve; - uint64_t SizeOfStackCommit; - uint64_t SizeOfHeapReserve; - uint64_t SizeOfHeapCommit; + uint32_t SizeOfStackReserve; + uint32_t SizeOfStackCommit; + uint32_t SizeOfHeapReserve; + uint32_t SizeOfHeapCommit; uint32_t LoaderFlags; uint32_t NumberOfRvaAndSize; }; @@ -526,11 +547,14 @@ namespace COFF { }; enum DLLCharacteristics { + /// ASLR with 64 bit address space. + IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020, /// DLL can be relocated at load time. IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040, /// Code integrity checks are enforced. IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080, - IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, ///< Image is NX compatible. + ///< Image is NX compatible. + IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, /// Isolation aware, but do not isolate the image. IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200, /// Does not use structured exception handling (SEH). No SEH handler may be @@ -538,7 +562,12 @@ namespace COFF { IMAGE_DLL_CHARACTERISTICS_NO_SEH = 0x0400, /// Do not bind the image. IMAGE_DLL_CHARACTERISTICS_NO_BIND = 0x0800, - IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000, ///< A WDM driver. + ///< Image should execute in an AppContainer. + IMAGE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000, + ///< A WDM driver. + IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000, + ///< Image supports Control Flow Guard. + IMAGE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000, /// Terminal Server aware. IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 }; @@ -611,6 +640,17 @@ namespace COFF { } }; + enum CodeViewLineTableIdentifiers { + DEBUG_SECTION_MAGIC = 0x4, + DEBUG_LINE_TABLE_SUBSECTION = 0xF2, + DEBUG_STRING_TABLE_SUBSECTION = 0xF3, + DEBUG_INDEX_SUBSECTION = 0xF4 + }; + + inline bool isReservedSectionNumber(int N) { + return N == IMAGE_SYM_UNDEFINED || N > MaxNumberOfSections; + } + } // End namespace COFF. } // End namespace llvm. diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index d70acbf24c42..beed31a4084f 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -15,6 +15,7 @@ #ifndef LLVM_SUPPORT_CASTING_H #define LLVM_SUPPORT_CASTING_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/type_traits.h" #include <cassert> @@ -58,11 +59,8 @@ struct isa_impl { /// \brief Always allow upcasts, and perform no dynamic check for them. template <typename To, typename From> -struct isa_impl<To, From, - typename enable_if< - llvm::is_base_of<To, From> - >::type - > { +struct isa_impl< + To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> { static inline bool doit(const From &) { return true; } }; @@ -131,7 +129,7 @@ struct isa_impl_wrap<To, FromTy, FromTy> { // if (isa<Type>(myVal)) { ... } // template <class X, class Y> -inline bool isa(const Y &Val) { +LLVM_ATTRIBUTE_UNUSED_RESULT inline bool isa(const Y &Val) { return isa_impl_wrap<X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val); } @@ -208,7 +206,7 @@ template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { template <class X> struct is_simple_type { static const bool value = - is_same<X, typename simplify_type<X>::SimpleType>::value; + std::is_same<X, typename simplify_type<X>::SimpleType>::value; }; // cast<X> - Return the argument parameter cast to the specified type. This @@ -219,8 +217,8 @@ template <class X> struct is_simple_type { // cast<Instruction>(myVal)->getParent() // template <class X, class Y> -inline typename enable_if_c<!is_simple_type<Y>::value, - typename cast_retty<X, const Y>::ret_type>::type +inline typename std::enable_if<!is_simple_type<Y>::value, + typename cast_retty<X, const Y>::ret_type>::type cast(const Y &Val) { assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); return cast_convert_val< @@ -245,8 +243,9 @@ inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) { // accepted. // template <class X, class Y> -inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { - if (Val == 0) return 0; +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +cast_or_null(Y *Val) { + if (!Val) return nullptr; assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); return cast<X>(Val); } @@ -261,28 +260,31 @@ inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { // template <class X, class Y> -inline typename enable_if_c<!is_simple_type<Y>::value, - typename cast_retty<X, const Y>::ret_type>::type +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type dyn_cast(const Y &Val) { - return isa<X>(Val) ? cast<X>(Val) : 0; + return isa<X>(Val) ? cast<X>(Val) : nullptr; } template <class X, class Y> -inline typename cast_retty<X, Y>::ret_type dyn_cast(Y &Val) { - return isa<X>(Val) ? cast<X>(Val) : 0; +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y>::ret_type +dyn_cast(Y &Val) { + return isa<X>(Val) ? cast<X>(Val) : nullptr; } template <class X, class Y> -inline typename cast_retty<X, Y *>::ret_type dyn_cast(Y *Val) { - return isa<X>(Val) ? cast<X>(Val) : 0; +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +dyn_cast(Y *Val) { + return isa<X>(Val) ? cast<X>(Val) : nullptr; } // dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null // value is accepted. // template <class X, class Y> -inline typename cast_retty<X, Y*>::ret_type dyn_cast_or_null(Y *Val) { - return (Val && isa<X>(Val)) ? cast<X>(Val) : 0; +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +dyn_cast_or_null(Y *Val) { + return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; } } // End llvm namespace diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 4efb6a67cf62..fdd901200fe9 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -21,10 +21,9 @@ #define LLVM_SUPPORT_COMMANDLINE_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Twine.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/type_traits.h" #include <cassert> #include <climits> #include <cstdarg> @@ -42,14 +41,14 @@ namespace cl { // ParseCommandLineOptions - Command line option processing entry point. // void ParseCommandLineOptions(int argc, const char * const *argv, - const char *Overview = 0); + const char *Overview = nullptr); //===----------------------------------------------------------------------===// // ParseEnvironmentOptions - Environment variable option processing alternate // entry point. // void ParseEnvironmentOptions(const char *progName, const char *envvar, - const char *Overview = 0); + const char *Overview = nullptr); ///===---------------------------------------------------------------------===// /// SetVersionPrinter - Override the default (LLVM specific) version printer @@ -147,10 +146,10 @@ private: const char *const Description; void registerCategory(); public: - OptionCategory(const char *const Name, const char *const Description = 0) + OptionCategory(const char *const Name, const char *const Description = nullptr) : Name(Name), Description(Description) { registerCategory(); } - const char *getName() { return Name; } - const char *getDescription() { return Description; } + const char *getName() const { return Name; } + const char *getDescription() const { return Description; } }; // The general Option Category (used as default category). @@ -239,7 +238,7 @@ protected: enum OptionHidden Hidden) : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), - Position(0), AdditionalVals(0), NextRegistered(0), + Position(0), AdditionalVals(0), NextRegistered(nullptr), ArgStr(""), HelpStr(""), ValueStr(""), Category(&GeneralCategory) { } @@ -249,6 +248,12 @@ public: // void addArgument(); + /// Unregisters this option from the CommandLine system. + /// + /// This option must have been the last option registered. + /// For testing purposes only. + void removeArgument(); + Option *getNextRegisteredOption() const { return NextRegistered; } // Return the width of the option tag for printing... @@ -265,8 +270,8 @@ public: // addOccurrence - Wrapper around handleOccurrence that enforces Flags. // - bool addOccurrence(unsigned pos, StringRef ArgName, - StringRef Value, bool MultiArg = false); + virtual bool addOccurrence(unsigned pos, StringRef ArgName, + StringRef Value, bool MultiArg = false); // Prints option name followed by message. Always returns true. bool error(const Twine &Message, StringRef ArgName = StringRef()); @@ -374,7 +379,9 @@ struct OptionValueBase : public GenericOptionValue { bool compare(const DataType &/*V*/) const { return false; } - virtual bool compare(const GenericOptionValue& /*V*/) const { return false; } + bool compare(const GenericOptionValue& /*V*/) const override { + return false; + } }; // Simple copy of the option value. @@ -398,7 +405,7 @@ public: return Valid && (Value != V); } - virtual bool compare(const GenericOptionValue &V) const { + bool compare(const GenericOptionValue &V) const override { const OptionValueCopy<DataType> &VC = static_cast< const OptionValueCopy<DataType>& >(V); if (!VC.hasValue()) return false; @@ -414,7 +421,7 @@ struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> { // Top-level option class. template<class DataType> -struct OptionValue : OptionValueBase<DataType, is_class<DataType>::value> { +struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> { OptionValue() {} OptionValue(const DataType& V) { @@ -444,7 +451,7 @@ struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> { return *this; } private: - virtual void anchor(); + void anchor() override; }; template<> @@ -461,7 +468,7 @@ struct OptionValue<std::string> : OptionValueCopy<std::string> { return *this; } private: - virtual void anchor(); + void anchor() override; }; //===----------------------------------------------------------------------===// @@ -640,14 +647,14 @@ public: typedef DataType parser_data_type; // Implement virtual functions needed by generic_parser_base - unsigned getNumOptions() const { return unsigned(Values.size()); } - const char *getOption(unsigned N) const { return Values[N].Name; } - const char *getDescription(unsigned N) const { + unsigned getNumOptions() const override { return unsigned(Values.size()); } + const char *getOption(unsigned N) const override { return Values[N].Name; } + const char *getDescription(unsigned N) const override { return Values[N].HelpStr; } // getOptionValue - Return the value of option name N. - virtual const GenericOptionValue &getOptionValue(unsigned N) const { + const GenericOptionValue &getOptionValue(unsigned N) const override { return Values[N].V; } @@ -756,13 +763,13 @@ public: } // getValueName - Do not print =<value> at all. - virtual const char *getValueName() const { return 0; } + const char *getValueName() const override { return nullptr; } void printOptionDiff(const Option &O, bool V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>); @@ -780,13 +787,13 @@ public: } // getValueName - Do not print =<value> at all. - virtual const char *getValueName() const { return 0; } + const char *getValueName() const override { return nullptr; } void printOptionDiff(const Option &O, boolOrDefault V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>); @@ -801,13 +808,13 @@ public: bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "int"; } + const char *getValueName() const override { return "int"; } void printOptionDiff(const Option &O, int V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<int>); @@ -823,13 +830,13 @@ public: bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "uint"; } + const char *getValueName() const override { return "uint"; } void printOptionDiff(const Option &O, unsigned V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>); @@ -845,13 +852,13 @@ public: unsigned long long &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "uint"; } + const char *getValueName() const override { return "uint"; } void printOptionDiff(const Option &O, unsigned long long V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>); @@ -866,13 +873,13 @@ public: bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "number"; } + const char *getValueName() const override { return "number"; } void printOptionDiff(const Option &O, double V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<double>); @@ -887,13 +894,13 @@ public: bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "number"; } + const char *getValueName() const override { return "number"; } void printOptionDiff(const Option &O, float V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<float>); @@ -911,13 +918,13 @@ public: } // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "string"; } + const char *getValueName() const override { return "string"; } void printOptionDiff(const Option &O, StringRef V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<std::string>); @@ -935,13 +942,13 @@ public: } // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "char"; } + const char *getValueName() const override { return "char"; } void printOptionDiff(const Option &O, char V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<char>); @@ -1020,8 +1027,8 @@ template<> struct applicator<const char*> { }; template<> struct applicator<NumOccurrencesFlag> { - static void opt(NumOccurrencesFlag NO, Option &O) { - O.setNumOccurrencesFlag(NO); + static void opt(NumOccurrencesFlag N, Option &O) { + O.setNumOccurrencesFlag(N); } }; template<> struct applicator<ValueExpected> { @@ -1055,13 +1062,13 @@ class opt_storage { DataType *Location; // Where to store the object... OptionValue<DataType> Default; - void check() const { - assert(Location != 0 && "cl::location(...) not specified for a command " + void check_location() const { + assert(Location && "cl::location(...) not specified for a command " "line option with external storage, " "or cl::init specified before cl::location()!!"); } public: - opt_storage() : Location(0) {} + opt_storage() : Location(nullptr) {} bool setLocation(Option &O, DataType &L) { if (Location) @@ -1073,14 +1080,14 @@ public: template<class T> void setValue(const T &V, bool initial = false) { - check(); + check_location(); *Location = V; if (initial) Default = V; } - DataType &getValue() { check(); return *Location; } - const DataType &getValue() const { check(); return *Location; } + DataType &getValue() { check_location(); return *Location; } + const DataType &getValue() const { check_location(); return *Location; } operator DataType() const { return this->getValue(); } @@ -1148,11 +1155,11 @@ template <class DataType, bool ExternalStorage = false, class ParserClass = parser<DataType> > class opt : public Option, public opt_storage<DataType, ExternalStorage, - is_class<DataType>::value> { + std::is_class<DataType>::value> { ParserClass Parser; - virtual bool handleOccurrence(unsigned pos, StringRef ArgName, - StringRef Arg) { + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { typename ParserClass::parser_data_type Val = typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) @@ -1162,20 +1169,20 @@ class opt : public Option, return false; } - virtual enum ValueExpected getValueExpectedFlagDefault() const { + enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - virtual void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) { + void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } // Forward printing stuff to the parser... - virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} - virtual void printOptionInfo(size_t GlobalWidth) const { + size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } - virtual void printOptionValue(size_t GlobalWidth, bool Force) const { + void printOptionValue(size_t GlobalWidth, bool Force) const override { if (Force || this->getDefault().compare(this->getValue())) { cl::printOptionDiff<ParserClass>( *this, Parser, this->getValue(), this->getDefault(), GlobalWidth); @@ -1322,14 +1329,15 @@ class list : public Option, public list_storage<DataType, Storage> { std::vector<unsigned> Positions; ParserClass Parser; - virtual enum ValueExpected getValueExpectedFlagDefault() const { + enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - virtual void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) { + void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } - virtual bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg){ + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { typename ParserClass::parser_data_type Val = typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) @@ -1341,13 +1349,14 @@ class list : public Option, public list_storage<DataType, Storage> { } // Forward printing stuff to the parser... - virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} - virtual void printOptionInfo(size_t GlobalWidth) const { + size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: list options don't currently store their default value. - virtual void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const {} + void printOptionValue(size_t /*GlobalWidth*/, + bool /*Force*/) const override {} void done() { addArgument(); @@ -1460,7 +1469,7 @@ class bits_storage { } public: - bits_storage() : Location(0) {} + bits_storage() : Location(nullptr) {} bool setLocation(Option &O, unsigned &L) { if (Location) @@ -1524,14 +1533,15 @@ class bits : public Option, public bits_storage<DataType, Storage> { std::vector<unsigned> Positions; ParserClass Parser; - virtual enum ValueExpected getValueExpectedFlagDefault() const { + enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - virtual void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) { + void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } - virtual bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg){ + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { typename ParserClass::parser_data_type Val = typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) @@ -1543,13 +1553,14 @@ class bits : public Option, public bits_storage<DataType, Storage> { } // Forward printing stuff to the parser... - virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} - virtual void printOptionInfo(size_t GlobalWidth) const { + size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: bits options don't currently store their default values. - virtual void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const {} + void printOptionValue(size_t /*GlobalWidth*/, + bool /*Force*/) const override {} void done() { addArgument(); @@ -1634,22 +1645,30 @@ public: class alias : public Option { Option *AliasFor; - virtual bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Arg) LLVM_OVERRIDE { + bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, + StringRef Arg) override { return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); } + bool addOccurrence(unsigned pos, StringRef /*ArgName*/, + StringRef Value, bool MultiArg = false) override { + return AliasFor->addOccurrence(pos, AliasFor->ArgStr, Value, MultiArg); + } // Handle printing stuff... - virtual size_t getOptionWidth() const LLVM_OVERRIDE; - virtual void printOptionInfo(size_t GlobalWidth) const LLVM_OVERRIDE; + size_t getOptionWidth() const override; + void printOptionInfo(size_t GlobalWidth) const override; // Aliases do not need to print their values. - virtual void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const LLVM_OVERRIDE {} + void printOptionValue(size_t /*GlobalWidth*/, + bool /*Force*/) const override {} + + ValueExpected getValueExpectedFlagDefault() const override { + return AliasFor->getValueExpectedFlag(); + } void done() { if (!hasArgStr()) error("cl::alias must have argument name specified!"); - if (AliasFor == 0) + if (!AliasFor) error("cl::alias must have an cl::aliasopt(option) specified!"); addArgument(); } @@ -1662,27 +1681,28 @@ public: // One option... template<class M0t> - explicit alias(const M0t &M0) : Option(Optional, Hidden), AliasFor(0) { + explicit alias(const M0t &M0) : Option(Optional, Hidden), AliasFor(nullptr) { apply(M0, this); done(); } // Two options... template<class M0t, class M1t> - alias(const M0t &M0, const M1t &M1) : Option(Optional, Hidden), AliasFor(0) { + alias(const M0t &M0, const M1t &M1) + : Option(Optional, Hidden), AliasFor(nullptr) { apply(M0, this); apply(M1, this); done(); } // Three options... template<class M0t, class M1t, class M2t> alias(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional, Hidden), AliasFor(0) { + : Option(Optional, Hidden), AliasFor(nullptr) { apply(M0, this); apply(M1, this); apply(M2, this); done(); } // Four options... template<class M0t, class M1t, class M2t, class M3t> alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(Optional, Hidden), AliasFor(0) { + : Option(Optional, Hidden), AliasFor(nullptr) { apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); done(); } diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 860f43e9423e..25bf32ade5f8 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -21,6 +21,10 @@ # define __has_feature(x) 0 #endif +#ifndef __has_extension +# define __has_extension(x) 0 +#endif + #ifndef __has_attribute # define __has_attribute(x) 0 #endif @@ -40,15 +44,27 @@ # endif #endif -/// \brief Does the compiler support r-value references? -/// This implies that <utility> provides the one-argument std::move; it -/// does not imply the existence of any other C++ library features. -#if (__has_feature(cxx_rvalue_references) \ - || defined(__GXX_EXPERIMENTAL_CXX0X__) \ - || (defined(_MSC_VER) && _MSC_VER >= 1600)) -#define LLVM_HAS_RVALUE_REFERENCES 1 +/// \macro LLVM_MSC_PREREQ +/// \brief Is the compiler MSVC of at least the specified version? +/// The common \param version values to check for are: +/// * 1700: Microsoft Visual Studio 2012 / 11.0 +/// * 1800: Microsoft Visual Studio 2013 / 12.0 +#ifdef _MSC_VER +#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version)) + +// We require at least MSVC 2012. +#if !LLVM_MSC_PREREQ(1700) +#error LLVM requires at least MSVC 2012. +#endif + #else -#define LLVM_HAS_RVALUE_REFERENCES 0 +#define LLVM_MSC_PREREQ(version) 0 +#endif + +#ifndef _MSC_VER +#define LLVM_NOEXCEPT noexcept +#else +#define LLVM_NOEXCEPT #endif /// \brief Does the compiler support r-value reference *this? @@ -63,51 +79,16 @@ #define LLVM_HAS_RVALUE_REFERENCE_THIS 0 #endif -/// \macro LLVM_HAS_CXX11_TYPETRAITS -/// \brief Does the compiler have the C++11 type traits. -/// -/// #include <type_traits> -/// -/// * enable_if -/// * {true,false}_type -/// * is_constructible -/// * etc... -#if defined(__GXX_EXPERIMENTAL_CXX0X__) \ - || (defined(_MSC_VER) && _MSC_VER >= 1700) -#define LLVM_HAS_CXX11_TYPETRAITS 1 -#else -#define LLVM_HAS_CXX11_TYPETRAITS 0 -#endif - -/// \macro LLVM_HAS_CXX11_STDLIB -/// \brief Does the compiler have the C++11 standard library. -/// -/// Implies LLVM_HAS_RVALUE_REFERENCES, LLVM_HAS_CXX11_TYPETRAITS -#if defined(__GXX_EXPERIMENTAL_CXX0X__) \ - || (defined(_MSC_VER) && _MSC_VER >= 1700) -#define LLVM_HAS_CXX11_STDLIB 1 -#else -#define LLVM_HAS_CXX11_STDLIB 0 -#endif - /// \macro LLVM_HAS_VARIADIC_TEMPLATES /// \brief Does this compiler support variadic templates. /// /// Implies LLVM_HAS_RVALUE_REFERENCES and the existence of std::forward. -#if __has_feature(cxx_variadic_templates) +#if __has_feature(cxx_variadic_templates) || LLVM_MSC_PREREQ(1800) # define LLVM_HAS_VARIADIC_TEMPLATES 1 #else # define LLVM_HAS_VARIADIC_TEMPLATES 0 #endif -/// llvm_move - Expands to ::std::move if the compiler supports -/// r-value references; otherwise, expands to the argument. -#if LLVM_HAS_RVALUE_REFERENCES -#define llvm_move(value) (::std::move(value)) -#else -#define llvm_move(value) (value) -#endif - /// Expands to '&' if r-value references are supported. /// /// This can be used to provide l-value/r-value overrides of member functions. @@ -129,32 +110,13 @@ /// public: /// ... /// }; -#if (__has_feature(cxx_deleted_functions) \ - || defined(__GXX_EXPERIMENTAL_CXX0X__)) - // No version of MSVC currently supports this. +#if __has_feature(cxx_deleted_functions) || \ + defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800) #define LLVM_DELETED_FUNCTION = delete #else #define LLVM_DELETED_FUNCTION #endif -/// LLVM_FINAL - Expands to 'final' if the compiler supports it. -/// Use to mark classes or virtual methods as final. -#if __has_feature(cxx_override_control) \ - || (defined(_MSC_VER) && _MSC_VER >= 1700) -#define LLVM_FINAL final -#else -#define LLVM_FINAL -#endif - -/// LLVM_OVERRIDE - Expands to 'override' if the compiler supports it. -/// Use to mark virtual methods as overriding a base class method. -#if __has_feature(cxx_override_control) \ - || (defined(_MSC_VER) && _MSC_VER >= 1700) -#define LLVM_OVERRIDE override -#else -#define LLVM_OVERRIDE -#endif - #if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define LLVM_CONSTEXPR constexpr #else @@ -335,19 +297,15 @@ # define LLVM_FUNCTION_NAME __func__ #endif -#if defined(HAVE_SANITIZER_MSAN_INTERFACE_H) -# include <sanitizer/msan_interface.h> -#else -# define __msan_allocated_memory(p, size) -# define __msan_unpoison(p, size) -#endif - /// \macro LLVM_MEMORY_SANITIZER_BUILD /// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. #if __has_feature(memory_sanitizer) # define LLVM_MEMORY_SANITIZER_BUILD 1 +# include <sanitizer/msan_interface.h> #else # define LLVM_MEMORY_SANITIZER_BUILD 0 +# define __msan_allocated_memory(p, size) +# define __msan_unpoison(p, size) #endif /// \macro LLVM_ADDRESS_SANITIZER_BUILD @@ -374,41 +332,30 @@ /// \macro LLVM_EXPLICIT /// \brief Expands to explicit on compilers which support explicit conversion /// operators. Otherwise expands to nothing. -#if (__has_feature(cxx_explicit_conversions) \ - || defined(__GXX_EXPERIMENTAL_CXX0X__)) +#if __has_feature(cxx_explicit_conversions) || \ + defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800) #define LLVM_EXPLICIT explicit #else #define LLVM_EXPLICIT #endif -/// \macro LLVM_STATIC_ASSERT -/// \brief Expands to C/C++'s static_assert on compilers which support it. -#if __has_feature(cxx_static_assert) -# define LLVM_STATIC_ASSERT(expr, msg) static_assert(expr, msg) -#elif __has_feature(c_static_assert) -# define LLVM_STATIC_ASSERT(expr, msg) _Static_assert(expr, msg) -#else -# define LLVM_STATIC_ASSERT(expr, msg) -#endif - -/// \macro LLVM_ENUM_INT_TYPE -/// \brief Expands to colon followed by the given integral type on compilers -/// which support C++11 strong enums. This can be used to make enums unsigned -/// with MSVC. -#if __has_feature(cxx_strong_enums) -# define LLVM_ENUM_INT_TYPE(intty) : intty -#elif defined(_MSC_VER) && _MSC_VER >= 1600 // Added in MSVC 2010. -# define LLVM_ENUM_INT_TYPE(intty) : intty -#else -# define LLVM_ENUM_INT_TYPE(intty) -#endif - /// \brief Does the compiler support generalized initializers (using braced -/// lists and std::initializer_list). -#if __has_feature(cxx_generalized_initializers) +/// lists and std::initializer_list). While clang may claim it supports general +/// initializers, if we're using MSVC's headers, we might not have a usable +/// std::initializer list type from the STL. Disable this for now. +#if __has_feature(cxx_generalized_initializers) && !defined(_MSC_VER) #define LLVM_HAS_INITIALIZER_LISTS 1 #else #define LLVM_HAS_INITIALIZER_LISTS 0 #endif +/// \brief Mark debug helper function definitions like dump() that should not be +/// stripped from debug builds. +// FIXME: Move this to a private config.h as it's not usable in public headers. +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED +#else +#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE +#endif + #endif diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h index bef9146d07df..8152b60eb098 100644 --- a/include/llvm/Support/Compression.h +++ b/include/llvm/Support/Compression.h @@ -15,11 +15,11 @@ #define LLVM_SUPPORT_COMPRESSION_H #include "llvm/Support/DataTypes.h" +#include <memory> +#include "llvm/ADT/SmallVector.h" namespace llvm { -class MemoryBuffer; -template<typename T> class OwningPtr; class StringRef; namespace zlib { @@ -33,21 +33,20 @@ enum CompressionLevel { enum Status { StatusOK, - StatusUnsupported, // zlib is unavaliable - StatusOutOfMemory, // there was not enough memory - StatusBufferTooShort, // there was not enough room in the output buffer - StatusInvalidArg, // invalid input parameter - StatusInvalidData // data was corrupted or incomplete + StatusUnsupported, // zlib is unavailable + StatusOutOfMemory, // there was not enough memory + StatusBufferTooShort, // there was not enough room in the output buffer + StatusInvalidArg, // invalid input parameter + StatusInvalidData // data was corrupted or incomplete }; bool isAvailable(); -Status compress(StringRef InputBuffer, - OwningPtr<MemoryBuffer> &CompressedBuffer, +Status compress(StringRef InputBuffer, SmallVectorImpl<char> &CompressedBuffer, CompressionLevel Level = DefaultCompression); Status uncompress(StringRef InputBuffer, - OwningPtr<MemoryBuffer> &UncompressedBuffer, + SmallVectorImpl<char> &UncompressedBuffer, size_t UncompressedSize); uint32_t crc32(StringRef Buffer); diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h index 282036619c49..a184d0df2132 100644 --- a/include/llvm/Support/ConvertUTF.h +++ b/include/llvm/Support/ConvertUTF.h @@ -136,7 +136,19 @@ ConversionResult ConvertUTF8toUTF16 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); -ConversionResult ConvertUTF8toUTF32 ( +/** + * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an + * incomplete code unit sequence, returns \c sourceExhausted. + */ +ConversionResult ConvertUTF8toUTF32Partial( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +/** + * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an + * incomplete code unit sequence, returns \c sourceIllegal. + */ +ConversionResult ConvertUTF8toUTF32( const UTF8** sourceStart, const UTF8* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index 4c0a5e26f00f..3869ebdc4a93 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -12,11 +12,13 @@ #include <string> +#include "llvm/ADT/STLExtras.h" + namespace llvm { class StringRef; class CrashRecoveryContextCleanup; - + /// \brief Crash recovery helper object. /// /// This class implements support for running operations in a safe context so @@ -47,9 +49,9 @@ class CrashRecoveryContext { CrashRecoveryContextCleanup *head; public: - CrashRecoveryContext() : Impl(0), head(0) {} + CrashRecoveryContext() : Impl(nullptr), head(nullptr) {} ~CrashRecoveryContext(); - + void registerCleanup(CrashRecoveryContextCleanup *cleanup); void unregisterCleanup(CrashRecoveryContextCleanup *cleanup); @@ -75,15 +77,24 @@ public: /// make as little assumptions as possible about the program state when /// RunSafely has returned false. Clients can use getBacktrace() to retrieve /// the backtrace of the crash on failures. - bool RunSafely(void (*Fn)(void*), void *UserData); + bool RunSafely(function_ref<void()> Fn); + bool RunSafely(void (*Fn)(void*), void *UserData) { + return RunSafely([&]() { Fn(UserData); }); + } /// \brief Execute the provide callback function (with the given arguments) in /// a protected context which is run in another thread (optionally with a /// requested stack size). /// /// See RunSafely() and llvm_execute_on_thread(). + /// + /// On Darwin, if PRIO_DARWIN_BG is set on the calling thread, it will be + /// propagated to the new thread as well. + bool RunSafelyOnThread(function_ref<void()>, unsigned RequestedStackSize = 0); bool RunSafelyOnThread(void (*Fn)(void*), void *UserData, - unsigned RequestedStackSize = 0); + unsigned RequestedStackSize = 0) { + return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize); + } /// \brief Explicitly trigger a crash recovery in the current process, and /// return failure from RunSafely(). This function does not return. diff --git a/include/llvm/Support/DataFlow.h b/include/llvm/Support/DataFlow.h deleted file mode 100644 index a09ccaac2789..000000000000 --- a/include/llvm/Support/DataFlow.h +++ /dev/null @@ -1,103 +0,0 @@ -//===-- llvm/Support/DataFlow.h - dataflow as graphs ------------*- 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 specializations of GraphTraits that allows Use-Def and -// Def-Use relations to be treated as proper graphs for generic algorithms. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_DATAFLOW_H -#define LLVM_SUPPORT_DATAFLOW_H - -#include "llvm/ADT/GraphTraits.h" -#include "llvm/IR/User.h" - -namespace llvm { - -//===----------------------------------------------------------------------===// -// Provide specializations of GraphTraits to be able to treat def-use/use-def -// chains as graphs - -template <> struct GraphTraits<const Value*> { - typedef const Value NodeType; - typedef Value::const_use_iterator ChildIteratorType; - - static NodeType *getEntryNode(const Value *G) { - return G; - } - - static inline ChildIteratorType child_begin(NodeType *N) { - return N->use_begin(); - } - - static inline ChildIteratorType child_end(NodeType *N) { - return N->use_end(); - } -}; - -template <> struct GraphTraits<Value*> { - typedef Value NodeType; - typedef Value::use_iterator ChildIteratorType; - - static NodeType *getEntryNode(Value *G) { - return G; - } - - static inline ChildIteratorType child_begin(NodeType *N) { - return N->use_begin(); - } - - static inline ChildIteratorType child_end(NodeType *N) { - return N->use_end(); - } -}; - -template <> struct GraphTraits<Inverse<const User*> > { - typedef const Value NodeType; - typedef User::const_op_iterator ChildIteratorType; - - static NodeType *getEntryNode(Inverse<const User*> G) { - return G.Graph; - } - - static inline ChildIteratorType child_begin(NodeType *N) { - if (const User *U = dyn_cast<User>(N)) - return U->op_begin(); - return NULL; - } - - static inline ChildIteratorType child_end(NodeType *N) { - if(const User *U = dyn_cast<User>(N)) - return U->op_end(); - return NULL; - } -}; - -template <> struct GraphTraits<Inverse<User*> > { - typedef Value NodeType; - typedef User::op_iterator ChildIteratorType; - - static NodeType *getEntryNode(Inverse<User*> G) { - return G.Graph; - } - - static inline ChildIteratorType child_begin(NodeType *N) { - if (User *U = dyn_cast<User>(N)) - return U->op_begin(); - return NULL; - } - - static inline ChildIteratorType child_end(NodeType *N) { - if (User *U = dyn_cast<User>(N)) - return U->op_end(); - return NULL; - } -}; - -} -#endif diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake index a26070cdc9fe..1f0c8eba5e11 100644 --- a/include/llvm/Support/DataTypes.h.cmake +++ b/include/llvm/Support/DataTypes.h.cmake @@ -37,6 +37,16 @@ #include <math.h> #endif +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#else +#error "Compiler must provide an implementation of stdint.h" +#endif + #ifndef _MSC_VER /* Note that this header's correct operation depends on __STDC_LIMIT_MACROS @@ -55,14 +65,6 @@ /* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ #include <sys/types.h> -#ifdef HAVE_INTTYPES_H -#include <inttypes.h> -#endif - -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif - #ifdef _AIX #include "llvm/Support/AIXDataTypesFix.h" #endif @@ -77,11 +79,6 @@ typedef u_int64_t uint64_t; #endif #else /* _MSC_VER */ -/* Visual C++ doesn't provide standard integer headers, but it does provide - built-in data types. */ -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif #include <stdlib.h> #include <stddef.h> #include <sys/types.h> @@ -90,93 +87,21 @@ typedef u_int64_t uint64_t; #else #include <math.h> #endif -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -typedef signed int int32_t; -typedef unsigned int uint32_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef signed char int8_t; -typedef unsigned char uint8_t; + #if defined(_WIN64) - typedef signed __int64 ssize_t; +typedef signed __int64 ssize_t; #else - typedef signed int ssize_t; -#endif -#ifndef INT8_MAX -# define INT8_MAX 127 -#endif -#ifndef INT8_MIN -# define INT8_MIN -128 -#endif -#ifndef UINT8_MAX -# define UINT8_MAX 255 -#endif -#ifndef INT16_MAX -# define INT16_MAX 32767 -#endif -#ifndef INT16_MIN -# define INT16_MIN -32768 -#endif -#ifndef UINT16_MAX -# define UINT16_MAX 65535 -#endif -#ifndef INT32_MAX -# define INT32_MAX 2147483647 -#endif -#ifndef INT32_MIN -/* MSC treats -2147483648 as -(2147483648U). */ -# define INT32_MIN (-INT32_MAX - 1) -#endif -#ifndef UINT32_MAX -# define UINT32_MAX 4294967295U -#endif -/* Certain compatibility updates to VC++ introduce the `cstdint' - * header, which defines the INT*_C macros. On default installs they - * are absent. */ -#ifndef INT8_C -# define INT8_C(C) C##i8 -#endif -#ifndef UINT8_C -# define UINT8_C(C) C##ui8 -#endif -#ifndef INT16_C -# define INT16_C(C) C##i16 -#endif -#ifndef UINT16_C -# define UINT16_C(C) C##ui16 -#endif -#ifndef INT32_C -# define INT32_C(C) C##i32 -#endif -#ifndef UINT32_C -# define UINT32_C(C) C##ui32 -#endif -#ifndef INT64_C -# define INT64_C(C) C##i64 -#endif -#ifndef UINT64_C -# define UINT64_C(C) C##ui64 -#endif - -#ifndef PRId64 -# define PRId64 "I64d" -#endif -#ifndef PRIi64 -# define PRIi64 "I64i" -#endif -#ifndef PRIo64 -# define PRIo64 "I64o" -#endif -#ifndef PRIu64 -# define PRIu64 "I64u" -#endif -#ifndef PRIx64 -# define PRIx64 "I64x" -#endif -#ifndef PRIX64 -# define PRIX64 "I64X" -#endif +typedef signed int ssize_t; +#endif /* _WIN64 */ + +#ifndef HAVE_INTTYPES_H +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#endif /* HAVE_INTTYPES_H */ #endif /* _MSC_VER */ diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in index 7fc9b725244e..09cfcdf3b56b 100644 --- a/include/llvm/Support/DataTypes.h.in +++ b/include/llvm/Support/DataTypes.h.in @@ -37,6 +37,16 @@ #include <math.h> #endif +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#else +#error "Compiler must provide an implementation of stdint.h" +#endif + #ifndef _MSC_VER /* Note that this header's correct operation depends on __STDC_LIMIT_MACROS @@ -55,14 +65,6 @@ /* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ #include <sys/types.h> -#ifdef HAVE_INTTYPES_H -#include <inttypes.h> -#endif - -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif - #ifdef _AIX #include "llvm/Support/AIXDataTypesFix.h" #endif @@ -77,8 +79,6 @@ typedef u_int64_t uint64_t; #endif #else /* _MSC_VER */ -/* Visual C++ doesn't provide standard integer headers, but it does provide - built-in data types. */ #include <stdlib.h> #include <stddef.h> #include <sys/types.h> @@ -87,94 +87,21 @@ typedef u_int64_t uint64_t; #else #include <math.h> #endif -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -typedef signed int int32_t; -typedef unsigned int uint32_t; -typedef short int16_t; -typedef unsigned short uint16_t; -typedef signed char int8_t; -typedef unsigned char uint8_t; + #if defined(_WIN64) - typedef signed __int64 ssize_t; +typedef signed __int64 ssize_t; #else - typedef signed int ssize_t; -#endif - -#ifndef INT8_MAX -# define INT8_MAX 127 -#endif -#ifndef INT8_MIN -# define INT8_MIN -128 -#endif -#ifndef UINT8_MAX -# define UINT8_MAX 255 -#endif -#ifndef INT16_MAX -# define INT16_MAX 32767 -#endif -#ifndef INT16_MIN -# define INT16_MIN -32768 -#endif -#ifndef UINT16_MAX -# define UINT16_MAX 65535 -#endif -#ifndef INT32_MAX -# define INT32_MAX 2147483647 -#endif -#ifndef INT32_MIN -/* MSC treats -2147483648 as -(2147483648U). */ -# define INT32_MIN (-INT32_MAX - 1) -#endif -#ifndef UINT32_MAX -# define UINT32_MAX 4294967295U -#endif -/* Certain compatibility updates to VC++ introduce the `cstdint' - * header, which defines the INT*_C macros. On default installs they - * are absent. */ -#ifndef INT8_C -# define INT8_C(C) C##i8 -#endif -#ifndef UINT8_C -# define UINT8_C(C) C##ui8 -#endif -#ifndef INT16_C -# define INT16_C(C) C##i16 -#endif -#ifndef UINT16_C -# define UINT16_C(C) C##ui16 -#endif -#ifndef INT32_C -# define INT32_C(C) C##i32 -#endif -#ifndef UINT32_C -# define UINT32_C(C) C##ui32 -#endif -#ifndef INT64_C -# define INT64_C(C) C##i64 -#endif -#ifndef UINT64_C -# define UINT64_C(C) C##ui64 -#endif - -#ifndef PRId64 -# define PRId64 "I64d" -#endif -#ifndef PRIi64 -# define PRIi64 "I64i" -#endif -#ifndef PRIo64 -# define PRIo64 "I64o" -#endif -#ifndef PRIu64 -# define PRIu64 "I64u" -#endif -#ifndef PRIx64 -# define PRIx64 "I64x" -#endif -#ifndef PRIX64 -# define PRIX64 "I64X" -#endif +typedef signed int ssize_t; +#endif /* _WIN64 */ + +#ifndef HAVE_INTTYPES_H +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#endif /* HAVE_INTTYPES_H */ #endif /* _MSC_VER */ diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h index 27024082962b..e93e6ca34498 100644 --- a/include/llvm/Support/Debug.h +++ b/include/llvm/Support/Debug.h @@ -13,10 +13,12 @@ // // In particular, just wrap your code with the DEBUG() macro, and it will be // enabled automatically if you specify '-debug' on the command-line. -// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify -// that your debug code belongs to class "foo". Then, on the command line, you -// can specify '-debug-only=foo' to enable JUST the debug information for the -// foo class. +// Alternatively, you can also define the DEBUG_TYPE macro to "foo" specify +// that your debug code belongs to class "foo". Be careful that you only do +// this after including Debug.h and not around any #include of headers. Headers +// should define and undef the macro acround the code that needs to use the +// DEBUG() macro. Then, on the command line, you can specify '-debug-only=foo' +// to enable JUST the debug information for the foo class. // // When compiling without assertions, the -debug-* options and all code in // DEBUG() statements disappears, so it does not affect the runtime of the code. @@ -30,12 +32,6 @@ namespace llvm { -/// DEBUG_TYPE macro - Files can specify a DEBUG_TYPE as a string, which causes -/// all of their DEBUG statements to be activatable with -debug-only=thatstring. -#ifndef DEBUG_TYPE -#define DEBUG_TYPE "" -#endif - #ifndef NDEBUG /// DebugFlag - This boolean is set to true if the '-debug' command line option /// is specified. This should probably not be referenced directly, instead, use diff --git a/include/llvm/Support/Disassembler.h b/include/llvm/Support/Disassembler.h deleted file mode 100644 index 6d1cc0fdcb50..000000000000 --- a/include/llvm/Support/Disassembler.h +++ /dev/null @@ -1,35 +0,0 @@ -//===- llvm/Support/Disassembler.h ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the necessary glue to call external disassembler -// libraries. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SYSTEM_DISASSEMBLER_H -#define LLVM_SYSTEM_DISASSEMBLER_H - -#include "llvm/Support/DataTypes.h" -#include <string> - -namespace llvm { -namespace sys { - -/// This function returns true, if there is possible to use some external -/// disassembler library. False otherwise. -bool hasDisassembler(); - -/// This function provides some "glue" code to call external disassembler -/// libraries. -std::string disassembleBuffer(uint8_t* start, size_t length, uint64_t pc = 0); - -} -} - -#endif // LLVM_SYSTEM_DISASSEMBLER_H diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index 23bbd1c384cf..cd9f75600cbc 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -24,7 +24,7 @@ namespace llvm { //===----------------------------------------------------------------------===// // Debug info constants. -enum LLVM_ENUM_INT_TYPE(uint32_t) { +enum : uint32_t { LLVMDebugVersion = (12 << 16), // Current version of debug information. LLVMDebugVersion11 = (11 << 16), // Constant for version 11. LLVMDebugVersion10 = (10 << 16), // Constant for version 10. @@ -41,13 +41,13 @@ namespace dwarf { //===----------------------------------------------------------------------===// // Dwarf constants as gleaned from the DWARF Debugging Information Format V.4 -// reference manual http://dwarf.freestandards.org. +// reference manual http://www.dwarfstd.org/. // // Do not mix the following two enumerations sets. DW_TAG_invalid changes the // enumeration base type. -enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) { +enum LLVMConstants : uint32_t { // llvm mock tags DW_TAG_invalid = ~0U, // Tag for invalid results. @@ -57,7 +57,6 @@ enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) { DW_TAG_user_base = 0x1000, // Recommended base for user tags. DWARF_VERSION = 4, // Default dwarf version we output. - DW_CIE_VERSION = 1, // Common frame information version. DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes. DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames. DW_ARANGES_VERSION = 2 // Section version number for .debug_aranges. @@ -68,7 +67,7 @@ enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) { const uint32_t DW_CIE_ID = UINT32_MAX; const uint64_t DW64_CIE_ID = UINT64_MAX; -enum Tag LLVM_ENUM_INT_TYPE(uint16_t) { +enum Tag : uint16_t { DW_TAG_array_type = 0x01, DW_TAG_class_type = 0x02, DW_TAG_entry_point = 0x03, @@ -129,6 +128,12 @@ enum Tag LLVM_ENUM_INT_TYPE(uint16_t) { DW_TAG_type_unit = 0x41, DW_TAG_rvalue_reference_type = 0x42, DW_TAG_template_alias = 0x43, + + // New in DWARF 5: + DW_TAG_coarray_type = 0x44, + DW_TAG_generic_subrange = 0x45, + DW_TAG_dynamic_type = 0x46, + DW_TAG_MIPS_loop = 0x4081, DW_TAG_format_label = 0x4101, DW_TAG_function_template = 0x4102, @@ -169,7 +174,7 @@ inline bool isType(Tag T) { } } -enum Attribute LLVM_ENUM_INT_TYPE(uint16_t) { +enum Attribute : uint16_t { // Attributes DW_AT_sibling = 0x01, DW_AT_location = 0x02, @@ -264,6 +269,18 @@ enum Attribute LLVM_ENUM_INT_TYPE(uint16_t) { DW_AT_enum_class = 0x6d, DW_AT_linkage_name = 0x6e, + // New in DWARF 5: + DW_AT_string_length_bit_size = 0x6f, + DW_AT_string_length_byte_size = 0x70, + DW_AT_rank = 0x71, + DW_AT_str_offsets_base = 0x72, + DW_AT_addr_base = 0x73, + DW_AT_ranges_base = 0x74, + DW_AT_dwo_id = 0x75, + DW_AT_dwo_name = 0x76, + DW_AT_reference = 0x77, + DW_AT_rvalue_reference = 0x78, + DW_AT_lo_user = 0x2000, DW_AT_hi_user = 0x3fff, @@ -323,7 +340,7 @@ enum Attribute LLVM_ENUM_INT_TYPE(uint16_t) { DW_AT_APPLE_property = 0x3fed }; -enum Form LLVM_ENUM_INT_TYPE(uint16_t) { +enum Form : uint16_t { // Attribute form encodings DW_FORM_addr = 0x01, DW_FORM_block2 = 0x03, @@ -605,7 +622,16 @@ enum SourceLanguage { DW_LANG_ObjC_plus_plus = 0x0011, DW_LANG_UPC = 0x0012, DW_LANG_D = 0x0013, + // New in DWARF 5: DW_LANG_Python = 0x0014, + DW_LANG_OpenCL = 0x0015, + DW_LANG_Go = 0x0016, + DW_LANG_Modula3 = 0x0017, + DW_LANG_Haskell = 0x0018, + DW_LANG_C_plus_plus_03 = 0x0019, + DW_LANG_C_plus_plus_11 = 0x001a, + DW_LANG_OCaml = 0x001b, + DW_LANG_lo_user = 0x8000, DW_LANG_Mips_Assembler = 0x8001, DW_LANG_hi_user = 0xffff @@ -744,6 +770,15 @@ enum Constants { DW_EH_PE_indirect = 0x80 }; +// Constants for debug_loc.dwo in the DWARF5 Split Debug Info Proposal +enum LocationListEntry : unsigned char { + DW_LLE_end_of_list_entry, + DW_LLE_base_address_selection_entry, + DW_LLE_start_end_entry, + DW_LLE_start_length_entry, + DW_LLE_offset_pair_entry +}; + enum ApplePropertyAttributes { // Apple Objective-C Property Attributes DW_APPLE_PROPERTY_readonly = 0x01, diff --git a/include/llvm/Support/DynamicLibrary.h b/include/llvm/Support/DynamicLibrary.h index 1e2d16ccbc81..de47be62a795 100644 --- a/include/llvm/Support/DynamicLibrary.h +++ b/include/llvm/Support/DynamicLibrary.h @@ -65,7 +65,7 @@ namespace sys { /// It is safe to call this function multiple times for the same library. /// @brief Open a dynamic library permanently. static DynamicLibrary getPermanentLibrary(const char *filename, - std::string *errMsg = 0); + std::string *errMsg = nullptr); /// This function permanently loads the dynamic library at the given path. /// Use this instead of getPermanentLibrary() when you won't need to get @@ -73,7 +73,7 @@ namespace sys { /// /// It is safe to call this function multiple times for the same library. static bool LoadLibraryPermanently(const char *Filename, - std::string *ErrMsg = 0) { + std::string *ErrMsg = nullptr) { return !getPermanentLibrary(Filename, ErrMsg).isValid(); } diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 2868f35a01a1..42abe8906ea3 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -124,6 +124,8 @@ enum { }; // Machine architectures +// See current registered ELF machine architectures at: +// http://www.uxsglobal.com/developers/gabi/latest/ch4.eheader.html enum { EM_NONE = 0, // No machine EM_M32 = 1, // AT&T WE 32100 @@ -287,7 +289,26 @@ enum { EM_RL78 = 197, // Renesas RL78 family EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor EM_78KOR = 199, // Renesas 78KOR family - EM_56800EX = 200 // Freescale 56800EX Digital Signal Controller (DSC) + EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller (DSC) + EM_BA1 = 201, // Beyond BA1 CPU architecture + EM_BA2 = 202, // Beyond BA2 CPU architecture + EM_XCORE = 203, // XMOS xCORE processor family + EM_MCHP_PIC = 204, // Microchip 8-bit PIC(r) family + EM_INTEL205 = 205, // Reserved by Intel + EM_INTEL206 = 206, // Reserved by Intel + EM_INTEL207 = 207, // Reserved by Intel + EM_INTEL208 = 208, // Reserved by Intel + EM_INTEL209 = 209, // Reserved by Intel + EM_KM32 = 210, // KM211 KM32 32-bit processor + EM_KMX32 = 211, // KM211 KMX32 32-bit processor + EM_KMX16 = 212, // KM211 KMX16 16-bit processor + EM_KMX8 = 213, // KM211 KMX8 8-bit processor + EM_KVARC = 214, // KM211 KVARC processor + EM_CDP = 215, // Paneve CDP architecture family + EM_COGE = 216, // Cognitive Smart Memory Processor + EM_COOL = 217, // iCelero CoolEngine + EM_NORC = 218, // Nanoradio Optimized RISC + EM_CSR_KALIMBA = 219 // CSR Kalimba architecture family }; // Object file classes. @@ -437,6 +458,7 @@ enum { R_PPC_GOT16_LO = 15, R_PPC_GOT16_HI = 16, R_PPC_GOT16_HA = 17, + R_PPC_PLTREL24 = 18, R_PPC_REL32 = 26, R_PPC_TLS = 67, R_PPC_DTPMOD32 = 68, @@ -474,6 +496,37 @@ enum { R_PPC_REL16_HA = 252 }; +// Specific e_flags for PPC64 +enum { + // e_flags bits specifying ABI: + // 1 for original ABI using function descriptors, + // 2 for revised ABI without function descriptors, + // 0 for unspecified or not using any features affected by the differences. + EF_PPC64_ABI = 3 +}; + +// Special values for the st_other field in the symbol table entry for PPC64. +enum { + STO_PPC64_LOCAL_BIT = 5, + STO_PPC64_LOCAL_MASK = (7 << STO_PPC64_LOCAL_BIT) +}; +static inline int64_t +decodePPC64LocalEntryOffset(unsigned Other) { + unsigned Val = (Other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT; + return ((1 << Val) >> 2) << 2; +} +static inline unsigned +encodePPC64LocalEntryOffset(int64_t Offset) { + unsigned Val = (Offset >= 4 * 4 + ? (Offset >= 8 * 4 + ? (Offset >= 16 * 4 ? 6 : 5) + : 4) + : (Offset >= 2 * 4 + ? 3 + : (Offset >= 1 * 4 ? 2 : 0))); + return Val << STO_PPC64_LOCAL_BIT; +} + // ELF Relocation types for PPC64 enum { R_PPC64_NONE = 0, @@ -651,7 +704,7 @@ enum { }; // ARM Specific e_flags -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { EF_ARM_SOFT_FLOAT = 0x00000200U, EF_ARM_VFP_FLOAT = 0x00000400U, EF_ARM_EABI_UNKNOWN = 0x00000000U, @@ -801,10 +854,13 @@ enum { }; // Mips Specific e_flags -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions EF_MIPS_PIC = 0x00000002, // Position independent code EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code + EF_MIPS_ABI2 = 0x00000020, + EF_MIPS_32BITMODE = 0x00000100, + EF_MIPS_NAN2008 = 0x00000400, // Uses IEE 754-2008 NaN encoding EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI //ARCH_ASE @@ -821,11 +877,12 @@ enum LLVM_ENUM_INT_TYPE(unsigned) { EF_MIPS_ARCH_64 = 0x60000000, // MIPS64 instruction set per linux not elf.h EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2 EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2 + EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6 + EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6 EF_MIPS_ARCH = 0xf0000000 // Mask for applying EF_MIPS_ARCH_ variant }; // ELF Relocation types for Mips -// . enum { R_MIPS_NONE = 0, R_MIPS_16 = 1, @@ -837,7 +894,6 @@ enum { R_MIPS_GPREL16 = 7, R_MIPS_LITERAL = 8, R_MIPS_GOT16 = 9, - R_MIPS_GOT = 9, R_MIPS_PC16 = 10, R_MIPS_CALL16 = 11, R_MIPS_GPREL32 = 12, @@ -879,6 +935,15 @@ enum { R_MIPS_TLS_TPREL_HI16 = 49, R_MIPS_TLS_TPREL_LO16 = 50, R_MIPS_GLOB_DAT = 51, + R_MIPS_PC21_S2 = 60, + R_MIPS_PC26_S2 = 61, + R_MIPS_PC18_S3 = 62, + R_MIPS_PC19_S2 = 63, + R_MIPS_PCHI16 = 64, + R_MIPS_PCLO16 = 65, + R_MIPS16_GOT16 = 102, + R_MIPS16_HI16 = 104, + R_MIPS16_LO16 = 105, R_MIPS_COPY = 126, R_MIPS_JUMP_SLOT = 127, R_MICROMIPS_26_S1 = 133, @@ -890,16 +955,23 @@ enum { R_MICROMIPS_GOT_DISP = 145, R_MICROMIPS_GOT_PAGE = 146, R_MICROMIPS_GOT_OFST = 147, + R_MICROMIPS_TLS_GD = 162, + R_MICROMIPS_TLS_LDM = 163, R_MICROMIPS_TLS_DTPREL_HI16 = 164, R_MICROMIPS_TLS_DTPREL_LO16 = 165, R_MICROMIPS_TLS_TPREL_HI16 = 169, R_MICROMIPS_TLS_TPREL_LO16 = 170, - R_MIPS_NUM = 218 + R_MIPS_NUM = 218, + R_MIPS_PC32 = 248 }; // Special values for the st_other field in the symbol table entry for MIPS. enum { - STO_MIPS_MICROMIPS = 0x80 // MIPS Specific ISA for MicroMips + STO_MIPS_OPTIONAL = 0x04, // Symbol whose definition is optional + STO_MIPS_PLT = 0x08, // PLT entry related dynamic table record + STO_MIPS_PIC = 0x20, // PIC func in an object mixes PIC/non-PIC + STO_MIPS_MICROMIPS = 0x80, // MIPS Specific ISA for MicroMips + STO_MIPS_MIPS16 = 0xf0 // MIPS Specific ISA for Mips16 }; // Hexagon Specific e_flags @@ -1087,6 +1159,94 @@ enum { R_390_IRELATIVE = 61 }; +// ELF Relocation type for Sparc. +enum { + R_SPARC_NONE = 0, + R_SPARC_8 = 1, + R_SPARC_16 = 2, + R_SPARC_32 = 3, + R_SPARC_DISP8 = 4, + R_SPARC_DISP16 = 5, + R_SPARC_DISP32 = 6, + R_SPARC_WDISP30 = 7, + R_SPARC_WDISP22 = 8, + R_SPARC_HI22 = 9, + R_SPARC_22 = 10, + R_SPARC_13 = 11, + R_SPARC_LO10 = 12, + R_SPARC_GOT10 = 13, + R_SPARC_GOT13 = 14, + R_SPARC_GOT22 = 15, + R_SPARC_PC10 = 16, + R_SPARC_PC22 = 17, + R_SPARC_WPLT30 = 18, + R_SPARC_COPY = 19, + R_SPARC_GLOB_DAT = 20, + R_SPARC_JMP_SLOT = 21, + R_SPARC_RELATIVE = 22, + R_SPARC_UA32 = 23, + R_SPARC_PLT32 = 24, + R_SPARC_HIPLT22 = 25, + R_SPARC_LOPLT10 = 26, + R_SPARC_PCPLT32 = 27, + R_SPARC_PCPLT22 = 28, + R_SPARC_PCPLT10 = 29, + R_SPARC_10 = 30, + R_SPARC_11 = 31, + R_SPARC_64 = 32, + R_SPARC_OLO10 = 33, + R_SPARC_HH22 = 34, + R_SPARC_HM10 = 35, + R_SPARC_LM22 = 36, + R_SPARC_PC_HH22 = 37, + R_SPARC_PC_HM10 = 38, + R_SPARC_PC_LM22 = 39, + R_SPARC_WDISP16 = 40, + R_SPARC_WDISP19 = 41, + R_SPARC_7 = 43, + R_SPARC_5 = 44, + R_SPARC_6 = 45, + R_SPARC_DISP64 = 46, + R_SPARC_PLT64 = 47, + R_SPARC_HIX22 = 48, + R_SPARC_LOX10 = 49, + R_SPARC_H44 = 50, + R_SPARC_M44 = 51, + R_SPARC_L44 = 52, + R_SPARC_REGISTER = 53, + R_SPARC_UA64 = 54, + R_SPARC_UA16 = 55, + R_SPARC_TLS_GD_HI22 = 56, + R_SPARC_TLS_GD_LO10 = 57, + R_SPARC_TLS_GD_ADD = 58, + R_SPARC_TLS_GD_CALL = 59, + R_SPARC_TLS_LDM_HI22 = 60, + R_SPARC_TLS_LDM_LO10 = 61, + R_SPARC_TLS_LDM_ADD = 62, + R_SPARC_TLS_LDM_CALL = 63, + R_SPARC_TLS_LDO_HIX22 = 64, + R_SPARC_TLS_LDO_LOX10 = 65, + R_SPARC_TLS_LDO_ADD = 66, + R_SPARC_TLS_IE_HI22 = 67, + R_SPARC_TLS_IE_LO10 = 68, + R_SPARC_TLS_IE_LD = 69, + R_SPARC_TLS_IE_LDX = 70, + R_SPARC_TLS_IE_ADD = 71, + R_SPARC_TLS_LE_HIX22 = 72, + R_SPARC_TLS_LE_LOX10 = 73, + R_SPARC_TLS_DTPMOD32 = 74, + R_SPARC_TLS_DTPMOD64 = 75, + R_SPARC_TLS_DTPOFF32 = 76, + R_SPARC_TLS_DTPOFF64 = 77, + R_SPARC_TLS_TPOFF32 = 78, + R_SPARC_TLS_TPOFF64 = 79, + R_SPARC_GOTDATA_HIX22 = 80, + R_SPARC_GOTDATA_LOX22 = 81, + R_SPARC_GOTDATA_OP_HIX22 = 82, + R_SPARC_GOTDATA_OP_LOX22 = 83, + R_SPARC_GOTDATA_OP = 84 +}; + // Section header. struct Elf32_Shdr { Elf32_Word sh_name; // Section name (index into string table) @@ -1130,7 +1290,7 @@ enum { }; // Section types. -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { SHT_NULL = 0, // No associated section (inactive entry). SHT_PROGBITS = 1, // Program-defined contents. SHT_SYMTAB = 2, // Symbol table. @@ -1171,6 +1331,7 @@ enum LLVM_ENUM_INT_TYPE(unsigned) { SHT_MIPS_REGINFO = 0x70000006, // Register usage information SHT_MIPS_OPTIONS = 0x7000000d, // General options + SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. @@ -1178,7 +1339,7 @@ enum LLVM_ENUM_INT_TYPE(unsigned) { }; // Section flags. -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { // Section data should be writable during execution. SHF_WRITE = 0x1, @@ -1270,7 +1431,7 @@ enum LLVM_ENUM_INT_TYPE(unsigned) { }; // Section Group Flags -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { GRP_COMDAT = 0x1, GRP_MASKOS = 0x0ff00000, GRP_MASKPROC = 0xf0000000 @@ -1488,11 +1649,12 @@ enum { // MIPS program header types. PT_MIPS_REGINFO = 0x70000000, // Register usage information. PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. - PT_MIPS_OPTIONS = 0x70000002 // Options segment. + PT_MIPS_OPTIONS = 0x70000002, // Options segment. + PT_MIPS_ABIFLAGS = 0x70000003 // Abiflags segment. }; // Segment flag bits. -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { PF_X = 1, // Execute PF_W = 2, // Write PF_R = 4, // Read @@ -1566,6 +1728,7 @@ enum { DT_LOPROC = 0x70000000, // Start of processor specific tags. DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags. + DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table. DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count. DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 0d358498839d..455d0fc241f2 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -17,7 +17,6 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Host.h" #include "llvm/Support/SwapByteOrder.h" -#include "llvm/Support/type_traits.h" namespace llvm { namespace support { @@ -35,13 +34,15 @@ namespace detail { } // end namespace detail namespace endian { +/// Swap the bytes of value to match the given endianness. template<typename value_type, endianness endian> inline value_type byte_swap(value_type value) { if (endian != native && sys::IsBigEndianHost != (endian == big)) - return sys::SwapByteOrder(value); + sys::swapByteOrder(value); return value; } +/// Read a value of a particular endianness from memory. template<typename value_type, endianness endian, std::size_t alignment> @@ -55,6 +56,16 @@ inline value_type read(const void *memory) { return byte_swap<value_type, endian>(ret); } +/// Read a value of a particular endianness from a buffer, and increment the +/// buffer past that value. +template<typename value_type, endianness endian, std::size_t alignment> +inline value_type readNext(const unsigned char *&memory) { + value_type ret = read<value_type, endian, alignment>(memory); + memory += sizeof(value_type); + return ret; +} + +/// Write a value to memory with a particular endianness. template<typename value_type, endianness endian, std::size_t alignment> diff --git a/include/llvm/Support/EndianStream.h b/include/llvm/Support/EndianStream.h new file mode 100644 index 000000000000..89c66d3b8480 --- /dev/null +++ b/include/llvm/Support/EndianStream.h @@ -0,0 +1,39 @@ +//===- EndianStream.h - Stream ops with endian specific data ----*- 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 utilities for operating on streams that have endian +// specific data. +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_SUPPORT_ENDIAN_STREAM_H_ +#define _LLVM_SUPPORT_ENDIAN_STREAM_H_ + +#include <llvm/Support/Endian.h> +#include <llvm/Support/raw_ostream.h> + +namespace llvm { +namespace support { + +namespace endian { +/// Adapter to write values to a stream in a particular byte order. +template <endianness endian> struct Writer { + raw_ostream &OS; + Writer(raw_ostream &OS) : OS(OS) {} + template <typename value_type> void write(value_type Val) { + Val = byte_swap<value_type, endian>(Val); + OS.write((const char *)&Val, sizeof(value_type)); + } +}; +} // end namespace endian + +} // end namespace support +} // end namespace llvm + +#endif // _LLVM_SUPPORT_ENDIAN_STREAM_H_ diff --git a/include/llvm/Support/Errc.h b/include/llvm/Support/Errc.h new file mode 100644 index 000000000000..80bfe2ac2ee5 --- /dev/null +++ b/include/llvm/Support/Errc.h @@ -0,0 +1,86 @@ +//===- llvm/Support/Errc.h - Defines the llvm::errc enum --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// While std::error_code works OK on all platforms we use, there are some +// some problems with std::errc that can be avoided by using our own +// enumeration: +// +// * std::errc is a namespace in some implementations. That meas that ADL +// doesn't work and it is sometimes necessary to write std::make_error_code +// or in templates: +// using std::make_error_code; +// make_error_code(...); +// +// with this enum it is safe to always just use make_error_code. +// +// * Some implementations define fewer names than others. This header has +// the intersection of all the ones we support. +// +// * std::errc is just marked with is_error_condition_enum. This means that +// common patters like AnErrorCode == errc::no_such_file_or_directory take +// 4 virtual calls instead of two comparisons. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERRC_H +#define LLVM_SUPPORT_ERRC_H + +#include <system_error> + +namespace llvm { +enum class errc { + argument_list_too_long = int(std::errc::argument_list_too_long), + argument_out_of_domain = int(std::errc::argument_out_of_domain), + bad_address = int(std::errc::bad_address), + bad_file_descriptor = int(std::errc::bad_file_descriptor), + broken_pipe = int(std::errc::broken_pipe), + device_or_resource_busy = int(std::errc::device_or_resource_busy), + directory_not_empty = int(std::errc::directory_not_empty), + executable_format_error = int(std::errc::executable_format_error), + file_exists = int(std::errc::file_exists), + file_too_large = int(std::errc::file_too_large), + filename_too_long = int(std::errc::filename_too_long), + function_not_supported = int(std::errc::function_not_supported), + illegal_byte_sequence = int(std::errc::illegal_byte_sequence), + inappropriate_io_control_operation = + int(std::errc::inappropriate_io_control_operation), + interrupted = int(std::errc::interrupted), + invalid_argument = int(std::errc::invalid_argument), + invalid_seek = int(std::errc::invalid_seek), + io_error = int(std::errc::io_error), + is_a_directory = int(std::errc::is_a_directory), + no_child_process = int(std::errc::no_child_process), + no_lock_available = int(std::errc::no_lock_available), + no_space_on_device = int(std::errc::no_space_on_device), + no_such_device_or_address = int(std::errc::no_such_device_or_address), + no_such_device = int(std::errc::no_such_device), + no_such_file_or_directory = int(std::errc::no_such_file_or_directory), + no_such_process = int(std::errc::no_such_process), + not_a_directory = int(std::errc::not_a_directory), + not_enough_memory = int(std::errc::not_enough_memory), + operation_not_permitted = int(std::errc::operation_not_permitted), + permission_denied = int(std::errc::permission_denied), + read_only_file_system = int(std::errc::read_only_file_system), + resource_deadlock_would_occur = int(std::errc::resource_deadlock_would_occur), + resource_unavailable_try_again = + int(std::errc::resource_unavailable_try_again), + result_out_of_range = int(std::errc::result_out_of_range), + too_many_files_open_in_system = int(std::errc::too_many_files_open_in_system), + too_many_files_open = int(std::errc::too_many_files_open), + too_many_links = int(std::errc::too_many_links) +}; + +inline std::error_code make_error_code(errc E) { + return std::error_code(static_cast<int>(E), std::generic_category()); +} +} + +namespace std { +template <> struct is_error_code_enum<llvm::errc> : std::true_type {}; +} +#endif diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h index b948d97bff92..9afd52d1abc7 100644 --- a/include/llvm/Support/ErrorHandling.h +++ b/include/llvm/Support/ErrorHandling.h @@ -30,9 +30,6 @@ namespace llvm { /// install_fatal_error_handler - Installs a new error handler to be used /// whenever a serious (non-recoverable) error is encountered by LLVM. /// - /// If you are using llvm_start_multithreaded, you should register the handler - /// before doing that. - /// /// If no error handler is installed the default is to print the error message /// to stderr, and call exit(1). If an error handler is installed then it is /// the handler's responsibility to log the message, it will no longer be @@ -47,11 +44,9 @@ namespace llvm { /// \param user_data - An argument which will be passed to the install error /// handler. void install_fatal_error_handler(fatal_error_handler_t handler, - void *user_data = 0); + void *user_data = nullptr); /// Restores default error handling behaviour. - /// This must not be called between llvm_start_multithreaded() and - /// llvm_stop_multithreaded(). void remove_fatal_error_handler(); /// ScopedFatalErrorHandler - This is a simple helper class which just @@ -59,7 +54,7 @@ namespace llvm { /// remove_fatal_error_handler in its destructor. struct ScopedFatalErrorHandler { explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, - void *user_data = 0) { + void *user_data = nullptr) { install_fatal_error_handler(handler, user_data); } @@ -86,9 +81,9 @@ namespace llvm { /// This function calls abort(), and prints the optional message to stderr. /// Use the llvm_unreachable macro (that adds location info), instead of /// calling this function directly. - LLVM_ATTRIBUTE_NORETURN void llvm_unreachable_internal(const char *msg=0, - const char *file=0, - unsigned line=0); + LLVM_ATTRIBUTE_NORETURN void + llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, + unsigned line=0); } /// Marks that the current location is not supposed to be reachable. diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index d5b11cbe5223..0742a2d06f71 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -18,16 +18,11 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/AlignOf.h" -#include "llvm/Support/system_error.h" -#include "llvm/Support/type_traits.h" - #include <cassert> -#if LLVM_HAS_CXX11_TYPETRAITS +#include <system_error> #include <type_traits> -#endif namespace llvm { -#if LLVM_HAS_CXX11_TYPETRAITS && LLVM_HAS_RVALUE_REFERENCES template<class T, class V> typename std::enable_if< std::is_constructible<T, V>::value , typename std::remove_reference<V>::type>::type && @@ -41,12 +36,6 @@ typename std::enable_if< !std::is_constructible<T, V>::value moveIfMoveConstructible(V &Val) { return Val; } -#else -template<class T, class V> -V &moveIfMoveConstructible(V &Val) { - return Val; -} -#endif /// \brief Stores a reference that can be changed. template <typename T> @@ -71,11 +60,10 @@ public: /// It is used like the following. /// \code /// ErrorOr<Buffer> getBuffer(); -/// void handleError(error_code ec); /// /// auto buffer = getBuffer(); -/// if (!buffer) -/// handleError(buffer); +/// if (error_code ec = buffer.getError()) +/// return ec; /// buffer->write("adena"); /// \endcode /// @@ -93,35 +81,33 @@ public: template<class T> class ErrorOr { template <class OtherT> friend class ErrorOr; - static const bool isRef = is_reference<T>::value; - typedef ReferenceStorage<typename remove_reference<T>::type> wrap; + static const bool isRef = std::is_reference<T>::value; + typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap; public: - typedef typename - conditional< isRef - , wrap - , T - >::type storage_type; + typedef typename std::conditional<isRef, wrap, T>::type storage_type; private: - typedef typename remove_reference<T>::type &reference; - typedef typename remove_reference<T>::type *pointer; + typedef typename std::remove_reference<T>::type &reference; + typedef const typename std::remove_reference<T>::type &const_reference; + typedef typename std::remove_reference<T>::type *pointer; public: template <class E> - ErrorOr(E ErrorCode, typename enable_if_c<is_error_code_enum<E>::value || - is_error_condition_enum<E>::value, - void *>::type = 0) + ErrorOr(E ErrorCode, + typename std::enable_if<std::is_error_code_enum<E>::value || + std::is_error_condition_enum<E>::value, + void *>::type = 0) : HasError(true) { - new (getError()) error_code(make_error_code(ErrorCode)); + new (getErrorStorage()) std::error_code(make_error_code(ErrorCode)); } - ErrorOr(llvm::error_code EC) : HasError(true) { - new (getError()) error_code(EC); + ErrorOr(std::error_code EC) : HasError(true) { + new (getErrorStorage()) std::error_code(EC); } ErrorOr(T Val) : HasError(false) { - new (get()) storage_type(moveIfMoveConstructible<storage_type>(Val)); + new (getStorage()) storage_type(moveIfMoveConstructible<storage_type>(Val)); } ErrorOr(const ErrorOr &Other) { @@ -144,7 +130,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES ErrorOr(ErrorOr &&Other) { moveConstruct(std::move(Other)); } @@ -164,31 +149,30 @@ public: moveAssign(std::move(Other)); return *this; } -#endif ~ErrorOr() { if (!HasError) - get()->~storage_type(); + getStorage()->~storage_type(); } - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} - /// \brief Return false if there is an error. - operator unspecified_bool_type() const { - return HasError ? 0 : unspecified_bool_true; + LLVM_EXPLICIT operator bool() const { + return !HasError; } - operator llvm::error_code() const { - return HasError ? *getError() : llvm::error_code::success(); + reference get() { return *getStorage(); } + const_reference get() const { return const_cast<ErrorOr<T> >(this)->get(); } + + std::error_code getError() const { + return HasError ? *getErrorStorage() : std::error_code(); } pointer operator ->() { - return toPointer(get()); + return toPointer(getStorage()); } reference operator *() { - return *get(); + return *getStorage(); } private: @@ -197,11 +181,11 @@ private: if (!Other.HasError) { // Get the other value. HasError = false; - new (get()) storage_type(*Other.get()); + new (getStorage()) storage_type(*Other.getStorage()); } else { // Get other's error. HasError = true; - new (getError()) error_code(Other); + new (getErrorStorage()) std::error_code(Other.getError()); } } @@ -224,17 +208,16 @@ private: new (this) ErrorOr(Other); } -#if LLVM_HAS_RVALUE_REFERENCES template <class OtherT> void moveConstruct(ErrorOr<OtherT> &&Other) { if (!Other.HasError) { // Get the other value. HasError = false; - new (get()) storage_type(std::move(*Other.get())); + new (getStorage()) storage_type(std::move(*Other.getStorage())); } else { // Get other's error. HasError = true; - new (getError()) error_code(Other); + new (getErrorStorage()) std::error_code(Other.getError()); } } @@ -246,7 +229,6 @@ private: this->~ErrorOr(); new (this) ErrorOr(std::move(Other)); } -#endif pointer toPointer(pointer Val) { return Val; @@ -256,38 +238,39 @@ private: return &Val->get(); } - storage_type *get() { + storage_type *getStorage() { assert(!HasError && "Cannot get value when an error exists!"); return reinterpret_cast<storage_type*>(TStorage.buffer); } - const storage_type *get() const { + const storage_type *getStorage() const { assert(!HasError && "Cannot get value when an error exists!"); return reinterpret_cast<const storage_type*>(TStorage.buffer); } - error_code *getError() { + std::error_code *getErrorStorage() { assert(HasError && "Cannot get error when a value exists!"); - return reinterpret_cast<error_code*>(ErrorStorage.buffer); + return reinterpret_cast<std::error_code *>(ErrorStorage.buffer); } - const error_code *getError() const { - return const_cast<ErrorOr<T> *>(this)->getError(); + const std::error_code *getErrorStorage() const { + return const_cast<ErrorOr<T> *>(this)->getErrorStorage(); } union { AlignedCharArrayUnion<storage_type> TStorage; - AlignedCharArrayUnion<error_code> ErrorStorage; + AlignedCharArrayUnion<std::error_code> ErrorStorage; }; bool HasError : 1; }; -template<class T, class E> -typename enable_if_c<is_error_code_enum<E>::value || - is_error_condition_enum<E>::value, bool>::type -operator ==(ErrorOr<T> &Err, E Code) { - return error_code(Err) == Code; +template <class T, class E> +typename std::enable_if<std::is_error_code_enum<E>::value || + std::is_error_condition_enum<E>::value, + bool>::type +operator==(ErrorOr<T> &Err, E Code) { + return std::error_code(Err) == Code; } } // end namespace llvm diff --git a/include/llvm/Support/FEnv.h b/include/llvm/Support/FEnv.h deleted file mode 100644 index 8560ee0a8afe..000000000000 --- a/include/llvm/Support/FEnv.h +++ /dev/null @@ -1,56 +0,0 @@ -//===- llvm/Support/FEnv.h - Host floating-point exceptions ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides an operating system independent interface to -// floating-point exception interfaces. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_FENV_H -#define LLVM_SUPPORT_FENV_H - -#include "llvm/Config/config.h" -#include <cerrno> -#ifdef HAVE_FENV_H -#include <fenv.h> -#endif - -// FIXME: Clang's #include handling apparently doesn't work for libstdc++'s -// fenv.h; see PR6907 for details. -#if defined(__clang__) && defined(_GLIBCXX_FENV_H) -#undef HAVE_FENV_H -#endif - -namespace llvm { -namespace sys { - -/// llvm_fenv_clearexcept - Clear the floating-point exception state. -static inline void llvm_fenv_clearexcept() { -#if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT - feclearexcept(FE_ALL_EXCEPT); -#endif - errno = 0; -} - -/// llvm_fenv_testexcept - Test if a floating-point exception was raised. -static inline bool llvm_fenv_testexcept() { - int errno_val = errno; - if (errno_val == ERANGE || errno_val == EDOM) - return true; -#if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT && HAVE_DECL_FE_INEXACT - if (fetestexcept(FE_ALL_EXCEPT & ~FE_INEXACT)) - return true; -#endif - return false; -} - -} // End sys namespace -} // End llvm namespace - -#endif diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index cbc9c467d23d..0a9a97995156 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -14,15 +14,12 @@ #ifndef LLVM_SUPPORT_FILEOUTPUTBUFFER_H #define LLVM_SUPPORT_FILEOUTPUTBUFFER_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/FileSystem.h" namespace llvm { -class error_code; - /// FileOutputBuffer - This interface provides simple way to create an in-memory /// buffer which will be written to a file. During the lifetime of these /// objects, the content or existence of the specified file is undefined. That @@ -40,9 +37,9 @@ public: /// Factory method to create an OutputBuffer object which manages a read/write /// buffer of the specified size. When committed, the buffer will be written /// to the file at the specified path. - static error_code create(StringRef FilePath, size_t Size, - OwningPtr<FileOutputBuffer> &Result, - unsigned Flags = 0); + static std::error_code create(StringRef FilePath, size_t Size, + std::unique_ptr<FileOutputBuffer> &Result, + unsigned Flags = 0); /// Returns a pointer to the start of the buffer. uint8_t *getBufferStart() { @@ -69,7 +66,7 @@ public: /// is called, the file is deleted in the destructor. The optional parameter /// is used if it turns out you want the file size to be smaller than /// initially requested. - error_code commit(int64_t NewSmallerSize = -1); + std::error_code commit(int64_t NewSmallerSize = -1); /// If this object was previously committed, the destructor just deletes /// this object. If this object was not committed, the destructor @@ -83,7 +80,7 @@ private: FileOutputBuffer(llvm::sys::fs::mapped_file_region *R, StringRef Path, StringRef TempPath); - OwningPtr<llvm::sys::fs::mapped_file_region> Region; + std::unique_ptr<llvm::sys::fs::mapped_file_region> Region; SmallString<128> FinalPath; SmallString<128> TempPath; }; diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index d301f842ea9f..556701c3ba34 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -28,17 +28,17 @@ #define LLVM_SUPPORT_FILESYSTEM_H #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TimeValue.h" -#include "llvm/Support/system_error.h" #include <ctime> #include <iterator> #include <stack> #include <string> +#include <system_error> +#include <tuple> #include <vector> #ifdef HAVE_SYS_STAT_H @@ -49,28 +49,18 @@ namespace llvm { namespace sys { namespace fs { -/// file_type - An "enum class" enumeration for the file system's view of the -/// type. -struct file_type { - enum _ { - status_error, - file_not_found, - regular_file, - directory_file, - symlink_file, - block_file, - character_file, - fifo_file, - socket_file, - type_unknown - }; - - file_type(_ v) : v_(v) {} - explicit file_type(int v) : v_(_(v)) {} - operator int() const {return v_;} - -private: - int v_; +/// An enumeration for the file system's view of the type. +enum class file_type { + status_error, + file_not_found, + regular_file, + directory_file, + symlink_file, + block_file, + character_file, + fifo_file, + socket_file, + type_unknown }; /// space_info - Self explanatory. @@ -137,15 +127,14 @@ public: } bool operator!=(const UniqueID &Other) const { return !(*this == Other); } bool operator<(const UniqueID &Other) const { - return Device < Other.Device || - (Device == Other.Device && File < Other.File); + return std::tie(Device, File) < std::tie(Other.Device, Other.File); } uint64_t getDevice() const { return Device; } uint64_t getFile() const { return File; } }; /// file_status - Represents the result of a call to stat and friends. It has -/// a platform specific member to store the result. +/// a platform-specific member to store the result. class file_status { #if defined(LLVM_ON_UNIX) @@ -168,15 +157,30 @@ class file_status file_type Type; perms Perms; public: - file_status() : Type(file_type::status_error) {} - file_status(file_type Type) : Type(Type) {} - #if defined(LLVM_ON_UNIX) + file_status() : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), + fs_st_uid(0), fs_st_gid(0), fs_st_size(0), + Type(file_type::status_error), Perms(perms_not_known) {} + + file_status(file_type Type) : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), + fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type), + Perms(perms_not_known) {} + file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t MTime, uid_t UID, gid_t GID, off_t Size) : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_mtime(MTime), fs_st_uid(UID), fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {} #elif defined(LLVM_ON_WIN32) + file_status() : LastWriteTimeHigh(0), LastWriteTimeLow(0), + VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), + FileIndexHigh(0), FileIndexLow(0), Type(file_type::status_error), + Perms(perms_not_known) {} + + file_status(file_type Type) : LastWriteTimeHigh(0), LastWriteTimeLow(0), + VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), + FileIndexHigh(0), FileIndexLow(0), Type(Type), + Perms(perms_not_known) {} + file_status(file_type Type, uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber, uint32_t FileSizeHigh, uint32_t FileSizeLow, @@ -269,107 +273,81 @@ private: /// /// @param path A path that is modified to be an absolute path. /// @returns errc::success if \a path has been made absolute, otherwise a -/// platform specific error_code. -error_code make_absolute(SmallVectorImpl<char> &path); +/// platform-specific error_code. +std::error_code make_absolute(SmallVectorImpl<char> &path); + +/// @brief Normalize path separators in \a Path +/// +/// If the path contains any '\' separators, they are transformed into '/'. +/// This is particularly useful when cross-compiling Windows on Linux, but is +/// safe to invoke on Windows, which accepts both characters as a path +/// separator. +std::error_code normalize_separators(SmallVectorImpl<char> &Path); /// @brief Create all the non-existent directories in path. /// /// @param path Directories to create. -/// @param existed Set to true if \a path already existed, false otherwise. -/// @returns errc::success if is_directory(path) and existed have been set, -/// otherwise a platform specific error_code. -error_code create_directories(const Twine &path, bool &existed); - -/// @brief Convenience function for clients that don't need to know if the -/// directory existed or not. -inline error_code create_directories(const Twine &Path) { - bool Existed; - return create_directories(Path, Existed); -} +/// @returns errc::success if is_directory(path), otherwise a platform +/// specific error_code. If IgnoreExisting is false, also returns +/// error if the directory already existed. +std::error_code create_directories(const Twine &path, + bool IgnoreExisting = true); /// @brief Create the directory in path. /// /// @param path Directory to create. -/// @param existed Set to true if \a path already existed, false otherwise. -/// @returns errc::success if is_directory(path) and existed have been set, -/// otherwise a platform specific error_code. -error_code create_directory(const Twine &path, bool &existed); - -/// @brief Convenience function for clients that don't need to know if the -/// directory existed or not. -inline error_code create_directory(const Twine &Path) { - bool Existed; - return create_directory(Path, Existed); -} +/// @returns errc::success if is_directory(path), otherwise a platform +/// specific error_code. If IgnoreExisting is false, also returns +/// error if the directory already existed. +std::error_code create_directory(const Twine &path, bool IgnoreExisting = true); -/// @brief Create a hard link from \a from to \a to. +/// @brief Create a link from \a from to \a to. +/// +/// The link may be a soft or a hard link, depending on the platform. The caller +/// may not assume which one. Currently on windows it creates a hard link since +/// soft links require extra privileges. On unix, it creates a soft link since +/// hard links don't work on SMB file systems. /// /// @param to The path to hard link to. /// @param from The path to hard link from. This is created. -/// @returns errc::success if exists(to) && exists(from) && equivalent(to, from) -/// , otherwise a platform specific error_code. -error_code create_hard_link(const Twine &to, const Twine &from); - -/// @brief Create a symbolic link from \a from to \a to. -/// -/// @param to The path to symbolically link to. -/// @param from The path to symbolically link from. This is created. -/// @returns errc::success if exists(to) && exists(from) && is_symlink(from), -/// otherwise a platform specific error_code. -error_code create_symlink(const Twine &to, const Twine &from); +/// @returns errc::success if the link was created, otherwise a platform +/// specific error_code. +std::error_code create_link(const Twine &to, const Twine &from); /// @brief Get the current path. /// /// @param result Holds the current path on return. /// @returns errc::success if the current path has been stored in result, -/// otherwise a platform specific error_code. -error_code current_path(SmallVectorImpl<char> &result); +/// otherwise a platform-specific error_code. +std::error_code current_path(SmallVectorImpl<char> &result); /// @brief Remove path. Equivalent to POSIX remove(). /// /// @param path Input path. -/// @param existed Set to true if \a path existed, false if it did not. -/// undefined otherwise. -/// @returns errc::success if path has been removed and existed has been -/// successfully set, otherwise a platform specific error_code. -error_code remove(const Twine &path, bool &existed); - -/// @brief Convenience function for clients that don't need to know if the file -/// existed or not. -inline error_code remove(const Twine &Path) { - bool Existed; - return remove(Path, Existed); -} - -/// @brief Recursively remove all files below \a path, then \a path. Files are -/// removed as if by POSIX remove(). -/// -/// @param path Input path. -/// @param num_removed Number of files removed. -/// @returns errc::success if path has been removed and num_removed has been -/// successfully set, otherwise a platform specific error_code. -error_code remove_all(const Twine &path, uint32_t &num_removed); - -/// @brief Convenience function for clients that don't need to know how many -/// files were removed. -inline error_code remove_all(const Twine &Path) { - uint32_t Removed; - return remove_all(Path, Removed); -} +/// @returns errc::success if path has been removed or didn't exist, otherwise a +/// platform-specific error code. If IgnoreNonExisting is false, also +/// returns error if the file didn't exist. +std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); /// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). /// /// @param from The path to rename from. /// @param to The path to rename to. This is created. -error_code rename(const Twine &from, const Twine &to); +std::error_code rename(const Twine &from, const Twine &to); + +/// @brief Copy the contents of \a From to \a To. +/// +/// @param From The path to copy from. +/// @param To The path to copy to. This is created. +std::error_code copy_file(const Twine &From, const Twine &To); /// @brief Resize path to size. File is resized as if by POSIX truncate(). /// /// @param path Input path. /// @param size Size to resize to. /// @returns errc::success if \a path has been resized to \a size, otherwise a -/// platform specific error_code. -error_code resize_file(const Twine &path, uint64_t size); +/// platform-specific error_code. +std::error_code resize_file(const Twine &path, uint64_t size); /// @} /// @name Physical Observers @@ -388,8 +366,8 @@ bool exists(file_status status); /// @param result Set to true if the file represented by status exists, false if /// it does not. Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code exists(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code exists(const Twine &path, bool &result); /// @brief Simpler version of exists for clients that don't need to /// differentiate between an error and false. @@ -430,8 +408,8 @@ bool equivalent(file_status A, file_status B); /// @param result Set to true if stat(A) and stat(B) have the same device and /// inode (or equivalent). /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code equivalent(const Twine &A, const Twine &B, bool &result); +/// platform-specific error_code. +std::error_code equivalent(const Twine &A, const Twine &B, bool &result); /// @brief Simpler version of equivalent for clients that don't need to /// differentiate between an error and false. @@ -452,8 +430,8 @@ bool is_directory(file_status status); /// @param result Set to true if \a path is a directory, false if it is not. /// Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_directory(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code is_directory(const Twine &path, bool &result); /// @brief Simpler version of is_directory for clients that don't need to /// differentiate between an error and false. @@ -474,8 +452,8 @@ bool is_regular_file(file_status status); /// @param result Set to true if \a path is a regular file, false if it is not. /// Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_regular_file(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code is_regular_file(const Twine &path, bool &result); /// @brief Simpler version of is_regular_file for clients that don't need to /// differentiate between an error and false. @@ -490,8 +468,7 @@ inline bool is_regular_file(const Twine &Path) { /// directory, regular file, or symlink? /// /// @param status A file_status previously returned from status. -/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) && -/// !is_symlink(s) +/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) bool is_other(file_status status); /// @brief Is path something that exists but is not a directory, @@ -501,51 +478,41 @@ bool is_other(file_status status); /// @param result Set to true if \a path exists, but is not a directory, regular /// file, or a symlink, false if it does not. Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_other(const Twine &path, bool &result); - -/// @brief Does status represent a symlink? -/// -/// @param status A file_status previously returned from stat. -/// @returns status.type() == symlink_file. -bool is_symlink(file_status status); - -/// @brief Is path a symlink? -/// -/// @param path Input path. -/// @param result Set to true if \a path is a symlink, false if it is not. -/// Undefined otherwise. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_symlink(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code is_other(const Twine &path, bool &result); /// @brief Get file status as if by POSIX stat(). /// /// @param path Input path. /// @param result Set to the file status. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code status(const Twine &path, file_status &result); +/// platform-specific error_code. +std::error_code status(const Twine &path, file_status &result); /// @brief A version for when a file descriptor is already available. -error_code status(int FD, file_status &Result); +std::error_code status(int FD, file_status &Result); /// @brief Get file size. /// /// @param Path Input path. /// @param Result Set to the size of the file in \a Path. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -inline error_code file_size(const Twine &Path, uint64_t &Result) { +/// platform-specific error_code. +inline std::error_code file_size(const Twine &Path, uint64_t &Result) { file_status Status; - error_code EC = status(Path, Status); + std::error_code EC = status(Path, Status); if (EC) return EC; Result = Status.getSize(); - return error_code::success(); + return std::error_code(); } -error_code setLastModificationAndAccessTime(int FD, TimeValue Time); +/// @brief Set the file modification and access time. +/// +/// @returns errc::success if the file times were successfully set, otherwise a +/// platform-specific error_code or errc::function_not_supported on +/// platforms where the functionality isn't available. +std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); /// @brief Is status available? /// @@ -558,8 +525,8 @@ bool status_known(file_status s); /// @param path Input path. /// @param result Set to true if status() != status_error. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code status_known(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code status_known(const Twine &path, bool &result); /// @brief Create a uniquely named file. /// @@ -581,14 +548,14 @@ error_code status_known(const Twine &path, bool &result); /// @param ResultFD Set to the opened file's file descriptor. /// @param ResultPath Set to the opened file's absolute path. /// @returns errc::success if Result{FD,Path} have been successfully set, -/// otherwise a platform specific error_code. -error_code createUniqueFile(const Twine &Model, int &ResultFD, - SmallVectorImpl<char> &ResultPath, - unsigned Mode = all_read | all_write); +/// otherwise a platform-specific error_code. +std::error_code createUniqueFile(const Twine &Model, int &ResultFD, + SmallVectorImpl<char> &ResultPath, + unsigned Mode = all_read | all_write); /// @brief Simpler version for clients that don't want an open file. -error_code createUniqueFile(const Twine &Model, - SmallVectorImpl<char> &ResultPath); +std::error_code createUniqueFile(const Twine &Model, + SmallVectorImpl<char> &ResultPath); /// @brief Create a file in the system temporary directory. /// @@ -598,18 +565,18 @@ error_code createUniqueFile(const Twine &Model, /// /// This should be used for things like a temporary .s that is removed after /// running the assembler. -error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, - int &ResultFD, - SmallVectorImpl<char> &ResultPath); +std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + int &ResultFD, + SmallVectorImpl<char> &ResultPath); /// @brief Simpler version for clients that don't want an open file. -error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, - SmallVectorImpl<char> &ResultPath); +std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + SmallVectorImpl<char> &ResultPath); -error_code createUniqueDirectory(const Twine &Prefix, - SmallVectorImpl<char> &ResultPath); +std::error_code createUniqueDirectory(const Twine &Prefix, + SmallVectorImpl<char> &ResultPath); -enum OpenFlags { +enum OpenFlags : unsigned { F_None = 0, /// F_Excl - When opening a file, this flag makes raw_fd_ostream @@ -621,9 +588,12 @@ enum OpenFlags { /// with F_Excl. F_Append = 2, - /// F_Binary - The file should be opened in binary mode on platforms that - /// make this distinction. - F_Binary = 4 + /// The file should be opened in text mode on platforms that make this + /// distinction. + F_Text = 4, + + /// Open the file for read and write. + F_RW = 8 }; inline OpenFlags operator|(OpenFlags A, OpenFlags B) { @@ -635,31 +605,10 @@ inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { return A; } -error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags, - unsigned Mode = 0666); +std::error_code openFileForWrite(const Twine &Name, int &ResultFD, + OpenFlags Flags, unsigned Mode = 0666); -error_code openFileForRead(const Twine &Name, int &ResultFD); - -/// @brief Are \a path's first bytes \a magic? -/// -/// @param path Input path. -/// @param magic Byte sequence to compare \a path's first len(magic) bytes to. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code has_magic(const Twine &path, const Twine &magic, bool &result); - -/// @brief Get \a path's first \a len bytes. -/// -/// @param path Input path. -/// @param len Number of magic bytes to get. -/// @param result Set to the first \a len bytes in the file pointed to by -/// \a path. Or the entire file if file_size(path) < len, in which -/// case result.size() returns the size of the file. -/// @returns errc::success if result has been successfully set, -/// errc::value_too_large if len is larger then the file pointed to by -/// \a path, otherwise a platform specific error_code. -error_code get_magic(const Twine &path, uint32_t len, - SmallVectorImpl<char> &result); +std::error_code openFileForRead(const Twine &Name, int &ResultFD); /// @brief Identify the type of a binary file based on how magical it is. file_magic identify_magic(StringRef magic); @@ -669,10 +618,10 @@ file_magic identify_magic(StringRef magic); /// @param path Input path. /// @param result Set to the type of file, or file_magic::unknown. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code identify_magic(const Twine &path, file_magic &result); +/// platform-specific error_code. +std::error_code identify_magic(const Twine &path, file_magic &result); -error_code getUniqueID(const Twine Path, UniqueID &Result); +std::error_code getUniqueID(const Twine Path, UniqueID &Result); /// This class represents a memory mapped file. It is based on /// boost::iostreams::mapped_file. @@ -689,7 +638,7 @@ public: }; private: - /// Platform specific mapping state. + /// Platform-specific mapping state. mapmode Mode; uint64_t Size; void *Mapping; @@ -699,15 +648,13 @@ private: void *FileMappingHandle; #endif - error_code init(int FD, bool CloseFD, uint64_t Offset); + std::error_code init(int FD, bool CloseFD, uint64_t Offset); public: typedef char char_type; -#if LLVM_HAS_RVALUE_REFERENCES mapped_file_region(mapped_file_region&&); mapped_file_region &operator =(mapped_file_region&&); -#endif /// Construct a mapped_file_region at \a path starting at \a offset of length /// \a length and with access \a mode. @@ -723,21 +670,14 @@ public: /// mapped_file_region::alignment(). /// \param ec This is set to errc::success if the map was constructed /// successfully. Otherwise it is set to a platform dependent error. - mapped_file_region(const Twine &path, - mapmode mode, - uint64_t length, - uint64_t offset, - error_code &ec); + mapped_file_region(const Twine &path, mapmode mode, uint64_t length, + uint64_t offset, std::error_code &ec); /// \param fd An open file descriptor to map. mapped_file_region takes /// ownership if closefd is true. It must have been opended in the correct /// mode. - mapped_file_region(int fd, - bool closefd, - mapmode mode, - uint64_t length, - uint64_t offset, - error_code &ec); + mapped_file_region(int fd, bool closefd, mapmode mode, uint64_t length, + uint64_t offset, std::error_code &ec); ~mapped_file_region(); @@ -753,30 +693,6 @@ public: static int alignment(); }; -/// @brief Memory maps the contents of a file -/// -/// @param path Path to file to map. -/// @param file_offset Byte offset in file where mapping should begin. -/// @param size Byte length of range of the file to map. -/// @param map_writable If true, the file will be mapped in r/w such -/// that changes to the mapped buffer will be flushed back -/// to the file. If false, the file will be mapped read-only -/// and the buffer will be read-only. -/// @param result Set to the start address of the mapped buffer. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, - bool map_writable, void *&result); - - -/// @brief Memory unmaps the contents of a file -/// -/// @param base Pointer to the start of the buffer. -/// @param size Byte length of the range to unmmap. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code unmap_file_pages(void *base, size_t size); - /// Return the path to the main executable, given the value of argv[0] from /// program startup and the address of main itself. In extremis, this function /// may fail and return an empty path. @@ -808,7 +724,7 @@ public: void replace_filename(const Twine &filename, file_status st = file_status()); const std::string &path() const { return Path; } - error_code status(file_status &result) const; + std::error_code status(file_status &result) const; bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } @@ -821,9 +737,9 @@ public: namespace detail { struct DirIterState; - error_code directory_iterator_construct(DirIterState&, StringRef); - error_code directory_iterator_increment(DirIterState&); - error_code directory_iterator_destruct(DirIterState&); + std::error_code directory_iterator_construct(DirIterState &, StringRef); + std::error_code directory_iterator_increment(DirIterState &); + std::error_code directory_iterator_destruct(DirIterState &); /// DirIterState - Keeps state for the directory_iterator. It is reference /// counted in order to preserve InputIterator semantics on copy. @@ -847,23 +763,23 @@ class directory_iterator { IntrusiveRefCntPtr<detail::DirIterState> State; public: - explicit directory_iterator(const Twine &path, error_code &ec) { + explicit directory_iterator(const Twine &path, std::error_code &ec) { State = new detail::DirIterState; SmallString<128> path_storage; ec = detail::directory_iterator_construct(*State, path.toStringRef(path_storage)); } - explicit directory_iterator(const directory_entry &de, error_code &ec) { + explicit directory_iterator(const directory_entry &de, std::error_code &ec) { State = new detail::DirIterState; ec = detail::directory_iterator_construct(*State, de.path()); } /// Construct end iterator. - directory_iterator() : State(0) {} + directory_iterator() : State(nullptr) {} // No operator++ because we need error_code. - directory_iterator &increment(error_code &ec) { + directory_iterator &increment(std::error_code &ec) { ec = directory_iterator_increment(*State); return *this; } @@ -874,9 +790,9 @@ public: bool operator==(const directory_iterator &RHS) const { if (State == RHS.State) return true; - if (RHS.State == 0) + if (!RHS.State) return State->CurrentEntry == directory_entry(); - if (State == 0) + if (!State) return RHS.State->CurrentEntry == directory_entry(); return State->CurrentEntry == RHS.State->CurrentEntry; } @@ -909,14 +825,14 @@ class recursive_directory_iterator { public: recursive_directory_iterator() {} - explicit recursive_directory_iterator(const Twine &path, error_code &ec) - : State(new detail::RecDirIterState) { + explicit recursive_directory_iterator(const Twine &path, std::error_code &ec) + : State(new detail::RecDirIterState) { State->Stack.push(directory_iterator(path, ec)); if (State->Stack.top() == directory_iterator()) State.reset(); } // No operator++ because we need error_code. - recursive_directory_iterator &increment(error_code &ec) { + recursive_directory_iterator &increment(std::error_code &ec) { const directory_iterator end_itr; if (State->HasNoPushRequest) @@ -965,7 +881,7 @@ public: assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); const directory_iterator end_itr; - error_code ec; + std::error_code ec; do { if (ec) report_fatal_error("Error incrementing directory iterator."); diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h index 79c59e4306c9..3f2f176eb469 100644 --- a/include/llvm/Support/FileUtilities.h +++ b/include/llvm/Support/FileUtilities.h @@ -30,7 +30,7 @@ namespace llvm { int DiffFilesWithTolerance(StringRef FileA, StringRef FileB, double AbsTol, double RelTol, - std::string *Error = 0); + std::string *Error = nullptr); /// FileRemover - This class is a simple object meant to be stack allocated. @@ -51,8 +51,7 @@ namespace llvm { ~FileRemover() { if (DeleteIt) { // Ignore problems deleting the file. - bool existed; - sys::fs::remove(Filename.str(), existed); + sys::fs::remove(Filename.str()); } } @@ -62,8 +61,7 @@ namespace llvm { void setFile(const Twine& filename, bool deleteIt = true) { if (DeleteIt) { // Ignore problems deleting the file. - bool existed; - sys::fs::remove(Filename.str(), existed); + sys::fs::remove(Filename.str()); } Filename.clear(); diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index aaa54e1090a6..b713cc72e852 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -36,23 +36,23 @@ namespace llvm { -/// format_object_base - This is a helper class used for handling formatted -/// output. It is the abstract base class of a templated derived class. +/// This is a helper class used for handling formatted output. It is the +/// abstract base class of a templated derived class. class format_object_base { protected: const char *Fmt; virtual void home(); // Out of line virtual method. - /// snprint - Call snprintf() for this object, on the given buffer and size. + /// Call snprintf() for this object, on the given buffer and size. virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; public: format_object_base(const char *fmt) : Fmt(fmt) {} virtual ~format_object_base() {} - /// print - Format the object into the specified buffer. On success, this - /// returns the length of the formatted string. If the buffer is too small, - /// this returns a length to retry with, which will be larger than BufferSize. + /// Format the object into the specified buffer. On success, this returns + /// the length of the formatted string. If the buffer is too small, this + /// returns a length to retry with, which will be larger than BufferSize. unsigned print(char *Buffer, unsigned BufferSize) const { assert(BufferSize && "Invalid buffer size!"); @@ -61,21 +61,23 @@ public: // VC++ and old GlibC return negative on overflow, just double the size. if (N < 0) - return BufferSize*2; + return BufferSize * 2; - // Other impls yield number of bytes needed, not including the final '\0'. + // Other implementations yield number of bytes needed, not including the + // final '\0'. if (unsigned(N) >= BufferSize) - return N+1; + return N + 1; // Otherwise N is the length of output (not including the final '\0'). return N; } }; -/// format_object1 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. +/// These are templated helper classes used by the format function that +/// capture the object to be formated and the format string. When actually +/// printed, this synthesizes the string into a temporary buffer provided and +/// returns whether or not it is big enough. + template <typename T> class format_object1 : public format_object_base { T Val; @@ -84,15 +86,11 @@ public: : format_object_base(fmt), Val(val) { } - virtual int snprint(char *Buffer, unsigned BufferSize) const { + int snprint(char *Buffer, unsigned BufferSize) const override { return snprintf(Buffer, BufferSize, Fmt, Val); } }; -/// format_object2 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template <typename T1, typename T2> class format_object2 : public format_object_base { T1 Val1; @@ -102,15 +100,11 @@ public: : format_object_base(fmt), Val1(val1), Val2(val2) { } - virtual int snprint(char *Buffer, unsigned BufferSize) const { + int snprint(char *Buffer, unsigned BufferSize) const override { return snprintf(Buffer, BufferSize, Fmt, Val1, Val2); } }; -/// format_object3 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template <typename T1, typename T2, typename T3> class format_object3 : public format_object_base { T1 Val1; @@ -121,15 +115,11 @@ public: : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) { } - virtual int snprint(char *Buffer, unsigned BufferSize) const { + int snprint(char *Buffer, unsigned BufferSize) const override { return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3); } }; -/// format_object4 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template <typename T1, typename T2, typename T3, typename T4> class format_object4 : public format_object_base { T1 Val1; @@ -142,15 +132,11 @@ public: : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) { } - virtual int snprint(char *Buffer, unsigned BufferSize) const { + int snprint(char *Buffer, unsigned BufferSize) const override { return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4); } }; -/// format_object5 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template <typename T1, typename T2, typename T3, typename T4, typename T5> class format_object5 : public format_object_base { T1 Val1; @@ -165,52 +151,57 @@ public: Val5(val5) { } - virtual int snprint(char *Buffer, unsigned BufferSize) const { + int snprint(char *Buffer, unsigned BufferSize) const override { return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5); } }; -/// This is a helper function that is used to produce formatted output. +template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6> +class format_object6 : public format_object_base { + T1 Val1; + T2 Val2; + T3 Val3; + T4 Val4; + T5 Val5; + T6 Val6; +public: + format_object6(const char *Fmt, const T1 &Val1, const T2 &Val2, + const T3 &Val3, const T4 &Val4, const T5 &Val5, const T6 &Val6) + : format_object_base(Fmt), Val1(Val1), Val2(Val2), Val3(Val3), Val4(Val4), + Val5(Val5), Val6(Val6) { } + + int snprint(char *Buffer, unsigned BufferSize) const override { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5, Val6); + } +}; + +/// These are helper functions used to produce formatted output. They use +/// template type deduction to construct the appropriate instance of the +/// format_object class to simplify their construction. /// /// This is typically used like: /// \code /// OS << format("%0.4f", myfloat) << '\n'; /// \endcode + template <typename T> inline format_object1<T> format(const char *Fmt, const T &Val) { return format_object1<T>(Fmt, Val); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template <typename T1, typename T2> inline format_object2<T1, T2> format(const char *Fmt, const T1 &Val1, const T2 &Val2) { return format_object2<T1, T2>(Fmt, Val1, Val2); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template <typename T1, typename T2, typename T3> inline format_object3<T1, T2, T3> format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3) { return format_object3<T1, T2, T3>(Fmt, Val1, Val2, Val3); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template <typename T1, typename T2, typename T3, typename T4> inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, @@ -218,12 +209,6 @@ inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template <typename T1, typename T2, typename T3, typename T4, typename T5> inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1, const T2 &Val2, const T3 &Val3, @@ -231,6 +216,15 @@ inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1, return format_object5<T1, T2, T3, T4, T5>(Fmt, Val1, Val2, Val3, Val4, Val5); } +template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6> +inline format_object6<T1, T2, T3, T4, T5, T6> +format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, + const T4 &Val4, const T5 &Val5, const T6 &Val6) { + return format_object6<T1, T2, T3, T4, T5, T6>(Fmt, Val1, Val2, Val3, Val4, + Val5, Val6); +} + } // end namespace llvm #endif diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index df1f2183e6cc..8137daaff1f8 100644 --- a/include/llvm/Support/FormattedStream.h +++ b/include/llvm/Support/FormattedStream.h @@ -57,11 +57,11 @@ private: /// const char *Scanned; - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, /// not counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE { + uint64_t current_pos() const override { // Our current position in the stream is all the contents which have been // written to the underlying stream (*not* the current position of the // underlying stream). @@ -85,12 +85,12 @@ public: /// underneath it. /// formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) - : raw_ostream(), TheStream(0), DeleteStream(false), Position(0, 0) { + : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { setStream(Stream, Delete); } explicit formatted_raw_ostream() - : raw_ostream(), TheStream(0), DeleteStream(false), Position(0, 0) { - Scanned = 0; + : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { + Scanned = nullptr; } ~formatted_raw_ostream() { @@ -114,7 +114,7 @@ public: SetUnbuffered(); TheStream->SetUnbuffered(); - Scanned = 0; + Scanned = nullptr; } /// PadToColumn - Align the output to some column number. If the current @@ -129,25 +129,23 @@ public: /// getLine - Return the line number unsigned getLine() { return Position.second; } - - raw_ostream &resetColor() { + + raw_ostream &resetColor() override { TheStream->resetColor(); return *this; } - - raw_ostream &reverseColor() { + + raw_ostream &reverseColor() override { TheStream->reverseColor(); return *this; } - - raw_ostream &changeColor(enum Colors Color, - bool Bold, - bool BG) { + + raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override { TheStream->changeColor(Color, Bold, BG); return *this; } - - bool is_displayed() const { + + bool is_displayed() const override { return TheStream->is_displayed(); } diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h index 0aa716aac077..0cb6cfd62ccb 100644 --- a/include/llvm/Support/GCOV.h +++ b/include/llvm/Support/GCOV.h @@ -1,4 +1,4 @@ -//===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===// +//===- GCOV.h - LLVM coverage tool ----------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This header provides the interface to read and write coverage files that +// This header provides the interface to read and write coverage files that // use 'gcov' format. // //===----------------------------------------------------------------------===// @@ -16,6 +16,7 @@ #define LLVM_SUPPORT_GCOV_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/MemoryBuffer.h" @@ -28,36 +29,71 @@ class GCOVBlock; class FileInfo; namespace GCOV { - enum GCOVFormat { - InvalidGCOV, - GCNO_402, - GCNO_404, - GCDA_402, - GCDA_404 + enum GCOVVersion { + V402, + V404 }; } // end GCOV namespace +/// GCOVOptions - A struct for passing gcov options between functions. +struct GCOVOptions { + GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N) + : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), + PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {} + + bool AllBlocks; + bool BranchInfo; + bool BranchCount; + bool FuncCoverage; + bool PreservePaths; + bool UncondBranch; + bool LongFileNames; + bool NoOutput; +}; + /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific /// read operations. class GCOVBuffer { public: GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {} - /// readGCOVFormat - Read GCOV signature at the beginning of buffer. - GCOV::GCOVFormat readGCOVFormat() { - StringRef Magic = Buffer->getBuffer().slice(0, 12); - Cursor = 12; - if (Magic == "oncg*404MVLL") - return GCOV::GCNO_404; - else if (Magic == "oncg*204MVLL") - return GCOV::GCNO_402; - else if (Magic == "adcg*404MVLL") - return GCOV::GCDA_404; - else if (Magic == "adcg*204MVLL") - return GCOV::GCDA_402; - - Cursor = 0; - return GCOV::InvalidGCOV; + /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer. + bool readGCNOFormat() { + StringRef File = Buffer->getBuffer().slice(0, 4); + if (File != "oncg") { + errs() << "Unexpected file type: " << File << ".\n"; + return false; + } + Cursor = 4; + return true; + } + + /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer. + bool readGCDAFormat() { + StringRef File = Buffer->getBuffer().slice(0, 4); + if (File != "adcg") { + errs() << "Unexpected file type: " << File << ".\n"; + return false; + } + Cursor = 4; + return true; + } + + /// readGCOVVersion - Read GCOV version. + bool readGCOVVersion(GCOV::GCOVVersion &Version) { + StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4); + if (VersionStr == "*204") { + Cursor += 4; + Version = GCOV::V402; + return true; + } + if (VersionStr == "*404") { + Cursor += 4; + Version = GCOV::V404; + return true; + } + errs() << "Unexpected version: " << VersionStr << ".\n"; + return false; } /// readFunctionTag - If cursor points to a function tag then increment the @@ -170,8 +206,11 @@ public: } bool readString(StringRef &Str) { - uint32_t Len; - if (!readInt(Len)) return false; + uint32_t Len = 0; + // Keep reading until we find a non-zero length. This emulates gcov's + // behaviour, which appears to do the same. + while (Len == 0) + if (!readInt(Len)) return false; Len *= 4; if (Buffer->getBuffer().size() < Cursor+Len) { errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n"; @@ -193,67 +232,196 @@ private: /// (.gcno and .gcda). class GCOVFile { public: - GCOVFile() : Functions(), RunCount(0), ProgramCount(0) {} - ~GCOVFile(); - bool read(GCOVBuffer &Buffer); - void dump(); + GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0), + ProgramCount(0) {} + bool readGCNO(GCOVBuffer &Buffer); + bool readGCDA(GCOVBuffer &Buffer); + uint32_t getChecksum() const { return Checksum; } + void dump() const; void collectLineCounts(FileInfo &FI); private: - SmallVector<GCOVFunction *, 16> Functions; + bool GCNOInitialized; + GCOV::GCOVVersion Version; + uint32_t Checksum; + SmallVector<std::unique_ptr<GCOVFunction>, 16> Functions; uint32_t RunCount; uint32_t ProgramCount; }; +/// GCOVEdge - Collects edge information. +struct GCOVEdge { + GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D), Count(0) {} + + GCOVBlock &Src; + GCOVBlock &Dst; + uint64_t Count; +}; + /// GCOVFunction - Collects function information. class GCOVFunction { public: - GCOVFunction() : Ident(0), LineNumber(0) {} - ~GCOVFunction(); - bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format); + typedef SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator + BlockIterator; + + GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {} + bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); + bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); + StringRef getName() const { return Name; } StringRef getFilename() const { return Filename; } - void dump(); + size_t getNumBlocks() const { return Blocks.size(); } + uint64_t getEntryCount() const; + uint64_t getExitCount() const; + + BlockIterator block_begin() const { return Blocks.begin(); } + BlockIterator block_end() const { return Blocks.end(); } + + void dump() const; void collectLineCounts(FileInfo &FI); private: + GCOVFile &Parent; uint32_t Ident; + uint32_t Checksum; uint32_t LineNumber; StringRef Name; StringRef Filename; - SmallVector<GCOVBlock *, 16> Blocks; + SmallVector<std::unique_ptr<GCOVBlock>, 16> Blocks; + SmallVector<std::unique_ptr<GCOVEdge>, 16> Edges; }; /// GCOVBlock - Collects block information. class GCOVBlock { + struct EdgeWeight { + EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {} + + GCOVBlock *Dst; + uint64_t Count; + }; + + struct SortDstEdgesFunctor { + bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) { + return E1->Dst.Number < E2->Dst.Number; + } + }; public: - GCOVBlock(GCOVFunction &P, uint32_t N) : - Parent(P), Number(N), Counter(0), Edges(), Lines() {} + typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator; + + GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0), + DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {} ~GCOVBlock(); - void addEdge(uint32_t N) { Edges.push_back(N); } + const GCOVFunction &getParent() const { return Parent; } void addLine(uint32_t N) { Lines.push_back(N); } - void addCount(uint64_t N) { Counter += N; } - size_t getNumEdges() { return Edges.size(); } - void dump(); + uint32_t getLastLine() const { return Lines.back(); } + void addCount(size_t DstEdgeNo, uint64_t N); + uint64_t getCount() const { return Counter; } + + void addSrcEdge(GCOVEdge *Edge) { + assert(&Edge->Dst == this); // up to caller to ensure edge is valid + SrcEdges.push_back(Edge); + } + void addDstEdge(GCOVEdge *Edge) { + assert(&Edge->Src == this); // up to caller to ensure edge is valid + // Check if adding this edge causes list to become unsorted. + if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number) + DstEdgesAreSorted = false; + DstEdges.push_back(Edge); + } + size_t getNumSrcEdges() const { return SrcEdges.size(); } + size_t getNumDstEdges() const { return DstEdges.size(); } + void sortDstEdges(); + + EdgeIterator src_begin() const { return SrcEdges.begin(); } + EdgeIterator src_end() const { return SrcEdges.end(); } + EdgeIterator dst_begin() const { return DstEdges.begin(); } + EdgeIterator dst_end() const { return DstEdges.end(); } + + void dump() const; void collectLineCounts(FileInfo &FI); private: GCOVFunction &Parent; uint32_t Number; uint64_t Counter; - SmallVector<uint32_t, 16> Edges; + bool DstEdgesAreSorted; + SmallVector<GCOVEdge *, 16> SrcEdges; + SmallVector<GCOVEdge *, 16> DstEdges; SmallVector<uint32_t, 16> Lines; }; -typedef DenseMap<uint32_t, uint64_t> LineCounts; class FileInfo { + // It is unlikely--but possible--for multiple functions to be on the same line. + // Therefore this typedef allows LineData.Functions to store multiple functions + // per instance. This is rare, however, so optimize for the common case. + typedef SmallVector<const GCOVFunction *, 1> FunctionVector; + typedef DenseMap<uint32_t, FunctionVector> FunctionLines; + typedef SmallVector<const GCOVBlock *, 4> BlockVector; + typedef DenseMap<uint32_t, BlockVector> BlockLines; + + struct LineData { + LineData() : LastLine(0) {} + BlockLines Blocks; + FunctionLines Functions; + uint32_t LastLine; + }; + + struct GCOVCoverage { + GCOVCoverage(StringRef Name) : + Name(Name), LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0), + BranchesTaken(0) {} + + StringRef Name; + + uint32_t LogicalLines; + uint32_t LinesExec; + + uint32_t Branches; + uint32_t BranchesExec; + uint32_t BranchesTaken; + }; public: - void addLineCount(StringRef Filename, uint32_t Line, uint64_t Count) { - LineInfo[Filename][Line-1] += Count; + FileInfo(const GCOVOptions &Options) : + Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {} + + void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) { + if (Line > LineInfo[Filename].LastLine) + LineInfo[Filename].LastLine = Line; + LineInfo[Filename].Blocks[Line-1].push_back(Block); + } + void addFunctionLine(StringRef Filename, uint32_t Line, + const GCOVFunction *Function) { + if (Line > LineInfo[Filename].LastLine) + LineInfo[Filename].LastLine = Line; + LineInfo[Filename].Functions[Line-1].push_back(Function); } void setRunCount(uint32_t Runs) { RunCount = Runs; } void setProgramCount(uint32_t Programs) { ProgramCount = Programs; } - void print(raw_fd_ostream &OS, StringRef gcnoFile, StringRef gcdaFile); + void print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile); + private: - StringMap<LineCounts> LineInfo; + std::string getCoveragePath(StringRef Filename, StringRef MainFilename); + std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath); + void printFunctionSummary(raw_ostream &OS, + const FunctionVector &Funcs) const; + void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, + uint32_t LineIndex, uint32_t &BlockNo) const; + void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, + GCOVCoverage &Coverage, uint32_t &EdgeNo); + void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, + uint64_t Count) const; + + void printCoverage(const GCOVCoverage &Coverage) const; + void printFuncCoverage() const; + void printFileCoverage() const; + + const GCOVOptions &Options; + StringMap<LineData> LineInfo; uint32_t RunCount; uint32_t ProgramCount; + + typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> + FileCoverageList; + typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap; + + FileCoverageList FileCoverages; + FuncCoverageMap FuncCoverages; }; } diff --git a/include/llvm/Analysis/Dominators.h b/include/llvm/Support/GenericDomTree.h index 3aa0beb6bb1e..876ab6ec71a5 100644 --- a/include/llvm/Analysis/Dominators.h +++ b/include/llvm/Support/GenericDomTree.h @@ -1,4 +1,4 @@ -//===- llvm/Analysis/Dominators.h - Dominator Info Calculation --*- C++ -*-===// +//===- GenericDomTree.h - Generic dominator trees for graphs ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,23 +6,23 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the DominatorTree class, which provides fast and efficient -// dominance queries. -// +/// \file +/// +/// This file defines a set of templates that efficiently compute a dominator +/// tree over a generic graph. This is used typically in LLVM for fast +/// dominance queries on the CFG, but is fully generic w.r.t. the underlying +/// graph types. +/// //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_DOMINATORS_H -#define LLVM_ANALYSIS_DOMINATORS_H +#ifndef LLVM_SUPPORT_GENERIC_DOM_TREE_H +#define LLVM_SUPPORT_GENERIC_DOM_TREE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/IR/Function.h" -#include "llvm/Pass.h" -#include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -55,17 +55,16 @@ public: //===----------------------------------------------------------------------===// -// DomTreeNode - Dominator Tree Node +// DomTreeNodeBase - Dominator Tree Node template<class NodeT> class DominatorTreeBase; struct PostDominatorTree; -class MachineBasicBlock; template <class NodeT> class DomTreeNodeBase { NodeT *TheBB; DomTreeNodeBase<NodeT> *IDom; std::vector<DomTreeNodeBase<NodeT> *> Children; - int DFSNumIn, DFSNumOut; + mutable int DFSNumIn, DFSNumOut; template<class N> friend class DominatorTreeBase; friend struct PostDominatorTree; @@ -148,14 +147,11 @@ private: } }; -EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<BasicBlock>); -EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase<MachineBasicBlock>); - template<class NodeT> inline raw_ostream &operator<<(raw_ostream &o, const DomTreeNodeBase<NodeT> *Node) { if (Node->getBlock()) - WriteAsOperand(o, Node->getBlock(), false); + Node->getBlock()->printAsOperand(o, false); else o << " <<exit node>>"; @@ -173,8 +169,6 @@ inline void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o, PrintDomTree<NodeT>(*I, o, Lev+1); } -typedef DomTreeNodeBase<BasicBlock> DomTreeNode; - //===----------------------------------------------------------------------===// /// DominatorTree - Calculate the immediate dominator tree for a function. /// @@ -192,9 +186,9 @@ class DominatorTreeBase : public DominatorBase<NodeT> { assert(isReachableFromEntry(A)); const DomTreeNodeBase<NodeT> *IDom; - while ((IDom = B->getIDom()) != 0 && IDom != A && IDom != B) + while ((IDom = B->getIDom()) != nullptr && IDom != A && IDom != B) B = IDom; // Walk up the tree - return IDom != 0; + return IDom != nullptr; } protected: @@ -202,8 +196,8 @@ protected: DomTreeNodeMapType DomTreeNodes; DomTreeNodeBase<NodeT> *RootNode; - bool DFSInfoValid; - unsigned int SlowQueries; + mutable bool DFSInfoValid; + mutable unsigned int SlowQueries; // Information record used during immediate dominators computation. struct InfoRec { unsigned DFSNum; @@ -211,12 +205,12 @@ protected: unsigned Semi; NodeT *Label; - InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(0) {} + InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(nullptr) {} }; DenseMap<NodeT*, NodeT*> IDoms; - // Vertex - Map the DFS number to the BasicBlock* + // Vertex - Map the DFS number to the NodeT* std::vector<NodeT*> Vertex; // Info - Collection of information used during the computation of idoms. @@ -230,7 +224,7 @@ protected: IDoms.clear(); this->Roots.clear(); Vertex.clear(); - RootNode = 0; + RootNode = nullptr; } // NewBB is split and now it has one successor. Update dominator tree to @@ -266,7 +260,7 @@ protected: // Find NewBB's immediate dominator and create new dominator tree node for // NewBB. - NodeT *NewBBIDom = 0; + NodeT *NewBBIDom = nullptr; unsigned i = 0; for (i = 0; i < PredBlocks.size(); ++i) if (DT.isReachableFromEntry(PredBlocks[i])) { @@ -303,7 +297,7 @@ public: /// compare - Return false if the other dominator tree base matches this /// dominator tree base. Otherwise return true. - bool compare(DominatorTreeBase &Other) const { + bool compare(const DominatorTreeBase &Other) const { const DomTreeNodeMapType &OtherDomTreeNodes = Other.DomTreeNodes; if (DomTreeNodes.size() != OtherDomTreeNodes.size()) @@ -336,6 +330,10 @@ public: return DomTreeNodes.lookup(BB); } + inline DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { + return getNode(BB); + } + /// getRootNode - This returns the entry node for the CFG of the function. If /// this tree represents the post-dominance relations for a function, however, /// this root may be a node with the block == NULL. This is the case when @@ -346,12 +344,14 @@ public: DomTreeNodeBase<NodeT> *getRootNode() { return RootNode; } const DomTreeNodeBase<NodeT> *getRootNode() const { return RootNode; } - /// Get all nodes dominated by R, including R itself. Return true on success. + /// Get all nodes dominated by R, including R itself. void getDescendants(NodeT *R, SmallVectorImpl<NodeT *> &Result) const { + Result.clear(); const DomTreeNodeBase<NodeT> *RN = getNode(R); + if (!RN) + return; // If R is unreachable, it will not be present in the DOM tree. SmallVector<const DomTreeNodeBase<NodeT> *, 8> WL; WL.push_back(RN); - Result.clear(); while (!WL.empty()) { const DomTreeNodeBase<NodeT> *N = WL.pop_back_val(); @@ -364,15 +364,15 @@ public: /// Note that this is not a constant time operation! /// bool properlyDominates(const DomTreeNodeBase<NodeT> *A, - const DomTreeNodeBase<NodeT> *B) { - if (A == 0 || B == 0) + const DomTreeNodeBase<NodeT> *B) const { + if (!A || !B) return false; if (A == B) return false; return dominates(A, B); } - bool properlyDominates(const NodeT *A, const NodeT *B); + bool properlyDominates(const NodeT *A, const NodeT *B) const; /// isReachableFromEntry - Return true if A is dominated by the entry /// block of the function containing it. @@ -390,7 +390,7 @@ public: /// constant time operation! /// inline bool dominates(const DomTreeNodeBase<NodeT> *A, - const DomTreeNodeBase<NodeT> *B) { + const DomTreeNodeBase<NodeT> *B) const { // A node trivially dominates itself. if (B == A) return true; @@ -425,7 +425,7 @@ public: return dominatedBySlowTreeWalk(A, B); } - bool dominates(const NodeT *A, const NodeT *B); + bool dominates(const NodeT *A, const NodeT *B) const; NodeT *getRoot() const { assert(this->Roots.size() == 1 && "Should always have entry node!"); @@ -457,6 +457,21 @@ public: DomTreeNodeBase<NodeT> *NodeA = getNode(A); DomTreeNodeBase<NodeT> *NodeB = getNode(B); + // If we have DFS info, then we can avoid all allocations by just querying + // it from each IDom. Note that because we call 'dominates' twice above, we + // expect to call through this code at most 16 times in a row without + // building valid DFS information. This is important as below is a *very* + // slow tree walk. + if (DFSInfoValid) { + DomTreeNodeBase<NodeT> *IDomA = NodeA->getIDom(); + while (IDomA) { + if (NodeB->DominatedBy(IDomA)) + return IDomA->getBlock(); + IDomA = IDomA->getIDom(); + } + return nullptr; + } + // Collect NodeA dominators set. SmallPtrSet<DomTreeNodeBase<NodeT>*, 16> NodeADoms; NodeADoms.insert(NodeA); @@ -475,7 +490,7 @@ public: IDomB = IDomB->getIDom(); } - return NULL; + return nullptr; } const NodeT *findNearestCommonDominator(const NodeT *A, const NodeT *B) { @@ -493,7 +508,7 @@ public: /// creates a new node as a child of DomBB dominator node,linking it into /// the children list of the immediate dominator. DomTreeNodeBase<NodeT> *addNewBlock(NodeT *BB, NodeT *DomBB) { - assert(getNode(BB) == 0 && "Block already in dominator tree!"); + assert(getNode(BB) == nullptr && "Block already in dominator tree!"); DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB); assert(IDomNode && "Not immediate dominator specified for block!"); DFSInfoValid = false; @@ -590,13 +605,13 @@ protected: /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking /// dominator tree in dfs order. - void updateDFSNumbers() { + void updateDFSNumbers() const { unsigned DFSNum = 0; - SmallVector<std::pair<DomTreeNodeBase<NodeT>*, - typename DomTreeNodeBase<NodeT>::iterator>, 32> WorkStack; + SmallVector<std::pair<const DomTreeNodeBase<NodeT>*, + typename DomTreeNodeBase<NodeT>::const_iterator>, 32> WorkStack; - DomTreeNodeBase<NodeT> *ThisRoot = getRootNode(); + const DomTreeNodeBase<NodeT> *ThisRoot = getRootNode(); if (!ThisRoot) return; @@ -609,8 +624,8 @@ protected: ThisRoot->DFSNumIn = DFSNum++; while (!WorkStack.empty()) { - DomTreeNodeBase<NodeT> *Node = WorkStack.back().first; - typename DomTreeNodeBase<NodeT>::iterator ChildIt = + const DomTreeNodeBase<NodeT> *Node = WorkStack.back().first; + typename DomTreeNodeBase<NodeT>::const_iterator ChildIt = WorkStack.back().second; // If we visited all of the children of this node, "recurse" back up the @@ -620,7 +635,7 @@ protected: WorkStack.pop_back(); } else { // Otherwise, recursively visit this child. - DomTreeNodeBase<NodeT> *Child = *ChildIt; + const DomTreeNodeBase<NodeT> *Child = *ChildIt; ++WorkStack.back().second; WorkStack.push_back(std::make_pair(Child, Child->begin())); @@ -640,10 +655,10 @@ protected: // immediate dominator. NodeT *IDom = getIDom(BB); - assert(IDom || this->DomTreeNodes[NULL]); + assert(IDom || this->DomTreeNodes[nullptr]); DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom); - // Add a new tree node for this BasicBlock, and link it as a child of + // Add a new tree node for this NodeT, and link it as a child of // IDomNode DomTreeNodeBase<NodeT> *C = new DomTreeNodeBase<NodeT>(BB, IDomNode); return this->DomTreeNodes[BB] = IDomNode->addChild(C); @@ -663,14 +678,14 @@ public: void recalculate(FT& F) { typedef GraphTraits<FT*> TraitsTy; reset(); - this->Vertex.push_back(0); + this->Vertex.push_back(nullptr); if (!this->IsPostDominators) { // Initialize root NodeT *entry = TraitsTy::getEntryNode(&F); this->Roots.push_back(entry); - this->IDoms[entry] = 0; - this->DomTreeNodes[entry] = 0; + this->IDoms[entry] = nullptr; + this->DomTreeNodes[entry] = nullptr; Calculate<FT, NodeT*>(*this, F); } else { @@ -681,8 +696,8 @@ public: addRoot(I); // Prepopulate maps so that we don't get iterator invalidation issues later. - this->IDoms[I] = 0; - this->DomTreeNodes[I] = 0; + this->IDoms[I] = nullptr; + this->DomTreeNodes[I] = nullptr; } Calculate<FT, Inverse<NodeT*> >(*this, F); @@ -693,7 +708,7 @@ public: // These two functions are declared out of line as a workaround for building // with old (< r147295) versions of clang because of pr11642. template<class NodeT> -bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) { +bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) const { if (A == B) return true; @@ -705,7 +720,7 @@ bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) { } template<class NodeT> bool -DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) { +DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) const { if (A == B) return false; @@ -716,225 +731,6 @@ DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) { getNode(const_cast<NodeT *>(B))); } -EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>); - -class BasicBlockEdge { - const BasicBlock *Start; - const BasicBlock *End; -public: - BasicBlockEdge(const BasicBlock *Start_, const BasicBlock *End_) : - Start(Start_), End(End_) { } - const BasicBlock *getStart() const { - return Start; - } - const BasicBlock *getEnd() const { - return End; - } - bool isSingleEdge() const; -}; - -//===------------------------------------- -/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to -/// compute a normal dominator tree. -/// -class DominatorTree : public FunctionPass { -public: - static char ID; // Pass ID, replacement for typeid - DominatorTreeBase<BasicBlock>* DT; - - DominatorTree() : FunctionPass(ID) { - initializeDominatorTreePass(*PassRegistry::getPassRegistry()); - DT = new DominatorTreeBase<BasicBlock>(false); - } - - ~DominatorTree() { - delete DT; - } - - DominatorTreeBase<BasicBlock>& getBase() { return *DT; } - - /// getRoots - Return the root blocks of the current CFG. This may include - /// multiple blocks if we are computing post dominators. For forward - /// dominators, this will always be a single block (the entry node). - /// - inline const std::vector<BasicBlock*> &getRoots() const { - return DT->getRoots(); - } - - inline BasicBlock *getRoot() const { - return DT->getRoot(); - } - - inline DomTreeNode *getRootNode() const { - return DT->getRootNode(); - } - - /// Get all nodes dominated by R, including R itself. Return true on success. - void getDescendants(BasicBlock *R, - SmallVectorImpl<BasicBlock *> &Result) const { - DT->getDescendants(R, Result); - } - - /// compare - Return false if the other dominator tree matches this - /// dominator tree. Otherwise return true. - inline bool compare(DominatorTree &Other) const { - DomTreeNode *R = getRootNode(); - DomTreeNode *OtherR = Other.getRootNode(); - - if (!R || !OtherR || R->getBlock() != OtherR->getBlock()) - return true; - - if (DT->compare(Other.getBase())) - return true; - - return false; - } - - virtual bool runOnFunction(Function &F); - - virtual void verifyAnalysis() const; - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - } - - inline bool dominates(const DomTreeNode* A, const DomTreeNode* B) const { - return DT->dominates(A, B); - } - - inline bool dominates(const BasicBlock* A, const BasicBlock* B) const { - return DT->dominates(A, B); - } - - // dominates - Return true if Def dominates a use in User. This performs - // the special checks necessary if Def and User are in the same basic block. - // Note that Def doesn't dominate a use in Def itself! - bool dominates(const Instruction *Def, const Use &U) const; - bool dominates(const Instruction *Def, const Instruction *User) const; - bool dominates(const Instruction *Def, const BasicBlock *BB) const; - bool dominates(const BasicBlockEdge &BBE, const Use &U) const; - bool dominates(const BasicBlockEdge &BBE, const BasicBlock *BB) const; - - bool properlyDominates(const DomTreeNode *A, const DomTreeNode *B) const { - return DT->properlyDominates(A, B); - } - - bool properlyDominates(const BasicBlock *A, const BasicBlock *B) const { - return DT->properlyDominates(A, B); - } - - /// findNearestCommonDominator - Find nearest common dominator basic block - /// for basic block A and B. If there is no such block then return NULL. - inline BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B) { - return DT->findNearestCommonDominator(A, B); - } - - inline const BasicBlock *findNearestCommonDominator(const BasicBlock *A, - const BasicBlock *B) { - return DT->findNearestCommonDominator(A, B); - } - - inline DomTreeNode *operator[](BasicBlock *BB) const { - return DT->getNode(BB); - } - - /// getNode - return the (Post)DominatorTree node for the specified basic - /// block. This is the same as using operator[] on this class. - /// - inline DomTreeNode *getNode(BasicBlock *BB) const { - return DT->getNode(BB); - } - - /// addNewBlock - Add a new node to the dominator tree information. This - /// creates a new node as a child of DomBB dominator node,linking it into - /// the children list of the immediate dominator. - inline DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) { - return DT->addNewBlock(BB, DomBB); - } - - /// changeImmediateDominator - This method is used to update the dominator - /// tree information when a node's immediate dominator changes. - /// - inline void changeImmediateDominator(BasicBlock *N, BasicBlock* NewIDom) { - DT->changeImmediateDominator(N, NewIDom); - } - - inline void changeImmediateDominator(DomTreeNode *N, DomTreeNode* NewIDom) { - DT->changeImmediateDominator(N, NewIDom); - } - - /// eraseNode - Removes a node from the dominator tree. Block must not - /// dominate any other blocks. Removes node from its immediate dominator's - /// children list. Deletes dominator node associated with basic block BB. - inline void eraseNode(BasicBlock *BB) { - DT->eraseNode(BB); - } - - /// splitBlock - BB is split and now it has one successor. Update dominator - /// tree to reflect this change. - inline void splitBlock(BasicBlock* NewBB) { - DT->splitBlock(NewBB); - } - - bool isReachableFromEntry(const BasicBlock* A) const { - return DT->isReachableFromEntry(A); - } - - bool isReachableFromEntry(const Use &U) const; - - - virtual void releaseMemory() { - DT->releaseMemory(); - } - - virtual void print(raw_ostream &OS, const Module* M= 0) const; -}; - -//===------------------------------------- -/// DominatorTree GraphTraits specialization so the DominatorTree can be -/// iterable by generic graph iterators. -/// -template <> struct GraphTraits<DomTreeNode*> { - typedef DomTreeNode NodeType; - typedef NodeType::iterator ChildIteratorType; - - static NodeType *getEntryNode(NodeType *N) { - return N; - } - static inline ChildIteratorType child_begin(NodeType *N) { - return N->begin(); - } - static inline ChildIteratorType child_end(NodeType *N) { - return N->end(); - } - - typedef df_iterator<DomTreeNode*> nodes_iterator; - - static nodes_iterator nodes_begin(DomTreeNode *N) { - return df_begin(getEntryNode(N)); - } - - static nodes_iterator nodes_end(DomTreeNode *N) { - return df_end(getEntryNode(N)); - } -}; - -template <> struct GraphTraits<DominatorTree*> - : public GraphTraits<DomTreeNode*> { - static NodeType *getEntryNode(DominatorTree *DT) { - return DT->getRootNode(); - } - - static nodes_iterator nodes_begin(DominatorTree *N) { - return df_begin(getEntryNode(N)); - } - - static nodes_iterator nodes_end(DominatorTree *N) { - return df_end(getEntryNode(N)); - } -}; - - -} // End llvm namespace +} #endif diff --git a/include/llvm/Analysis/DominatorInternals.h b/include/llvm/Support/GenericDomTreeConstruction.h index c0f95cbd9b9b..bcba5e0aeb43 100644 --- a/include/llvm/Analysis/DominatorInternals.h +++ b/include/llvm/Support/GenericDomTreeConstruction.h @@ -1,4 +1,4 @@ -//=== llvm/Analysis/DominatorInternals.h - Dominator Calculation -*- C++ -*-==// +//===- GenericDomTreeConstruction.h - Dominator Calculation ------*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -6,27 +6,27 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +/// \file +/// +/// Generic dominator tree construction - This file provides routines to +/// construct immediate dominator information for a flow-graph based on the +/// algorithm described in this document: +/// +/// A Fast Algorithm for Finding Dominators in a Flowgraph +/// T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141. +/// +/// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns +/// out that the theoretically slower O(n*log(n)) implementation is actually +/// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs. +/// +//===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_DOMINATOR_INTERNALS_H -#define LLVM_ANALYSIS_DOMINATOR_INTERNALS_H -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Analysis/Dominators.h" +#ifndef LLVM_SUPPORT_GENERIC_DOM_TREE_CONSTRUCTION_H +#define LLVM_SUPPORT_GENERIC_DOM_TREE_CONSTRUCTION_H -//===----------------------------------------------------------------------===// -// -// DominatorTree construction - This pass constructs immediate dominator -// information for a flow-graph based on the algorithm described in this -// document: -// -// A Fast Algorithm for Finding Dominators in a Flowgraph -// T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141. -// -// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns -// out that the theoretically slower O(n*log(n)) implementation is actually -// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs. -// -//===----------------------------------------------------------------------===// +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/GenericDomTree.h" namespace llvm { @@ -156,11 +156,11 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, bool MultipleRoots = (DT.Roots.size() > 1); if (MultipleRoots) { typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &BBInfo = - DT.Info[NULL]; + DT.Info[nullptr]; BBInfo.DFSNum = BBInfo.Semi = ++N; - BBInfo.Label = NULL; + BBInfo.Label = nullptr; - DT.Vertex.push_back(NULL); // Vertex[n] = V; + DT.Vertex.push_back(nullptr); // Vertex[n] = V; } // Step #1: Number blocks in depth-first order and initialize variables used @@ -249,10 +249,10 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, // one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0) // which postdominates all real exits if there are multiple exit blocks, or // an infinite loop. - typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : 0; + typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : nullptr; DT.DomTreeNodes[Root] = DT.RootNode = - new DomTreeNodeBase<typename GraphT::NodeType>(Root, 0); + new DomTreeNodeBase<typename GraphT::NodeType>(Root, nullptr); // Loop over all of the reachable blocks in the function... for (unsigned i = 2; i <= N; ++i) { @@ -263,7 +263,7 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, typename GraphT::NodeType* ImmDom = DT.getIDom(W); - assert(ImmDom || DT.DomTreeNodes[NULL]); + assert(ImmDom || DT.DomTreeNodes[nullptr]); // Get or calculate the node for the immediate dominator DomTreeNodeBase<typename GraphT::NodeType> *IDomNode = diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index 62547ddf0cef..2f02aa7a1c19 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -50,7 +50,7 @@ namespace GraphProgram { }; } -void DisplayGraph(StringRef Filename, bool wait = true, +bool DisplayGraph(StringRef Filename, bool wait = true, GraphProgram::Name program = GraphProgram::DOT); template<typename GraphType> @@ -259,8 +259,8 @@ public: /// emitSimpleNode - Outputs a simple (non-record) node void emitSimpleNode(const void *ID, const std::string &Attr, - const std::string &Label, unsigned NumEdgeSources = 0, - const std::vector<std::string> *EdgeSourceLabels = 0) { + const std::string &Label, unsigned NumEdgeSources = 0, + const std::vector<std::string> *EdgeSourceLabels = nullptr) { O << "\tNode" << ID << "[ "; if (!Attr.empty()) O << Attr << ","; @@ -325,7 +325,10 @@ template <typename GraphType> std::string WriteGraph(const GraphType &G, const Twine &Name, bool ShortNames = false, const Twine &Title = "") { int FD; - std::string Filename = createGraphFilename(Name, FD); + // Windows can't always handle long paths, so limit the length of the name. + std::string N = Name.str(); + N = N.substr(0, std::min<std::size_t>(N.size(), 140)); + std::string Filename = createGraphFilename(N, FD); raw_fd_ostream O(FD, /*shouldClose=*/ true); if (FD == -1) { diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h index 28c4cc790fe5..8f4bf3c1ba56 100644 --- a/include/llvm/Support/Host.h +++ b/include/llvm/Support/Host.h @@ -55,7 +55,7 @@ namespace sys { /// target which matches the host. /// /// \return - The host CPU name, or empty if the CPU could not be determined. - std::string getHostCPUName(); + StringRef getHostCPUName(); /// getHostCPUFeatures - Get the LLVM names for the host CPU features. /// The particular format of the names are target dependent, and suitable for diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index 3d7379250af4..ea76c9b58922 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -77,7 +77,7 @@ inline unsigned encodeULEB128(uint64_t Value, uint8_t *p, /// Utility function to decode a ULEB128 value. -inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = 0) { +inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) { const uint8_t *orig_p = p; uint64_t Value = 0; unsigned Shift = 0; @@ -90,6 +90,12 @@ inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = 0) { return Value; } +/// Utility function to get the size of the ULEB128-encoded value. +extern unsigned getULEB128Size(uint64_t Value); + +/// Utility function to get the size of the SLEB128-encoded value. +extern unsigned getSLEB128Size(int64_t Value); + } // namespace llvm #endif // LLVM_SYSTEM_LEB128_H diff --git a/include/llvm/Support/LineIterator.h b/include/llvm/Support/LineIterator.h new file mode 100644 index 000000000000..2a5826200143 --- /dev/null +++ b/include/llvm/Support/LineIterator.h @@ -0,0 +1,85 @@ +//===- LineIterator.h - Iterator to read a text buffer's lines --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_LINEITERATOR_H__ +#define LLVM_SUPPORT_LINEITERATOR_H__ + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include <iterator> + +namespace llvm { + +class MemoryBuffer; + +/// \brief A forward iterator which reads non-blank text lines from a buffer. +/// +/// This class provides a forward iterator interface for reading one line at +/// a time from a buffer. When default constructed the iterator will be the +/// "end" iterator. +/// +/// The iterator also is aware of what line number it is currently processing +/// and can strip comment lines given the comment-starting character. +/// +/// Note that this iterator requires the buffer to be nul terminated. +class line_iterator + : public std::iterator<std::forward_iterator_tag, StringRef> { + const MemoryBuffer *Buffer; + char CommentMarker; + + unsigned LineNumber; + StringRef CurrentLine; + +public: + /// \brief Default construct an "end" iterator. + line_iterator() : Buffer(nullptr) {} + + /// \brief Construct a new iterator around some memory buffer. + explicit line_iterator(const MemoryBuffer &Buffer, char CommentMarker = '\0'); + + /// \brief Return true if we've reached EOF or are an "end" iterator. + bool is_at_eof() const { return !Buffer; } + + /// \brief Return true if we're an "end" iterator or have reached EOF. + bool is_at_end() const { return is_at_eof(); } + + /// \brief Return the current line number. May return any number at EOF. + int64_t line_number() const { return LineNumber; } + + /// \brief Advance to the next (non-empty, non-comment) line. + line_iterator &operator++() { + advance(); + return *this; + } + line_iterator operator++(int) { + line_iterator tmp(*this); + advance(); + return tmp; + } + + /// \brief Get the current line as a \c StringRef. + StringRef operator*() const { return CurrentLine; } + const StringRef *operator->() const { return &CurrentLine; } + + friend bool operator==(const line_iterator &LHS, const line_iterator &RHS) { + return LHS.Buffer == RHS.Buffer && + LHS.CurrentLine.begin() == RHS.CurrentLine.begin(); + } + + friend bool operator!=(const line_iterator &LHS, const line_iterator &RHS) { + return !(LHS == RHS); + } + +private: + /// \brief Advance the iterator to the next line. + void advance(); +}; +} + +#endif // LLVM_SUPPORT_LINEITERATOR_H__ diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index 9df8675ef0af..61c65dabae3c 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -12,11 +12,10 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/system_error.h" +#include <system_error> #include <utility> // for std::pair namespace llvm { - /// \brief Class that manages the creation of a lock file to aid /// implicit coordination between different processes. /// @@ -40,13 +39,23 @@ public: LFS_Error }; + /// \brief Describes the result of waiting for the owner to release the lock. + enum WaitForUnlockResult { + /// \brief The lock was released successfully. + Res_Success, + /// \brief Owner died while holding the lock. + Res_OwnerDied, + /// \brief Reached timeout while waiting for the owner to release the lock. + Res_Timeout + }; + private: SmallString<128> FileName; SmallString<128> LockFileName; SmallString<128> UniqueLockFileName; Optional<std::pair<std::string, int> > Owner; - Optional<error_code> Error; + Optional<std::error_code> Error; LockFileManager(const LockFileManager &) LLVM_DELETED_FUNCTION; LockFileManager &operator=(const LockFileManager &) LLVM_DELETED_FUNCTION; @@ -67,7 +76,7 @@ public: operator LockFileState() const { return getState(); } /// \brief For a shared lock, wait until the owner releases the lock. - void waitForUnlock(); + WaitForUnlockResult waitForUnlock(); }; } // end namespace llvm diff --git a/include/llvm/Support/MD5.h b/include/llvm/Support/MD5.h index b2b8c2d55b87..4eb8507ea34f 100644 --- a/include/llvm/Support/MD5.h +++ b/include/llvm/Support/MD5.h @@ -28,13 +28,12 @@ #ifndef LLVM_SYSTEM_MD5_H #define LLVM_SYSTEM_MD5_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/DataTypes.h" namespace llvm { -template <typename T> class ArrayRef; - class MD5 { // Any 32-bit or wider unsigned integer data type will do. typedef uint32_t MD5_u32plus; diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index 897a6112f501..90df1f4f140f 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -21,7 +21,7 @@ namespace llvm { namespace MachO { // Enums from <mach-o/loader.h> - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Constants for the "magic" field in llvm::MachO::mach_header and // llvm::MachO::mach_header_64 MH_MAGIC = 0xFEEDFACEu, @@ -76,12 +76,12 @@ namespace llvm { MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u }; - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Flags for the "cmd" field in llvm::MachO::load_command LC_REQ_DYLD = 0x80000000u }; - enum LoadCommandType LLVM_ENUM_INT_TYPE(uint32_t) { + enum LoadCommandType : uint32_t { // Constants for the "cmd" field in llvm::MachO::load_command LC_SEGMENT = 0x00000001u, LC_SYMTAB = 0x00000002u, @@ -128,10 +128,11 @@ namespace llvm { LC_SOURCE_VERSION = 0x0000002Au, LC_DYLIB_CODE_SIGN_DRS = 0x0000002Bu, // 0x0000002Cu, - LC_LINKER_OPTIONS = 0x0000002Du + LC_LINKER_OPTIONS = 0x0000002Du, + LC_LINKER_OPTIMIZATION_HINT = 0x0000002Eu }; - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Constant bits for the "flags" field in llvm::MachO::segment_command SG_HIGHVM = 0x1u, SG_FVMLIB = 0x2u, @@ -147,48 +148,100 @@ namespace llvm { SECTION_ATTRIBUTES_SYS = 0x00ffff00u // SECTION_ATTRIBUTES_SYS }; - enum SectionType { + /// These are the section type and attributes fields. A MachO section can + /// have only one Type, but can have any of the attributes specified. + enum SectionType : uint32_t { // Constant masks for the "flags[7:0]" field in llvm::MachO::section and // llvm::MachO::section_64 (mask "flags" with SECTION_TYPE) + + /// S_REGULAR - Regular section. S_REGULAR = 0x00u, + /// S_ZEROFILL - Zero fill on demand section. S_ZEROFILL = 0x01u, + /// S_CSTRING_LITERALS - Section with literal C strings. S_CSTRING_LITERALS = 0x02u, + /// S_4BYTE_LITERALS - Section with 4 byte literals. S_4BYTE_LITERALS = 0x03u, + /// S_8BYTE_LITERALS - Section with 8 byte literals. S_8BYTE_LITERALS = 0x04u, + /// S_LITERAL_POINTERS - Section with pointers to literals. S_LITERAL_POINTERS = 0x05u, + /// S_NON_LAZY_SYMBOL_POINTERS - Section with non-lazy symbol pointers. S_NON_LAZY_SYMBOL_POINTERS = 0x06u, + /// S_LAZY_SYMBOL_POINTERS - Section with lazy symbol pointers. S_LAZY_SYMBOL_POINTERS = 0x07u, + /// S_SYMBOL_STUBS - Section with symbol stubs, byte size of stub in + /// the Reserved2 field. S_SYMBOL_STUBS = 0x08u, + /// S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for + /// initialization. S_MOD_INIT_FUNC_POINTERS = 0x09u, + /// S_MOD_TERM_FUNC_POINTERS - Section with only function pointers for + /// termination. S_MOD_TERM_FUNC_POINTERS = 0x0au, + /// S_COALESCED - Section contains symbols that are to be coalesced. S_COALESCED = 0x0bu, + /// S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4 + /// gigabytes). S_GB_ZEROFILL = 0x0cu, + /// S_INTERPOSING - Section with only pairs of function pointers for + /// interposing. S_INTERPOSING = 0x0du, + /// S_16BYTE_LITERALS - Section with only 16 byte literals. S_16BYTE_LITERALS = 0x0eu, + /// S_DTRACE_DOF - Section contains DTrace Object Format. S_DTRACE_DOF = 0x0fu, + /// S_LAZY_DYLIB_SYMBOL_POINTERS - Section with lazy symbol pointers to + /// lazy loaded dylibs. S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10u, + /// S_THREAD_LOCAL_REGULAR - Thread local data section. S_THREAD_LOCAL_REGULAR = 0x11u, + /// S_THREAD_LOCAL_ZEROFILL - Thread local zerofill section. S_THREAD_LOCAL_ZEROFILL = 0x12u, + /// S_THREAD_LOCAL_VARIABLES - Section with thread local variable + /// structure data. S_THREAD_LOCAL_VARIABLES = 0x13u, + /// S_THREAD_LOCAL_VARIABLE_POINTERS - Section with pointers to thread + /// local structures. S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14u, - S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15u + /// S_THREAD_LOCAL_INIT_FUNCTION_POINTERS - Section with thread local + /// variable initialization pointers to functions. + S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15u, + + LAST_KNOWN_SECTION_TYPE = S_THREAD_LOCAL_INIT_FUNCTION_POINTERS }; - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Constant masks for the "flags[31:24]" field in llvm::MachO::section and // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_USR) + + /// S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine + /// instructions. S_ATTR_PURE_INSTRUCTIONS = 0x80000000u, + /// S_ATTR_NO_TOC - Section contains coalesced symbols that are not to be + /// in a ranlib table of contents. S_ATTR_NO_TOC = 0x40000000u, + /// S_ATTR_STRIP_STATIC_SYMS - Ok to strip static symbols in this section + /// in files with the MY_DYLDLINK flag. S_ATTR_STRIP_STATIC_SYMS = 0x20000000u, + /// S_ATTR_NO_DEAD_STRIP - No dead stripping. S_ATTR_NO_DEAD_STRIP = 0x10000000u, + /// S_ATTR_LIVE_SUPPORT - Blocks are live if they reference live blocks. S_ATTR_LIVE_SUPPORT = 0x08000000u, + /// S_ATTR_SELF_MODIFYING_CODE - Used with i386 code stubs written on by + /// dyld. S_ATTR_SELF_MODIFYING_CODE = 0x04000000u, + /// S_ATTR_DEBUG - A debug section. S_ATTR_DEBUG = 0x02000000u, // Constant masks for the "flags[23:8]" field in llvm::MachO::section and // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_SYS) + + /// S_ATTR_SOME_INSTRUCTIONS - Section contains some machine instructions. S_ATTR_SOME_INSTRUCTIONS = 0x00000400u, + /// S_ATTR_EXT_RELOC - Section has external relocation entries. S_ATTR_EXT_RELOC = 0x00000200u, + /// S_ATTR_LOC_RELOC - Section has local relocation entries. S_ATTR_LOC_RELOC = 0x00000100u, // Constant masks for the value of an indirect symbol in an indirect @@ -307,22 +360,41 @@ namespace llvm { enum { // Constant masks for the "n_desc" field in llvm::MachO::nlist and // llvm::MachO::nlist_64 + // The low 3 bits are the for the REFERENCE_TYPE. + REFERENCE_TYPE = 0x7, + REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0, + REFERENCE_FLAG_UNDEFINED_LAZY = 1, + REFERENCE_FLAG_DEFINED = 2, + REFERENCE_FLAG_PRIVATE_DEFINED = 3, + REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4, + REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5, + // Flag bits (some overlap with the library ordinal bits). N_ARM_THUMB_DEF = 0x0008u, + REFERENCED_DYNAMICALLY = 0x0010u, N_NO_DEAD_STRIP = 0x0020u, N_WEAK_REF = 0x0040u, N_WEAK_DEF = 0x0080u, - N_SYMBOL_RESOLVER = 0x0100u + N_SYMBOL_RESOLVER = 0x0100u, + N_ALT_ENTRY = 0x0200u, + // For undefined symbols coming from libraries, see GET_LIBRARY_ORDINAL() + // as these are in the top 8 bits. + SELF_LIBRARY_ORDINAL = 0x0, + MAX_LIBRARY_ORDINAL = 0xfd, + DYNAMIC_LOOKUP_ORDINAL = 0xfe, + EXECUTABLE_ORDINAL = 0xff }; enum StabType { // Constant values for the "n_type" field in llvm::MachO::nlist and - // llvm::MachO::nlist_64 when "(n_type & NlistMaskStab) != 0" + // llvm::MachO::nlist_64 when "(n_type & N_STAB) != 0" N_GSYM = 0x20u, N_FNAME = 0x22u, N_FUN = 0x24u, N_STSYM = 0x26u, N_LCSYM = 0x28u, N_BNSYM = 0x2Eu, + N_PC = 0x30u, + N_AST = 0x32u, N_OPT = 0x3Cu, N_RSYM = 0x40u, N_SLINE = 0x44u, @@ -348,7 +420,7 @@ namespace llvm { N_LENG = 0xFEu }; - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Constant values for the r_symbolnum field in an // llvm::MachO::relocation_info structure when r_extern is 0. R_ABS = 0, @@ -403,6 +475,34 @@ namespace llvm { ARM_RELOC_HALF = 8, ARM_RELOC_HALF_SECTDIFF = 9, + // Constant values for the r_type field in an ARM64 architecture + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure. + + // For pointers. + ARM64_RELOC_UNSIGNED = 0, + // Must be followed by an ARM64_RELOC_UNSIGNED + ARM64_RELOC_SUBTRACTOR = 1, + // A B/BL instruction with 26-bit displacement. + ARM64_RELOC_BRANCH26 = 2, + // PC-rel distance to page of target. + ARM64_RELOC_PAGE21 = 3, + // Offset within page, scaled by r_length. + ARM64_RELOC_PAGEOFF12 = 4, + // PC-rel distance to page of GOT slot. + ARM64_RELOC_GOT_LOAD_PAGE21 = 5, + // Offset within page of GOT slot, scaled by r_length. + ARM64_RELOC_GOT_LOAD_PAGEOFF12 = 6, + // For pointers to GOT slots. + ARM64_RELOC_POINTER_TO_GOT = 7, + // PC-rel distance to page of TLVP slot. + ARM64_RELOC_TLVP_LOAD_PAGE21 = 8, + // Offset within page of TLVP slot, scaled by r_length. + ARM64_RELOC_TLVP_LOAD_PAGEOFF12 = 9, + // Must be followed by ARM64_RELOC_PAGE21 or ARM64_RELOC_PAGEOFF12. + ARM64_RELOC_ADDEND = 10, + + // Constant values for the r_type field in an x86_64 architecture // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info // structure @@ -739,9 +839,10 @@ namespace llvm { }; struct version_min_command { - uint32_t cmd; - uint32_t cmdsize; - uint32_t version; + uint32_t cmd; // LC_VERSION_MIN_MACOSX or + // LC_VERSION_MIN_IPHONEOS + uint32_t cmdsize; // sizeof(struct version_min_command) + uint32_t version; // X.Y.Z is encoded in nibbles xxxx.yy.zz uint32_t reserved; }; @@ -858,6 +959,13 @@ namespace llvm { }; // Structs from <mach-o/nlist.h> + struct nlist_base { + uint32_t n_strx; + uint8_t n_type; + uint8_t n_sect; + uint16_t n_desc; + }; + struct nlist { uint32_t n_strx; uint8_t n_type; @@ -874,6 +982,206 @@ namespace llvm { uint64_t n_value; }; + + // Byte order swapping functions for MachO structs + + inline void swapStruct(mach_header &mh) { + sys::swapByteOrder(mh.magic); + sys::swapByteOrder(mh.cputype); + sys::swapByteOrder(mh.cpusubtype); + sys::swapByteOrder(mh.filetype); + sys::swapByteOrder(mh.ncmds); + sys::swapByteOrder(mh.sizeofcmds); + sys::swapByteOrder(mh.flags); + } + + inline void swapStruct(mach_header_64 &H) { + sys::swapByteOrder(H.magic); + sys::swapByteOrder(H.cputype); + sys::swapByteOrder(H.cpusubtype); + sys::swapByteOrder(H.filetype); + sys::swapByteOrder(H.ncmds); + sys::swapByteOrder(H.sizeofcmds); + sys::swapByteOrder(H.flags); + sys::swapByteOrder(H.reserved); + } + + inline void swapStruct(load_command &lc) { + sys::swapByteOrder(lc.cmd); + sys::swapByteOrder(lc.cmdsize); + } + + inline void swapStruct(symtab_command &lc) { + sys::swapByteOrder(lc.cmd); + sys::swapByteOrder(lc.cmdsize); + sys::swapByteOrder(lc.symoff); + sys::swapByteOrder(lc.nsyms); + sys::swapByteOrder(lc.stroff); + sys::swapByteOrder(lc.strsize); + } + + inline void swapStruct(segment_command_64 &seg) { + sys::swapByteOrder(seg.cmd); + sys::swapByteOrder(seg.cmdsize); + sys::swapByteOrder(seg.vmaddr); + sys::swapByteOrder(seg.vmsize); + sys::swapByteOrder(seg.fileoff); + sys::swapByteOrder(seg.filesize); + sys::swapByteOrder(seg.maxprot); + sys::swapByteOrder(seg.initprot); + sys::swapByteOrder(seg.nsects); + sys::swapByteOrder(seg.flags); + } + + inline void swapStruct(segment_command &seg) { + sys::swapByteOrder(seg.cmd); + sys::swapByteOrder(seg.cmdsize); + sys::swapByteOrder(seg.vmaddr); + sys::swapByteOrder(seg.vmsize); + sys::swapByteOrder(seg.fileoff); + sys::swapByteOrder(seg.filesize); + sys::swapByteOrder(seg.maxprot); + sys::swapByteOrder(seg.initprot); + sys::swapByteOrder(seg.nsects); + sys::swapByteOrder(seg.flags); + } + + inline void swapStruct(section_64 §) { + sys::swapByteOrder(sect.addr); + sys::swapByteOrder(sect.size); + sys::swapByteOrder(sect.offset); + sys::swapByteOrder(sect.align); + sys::swapByteOrder(sect.reloff); + sys::swapByteOrder(sect.nreloc); + sys::swapByteOrder(sect.flags); + sys::swapByteOrder(sect.reserved1); + sys::swapByteOrder(sect.reserved2); + } + + inline void swapStruct(section §) { + sys::swapByteOrder(sect.addr); + sys::swapByteOrder(sect.size); + sys::swapByteOrder(sect.offset); + sys::swapByteOrder(sect.align); + sys::swapByteOrder(sect.reloff); + sys::swapByteOrder(sect.nreloc); + sys::swapByteOrder(sect.flags); + sys::swapByteOrder(sect.reserved1); + sys::swapByteOrder(sect.reserved2); + } + + inline void swapStruct(dyld_info_command &info) { + sys::swapByteOrder(info.cmd); + sys::swapByteOrder(info.cmdsize); + sys::swapByteOrder(info.rebase_off); + sys::swapByteOrder(info.rebase_size); + sys::swapByteOrder(info.bind_off); + sys::swapByteOrder(info.bind_size); + sys::swapByteOrder(info.weak_bind_off); + sys::swapByteOrder(info.weak_bind_size); + sys::swapByteOrder(info.lazy_bind_off); + sys::swapByteOrder(info.lazy_bind_size); + sys::swapByteOrder(info.export_off); + sys::swapByteOrder(info.export_size); + } + + inline void swapStruct(dylib_command &d) { + sys::swapByteOrder(d.cmd); + sys::swapByteOrder(d.cmdsize); + sys::swapByteOrder(d.dylib.name); + sys::swapByteOrder(d.dylib.timestamp); + sys::swapByteOrder(d.dylib.current_version); + sys::swapByteOrder(d.dylib.compatibility_version); + } + + inline void swapStruct(dylinker_command &d) { + sys::swapByteOrder(d.cmd); + sys::swapByteOrder(d.cmdsize); + sys::swapByteOrder(d.name); + } + + inline void swapStruct(entry_point_command &e) { + sys::swapByteOrder(e.cmd); + sys::swapByteOrder(e.cmdsize); + sys::swapByteOrder(e.entryoff); + sys::swapByteOrder(e.stacksize); + } + + inline void swapStruct(dysymtab_command &dst) { + sys::swapByteOrder(dst.cmd); + sys::swapByteOrder(dst.cmdsize); + sys::swapByteOrder(dst.ilocalsym); + sys::swapByteOrder(dst.nlocalsym); + sys::swapByteOrder(dst.iextdefsym); + sys::swapByteOrder(dst.nextdefsym); + sys::swapByteOrder(dst.iundefsym); + sys::swapByteOrder(dst.nundefsym); + sys::swapByteOrder(dst.tocoff); + sys::swapByteOrder(dst.ntoc); + sys::swapByteOrder(dst.modtaboff); + sys::swapByteOrder(dst.nmodtab); + sys::swapByteOrder(dst.extrefsymoff); + sys::swapByteOrder(dst.nextrefsyms); + sys::swapByteOrder(dst.indirectsymoff); + sys::swapByteOrder(dst.nindirectsyms); + sys::swapByteOrder(dst.extreloff); + sys::swapByteOrder(dst.nextrel); + sys::swapByteOrder(dst.locreloff); + sys::swapByteOrder(dst.nlocrel); + } + + inline void swapStruct(any_relocation_info &reloc) { + sys::swapByteOrder(reloc.r_word0); + sys::swapByteOrder(reloc.r_word1); + } + + inline void swapStruct(nlist_base &S) { + sys::swapByteOrder(S.n_strx); + sys::swapByteOrder(S.n_desc); + } + + inline void swapStruct(nlist &sym) { + sys::swapByteOrder(sym.n_strx); + sys::swapByteOrder(sym.n_desc); + sys::swapByteOrder(sym.n_value); + } + + inline void swapStruct(nlist_64 &sym) { + sys::swapByteOrder(sym.n_strx); + sys::swapByteOrder(sym.n_desc); + sys::swapByteOrder(sym.n_value); + } + + inline void swapStruct(linkedit_data_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.dataoff); + sys::swapByteOrder(C.datasize); + } + + inline void swapStruct(linker_options_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.count); + } + + inline void swapStruct(version_min_command&C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.version); + sys::swapByteOrder(C.reserved); + } + + inline void swapStruct(data_in_code_entry &C) { + sys::swapByteOrder(C.offset); + sys::swapByteOrder(C.length); + sys::swapByteOrder(C.kind); + } + + inline void swapStruct(uint32_t &C) { + sys::swapByteOrder(C); + } + // Get/Set functions from <mach-o/nlist.h> static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) { @@ -893,7 +1201,7 @@ namespace llvm { } // Enums from <mach/machine.h> - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Capability bits used in the definition of cpu_type. CPU_ARCH_MASK = 0xff000000, // Mask for architecture bits CPU_ARCH_ABI64 = 0x01000000 // 64 bit ABI @@ -908,15 +1216,16 @@ namespace llvm { /* CPU_TYPE_MIPS = 8, */ CPU_TYPE_MC98000 = 10, // Old Motorola PowerPC CPU_TYPE_ARM = 12, + CPU_TYPE_ARM64 = CPU_TYPE_ARM | CPU_ARCH_ABI64, CPU_TYPE_SPARC = 14, CPU_TYPE_POWERPC = 18, CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64 }; - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Capability bits used in the definition of cpusubtype. - CPU_SUB_TYPE_MASK = 0xff000000, // Mask for architecture bits - CPU_SUB_TYPE_LIB64 = 0x80000000, // 64 bit libraries + CPU_SUBTYPE_MASK = 0xff000000, // Mask for architecture bits + CPU_SUBTYPE_LIB64 = 0x80000000, // 64 bit libraries // Special CPU subtype constants. CPU_SUBTYPE_MULTIPLE = ~0u @@ -973,7 +1282,7 @@ namespace llvm { CPU_SUBTYPE_ARM_V5TEJ = 7, CPU_SUBTYPE_ARM_XSCALE = 8, CPU_SUBTYPE_ARM_V7 = 9, - CPU_SUBTYPE_ARM_V7F = 10, + // unused ARM_V7F = 10, CPU_SUBTYPE_ARM_V7S = 11, CPU_SUBTYPE_ARM_V7K = 12, CPU_SUBTYPE_ARM_V6M = 14, @@ -981,6 +1290,10 @@ namespace llvm { CPU_SUBTYPE_ARM_V7EM = 16 }; + enum CPUSubTypeARM64 { + CPU_SUBTYPE_ARM64_ALL = 0 + }; + enum CPUSubTypeSPARC { CPU_SUBTYPE_SPARC_ALL = 0 }; diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index 5587618d11bb..d8fbfeb8e20c 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -47,7 +47,7 @@ protected: void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const; public: /// isConstructed - Return true if this object has not been created yet. - bool isConstructed() const { return Ptr != 0; } + bool isConstructed() const { return Ptr != nullptr; } void destroy() const; }; @@ -103,9 +103,6 @@ void llvm_shutdown(); /// llvm_shutdown() when it is destroyed. struct llvm_shutdown_obj { llvm_shutdown_obj() { } - explicit llvm_shutdown_obj(bool multithreaded) { - if (multithreaded) llvm_start_multithreaded(); - } ~llvm_shutdown_obj() { llvm_shutdown(); } }; diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index ff41608f5f51..0abba62a2c23 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -16,9 +16,9 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/SwapByteOrder.h" -#include "llvm/Support/type_traits.h" - +#include <cassert> #include <cstring> +#include <type_traits> #ifdef _MSC_VER #include <intrin.h> @@ -44,8 +44,8 @@ enum ZeroBehavior { /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are /// valid arguments. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, std::size_t>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, std::size_t>::type countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { (void)ZB; @@ -71,8 +71,8 @@ countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { // Disable signed. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, std::size_t>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, std::size_t>::type countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) LLVM_DELETED_FUNCTION; #if __GNUC__ >= 4 || _MSC_VER @@ -115,8 +115,8 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are /// valid arguments. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, std::size_t>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, std::size_t>::type countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { (void)ZB; @@ -137,8 +137,8 @@ countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { // Disable signed. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, std::size_t>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, std::size_t>::type countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) LLVM_DELETED_FUNCTION; #if __GNUC__ >= 4 || _MSC_VER @@ -181,8 +181,8 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, T>::type findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits<T>::max(); @@ -192,8 +192,8 @@ findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { // Disable signed. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, T>::type findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION; /// \brief Get the index of the last set bit starting from the least @@ -204,8 +204,8 @@ findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION; /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, T>::type findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits<T>::max(); @@ -218,8 +218,8 @@ findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { // Disable signed. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, T>::type findLastSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION; /// \brief Macro compressed bit reversal table for 256 bits. @@ -230,6 +230,9 @@ static const unsigned char BitReverseTable256[256] = { #define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) #define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) R6(0), R6(2), R6(1), R6(3) +#undef R2 +#undef R4 +#undef R6 }; /// \brief Reverse the bits in \p Val. @@ -258,6 +261,12 @@ inline uint32_t Lo_32(uint64_t Value) { return static_cast<uint32_t>(Value); } +/// Make_64 - This functions makes a 64-bit integer from a high / low pair of +/// 32-bit integers. +inline uint64_t Make_64(uint32_t High, uint32_t Low) { + return ((uint64_t)High << 32) | (uint64_t)Low; +} + /// isInt - Checks if an integer fits into the given bit width. template<unsigned N> inline bool isInt(int64_t x) { @@ -541,6 +550,18 @@ inline uint64_t MinAlign(uint64_t A, uint64_t B) { return (A | B) & (1 + ~(A | B)); } +/// \brief Aligns \c Ptr to \c Alignment bytes, rounding up. +/// +/// Alignment should be a power of two. This method rounds up, so +/// AlignPtr(7, 4) == 8 and AlignPtr(8, 4) == 8. +inline char *alignPtr(char *Ptr, size_t Alignment) { + assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && + "Alignment is not a power of two!"); + + return (char *)(((uintptr_t)Ptr + Alignment - 1) & + ~(uintptr_t)(Alignment - 1)); +} + /// NextPowerOf2 - Returns the next power of two (in 64-bits) /// that is strictly greater than A. Returns zero on overflow. inline uint64_t NextPowerOf2(uint64_t A) { @@ -553,6 +574,13 @@ inline uint64_t NextPowerOf2(uint64_t A) { return A + 1; } +/// Returns the power of two which is less than or equal to the given value. +/// Essentially, it is a floor operation across the domain of powers of two. +inline uint64_t PowerOf2Floor(uint64_t A) { + if (!A) return 0; + return 1ull << (63 - countLeadingZeros(A, ZB_Undefined)); +} + /// Returns the next integer (mod 2**64) that is greater than or equal to /// \p Value and is a multiple of \p Align. \p Align must be non-zero. /// diff --git a/include/llvm/Support/Memory.h b/include/llvm/Support/Memory.h index a08c79649d53..b4305cb697d0 100644 --- a/include/llvm/Support/Memory.h +++ b/include/llvm/Support/Memory.h @@ -15,8 +15,8 @@ #define LLVM_SUPPORT_MEMORY_H #include "llvm/Support/DataTypes.h" -#include "llvm/Support/system_error.h" #include <string> +#include <system_error> namespace llvm { namespace sys { @@ -28,7 +28,7 @@ namespace sys { /// @brief Memory block abstraction. class MemoryBlock { public: - MemoryBlock() : Address(0), Size(0) { } + MemoryBlock() : Address(nullptr), Size(0) { } MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } void *base() const { return Address; } size_t size() const { return Size; } @@ -77,7 +77,7 @@ namespace sys { static MemoryBlock allocateMappedMemory(size_t NumBytes, const MemoryBlock *const NearBlock, unsigned Flags, - error_code &EC); + std::error_code &EC); /// This method releases a block of memory that was allocated with the /// allocateMappedMemory method. It should not be used to release any @@ -88,14 +88,14 @@ namespace sys { /// describing the failure if an error occurred. /// /// @brief Release mapped memory. - static error_code releaseMappedMemory(MemoryBlock &Block); + static std::error_code releaseMappedMemory(MemoryBlock &Block); /// This method sets the protection flags for a block of memory to the /// state specified by /p Flags. The behavior is not specified if the /// memory was not allocated using the allocateMappedMemory method. /// \p Block describes the memory block to be protected. /// \p Flags specifies the new protection state to be assigned to the block. - /// \p ErrMsg [out] returns a string describing any error that occured. + /// \p ErrMsg [out] returns a string describing any error that occurred. /// /// If \p Flags is MF_WRITE, the actual behavior varies /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the @@ -105,8 +105,8 @@ namespace sys { /// describing the failure if an error occurred. /// /// @brief Set memory protection state. - static error_code protectMappedMemory(const MemoryBlock &Block, - unsigned Flags); + static std::error_code protectMappedMemory(const MemoryBlock &Block, + unsigned Flags); /// This method allocates a block of Read/Write/Execute memory that is /// suitable for executing dynamically generated code (e.g. JIT). An @@ -120,7 +120,7 @@ namespace sys { /// @brief Allocate Read/Write/Execute memory. static MemoryBlock AllocateRWX(size_t NumBytes, const MemoryBlock *NearBlock, - std::string *ErrMsg = 0); + std::string *ErrMsg = nullptr); /// This method releases a block of Read/Write/Execute memory that was /// allocated with the AllocateRWX method. It should not be used to @@ -129,7 +129,7 @@ namespace sys { /// On success, this returns false, otherwise it returns true and fills /// in *ErrMsg. /// @brief Release Read/Write/Execute memory. - static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = 0); + static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr); /// InvalidateInstructionCache - Before the JIT can run a block of code @@ -140,12 +140,12 @@ namespace sys { /// setExecutable - Before the JIT can run a block of code, it has to be /// given read and executable privilege. Return true if it is already r-x /// or the system is able to change its previlege. - static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = 0); + static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = nullptr); /// setWritable - When adding to a block of code, the JIT may need /// to mark a block of code as RW since the protections are on page /// boundaries, and the JIT internal allocations are not page aligned. - static bool setWritable(MemoryBlock &M, std::string *ErrMsg = 0); + static bool setWritable(MemoryBlock &M, std::string *ErrMsg = nullptr); /// setRangeExecutable - Mark the page containing a range of addresses /// as executable. diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index ff22fb67c84e..147be47e1c8f 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -14,17 +14,16 @@ #ifndef LLVM_SUPPORT_MEMORYBUFFER_H #define LLVM_SUPPORT_MEMORYBUFFER_H +#include "llvm-c/Support.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" -#include "llvm-c/Core.h" +#include "llvm/Support/ErrorOr.h" +#include <memory> +#include <system_error> namespace llvm { - -class error_code; -template<class T> class OwningPtr; - /// MemoryBuffer - This interface provides simple read-only access to a block /// of memory, and provides simple methods for reading files and standard input /// into a memory buffer. In addition to basic access to the characters in the @@ -62,27 +61,38 @@ public: return "Unknown buffer"; } - /// getFile - Open the specified file as a MemoryBuffer, returning a new - /// MemoryBuffer if successful, otherwise returning null. If FileSize is - /// specified, this means that the client knows that the file exists and that - /// it has the specified size. - static error_code getFile(Twine Filename, OwningPtr<MemoryBuffer> &result, - int64_t FileSize = -1, - bool RequiresNullTerminator = true); + /// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer + /// if successful, otherwise returning null. If FileSize is specified, this + /// means that the client knows that the file exists and that it has the + /// specified size. + /// + /// \param IsVolatileSize Set to true to indicate that the file size may be + /// changing, e.g. when libclang tries to parse while the user is + /// editing/updating the file. + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getFile(Twine Filename, int64_t FileSize = -1, + bool RequiresNullTerminator = true, bool IsVolatileSize = false); /// Given an already-open file descriptor, map some slice of it into a /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. /// Since this is in the middle of a file, the buffer is not null terminated. - static error_code getOpenFileSlice(int FD, const char *Filename, - OwningPtr<MemoryBuffer> &Result, - uint64_t MapSize, int64_t Offset); + /// + /// \param IsVolatileSize Set to true to indicate that the file size may be + /// changing, e.g. when libclang tries to parse while the user is + /// editing/updating the file. + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getOpenFileSlice(int FD, const char *Filename, uint64_t MapSize, + int64_t Offset, bool IsVolatileSize = false); /// Given an already-open file descriptor, read the file and return a /// MemoryBuffer. - static error_code getOpenFile(int FD, const char *Filename, - OwningPtr<MemoryBuffer> &Result, - uint64_t FileSize, - bool RequiresNullTerminator = true); + /// + /// \param IsVolatileSize Set to true to indicate that the file size may be + /// changing, e.g. when libclang tries to parse while the user is + /// editing/updating the file. + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getOpenFile(int FD, const char *Filename, uint64_t FileSize, + bool RequiresNullTerminator = true, bool IsVolatileSize = false); /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note /// that InputData must be null terminated if RequiresNullTerminator is true. @@ -109,17 +119,13 @@ public: static MemoryBuffer *getNewUninitMemBuffer(size_t Size, StringRef BufferName = ""); - /// getSTDIN - Read all of stdin into a file buffer, and return it. - /// If an error occurs, this returns null and sets ec. - static error_code getSTDIN(OwningPtr<MemoryBuffer> &result); - + /// Read all of stdin into a file buffer, and return it. + static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN(); - /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin - /// if the Filename is "-". If an error occurs, this returns null and sets - /// ec. - static error_code getFileOrSTDIN(StringRef Filename, - OwningPtr<MemoryBuffer> &result, - int64_t FileSize = -1); + /// Open the specified file as a MemoryBuffer, or open stdin if the Filename + /// is "-". + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getFileOrSTDIN(StringRef Filename, int64_t FileSize = -1); //===--------------------------------------------------------------------===// // Provided for performance analysis. diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h new file mode 100644 index 000000000000..f6d43a440788 --- /dev/null +++ b/include/llvm/Support/OnDiskHashTable.h @@ -0,0 +1,571 @@ +//===--- OnDiskHashTable.h - On-Disk Hash Table Implementation --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines facilities for reading and writing on-disk hash tables. +/// +//===----------------------------------------------------------------------===// +#ifndef LLVM_SUPPORT_ON_DISK_HASH_TABLE_H +#define LLVM_SUPPORT_ON_DISK_HASH_TABLE_H + +#include "llvm/Support/Allocator.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdlib> + +namespace llvm { + +/// \brief Generates an on disk hash table. +/// +/// This needs an \c Info that handles storing values into the hash table's +/// payload and computes the hash for a given key. This should provide the +/// following interface: +/// +/// \code +/// class ExampleInfo { +/// public: +/// typedef ExampleKey key_type; // Must be copy constructible +/// typedef ExampleKey &key_type_ref; +/// typedef ExampleData data_type; // Must be copy constructible +/// typedef ExampleData &data_type_ref; +/// typedef uint32_t hash_value_type; // The type the hash function returns. +/// typedef uint32_t offset_type; // The type for offsets into the table. +/// +/// /// Calculate the hash for Key +/// static hash_value_type ComputeHash(key_type_ref Key); +/// /// Return the lengths, in bytes, of the given Key/Data pair. +/// static std::pair<offset_type, offset_type> +/// EmitKeyDataLength(raw_ostream &Out, key_type_ref Key, data_type_ref Data); +/// /// Write Key to Out. KeyLen is the length from EmitKeyDataLength. +/// static void EmitKey(raw_ostream &Out, key_type_ref Key, +/// offset_type KeyLen); +/// /// Write Data to Out. DataLen is the length from EmitKeyDataLength. +/// static void EmitData(raw_ostream &Out, key_type_ref Key, +/// data_type_ref Data, offset_type DataLen); +/// }; +/// \endcode +template <typename Info> class OnDiskChainedHashTableGenerator { + /// \brief A single item in the hash table. + class Item { + public: + typename Info::key_type Key; + typename Info::data_type Data; + Item *Next; + const typename Info::hash_value_type Hash; + + Item(typename Info::key_type_ref Key, typename Info::data_type_ref Data, + Info &InfoObj) + : Key(Key), Data(Data), Next(nullptr), Hash(InfoObj.ComputeHash(Key)) {} + }; + + typedef typename Info::offset_type offset_type; + offset_type NumBuckets; + offset_type NumEntries; + llvm::SpecificBumpPtrAllocator<Item> BA; + + /// \brief A linked list of values in a particular hash bucket. + class Bucket { + public: + offset_type Off; + Item *Head; + unsigned Length; + + Bucket() {} + }; + + Bucket *Buckets; + +private: + /// \brief Insert an item into the appropriate hash bucket. + void insert(Bucket *Buckets, size_t Size, Item *E) { + Bucket &B = Buckets[E->Hash & (Size - 1)]; + E->Next = B.Head; + ++B.Length; + B.Head = E; + } + + /// \brief Resize the hash table, moving the old entries into the new buckets. + void resize(size_t NewSize) { + Bucket *NewBuckets = (Bucket *)std::calloc(NewSize, sizeof(Bucket)); + // Populate NewBuckets with the old entries. + for (size_t I = 0; I < NumBuckets; ++I) + for (Item *E = Buckets[I].Head; E;) { + Item *N = E->Next; + E->Next = nullptr; + insert(NewBuckets, NewSize, E); + E = N; + } + + free(Buckets); + NumBuckets = NewSize; + Buckets = NewBuckets; + } + +public: + /// \brief Insert an entry into the table. + void insert(typename Info::key_type_ref Key, + typename Info::data_type_ref Data) { + Info InfoObj; + insert(Key, Data, InfoObj); + } + + /// \brief Insert an entry into the table. + /// + /// Uses the provided Info instead of a stack allocated one. + void insert(typename Info::key_type_ref Key, + typename Info::data_type_ref Data, Info &InfoObj) { + + ++NumEntries; + if (4 * NumEntries >= 3 * NumBuckets) + resize(NumBuckets * 2); + insert(Buckets, NumBuckets, new (BA.Allocate()) Item(Key, Data, InfoObj)); + } + + /// \brief Emit the table to Out, which must not be at offset 0. + offset_type Emit(raw_ostream &Out) { + Info InfoObj; + return Emit(Out, InfoObj); + } + + /// \brief Emit the table to Out, which must not be at offset 0. + /// + /// Uses the provided Info instead of a stack allocated one. + offset_type Emit(raw_ostream &Out, Info &InfoObj) { + using namespace llvm::support; + endian::Writer<little> LE(Out); + + // Emit the payload of the table. + for (offset_type I = 0; I < NumBuckets; ++I) { + Bucket &B = Buckets[I]; + if (!B.Head) + continue; + + // Store the offset for the data of this bucket. + B.Off = Out.tell(); + assert(B.Off && "Cannot write a bucket at offset 0. Please add padding."); + + // Write out the number of items in the bucket. + LE.write<uint16_t>(B.Length); + assert(B.Length != 0 && "Bucket has a head but zero length?"); + + // Write out the entries in the bucket. + for (Item *I = B.Head; I; I = I->Next) { + LE.write<typename Info::hash_value_type>(I->Hash); + const std::pair<offset_type, offset_type> &Len = + InfoObj.EmitKeyDataLength(Out, I->Key, I->Data); + InfoObj.EmitKey(Out, I->Key, Len.first); + InfoObj.EmitData(Out, I->Key, I->Data, Len.second); + } + } + + // Pad with zeros so that we can start the hashtable at an aligned address. + offset_type TableOff = Out.tell(); + uint64_t N = llvm::OffsetToAlignment(TableOff, alignOf<offset_type>()); + TableOff += N; + while (N--) + LE.write<uint8_t>(0); + + // Emit the hashtable itself. + LE.write<offset_type>(NumBuckets); + LE.write<offset_type>(NumEntries); + for (offset_type I = 0; I < NumBuckets; ++I) + LE.write<offset_type>(Buckets[I].Off); + + return TableOff; + } + + OnDiskChainedHashTableGenerator() { + NumEntries = 0; + NumBuckets = 64; + // Note that we do not need to run the constructors of the individual + // Bucket objects since 'calloc' returns bytes that are all 0. + Buckets = (Bucket *)std::calloc(NumBuckets, sizeof(Bucket)); + } + + ~OnDiskChainedHashTableGenerator() { std::free(Buckets); } +}; + +/// \brief Provides lookup on an on disk hash table. +/// +/// This needs an \c Info that handles reading values from the hash table's +/// payload and computes the hash for a given key. This should provide the +/// following interface: +/// +/// \code +/// class ExampleLookupInfo { +/// public: +/// typedef ExampleData data_type; +/// typedef ExampleInternalKey internal_key_type; // The stored key type. +/// typedef ExampleKey external_key_type; // The type to pass to find(). +/// typedef uint32_t hash_value_type; // The type the hash function returns. +/// typedef uint32_t offset_type; // The type for offsets into the table. +/// +/// /// Compare two keys for equality. +/// static bool EqualKey(internal_key_type &Key1, internal_key_type &Key2); +/// /// Calculate the hash for the given key. +/// static hash_value_type ComputeHash(internal_key_type &IKey); +/// /// Translate from the semantic type of a key in the hash table to the +/// /// type that is actually stored and used for hashing and comparisons. +/// /// The internal and external types are often the same, in which case this +/// /// can simply return the passed in value. +/// static const internal_key_type &GetInternalKey(external_key_type &EKey); +/// /// Read the key and data length from Buffer, leaving it pointing at the +/// /// following byte. +/// static std::pair<offset_type, offset_type> +/// ReadKeyDataLength(const unsigned char *&Buffer); +/// /// Read the key from Buffer, given the KeyLen as reported from +/// /// ReadKeyDataLength. +/// const internal_key_type &ReadKey(const unsigned char *Buffer, +/// offset_type KeyLen); +/// /// Read the data for Key from Buffer, given the DataLen as reported from +/// /// ReadKeyDataLength. +/// data_type ReadData(StringRef Key, const unsigned char *Buffer, +/// offset_type DataLen); +/// }; +/// \endcode +template <typename Info> class OnDiskChainedHashTable { + const typename Info::offset_type NumBuckets; + const typename Info::offset_type NumEntries; + const unsigned char *const Buckets; + const unsigned char *const Base; + Info InfoObj; + +public: + typedef typename Info::internal_key_type internal_key_type; + typedef typename Info::external_key_type external_key_type; + typedef typename Info::data_type data_type; + typedef typename Info::hash_value_type hash_value_type; + typedef typename Info::offset_type offset_type; + + OnDiskChainedHashTable(offset_type NumBuckets, offset_type NumEntries, + const unsigned char *Buckets, + const unsigned char *Base, + const Info &InfoObj = Info()) + : NumBuckets(NumBuckets), NumEntries(NumEntries), Buckets(Buckets), + Base(Base), InfoObj(InfoObj) { + assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 && + "'buckets' must have a 4-byte alignment"); + } + + offset_type getNumBuckets() const { return NumBuckets; } + offset_type getNumEntries() const { return NumEntries; } + const unsigned char *getBase() const { return Base; } + const unsigned char *getBuckets() const { return Buckets; } + + bool isEmpty() const { return NumEntries == 0; } + + class iterator { + internal_key_type Key; + const unsigned char *const Data; + const offset_type Len; + Info *InfoObj; + + public: + iterator() : Data(nullptr), Len(0) {} + iterator(const internal_key_type K, const unsigned char *D, offset_type L, + Info *InfoObj) + : Key(K), Data(D), Len(L), InfoObj(InfoObj) {} + + data_type operator*() const { return InfoObj->ReadData(Key, Data, Len); } + bool operator==(const iterator &X) const { return X.Data == Data; } + bool operator!=(const iterator &X) const { return X.Data != Data; } + }; + + /// \brief Look up the stored data for a particular key. + iterator find(const external_key_type &EKey, Info *InfoPtr = 0) { + if (!InfoPtr) + InfoPtr = &InfoObj; + + using namespace llvm::support; + const internal_key_type &IKey = InfoObj.GetInternalKey(EKey); + hash_value_type KeyHash = InfoObj.ComputeHash(IKey); + + // Each bucket is just an offset into the hash table file. + offset_type Idx = KeyHash & (NumBuckets - 1); + const unsigned char *Bucket = Buckets + sizeof(offset_type) * Idx; + + offset_type Offset = endian::readNext<offset_type, little, aligned>(Bucket); + if (Offset == 0) + return iterator(); // Empty bucket. + const unsigned char *Items = Base + Offset; + + // 'Items' starts with a 16-bit unsigned integer representing the + // number of items in this bucket. + unsigned Len = endian::readNext<uint16_t, little, unaligned>(Items); + + for (unsigned i = 0; i < Len; ++i) { + // Read the hash. + hash_value_type ItemHash = + endian::readNext<hash_value_type, little, unaligned>(Items); + + // Determine the length of the key and the data. + const std::pair<offset_type, offset_type> &L = + Info::ReadKeyDataLength(Items); + offset_type ItemLen = L.first + L.second; + + // Compare the hashes. If they are not the same, skip the entry entirely. + if (ItemHash != KeyHash) { + Items += ItemLen; + continue; + } + + // Read the key. + const internal_key_type &X = + InfoPtr->ReadKey((const unsigned char *const)Items, L.first); + + // If the key doesn't match just skip reading the value. + if (!InfoPtr->EqualKey(X, IKey)) { + Items += ItemLen; + continue; + } + + // The key matches! + return iterator(X, Items + L.first, L.second, InfoPtr); + } + + return iterator(); + } + + iterator end() const { return iterator(); } + + Info &getInfoObj() { return InfoObj; } + + /// \brief Create the hash table. + /// + /// \param Buckets is the beginning of the hash table itself, which follows + /// the payload of entire structure. This is the value returned by + /// OnDiskHashTableGenerator::Emit. + /// + /// \param Base is the point from which all offsets into the structure are + /// based. This is offset 0 in the stream that was used when Emitting the + /// table. + static OnDiskChainedHashTable *Create(const unsigned char *Buckets, + const unsigned char *const Base, + const Info &InfoObj = Info()) { + using namespace llvm::support; + assert(Buckets > Base); + assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 && + "buckets should be 4-byte aligned."); + + offset_type NumBuckets = + endian::readNext<offset_type, little, aligned>(Buckets); + offset_type NumEntries = + endian::readNext<offset_type, little, aligned>(Buckets); + return new OnDiskChainedHashTable<Info>(NumBuckets, NumEntries, Buckets, + Base, InfoObj); + } +}; + +/// \brief Provides lookup and iteration over an on disk hash table. +/// +/// \copydetails llvm::OnDiskChainedHashTable +template <typename Info> +class OnDiskIterableChainedHashTable : public OnDiskChainedHashTable<Info> { + const unsigned char *Payload; + +public: + typedef OnDiskChainedHashTable<Info> base_type; + typedef typename base_type::internal_key_type internal_key_type; + typedef typename base_type::external_key_type external_key_type; + typedef typename base_type::data_type data_type; + typedef typename base_type::hash_value_type hash_value_type; + typedef typename base_type::offset_type offset_type; + + OnDiskIterableChainedHashTable(offset_type NumBuckets, offset_type NumEntries, + const unsigned char *Buckets, + const unsigned char *Payload, + const unsigned char *Base, + const Info &InfoObj = Info()) + : base_type(NumBuckets, NumEntries, Buckets, Base, InfoObj), + Payload(Payload) {} + + /// \brief Iterates over all of the keys in the table. + class key_iterator { + const unsigned char *Ptr; + offset_type NumItemsInBucketLeft; + offset_type NumEntriesLeft; + Info *InfoObj; + + public: + typedef external_key_type value_type; + + key_iterator(const unsigned char *const Ptr, offset_type NumEntries, + Info *InfoObj) + : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries), + InfoObj(InfoObj) {} + key_iterator() + : Ptr(nullptr), NumItemsInBucketLeft(0), NumEntriesLeft(0), + InfoObj(0) {} + + friend bool operator==(const key_iterator &X, const key_iterator &Y) { + return X.NumEntriesLeft == Y.NumEntriesLeft; + } + friend bool operator!=(const key_iterator &X, const key_iterator &Y) { + return X.NumEntriesLeft != Y.NumEntriesLeft; + } + + key_iterator &operator++() { // Preincrement + using namespace llvm::support; + if (!NumItemsInBucketLeft) { + // 'Items' starts with a 16-bit unsigned integer representing the + // number of items in this bucket. + NumItemsInBucketLeft = + endian::readNext<uint16_t, little, unaligned>(Ptr); + } + Ptr += sizeof(hash_value_type); // Skip the hash. + // Determine the length of the key and the data. + const std::pair<offset_type, offset_type> &L = + Info::ReadKeyDataLength(Ptr); + Ptr += L.first + L.second; + assert(NumItemsInBucketLeft); + --NumItemsInBucketLeft; + assert(NumEntriesLeft); + --NumEntriesLeft; + return *this; + } + key_iterator operator++(int) { // Postincrement + key_iterator tmp = *this; ++*this; return tmp; + } + + value_type operator*() const { + const unsigned char *LocalPtr = Ptr; + if (!NumItemsInBucketLeft) + LocalPtr += 2; // number of items in bucket + LocalPtr += sizeof(hash_value_type); // Skip the hash. + + // Determine the length of the key and the data. + const std::pair<offset_type, offset_type> &L = + Info::ReadKeyDataLength(LocalPtr); + + // Read the key. + const internal_key_type &Key = InfoObj->ReadKey(LocalPtr, L.first); + return InfoObj->GetExternalKey(Key); + } + }; + + key_iterator key_begin() { + return key_iterator(Payload, this->getNumEntries(), &this->getInfoObj()); + } + key_iterator key_end() { return key_iterator(); } + + iterator_range<key_iterator> keys() { + return make_range(key_begin(), key_end()); + } + + /// \brief Iterates over all the entries in the table, returning the data. + class data_iterator { + const unsigned char *Ptr; + offset_type NumItemsInBucketLeft; + offset_type NumEntriesLeft; + Info *InfoObj; + + public: + typedef data_type value_type; + + data_iterator(const unsigned char *const Ptr, offset_type NumEntries, + Info *InfoObj) + : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries), + InfoObj(InfoObj) {} + data_iterator() + : Ptr(nullptr), NumItemsInBucketLeft(0), NumEntriesLeft(0), + InfoObj(nullptr) {} + + bool operator==(const data_iterator &X) const { + return X.NumEntriesLeft == NumEntriesLeft; + } + bool operator!=(const data_iterator &X) const { + return X.NumEntriesLeft != NumEntriesLeft; + } + + data_iterator &operator++() { // Preincrement + using namespace llvm::support; + if (!NumItemsInBucketLeft) { + // 'Items' starts with a 16-bit unsigned integer representing the + // number of items in this bucket. + NumItemsInBucketLeft = + endian::readNext<uint16_t, little, unaligned>(Ptr); + } + Ptr += sizeof(hash_value_type); // Skip the hash. + // Determine the length of the key and the data. + const std::pair<offset_type, offset_type> &L = + Info::ReadKeyDataLength(Ptr); + Ptr += L.first + L.second; + assert(NumItemsInBucketLeft); + --NumItemsInBucketLeft; + assert(NumEntriesLeft); + --NumEntriesLeft; + return *this; + } + data_iterator operator++(int) { // Postincrement + data_iterator tmp = *this; ++*this; return tmp; + } + + value_type operator*() const { + const unsigned char *LocalPtr = Ptr; + if (!NumItemsInBucketLeft) + LocalPtr += 2; // number of items in bucket + LocalPtr += sizeof(hash_value_type); // Skip the hash. + + // Determine the length of the key and the data. + const std::pair<offset_type, offset_type> &L = + Info::ReadKeyDataLength(LocalPtr); + + // Read the key. + const internal_key_type &Key = InfoObj->ReadKey(LocalPtr, L.first); + return InfoObj->ReadData(Key, LocalPtr + L.first, L.second); + } + }; + + data_iterator data_begin() { + return data_iterator(Payload, this->getNumEntries(), &this->getInfoObj()); + } + data_iterator data_end() { return data_iterator(); } + + iterator_range<data_iterator> data() { + return make_range(data_begin(), data_end()); + } + + /// \brief Create the hash table. + /// + /// \param Buckets is the beginning of the hash table itself, which follows + /// the payload of entire structure. This is the value returned by + /// OnDiskHashTableGenerator::Emit. + /// + /// \param Payload is the beginning of the data contained in the table. This + /// is Base plus any padding or header data that was stored, ie, the offset + /// that the stream was at when calling Emit. + /// + /// \param Base is the point from which all offsets into the structure are + /// based. This is offset 0 in the stream that was used when Emitting the + /// table. + static OnDiskIterableChainedHashTable * + Create(const unsigned char *Buckets, const unsigned char *const Payload, + const unsigned char *const Base, const Info &InfoObj = Info()) { + using namespace llvm::support; + assert(Buckets > Base); + assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 && + "buckets should be 4-byte aligned."); + + offset_type NumBuckets = + endian::readNext<offset_type, little, aligned>(Buckets); + offset_type NumEntries = + endian::readNext<offset_type, little, aligned>(Buckets); + return new OnDiskIterableChainedHashTable<Info>( + NumBuckets, NumEntries, Buckets, Payload, Base, InfoObj); + } +}; + +} // end namespace llvm + +#endif // LLVM_SUPPORT_ON_DISK_HASH_TABLE_H diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h index b2afe1b8e8ac..cf821f0ef4a4 100644 --- a/include/llvm/Support/Path.h +++ b/include/llvm/Support/Path.h @@ -295,6 +295,11 @@ const StringRef extension(StringRef path); /// @result true if \a value is a path separator character on the host OS bool is_separator(char value); +/// @brief Return the preferred separator for this platform. +/// +/// @result StringRef of the preferred separator, null-terminated. +const StringRef get_separator(); + /// @brief Get the typical temporary directory for the system, e.g., /// "/var/tmp" or "C:/TEMP" /// @@ -306,6 +311,12 @@ bool is_separator(char value); /// @param result Holds the resulting path name. void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result); +/// @brief Get the user's home directory. +/// +/// @param result Holds the resulting path name. +/// @result True if a home directory is set, false otherwise. +bool home_directory(SmallVectorImpl<char> &result); + /// @brief Has root name? /// /// root_name != "" diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h index 4f68fca24f38..914141ad3c4b 100644 --- a/include/llvm/Support/PrettyStackTrace.h +++ b/include/llvm/Support/PrettyStackTrace.h @@ -50,7 +50,7 @@ namespace llvm { const char *Str; public: PrettyStackTraceString(const char *str) : Str(str) {} - virtual void print(raw_ostream &OS) const LLVM_OVERRIDE; + void print(raw_ostream &OS) const override; }; /// PrettyStackTraceProgram - This object prints a specified program arguments @@ -63,7 +63,7 @@ namespace llvm { : ArgC(argc), ArgV(argv) { EnablePrettyStackTrace(); } - virtual void print(raw_ostream &OS) const LLVM_OVERRIDE; + void print(raw_ostream &OS) const override; }; } // end namespace llvm diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index 21720367199d..30973de3aac4 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -29,9 +29,9 @@ #include "llvm/ADT/Optional.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/system_error.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/TimeValue.h" +#include <system_error> namespace llvm { class StringRef; @@ -110,10 +110,10 @@ class self_process : public process { virtual ~self_process(); public: - virtual id_type get_id(); - virtual TimeValue get_user_time() const; - virtual TimeValue get_system_time() const; - virtual TimeValue get_wall_time() const; + id_type get_id() override; + TimeValue get_user_time() const override; + TimeValue get_system_time() const override; + TimeValue get_wall_time() const override; /// \name Process configuration (sysconf on POSIX) /// @{ @@ -171,10 +171,17 @@ public: // string. \arg Name is assumed to be in UTF-8 encoding too. static Optional<std::string> GetEnv(StringRef name); + /// This function searches for an existing file in the list of directories + /// in a PATH like environment variable, and returns the first file found, + /// according to the order of the entries in the PATH like environment + /// variable. + static Optional<std::string> FindInEnvPath(const std::string& EnvName, + const std::string& FileName); + /// This function returns a SmallVector containing the arguments passed from /// the operating system to the program. This function expects to be handed /// the vector passed in from main. - static error_code + static std::error_code GetArgumentVector(SmallVectorImpl<const char *> &Args, ArrayRef<const char *> ArgsFromMain, SpecificBumpPtrAllocator<char> &ArgAllocator); diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 00571a408016..51279a9b864a 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -16,10 +16,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Path.h" -#include "llvm/Support/system_error.h" +#include <system_error> namespace llvm { -class error_code; namespace sys { /// This is the OS-specific separator for PATH like environment variables: @@ -52,27 +51,31 @@ struct ProcessInfo { ProcessInfo(); }; - /// This static constructor (factory) will attempt to locate a program in - /// the operating system's file system using some pre-determined set of - /// locations to search (e.g. the PATH on Unix). Paths with slashes are - /// returned unmodified. - /// @returns A Path object initialized to the path of the program or a - /// Path object that is empty (invalid) if the program could not be found. - /// @brief Construct a Program by finding it by name. + /// This function attempts to locate a program in the operating + /// system's file system using some pre-determined set of locations to search + /// (e.g. the PATH on Unix). Paths with slashes are returned unmodified. + /// + /// It does not perform hashing as a shell would but instead stats each PATH + /// entry individually so should generally be avoided. Core LLVM library + /// functions and options should instead require fully specified paths. + /// + /// @returns A string containing the path of the program or an empty string if + /// the program could not be found. std::string FindProgramByName(const std::string& name); - // These functions change the specified standard stream (stdin, stdout, or - // stderr) to binary mode. They return errc::success if the specified stream + // These functions change the specified standard stream (stdin or stdout) to + // binary mode. They return errc::success if the specified stream // was changed. Otherwise a platform dependent error is returned. - error_code ChangeStdinToBinary(); - error_code ChangeStdoutToBinary(); - error_code ChangeStderrToBinary(); + std::error_code ChangeStdinToBinary(); + std::error_code ChangeStdoutToBinary(); /// This function executes the program using the arguments provided. The /// invoked program will inherit the stdin, stdout, and stderr file /// descriptors, the environment and other configuration settings of the /// invoking program. - /// This function waits the program to finish. + /// This function waits for the program to finish, so should be avoided in + /// library functions that aren't expected to block. Consider using + /// ExecuteNoWait() instead. /// @returns an integer result code indicating the status of the program. /// A zero or positive value indicates the result code of the program. /// -1 indicates failure to execute @@ -83,11 +86,11 @@ struct ProcessInfo { const char **args, ///< A vector of strings that are passed to the ///< program. The first element should be the name of the program. ///< The list *must* be terminated by a null char* entry. - const char **env = 0, ///< An optional vector of strings to use for + const char **env = nullptr, ///< An optional vector of strings to use for ///< the program's environment. If not provided, the current program's ///< environment will be used. - const StringRef **redirects = 0, ///< An optional array of pointers to - ///< paths. If the array is null, no redirection is done. The array + const StringRef **redirects = nullptr, ///< An optional array of pointers + ///< to paths. If the array is null, no redirection is done. The array ///< should have a size of at least three. The inferior process's ///< stdin(0), stdout(1), and stderr(2) will be redirected to the ///< corresponding paths. @@ -103,11 +106,11 @@ struct ProcessInfo { ///< of memory can be allocated by process. If memory usage will be ///< higher limit, the child is killed and this call returns. If zero ///< - no memory limit. - std::string *ErrMsg = 0, ///< If non-zero, provides a pointer to a string - ///< instance in which error messages will be returned. If the string - ///< is non-empty upon return an error occurred while invoking the + std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a + ///< string instance in which error messages will be returned. If the + ///< string is non-empty upon return an error occurred while invoking the ///< program. - bool *ExecutionFailed = 0); + bool *ExecutionFailed = nullptr); /// Similar to ExecuteAndWait, but returns immediately. /// @returns The \see ProcessInfo of the newly launced process. @@ -115,9 +118,9 @@ struct ProcessInfo { /// Wait until the process finished execution or win32 CloseHandle() API on /// ProcessInfo.ProcessHandle to avoid memory leaks. ProcessInfo - ExecuteNoWait(StringRef Program, const char **args, const char **env = 0, - const StringRef **redirects = 0, unsigned memoryLimit = 0, - std::string *ErrMsg = 0, bool *ExecutionFailed = 0); + ExecuteNoWait(StringRef Program, const char **args, const char **env = nullptr, + const StringRef **redirects = nullptr, unsigned memoryLimit = 0, + std::string *ErrMsg = nullptr, bool *ExecutionFailed = nullptr); /// Return true if the given arguments fit within system-specific /// argument length limits. @@ -138,9 +141,9 @@ struct ProcessInfo { ///< will perform a non-blocking wait on the child process. bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits ///< until child has terminated. - std::string *ErrMsg = 0 ///< If non-zero, provides a pointer to a string - ///< instance in which error messages will be returned. If the string - ///< is non-empty upon return an error occurred while invoking the + std::string *ErrMsg = nullptr ///< If non-zero, provides a pointer to a + ///< string instance in which error messages will be returned. If the + ///< string is non-empty upon return an error occurred while invoking the ///< program. ); } diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h new file mode 100644 index 000000000000..cadc713659d2 --- /dev/null +++ b/include/llvm/Support/RandomNumberGenerator.h @@ -0,0 +1,57 @@ +//==- llvm/Support/RandomNumberGenerator.h - RNG for diversity ---*- 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 abstraction for random number generation (RNG). +// Note that the current implementation is not cryptographically secure +// as it uses the C++11 <random> facilities. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RANDOMNUMBERGENERATOR_H_ +#define LLVM_SUPPORT_RANDOMNUMBERGENERATOR_H_ + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" // Needed for uint64_t on Windows. +#include <random> + +namespace llvm { + +/// A random number generator. +/// Instances of this class should not be shared across threads. +class RandomNumberGenerator { +public: + /// Seeds and salts the underlying RNG engine. The salt of type StringRef + /// is passed into the constructor. The seed can be set on the command + /// line via -rng-seed=<uint64>. + /// The reason for the salt is to ensure different random streams even if + /// the same seed is used for multiple invocations of the compiler. + /// A good salt value should add additional entropy and be constant across + /// different machines (i.e., no paths) to allow for reproducible builds. + /// An instance of this class can be retrieved from the current Module. + /// \see Module::getRNG + RandomNumberGenerator(StringRef Salt); + + /// Returns a random number in the range [0, Max). + uint64_t next(uint64_t Max); + +private: + // 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000 + // http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine + std::mt19937_64 Generator; + + // Noncopyable. + RandomNumberGenerator(const RandomNumberGenerator &other) + LLVM_DELETED_FUNCTION; + RandomNumberGenerator & + operator=(const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION; +}; +} + +#endif diff --git a/include/llvm/Support/Recycler.h b/include/llvm/Support/Recycler.h index bcc561db2d5c..e97f36a735fd 100644 --- a/include/llvm/Support/Recycler.h +++ b/include/llvm/Support/Recycler.h @@ -17,13 +17,12 @@ #include "llvm/ADT/ilist.h" #include "llvm/Support/AlignOf.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/ErrorHandling.h" #include <cassert> namespace llvm { -class BumpPtrAllocator; - /// PrintRecyclingAllocatorStats - Helper for RecyclingAllocator for /// printing statistics. /// @@ -100,10 +99,10 @@ public: template<class SubClass, class AllocatorType> SubClass *Allocate(AllocatorType &Allocator) { - assert(sizeof(SubClass) <= Size && - "Recycler allocation size is less than object size!"); - assert(AlignOf<SubClass>::Alignment <= Align && - "Recycler allocation alignment is less than object alignment!"); + static_assert(AlignOf<SubClass>::Alignment <= Align, + "Recycler allocation alignment is less than object align!"); + static_assert(sizeof(SubClass) <= Size, + "Recycler allocation size is less than object size!"); return !FreeList.empty() ? reinterpret_cast<SubClass *>(FreeList.remove(FreeList.begin())) : static_cast<SubClass *>(Allocator.Allocate(Size, Align)); diff --git a/include/llvm/Support/Regex.h b/include/llvm/Support/Regex.h index 3d071bedbd86..bf533ca1aa60 100644 --- a/include/llvm/Support/Regex.h +++ b/include/llvm/Support/Regex.h @@ -17,6 +17,7 @@ #ifndef LLVM_SUPPORT_REGEX_H #define LLVM_SUPPORT_REGEX_H +#include "llvm/Support/Compiler.h" #include <string> struct llvm_regex; @@ -45,6 +46,17 @@ namespace llvm { /// Compiles the given regular expression \p Regex. Regex(StringRef Regex, unsigned Flags = NoFlags); + Regex(const Regex &) LLVM_DELETED_FUNCTION; + Regex &operator=(Regex regex) { + std::swap(preg, regex.preg); + std::swap(error, regex.error); + return *this; + } + Regex(Regex &®ex) { + preg = regex.preg; + error = regex.error; + regex.preg = nullptr; + } ~Regex(); /// isValid - returns the error encountered during regex compilation, or @@ -63,7 +75,7 @@ namespace llvm { /// the first group is always the entire pattern. /// /// This returns true on a successful match. - bool match(StringRef String, SmallVectorImpl<StringRef> *Matches = 0); + bool match(StringRef String, SmallVectorImpl<StringRef> *Matches = nullptr); /// sub - Return the result of replacing the first match of the regex in /// \p String with the \p Repl string. Backreferences like "\0" in the @@ -75,12 +87,16 @@ namespace llvm { /// \param Error If non-null, any errors in the substitution (invalid /// backreferences, trailing backslashes) will be recorded as a non-empty /// string. - std::string sub(StringRef Repl, StringRef String, std::string *Error = 0); + std::string sub(StringRef Repl, StringRef String, + std::string *Error = nullptr); /// \brief If this function returns true, ^Str$ is an extended regular /// expression that matches Str and only Str. static bool isLiteralERE(StringRef Str); + /// \brief Turn String into a regex by escaping its special characters. + static std::string escape(StringRef String); + private: struct llvm_regex *preg; int error; diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h index 073becd586aa..b0c2e899855d 100644 --- a/include/llvm/Support/Registry.h +++ b/include/llvm/Support/Registry.h @@ -14,24 +14,27 @@ #ifndef LLVM_SUPPORT_REGISTRY_H #define LLVM_SUPPORT_REGISTRY_H +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" +#include <memory> + namespace llvm { /// A simple registry entry which provides only a name, description, and /// no-argument constructor. template <typename T> class SimpleRegistryEntry { const char *Name, *Desc; - T *(*Ctor)(); + std::unique_ptr<T> (*Ctor)(); public: - SimpleRegistryEntry(const char *N, const char *D, T *(*C)()) + SimpleRegistryEntry(const char *N, const char *D, std::unique_ptr<T> (*C)()) : Name(N), Desc(D), Ctor(C) {} const char *getName() const { return Name; } const char *getDesc() const { return Desc; } - T *instantiate() const { return Ctor(); } + std::unique_ptr<T> instantiate() const { return Ctor(); } }; @@ -88,7 +91,7 @@ namespace llvm { const entry& Val; public: - node(const entry& V) : Next(0), Val(V) { + node(const entry& V) : Next(nullptr), Val(V) { if (Tail) Tail->Next = this; else @@ -116,7 +119,7 @@ namespace llvm { }; static iterator begin() { return iterator(Head); } - static iterator end() { return iterator(0); } + static iterator end() { return iterator(nullptr); } /// Abstract base class for registry listeners, which are informed when new @@ -195,7 +198,7 @@ namespace llvm { entry Entry; node Node; - static T *CtorFn() { return new V(); } + static std::unique_ptr<T> CtorFn() { return make_unique<V>(); } public: Add(const char *Name, const char *Desc) diff --git a/include/llvm/Support/SMLoc.h b/include/llvm/Support/SMLoc.h index 0906471f624e..d5b4c57a8fd6 100644 --- a/include/llvm/Support/SMLoc.h +++ b/include/llvm/Support/SMLoc.h @@ -23,9 +23,9 @@ namespace llvm { class SMLoc { const char *Ptr; public: - SMLoc() : Ptr(0) {} + SMLoc() : Ptr(nullptr) {} - bool isValid() const { return Ptr != 0; } + bool isValid() const { return Ptr != nullptr; } bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; } bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; } diff --git a/include/llvm/Support/SaveAndRestore.h b/include/llvm/Support/SaveAndRestore.h index 6330becda9f6..ef154ac9c913 100644 --- a/include/llvm/Support/SaveAndRestore.h +++ b/include/llvm/Support/SaveAndRestore.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file provides utility classes that uses RAII to save and restore -// values. -// +/// +/// \file +/// This file provides utility classes that use RAII to save and restore +/// values. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_SAVEANDRESTORE_H @@ -17,31 +18,32 @@ namespace llvm { -// SaveAndRestore - A utility class that uses RAII to save and restore -// the value of a variable. -template<typename T> -struct SaveAndRestore { - SaveAndRestore(T& x) : X(x), old_value(x) {} - SaveAndRestore(T& x, const T &new_value) : X(x), old_value(x) { - X = new_value; +/// A utility class that uses RAII to save and restore the value of a variable. +template <typename T> struct SaveAndRestore { + SaveAndRestore(T &X) : X(X), OldValue(X) {} + SaveAndRestore(T &X, const T &NewValue) : X(X), OldValue(X) { + X = NewValue; } - ~SaveAndRestore() { X = old_value; } - T get() { return old_value; } + ~SaveAndRestore() { X = OldValue; } + T get() { return OldValue; } + private: - T& X; - T old_value; + T &X; + T OldValue; }; -// SaveOr - Similar to SaveAndRestore. Operates only on bools; the old -// value of a variable is saved, and during the dstor the old value is -// or'ed with the new value. +/// Similar to \c SaveAndRestore. Operates only on bools; the old value of a +/// variable is saved, and during the dstor the old value is or'ed with the new +/// value. struct SaveOr { - SaveOr(bool& x) : X(x), old_value(x) { x = false; } - ~SaveOr() { X |= old_value; } + SaveOr(bool &X) : X(X), OldValue(X) { X = false; } + ~SaveOr() { X |= OldValue; } + private: - bool& X; - const bool old_value; + bool &X; + const bool OldValue; }; -} +} // namespace llvm + #endif diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h new file mode 100644 index 000000000000..2bd7e741dd28 --- /dev/null +++ b/include/llvm/Support/ScaledNumber.h @@ -0,0 +1,897 @@ +//===- llvm/Support/ScaledNumber.h - Support for scaled numbers -*- 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 functions (and a class) useful for working with scaled +// numbers -- in particular, pairs of integers where one represents digits and +// another represents a scale. The functions are helpers and live in the +// namespace ScaledNumbers. The class ScaledNumber is useful for modelling +// certain cost metrics that need simple, integer-like semantics that are easy +// to reason about. +// +// These might remind you of soft-floats. If you want one of those, you're in +// the wrong place. Look at include/llvm/ADT/APFloat.h instead. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SCALEDNUMBER_H +#define LLVM_SUPPORT_SCALEDNUMBER_H + +#include "llvm/Support/MathExtras.h" + +#include <algorithm> +#include <cstdint> +#include <limits> +#include <string> +#include <tuple> +#include <utility> + +namespace llvm { +namespace ScaledNumbers { + +/// \brief Maximum scale; same as APFloat for easy debug printing. +const int32_t MaxScale = 16383; + +/// \brief Maximum scale; same as APFloat for easy debug printing. +const int32_t MinScale = -16382; + +/// \brief Get the width of a number. +template <class DigitsT> inline int getWidth() { return sizeof(DigitsT) * 8; } + +/// \brief Conditionally round up a scaled number. +/// +/// Given \c Digits and \c Scale, round up iff \c ShouldRound is \c true. +/// Always returns \c Scale unless there's an overflow, in which case it +/// returns \c 1+Scale. +/// +/// \pre adding 1 to \c Scale will not overflow INT16_MAX. +template <class DigitsT> +inline std::pair<DigitsT, int16_t> getRounded(DigitsT Digits, int16_t Scale, + bool ShouldRound) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + if (ShouldRound) + if (!++Digits) + // Overflow. + return std::make_pair(DigitsT(1) << (getWidth<DigitsT>() - 1), Scale + 1); + return std::make_pair(Digits, Scale); +} + +/// \brief Convenience helper for 32-bit rounding. +inline std::pair<uint32_t, int16_t> getRounded32(uint32_t Digits, int16_t Scale, + bool ShouldRound) { + return getRounded(Digits, Scale, ShouldRound); +} + +/// \brief Convenience helper for 64-bit rounding. +inline std::pair<uint64_t, int16_t> getRounded64(uint64_t Digits, int16_t Scale, + bool ShouldRound) { + return getRounded(Digits, Scale, ShouldRound); +} + +/// \brief Adjust a 64-bit scaled number down to the appropriate width. +/// +/// \pre Adding 64 to \c Scale will not overflow INT16_MAX. +template <class DigitsT> +inline std::pair<DigitsT, int16_t> getAdjusted(uint64_t Digits, + int16_t Scale = 0) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + const int Width = getWidth<DigitsT>(); + if (Width == 64 || Digits <= std::numeric_limits<DigitsT>::max()) + return std::make_pair(Digits, Scale); + + // Shift right and round. + int Shift = 64 - Width - countLeadingZeros(Digits); + return getRounded<DigitsT>(Digits >> Shift, Scale + Shift, + Digits & (UINT64_C(1) << (Shift - 1))); +} + +/// \brief Convenience helper for adjusting to 32 bits. +inline std::pair<uint32_t, int16_t> getAdjusted32(uint64_t Digits, + int16_t Scale = 0) { + return getAdjusted<uint32_t>(Digits, Scale); +} + +/// \brief Convenience helper for adjusting to 64 bits. +inline std::pair<uint64_t, int16_t> getAdjusted64(uint64_t Digits, + int16_t Scale = 0) { + return getAdjusted<uint64_t>(Digits, Scale); +} + +/// \brief Multiply two 64-bit integers to create a 64-bit scaled number. +/// +/// Implemented with four 64-bit integer multiplies. +std::pair<uint64_t, int16_t> multiply64(uint64_t LHS, uint64_t RHS); + +/// \brief Multiply two 32-bit integers to create a 32-bit scaled number. +/// +/// Implemented with one 64-bit integer multiply. +template <class DigitsT> +inline std::pair<DigitsT, int16_t> getProduct(DigitsT LHS, DigitsT RHS) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + if (getWidth<DigitsT>() <= 32 || (LHS <= UINT32_MAX && RHS <= UINT32_MAX)) + return getAdjusted<DigitsT>(uint64_t(LHS) * RHS); + + return multiply64(LHS, RHS); +} + +/// \brief Convenience helper for 32-bit product. +inline std::pair<uint32_t, int16_t> getProduct32(uint32_t LHS, uint32_t RHS) { + return getProduct(LHS, RHS); +} + +/// \brief Convenience helper for 64-bit product. +inline std::pair<uint64_t, int16_t> getProduct64(uint64_t LHS, uint64_t RHS) { + return getProduct(LHS, RHS); +} + +/// \brief Divide two 64-bit integers to create a 64-bit scaled number. +/// +/// Implemented with long division. +/// +/// \pre \c Dividend and \c Divisor are non-zero. +std::pair<uint64_t, int16_t> divide64(uint64_t Dividend, uint64_t Divisor); + +/// \brief Divide two 32-bit integers to create a 32-bit scaled number. +/// +/// Implemented with one 64-bit integer divide/remainder pair. +/// +/// \pre \c Dividend and \c Divisor are non-zero. +std::pair<uint32_t, int16_t> divide32(uint32_t Dividend, uint32_t Divisor); + +/// \brief Divide two 32-bit numbers to create a 32-bit scaled number. +/// +/// Implemented with one 64-bit integer divide/remainder pair. +/// +/// Returns \c (DigitsT_MAX, MaxScale) for divide-by-zero (0 for 0/0). +template <class DigitsT> +std::pair<DigitsT, int16_t> getQuotient(DigitsT Dividend, DigitsT Divisor) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + static_assert(sizeof(DigitsT) == 4 || sizeof(DigitsT) == 8, + "expected 32-bit or 64-bit digits"); + + // Check for zero. + if (!Dividend) + return std::make_pair(0, 0); + if (!Divisor) + return std::make_pair(std::numeric_limits<DigitsT>::max(), MaxScale); + + if (getWidth<DigitsT>() == 64) + return divide64(Dividend, Divisor); + return divide32(Dividend, Divisor); +} + +/// \brief Convenience helper for 32-bit quotient. +inline std::pair<uint32_t, int16_t> getQuotient32(uint32_t Dividend, + uint32_t Divisor) { + return getQuotient(Dividend, Divisor); +} + +/// \brief Convenience helper for 64-bit quotient. +inline std::pair<uint64_t, int16_t> getQuotient64(uint64_t Dividend, + uint64_t Divisor) { + return getQuotient(Dividend, Divisor); +} + +/// \brief Implementation of getLg() and friends. +/// +/// Returns the rounded lg of \c Digits*2^Scale and an int specifying whether +/// this was rounded up (1), down (-1), or exact (0). +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template <class DigitsT> +inline std::pair<int32_t, int> getLgImpl(DigitsT Digits, int16_t Scale) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + if (!Digits) + return std::make_pair(INT32_MIN, 0); + + // Get the floor of the lg of Digits. + int32_t LocalFloor = sizeof(Digits) * 8 - countLeadingZeros(Digits) - 1; + + // Get the actual floor. + int32_t Floor = Scale + LocalFloor; + if (Digits == UINT64_C(1) << LocalFloor) + return std::make_pair(Floor, 0); + + // Round based on the next digit. + assert(LocalFloor >= 1); + bool Round = Digits & UINT64_C(1) << (LocalFloor - 1); + return std::make_pair(Floor + Round, Round ? 1 : -1); +} + +/// \brief Get the lg (rounded) of a scaled number. +/// +/// Get the lg of \c Digits*2^Scale. +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template <class DigitsT> int32_t getLg(DigitsT Digits, int16_t Scale) { + return getLgImpl(Digits, Scale).first; +} + +/// \brief Get the lg floor of a scaled number. +/// +/// Get the floor of the lg of \c Digits*2^Scale. +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template <class DigitsT> int32_t getLgFloor(DigitsT Digits, int16_t Scale) { + auto Lg = getLgImpl(Digits, Scale); + return Lg.first - (Lg.second > 0); +} + +/// \brief Get the lg ceiling of a scaled number. +/// +/// Get the ceiling of the lg of \c Digits*2^Scale. +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template <class DigitsT> int32_t getLgCeiling(DigitsT Digits, int16_t Scale) { + auto Lg = getLgImpl(Digits, Scale); + return Lg.first + (Lg.second < 0); +} + +/// \brief Implementation for comparing scaled numbers. +/// +/// Compare two 64-bit numbers with different scales. Given that the scale of +/// \c L is higher than that of \c R by \c ScaleDiff, compare them. Return -1, +/// 1, and 0 for less than, greater than, and equal, respectively. +/// +/// \pre 0 <= ScaleDiff < 64. +int compareImpl(uint64_t L, uint64_t R, int ScaleDiff); + +/// \brief Compare two scaled numbers. +/// +/// Compare two scaled numbers. Returns 0 for equal, -1 for less than, and 1 +/// for greater than. +template <class DigitsT> +int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + // Check for zero. + if (!LDigits) + return RDigits ? -1 : 0; + if (!RDigits) + return 1; + + // Check for the scale. Use getLgFloor to be sure that the scale difference + // is always lower than 64. + int32_t lgL = getLgFloor(LDigits, LScale), lgR = getLgFloor(RDigits, RScale); + if (lgL != lgR) + return lgL < lgR ? -1 : 1; + + // Compare digits. + if (LScale < RScale) + return compareImpl(LDigits, RDigits, RScale - LScale); + + return -compareImpl(RDigits, LDigits, LScale - RScale); +} + +/// \brief Match scales of two numbers. +/// +/// Given two scaled numbers, match up their scales. Change the digits and +/// scales in place. Shift the digits as necessary to form equivalent numbers, +/// losing precision only when necessary. +/// +/// If the output value of \c LDigits (\c RDigits) is \c 0, the output value of +/// \c LScale (\c RScale) is unspecified. +/// +/// As a convenience, returns the matching scale. If the output value of one +/// number is zero, returns the scale of the other. If both are zero, which +/// scale is returned is unspecifed. +template <class DigitsT> +int16_t matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits, + int16_t &RScale) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + if (LScale < RScale) + // Swap arguments. + return matchScales(RDigits, RScale, LDigits, LScale); + if (!LDigits) + return RScale; + if (!RDigits || LScale == RScale) + return LScale; + + // Now LScale > RScale. Get the difference. + int32_t ScaleDiff = int32_t(LScale) - RScale; + if (ScaleDiff >= 2 * getWidth<DigitsT>()) { + // Don't bother shifting. RDigits will get zero-ed out anyway. + RDigits = 0; + return LScale; + } + + // Shift LDigits left as much as possible, then shift RDigits right. + int32_t ShiftL = std::min<int32_t>(countLeadingZeros(LDigits), ScaleDiff); + assert(ShiftL < getWidth<DigitsT>() && "can't shift more than width"); + + int32_t ShiftR = ScaleDiff - ShiftL; + if (ShiftR >= getWidth<DigitsT>()) { + // Don't bother shifting. RDigits will get zero-ed out anyway. + RDigits = 0; + return LScale; + } + + LDigits <<= ShiftL; + RDigits >>= ShiftR; + + LScale -= ShiftL; + RScale += ShiftR; + assert(LScale == RScale && "scales should match"); + return LScale; +} + +/// \brief Get the sum of two scaled numbers. +/// +/// Get the sum of two scaled numbers with as much precision as possible. +/// +/// \pre Adding 1 to \c LScale (or \c RScale) will not overflow INT16_MAX. +template <class DigitsT> +std::pair<DigitsT, int16_t> getSum(DigitsT LDigits, int16_t LScale, + DigitsT RDigits, int16_t RScale) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + // Check inputs up front. This is only relevent if addition overflows, but + // testing here should catch more bugs. + assert(LScale < INT16_MAX && "scale too large"); + assert(RScale < INT16_MAX && "scale too large"); + + // Normalize digits to match scales. + int16_t Scale = matchScales(LDigits, LScale, RDigits, RScale); + + // Compute sum. + DigitsT Sum = LDigits + RDigits; + if (Sum >= RDigits) + return std::make_pair(Sum, Scale); + + // Adjust sum after arithmetic overflow. + DigitsT HighBit = DigitsT(1) << (getWidth<DigitsT>() - 1); + return std::make_pair(HighBit | Sum >> 1, Scale + 1); +} + +/// \brief Convenience helper for 32-bit sum. +inline std::pair<uint32_t, int16_t> getSum32(uint32_t LDigits, int16_t LScale, + uint32_t RDigits, int16_t RScale) { + return getSum(LDigits, LScale, RDigits, RScale); +} + +/// \brief Convenience helper for 64-bit sum. +inline std::pair<uint64_t, int16_t> getSum64(uint64_t LDigits, int16_t LScale, + uint64_t RDigits, int16_t RScale) { + return getSum(LDigits, LScale, RDigits, RScale); +} + +/// \brief Get the difference of two scaled numbers. +/// +/// Get LHS minus RHS with as much precision as possible. +/// +/// Returns \c (0, 0) if the RHS is larger than the LHS. +template <class DigitsT> +std::pair<DigitsT, int16_t> getDifference(DigitsT LDigits, int16_t LScale, + DigitsT RDigits, int16_t RScale) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + // Normalize digits to match scales. + const DigitsT SavedRDigits = RDigits; + const int16_t SavedRScale = RScale; + matchScales(LDigits, LScale, RDigits, RScale); + + // Compute difference. + if (LDigits <= RDigits) + return std::make_pair(0, 0); + if (RDigits || !SavedRDigits) + return std::make_pair(LDigits - RDigits, LScale); + + // Check if RDigits just barely lost its last bit. E.g., for 32-bit: + // + // 1*2^32 - 1*2^0 == 0xffffffff != 1*2^32 + const auto RLgFloor = getLgFloor(SavedRDigits, SavedRScale); + if (!compare(LDigits, LScale, DigitsT(1), RLgFloor + getWidth<DigitsT>())) + return std::make_pair(std::numeric_limits<DigitsT>::max(), RLgFloor); + + return std::make_pair(LDigits, LScale); +} + +/// \brief Convenience helper for 32-bit difference. +inline std::pair<uint32_t, int16_t> getDifference32(uint32_t LDigits, + int16_t LScale, + uint32_t RDigits, + int16_t RScale) { + return getDifference(LDigits, LScale, RDigits, RScale); +} + +/// \brief Convenience helper for 64-bit difference. +inline std::pair<uint64_t, int16_t> getDifference64(uint64_t LDigits, + int16_t LScale, + uint64_t RDigits, + int16_t RScale) { + return getDifference(LDigits, LScale, RDigits, RScale); +} + +} // end namespace ScaledNumbers +} // end namespace llvm + +namespace llvm { + +class raw_ostream; +class ScaledNumberBase { +public: + static const int DefaultPrecision = 10; + + static void dump(uint64_t D, int16_t E, int Width); + static raw_ostream &print(raw_ostream &OS, uint64_t D, int16_t E, int Width, + unsigned Precision); + static std::string toString(uint64_t D, int16_t E, int Width, + unsigned Precision); + static int countLeadingZeros32(uint32_t N) { return countLeadingZeros(N); } + static int countLeadingZeros64(uint64_t N) { return countLeadingZeros(N); } + static uint64_t getHalf(uint64_t N) { return (N >> 1) + (N & 1); } + + static std::pair<uint64_t, bool> splitSigned(int64_t N) { + if (N >= 0) + return std::make_pair(N, false); + uint64_t Unsigned = N == INT64_MIN ? UINT64_C(1) << 63 : uint64_t(-N); + return std::make_pair(Unsigned, true); + } + static int64_t joinSigned(uint64_t U, bool IsNeg) { + if (U > uint64_t(INT64_MAX)) + return IsNeg ? INT64_MIN : INT64_MAX; + return IsNeg ? -int64_t(U) : int64_t(U); + } +}; + +/// \brief Simple representation of a scaled number. +/// +/// ScaledNumber is a number represented by digits and a scale. It uses simple +/// saturation arithmetic and every operation is well-defined for every value. +/// It's somewhat similar in behaviour to a soft-float, but is *not* a +/// replacement for one. If you're doing numerics, look at \a APFloat instead. +/// Nevertheless, we've found these semantics useful for modelling certain cost +/// metrics. +/// +/// The number is split into a signed scale and unsigned digits. The number +/// represented is \c getDigits()*2^getScale(). In this way, the digits are +/// much like the mantissa in the x87 long double, but there is no canonical +/// form so the same number can be represented by many bit representations. +/// +/// ScaledNumber is templated on the underlying integer type for digits, which +/// is expected to be unsigned. +/// +/// Unlike APFloat, ScaledNumber does not model architecture floating point +/// behaviour -- while this might make it a little faster and easier to reason +/// about, it certainly makes it more dangerous for general numerics. +/// +/// ScaledNumber is totally ordered. However, there is no canonical form, so +/// there are multiple representations of most scalars. E.g.: +/// +/// ScaledNumber(8u, 0) == ScaledNumber(4u, 1) +/// ScaledNumber(4u, 1) == ScaledNumber(2u, 2) +/// ScaledNumber(2u, 2) == ScaledNumber(1u, 3) +/// +/// ScaledNumber implements most arithmetic operations. Precision is kept +/// where possible. Uses simple saturation arithmetic, so that operations +/// saturate to 0.0 or getLargest() rather than under or overflowing. It has +/// some extra arithmetic for unit inversion. 0.0/0.0 is defined to be 0.0. +/// Any other division by 0.0 is defined to be getLargest(). +/// +/// As a convenience for modifying the exponent, left and right shifting are +/// both implemented, and both interpret negative shifts as positive shifts in +/// the opposite direction. +/// +/// Scales are limited to the range accepted by x87 long double. This makes +/// it trivial to add functionality to convert to APFloat (this is already +/// relied on for the implementation of printing). +/// +/// Possible (and conflicting) future directions: +/// +/// 1. Turn this into a wrapper around \a APFloat. +/// 2. Share the algorithm implementations with \a APFloat. +/// 3. Allow \a ScaledNumber to represent a signed number. +template <class DigitsT> class ScaledNumber : ScaledNumberBase { +public: + static_assert(!std::numeric_limits<DigitsT>::is_signed, + "only unsigned floats supported"); + + typedef DigitsT DigitsType; + +private: + typedef std::numeric_limits<DigitsType> DigitsLimits; + + static const int Width = sizeof(DigitsType) * 8; + static_assert(Width <= 64, "invalid integer width for digits"); + +private: + DigitsType Digits; + int16_t Scale; + +public: + ScaledNumber() : Digits(0), Scale(0) {} + + ScaledNumber(DigitsType Digits, int16_t Scale) + : Digits(Digits), Scale(Scale) {} + +private: + ScaledNumber(const std::pair<uint64_t, int16_t> &X) + : Digits(X.first), Scale(X.second) {} + +public: + static ScaledNumber getZero() { return ScaledNumber(0, 0); } + static ScaledNumber getOne() { return ScaledNumber(1, 0); } + static ScaledNumber getLargest() { + return ScaledNumber(DigitsLimits::max(), ScaledNumbers::MaxScale); + } + static ScaledNumber get(uint64_t N) { return adjustToWidth(N, 0); } + static ScaledNumber getInverse(uint64_t N) { + return get(N).invert(); + } + static ScaledNumber getFraction(DigitsType N, DigitsType D) { + return getQuotient(N, D); + } + + int16_t getScale() const { return Scale; } + DigitsType getDigits() const { return Digits; } + + /// \brief Convert to the given integer type. + /// + /// Convert to \c IntT using simple saturating arithmetic, truncating if + /// necessary. + template <class IntT> IntT toInt() const; + + bool isZero() const { return !Digits; } + bool isLargest() const { return *this == getLargest(); } + bool isOne() const { + if (Scale > 0 || Scale <= -Width) + return false; + return Digits == DigitsType(1) << -Scale; + } + + /// \brief The log base 2, rounded. + /// + /// Get the lg of the scalar. lg 0 is defined to be INT32_MIN. + int32_t lg() const { return ScaledNumbers::getLg(Digits, Scale); } + + /// \brief The log base 2, rounded towards INT32_MIN. + /// + /// Get the lg floor. lg 0 is defined to be INT32_MIN. + int32_t lgFloor() const { return ScaledNumbers::getLgFloor(Digits, Scale); } + + /// \brief The log base 2, rounded towards INT32_MAX. + /// + /// Get the lg ceiling. lg 0 is defined to be INT32_MIN. + int32_t lgCeiling() const { + return ScaledNumbers::getLgCeiling(Digits, Scale); + } + + bool operator==(const ScaledNumber &X) const { return compare(X) == 0; } + bool operator<(const ScaledNumber &X) const { return compare(X) < 0; } + bool operator!=(const ScaledNumber &X) const { return compare(X) != 0; } + bool operator>(const ScaledNumber &X) const { return compare(X) > 0; } + bool operator<=(const ScaledNumber &X) const { return compare(X) <= 0; } + bool operator>=(const ScaledNumber &X) const { return compare(X) >= 0; } + + bool operator!() const { return isZero(); } + + /// \brief Convert to a decimal representation in a string. + /// + /// Convert to a string. Uses scientific notation for very large/small + /// numbers. Scientific notation is used roughly for numbers outside of the + /// range 2^-64 through 2^64. + /// + /// \c Precision indicates the number of decimal digits of precision to use; + /// 0 requests the maximum available. + /// + /// As a special case to make debugging easier, if the number is small enough + /// to convert without scientific notation and has more than \c Precision + /// digits before the decimal place, it's printed accurately to the first + /// digit past zero. E.g., assuming 10 digits of precision: + /// + /// 98765432198.7654... => 98765432198.8 + /// 8765432198.7654... => 8765432198.8 + /// 765432198.7654... => 765432198.8 + /// 65432198.7654... => 65432198.77 + /// 5432198.7654... => 5432198.765 + std::string toString(unsigned Precision = DefaultPrecision) { + return ScaledNumberBase::toString(Digits, Scale, Width, Precision); + } + + /// \brief Print a decimal representation. + /// + /// Print a string. See toString for documentation. + raw_ostream &print(raw_ostream &OS, + unsigned Precision = DefaultPrecision) const { + return ScaledNumberBase::print(OS, Digits, Scale, Width, Precision); + } + void dump() const { return ScaledNumberBase::dump(Digits, Scale, Width); } + + ScaledNumber &operator+=(const ScaledNumber &X) { + std::tie(Digits, Scale) = + ScaledNumbers::getSum(Digits, Scale, X.Digits, X.Scale); + // Check for exponent past MaxScale. + if (Scale > ScaledNumbers::MaxScale) + *this = getLargest(); + return *this; + } + ScaledNumber &operator-=(const ScaledNumber &X) { + std::tie(Digits, Scale) = + ScaledNumbers::getDifference(Digits, Scale, X.Digits, X.Scale); + return *this; + } + ScaledNumber &operator*=(const ScaledNumber &X); + ScaledNumber &operator/=(const ScaledNumber &X); + ScaledNumber &operator<<=(int16_t Shift) { + shiftLeft(Shift); + return *this; + } + ScaledNumber &operator>>=(int16_t Shift) { + shiftRight(Shift); + return *this; + } + +private: + void shiftLeft(int32_t Shift); + void shiftRight(int32_t Shift); + + /// \brief Adjust two floats to have matching exponents. + /// + /// Adjust \c this and \c X to have matching exponents. Returns the new \c X + /// by value. Does nothing if \a isZero() for either. + /// + /// The value that compares smaller will lose precision, and possibly become + /// \a isZero(). + ScaledNumber matchScales(ScaledNumber X) { + ScaledNumbers::matchScales(Digits, Scale, X.Digits, X.Scale); + return X; + } + +public: + /// \brief Scale a large number accurately. + /// + /// Scale N (multiply it by this). Uses full precision multiplication, even + /// if Width is smaller than 64, so information is not lost. + uint64_t scale(uint64_t N) const; + uint64_t scaleByInverse(uint64_t N) const { + // TODO: implement directly, rather than relying on inverse. Inverse is + // expensive. + return inverse().scale(N); + } + int64_t scale(int64_t N) const { + std::pair<uint64_t, bool> Unsigned = splitSigned(N); + return joinSigned(scale(Unsigned.first), Unsigned.second); + } + int64_t scaleByInverse(int64_t N) const { + std::pair<uint64_t, bool> Unsigned = splitSigned(N); + return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second); + } + + int compare(const ScaledNumber &X) const { + return ScaledNumbers::compare(Digits, Scale, X.Digits, X.Scale); + } + int compareTo(uint64_t N) const { + ScaledNumber Scaled = get(N); + int Compare = compare(Scaled); + if (Width == 64 || Compare != 0) + return Compare; + + // Check for precision loss. We know *this == RoundTrip. + uint64_t RoundTrip = Scaled.template toInt<uint64_t>(); + return N == RoundTrip ? 0 : RoundTrip < N ? -1 : 1; + } + int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); } + + ScaledNumber &invert() { return *this = ScaledNumber::get(1) / *this; } + ScaledNumber inverse() const { return ScaledNumber(*this).invert(); } + +private: + static ScaledNumber getProduct(DigitsType LHS, DigitsType RHS) { + return ScaledNumbers::getProduct(LHS, RHS); + } + static ScaledNumber getQuotient(DigitsType Dividend, DigitsType Divisor) { + return ScaledNumbers::getQuotient(Dividend, Divisor); + } + + static int countLeadingZerosWidth(DigitsType Digits) { + if (Width == 64) + return countLeadingZeros64(Digits); + if (Width == 32) + return countLeadingZeros32(Digits); + return countLeadingZeros32(Digits) + Width - 32; + } + + /// \brief Adjust a number to width, rounding up if necessary. + /// + /// Should only be called for \c Shift close to zero. + /// + /// \pre Shift >= MinScale && Shift + 64 <= MaxScale. + static ScaledNumber adjustToWidth(uint64_t N, int32_t Shift) { + assert(Shift >= ScaledNumbers::MinScale && "Shift should be close to 0"); + assert(Shift <= ScaledNumbers::MaxScale - 64 && + "Shift should be close to 0"); + auto Adjusted = ScaledNumbers::getAdjusted<DigitsT>(N, Shift); + return Adjusted; + } + + static ScaledNumber getRounded(ScaledNumber P, bool Round) { + // Saturate. + if (P.isLargest()) + return P; + + return ScaledNumbers::getRounded(P.Digits, P.Scale, Round); + } +}; + +#define SCALED_NUMBER_BOP(op, base) \ + template <class DigitsT> \ + ScaledNumber<DigitsT> operator op(const ScaledNumber<DigitsT> &L, \ + const ScaledNumber<DigitsT> &R) { \ + return ScaledNumber<DigitsT>(L) base R; \ + } +SCALED_NUMBER_BOP(+, += ) +SCALED_NUMBER_BOP(-, -= ) +SCALED_NUMBER_BOP(*, *= ) +SCALED_NUMBER_BOP(/, /= ) +SCALED_NUMBER_BOP(<<, <<= ) +SCALED_NUMBER_BOP(>>, >>= ) +#undef SCALED_NUMBER_BOP + +template <class DigitsT> +raw_ostream &operator<<(raw_ostream &OS, const ScaledNumber<DigitsT> &X) { + return X.print(OS, 10); +} + +#define SCALED_NUMBER_COMPARE_TO_TYPE(op, T1, T2) \ + template <class DigitsT> \ + bool operator op(const ScaledNumber<DigitsT> &L, T1 R) { \ + return L.compareTo(T2(R)) op 0; \ + } \ + template <class DigitsT> \ + bool operator op(T1 L, const ScaledNumber<DigitsT> &R) { \ + return 0 op R.compareTo(T2(L)); \ + } +#define SCALED_NUMBER_COMPARE_TO(op) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, int64_t, int64_t) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, int32_t, int64_t) +SCALED_NUMBER_COMPARE_TO(< ) +SCALED_NUMBER_COMPARE_TO(> ) +SCALED_NUMBER_COMPARE_TO(== ) +SCALED_NUMBER_COMPARE_TO(!= ) +SCALED_NUMBER_COMPARE_TO(<= ) +SCALED_NUMBER_COMPARE_TO(>= ) +#undef SCALED_NUMBER_COMPARE_TO +#undef SCALED_NUMBER_COMPARE_TO_TYPE + +template <class DigitsT> +uint64_t ScaledNumber<DigitsT>::scale(uint64_t N) const { + if (Width == 64 || N <= DigitsLimits::max()) + return (get(N) * *this).template toInt<uint64_t>(); + + // Defer to the 64-bit version. + return ScaledNumber<uint64_t>(Digits, Scale).scale(N); +} + +template <class DigitsT> +template <class IntT> +IntT ScaledNumber<DigitsT>::toInt() const { + typedef std::numeric_limits<IntT> Limits; + if (*this < 1) + return 0; + if (*this >= Limits::max()) + return Limits::max(); + + IntT N = Digits; + if (Scale > 0) { + assert(size_t(Scale) < sizeof(IntT) * 8); + return N << Scale; + } + if (Scale < 0) { + assert(size_t(-Scale) < sizeof(IntT) * 8); + return N >> -Scale; + } + return N; +} + +template <class DigitsT> +ScaledNumber<DigitsT> &ScaledNumber<DigitsT>:: +operator*=(const ScaledNumber &X) { + if (isZero()) + return *this; + if (X.isZero()) + return *this = X; + + // Save the exponents. + int32_t Scales = int32_t(Scale) + int32_t(X.Scale); + + // Get the raw product. + *this = getProduct(Digits, X.Digits); + + // Combine with exponents. + return *this <<= Scales; +} +template <class DigitsT> +ScaledNumber<DigitsT> &ScaledNumber<DigitsT>:: +operator/=(const ScaledNumber &X) { + if (isZero()) + return *this; + if (X.isZero()) + return *this = getLargest(); + + // Save the exponents. + int32_t Scales = int32_t(Scale) - int32_t(X.Scale); + + // Get the raw quotient. + *this = getQuotient(Digits, X.Digits); + + // Combine with exponents. + return *this <<= Scales; +} +template <class DigitsT> void ScaledNumber<DigitsT>::shiftLeft(int32_t Shift) { + if (!Shift || isZero()) + return; + assert(Shift != INT32_MIN); + if (Shift < 0) { + shiftRight(-Shift); + return; + } + + // Shift as much as we can in the exponent. + int32_t ScaleShift = std::min(Shift, ScaledNumbers::MaxScale - Scale); + Scale += ScaleShift; + if (ScaleShift == Shift) + return; + + // Check this late, since it's rare. + if (isLargest()) + return; + + // Shift the digits themselves. + Shift -= ScaleShift; + if (Shift > countLeadingZerosWidth(Digits)) { + // Saturate. + *this = getLargest(); + return; + } + + Digits <<= Shift; + return; +} + +template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) { + if (!Shift || isZero()) + return; + assert(Shift != INT32_MIN); + if (Shift < 0) { + shiftLeft(-Shift); + return; + } + + // Shift as much as we can in the exponent. + int32_t ScaleShift = std::min(Shift, Scale - ScaledNumbers::MinScale); + Scale -= ScaleShift; + if (ScaleShift == Shift) + return; + + // Shift the digits themselves. + Shift -= ScaleShift; + if (Shift >= Width) { + // Saturate. + *this = getZero(); + return; + } + + Digits >>= Shift; + return; +} + +template <typename T> struct isPodLike; +template <typename T> struct isPodLike<ScaledNumber<T>> { + static const bool value = true; +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h index 58ed175dc22b..6cbc1f6854a6 100644 --- a/include/llvm/Support/Signals.h +++ b/include/llvm/Support/Signals.h @@ -28,7 +28,7 @@ namespace sys { /// This function registers signal handlers to ensure that if a signal gets /// delivered that the named file is removed. /// @brief Remove a file if a fatal signal occurs. - bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = 0); + bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = nullptr); /// This function removes a file from the list of files to be removed on /// signal delivery. diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index dd4897432d9e..4717553bd0de 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -30,7 +30,7 @@ namespace llvm { class Twine; class raw_ostream; -/// SourceMgr - This owns the files read by a parser, handles include stacks, +/// This owns the files read by a parser, handles include stacks, /// and handles diagnostic wrangling. class SourceMgr { public: @@ -40,47 +40,48 @@ public: DK_Note }; - /// DiagHandlerTy - Clients that want to handle their own diagnostics in a - /// custom way can register a function pointer+context as a diagnostic - /// handler. It gets called each time PrintMessage is invoked. + /// Clients that want to handle their own diagnostics in a custom way can + /// register a function pointer+context as a diagnostic handler. + /// It gets called each time PrintMessage is invoked. typedef void (*DiagHandlerTy)(const SMDiagnostic &, void *Context); private: struct SrcBuffer { - /// Buffer - The memory buffer for the file. + /// The memory buffer for the file. MemoryBuffer *Buffer; - /// IncludeLoc - This is the location of the parent include, or null if at - /// the top level. + /// This is the location of the parent include, or null if at the top level. SMLoc IncludeLoc; }; - /// Buffers - This is all of the buffers that we are reading from. + /// This is all of the buffers that we are reading from. std::vector<SrcBuffer> Buffers; - // IncludeDirectories - This is the list of directories we should search for - // include files in. + // This is the list of directories we should search for include files in. std::vector<std::string> IncludeDirectories; - /// LineNoCache - This is a cache for line number queries, its implementation - /// is really private to SourceMgr.cpp. + /// This is a cache for line number queries, its implementation is really + /// private to SourceMgr.cpp. mutable void *LineNoCache; DiagHandlerTy DiagHandler; void *DiagContext; + bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); } + SourceMgr(const SourceMgr&) LLVM_DELETED_FUNCTION; void operator=(const SourceMgr&) LLVM_DELETED_FUNCTION; public: - SourceMgr() : LineNoCache(0), DiagHandler(0), DiagContext(0) {} + SourceMgr() + : LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {} ~SourceMgr(); void setIncludeDirs(const std::vector<std::string> &Dirs) { IncludeDirectories = Dirs; } - /// setDiagHandler - Specify a diagnostic handler to be invoked every time - /// PrintMessage is called. Ctx is passed into the handler when it is invoked. - void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0) { + /// Specify a diagnostic handler to be invoked every time PrintMessage is + /// called. \p Ctx is passed into the handler when it is invoked. + void setDiagHandler(DiagHandlerTy DH, void *Ctx = nullptr) { DiagHandler = DH; DiagContext = Ctx; } @@ -89,60 +90,67 @@ public: void *getDiagContext() const { return DiagContext; } const SrcBuffer &getBufferInfo(unsigned i) const { - assert(i < Buffers.size() && "Invalid Buffer ID!"); - return Buffers[i]; + assert(isValidBufferID(i)); + return Buffers[i - 1]; } const MemoryBuffer *getMemoryBuffer(unsigned i) const { - assert(i < Buffers.size() && "Invalid Buffer ID!"); - return Buffers[i].Buffer; + assert(isValidBufferID(i)); + return Buffers[i - 1].Buffer; } - size_t getNumBuffers() const { + unsigned getNumBuffers() const { return Buffers.size(); } + unsigned getMainFileID() const { + assert(getNumBuffers()); + return 1; + } + SMLoc getParentIncludeLoc(unsigned i) const { - assert(i < Buffers.size() && "Invalid Buffer ID!"); - return Buffers[i].IncludeLoc; + assert(isValidBufferID(i)); + return Buffers[i - 1].IncludeLoc; } - /// AddNewSourceBuffer - Add a new source buffer to this source manager. This - /// takes ownership of the memory buffer. - size_t AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { + /// Add a new source buffer to this source manager. This takes ownership of + /// the memory buffer. + unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { SrcBuffer NB; NB.Buffer = F; NB.IncludeLoc = IncludeLoc; Buffers.push_back(NB); - return Buffers.size() - 1; + return Buffers.size(); } - /// AddIncludeFile - Search for a file with the specified name in the current - /// directory or in one of the IncludeDirs. If no file is found, this returns - /// ~0, otherwise it returns the buffer ID of the stacked file. - /// The full path to the included file can be found in IncludedFile. - size_t AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, - std::string &IncludedFile); + /// Search for a file with the specified name in the current directory or in + /// one of the IncludeDirs. + /// + /// If no file is found, this returns 0, otherwise it returns the buffer ID + /// of the stacked file. The full path to the included file can be found in + /// \p IncludedFile. + unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, + std::string &IncludedFile); - /// FindBufferContainingLoc - Return the ID of the buffer containing the - /// specified location, returning -1 if not found. - int FindBufferContainingLoc(SMLoc Loc) const; + /// Return the ID of the buffer containing the specified location. + /// + /// 0 is returned if the buffer is not found. + unsigned FindBufferContainingLoc(SMLoc Loc) const; - /// FindLineNumber - Find the line number for the specified location in the - /// specified file. This is not a fast method. - unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const { + /// Find the line number for the specified location in the specified file. + /// This is not a fast method. + unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const { return getLineAndColumn(Loc, BufferID).first; } - /// getLineAndColumn - Find the line and column number for the specified - /// location in the specified file. This is not a fast method. - std::pair<unsigned, unsigned> - getLineAndColumn(SMLoc Loc, int BufferID = -1) const; + /// Find the line and column number for the specified location in the + /// specified file. This is not a fast method. + std::pair<unsigned, unsigned> getLineAndColumn(SMLoc Loc, + unsigned BufferID = 0) const; - /// PrintMessage - Emit a message about the specified location with the - /// specified string. + /// Emit a message about the specified location with the specified string. /// - /// @param ShowColors - Display colored messages if output is a terminal and + /// \param ShowColors Display colored messages if output is a terminal and /// the default error handler is used. void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, @@ -156,21 +164,28 @@ public: ArrayRef<SMFixIt> FixIts = None, bool ShowColors = true) const; - /// GetMessage - Return an SMDiagnostic at the specified location with the - /// specified string. + /// Emits a manually-constructed diagnostic to the given output stream. + /// + /// \param ShowColors Display colored messages if output is a terminal and + /// the default error handler is used. + void PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic, + bool ShowColors = true) const; + + /// Return an SMDiagnostic at the specified location with the specified + /// string. /// - /// @param Msg If non-null, the kind of message (e.g., "error") which is + /// \param Msg If non-null, the kind of message (e.g., "error") which is /// prefixed to the message. SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef<SMRange> Ranges = None, ArrayRef<SMFixIt> FixIts = None) const; - /// PrintIncludeStack - Prints the names of included files and the line of the - /// file they were included from. A diagnostic handler can use this before - /// printing its custom formatted message. + /// Prints the names of included files and the line of the file they were + /// included from. A diagnostic handler can use this before printing its + /// custom formatted message. /// - /// @param IncludeLoc - The line of the include. - /// @param OS the raw_ostream to print on. + /// \param IncludeLoc The location of the include. + /// \param OS the raw_ostream to print on. void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; }; @@ -207,8 +222,8 @@ public: }; -/// SMDiagnostic - Instances of this class encapsulate one diagnostic report, -/// allowing printing to a raw_ostream as a caret diagnostic. +/// Instances of this class encapsulate one diagnostic report, allowing +/// printing to a raw_ostream as a caret diagnostic. class SMDiagnostic { const SourceMgr *SM; SMLoc Loc; @@ -222,10 +237,10 @@ class SMDiagnostic { public: // Null diagnostic. SMDiagnostic() - : SM(0), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} + : SM(nullptr), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} // Diagnostic with no location (e.g. file not found, command line arg error). SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg) - : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), + : SM(nullptr), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {} // Diagnostic with a location. diff --git a/include/llvm/Support/SpecialCaseList.h b/include/llvm/Support/SpecialCaseList.h new file mode 100644 index 000000000000..098b9c7a17b7 --- /dev/null +++ b/include/llvm/Support/SpecialCaseList.h @@ -0,0 +1,96 @@ +//===-- SpecialCaseList.h - special case list for sanitizers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// +// +// This is a utility class used to parse user-provided text files with +// "special case lists" for code sanitizers. Such files are used to +// define "ABI list" for DataFlowSanitizer and blacklists for another sanitizers +// like AddressSanitizer or UndefinedBehaviorSanitizer. +// +// Empty lines and lines starting with "#" are ignored. All the rest lines +// should have the form: +// section:wildcard_expression[=category] +// If category is not specified, it is assumed to be empty string. +// Definitions of "section" and "category" are sanitizer-specific. For example, +// sanitizer blacklists support sections "src", "fun" and "global". +// Wildcard expressions define, respectively, source files, functions or +// globals which shouldn't be instrumented. +// Examples of categories: +// "functional": used in DFSan to list functions with pure functional +// semantics. +// "init": used in ASan blacklist to disable initialization-order bugs +// detection for certain globals or source files. +// Full special case list file example: +// --- +// # Blacklisted items: +// fun:*_ZN4base6subtle* +// global:*global_with_bad_access_or_initialization* +// global:*global_with_initialization_issues*=init +// type:*Namespace::ClassName*=init +// src:file_with_tricky_code.cc +// src:ignore-global-initializers-issues.cc=init +// +// # Functions with pure functional semantics: +// fun:cos=functional +// fun:sin=functional +// --- +// Note that the wild card is in fact an llvm::Regex, but * is automatically +// replaced with .* +// This is similar to the "ignore" feature of ThreadSanitizer. +// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SPECIALCASELIST_H +#define LLVM_SUPPORT_SPECIALCASELIST_H + +#include "llvm/ADT/StringMap.h" + +namespace llvm { +class MemoryBuffer; +class Regex; +class StringRef; + +class SpecialCaseList { + public: + /// Parses the special case list from a file. If Path is empty, returns + /// an empty special case list. On failure, returns 0 and writes an error + /// message to string. + static SpecialCaseList *create(const StringRef Path, std::string &Error); + /// Parses the special case list from a memory buffer. On failure, returns + /// 0 and writes an error message to string. + static SpecialCaseList *create(const MemoryBuffer *MB, std::string &Error); + /// Parses the special case list from a file. On failure, reports a fatal + /// error. + static SpecialCaseList *createOrDie(const StringRef Path); + + ~SpecialCaseList(); + + /// Returns true, if special case list contains a line + /// \code + /// @Section:<E>=@Category + /// \endcode + /// and @Query satisfies a wildcard expression <E>. + bool inSection(const StringRef Section, const StringRef Query, + const StringRef Category = StringRef()) const; + + private: + SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION; + SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION; + + struct Entry; + StringMap<StringMap<Entry> > Entries; + + SpecialCaseList(); + /// Parses just-constructed SpecialCaseList entries from a memory buffer. + bool parse(const MemoryBuffer *MB, std::string &Error); +}; + +} // namespace llvm + +#endif // LLVM_SUPPORT_SPECIALCASELIST_H + diff --git a/include/llvm/Support/StreamableMemoryObject.h b/include/llvm/Support/StreamableMemoryObject.h index e823d489d3a8..6e71ad47c8dd 100644 --- a/include/llvm/Support/StreamableMemoryObject.h +++ b/include/llvm/Support/StreamableMemoryObject.h @@ -11,10 +11,12 @@ #ifndef LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H #define LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataStream.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryObject.h" +#include <cassert> +#include <memory> #include <vector> namespace llvm { @@ -38,7 +40,7 @@ class StreamableMemoryObject : public MemoryObject { /// getBase - Returns the lowest valid address in the region. /// /// @result - The lowest valid address. - virtual uint64_t getBase() const LLVM_OVERRIDE = 0; + uint64_t getBase() const override = 0; /// getExtent - Returns the size of the region in bytes. (The region is /// contiguous, so the highest valid address of the region @@ -46,7 +48,7 @@ class StreamableMemoryObject : public MemoryObject { /// May block until all bytes in the stream have been read /// /// @result - The size of the region. - virtual uint64_t getExtent() const LLVM_OVERRIDE = 0; + uint64_t getExtent() const override = 0; /// readByte - Tries to read a single byte from the region. /// May block until (address - base) bytes have been read @@ -54,7 +56,7 @@ class StreamableMemoryObject : public MemoryObject { /// @param ptr - A pointer to a byte to be filled in. Must be non-NULL. /// @result - 0 if successful; -1 if not. Failure may be due to a /// bounds violation or an implementation-specific error. - virtual int readByte(uint64_t address, uint8_t *ptr) const LLVM_OVERRIDE = 0; + int readByte(uint64_t address, uint8_t *ptr) const override = 0; /// readBytes - Tries to read a contiguous range of bytes from the /// region, up to the end of the region. @@ -70,9 +72,8 @@ class StreamableMemoryObject : public MemoryObject { /// and large enough to hold size bytes. /// @result - 0 if successful; -1 if not. Failure may be due to a /// bounds violation or an implementation-specific error. - virtual int readBytes(uint64_t address, - uint64_t size, - uint8_t *buf) const LLVM_OVERRIDE = 0; + int readBytes(uint64_t address, uint64_t size, + uint8_t *buf) const override = 0; /// getPointer - Ensures that the requested data is in memory, and returns /// A pointer to it. More efficient than using readBytes if the @@ -105,23 +106,21 @@ class StreamableMemoryObject : public MemoryObject { class StreamingMemoryObject : public StreamableMemoryObject { public: StreamingMemoryObject(DataStreamer *streamer); - virtual uint64_t getBase() const LLVM_OVERRIDE { return 0; } - virtual uint64_t getExtent() const LLVM_OVERRIDE; - virtual int readByte(uint64_t address, uint8_t *ptr) const LLVM_OVERRIDE; - virtual int readBytes(uint64_t address, - uint64_t size, - uint8_t *buf) const LLVM_OVERRIDE; - virtual const uint8_t *getPointer(uint64_t address, - uint64_t size) const LLVM_OVERRIDE { + uint64_t getBase() const override { return 0; } + uint64_t getExtent() const override; + int readByte(uint64_t address, uint8_t *ptr) const override; + int readBytes(uint64_t address, uint64_t size, + uint8_t *buf) const override; + const uint8_t *getPointer(uint64_t address, uint64_t size) const override { // This could be fixed by ensuring the bytes are fetched and making a copy, // requiring that the bitcode size be known, or otherwise ensuring that // the memory doesn't go away/get reallocated, but it's // not currently necessary. Users that need the pointer don't stream. - assert(0 && "getPointer in streaming memory objects not allowed"); - return NULL; + llvm_unreachable("getPointer in streaming memory objects not allowed"); + return nullptr; } - virtual bool isValidAddress(uint64_t address) const LLVM_OVERRIDE; - virtual bool isObjectEnd(uint64_t address) const LLVM_OVERRIDE; + bool isValidAddress(uint64_t address) const override; + bool isObjectEnd(uint64_t address) const override; /// Drop s bytes from the front of the stream, pushing the positions of the /// remaining bytes down by s. This is used to skip past the bitcode header, @@ -137,7 +136,7 @@ public: private: const static uint32_t kChunkSize = 4096 * 4; mutable std::vector<unsigned char> Bytes; - OwningPtr<DataStreamer> Streamer; + std::unique_ptr<DataStreamer> Streamer; mutable size_t BytesRead; // Bytes read from stream size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header) mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached @@ -156,8 +155,8 @@ private: kChunkSize); BytesRead += bytes; if (bytes < kChunkSize) { - if (ObjectSize && BytesRead < Pos) - assert(0 && "Unexpected short read fetching bitcode"); + assert((!ObjectSize || BytesRead >= Pos) && + "Unexpected short read fetching bitcode"); if (BytesRead <= Pos) { // reached EOF/ran out of bytes ObjectSize = BytesRead; EOFReached = true; diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h index 71adbc5342e2..3e0465340c3b 100644 --- a/include/llvm/Support/StringPool.h +++ b/include/llvm/Support/StringPool.h @@ -29,6 +29,7 @@ #ifndef LLVM_SUPPORT_STRINGPOOL_H #define LLVM_SUPPORT_STRINGPOOL_H +#include "llvm/Support/Compiler.h" #include "llvm/ADT/StringMap.h" #include <cassert> #include <new> @@ -48,7 +49,7 @@ namespace llvm { unsigned Refcount; ///< Number of referencing PooledStringPtrs. public: - PooledString() : Pool(0), Refcount(0) { } + PooledString() : Pool(nullptr), Refcount(0) { } }; friend class PooledStringPtr; @@ -81,7 +82,7 @@ namespace llvm { entry_t *S; public: - PooledStringPtr() : S(0) {} + PooledStringPtr() : S(nullptr) {} explicit PooledStringPtr(entry_t *E) : S(E) { if (S) ++S->getValue().Refcount; @@ -107,7 +108,7 @@ namespace llvm { S->getValue().Pool->InternTable.remove(S); S->Destroy(); } - S = 0; + S = nullptr; } ~PooledStringPtr() { clear(); } @@ -128,10 +129,10 @@ namespace llvm { } inline const char *operator*() const { return begin(); } - inline operator bool() const { return S != 0; } + inline LLVM_EXPLICIT operator bool() const { return S != nullptr; } - inline bool operator==(const PooledStringPtr &That) { return S == That.S; } - inline bool operator!=(const PooledStringPtr &That) { return S != That.S; } + inline bool operator==(const PooledStringPtr &That) const { return S == That.S; } + inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; } }; } // End llvm namespace diff --git a/include/llvm/Support/StringRefMemoryObject.h b/include/llvm/Support/StringRefMemoryObject.h index 994fa34b74bb..8a349eab84c8 100644 --- a/include/llvm/Support/StringRefMemoryObject.h +++ b/include/llvm/Support/StringRefMemoryObject.h @@ -29,11 +29,11 @@ public: StringRefMemoryObject(StringRef Bytes, uint64_t Base = 0) : Bytes(Bytes), Base(Base) {} - uint64_t getBase() const LLVM_OVERRIDE { return Base; } - uint64_t getExtent() const LLVM_OVERRIDE { return Bytes.size(); } + uint64_t getBase() const override { return Base; } + uint64_t getExtent() const override { return Bytes.size(); } - int readByte(uint64_t Addr, uint8_t *Byte) const LLVM_OVERRIDE; - int readBytes(uint64_t Addr, uint64_t Size, uint8_t *Buf) const LLVM_OVERRIDE; + int readByte(uint64_t Addr, uint8_t *Byte) const override; + int readBytes(uint64_t Addr, uint64_t Size, uint8_t *Buf) const override; }; } diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index e65f9cc0729d..340954f4c893 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -68,33 +68,38 @@ inline uint64_t SwapByteOrder_64(uint64_t value) { #endif } -inline unsigned char SwapByteOrder(unsigned char C) { return C; } -inline signed char SwapByteOrder(signed char C) { return C; } -inline char SwapByteOrder(char C) { return C; } +inline unsigned char getSwappedBytes(unsigned char C) { return C; } +inline signed char getSwappedBytes(signed char C) { return C; } +inline char getSwappedBytes(char C) { return C; } -inline unsigned short SwapByteOrder(unsigned short C) { return SwapByteOrder_16(C); } -inline signed short SwapByteOrder( signed short C) { return SwapByteOrder_16(C); } +inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); } +inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); } -inline unsigned int SwapByteOrder(unsigned int C) { return SwapByteOrder_32(C); } -inline signed int SwapByteOrder( signed int C) { return SwapByteOrder_32(C); } +inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); } +inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); } #if __LONG_MAX__ == __INT_MAX__ -inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_32(C); } -inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_32(C); } +inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); } +inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); } #elif __LONG_MAX__ == __LONG_LONG_MAX__ -inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_64(C); } -inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_64(C); } +inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); } +inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); } #else #error "Unknown long size!" #endif -inline unsigned long long SwapByteOrder(unsigned long long C) { +inline unsigned long long getSwappedBytes(unsigned long long C) { return SwapByteOrder_64(C); } -inline signed long long SwapByteOrder(signed long long C) { +inline signed long long getSwappedBytes(signed long long C) { return SwapByteOrder_64(C); } +template<typename T> +inline void swapByteOrder(T &Value) { + Value = getSwappedBytes(Value); +} + } // end namespace sys } // end namespace llvm diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index 9ecee3b7c21a..5d5b86a6a2ae 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -19,9 +19,9 @@ #ifndef LLVM_SUPPORT_TARGETREGISTRY_H #define LLVM_SUPPORT_TARGETREGISTRY_H +#include "llvm-c/Disassembler.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" -#include "llvm-c/Disassembler.h" #include <cassert> #include <string> @@ -45,17 +45,15 @@ namespace llvm { class MCSymbolizer; class MCRelocationInfo; class MCTargetAsmParser; + class MCTargetOptions; class TargetMachine; - class MCTargetStreamer; class TargetOptions; class raw_ostream; class formatted_raw_ostream; - MCStreamer *createAsmStreamer(MCContext &Ctx, - MCTargetStreamer *TargetStreamer, - formatted_raw_ostream &OS, bool isVerboseAsm, - bool useLoc, bool useCFI, - bool useDwarfDirectory, + MCStreamer *createNullStreamer(MCContext &Ctx); + MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); @@ -79,7 +77,7 @@ namespace llvm { public: friend struct TargetRegistry; - typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT); + typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch); typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI, StringRef TT); @@ -107,11 +105,14 @@ namespace llvm { const MCRegisterInfo &MRI, StringRef TT, StringRef CPU); - typedef MCTargetAsmParser *(*MCAsmParserCtorTy)(MCSubtargetInfo &STI, - MCAsmParser &P, - const MCInstrInfo &MII); + typedef MCTargetAsmParser *(*MCAsmParserCtorTy)( + MCSubtargetInfo &STI, + MCAsmParser &P, + const MCInstrInfo &MII, + const MCTargetOptions &Options); typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, - const MCSubtargetInfo &STI); + const MCSubtargetInfo &STI, + MCContext &Ctx); typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, @@ -128,18 +129,18 @@ namespace llvm { MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, + const MCSubtargetInfo &STI, bool RelaxAll, bool NoExecStack); typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, - bool useLoc, - bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); + typedef MCStreamer *(*NullStreamerCtorTy)(MCContext &Ctx); typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT, MCContext &Ctx); typedef MCSymbolizer *(*MCSymbolizerCtorTy)(StringRef TT, @@ -154,9 +155,8 @@ namespace llvm { /// TargetRegistry. Target *Next; - /// TripleMatchQualityFn - The target function for rating the match quality - /// of a triple. - TripleMatchQualityFnTy TripleMatchQualityFn; + /// The target function for checking if an architecture is supported. + ArchMatchFnTy ArchMatchFn; /// Name - The target name. const char *Name; @@ -227,6 +227,10 @@ namespace llvm { /// AsmStreamer, if registered (default = llvm::createAsmStreamer). AsmStreamerCtorTy AsmStreamerCtorFn; + /// Construction function for this target's NullStreamer, if registered + /// (default = llvm::createNullStreamer). + NullStreamerCtorTy NullStreamerCtorFn; + /// MCRelocationInfoCtorFn - Construction function for this target's /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo) MCRelocationInfoCtorTy MCRelocationInfoCtorFn; @@ -237,8 +241,8 @@ namespace llvm { public: Target() - : AsmStreamerCtorFn(0), MCRelocationInfoCtorFn(0), - MCSymbolizerCtorFn(0) {} + : AsmStreamerCtorFn(nullptr), NullStreamerCtorFn(nullptr), + MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {} /// @name Target Information /// @{ @@ -260,10 +264,10 @@ namespace llvm { bool hasJIT() const { return HasJIT; } /// hasTargetMachine - Check if this target supports code generation. - bool hasTargetMachine() const { return TargetMachineCtorFn != 0; } + bool hasTargetMachine() const { return TargetMachineCtorFn != nullptr; } /// hasMCAsmBackend - Check if this target supports .o generation. - bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != 0; } + bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != nullptr; } /// @} /// @name Feature Constructors @@ -279,7 +283,7 @@ namespace llvm { MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI, StringRef Triple) const { if (!MCAsmInfoCtorFn) - return 0; + return nullptr; return MCAsmInfoCtorFn(MRI, Triple); } @@ -289,7 +293,7 @@ namespace llvm { CodeModel::Model CM, CodeGenOpt::Level OL) const { if (!MCCodeGenInfoCtorFn) - return 0; + return nullptr; return MCCodeGenInfoCtorFn(Triple, RM, CM, OL); } @@ -297,7 +301,7 @@ namespace llvm { /// MCInstrInfo *createMCInstrInfo() const { if (!MCInstrInfoCtorFn) - return 0; + return nullptr; return MCInstrInfoCtorFn(); } @@ -305,7 +309,7 @@ namespace llvm { /// MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const { if (!MCInstrAnalysisCtorFn) - return 0; + return nullptr; return MCInstrAnalysisCtorFn(Info); } @@ -313,7 +317,7 @@ namespace llvm { /// MCRegisterInfo *createMCRegInfo(StringRef Triple) const { if (!MCRegInfoCtorFn) - return 0; + return nullptr; return MCRegInfoCtorFn(Triple); } @@ -329,7 +333,7 @@ namespace llvm { MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU, StringRef Features) const { if (!MCSubtargetInfoCtorFn) - return 0; + return nullptr; return MCSubtargetInfoCtorFn(Triple, CPU, Features); } @@ -346,7 +350,7 @@ namespace llvm { CodeModel::Model CM = CodeModel::Default, CodeGenOpt::Level OL = CodeGenOpt::Default) const { if (!TargetMachineCtorFn) - return 0; + return nullptr; return TargetMachineCtorFn(*this, Triple, CPU, Features, Options, RM, CM, OL); } @@ -357,7 +361,7 @@ namespace llvm { MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI, StringRef Triple, StringRef CPU) const { if (!MCAsmBackendCtorFn) - return 0; + return nullptr; return MCAsmBackendCtorFn(*this, MRI, Triple, CPU); } @@ -365,26 +369,29 @@ namespace llvm { /// /// \param Parser The target independent parser implementation to use for /// parsing and lexing. - MCTargetAsmParser *createMCAsmParser(MCSubtargetInfo &STI, - MCAsmParser &Parser, - const MCInstrInfo &MII) const { + MCTargetAsmParser *createMCAsmParser( + MCSubtargetInfo &STI, + MCAsmParser &Parser, + const MCInstrInfo &MII, + const MCTargetOptions &Options) const { if (!MCAsmParserCtorFn) - return 0; - return MCAsmParserCtorFn(STI, Parser, MII); + return nullptr; + return MCAsmParserCtorFn(STI, Parser, MII, Options); } /// createAsmPrinter - Create a target specific assembly printer pass. This /// takes ownership of the MCStreamer object. AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{ if (!AsmPrinterCtorFn) - return 0; + return nullptr; return AsmPrinterCtorFn(TM, Streamer); } - MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI) const { + MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI, + MCContext &Ctx) const { if (!MCDisassemblerCtorFn) - return 0; - return MCDisassemblerCtorFn(*this, STI); + return nullptr; + return MCDisassemblerCtorFn(*this, STI, Ctx); } MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, @@ -393,7 +400,7 @@ namespace llvm { const MCRegisterInfo &MRI, const MCSubtargetInfo &STI) const { if (!MCInstPrinterCtorFn) - return 0; + return nullptr; return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, MII, MRI, STI); } @@ -404,7 +411,7 @@ namespace llvm { const MCSubtargetInfo &STI, MCContext &Ctx) const { if (!MCCodeEmitterCtorFn) - return 0; + return nullptr; return MCCodeEmitterCtorFn(II, MRI, STI, Ctx); } @@ -421,11 +428,12 @@ namespace llvm { MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, + const MCSubtargetInfo &STI, bool RelaxAll, bool NoExecStack) const { if (!MCObjectStreamerCtorFn) - return 0; - return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, + return nullptr; + return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, STI, RelaxAll, NoExecStack); } @@ -433,20 +441,22 @@ namespace llvm { MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, - bool useLoc, - bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) const { if (AsmStreamerCtorFn) - return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, useCFI, - useDwarfDirectory, InstPrint, CE, TAB, - ShowInst); - return llvm::createAsmStreamer(Ctx, 0, OS, isVerboseAsm, useLoc, useCFI, - useDwarfDirectory, InstPrint, CE, TAB, - ShowInst); + return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useDwarfDirectory, + InstPrint, CE, TAB, ShowInst); + return llvm::createAsmStreamer(Ctx, OS, isVerboseAsm, useDwarfDirectory, + InstPrint, CE, TAB, ShowInst); + } + + MCStreamer *createNullStreamer(MCContext &Ctx) const { + if (NullStreamerCtorFn) + return NullStreamerCtorFn(Ctx); + return llvm::createNullStreamer(Ctx); } /// createMCRelocationInfo - Create a target specific MCRelocationInfo. @@ -490,8 +500,7 @@ namespace llvm { explicit iterator(Target *T) : Current(T) {} friend struct TargetRegistry; public: - iterator(const iterator &I) : Current(I.Current) {} - iterator() : Current(0) {} + iterator() : Current(nullptr) {} bool operator==(const iterator &x) const { return Current == x.Current; @@ -556,13 +565,6 @@ namespace llvm { Triple &TheTriple, std::string &Error); - /// getClosestTargetForJIT - Pick the best target that is compatible with - /// the current host. If no close target can be found, this returns null - /// and sets the Error string to a reason. - /// - /// Maintained for compatibility through 2.6. - static const Target *getClosestTargetForJIT(std::string &Error); - /// @} /// @name Target Registration /// @{ @@ -578,14 +580,13 @@ namespace llvm { /// @param Name - The target name. This should be a static string. /// @param ShortDesc - A short target description. This should be a static /// string. - /// @param TQualityFn - The triple match quality computation function for - /// this target. + /// @param ArchMatchFn - The arch match checking function for this target. /// @param HasJIT - Whether the target supports JIT code /// generation. static void RegisterTarget(Target &T, const char *Name, const char *ShortDesc, - Target::TripleMatchQualityFnTy TQualityFn, + Target::ArchMatchFnTy ArchMatchFn, bool HasJIT = false); /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the @@ -784,6 +785,10 @@ namespace llvm { T.AsmStreamerCtorFn = Fn; } + static void RegisterNullStreamer(Target &T, Target::NullStreamerCtorTy Fn) { + T.NullStreamerCtorFn = Fn; + } + /// RegisterMCRelocationInfo - Register an MCRelocationInfo /// implementation for the given target. /// @@ -831,15 +836,11 @@ namespace llvm { bool HasJIT = false> struct RegisterTarget { RegisterTarget(Target &T, const char *Name, const char *Desc) { - TargetRegistry::RegisterTarget(T, Name, Desc, - &getTripleMatchQuality, - HasJIT); + TargetRegistry::RegisterTarget(T, Name, Desc, &getArchMatch, HasJIT); } - static unsigned getTripleMatchQuality(const std::string &TT) { - if (Triple(TT).getArch() == TargetArchType) - return 20; - return 0; + static bool getArchMatch(Triple::ArchType Arch) { + return Arch == TargetArchType; } }; @@ -1107,8 +1108,9 @@ namespace llvm { private: static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P, - const MCInstrInfo &MII) { - return new MCAsmParserImpl(STI, P, MII); + const MCInstrInfo &MII, + const MCTargetOptions &Options) { + return new MCAsmParserImpl(STI, P, MII, Options); } }; diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h index a7e8774558d5..7e8758407c7c 100644 --- a/include/llvm/Support/Threading.h +++ b/include/llvm/Support/Threading.h @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// TThis file defines llvm_start_multithreaded() and friends. +// This file declares helper functions for running LLVM in a multi-threaded +// environment. // //===----------------------------------------------------------------------===// @@ -15,32 +16,10 @@ #define LLVM_SUPPORT_THREADING_H namespace llvm { - /// llvm_start_multithreaded - Allocate and initialize structures needed to - /// make LLVM safe for multithreading. The return value indicates whether - /// multithreaded initialization succeeded. LLVM will still be operational - /// on "failed" return, and will still be safe for hosting threading - /// applications in the JIT, but will not be safe for concurrent calls to the - /// LLVM APIs. - /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. - bool llvm_start_multithreaded(); - - /// llvm_stop_multithreaded - Deallocate structures necessary to make LLVM - /// safe for multithreading. - /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. - void llvm_stop_multithreaded(); - - /// llvm_is_multithreaded - Check whether LLVM is executing in thread-safe - /// mode or not. + /// Returns true if LLVM is compiled with support for multi-threading, and + /// false otherwise. bool llvm_is_multithreaded(); - /// acquire_global_lock - Acquire the global lock. This is a no-op if called - /// before llvm_start_multithreaded(). - void llvm_acquire_global_lock(); - - /// release_global_lock - Release the global lock. This is a no-op if called - /// before llvm_start_multithreaded(). - void llvm_release_global_lock(); - /// llvm_execute_on_thread - Execute the given \p UserFn on a separate /// thread, passing it the provided \p UserData. /// diff --git a/include/llvm/Support/TimeValue.h b/include/llvm/Support/TimeValue.h index 27854088f056..ee0e2866d59e 100644 --- a/include/llvm/Support/TimeValue.h +++ b/include/llvm/Support/TimeValue.h @@ -74,8 +74,7 @@ namespace sys { MILLISECONDS_PER_SECOND = 1000, ///< One Thousand NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million - NANOSECONDS_PER_POSIX_TICK = 100, ///< Posix tick is 100 Hz (10ms) - NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 100 Hz (10ms) + NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 10^7 Hz (10ns) }; /// @} @@ -236,15 +235,6 @@ namespace sys { ( nanos_ / NANOSECONDS_PER_MILLISECOND ); } - /// Converts the TimeValue into the corresponding number of "ticks" for - /// Posix, correcting for the difference in Posix zero time. - /// @brief Convert to unix time (100 nanoseconds since 12:00:00a Jan 1,1970) - uint64_t toPosixTime() const { - uint64_t result = seconds_ - PosixZeroTimeSeconds; - result += nanos_ / NANOSECONDS_PER_POSIX_TICK; - return result; - } - /// Converts the TimeValue into the corresponding number of seconds /// since the epoch (00:00:00 Jan 1,1970). uint64_t toEpochTime() const { diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index d009d7fae513..45c182831b2a 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -85,24 +85,24 @@ class Timer { Timer **Prev, *Next; // Doubly linked list of timers in the group. public: - explicit Timer(StringRef N) : TG(0) { init(N); } - Timer(StringRef N, TimerGroup &tg) : TG(0) { init(N, tg); } - Timer(const Timer &RHS) : TG(0) { - assert(RHS.TG == 0 && "Can only copy uninitialized timers"); + explicit Timer(StringRef N) : TG(nullptr) { init(N); } + Timer(StringRef N, TimerGroup &tg) : TG(nullptr) { init(N, tg); } + Timer(const Timer &RHS) : TG(nullptr) { + assert(!RHS.TG && "Can only copy uninitialized timers"); } const Timer &operator=(const Timer &T) { - assert(TG == 0 && T.TG == 0 && "Can only assign uninit timers"); + assert(!TG && !T.TG && "Can only assign uninit timers"); return *this; } ~Timer(); // Create an uninitialized timer, client must use 'init'. - explicit Timer() : TG(0) {} + explicit Timer() : TG(nullptr) {} void init(StringRef N); void init(StringRef N, TimerGroup &tg); const std::string &getName() const { return Name; } - bool isInitialized() const { return TG != 0; } + bool isInitialized() const { return TG != nullptr; } /// startTimer - Start the timer running. Time between calls to /// startTimer/stopTimer is counted by the Timer class. Note that these calls diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h index a2191ade80cf..88f8ccc292d3 100644 --- a/include/llvm/Support/ToolOutputFile.h +++ b/include/llvm/Support/ToolOutputFile.h @@ -47,7 +47,7 @@ public: /// tool_output_file - This constructor's arguments are passed to /// to raw_fd_ostream's constructor. tool_output_file(const char *filename, std::string &ErrorInfo, - sys::fs::OpenFlags Flags = sys::fs::F_None); + sys::fs::OpenFlags Flags); tool_output_file(const char *Filename, int FD); diff --git a/include/llvm/Support/Unicode.h b/include/llvm/Support/Unicode.h index e6a52c4c7065..f668a5bc88df 100644 --- a/include/llvm/Support/Unicode.h +++ b/include/llvm/Support/Unicode.h @@ -12,6 +12,9 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_SUPPORT_UNICODE_H +#define LLVM_SUPPORT_UNICODE_H + #include "llvm/ADT/StringRef.h" namespace llvm { @@ -60,3 +63,5 @@ int columnWidthUTF8(StringRef Text); } // namespace unicode } // namespace sys } // namespace llvm + +#endif diff --git a/include/llvm/Support/UnicodeCharRanges.h b/include/llvm/Support/UnicodeCharRanges.h index 86faa38c0afe..79137bf35363 100644 --- a/include/llvm/Support/UnicodeCharRanges.h +++ b/include/llvm/Support/UnicodeCharRanges.h @@ -16,12 +16,13 @@ #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" #include "llvm/Support/raw_ostream.h" - #include <algorithm> namespace llvm { namespace sys { +#define DEBUG_TYPE "unicode" + /// \brief Represents a closed range of Unicode code points [Lower, Upper]. struct UnicodeCharRange { uint32_t Lower; @@ -40,7 +41,7 @@ inline bool operator<(UnicodeCharRange Range, uint32_t Value) { /// array. class UnicodeCharSet { public: - typedef llvm::ArrayRef<UnicodeCharRange> CharRanges; + typedef ArrayRef<UnicodeCharRange> CharRanges; /// \brief Constructs a UnicodeCharSet instance from an array of /// UnicodeCharRanges. @@ -67,17 +68,17 @@ private: for (CharRanges::const_iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { if (I != Ranges.begin() && Prev >= I->Lower) { - DEBUG(llvm::dbgs() << "Upper bound 0x"); - DEBUG(llvm::dbgs().write_hex(Prev)); - DEBUG(llvm::dbgs() << " should be less than succeeding lower bound 0x"); - DEBUG(llvm::dbgs().write_hex(I->Lower) << "\n"); + DEBUG(dbgs() << "Upper bound 0x"); + DEBUG(dbgs().write_hex(Prev)); + DEBUG(dbgs() << " should be less than succeeding lower bound 0x"); + DEBUG(dbgs().write_hex(I->Lower) << "\n"); return false; } if (I->Upper < I->Lower) { - DEBUG(llvm::dbgs() << "Upper bound 0x"); - DEBUG(llvm::dbgs().write_hex(I->Lower)); - DEBUG(llvm::dbgs() << " should not be less than lower bound 0x"); - DEBUG(llvm::dbgs().write_hex(I->Upper) << "\n"); + DEBUG(dbgs() << "Upper bound 0x"); + DEBUG(dbgs().write_hex(I->Lower)); + DEBUG(dbgs() << " should not be less than lower bound 0x"); + DEBUG(dbgs().write_hex(I->Upper) << "\n"); return false; } Prev = I->Upper; @@ -89,6 +90,8 @@ private: const CharRanges Ranges; }; +#undef DEBUG_TYPE // "unicode" + } // namespace sys } // namespace llvm diff --git a/include/llvm/Support/Valgrind.h b/include/llvm/Support/Valgrind.h index 7ae40af754fc..cebf75c49c19 100644 --- a/include/llvm/Support/Valgrind.h +++ b/include/llvm/Support/Valgrind.h @@ -24,12 +24,10 @@ // tsan (Thread Sanitizer) is a valgrind-based tool that detects these exact // functions by name. extern "C" { -LLVM_ATTRIBUTE_WEAK void AnnotateHappensAfter(const char *file, int line, - const volatile void *cv); -LLVM_ATTRIBUTE_WEAK void AnnotateHappensBefore(const char *file, int line, - const volatile void *cv); -LLVM_ATTRIBUTE_WEAK void AnnotateIgnoreWritesBegin(const char *file, int line); -LLVM_ATTRIBUTE_WEAK void AnnotateIgnoreWritesEnd(const char *file, int line); +void AnnotateHappensAfter(const char *file, int line, const volatile void *cv); +void AnnotateHappensBefore(const char *file, int line, const volatile void *cv); +void AnnotateIgnoreWritesBegin(const char *file, int line); +void AnnotateIgnoreWritesEnd(const char *file, int line); } #endif diff --git a/include/llvm/Support/Win64EH.h b/include/llvm/Support/Win64EH.h index ecce71368041..7ca218e87a77 100644 --- a/include/llvm/Support/Win64EH.h +++ b/include/llvm/Support/Win64EH.h @@ -108,17 +108,19 @@ struct UnwindInfo { /// \brief Return pointer to language specific data part of UnwindInfo. const void *getLanguageSpecificData() const { - return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes+1) & ~1]); + return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes + 1) & ~1]); } /// \brief Return image-relative offset of language-specific exception handler. uint32_t getLanguageSpecificHandlerOffset() const { - return *reinterpret_cast<const uint32_t *>(getLanguageSpecificData()); + return *reinterpret_cast<const support::ulittle32_t *>( + getLanguageSpecificData()); } /// \brief Set image-relative offset of language-specific exception handler. void setLanguageSpecificHandlerOffset(uint32_t offset) { - *reinterpret_cast<uint32_t *>(getLanguageSpecificData()) = offset; + *reinterpret_cast<support::ulittle32_t *>(getLanguageSpecificData()) = + offset; } /// \brief Return pointer to exception-specific data. diff --git a/include/llvm/Support/WindowsError.h b/include/llvm/Support/WindowsError.h new file mode 100644 index 000000000000..0e909a05bf4a --- /dev/null +++ b/include/llvm/Support/WindowsError.h @@ -0,0 +1,19 @@ +//===-- WindowsError.h - Support for mapping windows errors to posix-------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WINDOWS_ERROR_H +#define LLVM_SUPPORT_WINDOWS_ERROR_H + +#include <system_error> + +namespace llvm { +std::error_code mapWindowsError(unsigned EV); +} + +#endif diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index 702044936c62..c39874cbd2c5 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -38,14 +38,12 @@ #ifndef LLVM_SUPPORT_YAMLPARSER_H #define LLVM_SUPPORT_YAMLPARSER_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/SMLoc.h" - -#include <map> #include <limits> +#include <map> #include <utility> namespace llvm { @@ -62,26 +60,26 @@ class Node; class Scanner; struct Token; -/// @brief Dump all the tokens in this stream to OS. -/// @returns true if there was an error, false otherwise. +/// \brief Dump all the tokens in this stream to OS. +/// \returns true if there was an error, false otherwise. bool dumpTokens(StringRef Input, raw_ostream &); -/// @brief Scans all tokens in input without outputting anything. This is used +/// \brief Scans all tokens in input without outputting anything. This is used /// for benchmarking the tokenizer. -/// @returns true if there was an error, false otherwise. +/// \returns true if there was an error, false otherwise. bool scanTokens(StringRef Input); -/// @brief Escape \a Input for a double quoted scalar. +/// \brief Escape \a Input for a double quoted scalar. std::string escape(StringRef Input); -/// @brief This class represents a YAML stream potentially containing multiple +/// \brief This class represents a YAML stream potentially containing multiple /// documents. class Stream { public: - /// @brief This keeps a reference to the string referenced by \p Input. + /// \brief This keeps a reference to the string referenced by \p Input. Stream(StringRef Input, SourceMgr &); - /// @brief This takes ownership of \p InputBuffer. + /// \brief This takes ownership of \p InputBuffer. Stream(MemoryBuffer *InputBuffer, SourceMgr &); ~Stream(); @@ -97,15 +95,16 @@ public: void printError(Node *N, const Twine &Msg); private: - OwningPtr<Scanner> scanner; - OwningPtr<Document> CurrentDoc; + std::unique_ptr<Scanner> scanner; + std::unique_ptr<Document> CurrentDoc; friend class Document; }; -/// @brief Abstract base class for all Nodes. +/// \brief Abstract base class for all Nodes. class Node { - virtual void anchor(); + virtual void anchor(); + public: enum NodeKind { NK_Null, @@ -116,10 +115,10 @@ public: NK_Alias }; - Node(unsigned int Type, OwningPtr<Document> &, StringRef Anchor, + Node(unsigned int Type, std::unique_ptr<Document> &, StringRef Anchor, StringRef Tag); - /// @brief Get the value of the anchor attached to this node. If it does not + /// \brief Get the value of the anchor attached to this node. If it does not /// have one, getAnchor().size() will be 0. StringRef getAnchor() const { return Anchor; } @@ -146,18 +145,17 @@ public: unsigned int getType() const { return TypeID; } - void *operator new ( size_t Size - , BumpPtrAllocator &Alloc - , size_t Alignment = 16) throw() { + void *operator new(size_t Size, BumpPtrAllocator &Alloc, + size_t Alignment = 16) throw() { return Alloc.Allocate(Size, Alignment); } - void operator delete(void *Ptr, BumpPtrAllocator &Alloc, size_t) throw() { - Alloc.Deallocate(Ptr); + void operator delete(void *Ptr, BumpPtrAllocator &Alloc, size_t Size) throw() { + Alloc.Deallocate(Ptr, Size); } protected: - OwningPtr<Document> &Doc; + std::unique_ptr<Document> &Doc; SMRange SourceRange; void operator delete(void *) throw() {} @@ -171,30 +169,30 @@ private: StringRef Tag; }; -/// @brief A null value. +/// \brief A null value. /// /// Example: /// !!null null class NullNode : public Node { - virtual void anchor(); + void anchor() override; + public: - NullNode(OwningPtr<Document> &D) + NullNode(std::unique_ptr<Document> &D) : Node(NK_Null, D, StringRef(), StringRef()) {} - static inline bool classof(const Node *N) { - return N->getType() == NK_Null; - } + static inline bool classof(const Node *N) { return N->getType() == NK_Null; } }; -/// @brief A scalar node is an opaque datum that can be presented as a +/// \brief A scalar node is an opaque datum that can be presented as a /// series of zero or more Unicode scalar values. /// /// Example: /// Adena class ScalarNode : public Node { - virtual void anchor(); + void anchor() override; + public: - ScalarNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, + ScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, StringRef Val) : Node(NK_Scalar, D, Anchor, Tag), Value(Val) { SMLoc Start = SMLoc::getFromPointer(Val.begin()); @@ -207,9 +205,9 @@ public: // utf8). StringRef getRawValue() const { return Value; } - /// @brief Gets the value of this node as a StringRef. + /// \brief Gets the value of this node as a StringRef. /// - /// @param Storage is used to store the content of the returned StringRef iff + /// \param Storage is used to store the content of the returned StringRef iff /// it requires any modification from how it appeared in the source. /// This happens with escaped characters and multi-line literals. StringRef getValue(SmallVectorImpl<char> &Storage) const; @@ -221,12 +219,12 @@ public: private: StringRef Value; - StringRef unescapeDoubleQuoted( StringRef UnquotedValue - , StringRef::size_type Start - , SmallVectorImpl<char> &Storage) const; + StringRef unescapeDoubleQuoted(StringRef UnquotedValue, + StringRef::size_type Start, + SmallVectorImpl<char> &Storage) const; }; -/// @brief A key and value pair. While not technically a Node under the YAML +/// \brief A key and value pair. While not technically a Node under the YAML /// representation graph, it is easier to treat them this way. /// /// TODO: Consider making this not a child of Node. @@ -234,29 +232,28 @@ private: /// Example: /// Section: .text class KeyValueNode : public Node { - virtual void anchor(); + void anchor() override; + public: - KeyValueNode(OwningPtr<Document> &D) - : Node(NK_KeyValue, D, StringRef(), StringRef()) - , Key(0) - , Value(0) - {} + KeyValueNode(std::unique_ptr<Document> &D) + : Node(NK_KeyValue, D, StringRef(), StringRef()), Key(nullptr), + Value(nullptr) {} - /// @brief Parse and return the key. + /// \brief Parse and return the key. /// /// This may be called multiple times. /// - /// @returns The key, or nullptr if failed() == true. + /// \returns The key, or nullptr if failed() == true. Node *getKey(); - /// @brief Parse and return the value. + /// \brief Parse and return the value. /// /// This may be called multiple times. /// - /// @returns The value, or nullptr if failed() == true. + /// \returns The value, or nullptr if failed() == true. Node *getValue(); - virtual void skip() LLVM_OVERRIDE { + void skip() override { getKey()->skip(); getValue()->skip(); } @@ -270,47 +267,47 @@ private: Node *Value; }; -/// @brief This is an iterator abstraction over YAML collections shared by both +/// \brief This is an iterator abstraction over YAML collections shared by both /// sequences and maps. /// /// BaseT must have a ValueT* member named CurrentEntry and a member function /// increment() which must set CurrentEntry to 0 to create an end iterator. template <class BaseT, class ValueT> class basic_collection_iterator - : public std::iterator<std::forward_iterator_tag, ValueT> { + : public std::iterator<std::forward_iterator_tag, ValueT> { public: - basic_collection_iterator() : Base(0) {} + basic_collection_iterator() : Base(nullptr) {} basic_collection_iterator(BaseT *B) : Base(B) {} - ValueT *operator ->() const { + ValueT *operator->() const { assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); return Base->CurrentEntry; } - ValueT &operator *() const { + ValueT &operator*() const { assert(Base && Base->CurrentEntry && "Attempted to dereference end iterator!"); return *Base->CurrentEntry; } - operator ValueT*() const { + operator ValueT *() const { assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); return Base->CurrentEntry; } - bool operator !=(const basic_collection_iterator &Other) const { - if(Base != Other.Base) + bool operator!=(const basic_collection_iterator &Other) const { + if (Base != Other.Base) return true; - return (Base && Other.Base) && Base->CurrentEntry - != Other.Base->CurrentEntry; + return (Base && Other.Base) && + Base->CurrentEntry != Other.Base->CurrentEntry; } basic_collection_iterator &operator++() { assert(Base && "Attempted to advance iterator past end!"); Base->increment(); // Create an end iterator. - if (Base->CurrentEntry == 0) - Base = 0; + if (!Base->CurrentEntry) + Base = nullptr; return *this; } @@ -328,17 +325,16 @@ typename CollectionType::iterator begin(CollectionType &C) { return ret; } -template <class CollectionType> -void skip(CollectionType &C) { +template <class CollectionType> void skip(CollectionType &C) { // TODO: support skipping from the middle of a parsed collection ;/ assert((C.IsAtBeginning || C.IsAtEnd) && "Cannot skip mid parse!"); if (C.IsAtBeginning) - for (typename CollectionType::iterator i = begin(C), e = C.end(); - i != e; ++i) + for (typename CollectionType::iterator i = begin(C), e = C.end(); i != e; + ++i) i->skip(); } -/// @brief Represents a YAML map created from either a block map for a flow map. +/// \brief Represents a YAML map created from either a block map for a flow map. /// /// This parses the YAML stream as increment() is called. /// @@ -346,7 +342,8 @@ void skip(CollectionType &C) { /// Name: _main /// Scope: Global class MappingNode : public Node { - virtual void anchor(); + void anchor() override; + public: enum MappingType { MT_Block, @@ -354,25 +351,21 @@ public: MT_Inline ///< An inline mapping node is used for "[key: value]". }; - MappingNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, + MappingNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, MappingType MT) : Node(NK_Mapping, D, Anchor, Tag), Type(MT), IsAtBeginning(true), - IsAtEnd(false), CurrentEntry(0) {} + IsAtEnd(false), CurrentEntry(nullptr) {} friend class basic_collection_iterator<MappingNode, KeyValueNode>; typedef basic_collection_iterator<MappingNode, KeyValueNode> iterator; template <class T> friend typename T::iterator yaml::begin(T &); template <class T> friend void yaml::skip(T &); - iterator begin() { - return yaml::begin(*this); - } + iterator begin() { return yaml::begin(*this); } iterator end() { return iterator(); } - virtual void skip() LLVM_OVERRIDE { - yaml::skip(*this); - } + void skip() override { yaml::skip(*this); } static inline bool classof(const Node *N) { return N->getType() == NK_Mapping; @@ -387,7 +380,7 @@ private: void increment(); }; -/// @brief Represents a YAML sequence created from either a block sequence for a +/// \brief Represents a YAML sequence created from either a block sequence for a /// flow sequence. /// /// This parses the YAML stream as increment() is called. @@ -396,7 +389,8 @@ private: /// - Hello /// - World class SequenceNode : public Node { - virtual void anchor(); + void anchor() override; + public: enum SequenceType { ST_Block, @@ -411,12 +405,12 @@ public: ST_Indentless }; - SequenceNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, + SequenceNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, SequenceType ST) : Node(NK_Sequence, D, Anchor, Tag), SeqType(ST), IsAtBeginning(true), IsAtEnd(false), WasPreviousTokenFlowEntry(true), // Start with an imaginary ','. - CurrentEntry(0) {} + CurrentEntry(nullptr) {} friend class basic_collection_iterator<SequenceNode, Node>; typedef basic_collection_iterator<SequenceNode, Node> iterator; @@ -425,15 +419,11 @@ public: void increment(); - iterator begin() { - return yaml::begin(*this); - } + iterator begin() { return yaml::begin(*this); } iterator end() { return iterator(); } - virtual void skip() LLVM_OVERRIDE { - yaml::skip(*this); - } + void skip() override { yaml::skip(*this); } static inline bool classof(const Node *N) { return N->getType() == NK_Sequence; @@ -447,63 +437,60 @@ private: Node *CurrentEntry; }; -/// @brief Represents an alias to a Node with an anchor. +/// \brief Represents an alias to a Node with an anchor. /// /// Example: /// *AnchorName class AliasNode : public Node { - virtual void anchor(); + void anchor() override; + public: - AliasNode(OwningPtr<Document> &D, StringRef Val) - : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} + AliasNode(std::unique_ptr<Document> &D, StringRef Val) + : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} StringRef getName() const { return Name; } Node *getTarget(); - static inline bool classof(const Node *N) { - return N->getType() == NK_Alias; - } + static inline bool classof(const Node *N) { return N->getType() == NK_Alias; } private: StringRef Name; }; -/// @brief A YAML Stream is a sequence of Documents. A document contains a root +/// \brief A YAML Stream is a sequence of Documents. A document contains a root /// node. class Document { public: - /// @brief Root for parsing a node. Returns a single node. + /// \brief Root for parsing a node. Returns a single node. Node *parseBlockNode(); Document(Stream &ParentStream); - /// @brief Finish parsing the current document and return true if there are + /// \brief Finish parsing the current document and return true if there are /// more. Return false otherwise. bool skip(); - /// @brief Parse and return the root level node. + /// \brief Parse and return the root level node. Node *getRoot() { if (Root) return Root; return Root = parseBlockNode(); } - const std::map<StringRef, StringRef> &getTagMap() const { - return TagMap; - } + const std::map<StringRef, StringRef> &getTagMap() const { return TagMap; } private: friend class Node; friend class document_iterator; - /// @brief Stream to read tokens from. + /// \brief Stream to read tokens from. Stream &stream; - /// @brief Used to allocate nodes to. All are destroyed without calling their + /// \brief Used to allocate nodes to. All are destroyed without calling their /// destructor when the document is destroyed. BumpPtrAllocator NodeAllocator; - /// @brief The root node. Used to support skipping a partially parsed + /// \brief The root node. Used to support skipping a partially parsed /// document. Node *Root; @@ -515,7 +502,7 @@ private: void setError(const Twine &Message, Token &Location) const; bool failed() const; - /// @brief Parse %BLAH directives and return true if any were encountered. + /// \brief Parse %BLAH directives and return true if any were encountered. bool parseDirectives(); /// \brief Parse %YAML @@ -524,30 +511,28 @@ private: /// \brief Parse %TAG void parseTAGDirective(); - /// @brief Consume the next token and error if it is not \a TK. + /// \brief Consume the next token and error if it is not \a TK. bool expectToken(int TK); }; -/// @brief Iterator abstraction for Documents over a Stream. +/// \brief Iterator abstraction for Documents over a Stream. class document_iterator { public: - document_iterator() : Doc(0) {} - document_iterator(OwningPtr<Document> &D) : Doc(&D) {} + document_iterator() : Doc(nullptr) {} + document_iterator(std::unique_ptr<Document> &D) : Doc(&D) {} - bool operator ==(const document_iterator &Other) { + bool operator==(const document_iterator &Other) { if (isAtEnd() || Other.isAtEnd()) return isAtEnd() && Other.isAtEnd(); return Doc == Other.Doc; } - bool operator !=(const document_iterator &Other) { - return !(*this == Other); - } + bool operator!=(const document_iterator &Other) { return !(*this == Other); } - document_iterator operator ++() { - assert(Doc != 0 && "incrementing iterator past the end."); + document_iterator operator++() { + assert(Doc && "incrementing iterator past the end."); if (!(*Doc)->skip()) { - Doc->reset(0); + Doc->reset(nullptr); } else { Stream &S = (*Doc)->stream; Doc->reset(new Document(S)); @@ -555,23 +540,18 @@ public: return *this; } - Document &operator *() { - return *Doc->get(); - } + Document &operator*() { return *Doc->get(); } - OwningPtr<Document> &operator ->() { - return *Doc; - } + std::unique_ptr<Document> &operator->() { return *Doc; } private: - bool isAtEnd() const { - return !Doc || !*Doc; - } + bool isAtEnd() const { return !Doc || !*Doc; } - OwningPtr<Document> *Doc; + std::unique_ptr<Document> *Doc; }; -} -} +} // End namespace yaml. + +} // End namespace llvm. #endif diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index c19eb23c5cd0..a23faf65bb59 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -1,4 +1,4 @@ -//===- llvm/Supporrt/YAMLTraits.h -------------------------------*- C++ -*-===// +//===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===// // // The LLVM Linker // @@ -13,19 +13,18 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Regex.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/YAMLParser.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" -#include "llvm/Support/type_traits.h" - +#include <system_error> namespace llvm { namespace yaml { @@ -34,7 +33,7 @@ namespace yaml { /// This class should be specialized by any type that needs to be converted /// to/from a YAML mapping. For example: /// -/// struct ScalarBitSetTraits<MyStruct> { +/// struct MappingTraits<MyStruct> { /// static void mapping(IO &io, MyStruct &s) { /// io.mapRequired("name", s.name); /// io.mapRequired("size", s.size); @@ -45,6 +44,8 @@ template<class T> struct MappingTraits { // Must provide: // static void mapping(IO &io, T &fields); + // Optionally may provide: + // static StringRef validate(IO &io, T &fields); }; @@ -98,6 +99,7 @@ struct ScalarBitSetTraits { /// // return empty string on success, or error string /// return StringRef(); /// } +/// static bool mustQuote(StringRef) { return true; } /// }; template<typename T> struct ScalarTraits { @@ -109,6 +111,9 @@ struct ScalarTraits { // Function to convert a string to a value. Returns the empty // StringRef on success or an error string if string is malformed: //static StringRef input(StringRef scalar, void *ctxt, T &value); + // + // Function to determine if the value should be quoted. + //static bool mustQuote(StringRef); }; @@ -171,7 +176,8 @@ struct has_ScalarEnumerationTraits static double test(...); public: - static bool const value = (sizeof(test<ScalarEnumerationTraits<T> >(0)) == 1); + static bool const value = + (sizeof(test<ScalarEnumerationTraits<T> >(nullptr)) == 1); }; @@ -188,7 +194,7 @@ struct has_ScalarBitSetTraits static double test(...); public: - static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(0)) == 1); + static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(nullptr)) == 1); }; @@ -198,16 +204,19 @@ struct has_ScalarTraits { typedef StringRef (*Signature_input)(StringRef, void*, T&); typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&); + typedef bool (*Signature_mustQuote)(StringRef); template <typename U> - static char test(SameType<Signature_input, &U::input>*, - SameType<Signature_output, &U::output>*); + static char test(SameType<Signature_input, &U::input> *, + SameType<Signature_output, &U::output> *, + SameType<Signature_mustQuote, &U::mustQuote> *); template <typename U> static double test(...); public: - static bool const value = (sizeof(test<ScalarTraits<T> >(0,0)) == 1); + static bool const value = + (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1); }; @@ -224,9 +233,26 @@ struct has_MappingTraits static double test(...); public: - static bool const value = (sizeof(test<MappingTraits<T> >(0)) == 1); + static bool const value = (sizeof(test<MappingTraits<T> >(nullptr)) == 1); }; +// Test if MappingTraits<T>::validate() is defined on type T. +template <class T> +struct has_MappingValidateTraits +{ + typedef StringRef (*Signature_validate)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_validate, &U::validate>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<MappingTraits<T> >(nullptr)) == 1); +}; + + // Test if SequenceTraits<T> is defined on type T. template <class T> @@ -241,14 +267,14 @@ struct has_SequenceMethodTraits static double test(...); public: - static bool const value = (sizeof(test<SequenceTraits<T> >(0)) == 1); + static bool const value = (sizeof(test<SequenceTraits<T> >(nullptr)) == 1); }; // has_FlowTraits<int> will cause an error with some compilers because // it subclasses int. Using this wrapper only instantiates the // real has_FlowTraits only if the template type is a class. -template <typename T, bool Enabled = llvm::is_class<T>::value> +template <typename T, bool Enabled = std::is_class<T>::value> class has_FlowTraits { public: @@ -271,14 +297,14 @@ struct has_FlowTraits<T, true> static char (&f(...))[2]; public: - static bool const value = sizeof(f<Derived>(0)) == 2; + static bool const value = sizeof(f<Derived>(nullptr)) == 2; }; // Test if SequenceTraits<T> is defined on type T template<typename T> -struct has_SequenceTraits : public llvm::integral_constant<bool, +struct has_SequenceTraits : public std::integral_constant<bool, has_SequenceMethodTraits<T>::value > { }; @@ -295,14 +321,88 @@ struct has_DocumentListTraits static double test(...); public: - static bool const value = (sizeof(test<DocumentListTraits<T> >(0)) == 1); + static bool const value = (sizeof(test<DocumentListTraits<T> >(nullptr))==1); }; +inline bool isNumber(StringRef S) { + static const char OctalChars[] = "01234567"; + if (S.startswith("0") && + S.drop_front().find_first_not_of(OctalChars) == StringRef::npos) + return true; + + if (S.startswith("0o") && + S.drop_front(2).find_first_not_of(OctalChars) == StringRef::npos) + return true; + + static const char HexChars[] = "0123456789abcdefABCDEF"; + if (S.startswith("0x") && + S.drop_front(2).find_first_not_of(HexChars) == StringRef::npos) + return true; + + static const char DecChars[] = "0123456789"; + if (S.find_first_not_of(DecChars) == StringRef::npos) + return true; + if (S.equals(".inf") || S.equals(".Inf") || S.equals(".INF")) + return true; + + Regex FloatMatcher("^(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$"); + if (FloatMatcher.match(S)) + return true; + + return false; +} + +inline bool isNumeric(StringRef S) { + if ((S.front() == '-' || S.front() == '+') && isNumber(S.drop_front())) + return true; + + if (isNumber(S)) + return true; + + if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN")) + return true; + + return false; +} + +inline bool isNull(StringRef S) { + return S.equals("null") || S.equals("Null") || S.equals("NULL") || + S.equals("~"); +} + +inline bool isBool(StringRef S) { + return S.equals("true") || S.equals("True") || S.equals("TRUE") || + S.equals("false") || S.equals("False") || S.equals("FALSE"); +} + +inline bool needsQuotes(StringRef S) { + if (S.empty()) + return true; + if (isspace(S.front()) || isspace(S.back())) + return true; + if (S.front() == ',') + return true; + + static const char ScalarSafeChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t"; + if (S.find_first_not_of(ScalarSafeChars) != StringRef::npos) + return true; + + if (isNull(S)) + return true; + if (isBool(S)) + return true; + if (isNumeric(S)) + return true; + + return false; +} template<typename T> -struct missingTraits : public llvm::integral_constant<bool, +struct missingTraits : public std::integral_constant<bool, !has_ScalarEnumerationTraits<T>::value && !has_ScalarBitSetTraits<T>::value && !has_ScalarTraits<T>::value @@ -310,15 +410,23 @@ struct missingTraits : public llvm::integral_constant<bool, && !has_SequenceTraits<T>::value && !has_DocumentListTraits<T>::value > {}; +template<typename T> +struct validatedMappingTraits : public std::integral_constant<bool, + has_MappingTraits<T>::value + && has_MappingValidateTraits<T>::value> {}; +template<typename T> +struct unvalidatedMappingTraits : public std::integral_constant<bool, + has_MappingTraits<T>::value + && !has_MappingValidateTraits<T>::value> {}; // Base class for Input and Output. class IO { public: - IO(void *Ctxt=NULL); + IO(void *Ctxt=nullptr); virtual ~IO(); - virtual bool outputting() const = 0; + virtual bool outputting() = 0; virtual unsigned beginSequence() = 0; virtual bool preflightElement(unsigned, void *&) = 0; @@ -345,7 +453,7 @@ public: virtual bool bitSetMatch(const char*, bool) = 0; virtual void endBitSetScalar() = 0; - virtual void scalarString(StringRef &) = 0; + virtual void scalarString(StringRef &, bool) = 0; virtual void setError(const Twine &) = 0; @@ -379,6 +487,19 @@ public: } } + template <typename T> + void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) { + if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) + Val = Val | ConstVal; + } + + template <typename T> + void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal, + uint32_t Mask) { + if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) + Val = Val | ConstVal; + } + void *getContext(); void setContext(void *); @@ -388,7 +509,7 @@ public: } template <typename T> - typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type + typename std::enable_if<has_SequenceTraits<T>::value,void>::type mapOptional(const char* Key, T& Val) { // omit key/value instead of outputting empty sequence if ( this->canElideEmptySequence() && !(Val.begin() != Val.end()) ) @@ -397,7 +518,12 @@ public: } template <typename T> - typename llvm::enable_if_c<!has_SequenceTraits<T>::value,void>::type + void mapOptional(const char* Key, Optional<T> &Val) { + processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false); + } + + template <typename T> + typename std::enable_if<!has_SequenceTraits<T>::value,void>::type mapOptional(const char* Key, T& Val) { this->processKey(Key, Val, false); } @@ -409,6 +535,26 @@ public: private: template <typename T> + void processKeyWithDefault(const char *Key, Optional<T> &Val, + const Optional<T> &DefaultValue, bool Required) { + assert(DefaultValue.hasValue() == false && + "Optional<T> shouldn't have a value!"); + void *SaveInfo; + bool UseDefault; + const bool sameAsDefault = outputting() && !Val.hasValue(); + if (!outputting() && !Val.hasValue()) + Val = T(); + if (this->preflightKey(Key, Required, sameAsDefault, UseDefault, + SaveInfo)) { + yamlize(*this, Val.getValue(), Required); + this->postflightKey(SaveInfo); + } else { + if (UseDefault) + Val = DefaultValue; + } + } + + template <typename T> void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue, bool Required) { void *SaveInfo; @@ -442,7 +588,7 @@ private: template<typename T> -typename llvm::enable_if_c<has_ScalarEnumerationTraits<T>::value,void>::type +typename std::enable_if<has_ScalarEnumerationTraits<T>::value,void>::type yamlize(IO &io, T &Val, bool) { io.beginEnumScalar(); ScalarEnumerationTraits<T>::enumeration(io, Val); @@ -450,7 +596,7 @@ yamlize(IO &io, T &Val, bool) { } template<typename T> -typename llvm::enable_if_c<has_ScalarBitSetTraits<T>::value,void>::type +typename std::enable_if<has_ScalarBitSetTraits<T>::value,void>::type yamlize(IO &io, T &Val, bool) { bool DoClear; if ( io.beginBitSetScalar(DoClear) ) { @@ -463,18 +609,18 @@ yamlize(IO &io, T &Val, bool) { template<typename T> -typename llvm::enable_if_c<has_ScalarTraits<T>::value,void>::type +typename std::enable_if<has_ScalarTraits<T>::value,void>::type yamlize(IO &io, T &Val, bool) { if ( io.outputting() ) { std::string Storage; llvm::raw_string_ostream Buffer(Storage); ScalarTraits<T>::output(Val, io.getContext(), Buffer); StringRef Str = Buffer.str(); - io.scalarString(Str); + io.scalarString(Str, ScalarTraits<T>::mustQuote(Str)); } else { StringRef Str; - io.scalarString(Str); + io.scalarString(Str, ScalarTraits<T>::mustQuote(Str)); StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val); if ( !Result.empty() ) { io.setError(llvm::Twine(Result)); @@ -484,21 +630,41 @@ yamlize(IO &io, T &Val, bool) { template<typename T> -typename llvm::enable_if_c<has_MappingTraits<T>::value, void>::type +typename std::enable_if<validatedMappingTraits<T>::value, void>::type yamlize(IO &io, T &Val, bool) { io.beginMapping(); + if (io.outputting()) { + StringRef Err = MappingTraits<T>::validate(io, Val); + if (!Err.empty()) { + llvm::errs() << Err << "\n"; + assert(Err.empty() && "invalid struct trying to be written as yaml"); + } + } MappingTraits<T>::mapping(io, Val); + if (!io.outputting()) { + StringRef Err = MappingTraits<T>::validate(io, Val); + if (!Err.empty()) + io.setError(Err); + } io.endMapping(); } template<typename T> -typename llvm::enable_if_c<missingTraits<T>::value, void>::type +typename std::enable_if<unvalidatedMappingTraits<T>::value, void>::type +yamlize(IO &io, T &Val, bool) { + io.beginMapping(); + MappingTraits<T>::mapping(io, Val); + io.endMapping(); +} + +template<typename T> +typename std::enable_if<missingTraits<T>::value, void>::type yamlize(IO &io, T &Val, bool) { char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; } template<typename T> -typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type +typename std::enable_if<has_SequenceTraits<T>::value,void>::type yamlize(IO &io, T &Seq, bool) { if ( has_FlowTraits< SequenceTraits<T> >::value ) { unsigned incnt = io.beginFlowSequence(); @@ -531,72 +697,91 @@ template<> struct ScalarTraits<bool> { static void output(const bool &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, bool &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<StringRef> { static void output(const StringRef &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, StringRef &); + static bool mustQuote(StringRef S) { return needsQuotes(S); } +}; + +template<> +struct ScalarTraits<std::string> { + static void output(const std::string &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, std::string &); + static bool mustQuote(StringRef S) { return needsQuotes(S); } }; template<> struct ScalarTraits<uint8_t> { static void output(const uint8_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, uint8_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<uint16_t> { static void output(const uint16_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, uint16_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<uint32_t> { static void output(const uint32_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, uint32_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<uint64_t> { static void output(const uint64_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, uint64_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<int8_t> { static void output(const int8_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, int8_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<int16_t> { static void output(const int16_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, int16_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<int32_t> { static void output(const int32_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, int32_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<int64_t> { static void output(const int64_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, int64_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<float> { static void output(const float &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, float &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<double> { static void output(const double &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, double &); + static bool mustQuote(StringRef) { return false; } }; @@ -606,7 +791,7 @@ struct ScalarTraits<double> { template <typename TNorm, typename TFinal> struct MappingNormalization { MappingNormalization(IO &i_o, TFinal &Obj) - : io(i_o), BufPtr(NULL), Result(Obj) { + : io(i_o), BufPtr(nullptr), Result(Obj) { if ( io.outputting() ) { BufPtr = new (&Buffer) TNorm(io, Obj); } @@ -689,40 +874,38 @@ public: // user-data. The DiagHandler can be specified to provide // alternative error reporting. Input(StringRef InputContent, - void *Ctxt = NULL, - SourceMgr::DiagHandlerTy DiagHandler = NULL, - void *DiagHandlerCtxt = NULL); + void *Ctxt = nullptr, + SourceMgr::DiagHandlerTy DiagHandler = nullptr, + void *DiagHandlerCtxt = nullptr); ~Input(); // Check if there was an syntax or semantic error during parsing. - llvm::error_code error(); - - static bool classof(const IO *io) { return !io->outputting(); } + std::error_code error(); private: - virtual bool outputting() const; - virtual bool mapTag(StringRef, bool); - virtual void beginMapping(); - virtual void endMapping(); - virtual bool preflightKey(const char *, bool, bool, bool &, void *&); - virtual void postflightKey(void *); - virtual unsigned beginSequence(); - virtual void endSequence(); - virtual bool preflightElement(unsigned index, void *&); - virtual void postflightElement(void *); - virtual unsigned beginFlowSequence(); - virtual bool preflightFlowElement(unsigned , void *&); - virtual void postflightFlowElement(void *); - virtual void endFlowSequence(); - virtual void beginEnumScalar(); - virtual bool matchEnumScalar(const char*, bool); - virtual void endEnumScalar(); - virtual bool beginBitSetScalar(bool &); - virtual bool bitSetMatch(const char *, bool ); - virtual void endBitSetScalar(); - virtual void scalarString(StringRef &); - virtual void setError(const Twine &message); - virtual bool canElideEmptySequence(); + bool outputting() override; + bool mapTag(StringRef, bool) override; + void beginMapping() override; + void endMapping() override; + bool preflightKey(const char *, bool, bool, bool &, void *&) override; + void postflightKey(void *) override; + unsigned beginSequence() override; + void endSequence() override; + bool preflightElement(unsigned index, void *&) override; + void postflightElement(void *) override; + unsigned beginFlowSequence() override; + bool preflightFlowElement(unsigned , void *&) override; + void postflightFlowElement(void *) override; + void endFlowSequence() override; + void beginEnumScalar() override; + bool matchEnumScalar(const char*, bool) override; + void endEnumScalar() override; + bool beginBitSetScalar(bool &) override; + bool bitSetMatch(const char *, bool ) override; + void endBitSetScalar() override; + void scalarString(StringRef &, bool) override; + void setError(const Twine &message) override; + bool canElideEmptySequence() override; class HNode { virtual void anchor(); @@ -735,7 +918,7 @@ private: }; class EmptyHNode : public HNode { - virtual void anchor(); + void anchor() override; public: EmptyHNode(Node *n) : HNode(n) { } static inline bool classof(const HNode *n) { @@ -745,7 +928,7 @@ private: }; class ScalarHNode : public HNode { - virtual void anchor(); + void anchor() override; public: ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } @@ -799,18 +982,18 @@ public: // These are only used by operator>>. They could be private // if those templated things could be made friends. bool setCurrentDocument(); - void nextDocument(); + bool nextDocument(); private: - llvm::SourceMgr SrcMgr; // must be before Strm - OwningPtr<llvm::yaml::Stream> Strm; - OwningPtr<HNode> TopNode; - llvm::error_code EC; - llvm::BumpPtrAllocator StringAllocator; - llvm::yaml::document_iterator DocIterator; - std::vector<bool> BitValuesUsed; - HNode *CurrentNode; - bool ScalarMatchFound; + llvm::SourceMgr SrcMgr; // must be before Strm + std::unique_ptr<llvm::yaml::Stream> Strm; + std::unique_ptr<HNode> TopNode; + std::error_code EC; + llvm::BumpPtrAllocator StringAllocator; + llvm::yaml::document_iterator DocIterator; + std::vector<bool> BitValuesUsed; + HNode *CurrentNode; + bool ScalarMatchFound; }; @@ -822,34 +1005,32 @@ private: /// class Output : public IO { public: - Output(llvm::raw_ostream &, void *Ctxt=NULL); + Output(llvm::raw_ostream &, void *Ctxt=nullptr); virtual ~Output(); - static bool classof(const IO *io) { return io->outputting(); } - - virtual bool outputting() const; - virtual bool mapTag(StringRef, bool); - virtual void beginMapping(); - virtual void endMapping(); - virtual bool preflightKey(const char *key, bool, bool, bool &, void *&); - virtual void postflightKey(void *); - virtual unsigned beginSequence(); - virtual void endSequence(); - virtual bool preflightElement(unsigned, void *&); - virtual void postflightElement(void *); - virtual unsigned beginFlowSequence(); - virtual bool preflightFlowElement(unsigned, void *&); - virtual void postflightFlowElement(void *); - virtual void endFlowSequence(); - virtual void beginEnumScalar(); - virtual bool matchEnumScalar(const char*, bool); - virtual void endEnumScalar(); - virtual bool beginBitSetScalar(bool &); - virtual bool bitSetMatch(const char *, bool ); - virtual void endBitSetScalar(); - virtual void scalarString(StringRef &); - virtual void setError(const Twine &message); - virtual bool canElideEmptySequence(); + bool outputting() override; + bool mapTag(StringRef, bool) override; + void beginMapping() override; + void endMapping() override; + bool preflightKey(const char *key, bool, bool, bool &, void *&) override; + void postflightKey(void *) override; + unsigned beginSequence() override; + void endSequence() override; + bool preflightElement(unsigned, void *&) override; + void postflightElement(void *) override; + unsigned beginFlowSequence() override; + bool preflightFlowElement(unsigned, void *&) override; + void postflightFlowElement(void *) override; + void endFlowSequence() override; + void beginEnumScalar() override; + bool matchEnumScalar(const char*, bool) override; + void endEnumScalar() override; + bool beginBitSetScalar(bool &) override; + bool bitSetMatch(const char *, bool ) override; + void endBitSetScalar() override; + void scalarString(StringRef &, bool) override; + void setError(const Twine &message) override; + bool canElideEmptySequence() override; public: // These are only used by operator<<. They could be private // if that templated operator could be made a friend. @@ -918,31 +1099,35 @@ template<> struct ScalarTraits<Hex8> { static void output(const Hex8 &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, Hex8 &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<Hex16> { static void output(const Hex16 &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, Hex16 &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<Hex32> { static void output(const Hex32 &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, Hex32 &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<Hex64> { static void output(const Hex64 &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, Hex64 &); + static bool mustQuote(StringRef) { return false; } }; // Define non-member operator>> so that Input can stream in a document list. template <typename T> inline -typename llvm::enable_if_c<has_DocumentListTraits<T>::value,Input &>::type +typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type operator>>(Input &yin, T &docList) { int i = 0; while ( yin.setCurrentDocument() ) { @@ -958,7 +1143,7 @@ operator>>(Input &yin, T &docList) { // Define non-member operator>> so that Input can stream in a map as a document. template <typename T> inline -typename llvm::enable_if_c<has_MappingTraits<T>::value,Input &>::type +typename std::enable_if<has_MappingTraits<T>::value, Input &>::type operator>>(Input &yin, T &docMap) { yin.setCurrentDocument(); yamlize(yin, docMap, true); @@ -969,7 +1154,7 @@ operator>>(Input &yin, T &docMap) { // a document. template <typename T> inline -typename llvm::enable_if_c<has_SequenceTraits<T>::value,Input &>::type +typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type operator>>(Input &yin, T &docSeq) { if (yin.setCurrentDocument()) yamlize(yin, docSeq, true); @@ -979,7 +1164,7 @@ operator>>(Input &yin, T &docSeq) { // Provide better error message about types missing a trait specialization template <typename T> inline -typename llvm::enable_if_c<missingTraits<T>::value,Input &>::type +typename std::enable_if<missingTraits<T>::value, Input &>::type operator>>(Input &yin, T &docSeq) { char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; return yin; @@ -989,7 +1174,7 @@ operator>>(Input &yin, T &docSeq) { // Define non-member operator<< so that Output can stream out document list. template <typename T> inline -typename llvm::enable_if_c<has_DocumentListTraits<T>::value,Output &>::type +typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type operator<<(Output &yout, T &docList) { yout.beginDocuments(); const size_t count = DocumentListTraits<T>::size(yout, docList); @@ -1006,7 +1191,7 @@ operator<<(Output &yout, T &docList) { // Define non-member operator<< so that Output can stream out a map. template <typename T> inline -typename llvm::enable_if_c<has_MappingTraits<T>::value,Output &>::type +typename std::enable_if<has_MappingTraits<T>::value, Output &>::type operator<<(Output &yout, T &map) { yout.beginDocuments(); if ( yout.preflightDocument(0) ) { @@ -1020,7 +1205,7 @@ operator<<(Output &yout, T &map) { // Define non-member operator<< so that Output can stream out a sequence. template <typename T> inline -typename llvm::enable_if_c<has_SequenceTraits<T>::value,Output &>::type +typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type operator<<(Output &yout, T &seq) { yout.beginDocuments(); if ( yout.preflightDocument(0) ) { @@ -1034,7 +1219,7 @@ operator<<(Output &yout, T &seq) { // Provide better error message about types missing a trait specialization template <typename T> inline -typename llvm::enable_if_c<missingTraits<T>::value,Output &>::type +typename std::enable_if<missingTraits<T>::value, Output &>::type operator<<(Output &yout, T &seq) { char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; return yout; @@ -1075,6 +1260,7 @@ operator<<(Output &yout, T &seq) { return seq.size(); \ } \ static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ + (void)flow; /* Remove this workaround after PR17897 is fixed */ \ if ( index >= seq.size() ) \ seq.resize(index+1); \ return seq[index]; \ diff --git a/include/llvm/Support/circular_raw_ostream.h b/include/llvm/Support/circular_raw_ostream.h index 900030685725..ee7b89fe8c8d 100644 --- a/include/llvm/Support/circular_raw_ostream.h +++ b/include/llvm/Support/circular_raw_ostream.h @@ -81,12 +81,12 @@ namespace llvm Filled = false; } - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, /// not counting the bytes currently in the buffer. /// - virtual uint64_t current_pos() const LLVM_OVERRIDE { + uint64_t current_pos() const override { // This has the same effect as calling TheStream.current_pos(), // but that interface is private. return TheStream->tell() - TheStream->GetNumBytesInBuffer(); @@ -109,10 +109,10 @@ namespace llvm circular_raw_ostream(raw_ostream &Stream, const char *Header, size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) : raw_ostream(/*unbuffered*/true), - TheStream(0), + TheStream(nullptr), OwnsStream(Owns), BufferSize(BuffSize), - BufferArray(0), + BufferArray(nullptr), Filled(false), Banner(Header) { if (BufferSize != 0) @@ -122,9 +122,9 @@ namespace llvm } explicit circular_raw_ostream() : raw_ostream(/*unbuffered*/true), - TheStream(0), + TheStream(nullptr), OwnsStream(REFERENCE_ONLY), - BufferArray(0), + BufferArray(nullptr), Filled(false), Banner("") { Cur = BufferArray; diff --git a/include/llvm/Support/raw_os_ostream.h b/include/llvm/Support/raw_os_ostream.h index 4385721e8206..04cf3b6202c4 100644 --- a/include/llvm/Support/raw_os_ostream.h +++ b/include/llvm/Support/raw_os_ostream.h @@ -26,11 +26,11 @@ class raw_os_ostream : public raw_ostream { std::ostream &OS; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE; + uint64_t current_pos() const override; public: raw_os_ostream(std::ostream &O) : OS(O) {} diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index ec7e06b535e5..34fbe082cda8 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -17,13 +17,18 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/FileSystem.h" namespace llvm { class format_object_base; template <typename T> class SmallVectorImpl; + namespace sys { + namespace fs { + enum OpenFlags : unsigned; + } + } + /// raw_ostream - This class implements an extremely fast bulk output stream /// that can *only* output to a stream. It does not support seeking, reopening, /// rewinding, line buffered disciplines etc. It is a simple buffer that outputs @@ -76,7 +81,7 @@ public: explicit raw_ostream(bool unbuffered=false) : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { // Start out ready to flush. - OutBufStart = OutBufEnd = OutBufCur = 0; + OutBufStart = OutBufEnd = OutBufCur = nullptr; } virtual ~raw_ostream(); @@ -102,7 +107,7 @@ public: size_t GetBufferSize() const { // If we're supposed to be buffered but haven't actually gotten around // to allocating the buffer yet, return the value that would be used. - if (BufferMode != Unbuffered && OutBufStart == 0) + if (BufferMode != Unbuffered && OutBufStart == nullptr) return preferred_buffer_size(); // Otherwise just return the size of the allocated buffer. @@ -115,7 +120,7 @@ public: /// set to unbuffered. void SetUnbuffered() { flush(); - SetBufferAndMode(0, 0, Unbuffered); + SetBufferAndMode(nullptr, 0, Unbuffered); } size_t GetNumBytesInBuffer() const { @@ -157,7 +162,7 @@ public: size_t Size = Str.size(); // Make sure we can use the fast path. - if (OutBufCur+Size > OutBufEnd) + if (Size > (size_t)(OutBufEnd - OutBufCur)) return write(Str.data(), Size); memcpy(OutBufCur, Str.data(), Size); @@ -322,14 +327,14 @@ class raw_fd_ostream : public raw_ostream { uint64_t pos; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE { return pos; } + uint64_t current_pos() const override { return pos; } /// preferred_buffer_size - Determine an efficient buffer size. - virtual size_t preferred_buffer_size() const LLVM_OVERRIDE; + size_t preferred_buffer_size() const override; /// error_detected - Set the flag indicating that an output error has /// been encountered. @@ -347,7 +352,7 @@ public: /// file descriptor when it is done (this is necessary to detect /// output errors). raw_fd_ostream(const char *Filename, std::string &ErrorInfo, - sys::fs::OpenFlags Flags = sys::fs::F_None); + sys::fs::OpenFlags Flags); /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If /// ShouldClose is true, this closes the file when the stream is destroyed. @@ -373,15 +378,15 @@ public: UseAtomicWrites = Value; } - virtual raw_ostream &changeColor(enum Colors colors, bool bold=false, - bool bg=false) LLVM_OVERRIDE; - virtual raw_ostream &resetColor() LLVM_OVERRIDE; + raw_ostream &changeColor(enum Colors colors, bool bold=false, + bool bg=false) override; + raw_ostream &resetColor() override; - virtual raw_ostream &reverseColor() LLVM_OVERRIDE; + raw_ostream &reverseColor() override; - virtual bool is_displayed() const LLVM_OVERRIDE; + bool is_displayed() const override; - virtual bool has_colors() const LLVM_OVERRIDE; + bool has_colors() const override; /// has_error - Return the value of the flag in this raw_fd_ostream indicating /// whether an output error has been encountered. @@ -427,11 +432,11 @@ class raw_string_ostream : public raw_ostream { std::string &OS; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE { return OS.size(); } + uint64_t current_pos() const override { return OS.size(); } public: explicit raw_string_ostream(std::string &O) : OS(O) {} ~raw_string_ostream(); @@ -451,11 +456,11 @@ class raw_svector_ostream : public raw_ostream { SmallVectorImpl<char> &OS; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE; + uint64_t current_pos() const override; public: /// Construct a new raw_svector_ostream. /// @@ -477,11 +482,11 @@ public: /// raw_null_ostream - A raw_ostream that discards all output. class raw_null_ostream : public raw_ostream { /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t size) override; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE; + uint64_t current_pos() const override; public: explicit raw_null_ostream() {} diff --git a/include/llvm/Support/system_error.h b/include/llvm/Support/system_error.h deleted file mode 100644 index 43dace6ab816..000000000000 --- a/include/llvm/Support/system_error.h +++ /dev/null @@ -1,905 +0,0 @@ -//===---------------------------- system_error ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This was lifted from libc++ and modified for C++03. This is called -// system_error even though it does not define that class because that's what -// it's called in C++0x. We don't define system_error because it is only used -// for exception handling, which we don't use in LLVM. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_SYSTEM_ERROR_H -#define LLVM_SUPPORT_SYSTEM_ERROR_H - -#include "llvm/Support/Compiler.h" - -/* - system_error synopsis - -namespace std -{ - -class error_category -{ -public: - virtual ~error_category(); - - error_category(const error_category&) = delete; - error_category& operator=(const error_category&) = delete; - - virtual const char* name() const = 0; - virtual error_condition default_error_condition(int ev) const; - virtual bool equivalent(int code, const error_condition& condition) const; - virtual bool equivalent(const error_code& code, int condition) const; - virtual std::string message(int ev) const = 0; - - bool operator==(const error_category& rhs) const; - bool operator!=(const error_category& rhs) const; - bool operator<(const error_category& rhs) const; -}; - -const error_category& generic_category(); -const error_category& system_category(); - -template <class T> struct is_error_code_enum - : public false_type {}; - -template <class T> struct is_error_condition_enum - : public false_type {}; - -class error_code -{ -public: - // constructors: - error_code(); - error_code(int val, const error_category& cat); - template <class ErrorCodeEnum> - error_code(ErrorCodeEnum e); - - // modifiers: - void assign(int val, const error_category& cat); - template <class ErrorCodeEnum> - error_code& operator=(ErrorCodeEnum e); - void clear(); - - // observers: - int value() const; - const error_category& category() const; - error_condition default_error_condition() const; - std::string message() const; - explicit operator bool() const; -}; - -// non-member functions: -bool operator<(const error_code& lhs, const error_code& rhs); -template <class charT, class traits> - basic_ostream<charT,traits>& - operator<<(basic_ostream<charT,traits>& os, const error_code& ec); - -class error_condition -{ -public: - // constructors: - error_condition(); - error_condition(int val, const error_category& cat); - template <class ErrorConditionEnum> - error_condition(ErrorConditionEnum e); - - // modifiers: - void assign(int val, const error_category& cat); - template <class ErrorConditionEnum> - error_condition& operator=(ErrorConditionEnum e); - void clear(); - - // observers: - int value() const; - const error_category& category() const; - std::string message() const; - explicit operator bool() const; -}; - -bool operator<(const error_condition& lhs, const error_condition& rhs); - -class system_error - : public runtime_error -{ -public: - system_error(error_code ec, const std::string& what_arg); - system_error(error_code ec, const char* what_arg); - system_error(error_code ec); - system_error(int ev, const error_category& ecat, const std::string& what_arg); - system_error(int ev, const error_category& ecat, const char* what_arg); - system_error(int ev, const error_category& ecat); - - const error_code& code() const throw(); - const char* what() const throw(); -}; - -enum class errc -{ - address_family_not_supported, // EAFNOSUPPORT - address_in_use, // EADDRINUSE - address_not_available, // EADDRNOTAVAIL - already_connected, // EISCONN - argument_list_too_long, // E2BIG - argument_out_of_domain, // EDOM - bad_address, // EFAULT - bad_file_descriptor, // EBADF - bad_message, // EBADMSG - broken_pipe, // EPIPE - connection_aborted, // ECONNABORTED - connection_already_in_progress, // EALREADY - connection_refused, // ECONNREFUSED - connection_reset, // ECONNRESET - cross_device_link, // EXDEV - destination_address_required, // EDESTADDRREQ - device_or_resource_busy, // EBUSY - directory_not_empty, // ENOTEMPTY - executable_format_error, // ENOEXEC - file_exists, // EEXIST - file_too_large, // EFBIG - filename_too_long, // ENAMETOOLONG - function_not_supported, // ENOSYS - host_unreachable, // EHOSTUNREACH - identifier_removed, // EIDRM - illegal_byte_sequence, // EILSEQ - inappropriate_io_control_operation, // ENOTTY - interrupted, // EINTR - invalid_argument, // EINVAL - invalid_seek, // ESPIPE - io_error, // EIO - is_a_directory, // EISDIR - message_size, // EMSGSIZE - network_down, // ENETDOWN - network_reset, // ENETRESET - network_unreachable, // ENETUNREACH - no_buffer_space, // ENOBUFS - no_child_process, // ECHILD - no_link, // ENOLINK - no_lock_available, // ENOLCK - no_message_available, // ENODATA - no_message, // ENOMSG - no_protocol_option, // ENOPROTOOPT - no_space_on_device, // ENOSPC - no_stream_resources, // ENOSR - no_such_device_or_address, // ENXIO - no_such_device, // ENODEV - no_such_file_or_directory, // ENOENT - no_such_process, // ESRCH - not_a_directory, // ENOTDIR - not_a_socket, // ENOTSOCK - not_a_stream, // ENOSTR - not_connected, // ENOTCONN - not_enough_memory, // ENOMEM - not_supported, // ENOTSUP - operation_canceled, // ECANCELED - operation_in_progress, // EINPROGRESS - operation_not_permitted, // EPERM - operation_not_supported, // EOPNOTSUPP - operation_would_block, // EWOULDBLOCK - owner_dead, // EOWNERDEAD - permission_denied, // EACCES - protocol_error, // EPROTO - protocol_not_supported, // EPROTONOSUPPORT - read_only_file_system, // EROFS - resource_deadlock_would_occur, // EDEADLK - resource_unavailable_try_again, // EAGAIN - result_out_of_range, // ERANGE - state_not_recoverable, // ENOTRECOVERABLE - stream_timeout, // ETIME - text_file_busy, // ETXTBSY - timed_out, // ETIMEDOUT - too_many_files_open_in_system, // ENFILE - too_many_files_open, // EMFILE - too_many_links, // EMLINK - too_many_symbolic_link_levels, // ELOOP - value_too_large, // EOVERFLOW - wrong_protocol_type // EPROTOTYPE -}; - -template <> struct is_error_condition_enum<errc> : true_type { } - -error_code make_error_code(errc e); -error_condition make_error_condition(errc e); - -// Comparison operators: -bool operator==(const error_code& lhs, const error_code& rhs); -bool operator==(const error_code& lhs, const error_condition& rhs); -bool operator==(const error_condition& lhs, const error_code& rhs); -bool operator==(const error_condition& lhs, const error_condition& rhs); -bool operator!=(const error_code& lhs, const error_code& rhs); -bool operator!=(const error_code& lhs, const error_condition& rhs); -bool operator!=(const error_condition& lhs, const error_code& rhs); -bool operator!=(const error_condition& lhs, const error_condition& rhs); - -template <> struct hash<std::error_code>; - -} // std - -*/ - -#include "llvm/Config/llvm-config.h" -#include "llvm/Support/type_traits.h" -#include <cerrno> -#include <string> - -// This must be here instead of a .inc file because it is used in the definition -// of the enum values below. -#ifdef LLVM_ON_WIN32 - - // The following numbers were taken from VS2010. -# ifndef EAFNOSUPPORT -# define EAFNOSUPPORT 102 -# endif -# ifndef EADDRINUSE -# define EADDRINUSE 100 -# endif -# ifndef EADDRNOTAVAIL -# define EADDRNOTAVAIL 101 -# endif -# ifndef EISCONN -# define EISCONN 113 -# endif -# ifndef E2BIG -# define E2BIG 7 -# endif -# ifndef EDOM -# define EDOM 33 -# endif -# ifndef EFAULT -# define EFAULT 14 -# endif -# ifndef EBADF -# define EBADF 9 -# endif -# ifndef EBADMSG -# define EBADMSG 104 -# endif -# ifndef EPIPE -# define EPIPE 32 -# endif -# ifndef ECONNABORTED -# define ECONNABORTED 106 -# endif -# ifndef EALREADY -# define EALREADY 103 -# endif -# ifndef ECONNREFUSED -# define ECONNREFUSED 107 -# endif -# ifndef ECONNRESET -# define ECONNRESET 108 -# endif -# ifndef EXDEV -# define EXDEV 18 -# endif -# ifndef EDESTADDRREQ -# define EDESTADDRREQ 109 -# endif -# ifndef EBUSY -# define EBUSY 16 -# endif -# ifndef ENOTEMPTY -# define ENOTEMPTY 41 -# endif -# ifndef ENOEXEC -# define ENOEXEC 8 -# endif -# ifndef EEXIST -# define EEXIST 17 -# endif -# ifndef EFBIG -# define EFBIG 27 -# endif -# ifndef ENAMETOOLONG -# define ENAMETOOLONG 38 -# endif -# ifndef ENOSYS -# define ENOSYS 40 -# endif -# ifndef EHOSTUNREACH -# define EHOSTUNREACH 110 -# endif -# ifndef EIDRM -# define EIDRM 111 -# endif -# ifndef EILSEQ -# define EILSEQ 42 -# endif -# ifndef ENOTTY -# define ENOTTY 25 -# endif -# ifndef EINTR -# define EINTR 4 -# endif -# ifndef EINVAL -# define EINVAL 22 -# endif -# ifndef ESPIPE -# define ESPIPE 29 -# endif -# ifndef EIO -# define EIO 5 -# endif -# ifndef EISDIR -# define EISDIR 21 -# endif -# ifndef EMSGSIZE -# define EMSGSIZE 115 -# endif -# ifndef ENETDOWN -# define ENETDOWN 116 -# endif -# ifndef ENETRESET -# define ENETRESET 117 -# endif -# ifndef ENETUNREACH -# define ENETUNREACH 118 -# endif -# ifndef ENOBUFS -# define ENOBUFS 119 -# endif -# ifndef ECHILD -# define ECHILD 10 -# endif -# ifndef ENOLINK -# define ENOLINK 121 -# endif -# ifndef ENOLCK -# define ENOLCK 39 -# endif -# ifndef ENODATA -# define ENODATA 120 -# endif -# ifndef ENOMSG -# define ENOMSG 122 -# endif -# ifndef ENOPROTOOPT -# define ENOPROTOOPT 123 -# endif -# ifndef ENOSPC -# define ENOSPC 28 -# endif -# ifndef ENOSR -# define ENOSR 124 -# endif -# ifndef ENXIO -# define ENXIO 6 -# endif -# ifndef ENODEV -# define ENODEV 19 -# endif -# ifndef ENOENT -# define ENOENT 2 -# endif -# ifndef ESRCH -# define ESRCH 3 -# endif -# ifndef ENOTDIR -# define ENOTDIR 20 -# endif -# ifndef ENOTSOCK -# define ENOTSOCK 128 -# endif -# ifndef ENOSTR -# define ENOSTR 125 -# endif -# ifndef ENOTCONN -# define ENOTCONN 126 -# endif -# ifndef ENOMEM -# define ENOMEM 12 -# endif -# ifndef ENOTSUP -# define ENOTSUP 129 -# endif -# ifndef ECANCELED -# define ECANCELED 105 -# endif -# ifndef EINPROGRESS -# define EINPROGRESS 112 -# endif -# ifndef EPERM -# define EPERM 1 -# endif -# ifndef EOPNOTSUPP -# define EOPNOTSUPP 130 -# endif -# ifndef EWOULDBLOCK -# define EWOULDBLOCK 140 -# endif -# ifndef EOWNERDEAD -# define EOWNERDEAD 133 -# endif -# ifndef EACCES -# define EACCES 13 -# endif -# ifndef EPROTO -# define EPROTO 134 -# endif -# ifndef EPROTONOSUPPORT -# define EPROTONOSUPPORT 135 -# endif -# ifndef EROFS -# define EROFS 30 -# endif -# ifndef EDEADLK -# define EDEADLK 36 -# endif -# ifndef EAGAIN -# define EAGAIN 11 -# endif -# ifndef ERANGE -# define ERANGE 34 -# endif -# ifndef ENOTRECOVERABLE -# define ENOTRECOVERABLE 127 -# endif -# ifndef ETIME -# define ETIME 137 -# endif -# ifndef ETXTBSY -# define ETXTBSY 139 -# endif -# ifndef ETIMEDOUT -# define ETIMEDOUT 138 -# endif -# ifndef ENFILE -# define ENFILE 23 -# endif -# ifndef EMFILE -# define EMFILE 24 -# endif -# ifndef EMLINK -# define EMLINK 31 -# endif -# ifndef ELOOP -# define ELOOP 114 -# endif -# ifndef EOVERFLOW -# define EOVERFLOW 132 -# endif -# ifndef EPROTOTYPE -# define EPROTOTYPE 136 -# endif -#endif - -namespace llvm { - -// is_error_code_enum - -template <class Tp> struct is_error_code_enum : public false_type {}; - -// is_error_condition_enum - -template <class Tp> struct is_error_condition_enum : public false_type {}; - -// Some error codes are not present on all platforms, so we provide equivalents -// for them: - -//enum class errc -struct errc { -enum _ { - success = 0, - address_family_not_supported = EAFNOSUPPORT, - address_in_use = EADDRINUSE, - address_not_available = EADDRNOTAVAIL, - already_connected = EISCONN, - argument_list_too_long = E2BIG, - argument_out_of_domain = EDOM, - bad_address = EFAULT, - bad_file_descriptor = EBADF, -#ifdef EBADMSG - bad_message = EBADMSG, -#else - bad_message = EINVAL, -#endif - broken_pipe = EPIPE, - connection_aborted = ECONNABORTED, - connection_already_in_progress = EALREADY, - connection_refused = ECONNREFUSED, - connection_reset = ECONNRESET, - cross_device_link = EXDEV, - destination_address_required = EDESTADDRREQ, - device_or_resource_busy = EBUSY, - directory_not_empty = ENOTEMPTY, - executable_format_error = ENOEXEC, - file_exists = EEXIST, - file_too_large = EFBIG, - filename_too_long = ENAMETOOLONG, - function_not_supported = ENOSYS, - host_unreachable = EHOSTUNREACH, - identifier_removed = EIDRM, - illegal_byte_sequence = EILSEQ, - inappropriate_io_control_operation = ENOTTY, - interrupted = EINTR, - invalid_argument = EINVAL, - invalid_seek = ESPIPE, - io_error = EIO, - is_a_directory = EISDIR, - message_size = EMSGSIZE, - network_down = ENETDOWN, - network_reset = ENETRESET, - network_unreachable = ENETUNREACH, - no_buffer_space = ENOBUFS, - no_child_process = ECHILD, -#ifdef ENOLINK - no_link = ENOLINK, -#else - no_link = EINVAL, -#endif - no_lock_available = ENOLCK, -#ifdef ENODATA - no_message_available = ENODATA, -#else - no_message_available = ENOMSG, -#endif - no_message = ENOMSG, - no_protocol_option = ENOPROTOOPT, - no_space_on_device = ENOSPC, -#ifdef ENOSR - no_stream_resources = ENOSR, -#else - no_stream_resources = ENOMEM, -#endif - no_such_device_or_address = ENXIO, - no_such_device = ENODEV, - no_such_file_or_directory = ENOENT, - no_such_process = ESRCH, - not_a_directory = ENOTDIR, - not_a_socket = ENOTSOCK, -#ifdef ENOSTR - not_a_stream = ENOSTR, -#else - not_a_stream = EINVAL, -#endif - not_connected = ENOTCONN, - not_enough_memory = ENOMEM, - not_supported = ENOTSUP, -#ifdef ECANCELED - operation_canceled = ECANCELED, -#else - operation_canceled = EINVAL, -#endif - operation_in_progress = EINPROGRESS, - operation_not_permitted = EPERM, - operation_not_supported = EOPNOTSUPP, - operation_would_block = EWOULDBLOCK, -#ifdef EOWNERDEAD - owner_dead = EOWNERDEAD, -#else - owner_dead = EINVAL, -#endif - permission_denied = EACCES, -#ifdef EPROTO - protocol_error = EPROTO, -#else - protocol_error = EINVAL, -#endif - protocol_not_supported = EPROTONOSUPPORT, - read_only_file_system = EROFS, - resource_deadlock_would_occur = EDEADLK, - resource_unavailable_try_again = EAGAIN, - result_out_of_range = ERANGE, -#ifdef ENOTRECOVERABLE - state_not_recoverable = ENOTRECOVERABLE, -#else - state_not_recoverable = EINVAL, -#endif -#ifdef ETIME - stream_timeout = ETIME, -#else - stream_timeout = ETIMEDOUT, -#endif - text_file_busy = ETXTBSY, - timed_out = ETIMEDOUT, - too_many_files_open_in_system = ENFILE, - too_many_files_open = EMFILE, - too_many_links = EMLINK, - too_many_symbolic_link_levels = ELOOP, - value_too_large = EOVERFLOW, - wrong_protocol_type = EPROTOTYPE -}; - - _ v_; - - errc(_ v) : v_(v) {} - operator int() const {return v_;} -}; - -template <> struct is_error_condition_enum<errc> : true_type { }; - -template <> struct is_error_condition_enum<errc::_> : true_type { }; - -class error_condition; -class error_code; - -// class error_category - -class _do_message; - -class error_category -{ -public: - virtual ~error_category(); - -private: - error_category(); - error_category(const error_category&) LLVM_DELETED_FUNCTION; - error_category& operator=(const error_category&) LLVM_DELETED_FUNCTION; - -public: - virtual const char* name() const = 0; - virtual error_condition default_error_condition(int _ev) const; - virtual bool equivalent(int _code, const error_condition& _condition) const; - virtual bool equivalent(const error_code& _code, int _condition) const; - virtual std::string message(int _ev) const = 0; - - bool operator==(const error_category& _rhs) const {return this == &_rhs;} - - bool operator!=(const error_category& _rhs) const {return !(*this == _rhs);} - - bool operator< (const error_category& _rhs) const {return this < &_rhs;} - - friend class _do_message; -}; - -class _do_message : public error_category -{ -public: - virtual std::string message(int ev) const LLVM_OVERRIDE; -}; - -const error_category& generic_category(); -const error_category& system_category(); - -/// Get the error_category used for errno values from POSIX functions. This is -/// the same as the system_category on POSIX systems, but is the same as the -/// generic_category on Windows. -const error_category& posix_category(); - -class error_condition -{ - int _val_; - const error_category* _cat_; -public: - error_condition() : _val_(0), _cat_(&generic_category()) {} - - error_condition(int _val, const error_category& _cat) - : _val_(_val), _cat_(&_cat) {} - - template <class E> - error_condition(E _e, typename enable_if_c< - is_error_condition_enum<E>::value - >::type* = 0) - {*this = make_error_condition(_e);} - - void assign(int _val, const error_category& _cat) { - _val_ = _val; - _cat_ = &_cat; - } - - template <class E> - typename enable_if_c - < - is_error_condition_enum<E>::value, - error_condition& - >::type - operator=(E _e) - {*this = make_error_condition(_e); return *this;} - - void clear() { - _val_ = 0; - _cat_ = &generic_category(); - } - - int value() const {return _val_;} - - const error_category& category() const {return *_cat_;} - std::string message() const; - - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} - - operator unspecified_bool_type() const { // true if error - return _val_ == 0 ? 0 : unspecified_bool_true; - } -}; - -inline error_condition make_error_condition(errc _e) { - return error_condition(static_cast<int>(_e), generic_category()); -} - -inline bool operator<(const error_condition& _x, const error_condition& _y) { - return _x.category() < _y.category() - || (_x.category() == _y.category() && _x.value() < _y.value()); -} - -// error_code - -class error_code { - int _val_; - const error_category* _cat_; -public: - error_code() : _val_(0), _cat_(&system_category()) {} - - static error_code success() { - return error_code(); - } - - error_code(int _val, const error_category& _cat) - : _val_(_val), _cat_(&_cat) {} - - template <class E> - error_code(E _e, typename enable_if_c< - is_error_code_enum<E>::value - >::type* = 0) { - *this = make_error_code(_e); - } - - void assign(int _val, const error_category& _cat) { - _val_ = _val; - _cat_ = &_cat; - } - - template <class E> - typename enable_if_c - < - is_error_code_enum<E>::value, - error_code& - >::type - operator=(E _e) - {*this = make_error_code(_e); return *this;} - - void clear() { - _val_ = 0; - _cat_ = &system_category(); - } - - int value() const {return _val_;} - - const error_category& category() const {return *_cat_;} - - error_condition default_error_condition() const - {return _cat_->default_error_condition(_val_);} - - std::string message() const; - - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} - - operator unspecified_bool_type() const { // true if error - return _val_ == 0 ? 0 : unspecified_bool_true; - } -}; - -inline error_code make_error_code(errc _e) { - return error_code(static_cast<int>(_e), generic_category()); -} - -inline bool operator<(const error_code& _x, const error_code& _y) { - return _x.category() < _y.category() - || (_x.category() == _y.category() && _x.value() < _y.value()); -} - -inline bool operator==(const error_code& _x, const error_code& _y) { - return _x.category() == _y.category() && _x.value() == _y.value(); -} - -inline bool operator==(const error_code& _x, const error_condition& _y) { - return _x.category().equivalent(_x.value(), _y) - || _y.category().equivalent(_x, _y.value()); -} - -inline bool operator==(const error_condition& _x, const error_code& _y) { - return _y == _x; -} - -inline bool operator==(const error_condition& _x, const error_condition& _y) { - return _x.category() == _y.category() && _x.value() == _y.value(); -} - -inline bool operator!=(const error_code& _x, const error_code& _y) { - return !(_x == _y); -} - -inline bool operator!=(const error_code& _x, const error_condition& _y) { - return !(_x == _y); -} - -inline bool operator!=(const error_condition& _x, const error_code& _y) { - return !(_x == _y); -} - -inline bool operator!=(const error_condition& _x, const error_condition& _y) { - return !(_x == _y); -} - -// Windows errors. - -// To construct an error_code after an API error: -// -// error_code( ::GetLastError(), system_category() ) -struct windows_error { -enum _ { - success = 0, - // These names and values are based on Windows WinError.h - // This is not a complete list. Add to this list if you need to explicitly - // check for it. - invalid_function = 1, // ERROR_INVALID_FUNCTION, - file_not_found = 2, // ERROR_FILE_NOT_FOUND, - path_not_found = 3, // ERROR_PATH_NOT_FOUND, - too_many_open_files = 4, // ERROR_TOO_MANY_OPEN_FILES, - access_denied = 5, // ERROR_ACCESS_DENIED, - invalid_handle = 6, // ERROR_INVALID_HANDLE, - arena_trashed = 7, // ERROR_ARENA_TRASHED, - not_enough_memory = 8, // ERROR_NOT_ENOUGH_MEMORY, - invalid_block = 9, // ERROR_INVALID_BLOCK, - bad_environment = 10, // ERROR_BAD_ENVIRONMENT, - bad_format = 11, // ERROR_BAD_FORMAT, - invalid_access = 12, // ERROR_INVALID_ACCESS, - outofmemory = 14, // ERROR_OUTOFMEMORY, - invalid_drive = 15, // ERROR_INVALID_DRIVE, - current_directory = 16, // ERROR_CURRENT_DIRECTORY, - not_same_device = 17, // ERROR_NOT_SAME_DEVICE, - no_more_files = 18, // ERROR_NO_MORE_FILES, - write_protect = 19, // ERROR_WRITE_PROTECT, - bad_unit = 20, // ERROR_BAD_UNIT, - not_ready = 21, // ERROR_NOT_READY, - bad_command = 22, // ERROR_BAD_COMMAND, - crc = 23, // ERROR_CRC, - bad_length = 24, // ERROR_BAD_LENGTH, - seek = 25, // ERROR_SEEK, - not_dos_disk = 26, // ERROR_NOT_DOS_DISK, - sector_not_found = 27, // ERROR_SECTOR_NOT_FOUND, - out_of_paper = 28, // ERROR_OUT_OF_PAPER, - write_fault = 29, // ERROR_WRITE_FAULT, - read_fault = 30, // ERROR_READ_FAULT, - gen_failure = 31, // ERROR_GEN_FAILURE, - sharing_violation = 32, // ERROR_SHARING_VIOLATION, - lock_violation = 33, // ERROR_LOCK_VIOLATION, - wrong_disk = 34, // ERROR_WRONG_DISK, - sharing_buffer_exceeded = 36, // ERROR_SHARING_BUFFER_EXCEEDED, - handle_eof = 38, // ERROR_HANDLE_EOF, - handle_disk_full = 39, // ERROR_HANDLE_DISK_FULL, - rem_not_list = 51, // ERROR_REM_NOT_LIST, - dup_name = 52, // ERROR_DUP_NAME, - bad_net_path = 53, // ERROR_BAD_NETPATH, - network_busy = 54, // ERROR_NETWORK_BUSY, - file_exists = 80, // ERROR_FILE_EXISTS, - cannot_make = 82, // ERROR_CANNOT_MAKE, - broken_pipe = 109, // ERROR_BROKEN_PIPE, - open_failed = 110, // ERROR_OPEN_FAILED, - buffer_overflow = 111, // ERROR_BUFFER_OVERFLOW, - disk_full = 112, // ERROR_DISK_FULL, - insufficient_buffer = 122, // ERROR_INSUFFICIENT_BUFFER, - lock_failed = 167, // ERROR_LOCK_FAILED, - busy = 170, // ERROR_BUSY, - cancel_violation = 173, // ERROR_CANCEL_VIOLATION, - already_exists = 183 // ERROR_ALREADY_EXISTS -}; - _ v_; - - windows_error(_ v) : v_(v) {} - explicit windows_error(int v) : v_(_(v)) {} - operator int() const {return v_;} -}; - - -template <> struct is_error_code_enum<windows_error> : true_type { }; - -template <> struct is_error_code_enum<windows_error::_> : true_type { }; - -inline error_code make_error_code(windows_error e) { - return error_code(static_cast<int>(e), system_category()); -} - -} // end namespace llvm - -#endif diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index 906e97c91fb6..70953a9cb70e 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -7,18 +7,14 @@ // //===----------------------------------------------------------------------===// // -// This file provides a template class that determines if a type is a class or -// not. The basic mechanism, based on using the pointer to member function of -// a zero argument to a function was "boosted" from the boost type_traits -// library. See http://www.boost.org/ for all the gory details. +// This file provides useful additions to the standard type_traits library. // //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_TYPE_TRAITS_H #define LLVM_SUPPORT_TYPE_TRAITS_H -#include "llvm/Support/DataTypes.h" -#include <cstddef> +#include <type_traits> #include <utility> #ifndef __has_feature @@ -26,40 +22,8 @@ #define __has_feature(x) 0 #endif -// This is actually the conforming implementation which works with abstract -// classes. However, enough compilers have trouble with it that most will use -// the one in boost/type_traits/object_traits.hpp. This implementation actually -// works with VC7.0, but other interactions seem to fail when we use it. - namespace llvm { - -namespace dont_use -{ - // These two functions should never be used. They are helpers to - // the is_class template below. They cannot be located inside - // is_class because doing so causes at least GCC to think that - // the value of the "value" enumerator is not constant. Placing - // them out here (for some strange reason) allows the sizeof - // operator against them to magically be constant. This is - // important to make the is_class<T>::value idiom zero cost. it - // evaluates to a constant 1 or 0 depending on whether the - // parameter T is a class or not (respectively). - template<typename T> char is_class_helper(void(T::*)()); - template<typename T> double is_class_helper(...); -} -template <typename T> -struct is_class -{ - // is_class<> metafunction due to Paul Mensonides (leavings@attbi.com). For - // more details: - // http://groups.google.com/groups?hl=en&selm=000001c1cc83%24e154d5e0%247772e50c%40c161550a&rnum=1 -public: - static const bool value = - sizeof(char) == sizeof(dont_use::is_class_helper<T>(0)); -}; - - /// isPodLike - This is a type trait that is used to determine whether a given /// type can be copied around with memcpy instead of running ctors etc. template <typename T> @@ -71,7 +35,7 @@ struct isPodLike { #else // If we don't know anything else, we can (at least) assume that all non-class // types are PODs. - static const bool value = !is_class<T>::value; + static const bool value = !std::is_class<T>::value; #endif }; @@ -80,161 +44,45 @@ template<typename T, typename U> struct isPodLike<std::pair<T, U> > { static const bool value = isPodLike<T>::value && isPodLike<U>::value; }; - - -template <class T, T v> -struct integral_constant { - typedef T value_type; - static const value_type value = v; - typedef integral_constant<T,v> type; - operator value_type() { return value; } -}; - -typedef integral_constant<bool, true> true_type; -typedef integral_constant<bool, false> false_type; - -/// \brief Metafunction that determines whether the two given types are -/// equivalent. -template<typename T, typename U> struct is_same : public false_type {}; -template<typename T> struct is_same<T, T> : public true_type {}; - -/// \brief Metafunction that removes const qualification from a type. -template <typename T> struct remove_const { typedef T type; }; -template <typename T> struct remove_const<const T> { typedef T type; }; - -/// \brief Metafunction that removes volatile qualification from a type. -template <typename T> struct remove_volatile { typedef T type; }; -template <typename T> struct remove_volatile<volatile T> { typedef T type; }; - -/// \brief Metafunction that removes both const and volatile qualification from -/// a type. -template <typename T> struct remove_cv { - typedef typename remove_const<typename remove_volatile<T>::type>::type type; -}; - -/// \brief Helper to implement is_integral metafunction. -template <typename T> struct is_integral_impl : false_type {}; -template <> struct is_integral_impl< bool> : true_type {}; -template <> struct is_integral_impl< char> : true_type {}; -template <> struct is_integral_impl< signed char> : true_type {}; -template <> struct is_integral_impl<unsigned char> : true_type {}; -template <> struct is_integral_impl< wchar_t> : true_type {}; -template <> struct is_integral_impl< short> : true_type {}; -template <> struct is_integral_impl<unsigned short> : true_type {}; -template <> struct is_integral_impl< int> : true_type {}; -template <> struct is_integral_impl<unsigned int> : true_type {}; -template <> struct is_integral_impl< long> : true_type {}; -template <> struct is_integral_impl<unsigned long> : true_type {}; -template <> struct is_integral_impl< long long> : true_type {}; -template <> struct is_integral_impl<unsigned long long> : true_type {}; - -/// \brief Metafunction that determines whether the given type is an integral -/// type. -template <typename T> -struct is_integral : is_integral_impl<T> {}; - -/// \brief Metafunction to remove reference from a type. -template <typename T> struct remove_reference { typedef T type; }; -template <typename T> struct remove_reference<T&> { typedef T type; }; - -/// \brief Metafunction that determines whether the given type is a pointer -/// type. -template <typename T> struct is_pointer : false_type {}; -template <typename T> struct is_pointer<T*> : true_type {}; -template <typename T> struct is_pointer<T* const> : true_type {}; -template <typename T> struct is_pointer<T* volatile> : true_type {}; -template <typename T> struct is_pointer<T* const volatile> : true_type {}; - -/// \brief Metafunction that determines wheather the given type is a reference. -template <typename T> struct is_reference : false_type {}; -template <typename T> struct is_reference<T&> : true_type {}; /// \brief Metafunction that determines whether the given type is either an /// integral type or an enumeration type. /// -/// Note that this accepts potentially more integral types than we whitelist -/// above for is_integral because it is based on merely being convertible -/// implicitly to an integral type. +/// Note that this accepts potentially more integral types than is_integral +/// because it is based on merely being convertible implicitly to an integral +/// type. template <typename T> class is_integral_or_enum { - // Provide an overload which can be called with anything implicitly - // convertible to an unsigned long long. This should catch integer types and - // enumeration types at least. We blacklist classes with conversion operators - // below. - static double check_int_convertible(unsigned long long); - static char check_int_convertible(...); - - typedef typename remove_reference<T>::type UnderlyingT; - static UnderlyingT &nonce_instance; + typedef typename std::remove_reference<T>::type UnderlyingT; public: - static const bool - value = (!is_class<UnderlyingT>::value && !is_pointer<UnderlyingT>::value && - !is_same<UnderlyingT, float>::value && - !is_same<UnderlyingT, double>::value && - sizeof(char) != sizeof(check_int_convertible(nonce_instance))); -}; - -// enable_if_c - Enable/disable a template based on a metafunction -template<bool Cond, typename T = void> -struct enable_if_c { - typedef T type; -}; - -template<typename T> struct enable_if_c<false, T> { }; - -// enable_if - Enable/disable a template based on a metafunction -template<typename Cond, typename T = void> -struct enable_if : public enable_if_c<Cond::value, T> { }; - -namespace dont_use { - template<typename Base> char base_of_helper(const volatile Base*); - template<typename Base> double base_of_helper(...); -} - -/// is_base_of - Metafunction to determine whether one type is a base class of -/// (or identical to) another type. -template<typename Base, typename Derived> -struct is_base_of { - static const bool value - = is_class<Base>::value && is_class<Derived>::value && - sizeof(char) == sizeof(dont_use::base_of_helper<Base>((Derived*)0)); + static const bool value = + !std::is_class<UnderlyingT>::value && // Filter conversion operators. + !std::is_pointer<UnderlyingT>::value && + !std::is_floating_point<UnderlyingT>::value && + std::is_convertible<UnderlyingT, unsigned long long>::value; }; -// remove_pointer - Metafunction to turn Foo* into Foo. Defined in -// C++0x [meta.trans.ptr]. -template <typename T> struct remove_pointer { typedef T type; }; -template <typename T> struct remove_pointer<T*> { typedef T type; }; -template <typename T> struct remove_pointer<T*const> { typedef T type; }; -template <typename T> struct remove_pointer<T*volatile> { typedef T type; }; -template <typename T> struct remove_pointer<T*const volatile> { - typedef T type; }; - -// If T is a pointer, just return it. If it is not, return T&. +/// \brief If T is a pointer, just return it. If it is not, return T&. template<typename T, typename Enable = void> struct add_lvalue_reference_if_not_pointer { typedef T &type; }; -template<typename T> -struct add_lvalue_reference_if_not_pointer<T, - typename enable_if<is_pointer<T> >::type> { +template <typename T> +struct add_lvalue_reference_if_not_pointer< + T, typename std::enable_if<std::is_pointer<T>::value>::type> { typedef T type; }; -// If T is a pointer to X, return a pointer to const X. If it is not, return -// const T. +/// \brief If T is a pointer to X, return a pointer to const X. If it is not, +/// return const T. template<typename T, typename Enable = void> struct add_const_past_pointer { typedef const T type; }; -template<typename T> -struct add_const_past_pointer<T, typename enable_if<is_pointer<T> >::type> { - typedef const typename remove_pointer<T>::type *type; +template <typename T> +struct add_const_past_pointer< + T, typename std::enable_if<std::is_pointer<T>::value>::type> { + typedef const typename std::remove_pointer<T>::type *type; }; -template <bool, typename T, typename F> -struct conditional { typedef T type; }; - -template <typename T, typename F> -struct conditional<false, T, F> { typedef F type; }; - } #ifdef LLVM_DEFINED_HAS_FEATURE diff --git a/include/llvm/TableGen/Error.h b/include/llvm/TableGen/Error.h index 2d0a2b45a96a..3df658df8809 100644 --- a/include/llvm/TableGen/Error.h +++ b/include/llvm/TableGen/Error.h @@ -27,14 +27,13 @@ void PrintError(ArrayRef<SMLoc> ErrorLoc, const Twine &Msg); void PrintError(const char *Loc, const Twine &Msg); void PrintError(const Twine &Msg); -LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const std::string &Msg); +LLVM_ATTRIBUTE_NORETURN void PrintFatalError(const Twine &Msg); LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, - const std::string &Msg); + const Twine &Msg); extern SourceMgr SrcMgr; extern unsigned ErrorsPrinted; - } // end namespace "llvm" #endif diff --git a/include/llvm/TableGen/Main.h b/include/llvm/TableGen/Main.h index 6b51e20146d7..866b9868deb5 100644 --- a/include/llvm/TableGen/Main.h +++ b/include/llvm/TableGen/Main.h @@ -23,7 +23,6 @@ class raw_ostream; typedef bool TableGenMainFn(raw_ostream &OS, RecordKeeper &Records); int TableGenMain(char *argv0, TableGenMainFn *MainFn); - } #endif diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 50352bd9a572..36464d75d5ab 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -87,7 +87,7 @@ private: public: RecTyKind getRecTyKind() const { return Kind; } - RecTy(RecTyKind K) : Kind(K), ListTy(0) {} + RecTy(RecTyKind K) : Kind(K), ListTy(nullptr) {} virtual ~RecTy() {} virtual std::string getAsString() const = 0; @@ -102,12 +102,12 @@ public: ListRecTy *getListTy(); public: // These methods should only be called from subclasses of Init - virtual Init *convertValue( UnsetInit *UI) { return 0; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } + virtual Init *convertValue( UnsetInit *UI) { return nullptr; } + virtual Init *convertValue( BitInit *BI) { return nullptr; } + virtual Init *convertValue( BitsInit *BI) { return nullptr; } + virtual Init *convertValue( IntInit *II) { return nullptr; } + virtual Init *convertValue(StringInit *SI) { return nullptr; } + virtual Init *convertValue( ListInit *LI) { return nullptr; } virtual Init *convertValue( UnOpInit *UI) { return convertValue((TypedInit*)UI); } @@ -117,10 +117,10 @@ public: // These methods should only be called from subclasses of Init virtual Init *convertValue( TernOpInit *UI) { return convertValue((TypedInit*)UI); } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( TypedInit *TI) { return 0; } + virtual Init *convertValue(VarBitInit *VB) { return nullptr; } + virtual Init *convertValue( DefInit *DI) { return nullptr; } + virtual Init *convertValue( DagInit *DI) { return nullptr; } + virtual Init *convertValue( TypedInit *TI) { return nullptr; } virtual Init *convertValue( VarInit *VI) { return convertValue((TypedInit*)VI); } @@ -137,12 +137,12 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) { return OS; } - /// BitRecTy - 'bit' - Represent a single bit /// class BitRecTy : public RecTy { static BitRecTy Shared; BitRecTy() : RecTy(BitRecTyKind) {} + public: static bool classof(const RecTy *RT) { return RT->getRecTyKind() == BitRecTyKind; @@ -150,36 +150,36 @@ public: static BitRecTy *get() { return &Shared; } - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return (Init*)BI; } - virtual Init *convertValue( BitsInit *BI); - virtual Init *convertValue( IntInit *II); - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - virtual std::string getAsString() const { return "bit"; } - - virtual bool typeIsConvertibleTo(const RecTy *RHS) const { + Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } + Init *convertValue( BitInit *BI) override { return (Init*)BI; } + Init *convertValue( BitsInit *BI) override; + Init *convertValue( IntInit *II) override; + Init *convertValue(StringInit *SI) override { return nullptr; } + Init *convertValue( ListInit *LI) override { return nullptr; } + Init *convertValue(VarBitInit *VB) override { return (Init*)VB; } + Init *convertValue( DefInit *DI) override { return nullptr; } + Init *convertValue( DagInit *DI) override { return nullptr; } + Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);} + Init *convertValue( TypedInit *TI) override; + Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} + Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} + + std::string getAsString() const override { return "bit"; } + + bool typeIsConvertibleTo(const RecTy *RHS) const override { return RHS->baseClassOf(this); } - virtual bool baseClassOf(const RecTy*) const; + bool baseClassOf(const RecTy*) const override; }; - /// BitsRecTy - 'bits<n>' - Represent a fixed number of bits /// class BitsRecTy : public RecTy { unsigned Size; explicit BitsRecTy(unsigned Sz) : RecTy(BitsRecTyKind), Size(Sz) {} + public: static bool classof(const RecTy *RT) { return RT->getRecTyKind() == BitsRecTyKind; @@ -189,36 +189,36 @@ public: unsigned getNumBits() const { return Size; } - virtual Init *convertValue( UnsetInit *UI); - virtual Init *convertValue( BitInit *UI); - virtual Init *convertValue( BitsInit *BI); - virtual Init *convertValue( IntInit *II); - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - virtual std::string getAsString() const; - - virtual bool typeIsConvertibleTo(const RecTy *RHS) const { + Init *convertValue( UnsetInit *UI) override; + Init *convertValue( BitInit *UI) override; + Init *convertValue( BitsInit *BI) override; + Init *convertValue( IntInit *II) override; + Init *convertValue(StringInit *SI) override { return nullptr; } + Init *convertValue( ListInit *LI) override { return nullptr; } + Init *convertValue(VarBitInit *VB) override { return nullptr; } + Init *convertValue( DefInit *DI) override { return nullptr; } + Init *convertValue( DagInit *DI) override { return nullptr; } + Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue(TernOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue( TypedInit *TI) override; + Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} + Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} + + std::string getAsString() const override; + + bool typeIsConvertibleTo(const RecTy *RHS) const override { return RHS->baseClassOf(this); } - virtual bool baseClassOf(const RecTy*) const; + bool baseClassOf(const RecTy*) const override; }; - /// IntRecTy - 'int' - Represent an integer value of no particular size /// class IntRecTy : public RecTy { static IntRecTy Shared; IntRecTy() : RecTy(IntRecTyKind) {} + public: static bool classof(const RecTy *RT) { return RT->getRecTyKind() == IntRecTyKind; @@ -226,29 +226,29 @@ public: static IntRecTy *get() { return &Shared; } - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI); - virtual Init *convertValue( BitsInit *BI); - virtual Init *convertValue( IntInit *II) { return (Init*)II; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - virtual std::string getAsString() const { return "int"; } - - virtual bool typeIsConvertibleTo(const RecTy *RHS) const { + Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } + Init *convertValue( BitInit *BI) override; + Init *convertValue( BitsInit *BI) override; + Init *convertValue( IntInit *II) override { return (Init*)II; } + Init *convertValue(StringInit *SI) override { return nullptr; } + Init *convertValue( ListInit *LI) override { return nullptr; } + Init *convertValue(VarBitInit *VB) override { return nullptr; } + Init *convertValue( DefInit *DI) override { return nullptr; } + Init *convertValue( DagInit *DI) override { return nullptr; } + Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);} + Init *convertValue( TypedInit *TI) override; + Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} + Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} + + std::string getAsString() const override { return "int"; } + + bool typeIsConvertibleTo(const RecTy *RHS) const override { return RHS->baseClassOf(this); } - virtual bool baseClassOf(const RecTy*) const; + bool baseClassOf(const RecTy*) const override; }; /// StringRecTy - 'string' - Represent an string value @@ -256,6 +256,7 @@ public: class StringRecTy : public RecTy { static StringRecTy Shared; StringRecTy() : RecTy(StringRecTyKind) {} + public: static bool classof(const RecTy *RT) { return RT->getRecTyKind() == StringRecTyKind; @@ -263,26 +264,26 @@ public: static StringRecTy *get() { return &Shared; } - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return (Init*)SI; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( UnOpInit *BO); - virtual Init *convertValue( BinOpInit *BO); - virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);} - - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - virtual std::string getAsString() const { return "string"; } - - virtual bool typeIsConvertibleTo(const RecTy *RHS) const { + Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } + Init *convertValue( BitInit *BI) override { return nullptr; } + Init *convertValue( BitsInit *BI) override { return nullptr; } + Init *convertValue( IntInit *II) override { return nullptr; } + Init *convertValue(StringInit *SI) override { return (Init*)SI; } + Init *convertValue( ListInit *LI) override { return nullptr; } + Init *convertValue( UnOpInit *BO) override; + Init *convertValue( BinOpInit *BO) override; + Init *convertValue( TernOpInit *BO) override {return RecTy::convertValue(BO);} + + Init *convertValue(VarBitInit *VB) override { return nullptr; } + Init *convertValue( DefInit *DI) override { return nullptr; } + Init *convertValue( DagInit *DI) override { return nullptr; } + Init *convertValue( TypedInit *TI) override; + Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} + Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} + + std::string getAsString() const override { return "string"; } + + bool typeIsConvertibleTo(const RecTy *RHS) const override { return RHS->baseClassOf(this); } }; @@ -294,6 +295,7 @@ class ListRecTy : public RecTy { RecTy *Ty; explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), Ty(T) {} friend ListRecTy *RecTy::getListTy(); + public: static bool classof(const RecTy *RT) { return RT->getRecTyKind() == ListRecTyKind; @@ -302,29 +304,29 @@ public: static ListRecTy *get(RecTy *T) { return T->getListTy(); } RecTy *getElementType() const { return Ty; } - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI); - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - virtual std::string getAsString() const; - - virtual bool typeIsConvertibleTo(const RecTy *RHS) const { + Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } + Init *convertValue( BitInit *BI) override { return nullptr; } + Init *convertValue( BitsInit *BI) override { return nullptr; } + Init *convertValue( IntInit *II) override { return nullptr; } + Init *convertValue(StringInit *SI) override { return nullptr; } + Init *convertValue( ListInit *LI) override; + Init *convertValue(VarBitInit *VB) override { return nullptr; } + Init *convertValue( DefInit *DI) override { return nullptr; } + Init *convertValue( DagInit *DI) override { return nullptr; } + Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue(TernOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue( TypedInit *TI) override; + Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} + Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} + + std::string getAsString() const override; + + bool typeIsConvertibleTo(const RecTy *RHS) const override { return RHS->baseClassOf(this); } - virtual bool baseClassOf(const RecTy*) const; + bool baseClassOf(const RecTy*) const override; }; /// DagRecTy - 'dag' - Represent a dag fragment @@ -332,6 +334,7 @@ public: class DagRecTy : public RecTy { static DagRecTy Shared; DagRecTy() : RecTy(DagRecTyKind) {} + public: static bool classof(const RecTy *RT) { return RT->getRecTyKind() == DagRecTyKind; @@ -339,30 +342,29 @@ public: static DagRecTy *get() { return &Shared; } - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *BO); - virtual Init *convertValue( BinOpInit *BO); - virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);} - virtual Init *convertValue( DagInit *CI) { return (Init*)CI; } - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - virtual std::string getAsString() const { return "dag"; } - - virtual bool typeIsConvertibleTo(const RecTy *RHS) const { + Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } + Init *convertValue( BitInit *BI) override { return nullptr; } + Init *convertValue( BitsInit *BI) override { return nullptr; } + Init *convertValue( IntInit *II) override { return nullptr; } + Init *convertValue(StringInit *SI) override { return nullptr; } + Init *convertValue( ListInit *LI) override { return nullptr; } + Init *convertValue(VarBitInit *VB) override { return nullptr; } + Init *convertValue( DefInit *DI) override { return nullptr; } + Init *convertValue( UnOpInit *BO) override; + Init *convertValue( BinOpInit *BO) override; + Init *convertValue( TernOpInit *BO) override {return RecTy::convertValue(BO);} + Init *convertValue( DagInit *CI) override { return (Init*)CI; } + Init *convertValue( TypedInit *TI) override; + Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} + Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} + + std::string getAsString() const override { return "dag"; } + + bool typeIsConvertibleTo(const RecTy *RHS) const override { return RHS->baseClassOf(this); } }; - /// RecordRecTy - '[classname]' - Represent an instance of a class, such as: /// (R32 X = EAX). /// @@ -370,6 +372,7 @@ class RecordRecTy : public RecTy { Record *Rec; explicit RecordRecTy(Record *R) : RecTy(RecordRecTyKind), Rec(R) {} friend class Record; + public: static bool classof(const RecTy *RT) { return RT->getRecTyKind() == RecordRecTyKind; @@ -379,28 +382,28 @@ public: Record *getRecord() const { return Rec; } - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( DefInit *DI); - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( TypedInit *VI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - virtual std::string getAsString() const; - - virtual bool typeIsConvertibleTo(const RecTy *RHS) const { + Init *convertValue( UnsetInit *UI) override { return (Init*)UI; } + Init *convertValue( BitInit *BI) override { return nullptr; } + Init *convertValue( BitsInit *BI) override { return nullptr; } + Init *convertValue( IntInit *II) override { return nullptr; } + Init *convertValue(StringInit *SI) override { return nullptr; } + Init *convertValue( ListInit *LI) override { return nullptr; } + Init *convertValue(VarBitInit *VB) override { return nullptr; } + Init *convertValue( UnOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue( BinOpInit *UI) override { return RecTy::convertValue(UI);} + Init *convertValue( TernOpInit *UI) override {return RecTy::convertValue(UI);} + Init *convertValue( DefInit *DI) override; + Init *convertValue( DagInit *DI) override { return nullptr; } + Init *convertValue( TypedInit *VI) override; + Init *convertValue( VarInit *VI) override { return RecTy::convertValue(VI);} + Init *convertValue( FieldInit *FI) override { return RecTy::convertValue(FI);} + + std::string getAsString() const override; + + bool typeIsConvertibleTo(const RecTy *RHS) const override { return RHS->baseClassOf(this); } - virtual bool baseClassOf(const RecTy*) const; + bool baseClassOf(const RecTy*) const override; }; /// resolveTypes - Find a common type that T1 and T2 convert to. @@ -496,7 +499,7 @@ public: /// virtual Init * convertInitializerBitRange(const std::vector<unsigned> &Bits) const { - return 0; + return nullptr; } /// convertInitListSlice - This method is used to implement the list slice @@ -506,14 +509,16 @@ public: /// virtual Init * convertInitListSlice(const std::vector<unsigned> &Elements) const { - return 0; + return nullptr; } /// getFieldType - This method is used to implement the FieldInit class. /// Implementors of this method should return the type of the named field if /// they are of record type. /// - virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; } + virtual RecTy *getFieldType(const std::string &FieldName) const { + return nullptr; + } /// getFieldInit - This method complements getFieldType to return the /// initializer for the specified field. If getFieldType returns non-null @@ -521,7 +526,7 @@ public: /// virtual Init *getFieldInit(Record &R, const RecordVal *RV, const std::string &FieldName) const { - return 0; + return nullptr; } /// resolveReferences - This method is used by classes that refer to other @@ -569,16 +574,16 @@ public: } RecTy *getType() const { return Ty; } - virtual Init * - convertInitializerBitRange(const std::vector<unsigned> &Bits) const; - virtual Init * - convertInitListSlice(const std::vector<unsigned> &Elements) const; + Init * + convertInitializerBitRange(const std::vector<unsigned> &Bits) const override; + Init * + convertInitListSlice(const std::vector<unsigned> &Elements) const override; /// getFieldType - This method is used to implement the FieldInit class. /// Implementors of this method should return the type of the named field if /// they are of record type. /// - virtual RecTy *getFieldType(const std::string &FieldName) const; + RecTy *getFieldType(const std::string &FieldName) const override; /// resolveListElementReference - This method is used to implement /// VarListElementInit::resolveReferences. If the list element is resolvable @@ -587,14 +592,13 @@ public: unsigned Elt) const = 0; }; - /// UnsetInit - ? - Represents an uninitialized value /// class UnsetInit : public Init { UnsetInit() : Init(IK_UnsetInit) {} UnsetInit(const UnsetInit &) LLVM_DELETED_FUNCTION; UnsetInit &operator=(const UnsetInit &Other) LLVM_DELETED_FUNCTION; - virtual void anchor(); + void anchor() override; public: static bool classof(const Init *I) { @@ -602,19 +606,18 @@ public: } static UnsetInit *get(); - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<UnsetInit *>(this)); } - virtual Init *getBit(unsigned Bit) const { + Init *getBit(unsigned Bit) const override { return const_cast<UnsetInit*>(this); } - virtual bool isComplete() const { return false; } - virtual std::string getAsString() const { return "?"; } + bool isComplete() const override { return false; } + std::string getAsString() const override { return "?"; } }; - /// BitInit - true/false - Represent a concrete initializer for a bit. /// class BitInit : public Init { @@ -623,7 +626,7 @@ class BitInit : public Init { explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {} BitInit(const BitInit &Other) LLVM_DELETED_FUNCTION; BitInit &operator=(BitInit &Other) LLVM_DELETED_FUNCTION; - virtual void anchor(); + void anchor() override; public: static bool classof(const Init *I) { @@ -633,16 +636,16 @@ public: bool getValue() const { return Value; } - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<BitInit *>(this)); } - virtual Init *getBit(unsigned Bit) const { + Init *getBit(unsigned Bit) const override { assert(Bit < 1 && "Bit index out of range!"); return const_cast<BitInit*>(this); } - virtual std::string getAsString() const { return Value ? "1" : "0"; } + std::string getAsString() const override { return Value ? "1" : "0"; } }; /// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value. @@ -667,13 +670,13 @@ public: unsigned getNumBits() const { return Bits.size(); } - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<BitsInit *>(this)); } - virtual Init * - convertInitializerBitRange(const std::vector<unsigned> &Bits) const; + Init * + convertInitializerBitRange(const std::vector<unsigned> &Bits) const override; - virtual bool isComplete() const { + bool isComplete() const override { for (unsigned i = 0; i != getNumBits(); ++i) if (!getBit(i)->isComplete()) return false; return true; @@ -683,17 +686,16 @@ public: if (getBit(i)->isComplete()) return false; return true; } - virtual std::string getAsString() const; + std::string getAsString() const override; - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + Init *resolveReferences(Record &R, const RecordVal *RV) const override; - virtual Init *getBit(unsigned Bit) const { + Init *getBit(unsigned Bit) const override { assert(Bit < Bits.size() && "Bit index out of range!"); return Bits[Bit]; } }; - /// IntInit - 7 - Represent an initialization by a literal integer value. /// class IntInit : public TypedInit { @@ -713,28 +715,27 @@ public: int64_t getValue() const { return Value; } - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<IntInit *>(this)); } - virtual Init * - convertInitializerBitRange(const std::vector<unsigned> &Bits) const; + Init * + convertInitializerBitRange(const std::vector<unsigned> &Bits) const override; - virtual std::string getAsString() const; + std::string getAsString() const override; /// resolveListElementReference - This method is used to implement /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const { + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override { llvm_unreachable("Illegal element reference off int"); } - virtual Init *getBit(unsigned Bit) const { + Init *getBit(unsigned Bit) const override { return BitInit::get((Value & (1ULL << Bit)) != 0); } }; - /// StringInit - "foo" - Represent an initialization by a string value. /// class StringInit : public TypedInit { @@ -745,7 +746,7 @@ class StringInit : public TypedInit { StringInit(const StringInit &Other) LLVM_DELETED_FUNCTION; StringInit &operator=(const StringInit &Other) LLVM_DELETED_FUNCTION; - virtual void anchor(); + void anchor() override; public: static bool classof(const Init *I) { @@ -755,22 +756,22 @@ public: const std::string &getValue() const { return Value; } - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<StringInit *>(this)); } - virtual std::string getAsString() const { return "\"" + Value + "\""; } - virtual std::string getAsUnquotedString() const { return Value; } + std::string getAsString() const override { return "\"" + Value + "\""; } + std::string getAsUnquotedString() const override { return Value; } /// resolveListElementReference - This method is used to implement /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const { + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override { llvm_unreachable("Illegal element reference off string"); } - virtual Init *getBit(unsigned Bit) const { + Init *getBit(unsigned Bit) const override { llvm_unreachable("Illegal bit reference off string"); } }; @@ -779,6 +780,7 @@ public: /// class ListInit : public TypedInit, public FoldingSetNode { std::vector<Init*> Values; + public: typedef std::vector<Init*>::const_iterator const_iterator; @@ -806,10 +808,10 @@ public: Record *getElementAsRecord(unsigned i) const; - virtual Init * - convertInitListSlice(const std::vector<unsigned> &Elements) const; + Init * + convertInitListSlice(const std::vector<unsigned> &Elements) const override; - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<ListInit *>(this)); } @@ -818,9 +820,9 @@ public: /// If a value is set for the variable later, this method will be called on /// users of the value to allow the value to propagate out. /// - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + Init *resolveReferences(Record &R, const RecordVal *RV) const override; - virtual std::string getAsString() const; + std::string getAsString() const override; ArrayRef<Init*> getValues() const { return Values; } @@ -833,15 +835,14 @@ public: /// resolveListElementReference - This method is used to implement /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const; + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override; - virtual Init *getBit(unsigned Bit) const { + Init *getBit(unsigned Bit) const override { llvm_unreachable("Illegal bit reference off list"); } }; - /// OpInit - Base class for operators /// class OpInit : public TypedInit { @@ -866,22 +867,22 @@ public: // possible to fold. virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0; - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<OpInit *>(this)); } - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const; + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override; - virtual Init *getBit(unsigned Bit) const; + Init *getBit(unsigned Bit) const override; }; - /// UnOpInit - !op (X) - Transform an init. /// class UnOpInit : public OpInit { public: enum UnaryOp { CAST, HEAD, TAIL, EMPTY }; + private: UnaryOp Opc; Init *LHS; @@ -899,14 +900,14 @@ public: static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type); // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector<Init *> &Operands) const { + OpInit *clone(std::vector<Init *> &Operands) const override { assert(Operands.size() == 1 && "Wrong number of operands for unary operation"); return UnOpInit::get(getOpcode(), *Operands.begin(), getType()); } - virtual int getNumOperands() const { return 1; } - virtual Init *getOperand(int i) const { + int getNumOperands() const override { return 1; } + Init *getOperand(int i) const override { assert(i == 0 && "Invalid operand id for unary operator"); return getOperand(); } @@ -916,18 +917,19 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; + Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override; - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + Init *resolveReferences(Record &R, const RecordVal *RV) const override; - virtual std::string getAsString() const; + std::string getAsString() const override; }; /// BinOpInit - !op (X, Y) - Combine two inits. /// class BinOpInit : public OpInit { public: - enum BinaryOp { ADD, SHL, SRA, SRL, STRCONCAT, CONCAT, EQ }; + enum BinaryOp { ADD, SHL, SRA, SRL, LISTCONCAT, STRCONCAT, CONCAT, EQ }; + private: BinaryOp Opc; Init *LHS, *RHS; @@ -946,14 +948,14 @@ public: RecTy *Type); // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector<Init *> &Operands) const { + OpInit *clone(std::vector<Init *> &Operands) const override { assert(Operands.size() == 2 && "Wrong number of operands for binary operation"); return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType()); } - virtual int getNumOperands() const { return 2; } - virtual Init *getOperand(int i) const { + int getNumOperands() const override { return 2; } + Init *getOperand(int i) const override { assert((i == 0 || i == 1) && "Invalid operand id for binary operator"); if (i == 0) { return getLHS(); @@ -968,11 +970,11 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; + Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override; - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + Init *resolveReferences(Record &R, const RecordVal *RV) const override; - virtual std::string getAsString() const; + std::string getAsString() const override; }; /// TernOpInit - !op (X, Y, Z) - Combine two inits. @@ -980,6 +982,7 @@ public: class TernOpInit : public OpInit { public: enum TernaryOp { SUBST, FOREACH, IF }; + private: TernaryOp Opc; Init *LHS, *MHS, *RHS; @@ -1000,15 +1003,15 @@ public: RecTy *Type); // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector<Init *> &Operands) const { + OpInit *clone(std::vector<Init *> &Operands) const override { assert(Operands.size() == 3 && "Wrong number of operands for ternary operation"); return TernOpInit::get(getOpcode(), Operands[0], Operands[1], Operands[2], getType()); } - virtual int getNumOperands() const { return 3; } - virtual Init *getOperand(int i) const { + int getNumOperands() const override { return 3; } + Init *getOperand(int i) const override { assert((i == 0 || i == 1 || i == 2) && "Invalid operand id for ternary operator"); if (i == 0) { @@ -1027,16 +1030,15 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; + Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override; - virtual bool isComplete() const { return false; } + bool isComplete() const override { return false; } - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + Init *resolveReferences(Record &R, const RecordVal *RV) const override; - virtual std::string getAsString() const; + std::string getAsString() const override; }; - /// VarInit - 'Opcode' - Represent a reference to an entire variable object. /// class VarInit : public TypedInit { @@ -1057,7 +1059,7 @@ public: static VarInit *get(const std::string &VN, RecTy *T); static VarInit *get(Init *VN, RecTy *T); - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<VarInit *>(this)); } @@ -1067,26 +1069,25 @@ public: return getNameInit()->getAsUnquotedString(); } - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const; + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override; - virtual RecTy *getFieldType(const std::string &FieldName) const; - virtual Init *getFieldInit(Record &R, const RecordVal *RV, - const std::string &FieldName) const; + RecTy *getFieldType(const std::string &FieldName) const override; + Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const override; /// resolveReferences - This method is used by classes that refer to other /// variables which may not be defined at the time they expression is formed. /// If a value is set for the variable later, this method will be called on /// users of the value to allow the value to propagate out. /// - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + Init *resolveReferences(Record &R, const RecordVal *RV) const override; - virtual Init *getBit(unsigned Bit) const; + Init *getBit(unsigned Bit) const override; - virtual std::string getAsString() const { return getName(); } + std::string getAsString() const override { return getName(); } }; - /// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field. /// class VarBitInit : public Init { @@ -1110,17 +1111,17 @@ public: } static VarBitInit *get(TypedInit *T, unsigned B); - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<VarBitInit *>(this)); } - virtual Init *getBitVar() const { return TI; } - virtual unsigned getBitNum() const { return Bit; } + Init *getBitVar() const override { return TI; } + unsigned getBitNum() const override { return Bit; } - virtual std::string getAsString() const; - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + std::string getAsString() const override; + Init *resolveReferences(Record &R, const RecordVal *RV) const override; - virtual Init *getBit(unsigned B) const { + Init *getBit(unsigned B) const override { assert(B < 1 && "Bit index out of range!"); return const_cast<VarBitInit*>(this); } @@ -1149,7 +1150,7 @@ public: } static VarListElementInit *get(TypedInit *T, unsigned E); - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<VarListElementInit *>(this)); } @@ -1159,14 +1160,13 @@ public: /// resolveListElementReference - This method is used to implement /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, - const RecordVal *RV, - unsigned Elt) const; + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override; - virtual std::string getAsString() const; - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + std::string getAsString() const override; + Init *resolveReferences(Record &R, const RecordVal *RV) const override; - virtual Init *getBit(unsigned Bit) const; + Init *getBit(unsigned Bit) const override; }; /// DefInit - AL - Represent a reference to a 'def' in the description @@ -1186,7 +1186,7 @@ public: } static DefInit *get(Record*); - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<DefInit *>(this)); } @@ -1194,26 +1194,25 @@ public: //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits); - virtual RecTy *getFieldType(const std::string &FieldName) const; - virtual Init *getFieldInit(Record &R, const RecordVal *RV, - const std::string &FieldName) const; + RecTy *getFieldType(const std::string &FieldName) const override; + Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const override; - virtual std::string getAsString() const; + std::string getAsString() const override; - virtual Init *getBit(unsigned Bit) const { + Init *getBit(unsigned Bit) const override { llvm_unreachable("Illegal bit reference off def"); } /// resolveListElementReference - This method is used to implement /// VarListElementInit::resolveReferences. If the list element is resolvable /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const { + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override { llvm_unreachable("Illegal element reference off def"); } }; - /// FieldInit - X.Y - Represent a reference to a subfield of a variable /// class FieldInit : public TypedInit { @@ -1235,19 +1234,18 @@ public: static FieldInit *get(Init *R, const std::string &FN); static FieldInit *get(Init *R, const Init *FN); - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<FieldInit *>(this)); } - virtual Init *getBit(unsigned Bit) const; + Init *getBit(unsigned Bit) const override; - virtual Init *resolveListElementReference(Record &R, - const RecordVal *RV, - unsigned Elt) const; + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override; - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + Init *resolveReferences(Record &R, const RecordVal *RV) const override; - virtual std::string getAsString() const { + std::string getAsString() const override { return Rec->getAsString() + "." + FieldName; } }; @@ -1285,7 +1283,7 @@ public: void Profile(FoldingSetNodeID &ID) const; - virtual Init *convertInitializerTo(RecTy *Ty) const { + Init *convertInitializerTo(RecTy *Ty) const override { return Ty->convertValue(const_cast<DagInit *>(this)); } @@ -1303,9 +1301,9 @@ public: return ArgNames[Num]; } - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + Init *resolveReferences(Record &R, const RecordVal *RV) const override; - virtual std::string getAsString() const; + std::string getAsString() const override; typedef std::vector<Init*>::const_iterator const_arg_iterator; typedef std::vector<std::string>::const_iterator const_name_iterator; @@ -1322,12 +1320,12 @@ public: inline size_t name_size () const { return ArgNames.size(); } inline bool name_empty() const { return ArgNames.empty(); } - virtual Init *getBit(unsigned Bit) const { + Init *getBit(unsigned Bit) const override { llvm_unreachable("Illegal bit reference off dag"); } - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const { + Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const override { llvm_unreachable("Illegal element reference off dag"); } }; @@ -1341,6 +1339,7 @@ class RecordVal { RecTy *Ty; unsigned Prefix; Init *Value; + public: RecordVal(Init *N, RecTy *T, unsigned P); RecordVal(const std::string &N, RecTy *T, unsigned P); @@ -1358,9 +1357,9 @@ public: bool setValue(Init *V) { if (V) { Value = V->convertInitializerTo(Ty); - return Value == 0; + return Value == nullptr; } - Value = 0; + Value = nullptr; return false; } @@ -1397,18 +1396,17 @@ class Record { void checkName(); public: - // Constructs a record. explicit Record(const std::string &N, ArrayRef<SMLoc> locs, RecordKeeper &records, bool Anonymous = false) : ID(LastID++), Name(StringInit::get(N)), Locs(locs.begin(), locs.end()), - TrackedRecords(records), TheInit(0), IsAnonymous(Anonymous) { + TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous) { init(); } explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records, bool Anonymous = false) : ID(LastID++), Name(N), Locs(locs.begin(), locs.end()), - TrackedRecords(records), TheInit(0), IsAnonymous(Anonymous) { + TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous) { init(); } @@ -1422,10 +1420,8 @@ public: ~Record() {} - static unsigned getNewUID() { return LastID++; } - unsigned getID() const { return ID; } const std::string &getName() const; @@ -1463,7 +1459,7 @@ public: const RecordVal *getValue(const Init *Name) const { for (unsigned i = 0, e = Values.size(); i != e; ++i) if (Values[i].getNameInit() == Name) return &Values[i]; - return 0; + return nullptr; } const RecordVal *getValue(StringRef Name) const { return getValue(StringInit::get(Name)); @@ -1471,7 +1467,7 @@ public: RecordVal *getValue(const Init *Name) { for (unsigned i = 0, e = Values.size(); i != e; ++i) if (Values[i].getNameInit() == Name) return &Values[i]; - return 0; + return nullptr; } RecordVal *getValue(StringRef Name) { return getValue(StringInit::get(Name)); @@ -1486,7 +1482,7 @@ public: } void addValue(const RecordVal &RV) { - assert(getValue(RV.getNameInit()) == 0 && "Value already added!"); + assert(getValue(RV.getNameInit()) == nullptr && "Value already added!"); Values.push_back(RV); if (Values.size() > 1) // Keep NAME at the end of the list. It makes record dumps a @@ -1533,7 +1529,7 @@ public: /// resolveReferences - If there are any field references that refer to fields /// that have been filled in, we can propagate the values now. /// - void resolveReferences() { resolveReferencesTo(0); } + void resolveReferences() { resolveReferencesTo(nullptr); } /// resolveReferencesTo - If anything in this record refers to RV, replace the /// reference to RV with the RHS of RV. If RV is null, we resolve all @@ -1614,7 +1610,7 @@ public: /// getValueAsBitOrUnset - This method looks up the specified field and /// returns its value as a bit. If the field is unset, sets Unset to true and - /// retunrs false. + /// returns false. /// bool getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const; @@ -1662,11 +1658,11 @@ public: Record *getClass(const std::string &Name) const { std::map<std::string, Record*>::const_iterator I = Classes.find(Name); - return I == Classes.end() ? 0 : I->second; + return I == Classes.end() ? nullptr : I->second; } Record *getDef(const std::string &Name) const { std::map<std::string, Record*>::const_iterator I = Defs.find(Name); - return I == Defs.end() ? 0 : I->second; + return I == Defs.end() ? nullptr : I->second; } void addClass(Record *R) { bool Ins = Classes.insert(std::make_pair(R->getName(), R)).second; diff --git a/include/llvm/TableGen/SetTheory.h b/include/llvm/TableGen/SetTheory.h new file mode 100644 index 000000000000..5baed79fb76a --- /dev/null +++ b/include/llvm/TableGen/SetTheory.h @@ -0,0 +1,142 @@ +//===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SetTheory class that computes ordered sets of +// Records from DAG expressions. Operators for standard set operations are +// predefined, and it is possible to add special purpose set operators as well. +// +// The user may define named sets as Records of predefined classes. Set +// expanders can be added to a SetTheory instance to teach it how to find the +// elements of such a named set. +// +// These are the predefined operators. The argument lists can be individual +// elements (defs), other sets (defs of expandable classes), lists, or DAG +// expressions that are evaluated recursively. +// +// - (add S1, S2 ...) Union sets. This is also how sets are created from element +// lists. +// +// - (sub S1, S2, ...) Set difference. Every element in S1 except for the +// elements in S2, ... +// +// - (and S1, S2) Set intersection. Every element in S1 that is also in S2. +// +// - (shl S, N) Shift left. Remove the first N elements from S. +// +// - (trunc S, N) Truncate. The first N elements of S. +// +// - (rotl S, N) Rotate left. Same as (add (shl S, N), (trunc S, N)). +// +// - (rotr S, N) Rotate right. +// +// - (decimate S, N) Decimate S by picking every N'th element, starting with +// the first one. For instance, (decimate S, 2) returns the even elements of +// S. +// +// - (sequence "Format", From, To) Generate a sequence of defs with printf. +// For instance, (sequence "R%u", 0, 3) -> [ R0, R1, R2, R3 ] +// +//===----------------------------------------------------------------------===// + +#ifndef SETTHEORY_H +#define SETTHEORY_H + +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/SourceMgr.h" +#include <map> +#include <vector> + +namespace llvm { + +class DagInit; +class Init; +class Record; +class RecordKeeper; + +class SetTheory { +public: + typedef std::vector<Record*> RecVec; + typedef SmallSetVector<Record*, 16> RecSet; + + /// Operator - A callback representing a DAG operator. + class Operator { + virtual void anchor(); + public: + virtual ~Operator() {} + + /// apply - Apply this operator to Expr's arguments and insert the result + /// in Elts. + virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts, + ArrayRef<SMLoc> Loc) =0; + }; + + /// Expander - A callback function that can transform a Record representing a + /// set into a fully expanded list of elements. Expanders provide a way for + /// users to define named sets that can be used in DAG expressions. + class Expander { + virtual void anchor(); + public: + virtual ~Expander() {} + + virtual void expand(SetTheory&, Record*, RecSet &Elts) =0; + }; + +private: + // Map set defs to their fully expanded contents. This serves as a memoization + // cache and it makes it possible to return const references on queries. + typedef std::map<Record*, RecVec> ExpandMap; + ExpandMap Expansions; + + // Known DAG operators by name. + StringMap<Operator*> Operators; + + // Typed expanders by class name. + StringMap<Expander*> Expanders; + +public: + /// Create a SetTheory instance with only the standard operators. + SetTheory(); + + /// addExpander - Add an expander for Records with the named super class. + void addExpander(StringRef ClassName, Expander*); + + /// addFieldExpander - Add an expander for ClassName that simply evaluates + /// FieldName in the Record to get the set elements. That is all that is + /// needed for a class like: + /// + /// class Set<dag d> { + /// dag Elts = d; + /// } + /// + void addFieldExpander(StringRef ClassName, StringRef FieldName); + + /// addOperator - Add a DAG operator. + void addOperator(StringRef Name, Operator*); + + /// evaluate - Evaluate Expr and append the resulting set to Elts. + void evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc); + + /// evaluate - Evaluate a sequence of Inits and append to Elts. + template<typename Iter> + void evaluate(Iter begin, Iter end, RecSet &Elts, ArrayRef<SMLoc> Loc) { + while (begin != end) + evaluate(*begin++, Elts, Loc); + } + + /// expand - Expand a record into a set of elements if possible. Return a + /// pointer to the expanded elements, or NULL if Set cannot be expanded + /// further. + const RecVec *expand(Record *Set); +}; + +} // end namespace llvm + +#endif + diff --git a/include/llvm/TableGen/StringMatcher.h b/include/llvm/TableGen/StringMatcher.h index 99cbcadd7693..b43877910834 100644 --- a/include/llvm/TableGen/StringMatcher.h +++ b/include/llvm/TableGen/StringMatcher.h @@ -21,29 +21,29 @@ namespace llvm { class raw_ostream; - + /// StringMatcher - Given a list of strings and code to execute when they match, /// output a simple switch tree to classify the input string. -/// +/// /// If a match is found, the code in Vals[i].second is executed; control must /// not exit this code fragment. If nothing matches, execution falls through. /// class StringMatcher { public: typedef std::pair<std::string, std::string> StringPair; + private: StringRef StrVariableName; const std::vector<StringPair> &Matches; raw_ostream &OS; - + public: StringMatcher(StringRef strVariableName, const std::vector<StringPair> &matches, raw_ostream &os) : StrVariableName(strVariableName), Matches(matches), OS(os) {} - + void Emit(unsigned Indent = 0) const; - - + private: bool EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches, unsigned CharNo, unsigned IndentCount) const; diff --git a/include/llvm/TableGen/StringToOffsetTable.h b/include/llvm/TableGen/StringToOffsetTable.h index d94d3a266822..c924bd8ec57d 100644 --- a/include/llvm/TableGen/StringToOffsetTable.h +++ b/include/llvm/TableGen/StringToOffsetTable.h @@ -25,8 +25,8 @@ namespace llvm { class StringToOffsetTable { StringMap<unsigned> StringOffset; std::string AggregateString; + public: - unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) { StringMapEntry<unsigned> &Entry = StringOffset.GetOrCreateValue(Str, -1U); if (Entry.getValue() == -1U) { @@ -36,10 +36,10 @@ public: if (appendZero) AggregateString += '\0'; } - + return Entry.getValue(); } - + void EmitString(raw_ostream &O) { // Escape the string. SmallString<256> Str; @@ -55,11 +55,11 @@ public: } O << AggregateString[i]; ++CharsPrinted; - + // Print escape sequences all together. if (AggregateString[i] != '\\') continue; - + assert(i+1 < AggregateString.size() && "Incomplete escape sequence!"); if (isdigit(AggregateString[i+1])) { assert(isdigit(AggregateString[i+2]) && diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 3f6eae6bb20a..f77cc7a35eb8 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -587,6 +587,11 @@ class Operand<ValueType ty> : DAGOperand { string OperandType = "OPERAND_UNKNOWN"; dag MIOperandInfo = (ops); + // MCOperandPredicate - Optionally, a code fragment operating on + // const MCOperand &MCOp, and returning a bool, to indicate if + // the value of MCOp is valid for the specific subclass of Operand + code MCOperandPredicate; + // ParserMatchClass - The "match class" that operands of this type fit // in. Match classes are used to define the order in which instructions are // match, to ensure that which instructions gets matched is deterministic. @@ -685,6 +690,27 @@ class InstrInfo { // // This option is a temporary migration help. It will go away. bit guessInstructionProperties = 1; + + // TableGen's instruction encoder generator has support for matching operands + // to bit-field variables both by name and by position. While matching by + // name is preferred, this is currently not possible for complex operands, + // and some targets still reply on the positional encoding rules. When + // generating a decoder for such targets, the positional encoding rules must + // be used by the decoder generator as well. + // + // This option is temporary; it will go away once the TableGen decoder + // generator has better support for complex operands and targets have + // migrated away from using positionally encoded operands. + bit decodePositionallyEncodedOperands = 0; + + // When set, this indicates that there will be no overlap between those + // operands that are matched by ordering (positional operands) and those + // matched by name. + // + // This option is temporary; it will go away once the TableGen decoder + // generator has better support for complex operands and targets have + // migrated away from using positionally encoded operands. + bit noNamedPositionallyEncodedOperands = 0; } // Standard Pseudo Instructions. @@ -702,7 +728,7 @@ def INLINEASM : Instruction { let AsmString = ""; let neverHasSideEffects = 1; // Note side effect is encoded in an operand. } -def PROLOG_LABEL : Instruction { +def CFI_INSTRUCTION : Instruction { let OutOperandList = (outs); let InOperandList = (ins i32imm:$id); let AsmString = ""; @@ -802,16 +828,18 @@ def LIFETIME_END : Instruction { } def STACKMAP : Instruction { let OutOperandList = (outs); - let InOperandList = (ins i32imm:$id, i32imm:$nbytes, variable_ops); + let InOperandList = (ins i64imm:$id, i32imm:$nbytes, variable_ops); let isCall = 1; let mayLoad = 1; + let usesCustomInserter = 1; } def PATCHPOINT : Instruction { let OutOperandList = (outs unknown:$dst); - let InOperandList = (ins i32imm:$id, i32imm:$nbytes, unknown:$callee, + let InOperandList = (ins i64imm:$id, i32imm:$nbytes, unknown:$callee, i32imm:$nargs, i32imm:$cc, variable_ops); let isCall = 1; let mayLoad = 1; + let usesCustomInserter = 1; } } @@ -927,10 +955,15 @@ class MnemonicAlias<string From, string To, string VariantName = ""> { /// InstAlias - This defines an alternate assembly syntax that is allowed to /// match an instruction that has a different (more canonical) assembly /// representation. -class InstAlias<string Asm, dag Result, bit Emit = 0b1> { +class InstAlias<string Asm, dag Result, int Emit = 1> { string AsmString = Asm; // The .s format to match the instruction with. dag ResultInst = Result; // The MCInst to generate. - bit EmitAlias = Emit; // Emit the alias instead of what's aliased. + + // This determines which order the InstPrinter detects aliases for + // printing. A larger value makes the alias more likely to be + // emitted. The Instruction's own definition is notionally 0.5, so 0 + // disables printing and 1 enables it if there are no conflicting aliases. + int EmitPriority = Emit; // Predicates - Predicates that must be true for this to match. list<Predicate> Predicates = []; @@ -947,7 +980,7 @@ class AsmWriter { // AsmWriterClassName - This specifies the suffix to use for the asmwriter // class. Generated AsmWriter classes are always prefixed with the target // name. - string AsmWriterClassName = "AsmPrinter"; + string AsmWriterClassName = "InstPrinter"; // Variant - AsmWriters can be of multiple different variants. Variants are // used to support targets that need to emit assembly code in ways that are @@ -957,21 +990,8 @@ class AsmWriter { // == 1, will expand to "y". int Variant = 0; - - // FirstOperandColumn/OperandSpacing - If the assembler syntax uses a columnar - // layout, the asmwriter can actually generate output in this columns (in - // verbose-asm mode). These two values indicate the width of the first column - // (the "opcode" area) and the width to reserve for subsequent operands. When - // verbose asm mode is enabled, operands will be indented to respect this. - int FirstOperandColumn = -1; - // OperandSpacing - Space between operand columns. int OperandSpacing = -1; - - // isMCAsmWriter - Is this assembly writer for an MC emitter? This controls - // generation of the printInstruction() method. For MC printers, it takes - // an MCInstr* operand, otherwise it takes a MachineInstr*. - bit isMCAsmWriter = 0; } def DefaultAsmWriter : AsmWriter; diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h index 9cc52a591b36..a0f26741a8f0 100644 --- a/include/llvm/Target/TargetCallingConv.h +++ b/include/llvm/Target/TargetCallingConv.h @@ -14,6 +14,7 @@ #ifndef LLVM_TARGET_TARGETCALLINGCONV_H #define LLVM_TARGET_TARGETCALLINGCONV_H +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" #include <string> @@ -42,10 +43,16 @@ namespace ISD { static const uint64_t ByValAlignOffs = 7; static const uint64_t Split = 1ULL<<11; static const uint64_t SplitOffs = 11; + static const uint64_t InAlloca = 1ULL<<12; ///< Passed with inalloca + static const uint64_t InAllocaOffs = 12; static const uint64_t OrigAlign = 0x1FULL<<27; static const uint64_t OrigAlignOffs = 27; - static const uint64_t ByValSize = 0xffffffffULL<<32; ///< Struct size + static const uint64_t ByValSize = 0x3fffffffULL<<32; ///< Struct size static const uint64_t ByValSizeOffs = 32; + static const uint64_t InConsecutiveRegsLast = 0x1ULL<<62; ///< Struct size + static const uint64_t InConsecutiveRegsLastOffs = 62; + static const uint64_t InConsecutiveRegs = 0x1ULL<<63; ///< Struct size + static const uint64_t InConsecutiveRegsOffs = 63; static const uint64_t One = 1ULL; ///< 1 of this type, for shifts @@ -68,12 +75,21 @@ namespace ISD { bool isByVal() const { return Flags & ByVal; } void setByVal() { Flags |= One << ByValOffs; } + bool isInAlloca() const { return Flags & InAlloca; } + void setInAlloca() { Flags |= One << InAllocaOffs; } + bool isNest() const { return Flags & Nest; } void setNest() { Flags |= One << NestOffs; } bool isReturned() const { return Flags & Returned; } void setReturned() { Flags |= One << ReturnedOffs; } + bool isInConsecutiveRegs() const { return Flags & InConsecutiveRegs; } + void setInConsecutiveRegs() { Flags |= One << InConsecutiveRegsOffs; } + + bool isInConsecutiveRegsLast() const { return Flags & InConsecutiveRegsLast; } + void setInConsecutiveRegsLast() { Flags |= One << InConsecutiveRegsLastOffs; } + unsigned getByValAlign() const { return (unsigned) ((One << ((Flags & ByValAlign) >> ByValAlignOffs)) / 2); diff --git a/include/llvm/Target/TargetCallingConv.td b/include/llvm/Target/TargetCallingConv.td index c1bef28652e9..8f31e0898399 100644 --- a/include/llvm/Target/TargetCallingConv.td +++ b/include/llvm/Target/TargetCallingConv.td @@ -42,6 +42,11 @@ class CCIf<string predicate, CCAction A> : CCPredicateAction<A> { class CCIfByVal<CCAction A> : CCIf<"ArgFlags.isByVal()", A> { } +/// CCIfConsecutiveRegs - If the current argument has InConsecutiveRegs +/// parameter attribute, apply Action A. +class CCIfConsecutiveRegs<CCAction A> : CCIf<"ArgFlags.isInConsecutiveRegs()", A> { +} + /// CCIfCC - Match if the current calling convention is 'CC'. class CCIfCC<string CC, CCAction A> : CCIf<!strconcat("State.getCallingConv() == ", CC), A> {} @@ -89,11 +94,15 @@ class CCAssignToStack<int size, int align> : CCAction { int Align = align; } -/// CCAssignToStackWithShadow - Same as CCAssignToStack, but with a register -/// to be shadowed. -class CCAssignToStackWithShadow<int size, int align, Register reg> : - CCAssignToStack<size, align> { - Register ShadowReg = reg; +/// CCAssignToStackWithShadow - Same as CCAssignToStack, but with a list of +/// registers to be shadowed. Note that, unlike CCAssignToRegWithShadow, this +/// shadows ALL of the registers in shadowList. +class CCAssignToStackWithShadow<int size, + int align, + list<Register> shadowList> : CCAction { + int Size = size; + int Align = align; + list<Register> ShadowRegList = shadowList; } /// CCPassByVal - This action always matches: it assigns the value to a stack diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h index a60147f5c092..bfddd0601794 100644 --- a/include/llvm/Target/TargetFrameLowering.h +++ b/include/llvm/Target/TargetFrameLowering.h @@ -93,6 +93,19 @@ public: /// stack pointer. virtual bool isFPCloseToIncomingSP() const { return true; } + /// assignCalleeSavedSpillSlots - Allows target to override spill slot + /// assignment logic. If implemented, assignCalleeSavedSpillSlots() should + /// assign frame slots to all CSI entries and return true. If this method + /// returns false, spill slots will be assigned using generic implementation. + /// assignCalleeSavedSpillSlots() may add, delete or rearrange elements of + /// CSI. + virtual bool + assignCalleeSavedSpillSlots(MachineFunction &MF, + const TargetRegisterInfo *TRI, + std::vector<CalleeSavedInfo> &CSI) const { + return false; + } + /// getCalleeSavedSpillSlots - This method returns a pointer to an array of /// pairs, that contains an entry for each callee saved register that must be /// spilled to a particular stack location if it is spilled. @@ -105,7 +118,7 @@ public: virtual const SpillSlot * getCalleeSavedSpillSlots(unsigned &NumEntries) const { NumEntries = 0; - return 0; + return nullptr; } /// targetHandlesStackFrameRounding - Returns true if the target is @@ -190,7 +203,7 @@ public: /// before PrologEpilogInserter scans the physical registers used to determine /// what callee saved registers should be spilled. This method is optional. virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, - RegScavenger *RS = NULL) const { + RegScavenger *RS = nullptr) const { } @@ -200,7 +213,7 @@ public: /// replaced with direct constants. This method is optional. /// virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF, - RegScavenger *RS = NULL) const { + RegScavenger *RS = nullptr) const { } /// eliminateCallFramePseudoInstr - This method is called during prolog/epilog diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index d4e14f60f237..87e7c14ac1e8 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -29,6 +29,7 @@ class MachineRegisterInfo; class MDNode; class MCInst; class MCSchedModel; +class MCSymbolRefExpr; class SDNode; class ScheduleHazardRecognizer; class SelectionDAG; @@ -36,6 +37,7 @@ class ScheduleDAG; class TargetRegisterClass; class TargetRegisterInfo; class BranchProbability; +class TargetSubtargetInfo; template<class T> class SmallVectorImpl; @@ -66,7 +68,7 @@ public: /// rematerializable, meaning it has no side effects and requires no operands /// that aren't always available. bool isTriviallyReMaterializable(const MachineInstr *MI, - AliasAnalysis *AA = 0) const { + AliasAnalysis *AA = nullptr) const { return MI->getOpcode() == TargetOpcode::IMPLICIT_DEF || (MI->getDesc().isRematerializable() && (isReallyTriviallyReMaterializable(MI, AA) || @@ -230,7 +232,7 @@ public: virtual MachineInstr * convertToThreeAddress(MachineFunction::iterator &MFI, MachineBasicBlock::iterator &MBBI, LiveVariables *LV) const { - return 0; + return nullptr; } /// commuteInstruction - If a target has any instructions that are @@ -257,7 +259,7 @@ public: /// aggressive checks. virtual bool produceSameValue(const MachineInstr *MI0, const MachineInstr *MI1, - const MachineRegisterInfo *MRI = 0) const; + const MachineRegisterInfo *MRI = nullptr) const; /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning /// true if it cannot be understood (e.g. it's a switch dispatch or isn't @@ -321,6 +323,20 @@ public: virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, MachineBasicBlock *NewDest) const; + /// getUnconditionalBranch - Get an instruction that performs an unconditional + /// branch to the given symbol. + virtual void + getUnconditionalBranch(MCInst &MI, + const MCSymbolRefExpr *BranchTarget) const { + llvm_unreachable("Target didn't implement " + "TargetInstrInfo::getUnconditionalBranch!"); + } + + /// getTrap - Get a machine trap instruction + virtual void getTrap(MCInst &MI) const { + llvm_unreachable("Target didn't implement TargetInstrInfo::getTrap!"); + } + /// isLegalToSplitMBBAt - Return true if it's legal to split the given basic /// block at the specified instruction (i.e. instruction would be the start /// of a new basic block). @@ -555,7 +571,7 @@ protected: MachineInstr* MI, const SmallVectorImpl<unsigned> &Ops, int FrameIndex) const { - return 0; + return nullptr; } /// foldMemoryOperandImpl - Target-dependent implementation for @@ -565,7 +581,7 @@ protected: MachineInstr* MI, const SmallVectorImpl<unsigned> &Ops, MachineInstr* LoadMI) const { - return 0; + return nullptr; } public: @@ -597,7 +613,7 @@ public: /// value. virtual unsigned getOpcodeAfterMemoryUnfold(unsigned Opc, bool UnfoldLoad, bool UnfoldStore, - unsigned *LoadRegIndex = 0) const { + unsigned *LoadRegIndex = nullptr) const { return 0; } @@ -728,7 +744,7 @@ public: /// use for this target when scheduling the machine instructions before /// register allocation. virtual ScheduleHazardRecognizer* - CreateTargetHazardRecognizer(const TargetMachine *TM, + CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const; /// CreateTargetMIHazardRecognizer - Allocate and return a hazard recognizer @@ -780,7 +796,7 @@ public: const MachineRegisterInfo *MRI, unsigned &FoldAsLoadDefReg, MachineInstr *&DefMI) const { - return 0; + return nullptr; } /// FoldImmediate - 'Reg' is known to be defined by a move immediate @@ -838,7 +854,7 @@ public: /// PredCost. virtual unsigned getInstrLatency(const InstrItineraryData *ItinData, const MachineInstr *MI, - unsigned *PredCost = 0) const; + unsigned *PredCost = nullptr) const; virtual unsigned getPredicationCost(const MachineInstr *MI) const; @@ -1003,7 +1019,7 @@ public: /// Create machine specific model for scheduling. virtual DFAPacketizer* CreateTargetScheduleState(const TargetMachine*, const ScheduleDAG*) const { - return NULL; + return nullptr; } private: diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h index ce213496935d..6de264e90ef7 100644 --- a/include/llvm/Target/TargetIntrinsicInfo.h +++ b/include/llvm/Target/TargetIntrinsicInfo.h @@ -40,7 +40,7 @@ public: /// intrinsic, Tys should point to an array of numTys pointers to Type, /// and must provide exactly one type for each overloaded type in the /// intrinsic. - virtual std::string getName(unsigned IID, Type **Tys = 0, + virtual std::string getName(unsigned IID, Type **Tys = nullptr, unsigned numTys = 0) const = 0; /// Look up target intrinsic by name. Return intrinsic ID or 0 for unknown @@ -56,7 +56,7 @@ public: /// Create or insert an LLVM Function declaration for an intrinsic, /// and return it. The Tys and numTys are for intrinsics with overloaded /// types. See above for more information. - virtual Function *getDeclaration(Module *M, unsigned ID, Type **Tys = 0, + virtual Function *getDeclaration(Module *M, unsigned ID, Type **Tys = nullptr, unsigned numTys = 0) const = 0; }; diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h index 46eaef2871b1..d4f9f2330594 100644 --- a/include/llvm/Target/TargetLibraryInfo.h +++ b/include/llvm/Target/TargetLibraryInfo.h @@ -67,8 +67,8 @@ namespace llvm { memcpy_chk, /// double __sincospi_stret(double x); sincospi_stret, - /// float __sincospi_stretf(float x); - sincospi_stretf, + /// float __sincospif_stret(float x); + sincospif_stret, /// double __sinpi(double x); sinpi, /// float __sinpif(float x); @@ -251,6 +251,18 @@ namespace llvm { floorf, /// long double floorl(long double x); floorl, + /// double fmax(double x, double y); + fmax, + /// float fmaxf(float x, float y); + fmaxf, + /// long double fmaxl(long double x, long double y); + fmaxl, + /// double fmin(double x, double y); + fmin, + /// float fminf(float x, float y); + fminf, + /// long double fminl(long double x, long double y); + fminl, /// double fmod(double x, double y); fmod, /// float fmodf(float x, float y); @@ -340,6 +352,12 @@ namespace llvm { labs, /// int lchown(const char *path, uid_t owner, gid_t group); lchown, + /// double ldexp(double x, int n); + ldexp, + /// float ldexpf(float x, int n); + ldexpf, + /// long double ldexpl(long double x, int n); + ldexpl, /// long long int llabs(long long int j); llabs, /// double log(double x); @@ -703,6 +721,8 @@ public: case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl: case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite: case LibFunc::sqrtl_finite: + case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl: + case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl: case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl: case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 5ab04f794452..ea9a48e2db8a 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -28,9 +28,11 @@ #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/IR/Attributes.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/InlineAsm.h" -#include "llvm/Support/CallSite.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Target/TargetCallingConv.h" #include "llvm/Target/TargetMachine.h" #include <climits> @@ -48,8 +50,10 @@ namespace llvm { class MachineFunction; class MachineInstr; class MachineJumpTableInfo; + class Mangler; class MCContext; class MCExpr; + class MCSymbol; template<typename T> class SmallVectorImpl; class DataLayout; class TargetRegisterClass; @@ -143,7 +147,7 @@ protected: public: const TargetMachine &getTargetMachine() const { return TM; } - const DataLayout *getDataLayout() const { return TD; } + const DataLayout *getDataLayout() const { return DL; } const TargetLoweringObjectFile &getObjFileLowering() const { return TLOF; } bool isBigEndian() const { return !IsLittleEndian; } @@ -173,10 +177,38 @@ public: return true; } - /// Return true if a vector of the given type should be split - /// (TypeSplitVector) instead of promoted (TypePromoteInteger) during type - /// legalization. - virtual bool shouldSplitVectorElementType(EVT /*VT*/) const { return false; } + /// Return true if multiple condition registers are available. + bool hasMultipleConditionRegisters() const { + return HasMultipleConditionRegisters; + } + + /// Return true if the target has BitExtract instructions. + bool hasExtractBitsInsn() const { return HasExtractBitsInsn; } + + /// Return the preferred vector type legalization action. + virtual TargetLoweringBase::LegalizeTypeAction + getPreferredVectorAction(EVT VT) const { + // The default action for one element vectors is to scalarize + if (VT.getVectorNumElements() == 1) + return TypeScalarizeVector; + // The default action for other vectors is to promote + return TypePromoteInteger; + } + + // There are two general methods for expanding a BUILD_VECTOR node: + // 1. Use SCALAR_TO_VECTOR on the defined scalar values and then shuffle + // them together. + // 2. Build the vector on the stack and then load it. + // If this function returns true, then method (1) will be used, subject to + // the constraint that all of the necessary shuffles are legal (as determined + // by isShuffleMaskLegal). If this function returns false, then method (2) is + // always used. The vector type, and the number of defined values, are + // provided. + virtual bool + shouldExpandBuildVectorWithShuffles(EVT /* VT */, + unsigned DefinedValues) const { + return DefinedValues < 3; + } /// Return true if integer divide is usually cheaper than a sequence of /// several shifts, adds, and multiplies for this target. @@ -215,6 +247,21 @@ public: return true; } + /// \brief Return if the target supports combining a + /// chain like: + /// \code + /// %andResult = and %val1, #imm-with-one-bit-set; + /// %icmpResult = icmp %andResult, 0 + /// br i1 %icmpResult, label %dest1, label %dest2 + /// \endcode + /// into a single machine instruction of a form like: + /// \code + /// brOnBitSet %register, #bitNumber, dest + /// \endcode + bool isMaskAndBranchFoldingLegal() const { + return MaskAndBranchFoldingIsLegal; + } + /// Return the ValueType of the result of SETCC operations. Also used to /// obtain the target's preferred type for the condition operand of SELECT and /// BRCOND nodes. In the case of BRCOND the argument passed is MVT::Other @@ -237,8 +284,17 @@ public: /// selects between the two kinds. For example on X86 a scalar boolean should /// be zero extended from i1, while the elements of a vector of booleans /// should be sign extended from i1. - BooleanContent getBooleanContents(bool isVec) const { - return isVec ? BooleanVectorContents : BooleanContents; + /// + /// Some cpus also treat floating point types the same way as they treat + /// vectors instead of the way they treat scalars. + BooleanContent getBooleanContents(bool isVec, bool isFloat) const { + if (isVec) + return BooleanVectorContents; + return isFloat ? BooleanFloatContents : BooleanContents; + } + + BooleanContent getBooleanContents(EVT Type) const { + return getBooleanContents(Type.isVector(), Type.isFloatingPoint()); } /// Return target scheduling preference. @@ -285,7 +341,7 @@ public: bool isTypeLegal(EVT VT) const { assert(!VT.isSimple() || (unsigned)VT.getSimpleVT().SimpleTy < array_lengthof(RegClassForVT)); - return VT.isSimple() && RegClassForVT[VT.getSimpleVT().SimpleTy] != 0; + return VT.isSimple() && RegClassForVT[VT.getSimpleVT().SimpleTy] != nullptr; } class ValueTypeActionImpl { @@ -295,7 +351,7 @@ public: public: ValueTypeActionImpl() { - std::fill(ValueTypeActions, array_endof(ValueTypeActions), 0); + std::fill(std::begin(ValueTypeActions), std::end(ValueTypeActions), 0); } LegalizeTypeAction getTypeAction(MVT VT) const { @@ -604,8 +660,9 @@ public: return getValueType(Ty, AllowUnknown).getSimpleVT(); } - /// Return the desired alignment for ByVal aggregate function arguments in the - /// caller parameter area. This is the actual alignment, not its logarithm. + /// Return the desired alignment for ByVal or InAlloca aggregate function + /// arguments in the caller parameter area. This is the actual alignment, not + /// its logarithm. virtual unsigned getByValTypeAlignment(Type *Ty) const; /// Return the type of registers that this ValueType will eventually require. @@ -668,6 +725,13 @@ public: /// reduce runtime. virtual bool ShouldShrinkFPConstant(EVT) const { return true; } + /// When splitting a value of the specified type into parts, does the Lo + /// or Hi part come first? This usually follows the endianness, except + /// for ppcf128, where the Hi part always comes first. + bool hasBigEndianPartOrdering(EVT VT) const { + return isBigEndian() || VT == MVT::ppcf128; + } + /// If true, the target has custom DAG combine transformations that it can /// perform for the specified node. bool hasTargetDAGCombine(ISD::NodeType NT) const { @@ -707,14 +771,16 @@ public: /// \brief Determine if the target supports unaligned memory accesses. /// - /// This function returns true if the target allows unaligned memory accesses. - /// of the specified type. If true, it also returns whether the unaligned - /// memory access is "fast" in the second argument by reference. This is used, - /// for example, in situations where an array copy/move/set is converted to a - /// sequence of store operations. It's use helps to ensure that such - /// replacements don't generate code that causes an alignment error (trap) on - /// the target machine. - virtual bool allowsUnalignedMemoryAccesses(EVT, bool * /*Fast*/ = 0) const { + /// This function returns true if the target allows unaligned memory accesses + /// of the specified type in the given address space. If true, it also returns + /// whether the unaligned memory access is "fast" in the third argument by + /// reference. This is used, for example, in situations where an array + /// copy/move/set is converted to a sequence of store operations. Its use + /// helps to ensure that such replacements don't generate code that causes an + /// alignment error (trap) on the target machine. + virtual bool allowsUnalignedMemoryAccesses(EVT, + unsigned AddrSpace = 0, + bool * /*Fast*/ = nullptr) const { return false; } @@ -856,6 +922,35 @@ public: /// @} //===--------------------------------------------------------------------===// + /// \name Helpers for load-linked/store-conditional atomic expansion. + /// @{ + + /// Perform a load-linked operation on Addr, returning a "Value *" with the + /// corresponding pointee type. This may entail some non-trivial operations to + /// truncate or reconstruct types that will be illegal in the backend. See + /// ARMISelLowering for an example implementation. + virtual Value *emitLoadLinked(IRBuilder<> &Builder, Value *Addr, + AtomicOrdering Ord) const { + llvm_unreachable("Load linked unimplemented on this target"); + } + + /// Perform a store-conditional operation to Addr. Return the status of the + /// store. This should be 0 if the store succeeded, non-zero otherwise. + virtual Value *emitStoreConditional(IRBuilder<> &Builder, Value *Val, + Value *Addr, AtomicOrdering Ord) const { + llvm_unreachable("Store conditional unimplemented on this target"); + } + + /// Return true if the given (atomic) instruction should be expanded by the + /// IR-level AtomicExpandLoadLinked pass into a loop involving + /// load-linked/store-conditional pairs. Atomic stores will be expanded in the + /// same way as "atomic xchg" operations which ignore their output if needed. + virtual bool shouldExpandAtomicInIR(Instruction *Inst) const { + return false; + } + + + //===--------------------------------------------------------------------===// // TargetLowering Configuration Methods - These methods should be invoked by // the derived class constructor to configure this object for the target. // @@ -864,9 +959,19 @@ public: virtual void resetOperationActions() {} protected: - /// Specify how the target extends the result of a boolean value from i1 to a - /// wider type. See getBooleanContents. - void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; } + /// Specify how the target extends the result of integer and floating point + /// boolean values from i1 to a wider type. See getBooleanContents. + void setBooleanContents(BooleanContent Ty) { + BooleanContents = Ty; + BooleanFloatContents = Ty; + } + + /// Specify how the target extends the result of integer and floating point + /// boolean values from i1 to a wider type. See getBooleanContents. + void setBooleanContents(BooleanContent IntTy, BooleanContent FloatTy) { + BooleanContents = IntTy; + BooleanFloatContents = FloatTy; + } /// Specify how the target extends the result of a vector boolean value from a /// vector of i1 to a wider type. See getBooleanContents. @@ -880,13 +985,13 @@ protected: } /// Indicate whether this target prefers to use _setjmp to implement - /// llvm.setjmp or the non _ version. Defaults to false. + /// llvm.setjmp or the version without _. Defaults to false. void setUseUnderscoreSetJmp(bool Val) { UseUnderscoreSetJmp = Val; } /// Indicate whether this target prefers to use _longjmp to implement - /// llvm.longjmp or the non _ version. Defaults to false. + /// llvm.longjmp or the version without _. Defaults to false. void setUseUnderscoreLongJmp(bool Val) { UseUnderscoreLongJmp = Val; } @@ -926,6 +1031,23 @@ protected: SelectIsExpensive = isExpensive; } + /// Tells the code generator that the target has multiple (allocatable) + /// condition registers that can be used to store the results of comparisons + /// for use by selects and conditional branches. With multiple condition + /// registers, the code generator will not aggressively sink comparisons into + /// the blocks of their users. + void setHasMultipleConditionRegisters(bool hasManyRegs = true) { + HasMultipleConditionRegisters = hasManyRegs; + } + + /// Tells the code generator that the target has BitExtract instructions. + /// The code generator will aggressively sink "shift"s into the blocks of + /// their users if the users will generate "and" instructions which can be + /// combined with "shift" to BitExtract instructions. + void setHasExtractBitsInsn(bool hasExtractInsn = true) { + HasExtractBitsInsn = hasExtractInsn; + } + /// Tells the code generator not to expand sequence of operations into a /// separate sequences that increases the amount of flow control. void setJumpIsExpensive(bool isExpensive = true) { @@ -1129,7 +1251,7 @@ public: int64_t BaseOffs; bool HasBaseReg; int64_t Scale; - AddrMode() : BaseGV(0), BaseOffs(0), HasBaseReg(false), Scale(0) {} + AddrMode() : BaseGV(nullptr), BaseOffs(0), HasBaseReg(false), Scale(0) {} }; /// Return true if the addressing mode represented by AM is legal for this @@ -1166,6 +1288,14 @@ public: return true; } + /// Return true if it's significantly cheaper to shift a vector by a uniform + /// scalar than by an amount which will vary across each lane. On x86, for + /// example, there is a "psllw" instruction for the former case, but no simple + /// instruction for a general "a << b" operation on vectors. + virtual bool isVectorShiftByScalarCheap(Type *Ty) const { + return false; + } + /// Return true if it's free to truncate a value of type Ty1 to type /// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16 /// by referencing its sub-register AX. @@ -1273,6 +1403,15 @@ public: return false; } + /// \brief Return true if it is beneficial to convert a load of a constant to + /// just the constant itself. + /// On some targets it might be more efficient to use a combination of + /// arithmetic instructions to materialize the constant instead of loading it + /// from a constant pool. + virtual bool shouldConvertConstantLoadToIntImm(const APInt &Imm, + Type *Ty) const { + return false; + } //===--------------------------------------------------------------------===// // Runtime Library hooks // @@ -1311,7 +1450,7 @@ public: private: const TargetMachine &TM; - const DataLayout *TD; + const DataLayout *DL; const TargetLoweringObjectFile &TLOF; /// True if this is a little endian target. @@ -1321,6 +1460,19 @@ private: /// the select operations if possible. bool SelectIsExpensive; + /// Tells the code generator that the target has multiple (allocatable) + /// condition registers that can be used to store the results of comparisons + /// for use by selects and conditional branches. With multiple condition + /// registers, the code generator will not aggressively sink comparisons into + /// the blocks of their users. + bool HasMultipleConditionRegisters; + + /// Tells the code generator that the target has BitExtract instructions. + /// The code generator will aggressively sink "shift"s into the blocks of + /// their users if the users will generate "and" instructions which can be + /// combined with "shift" to BitExtract instructions. + bool HasExtractBitsInsn; + /// Tells the code generator not to expand integer divides by constants into a /// sequence of muls, adds, and shifts. This is a hack until a real cost /// model is in place. If we ever optimize for size, this will be set to true @@ -1363,6 +1515,10 @@ private: /// a type wider than i1. See getBooleanContents. BooleanContent BooleanContents; + /// Information about the contents of the high-bits in boolean values held in + /// a type wider than i1. See getBooleanContents. + BooleanContent BooleanFloatContents; + /// Information about the contents of the high-bits in boolean vector values /// when the element type is wider than i1. See getBooleanContents. BooleanContent BooleanVectorContents; @@ -1479,7 +1635,7 @@ public: LegalizeTypeAction LA = ValueTypeActions.getTypeAction(SVT); assert( - (LA == TypeLegal || + (LA == TypeLegal || LA == TypeSoftenFloat || ValueTypeActions.getTypeAction(NVT) != TypePromoteInteger) && "Promote may not follow Expand or Promote"); @@ -1681,10 +1837,18 @@ protected: /// the branch is usually predicted right. bool PredictableSelectIsExpensive; + /// MaskAndBranchFoldingIsLegal - Indicates if the target supports folding + /// a mask of a single bit, a compare, and a branch into a single instruction. + bool MaskAndBranchFoldingIsLegal; + protected: /// Return true if the value types that can be represented by the specified /// register class are all legal. bool isLegalRC(const TargetRegisterClass *RC) const; + + /// Replace/modify any TargetFrameIndex operands with a targte-dependent + /// sequence of memory operands that is recognized by PrologEpilogInserter. + MachineBasicBlock *emitPatchPoint(MachineInstr *MI, MachineBasicBlock *MBB) const; }; /// This class defines information used to lower LLVM code to legal SelectionDAG @@ -1814,15 +1978,16 @@ public: /// Determine which of the bits specified in Mask are known to be either zero /// or one and return them in the KnownZero/KnownOne bitsets. - virtual void computeMaskedBitsForTargetNode(const SDValue Op, - APInt &KnownZero, - APInt &KnownOne, - const SelectionDAG &DAG, - unsigned Depth = 0) const; + virtual void computeKnownBitsForTargetNode(const SDValue Op, + APInt &KnownZero, + APInt &KnownOne, + const SelectionDAG &DAG, + unsigned Depth = 0) const; /// This method can be implemented by targets that want to expose additional /// information about sign bits to the DAG Combiner. virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op, + const SelectionDAG &DAG, unsigned Depth = 0) const; struct DAGCombinerInfo { @@ -1853,6 +2018,14 @@ public: void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO); }; + /// Return if the N is a constant or constant vector equal to the true value + /// from getBooleanContents(). + bool isConstTrueVal(const SDNode *N) const; + + /// Return if the N is a constant or constant vector equal to the false value + /// from getBooleanContents(). + bool isConstFalseVal(const SDNode *N) const; + /// Try to simplify a setcc built with the specified operands and cc. If it is /// unable to simplify it, return a null SDValue. SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, @@ -1879,6 +2052,15 @@ public: /// virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + /// Return true if it is profitable to move a following shift through this + // node, adjusting any immediate operands as necessary to preserve semantics. + // This transformation may not be desirable if it disrupts a particularly + // auspicious target-specific tree (e.g. bitfield extraction in AArch64). + // By default, it returns true. + virtual bool isDesirableToCommuteWithShift(const SDNode *N /*Op*/) const { + return true; + } + /// Return true if the target has native support for the specified value type /// and it is 'desirable' to use the type for the given node type. e.g. On x86 /// i16 is legal, but undesirable since i16 instruction encodings are longer @@ -1931,12 +2113,13 @@ public: bool isSRet : 1; bool isNest : 1; bool isByVal : 1; + bool isInAlloca : 1; bool isReturned : 1; uint16_t Alignment; ArgListEntry() : isSExt(false), isZExt(false), isInReg(false), - isSRet(false), isNest(false), isByVal(false), isReturned(false), - Alignment(0) { } + isSRet(false), isNest(false), isByVal(false), isInAlloca(false), + isReturned(false), Alignment(0) { } void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx); }; @@ -1963,7 +2146,7 @@ public: unsigned NumFixedArgs; CallingConv::ID CallConv; SDValue Callee; - ArgListTy &Args; + ArgListTy Args; SelectionDAG &DAG; SDLoc DL; ImmutableCallSite *CS; @@ -1971,33 +2154,95 @@ public: SmallVector<SDValue, 32> OutVals; SmallVector<ISD::InputArg, 32> Ins; + CallLoweringInfo(SelectionDAG &DAG) + : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false), + IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), + IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), + DAG(DAG), CS(nullptr) {} - /// Constructs a call lowering context based on the ImmutableCallSite \p cs. - CallLoweringInfo(SDValue chain, Type *retTy, - FunctionType *FTy, bool isTailCall, SDValue callee, - ArgListTy &args, SelectionDAG &dag, SDLoc dl, - ImmutableCallSite &cs) - : Chain(chain), RetTy(retTy), RetSExt(cs.paramHasAttr(0, Attribute::SExt)), - RetZExt(cs.paramHasAttr(0, Attribute::ZExt)), IsVarArg(FTy->isVarArg()), - IsInReg(cs.paramHasAttr(0, Attribute::InReg)), - DoesNotReturn(cs.doesNotReturn()), - IsReturnValueUsed(!cs.getInstruction()->use_empty()), - IsTailCall(isTailCall), NumFixedArgs(FTy->getNumParams()), - CallConv(cs.getCallingConv()), Callee(callee), Args(args), DAG(dag), - DL(dl), CS(&cs) {} - - /// Constructs a call lowering context based on the provided call - /// information. - CallLoweringInfo(SDValue chain, Type *retTy, bool retSExt, bool retZExt, - bool isVarArg, bool isInReg, unsigned numFixedArgs, - CallingConv::ID callConv, bool isTailCall, - bool doesNotReturn, bool isReturnValueUsed, SDValue callee, - ArgListTy &args, SelectionDAG &dag, SDLoc dl) - : Chain(chain), RetTy(retTy), RetSExt(retSExt), RetZExt(retZExt), - IsVarArg(isVarArg), IsInReg(isInReg), DoesNotReturn(doesNotReturn), - IsReturnValueUsed(isReturnValueUsed), IsTailCall(isTailCall), - NumFixedArgs(numFixedArgs), CallConv(callConv), Callee(callee), - Args(args), DAG(dag), DL(dl), CS(NULL) {} + CallLoweringInfo &setDebugLoc(SDLoc dl) { + DL = dl; + return *this; + } + + CallLoweringInfo &setChain(SDValue InChain) { + Chain = InChain; + return *this; + } + + CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultType, + SDValue Target, ArgListTy &&ArgsList, + unsigned FixedArgs = -1) { + RetTy = ResultType; + Callee = Target; + CallConv = CC; + NumFixedArgs = + (FixedArgs == static_cast<unsigned>(-1) ? Args.size() : FixedArgs); + Args = std::move(ArgsList); + return *this; + } + + CallLoweringInfo &setCallee(Type *ResultType, FunctionType *FTy, + SDValue Target, ArgListTy &&ArgsList, + ImmutableCallSite &Call) { + RetTy = ResultType; + + IsInReg = Call.paramHasAttr(0, Attribute::InReg); + DoesNotReturn = Call.doesNotReturn(); + IsVarArg = FTy->isVarArg(); + IsReturnValueUsed = !Call.getInstruction()->use_empty(); + RetSExt = Call.paramHasAttr(0, Attribute::SExt); + RetZExt = Call.paramHasAttr(0, Attribute::ZExt); + + Callee = Target; + + CallConv = Call.getCallingConv(); + NumFixedArgs = FTy->getNumParams(); + Args = std::move(ArgsList); + + CS = &Call; + + return *this; + } + + CallLoweringInfo &setInRegister(bool Value = true) { + IsInReg = Value; + return *this; + } + + CallLoweringInfo &setNoReturn(bool Value = true) { + DoesNotReturn = Value; + return *this; + } + + CallLoweringInfo &setVarArg(bool Value = true) { + IsVarArg = Value; + return *this; + } + + CallLoweringInfo &setTailCall(bool Value = true) { + IsTailCall = Value; + return *this; + } + + CallLoweringInfo &setDiscardResult(bool Value = true) { + IsReturnValueUsed = !Value; + return *this; + } + + CallLoweringInfo &setSExtResult(bool Value = true) { + RetSExt = Value; + return *this; + } + + CallLoweringInfo &setZExtResult(bool Value = true) { + RetZExt = Value; + return *this; + } + + ArgListTy &getArgs() { + return Args; + } }; /// This function lowers an abstract call to a function into an actual call. @@ -2060,6 +2305,19 @@ public: return false; } + /// Return the builtin name for the __builtin___clear_cache intrinsic + /// Default is to invoke the clear cache library call + virtual const char * getClearCacheBuiltinName() const { + return "__clear_cache"; + } + + /// Return the register ID of the name passed in. Used by named register + /// global variables extension. There is no target-independent behaviour + /// so the default action is to bail. + virtual unsigned getRegisterByName(const char* RegName, EVT VT) const { + report_fatal_error("Named registers not implemented for this target"); + } + /// Return the type that should be used to zero or sign extend a /// zeroext/signext integer argument or return value. FIXME: Most C calling /// convention requires the return type to be promoted, but this is not true @@ -2072,10 +2330,31 @@ public: return VT.bitsLT(MinVT) ? MinVT : VT; } + /// For some targets, an LLVM struct type must be broken down into multiple + /// simple types, but the calling convention specifies that the entire struct + /// must be passed in a block of consecutive registers. + virtual bool + functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID CallConv, + bool isVarArg) const { + return false; + } + /// Returns a 0 terminated array of registers that can be safely used as /// scratch registers. - virtual const uint16_t *getScratchRegisters(CallingConv::ID CC) const { - return NULL; + virtual const MCPhysReg *getScratchRegisters(CallingConv::ID CC) const { + return nullptr; + } + + /// This callback is used to prepare for a volatile or atomic load. + /// It takes a chain node as input and returns the chain for the load itself. + /// + /// Having a callback like this is necessary for targets like SystemZ, + /// which allows a CPU to reuse the result of a previous load indefinitely, + /// even if a cache-coherent store is performed by another CPU. The default + /// implementation does nothing. + virtual SDValue prepareVolatileOrAtomicLoad(SDValue Chain, SDLoc DL, + SelectionDAG &DAG) const { + return Chain; } /// This callback is invoked by the type legalizer to legalize nodes with an @@ -2124,9 +2403,13 @@ public: /// target does not support "fast" ISel. virtual FastISel *createFastISel(FunctionLoweringInfo &, const TargetLibraryInfo *) const { - return 0; + return nullptr; } + + bool verifyReturnAddressArgumentIsConstant(SDValue Op, + SelectionDAG &DAG) const; + //===--------------------------------------------------------------------===// // Inline Asm Support hooks // @@ -2190,20 +2473,11 @@ public: /// operand it matches. unsigned getMatchedOperand() const; - /// Copy constructor for copying from an AsmOperandInfo. - AsmOperandInfo(const AsmOperandInfo &info) - : InlineAsm::ConstraintInfo(info), - ConstraintCode(info.ConstraintCode), - ConstraintType(info.ConstraintType), - CallOperandVal(info.CallOperandVal), - ConstraintVT(info.ConstraintVT) { - } - /// Copy constructor for copying from a ConstraintInfo. AsmOperandInfo(const InlineAsm::ConstraintInfo &info) : InlineAsm::ConstraintInfo(info), ConstraintType(TargetLowering::C_Unknown), - CallOperandVal(0), ConstraintVT(MVT::Other) { + CallOperandVal(nullptr), ConstraintVT(MVT::Other) { } }; @@ -2231,7 +2505,7 @@ public: /// Op, otherwise an empty SDValue can be passed. virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, - SelectionDAG *DAG = 0) const; + SelectionDAG *DAG = nullptr) const; /// Given a constraint, return the type of constraint it is for this target. virtual ConstraintType getConstraintType(const std::string &Constraint) const; @@ -2265,10 +2539,36 @@ public: // SDValue BuildExactSDIV(SDValue Op1, SDValue Op2, SDLoc dl, SelectionDAG &DAG) const; - SDValue BuildSDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, - std::vector<SDNode*> *Created) const; - SDValue BuildUDIV(SDNode *N, SelectionDAG &DAG, bool IsAfterLegalization, - std::vector<SDNode*> *Created) const; + SDValue BuildSDIV(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, + bool IsAfterLegalization, + std::vector<SDNode *> *Created) const; + SDValue BuildUDIV(SDNode *N, const APInt &Divisor, SelectionDAG &DAG, + bool IsAfterLegalization, + std::vector<SDNode *> *Created) const; + + //===--------------------------------------------------------------------===// + // Legalization utility functions + // + + /// Expand a MUL into two nodes. One that computes the high bits of + /// the result and one that computes the low bits. + /// \param HiLoVT The value type to use for the Lo and Hi nodes. + /// \param LL Low bits of the LHS of the MUL. You can use this parameter + /// if you want to control how low bits are extracted from the LHS. + /// \param LH High bits of the LHS of the MUL. See LL for meaning. + /// \param RL Low bits of the RHS of the MUL. See LL for meaning + /// \param RH High bits of the RHS of the MUL. See LL for meaning. + /// \returns true if the node has been expanded. false if it has not + bool expandMUL(SDNode *N, SDValue &Lo, SDValue &Hi, EVT HiLoVT, + SelectionDAG &DAG, SDValue LL = SDValue(), + SDValue LH = SDValue(), SDValue RL = SDValue(), + SDValue RH = SDValue()) const; + + /// Expand float(f32) to SINT(i64) conversion + /// \param N Node to expand + /// \param Result output after conversion + /// \returns True, if the expansion was successful, false otherwise + bool expandFP_TO_SINT(SDNode *N, SDValue &Result, SelectionDAG &DAG) const; //===--------------------------------------------------------------------===// // Instruction Emitting Hooks diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 284b6bbdb897..7c32a5e3d0ca 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -29,11 +29,13 @@ namespace llvm { class MCSymbol; class MCSymbolRefExpr; class MCStreamer; + class ConstantExpr; class GlobalValue; class TargetMachine; - + class TargetLoweringObjectFile : public MCObjectFileInfo { MCContext *Ctx; + const DataLayout *DL; TargetLoweringObjectFile( const TargetLoweringObjectFile&) LLVM_DELETED_FUNCTION; @@ -42,103 +44,100 @@ class TargetLoweringObjectFile : public MCObjectFileInfo { public: MCContext &getContext() const { return *Ctx; } - TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(0) {} - + TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr) {} + virtual ~TargetLoweringObjectFile(); - - /// Initialize - this method must be called before any actual lowering is - /// done. This specifies the current context for codegen, and gives the - /// lowering implementations a chance to set up their default sections. + + /// This method must be called before any actual lowering is done. This + /// specifies the current context for codegen, and gives the lowering + /// implementations a chance to set up their default sections. virtual void Initialize(MCContext &ctx, const TargetMachine &TM); - + virtual void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, const MCSymbol *Sym) const; - /// emitModuleFlags - Emit the module flags that the platform cares about. - virtual void emitModuleFlags(MCStreamer &, - ArrayRef<Module::ModuleFlagEntry>, - Mangler *, const TargetMachine &) const { + /// Extract the dependent library name from a linker option string. Returns + /// StringRef() if the option does not specify a library. + virtual StringRef getDepLibFromLinkerOpt(StringRef LinkerOption) const { + return StringRef(); } - /// shouldEmitUsedDirectiveFor - This hook allows targets to selectively - /// decide not to emit the UsedDirective for some symbols in llvm.used. - /// FIXME: REMOVE this (rdar://7071300) - virtual bool shouldEmitUsedDirectiveFor(const GlobalValue *GV, - Mangler *) const { - return GV != 0; - } - - /// getSectionForConstant - Given a constant with the SectionKind, return a - /// section that it should be placed in. - virtual const MCSection *getSectionForConstant(SectionKind Kind) const; - - /// getKindForGlobal - Classify the specified global variable into a set of - /// target independent categories embodied in SectionKind. + /// Emit the module flags that the platform cares about. + virtual void emitModuleFlags(MCStreamer &Streamer, + ArrayRef<Module::ModuleFlagEntry> Flags, + Mangler &Mang, const TargetMachine &TM) const {} + + /// Given a constant with the SectionKind, return a section that it should be + /// placed in. + virtual const MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const; + + /// Classify the specified global variable into a set of target independent + /// categories embodied in SectionKind. static SectionKind getKindForGlobal(const GlobalValue *GV, const TargetMachine &TM); - - /// SectionForGlobal - This method computes the appropriate section to emit - /// the specified global variable or function definition. This should not - /// be passed external (or available externally) globals. + + /// This method computes the appropriate section to emit the specified global + /// variable or function definition. This should not be passed external (or + /// available externally) globals. const MCSection *SectionForGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler *Mang, + SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const; - - /// SectionForGlobal - This method computes the appropriate section to emit - /// the specified global variable or function definition. This should not - /// be passed external (or available externally) globals. + + /// This method computes the appropriate section to emit the specified global + /// variable or function definition. This should not be passed external (or + /// available externally) globals. const MCSection *SectionForGlobal(const GlobalValue *GV, - Mangler *Mang, + Mangler &Mang, const TargetMachine &TM) const { return SectionForGlobal(GV, getKindForGlobal(GV, TM), Mang, TM); } - /// getExplicitSectionGlobal - Targets should implement this method to assign - /// a section to globals with an explicit section specfied. The - /// implementation of this method can assume that GV->hasSection() is true. - virtual const MCSection * - getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const = 0; - - /// getSpecialCasedSectionGlobals - Allow the target to completely override - /// section assignment of a global. + /// Targets should implement this method to assign a section to globals with + /// an explicit section specfied. The implementation of this method can + /// assume that GV->hasSection() is true. virtual const MCSection * - getSpecialCasedSectionGlobals(const GlobalValue *GV, Mangler *Mang, - SectionKind Kind) const { - return 0; + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, const TargetMachine &TM) const = 0; + + /// Allow the target to completely override section assignment of a global. + virtual const MCSection *getSpecialCasedSectionGlobals(const GlobalValue *GV, + SectionKind Kind, + Mangler &Mang) const { + return nullptr; } - - /// getTTypeGlobalReference - Return an MCExpr to use for a reference - /// to the specified global variable from exception handling information. - /// - virtual const MCExpr * - getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, unsigned Encoding, - MCStreamer &Streamer) const; - - /// Return the MCSymbol for the specified global value. This symbol is the - /// main label that is the address of the global - MCSymbol *getSymbol(Mangler &M, const GlobalValue *GV) const; - // getCFIPersonalitySymbol - The symbol that gets passed to .cfi_personality. - virtual MCSymbol * - getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI) const; + /// Return an MCExpr to use for a reference to the specified global variable + /// from exception handling information. + virtual const MCExpr * + getTTypeGlobalReference(const GlobalValue *GV, unsigned Encoding, + Mangler &Mang, const TargetMachine &TM, + MachineModuleInfo *MMI, MCStreamer &Streamer) const; + + /// Return the MCSymbol for a private symbol with global value name as its + /// base, with the specified suffix. + MCSymbol *getSymbolWithGlobalValueBase(const GlobalValue *GV, + StringRef Suffix, Mangler &Mang, + const TargetMachine &TM) const; + + // The symbol that gets passed to .cfi_personality. + virtual MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, + Mangler &Mang, + const TargetMachine &TM, + MachineModuleInfo *MMI) const; - /// const MCExpr * getTTypeReference(const MCSymbolRefExpr *Sym, unsigned Encoding, MCStreamer &Streamer) const; - virtual const MCSection * - getStaticCtorSection(unsigned Priority = 65535) const { - (void)Priority; + virtual const MCSection *getStaticCtorSection(unsigned Priority, + const MCSymbol *KeySym) const { return StaticCtorSection; } - virtual const MCSection * - getStaticDtorSection(unsigned Priority = 65535) const { - (void)Priority; + + virtual const MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const { return StaticDtorSection; } @@ -146,10 +145,22 @@ public: /// emitting the address in debug info. virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const; + virtual const MCExpr * + getExecutableRelativeSymbol(const ConstantExpr *CE, Mangler &Mang, + const TargetMachine &TM) const { + return nullptr; + } + + /// \brief True if the section is atomized using the symbols in it. + /// This is false if the section is not atomized at all (most ELF sections) or + /// if it is atomized based on its contents (MachO' __TEXT,__cstring for + /// example). + virtual bool isSectionAtomizableBySymbols(const MCSection &Section) const; + protected: virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const; + Mangler &Mang, const TargetMachine &TM) const; }; } // end namespace llvm diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 11b0f5fb77fc..b263c571d9e6 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -26,9 +26,11 @@ namespace llvm { class InstrItineraryData; class JITCodeEmitter; class GlobalValue; +class Mangler; class MCAsmInfo; class MCCodeGenInfo; class MCContext; +class MCSymbol; class Target; class DataLayout; class TargetLibraryInfo; @@ -82,12 +84,7 @@ protected: // Can only create subclasses. /// const MCAsmInfo *AsmInfo; - unsigned MCRelaxAll : 1; - unsigned MCNoExecStack : 1; - unsigned MCSaveTempLabels : 1; - unsigned MCUseLoc : 1; - unsigned MCUseCFI : 1; - unsigned MCUseDwarfDirectory : 1; + unsigned RequireStructuredCFG : 1; public: virtual ~TargetMachine(); @@ -100,7 +97,9 @@ public: /// getSubtargetImpl - virtual method implemented by subclasses that returns /// a reference to that target's TargetSubtargetInfo-derived member variable. - virtual const TargetSubtargetInfo *getSubtargetImpl() const { return 0; } + virtual const TargetSubtargetInfo *getSubtargetImpl() const { + return nullptr; + } mutable TargetOptions Options; @@ -108,7 +107,7 @@ public: void resetTargetOptions(const MachineFunction *MF) const; // Interfaces to the major aspects of target machine information: - // + // // -- Instruction opcode and operand information // -- Pipelines and scheduling information // -- Stack frame information @@ -116,11 +115,15 @@ public: // // N.B. These objects may change during compilation. It's not safe to cache // them between functions. - virtual const TargetInstrInfo *getInstrInfo() const { return 0; } - virtual const TargetFrameLowering *getFrameLowering() const { return 0; } - virtual const TargetLowering *getTargetLowering() const { return 0; } - virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const{ return 0; } - virtual const DataLayout *getDataLayout() const { return 0; } + virtual const TargetInstrInfo *getInstrInfo() const { return nullptr; } + virtual const TargetFrameLowering *getFrameLowering() const { + return nullptr; + } + virtual const TargetLowering *getTargetLowering() const { return nullptr; } + virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const { + return nullptr; + } + virtual const DataLayout *getDataLayout() const { return nullptr; } /// getMCAsmInfo - Return target specific asm information. /// @@ -137,66 +140,27 @@ public: /// not, return null. This is kept separate from RegInfo until RegInfo has /// details of graph coloring register allocation removed from it. /// - virtual const TargetRegisterInfo *getRegisterInfo() const { return 0; } + virtual const TargetRegisterInfo *getRegisterInfo() const { return nullptr; } /// getIntrinsicInfo - If intrinsic information is available, return it. If /// not, return null. /// - virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return 0; } + virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return nullptr;} /// getJITInfo - If this target supports a JIT, return information for it, /// otherwise return null. /// - virtual TargetJITInfo *getJITInfo() { return 0; } + virtual TargetJITInfo *getJITInfo() { return nullptr; } /// getInstrItineraryData - Returns instruction itinerary data for the target /// or specific subtarget. /// virtual const InstrItineraryData *getInstrItineraryData() const { - return 0; + return nullptr; } - /// hasMCRelaxAll - Check whether all machine code instructions should be - /// relaxed. - bool hasMCRelaxAll() const { return MCRelaxAll; } - - /// setMCRelaxAll - Set whether all machine code instructions should be - /// relaxed. - void setMCRelaxAll(bool Value) { MCRelaxAll = Value; } - - /// hasMCSaveTempLabels - Check whether temporary labels will be preserved - /// (i.e., not treated as temporary). - bool hasMCSaveTempLabels() const { return MCSaveTempLabels; } - - /// setMCSaveTempLabels - Set whether temporary labels will be preserved - /// (i.e., not treated as temporary). - void setMCSaveTempLabels(bool Value) { MCSaveTempLabels = Value; } - - /// hasMCNoExecStack - Check whether an executable stack is not needed. - bool hasMCNoExecStack() const { return MCNoExecStack; } - - /// setMCNoExecStack - Set whether an executabel stack is not needed. - void setMCNoExecStack(bool Value) { MCNoExecStack = Value; } - - /// hasMCUseLoc - Check whether we should use dwarf's .loc directive. - bool hasMCUseLoc() const { return MCUseLoc; } - - /// setMCUseLoc - Set whether all we should use dwarf's .loc directive. - void setMCUseLoc(bool Value) { MCUseLoc = Value; } - - /// hasMCUseCFI - Check whether we should use dwarf's .cfi_* directives. - bool hasMCUseCFI() const { return MCUseCFI; } - - /// setMCUseCFI - Set whether all we should use dwarf's .cfi_* directives. - void setMCUseCFI(bool Value) { MCUseCFI = Value; } - - /// hasMCUseDwarfDirectory - Check whether we should use .file directives with - /// explicit directories. - bool hasMCUseDwarfDirectory() const { return MCUseDwarfDirectory; } - - /// setMCUseDwarfDirectory - Set whether all we should use .file directives - /// with explicit directories. - void setMCUseDwarfDirectory(bool Value) { MCUseDwarfDirectory = Value; } + bool requiresStructuredCFG() const { return RequireStructuredCFG; } + void setRequiresStructuredCFG(bool Value) { RequireStructuredCFG = Value; } /// getRelocationModel - Returns the code generation relocation model. The /// choices are static, PIC, and dynamic-no-pic, and target default. @@ -223,26 +187,26 @@ public: /// getAsmVerbosityDefault - Returns the default value of asm verbosity. /// - static bool getAsmVerbosityDefault(); + bool getAsmVerbosityDefault() const ; /// setAsmVerbosityDefault - Set the default value of asm verbosity. Default /// is false. - static void setAsmVerbosityDefault(bool); + void setAsmVerbosityDefault(bool); /// getDataSections - Return true if data objects should be emitted into their /// own section, corresponds to -fdata-sections. - static bool getDataSections(); + bool getDataSections() const; /// getFunctionSections - Return true if functions should be emitted into /// their own section, corresponding to -ffunction-sections. - static bool getFunctionSections(); + bool getFunctionSections() const; /// setDataSections - Set if the data are emit into separate sections. - static void setDataSections(bool); + void setDataSections(bool); /// setFunctionSections - Set if the functions are emit into separate /// sections. - static void setFunctionSections(bool); + void setFunctionSections(bool); /// \brief Register analysis passes for this target with a pass manager. virtual void addAnalysisPasses(PassManagerBase &) {} @@ -264,8 +228,8 @@ public: formatted_raw_ostream &, CodeGenFileType, bool /*DisableVerify*/ = true, - AnalysisID /*StartAfter*/ = 0, - AnalysisID /*StopAfter*/ = 0) { + AnalysisID /*StartAfter*/ = nullptr, + AnalysisID /*StopAfter*/ = nullptr) { return true; } @@ -292,6 +256,10 @@ public: bool /*DisableVerify*/ = true) { return true; } + + void getNameWithPrefix(SmallVectorImpl<char> &Name, const GlobalValue *GV, + Mangler &Mang, bool MayAlwaysUsePrivate = false) const; + MCSymbol *getSymbol(const GlobalValue *GV, Mangler &Mang) const; }; /// LLVMTargetMachine - This class describes a target machine that is @@ -309,7 +277,7 @@ public: /// \brief Register analysis passes for this target with a pass manager. /// /// This registers target independent analysis passes. - virtual void addAnalysisPasses(PassManagerBase &PM); + void addAnalysisPasses(PassManagerBase &PM) override; /// createPassConfig - Create a pass configuration object to be used by /// addPassToEmitX methods for generating a pipeline of CodeGen passes. @@ -318,12 +286,10 @@ public: /// addPassesToEmitFile - Add passes to the specified pass manager to get the /// specified file emitted. Typically this will involve several steps of code /// generation. - virtual bool addPassesToEmitFile(PassManagerBase &PM, - formatted_raw_ostream &Out, - CodeGenFileType FileType, - bool DisableVerify = true, - AnalysisID StartAfter = 0, - AnalysisID StopAfter = 0); + bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, + CodeGenFileType FileType, bool DisableVerify = true, + AnalysisID StartAfter = nullptr, + AnalysisID StopAfter = nullptr) override; /// addPassesToEmitMachineCode - Add passes to the specified pass manager to /// get machine code emitted. This uses a JITCodeEmitter object to handle @@ -331,19 +297,16 @@ public: /// of functions. This method returns true if machine code emission is /// not supported. /// - virtual bool addPassesToEmitMachineCode(PassManagerBase &PM, - JITCodeEmitter &MCE, - bool DisableVerify = true); + bool addPassesToEmitMachineCode(PassManagerBase &PM, JITCodeEmitter &MCE, + bool DisableVerify = true) override; /// addPassesToEmitMC - Add passes to the specified pass manager to get /// machine code emitted with the MCJIT. This method returns true if machine /// code is not supported. It fills the MCContext Ctx pointer which can be /// used to build custom MCStreamer. /// - virtual bool addPassesToEmitMC(PassManagerBase &PM, - MCContext *&Ctx, - raw_ostream &OS, - bool DisableVerify = true); + bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, + raw_ostream &OS, bool DisableVerify = true) override; /// addCodeEmitter - This pass should be overridden by the target to add a /// code emitter, if supported. If this is not supported, 'true' should be diff --git a/include/llvm/Target/TargetOpcodes.h b/include/llvm/Target/TargetOpcodes.h index bd74cb9c0f45..abb3ecacaefd 100644 --- a/include/llvm/Target/TargetOpcodes.h +++ b/include/llvm/Target/TargetOpcodes.h @@ -22,90 +22,90 @@ namespace llvm { /// must be the same as in CodeGenTarget.cpp. /// namespace TargetOpcode { - enum { - PHI = 0, - INLINEASM = 1, - PROLOG_LABEL = 2, - EH_LABEL = 3, - GC_LABEL = 4, - - /// KILL - This instruction is a noop that is used only to adjust the - /// liveness of registers. This can be useful when dealing with - /// sub-registers. - KILL = 5, - - /// EXTRACT_SUBREG - This instruction takes two operands: a register - /// that has subregisters, and a subregister index. It returns the - /// extracted subregister value. This is commonly used to implement - /// truncation operations on target architectures which support it. - EXTRACT_SUBREG = 6, - - /// INSERT_SUBREG - This instruction takes three operands: a register that - /// has subregisters, a register providing an insert value, and a - /// subregister index. It returns the value of the first register with the - /// value of the second register inserted. The first register is often - /// defined by an IMPLICIT_DEF, because it is commonly used to implement - /// anyext operations on target architectures which support it. - INSERT_SUBREG = 7, - - /// IMPLICIT_DEF - This is the MachineInstr-level equivalent of undef. - IMPLICIT_DEF = 8, - - /// SUBREG_TO_REG - This instruction is similar to INSERT_SUBREG except that - /// the first operand is an immediate integer constant. This constant is - /// often zero, because it is commonly used to assert that the instruction - /// defining the register implicitly clears the high bits. - SUBREG_TO_REG = 9, - - /// COPY_TO_REGCLASS - This instruction is a placeholder for a plain - /// register-to-register copy into a specific register class. This is only - /// used between instruction selection and MachineInstr creation, before - /// virtual registers have been created for all the instructions, and it's - /// only needed in cases where the register classes implied by the - /// instructions are insufficient. It is emitted as a COPY MachineInstr. - COPY_TO_REGCLASS = 10, - - /// DBG_VALUE - a mapping of the llvm.dbg.value intrinsic - DBG_VALUE = 11, - - /// REG_SEQUENCE - This variadic instruction is used to form a register that - /// represents a consecutive sequence of sub-registers. It's used as a - /// register coalescing / allocation aid and must be eliminated before code - /// emission. - // In SDNode form, the first operand encodes the register class created by - // the REG_SEQUENCE, while each subsequent pair names a vreg + subreg index - // pair. Once it has been lowered to a MachineInstr, the regclass operand - // is no longer present. - /// e.g. v1027 = REG_SEQUENCE v1024, 3, v1025, 4, v1026, 5 - /// After register coalescing references of v1024 should be replace with - /// v1027:3, v1025 with v1027:4, etc. - REG_SEQUENCE = 12, - - /// COPY - Target-independent register copy. This instruction can also be - /// used to copy between subregisters of virtual registers. - COPY = 13, - - /// BUNDLE - This instruction represents an instruction bundle. Instructions - /// which immediately follow a BUNDLE instruction which are marked with - /// 'InsideBundle' flag are inside the bundle. - BUNDLE = 14, - - /// Lifetime markers. - LIFETIME_START = 15, - LIFETIME_END = 16, - - /// A Stackmap instruction captures the location of live variables at its - /// position in the instruction stream. It is followed by a shadow of bytes - /// that must lie within the function and not contain another stackmap. - STACKMAP = 17, - - /// Patchable call instruction - this instruction represents a call to a - /// constant address, followed by a series of NOPs. It is intended to - /// support optimizations for dynamic languages (such as javascript) that - /// rewrite calls to runtimes with more efficient code sequences. - /// This also implies a stack map. - PATCHPOINT = 18 - }; +enum { + PHI = 0, + INLINEASM = 1, + CFI_INSTRUCTION = 2, + EH_LABEL = 3, + GC_LABEL = 4, + + /// KILL - This instruction is a noop that is used only to adjust the + /// liveness of registers. This can be useful when dealing with + /// sub-registers. + KILL = 5, + + /// EXTRACT_SUBREG - This instruction takes two operands: a register + /// that has subregisters, and a subregister index. It returns the + /// extracted subregister value. This is commonly used to implement + /// truncation operations on target architectures which support it. + EXTRACT_SUBREG = 6, + + /// INSERT_SUBREG - This instruction takes three operands: a register that + /// has subregisters, a register providing an insert value, and a + /// subregister index. It returns the value of the first register with the + /// value of the second register inserted. The first register is often + /// defined by an IMPLICIT_DEF, because it is commonly used to implement + /// anyext operations on target architectures which support it. + INSERT_SUBREG = 7, + + /// IMPLICIT_DEF - This is the MachineInstr-level equivalent of undef. + IMPLICIT_DEF = 8, + + /// SUBREG_TO_REG - This instruction is similar to INSERT_SUBREG except that + /// the first operand is an immediate integer constant. This constant is + /// often zero, because it is commonly used to assert that the instruction + /// defining the register implicitly clears the high bits. + SUBREG_TO_REG = 9, + + /// COPY_TO_REGCLASS - This instruction is a placeholder for a plain + /// register-to-register copy into a specific register class. This is only + /// used between instruction selection and MachineInstr creation, before + /// virtual registers have been created for all the instructions, and it's + /// only needed in cases where the register classes implied by the + /// instructions are insufficient. It is emitted as a COPY MachineInstr. + COPY_TO_REGCLASS = 10, + + /// DBG_VALUE - a mapping of the llvm.dbg.value intrinsic + DBG_VALUE = 11, + + /// REG_SEQUENCE - This variadic instruction is used to form a register that + /// represents a consecutive sequence of sub-registers. It's used as a + /// register coalescing / allocation aid and must be eliminated before code + /// emission. + // In SDNode form, the first operand encodes the register class created by + // the REG_SEQUENCE, while each subsequent pair names a vreg + subreg index + // pair. Once it has been lowered to a MachineInstr, the regclass operand + // is no longer present. + /// e.g. v1027 = REG_SEQUENCE v1024, 3, v1025, 4, v1026, 5 + /// After register coalescing references of v1024 should be replace with + /// v1027:3, v1025 with v1027:4, etc. + REG_SEQUENCE = 12, + + /// COPY - Target-independent register copy. This instruction can also be + /// used to copy between subregisters of virtual registers. + COPY = 13, + + /// BUNDLE - This instruction represents an instruction bundle. Instructions + /// which immediately follow a BUNDLE instruction which are marked with + /// 'InsideBundle' flag are inside the bundle. + BUNDLE = 14, + + /// Lifetime markers. + LIFETIME_START = 15, + LIFETIME_END = 16, + + /// A Stackmap instruction captures the location of live variables at its + /// position in the instruction stream. It is followed by a shadow of bytes + /// that must lie within the function and not contain another stackmap. + STACKMAP = 17, + + /// Patchable call instruction - this instruction represents a call to a + /// constant address, followed by a series of NOPs. It is intended to + /// support optimizations for dynamic languages (such as javascript) that + /// rewrite calls to runtimes with more efficient code sequences. + /// This also implies a stack map. + PATCHPOINT = 18 +}; } // end namespace TargetOpcode } // end namespace llvm diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index d9c8651e7ed0..922fae54bb80 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -15,6 +15,7 @@ #ifndef LLVM_TARGET_TARGETOPTIONS_H #define LLVM_TARGET_TARGETOPTIONS_H +#include "llvm/MC/MCTargetOptions.h" #include <string> namespace llvm { @@ -38,21 +39,33 @@ namespace llvm { }; } + namespace JumpTable { + enum JumpTableType { + Single, // Use a single table for all indirect jumptable calls. + Arity, // Use one table per number of function parameters. + Simplified, // Use one table per function type, with types projected + // into 4 types: pointer to non-function, struct, + // primitive, and function pointer. + Full // Use one table per unique function type + }; + } + class TargetOptions { public: TargetOptions() : PrintMachineCode(false), NoFramePointerElim(false), - LessPreciseFPMADOption(false), - UnsafeFPMath(false), NoInfsFPMath(false), - NoNaNsFPMath(false), HonorSignDependentRoundingFPMathOption(false), - UseSoftFloat(false), NoZerosInBSS(false), - JITEmitDebugInfo(false), JITEmitDebugInfoToDisk(false), - GuaranteedTailCallOpt(false), DisableTailCalls(false), - StackAlignmentOverride(0), + LessPreciseFPMADOption(false), UnsafeFPMath(false), + NoInfsFPMath(false), NoNaNsFPMath(false), + HonorSignDependentRoundingFPMathOption(false), UseSoftFloat(false), + NoZerosInBSS(false), JITEmitDebugInfo(false), + JITEmitDebugInfoToDisk(false), GuaranteedTailCallOpt(false), + DisableTailCalls(false), StackAlignmentOverride(0), EnableFastISel(false), PositionIndependentExecutable(false), - EnableSegmentedStacks(false), UseInitArray(false), TrapFuncName(""), - FloatABIType(FloatABI::Default), AllowFPOpFusion(FPOpFusion::Standard) - {} + UseInitArray(false), DisableIntegratedAS(false), + CompressDebugSections(false), FunctionSections(false), + DataSections(false), TrapUnreachable(false), TrapFuncName(""), + FloatABIType(FloatABI::Default), + AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -152,12 +165,25 @@ namespace llvm { /// if the relocation model is anything other than PIC. unsigned PositionIndependentExecutable : 1; - unsigned EnableSegmentedStacks : 1; - /// UseInitArray - Use .init_array instead of .ctors for static /// constructors. unsigned UseInitArray : 1; + /// Disable the integrated assembler. + unsigned DisableIntegratedAS : 1; + + /// Compress DWARF debug sections. + unsigned CompressDebugSections : 1; + + /// Emit functions into separate sections. + unsigned FunctionSections : 1; + + /// Emit data into separate sections. + unsigned DataSections : 1; + + /// Emit target-specific trap instruction for 'unreachable' IR instructions. + unsigned TrapUnreachable : 1; + /// getTrapFunctionName - If this returns a non-empty string, this means /// isel should lower Intrinsic::trap to a call to the specified function /// name instead of an ISD::TRAP node. @@ -189,6 +215,13 @@ namespace llvm { /// via the llvm.fma.* intrinsic) will always be honored, regardless of /// the value of this option. FPOpFusion::FPOpFusionMode AllowFPOpFusion; + + /// JTType - This flag specifies the type of jump-instruction table to + /// create for functions that have the jumptable attribute. + JumpTable::JumpTableType JTType; + + /// Machine level options. + MCTargetOptions MCOptions; }; // Comparison operators: @@ -211,11 +244,12 @@ inline bool operator==(const TargetOptions &LHS, ARE_EQUAL(StackAlignmentOverride) && ARE_EQUAL(EnableFastISel) && ARE_EQUAL(PositionIndependentExecutable) && - ARE_EQUAL(EnableSegmentedStacks) && ARE_EQUAL(UseInitArray) && + ARE_EQUAL(TrapUnreachable) && ARE_EQUAL(TrapFuncName) && ARE_EQUAL(FloatABIType) && - ARE_EQUAL(AllowFPOpFusion); + ARE_EQUAL(AllowFPOpFusion) && + ARE_EQUAL(MCOptions); #undef ARE_EQUAL } diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 958bea6f2b95..5dda8bd4b938 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -174,7 +174,7 @@ public: /// isASubClass - return true if this TargetRegisterClass is a subset /// class of at least one other TargetRegisterClass. bool isASubClass() const { - return SuperClasses[0] != 0; + return SuperClasses[0] != nullptr; } /// getRawAllocationOrder - Returns the preferred order for allocating @@ -317,7 +317,7 @@ public: /// indicating if a register is allocatable or not. If a register class is /// specified, returns the subset for the class. BitVector getAllocatableSet(const MachineFunction &MF, - const TargetRegisterClass *RC = NULL) const; + const TargetRegisterClass *RC = nullptr) const; /// getCostPerUse - Return the additional cost of using this register instead /// of other registers in its class. @@ -420,8 +420,8 @@ public: /// order of desired callee-save stack frame offset. The first register is /// closest to the incoming stack pointer if stack grows down, and vice versa. /// - virtual const MCPhysReg* getCalleeSavedRegs(const MachineFunction *MF = 0) - const = 0; + virtual const MCPhysReg* + getCalleeSavedRegs(const MachineFunction *MF = nullptr) const = 0; /// getCallPreservedMask - Return a mask of call-preserved registers for the /// given calling convention on the current sub-target. The mask should @@ -443,7 +443,7 @@ public: /// virtual const uint32_t *getCallPreservedMask(CallingConv::ID) const { // The default mask clobbers everything. All targets should override. - return 0; + return nullptr; } /// getReservedRegs - Returns a bitset indexed by physical register number @@ -651,7 +651,7 @@ public: ArrayRef<MCPhysReg> Order, SmallVectorImpl<MCPhysReg> &Hints, const MachineFunction &MF, - const VirtRegMap *VRM = 0) const; + const VirtRegMap *VRM = nullptr) const; /// avoidWriteAfterWrite - Return true if the register allocator should avoid /// writing a register from RC in two consecutive instructions. @@ -672,6 +672,28 @@ public: // Do nothing. } + /// Allow the target to reverse allocation order of local live ranges. This + /// will generally allocate shorter local live ranges first. For targets with + /// many registers, this could reduce regalloc compile time by a large + /// factor. It is disabled by default for three reasons: + /// (1) Top-down allocation is simpler and easier to debug for targets that + /// don't benefit from reversing the order. + /// (2) Bottom-up allocation could result in poor evicition decisions on some + /// targets affecting the performance of compiled code. + /// (3) Bottom-up allocation is no longer guaranteed to optimally color. + virtual bool reverseLocalAssignment() const { return false; } + + /// Allow the target to override register assignment heuristics based on the + /// live range size. If this returns false, then local live ranges are always + /// assigned in order regardless of their size. This is a temporary hook for + /// debugging downstream codegen failures exposed by regalloc. + virtual bool mayOverrideLocalAssignment() const { return true; } + + /// Allow the target to override the cost of using a callee-saved register for + /// the first time. Default value of 0 means we will use a callee-saved + /// register if it is available. + virtual unsigned getCSRFirstUseCost() const { return 0; } + /// requiresRegisterScavenging - returns true if the target requires (and can /// make use of) the register scavenger. virtual bool requiresRegisterScavenging(const MachineFunction &MF) const { @@ -748,8 +770,8 @@ public: /// resolveFrameIndex - Resolve a frame index operand of an instruction /// to reference the indicated base register plus offset instead. - virtual void resolveFrameIndex(MachineBasicBlock::iterator I, - unsigned BaseReg, int64_t Offset) const { + virtual void resolveFrameIndex(MachineInstr &MI, unsigned BaseReg, + int64_t Offset) const { llvm_unreachable("resolveFrameIndex does not exist on this target"); } @@ -783,7 +805,19 @@ public: /// instruction. FIOperandNum is the FI operand number. virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, unsigned FIOperandNum, - RegScavenger *RS = NULL) const = 0; + RegScavenger *RS = nullptr) const = 0; + + //===--------------------------------------------------------------------===// + /// Subtarget Hooks + + /// \brief SrcRC and DstRC will be morphed into NewRC if this returns true. + virtual bool shouldCoalesce(MachineInstr *MI, + const TargetRegisterClass *SrcRC, + unsigned SubReg, + const TargetRegisterClass *DstRC, + unsigned DstSubReg, + const TargetRegisterClass *NewRC) const + { return true; } //===--------------------------------------------------------------------===// /// Debug information queries. @@ -791,12 +825,6 @@ public: /// getFrameRegister - This method should return the register used as a base /// for values allocated in the current stack frame. virtual unsigned getFrameRegister(const MachineFunction &MF) const = 0; - - /// getCompactUnwindRegNum - This function maps the register to the number for - /// compact unwind encoding. Return -1 if the register isn't valid. - virtual int getCompactUnwindRegNum(unsigned, bool) const { - return -1; - } }; @@ -852,7 +880,7 @@ public: Mask += RCMaskWords; SubReg = *Idx++; if (!SubReg) - Idx = 0; + Idx = nullptr; } }; @@ -880,7 +908,7 @@ class PrintReg { unsigned Reg; unsigned SubIdx; public: - explicit PrintReg(unsigned reg, const TargetRegisterInfo *tri = 0, + explicit PrintReg(unsigned reg, const TargetRegisterInfo *tri = nullptr, unsigned subidx = 0) : TRI(tri), Reg(reg), SubIdx(subidx) {} void print(raw_ostream&) const; diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index 9d4858ac32f2..89db37ca859b 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -79,6 +79,8 @@ class SchedMachineModel { int MinLatency = -1; // Determines which instructions are allowed in a group. // (-1) inorder (0) ooo, (1): inorder +var latencies. int MicroOpBufferSize = -1; // Max micro-ops that can be buffered. + int LoopMicroOpBufferSize = -1; // Max micro-ops that can be buffered for + // optimized loop dispatch/execution. int LoadLatency = -1; // Cycles for loads to access the cache. int HighLatency = -1; // Approximation of cycles for "high latency" ops. int MispredictPenalty = -1; // Extra cycles for a mispredicted branch. @@ -86,6 +88,8 @@ class SchedMachineModel { // Per-cycle resources tables. ProcessorItineraries Itineraries = NoItineraries; + bit PostRAScheduler = 0; // Enable Post RegAlloc Scheduler pass. + // Subtargets that define a model for only a subset of instructions // that have a scheduling class (itinerary class or SchedRW list) // and may actually be generated for that subtarget must clear this @@ -114,14 +118,46 @@ class ProcResourceKind; // resources implies using one of the super resoruces. // // ProcResourceUnits normally model a few buffered resources within an -// out-of-order engine that the compiler attempts to conserve. -// Buffered resources may be held for multiple clock cycles, but the -// scheduler does not pin them to a particular clock cycle relative to -// instruction dispatch. Setting BufferSize=0 changes this to an -// in-order resource. In this case, the scheduler counts down from the -// cycle that the instruction issues in-order, forcing an interlock -// with subsequent instructions that require the same resource until -// the number of ResourceCyles specified in WriteRes expire. +// out-of-order engine. Buffered resources may be held for multiple +// clock cycles, but the scheduler does not pin them to a particular +// clock cycle relative to instruction dispatch. Setting BufferSize=0 +// changes this to an in-order issue/dispatch resource. In this case, +// the scheduler counts down from the cycle that the instruction +// issues in-order, forcing a stall whenever a subsequent instruction +// requires the same resource until the number of ResourceCyles +// specified in WriteRes expire. Setting BufferSize=1 changes this to +// an in-order latency resource. In this case, the scheduler models +// producer/consumer stalls between instructions that use the +// resource. +// +// Examples (all assume an out-of-order engine): +// +// Use BufferSize = -1 for "issue ports" fed by a unified reservation +// station. Here the size of the reservation station is modeled by +// MicroOpBufferSize, which should be the minimum size of either the +// register rename pool, unified reservation station, or reorder +// buffer. +// +// Use BufferSize = 0 for resources that force "dispatch/issue +// groups". (Different processors define dispath/issue +// differently. Here we refer to stage between decoding into micro-ops +// and moving them into a reservation station.) Normally NumMicroOps +// is sufficient to limit dispatch/issue groups. However, some +// processors can form groups of with only certain combinitions of +// instruction types. e.g. POWER7. +// +// Use BufferSize = 1 for in-order execution units. This is used for +// an in-order pipeline within an out-of-order core where scheduling +// dependent operations back-to-back is guaranteed to cause a +// bubble. e.g. Cortex-a9 floating-point. +// +// Use BufferSize > 1 for out-of-order executions units with a +// separate reservation station. This simply models the size of the +// reservation station. +// +// To model both dispatch/issue groups and in-order execution units, +// create two types of units, one with BufferSize=0 and one with +// BufferSize=1. // // SchedModel ties these units to a processor for any stand-alone defs // of this class. Instances of subclass ProcResource will be automatically diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index d94bdc67bf02..2d822de4ad69 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -205,7 +205,7 @@ def SDTPrefetch : SDTypeProfile<0, 4, [ // prefetch SDTCisPtrTy<0>, SDTCisSameAs<1, 2>, SDTCisSameAs<1, 3>, SDTCisInt<1> ]>; -def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barier +def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barrier SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisSameAs<0,4>, SDTCisInt<0> ]>; @@ -362,7 +362,6 @@ def bitconvert : SDNode<"ISD::BITCAST" , SDTUnaryOp>; def extractelt : SDNode<"ISD::EXTRACT_VECTOR_ELT", SDTVecExtract>; def insertelt : SDNode<"ISD::INSERT_VECTOR_ELT", SDTVecInsert>; - def fadd : SDNode<"ISD::FADD" , SDTFPBinOp, [SDNPCommutative]>; def fsub : SDNode<"ISD::FSUB" , SDTFPBinOp>; def fmul : SDNode<"ISD::FMUL" , SDTFPBinOp, [SDNPCommutative]>; @@ -393,8 +392,8 @@ def sint_to_fp : SDNode<"ISD::SINT_TO_FP" , SDTIntToFPOp>; def uint_to_fp : SDNode<"ISD::UINT_TO_FP" , SDTIntToFPOp>; def fp_to_sint : SDNode<"ISD::FP_TO_SINT" , SDTFPToIntOp>; def fp_to_uint : SDNode<"ISD::FP_TO_UINT" , SDTFPToIntOp>; -def f16_to_f32 : SDNode<"ISD::FP16_TO_FP32", SDTIntToFPOp>; -def f32_to_f16 : SDNode<"ISD::FP32_TO_FP16", SDTFPToIntOp>; +def f16_to_fp : SDNode<"ISD::FP16_TO_FP" , SDTIntToFPOp>; +def fp_to_f16 : SDNode<"ISD::FP_TO_FP16" , SDTFPToIntOp>; def setcc : SDNode<"ISD::SETCC" , SDTSetCC>; def select : SDNode<"ISD::SELECT" , SDTSelect>; @@ -466,7 +465,7 @@ def vector_extract : SDNode<"ISD::EXTRACT_VECTOR_ELT", def vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisPtrTy<3>]>, []>; def concat_vectors : SDNode<"ISD::CONCAT_VECTORS", - SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<1, 2>]>,[]>; + SDTypeProfile<1, 2, [SDTCisSubVecOfVec<1, 0>, SDTCisSameAs<1, 2>]>,[]>; // This operator does not do subvector type checking. The ARM // backend, at least, needs it. @@ -492,6 +491,12 @@ def intrinsic_wo_chain : SDNode<"ISD::INTRINSIC_WO_CHAIN", // Do not use cvt directly. Use cvt forms below def cvt : SDNode<"ISD::CONVERT_RNDSAT", SDTConvertOp>; +def SDT_assertext : SDTypeProfile<1, 1, + [SDTCisInt<0>, SDTCisInt<1>, SDTCisSameAs<1, 0>]>; +def assertsext : SDNode<"ISD::AssertSext", SDT_assertext>; +def assertzext : SDNode<"ISD::AssertZext", SDT_assertext>; + + //===----------------------------------------------------------------------===// // Selection DAG Condition Codes @@ -554,6 +559,12 @@ class PatFrag<dag ops, dag frag, code pred = [{}], SDNodeXForm OperandTransform = xform; } +// OutPatFrag is a pattern fragment that is used as part of an output pattern +// (not an input pattern). These do not have predicates or transforms, but are +// used to avoid repeated subexpressions in output patterns. +class OutPatFrag<dag ops, dag frag> + : PatFrag<ops, frag, [{}], NOOP_SDNodeXForm>; + // PatLeaf's are pattern fragments that have no operands. This is just a helper // to define immediates and other common things concisely. class PatLeaf<dag frag, code pred = [{}], SDNodeXForm xform = NOOP_SDNodeXForm> diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h index 3474ee493eae..78a2db183fb1 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -31,13 +31,13 @@ class TargetSelectionDAGInfo { TargetSelectionDAGInfo(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION; void operator=(const TargetSelectionDAGInfo &) LLVM_DELETED_FUNCTION; - const DataLayout *TD; + const DataLayout *DL; protected: - const DataLayout *getDataLayout() const { return TD; } + const DataLayout *getDataLayout() const { return DL; } public: - explicit TargetSelectionDAGInfo(const TargetMachine &TM); + explicit TargetSelectionDAGInfo(const DataLayout *DL); virtual ~TargetSelectionDAGInfo(); /// EmitTargetCodeForMemcpy - Emit target-specific code that performs a diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index 1b2e06acc2b0..86e303e18348 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -66,6 +66,16 @@ public: /// scheduler. It does not yet disable the postRA scheduler. virtual bool enableMachineScheduler() const; + /// \brief True if the subtarget should run PostMachineScheduler. + /// + /// This only takes effect if the target has configured the + /// PostMachineScheduler pass to run, or if the global cl::opt flag, + /// MISchedPostRA, is set. + virtual bool enablePostMachineScheduler() const; + + /// \brief True if the subtarget should run the atomic expansion pass. + virtual bool enableAtomicExpandLoadLinked() const; + /// \brief Override generic scheduling policy within a region. /// /// This is a convenient way for targets that don't provide any custom @@ -76,25 +86,46 @@ public: MachineInstr *end, unsigned NumRegionInstrs) const {} - // enablePostRAScheduler - If the target can benefit from post-regalloc - // scheduling and the specified optimization level meets the requirement - // return true to enable post-register-allocation scheduling. In - // CriticalPathRCs return any register classes that should only be broken - // if on the critical path. - virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, - AntiDepBreakMode& Mode, - RegClassVector& CriticalPathRCs) const; - // adjustSchedDependency - Perform target specific adjustments to - // the latency of a schedule dependency. + // \brief Perform target specific adjustments to the latency of a schedule + // dependency. virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep& dep) const { } + + // For use with PostRAScheduling: get the anti-dependence breaking that should + // be performed before post-RA scheduling. + virtual AntiDepBreakMode getAntiDepBreakMode() const { + return ANTIDEP_NONE; + } + + // For use with PostRAScheduling: in CriticalPathRCs, return any register + // classes that should only be considered for anti-dependence breaking if they + // are on the critical path. + virtual void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const { + return CriticalPathRCs.clear(); + } + + // For use with PostRAScheduling: get the minimum optimization level needed + // to enable post-RA scheduling. + virtual CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const { + return CodeGenOpt::Default; + } + + /// \brief True if the subtarget should run the local reassignment + /// heuristic of the register allocator. + /// This heuristic may be compile time intensive, \p OptLevel provides + /// a finer grain to tune the register allocator. + virtual bool enableRALocalReassignment(CodeGenOpt::Level OptLevel) const; /// \brief Enable use of alias analysis during code generation (during MI /// scheduling, DAGCombine, etc.). virtual bool useAA() const; + /// \brief Enable the use of the early if conversion pass. + virtual bool enableEarlyIfConversion() const { return false; } + /// \brief Reset the features for the subtarget. virtual void resetSubtargetFeatures(const MachineFunction *MF) { } + }; } // End llvm namespace diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index 7f51c516b9b5..ce1a7d6a5230 100644 --- a/include/llvm/Transforms/IPO.h +++ b/include/llvm/Transforms/IPO.h @@ -34,7 +34,7 @@ ModulePass *createStripSymbolsPass(bool OnlyDebugInfo = false); //===----------------------------------------------------------------------===// // -// These functions strips symbols from functions and modules. +// These functions strips symbols from functions and modules. // Only debugging information is not stripped. // ModulePass *createStripNonDebugSymbolsPass(); @@ -58,40 +58,41 @@ ModulePass *createStripDeadDebugInfoPass(); /// ModulePass *createConstantMergePass(); - //===----------------------------------------------------------------------===// /// createGlobalOptimizerPass - This function returns a new pass that optimizes /// non-address taken internal globals. /// ModulePass *createGlobalOptimizerPass(); - //===----------------------------------------------------------------------===// /// createGlobalDCEPass - This transform is designed to eliminate unreachable /// internal globals (functions or global variables) /// ModulePass *createGlobalDCEPass(); - //===----------------------------------------------------------------------===// /// createGVExtractionPass - If deleteFn is true, this pass deletes /// the specified global values. Otherwise, it deletes as much of the module as /// possible, except for the global values specified. /// -ModulePass *createGVExtractionPass(std::vector<GlobalValue*>& GVs, bool +ModulePass *createGVExtractionPass(std::vector<GlobalValue*>& GVs, bool deleteFn = false); //===----------------------------------------------------------------------===// /// createFunctionInliningPass - Return a new pass object that uses a heuristic /// to inline direct function calls to small functions. /// +/// The Threshold can be passed directly, or asked to be computed from the +/// given optimization and size optimization arguments. +/// /// The -inline-threshold command line option takes precedence over the /// threshold given here. Pass *createFunctionInliningPass(); Pass *createFunctionInliningPass(int Threshold); +Pass *createFunctionInliningPass(unsigned OptLevel, unsigned SizeOptLevel); //===----------------------------------------------------------------------===// -/// createAlwaysInlinerPass - Return a new pass object that inlines only +/// createAlwaysInlinerPass - Return a new pass object that inlines only /// functions that are marked as "always_inline". Pass *createAlwaysInlinerPass(); Pass *createAlwaysInlinerPass(bool InsertLifetime); @@ -187,7 +188,7 @@ ModulePass *createMergeFunctionsPass(); /// createPartialInliningPass - This pass inlines parts of functions. /// ModulePass *createPartialInliningPass(); - + //===----------------------------------------------------------------------===// // createMetaRenamerPass - Rename everything with metasyntatic names. // diff --git a/include/llvm/Transforms/IPO/InlinerPass.h b/include/llvm/Transforms/IPO/InlinerPass.h index 43a0ac8cc1f7..6a644ad4a63b 100644 --- a/include/llvm/Transforms/IPO/InlinerPass.h +++ b/include/llvm/Transforms/IPO/InlinerPass.h @@ -36,16 +36,16 @@ struct Inliner : public CallGraphSCCPass { /// getAnalysisUsage - For this class, we declare that we require and preserve /// the call graph. If the derived class implements this method, it should /// always explicitly call the implementation here. - virtual void getAnalysisUsage(AnalysisUsage &Info) const; + void getAnalysisUsage(AnalysisUsage &Info) const override; // Main run interface method, this implements the interface required by the // Pass class. - virtual bool runOnSCC(CallGraphSCC &SCC); + bool runOnSCC(CallGraphSCC &SCC) override; using llvm::Pass::doFinalization; // doFinalization - Remove now-dead linkonce functions at the end of // processing to avoid breaking the SCC traversal. - virtual bool doFinalization(CallGraph &CG); + bool doFinalization(CallGraph &CG) override; /// This method returns the value specified by the -inline-threshold value, /// specified on the command line. This is typically not directly needed. diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 27887749e960..50877d013702 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -55,7 +55,6 @@ using legacy::FunctionPassManager; /// ... class PassManagerBuilder { public: - /// Extensions are passed the builder itself (so they can see how it is /// configured) as well as the pass manager to add stuff to. typedef void (*ExtensionFn)(const PassManagerBuilder &Builder, @@ -86,7 +85,12 @@ public: /// EP_EnabledOnOptLevel0 - This extension point allows adding passes that /// should not be disabled by O0 optimization level. The passes will be /// inserted after the inlining pass. - EP_EnabledOnOptLevel0 + EP_EnabledOnOptLevel0, + + /// EP_Peephole - This extension point allows adding passes that perform + /// peephole optimizations similar to the instruction combiner. These passes + /// will be inserted after each instance of the instruction combiner pass. + EP_Peephole, }; /// The Optimization Level - Specify the basic optimization level. @@ -106,13 +110,14 @@ public: /// added to the per-module passes. Pass *Inliner; + bool DisableTailCalls; bool DisableUnitAtATime; bool DisableUnrollLoops; bool BBVectorize; bool SLPVectorize; bool LoopVectorize; - bool LateVectorize; bool RerollLoops; + bool LoadCombine; private: /// ExtensionList - This is list of all of the extensions that are registered. @@ -130,8 +135,8 @@ public: private: void addExtensionsToPM(ExtensionPointTy ETy, PassManagerBase &PM) const; void addInitialAliasAnalysisPasses(PassManagerBase &PM) const; -public: +public: /// populateFunctionPassManager - This fills in the function pass manager, /// which is expected to be run on each function immediately as it is /// generated. The idea is to reduce the size of the IR in memory. diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 8a1b34e488be..c6a339b0fd22 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -16,7 +16,7 @@ #include "llvm/ADT/StringRef.h" -#if defined(__GNUC__) && defined(__linux__) +#if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID) inline void *getDFSanArgTLSPtrForJIT() { extern __thread __attribute__((tls_model("initial-exec"))) void *__dfsan_arg_tls; @@ -64,27 +64,21 @@ ModulePass *createGCOVProfilerPass(const GCOVOptions &Options = GCOVOptions::getDefault()); // Insert AddressSanitizer (address sanity checking) instrumentation -FunctionPass *createAddressSanitizerFunctionPass( - bool CheckInitOrder = true, bool CheckUseAfterReturn = false, - bool CheckLifetime = false, StringRef BlacklistFile = StringRef(), - bool ZeroBaseShadow = false); -ModulePass *createAddressSanitizerModulePass( - bool CheckInitOrder = true, StringRef BlacklistFile = StringRef(), - bool ZeroBaseShadow = false); +FunctionPass *createAddressSanitizerFunctionPass(); +ModulePass *createAddressSanitizerModulePass(); // Insert MemorySanitizer instrumentation (detection of uninitialized reads) -FunctionPass *createMemorySanitizerPass(bool TrackOrigins = false, - StringRef BlacklistFile = StringRef()); +FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0); // Insert ThreadSanitizer (race detection) instrumentation -FunctionPass *createThreadSanitizerPass(StringRef BlacklistFile = StringRef()); +FunctionPass *createThreadSanitizerPass(); // Insert DataFlowSanitizer (dynamic data flow analysis) instrumentation ModulePass *createDataFlowSanitizerPass(StringRef ABIListFile = StringRef(), - void *(*getArgTLS)() = 0, - void *(*getRetValTLS)() = 0); + void *(*getArgTLS)() = nullptr, + void *(*getRetValTLS)() = nullptr); -#if defined(__GNUC__) && defined(__linux__) +#if defined(__GNUC__) && defined(__linux__) && !defined(ANDROID) inline ModulePass *createDataFlowSanitizerPassForJIT(StringRef ABIListFile = StringRef()) { return createDataFlowSanitizerPass(ABIListFile, getDFSanArgTLSPtrForJIT, diff --git a/include/llvm/Transforms/ObjCARC.h b/include/llvm/Transforms/ObjCARC.h index b3c19c077eab..1897adc2ffbf 100644 --- a/include/llvm/Transforms/ObjCARC.h +++ b/include/llvm/Transforms/ObjCARC.h @@ -46,4 +46,3 @@ Pass *createObjCARCOptPass(); } // End llvm namespace #endif - diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 1521c4cff562..413134e51c7a 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -19,6 +19,7 @@ namespace llvm { +class BasicBlockPass; class FunctionPass; class Pass; class GetElementPtrInst; @@ -122,7 +123,7 @@ Pass *createLICMPass(); // Pass *createLoopStrengthReducePass(); -Pass *createGlobalMergePass(const TargetMachine *TM = 0); +Pass *createGlobalMergePass(const TargetMachine *TM = nullptr); //===----------------------------------------------------------------------===// // @@ -142,6 +143,8 @@ Pass *createLoopInstSimplifyPass(); // Pass *createLoopUnrollPass(int Threshold = -1, int Count = -1, int AllowPartial = -1, int Runtime = -1); +// Create an unrolling pass for full unrolling only. +Pass *createSimpleLoopUnrollPass(); //===----------------------------------------------------------------------===// // @@ -153,14 +156,14 @@ Pass *createLoopRerollPass(); // // LoopRotate - This pass is a simple loop rotating pass. // -Pass *createLoopRotatePass(); +Pass *createLoopRotatePass(int MaxHeaderSize = -1); //===----------------------------------------------------------------------===// // // LoopIdiom - This pass recognizes and replaces idioms in loops. // Pass *createLoopIdiomPass(); - + //===----------------------------------------------------------------------===// // // PromoteMemoryToRegister - This pass is used to promote memory references to @@ -199,7 +202,7 @@ FunctionPass *createReassociatePass(); // preds always go to some succ. // FunctionPass *createJumpThreadingPass(); - + //===----------------------------------------------------------------------===// // // CFGSimplification - Merge basic blocks, eliminate unreachable blocks, @@ -262,16 +265,10 @@ extern char &LowerSwitchID; //===----------------------------------------------------------------------===// // -// LowerInvoke - This pass converts invoke and unwind instructions to use sjlj -// exception handling mechanisms. Note that after this pass runs the CFG is not -// entirely accurate (exceptional control flow edges are not correct anymore) so -// only very simple things should be done after the lowerinvoke pass has run -// (like generation of native code). This should *NOT* be used as a general -// purpose "my LLVM-to-LLVM pass doesn't support the invoke instruction yet" -// lowering pass. +// LowerInvoke - This pass removes invoke instructions, converting them to call +// instructions. // -FunctionPass *createLowerInvokePass(const TargetMachine *TM = 0, - bool useExpensiveEHSupport = false); +FunctionPass *createLowerInvokePass(); extern char &LowerInvokePassID; //===----------------------------------------------------------------------===// @@ -288,10 +285,17 @@ extern char &LCSSAID; // tree. // FunctionPass *createEarlyCSEPass(); - + +//===----------------------------------------------------------------------===// +// +// MergedLoadStoreMotion - This pass merges loads and stores in diamonds. Loads +// are hoisted into the header, while stores sink into the footer. +// +FunctionPass *createMergedLoadStoreMotionPass(); + //===----------------------------------------------------------------------===// // -// GVN - This pass performs global value numbering and redundant load +// GVN - This pass performs global value numbering and redundant load // elimination cotemporaneously. // FunctionPass *createGVNPass(bool NoLoads = false); @@ -309,12 +313,12 @@ FunctionPass *createMemCpyOptPass(); // can prove are dead. // Pass *createLoopDeletionPass(); - + //===----------------------------------------------------------------------===// // -// CodeGenPrepare - This pass prepares a function for instruction selection. +// ConstantHoisting - This pass prepares a function for expensive constants. // -FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = 0); +FunctionPass *createConstantHoistingPass(); //===----------------------------------------------------------------------===// // @@ -322,7 +326,7 @@ FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = 0); // FunctionPass *createInstructionNamerPass(); extern char &InstructionNamerID; - + //===----------------------------------------------------------------------===// // // Sink - Code Sinking @@ -348,14 +352,12 @@ Pass *createCorrelatedValuePropagationPass(); FunctionPass *createInstructionSimplifierPass(); extern char &InstructionSimplifierID; - //===----------------------------------------------------------------------===// // // LowerExpectIntrinsics - Removes llvm.expect intrinsics and creates // "block_weights" metadata. FunctionPass *createLowerExpectIntrinsicPass(); - //===----------------------------------------------------------------------===// // // PartiallyInlineLibCalls - Tries to inline the fast path of library @@ -370,6 +372,29 @@ FunctionPass *createPartiallyInlineLibCallsPass(); FunctionPass *createSampleProfileLoaderPass(); FunctionPass *createSampleProfileLoaderPass(StringRef Name); +//===----------------------------------------------------------------------===// +// +// ScalarizerPass - Converts vector operations into scalar operations +// +FunctionPass *createScalarizerPass(); + +//===----------------------------------------------------------------------===// +// +// AddDiscriminators - Add DWARF path discriminators to the IR. +FunctionPass *createAddDiscriminatorsPass(); + +//===----------------------------------------------------------------------===// +// +// SeparateConstOffsetFromGEP - Split GEPs for better CSE +// +FunctionPass *createSeparateConstOffsetFromGEPPass(); + +//===----------------------------------------------------------------------===// +// +// LoadCombine - Combine loads into bigger loads. +// +BasicBlockPass *createLoadCombinePass(); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/ASanStackFrameLayout.h b/include/llvm/Transforms/Utils/ASanStackFrameLayout.h new file mode 100644 index 000000000000..4e4f02c84ece --- /dev/null +++ b/include/llvm/Transforms/Utils/ASanStackFrameLayout.h @@ -0,0 +1,64 @@ +//===- ASanStackFrameLayout.h - ComputeASanStackFrameLayout -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines ComputeASanStackFrameLayout and auxiliary data structs. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TRANSFORMS_UTILS_ASANSTACKFRAMELAYOUT_H +#define LLVM_TRANSFORMS_UTILS_ASANSTACKFRAMELAYOUT_H +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class AllocaInst; + +// These magic constants should be the same as in +// in asan_internal.h from ASan runtime in compiler-rt. +static const int kAsanStackLeftRedzoneMagic = 0xf1; +static const int kAsanStackMidRedzoneMagic = 0xf2; +static const int kAsanStackRightRedzoneMagic = 0xf3; + +// Input/output data struct for ComputeASanStackFrameLayout. +struct ASanStackVariableDescription { + const char *Name; // Name of the variable that will be displayed by asan + // if a stack-related bug is reported. + uint64_t Size; // Size of the variable in bytes. + size_t Alignment; // Alignment of the variable (power of 2). + AllocaInst *AI; // The actual AllocaInst. + size_t Offset; // Offset from the beginning of the frame; + // set by ComputeASanStackFrameLayout. +}; + +// Output data struct for ComputeASanStackFrameLayout. +struct ASanStackFrameLayout { + // Frame description, see DescribeAddressIfStack in ASan runtime. + SmallString<64> DescriptionString; + // The contents of the shadow memory for the stack frame that we need + // to set at function entry. + SmallVector<uint8_t, 64> ShadowBytes; + size_t FrameAlignment; // Alignment for the entire frame. + size_t FrameSize; // Size of the frame in bytes. +}; + +void ComputeASanStackFrameLayout( + // The array of stack variables. The elements may get reordered and changed. + SmallVectorImpl<ASanStackVariableDescription> &Vars, + // AddressSanitizer's shadow granularity. Usually 8, may also be 16, 32, 64. + size_t Granularity, + // The minimal size of the left-most redzone (header). + // At least 4 pointer sizes, power of 2, and >= Granularity. + // The resulting FrameSize should be multiple of MinHeaderSize. + size_t MinHeaderSize, + // The result is put here. + ASanStackFrameLayout *Layout); + +} // llvm namespace + +#endif // LLVM_TRANSFORMS_UTILS_ASANSTACKFRAMELAYOUT_H diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 65cafe2ec281..bcafda657c2b 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -18,11 +18,12 @@ // FIXME: Move to this file: BasicBlock::removePredecessor, BB::splitBasicBlock #include "llvm/IR/BasicBlock.h" -#include "llvm/Support/CFG.h" +#include "llvm/IR/CFG.h" namespace llvm { class AliasAnalysis; +class DominatorTree; class Instruction; class MDNode; class Pass; @@ -34,23 +35,22 @@ class TerminatorInst; /// predecessors. void DeleteDeadBlock(BasicBlock *BB); - /// FoldSingleEntryPHINodes - We know that BB has one predecessor. If there are /// any single-entry PHI nodes in it, fold them away. This handles the case /// when all entries to the PHI nodes in a block are guaranteed equal, such as /// when the block has exactly one predecessor. -void FoldSingleEntryPHINodes(BasicBlock *BB, Pass *P = 0); +void FoldSingleEntryPHINodes(BasicBlock *BB, Pass *P = nullptr); /// DeleteDeadPHIs - Examine each PHI in the given block and delete it if it /// is dead. Also recursively delete any operands that become dead as /// a result. This includes tracing the def-use list from the PHI to see if /// it is ultimately unused or if it reaches an unused cycle. Return true /// if any PHIs were deleted. -bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = 0); +bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr); /// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor, /// if possible. The return value indicates success or failure. -bool MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P = 0); +bool MergeBlockIntoPredecessor(BasicBlock *BB, Pass *P = nullptr); // ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) // with a value, then remove and delete the original instruction. @@ -89,12 +89,13 @@ void ReplaceInstWithInst(Instruction *From, Instruction *To); /// to. /// BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, - Pass *P = 0, bool MergeIdenticalEdges = false, + Pass *P = nullptr, + bool MergeIdenticalEdges = false, bool DontDeleteUselessPHIs = false, bool SplitLandingPads = false); inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, - Pass *P = 0) { + Pass *P = nullptr) { return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P); } @@ -103,7 +104,8 @@ inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, /// This updates all of the same analyses as the other SplitCriticalEdge /// function. If P is specified, it updates the analyses /// described above. -inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, Pass *P = 0) { +inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, + Pass *P = nullptr) { bool MadeChange = false; TerminatorInst *TI = (*PI)->getTerminator(); for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) @@ -117,7 +119,7 @@ inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, Pass *P = 0) { /// an edge between the two blocks. If P is specified, it updates the analyses /// described above. inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, - Pass *P = 0, + Pass *P = nullptr, bool MergeIdenticalEdges = false, bool DontDeleteUselessPHIs = false) { TerminatorInst *TI = Src->getTerminator(); @@ -155,7 +157,7 @@ BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P); /// is an exit of a loop with other exits). /// BasicBlock *SplitBlockPredecessors(BasicBlock *BB, ArrayRef<BasicBlock*> Preds, - const char *Suffix, Pass *P = 0); + const char *Suffix, Pass *P = nullptr); /// SplitLandingPadPredecessors - This method transforms the landing pad, /// OrigBB, by introducing two new basic blocks into the function. One of those @@ -183,27 +185,49 @@ ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, BasicBlock *Pred); /// SplitBlockAndInsertIfThen - Split the containing block at the -/// specified instruction - everything before and including Cmp stays -/// in the old basic block, and everything after Cmp is moved to a +/// specified instruction - everything before and including SplitBefore stays +/// in the old basic block, and everything after SplitBefore is moved to a /// new block. The two blocks are connected by a conditional branch /// (with value of Cmp being the condition). /// Before: /// Head -/// Cmp +/// SplitBefore /// Tail /// After: /// Head -/// Cmp -/// if (Cmp) +/// if (Cond) /// ThenBlock +/// SplitBefore /// Tail /// /// If Unreachable is true, then ThenBlock ends with /// UnreachableInst, otherwise it branches to Tail. /// Returns the NewBasicBlock's terminator. - -TerminatorInst *SplitBlockAndInsertIfThen(Instruction *Cmp, - bool Unreachable, MDNode *BranchWeights = 0); +/// +/// Updates DT if given. +TerminatorInst *SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, + bool Unreachable, + MDNode *BranchWeights = nullptr, + DominatorTree *DT = nullptr); + +/// SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, +/// but also creates the ElseBlock. +/// Before: +/// Head +/// SplitBefore +/// Tail +/// After: +/// Head +/// if (Cond) +/// ThenBlock +/// else +/// ElseBlock +/// SplitBefore +/// Tail +void SplitBlockAndInsertIfThenElse(Value *Cond, Instruction *SplitBefore, + TerminatorInst **ThenTerm, + TerminatorInst **ElseTerm, + MDNode *BranchWeights = nullptr); /// /// GetIfCondition - Check whether BB is the merge point of a if-region. @@ -211,9 +235,8 @@ TerminatorInst *SplitBlockAndInsertIfThen(Instruction *Cmp, /// BB will be taken. Also, return by references the block that will be /// entered from if the condition is true, and the block that will be /// entered if the condition is false. - Value *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue, - BasicBlock *&IfFalse); + BasicBlock *&IfFalse); } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index 181ed071eab1..1e407fb468e1 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -21,7 +21,7 @@ namespace llvm { class Value; class DataLayout; class TargetLibraryInfo; - + /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. Value *CastToCStr(Value *V, IRBuilder<> &B); @@ -83,6 +83,14 @@ namespace llvm { Value *EmitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B, const AttributeSet &Attrs); + /// EmitUnaryFloatFnCall - Emit a call to the binary function named 'Name' + /// (e.g. 'fmin'). This function is known to take type matching 'Op1' and + /// 'Op2' and return one value with the same type. If 'Op1/Op2' are long + /// double, 'l' is added as the suffix of name, if 'Op1/Op2' are float, we + /// add a 'f' suffix. + Value *EmitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name, + IRBuilder<> &B, const AttributeSet &Attrs); + /// EmitPutChar - Emit a call to the putchar function. This assumes that Char /// is an integer. Value *EmitPutChar(Value *Char, IRBuilder<> &B, const DataLayout *TD, @@ -116,6 +124,7 @@ namespace llvm { virtual void replaceCall(Value *With) = 0; virtual bool isFoldable(unsigned SizeCIOp, unsigned SizeArgOp, bool isString) const = 0; + public: virtual ~SimplifyFortifiedLibCalls(); bool fold(CallInst *CI, const DataLayout *TD, const TargetLibraryInfo *TLI); diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index 3ec132937c0d..bdf50ddf5cc6 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -20,8 +20,8 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" -#include "llvm/ADT/ValueMap.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/IR/ValueMap.h" #include "llvm/Transforms/Utils/ValueMapper.h" namespace llvm { @@ -55,17 +55,16 @@ struct ClonedCodeInfo { /// ContainsCalls - This is set to true if the cloned code contains a normal /// call instruction. bool ContainsCalls; - + /// ContainsDynamicAllocas - This is set to true if the cloned code contains /// a 'dynamic' alloca. Dynamic allocas are allocas that are either not in /// the entry block or they are in the entry block but are not a constant /// size. bool ContainsDynamicAllocas; - + ClonedCodeInfo() : ContainsCalls(false), ContainsDynamicAllocas(false) {} }; - /// CloneBasicBlock - Return a copy of the specified basic block, but without /// embedding the block into a particular function. The block returned is an /// exact copy of the specified basic block, without any remapping having been @@ -96,8 +95,8 @@ struct ClonedCodeInfo { /// BasicBlock *CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, - const Twine &NameSuffix = "", Function *F = 0, - ClonedCodeInfo *CodeInfo = 0); + const Twine &NameSuffix = "", Function *F = nullptr, + ClonedCodeInfo *CodeInfo = nullptr); /// CloneFunction - Return a copy of the specified function, but without /// embedding the function into another module. Also, any references specified @@ -109,12 +108,12 @@ BasicBlock *CloneBasicBlock(const BasicBlock *BB, /// information about the cloned code if non-null. /// /// If ModuleLevelChanges is false, VMap contains no non-identity GlobalValue -/// mappings. +/// mappings, and debug info metadata will not be cloned. /// Function *CloneFunction(const Function *F, ValueToValueMapTy &VMap, bool ModuleLevelChanges, - ClonedCodeInfo *CodeInfo = 0); + ClonedCodeInfo *CodeInfo = nullptr); /// Clone OldFunc into NewFunc, transforming the old arguments into references /// to VMap values. Note that if NewFunc already has basic blocks, the ones @@ -129,10 +128,10 @@ void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, bool ModuleLevelChanges, SmallVectorImpl<ReturnInst*> &Returns, - const char *NameSuffix = "", - ClonedCodeInfo *CodeInfo = 0, - ValueMapTypeRemapper *TypeMapper = 0, - ValueMaterializer *Materializer = 0); + const char *NameSuffix = "", + ClonedCodeInfo *CodeInfo = nullptr, + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr); /// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto, /// except that it does some simple constant prop and DCE on the fly. The @@ -149,23 +148,22 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, bool ModuleLevelChanges, SmallVectorImpl<ReturnInst*> &Returns, - const char *NameSuffix = "", - ClonedCodeInfo *CodeInfo = 0, - const DataLayout *TD = 0, - Instruction *TheCall = 0); + const char *NameSuffix = "", + ClonedCodeInfo *CodeInfo = nullptr, + const DataLayout *DL = nullptr, + Instruction *TheCall = nullptr); - /// InlineFunctionInfo - This class captures the data input to the -/// InlineFunction call, and records the auxiliary results produced by it. +/// InlineFunction call, and records the auxiliary results produced by it. class InlineFunctionInfo { public: - explicit InlineFunctionInfo(CallGraph *cg = 0, const DataLayout *td = 0) - : CG(cg), TD(td) {} - + explicit InlineFunctionInfo(CallGraph *cg = nullptr, const DataLayout *DL = nullptr) + : CG(cg), DL(DL) {} + /// CG - If non-null, InlineFunction will update the callgraph to reflect the /// changes it makes. CallGraph *CG; - const DataLayout *TD; + const DataLayout *DL; /// StaticAllocas - InlineFunction fills this in with all static allocas that /// get copied into the caller. @@ -174,13 +172,13 @@ public: /// InlinedCalls - InlineFunction fills this in with callsites that were /// inlined from the callee. This is only filled in if CG is non-null. SmallVector<WeakVH, 8> InlinedCalls; - + void reset() { StaticAllocas.clear(); InlinedCalls.clear(); } }; - + /// InlineFunction - This function inlines the called function into the basic /// block of the caller. This returns false if it is not possible to inline /// this call. The program is still in a well defined state if this occurs diff --git a/include/llvm/Transforms/Utils/CmpInstAnalysis.h b/include/llvm/Transforms/Utils/CmpInstAnalysis.h index 488d7a59d329..73c15e42c359 100644 --- a/include/llvm/Transforms/Utils/CmpInstAnalysis.h +++ b/include/llvm/Transforms/Utils/CmpInstAnalysis.h @@ -1,4 +1,4 @@ -//===-- CmpInstAnalysis.h - Utils to help fold compare insts ------===// +//===-- CmpInstAnalysis.h - Utils to help fold compare insts ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -63,4 +63,3 @@ namespace llvm { } // end namespace llvm #endif - diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h index 1122678035b5..6b41e82dac73 100644 --- a/include/llvm/Transforms/Utils/CodeExtractor.h +++ b/include/llvm/Transforms/Utils/CodeExtractor.h @@ -66,7 +66,7 @@ namespace llvm { /// dominates the rest, prepare a code extractor object for pulling this /// sequence out into its new function. When a DominatorTree is also given, /// extra checking and transformations are enabled. - CodeExtractor(ArrayRef<BasicBlock *> BBs, DominatorTree *DT = 0, + CodeExtractor(ArrayRef<BasicBlock *> BBs, DominatorTree *DT = nullptr, bool AggregateArgs = false); /// \brief Create a code extractor for a loop body. @@ -120,7 +120,6 @@ namespace llvm { BasicBlock *newHeader, ValueSet &inputs, ValueSet &outputs); - }; } diff --git a/include/llvm/Transforms/Utils/CtorUtils.h b/include/llvm/Transforms/Utils/CtorUtils.h new file mode 100644 index 000000000000..81e7b951c252 --- /dev/null +++ b/include/llvm/Transforms/Utils/CtorUtils.h @@ -0,0 +1,32 @@ +//===- CtorUtils.h - Helpers for working with global_ctors ------*- 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 functions that are used to process llvm.global_ctors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H +#define LLVM_TRANSFORMS_UTILS_CTOR_UTILS_H + +#include "llvm/ADT/STLExtras.h" + +namespace llvm { + +class GlobalVariable; +class Function; +class Module; + +/// Call "ShouldRemove" for every entry in M's global_ctor list and remove the +/// entries for which it returns true. Return true if anything changed. +bool optimizeGlobalCtorsList(Module &M, + function_ref<bool(Function *)> ShouldRemove); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/Utils/IntegerDivision.h b/include/llvm/Transforms/Utils/IntegerDivision.h index 27d3c588b518..0ec3321b9cf8 100644 --- a/include/llvm/Transforms/Utils/IntegerDivision.h +++ b/include/llvm/Transforms/Utils/IntegerDivision.h @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// // -// This file contains an implementation of 32bit integer division for targets -// that don't have native support. It's largely derived from compiler-rt's -// implementation of __udivsi3, but hand-tuned for targets that prefer less -// control flow. +// This file contains an implementation of 32bit and 64bit scalar integer +// division for targets that don't have native support. It's largely derived +// from compiler-rt's implementations of __udivsi3 and __udivmoddi4, +// but hand-tuned for targets that prefer less control flow. // //===----------------------------------------------------------------------===// @@ -26,9 +26,8 @@ namespace llvm { /// Generate code to calculate the remainder of two integers, replacing Rem /// with the generated code. This currently generates code using the udiv /// expansion, but future work includes generating more specialized code, - /// e.g. when more information about the operands are known. Currently only - /// implements 32bit scalar division (due to udiv's limitation), but future - /// work is removing this limitation. + /// e.g. when more information about the operands are known. Implements both + /// 32bit and 64bit scalar division. /// /// @brief Replace Rem with generated code. bool expandRemainder(BinaryOperator *Rem); @@ -36,27 +35,39 @@ namespace llvm { /// Generate code to divide two integers, replacing Div with the generated /// code. This currently generates code similarly to compiler-rt's /// implementations, but future work includes generating more specialized code - /// when more information about the operands are known. Currently only - /// implements 32bit scalar division, but future work is removing this - /// limitation. + /// when more information about the operands are known. Implements both + /// 32bit and 64bit scalar division. /// /// @brief Replace Div with generated code. bool expandDivision(BinaryOperator* Div); /// Generate code to calculate the remainder of two integers, replacing Rem - /// with the generated code. Uses the above 32bit routine, therefore adequate - /// for targets with little or no support for less than 32 bit arithmetic. + /// with the generated code. Uses ExpandReminder with a 32bit Rem which + /// makes it useful for targets with little or no support for less than + /// 32 bit arithmetic. /// /// @brief Replace Rem with generated code. bool expandRemainderUpTo32Bits(BinaryOperator *Rem); - /// Generate code to divide two integers, replacing Div with the generated - /// code. Uses the above 32bit routine, therefore adequate for targets with - /// little or no support for less than 32 bit arithmetic. - /// + /// Generate code to calculate the remainder of two integers, replacing Rem + /// with the generated code. Uses ExpandReminder with a 64bit Rem. + /// + /// @brief Replace Rem with generated code. + bool expandRemainderUpTo64Bits(BinaryOperator *Rem); + + /// Generate code to divide two integers, replacing Div with the generated + /// code. Uses ExpandDivision with a 32bit Div which makes it useful for + /// targets with little or no support for less than 32 bit arithmetic. + /// /// @brief Replace Rem with generated code. bool expandDivisionUpTo32Bits(BinaryOperator *Div); + /// Generate code to divide two integers, replacing Div with the generated + /// code. Uses ExpandDivision with a 64bit Div. + /// + /// @brief Replace Rem with generated code. + bool expandDivisionUpTo64Bits(BinaryOperator *Div); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index 5586c155bb11..c0c690664a9c 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -16,9 +16,9 @@ #define LLVM_TRANSFORMS_UTILS_LOCAL_H #include "llvm/IR/DataLayout.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Operator.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" namespace llvm { @@ -55,7 +55,7 @@ template<typename T> class SmallVectorImpl; /// conditions and indirectbr addresses this might make dead if /// DeleteDeadConditions is true. bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false, - const TargetLibraryInfo *TLI = 0); + const TargetLibraryInfo *TLI = nullptr); //===----------------------------------------------------------------------===// // Local dead code elimination. @@ -64,30 +64,31 @@ bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false, /// isInstructionTriviallyDead - Return true if the result produced by the /// instruction is not used, and the instruction has no side effects. /// -bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=0); +bool isInstructionTriviallyDead(Instruction *I, + const TargetLibraryInfo *TLI = nullptr); /// RecursivelyDeleteTriviallyDeadInstructions - If the specified value is a /// trivially dead instruction, delete it. If that makes any of its operands /// trivially dead, delete them too, recursively. Return true if any /// instructions were deleted. bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, - const TargetLibraryInfo *TLI=0); + const TargetLibraryInfo *TLI = nullptr); /// RecursivelyDeleteDeadPHINode - If the specified value is an effectively /// dead PHI node, due to being a def-use chain of single-use nodes that /// either forms a cycle or is terminated by a trivially dead instruction, /// delete it. If that makes any of its operands trivially dead, delete them /// too, recursively. Return true if a change was made. -bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo *TLI=0); - +bool RecursivelyDeleteDeadPHINode(PHINode *PN, + const TargetLibraryInfo *TLI = nullptr); /// SimplifyInstructionsInBlock - Scan the specified basic block and try to /// simplify any instructions in it and recursively delete dead instructions. /// /// This returns true if it changed the code, note that it can delete /// instructions in other blocks as well in this block. -bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = 0, - const TargetLibraryInfo *TLI = 0); +bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr); //===----------------------------------------------------------------------===// // Control Flow Graph Restructuring. @@ -105,16 +106,14 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = 0, /// .. and delete the predecessor corresponding to the '1', this will attempt to /// recursively fold the 'and' to 0. void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, - DataLayout *TD = 0); - + DataLayout *TD = nullptr); /// MergeBasicBlockIntoOnlyPred - BB is a block with one predecessor and its /// predecessor is known to have one successor (BB!). Eliminate the edge /// between them, moving the instructions in the predecessor into BB. This /// deletes the predecessor block. /// -void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, Pass *P = 0); - +void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, Pass *P = nullptr); /// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an /// unconditional branch, and contains no instructions other than PHI nodes, @@ -137,19 +136,19 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB); /// the basic block that was pointed to. /// bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, - const DataLayout *TD = 0); + const DataLayout *TD = nullptr); /// FlatternCFG - This function is used to flatten a CFG. For /// example, it uses parallel-and and parallel-or mode to collapse // if-conditions and merge if-regions with identical statements. /// -bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = 0); +bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = nullptr); /// FoldBranchToCommonDest - If this basic block is ONLY a setcc and a branch, /// and if a predecessor branches to us and one of our successors, fold the /// setcc into the predecessor and use logical operations to pick the right /// destination. -bool FoldBranchToCommonDest(BranchInst *BI); +bool FoldBranchToCommonDest(BranchInst *BI, const DataLayout *DL = nullptr); /// DemoteRegToStack - This function takes a virtual register computed by an /// Instruction and replaces it with a slot in the stack frame, allocated via @@ -159,22 +158,23 @@ bool FoldBranchToCommonDest(BranchInst *BI); /// AllocaInst *DemoteRegToStack(Instruction &X, bool VolatileLoads = false, - Instruction *AllocaPoint = 0); + Instruction *AllocaPoint = nullptr); /// DemotePHIToStack - This function takes a virtual register computed by a phi /// node and replaces it with a slot in the stack frame, allocated via alloca. /// The phi node is deleted and it returns the pointer to the alloca inserted. -AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = 0); +AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = nullptr); /// getOrEnforceKnownAlignment - If the specified pointer has an alignment that /// we can determine, return it, otherwise return 0. If PrefAlign is specified, /// and it is more than the alignment of the ultimate object, see if we can /// increase the alignment of the ultimate object, making this check succeed. unsigned getOrEnforceKnownAlignment(Value *V, unsigned PrefAlign, - const DataLayout *TD = 0); + const DataLayout *TD = nullptr); /// getKnownAlignment - Try to infer an alignment for the specified pointer. -static inline unsigned getKnownAlignment(Value *V, const DataLayout *TD = 0) { +static inline unsigned getKnownAlignment(Value *V, + const DataLayout *TD = nullptr) { return getOrEnforceKnownAlignment(V, 0, TD); } diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h index 4745eba079ae..7e3a74aae93c 100644 --- a/include/llvm/Transforms/Utils/LoopUtils.h +++ b/include/llvm/Transforms/Utils/LoopUtils.h @@ -15,12 +15,51 @@ #define LLVM_TRANSFORMS_UTILS_LOOPUTILS_H namespace llvm { - +class AliasAnalysis; +class BasicBlock; +class DataLayout; +class DominatorTree; class Loop; +class LoopInfo; class Pass; +class ScalarEvolution; BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P); +/// \brief Simplify each loop in a loop nest recursively. +/// +/// This takes a potentially un-simplified loop L (and its children) and turns +/// it into a simplified loop nest with preheaders and single backedges. It +/// will optionally update \c AliasAnalysis and \c ScalarEvolution analyses if +/// passed into it. +bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, Pass *PP, + AliasAnalysis *AA = nullptr, ScalarEvolution *SE = nullptr, + const DataLayout *DL = nullptr); + +/// \brief Put loop into LCSSA form. +/// +/// Looks at all instructions in the loop which have uses outside of the +/// current loop. For each, an LCSSA PHI node is inserted and the uses outside +/// the loop are rewritten to use this node. +/// +/// LoopInfo and DominatorTree are required and preserved. +/// +/// If ScalarEvolution is passed in, it will be preserved. +/// +/// Returns true if any modifications are made to the loop. +bool formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE = nullptr); + +/// \brief Put a loop nest into LCSSA form. +/// +/// This recursively forms LCSSA for a loop nest. +/// +/// LoopInfo and DominatorTree are required and preserved. +/// +/// If ScalarEvolution is passed in, it will be preserved. +/// +/// Returns true if any modifications are made to the loop. +bool formLCSSARecursively(Loop &L, DominatorTree &DT, + ScalarEvolution *SE = nullptr); } #endif diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h index 22f46e5fc963..c83fedb0e2ca 100644 --- a/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -41,7 +41,7 @@ bool isAllocaPromotable(const AllocaInst *AI); /// If AST is specified, the specified tracker is updated to reflect changes /// made to the IR. void PromoteMemToReg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT, - AliasSetTracker *AST = 0); + AliasSetTracker *AST = nullptr); } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h index 0c0e5de584fd..7874a5fd8119 100644 --- a/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/include/llvm/Transforms/Utils/SSAUpdater.h @@ -56,7 +56,7 @@ private: public: /// If InsertedPHIs is specified, it will be filled /// in with all PHI Nodes created by rewriting. - explicit SSAUpdater(SmallVectorImpl<PHINode*> *InsertedPHIs = 0); + explicit SSAUpdater(SmallVectorImpl<PHINode*> *InsertedPHIs = nullptr); ~SSAUpdater(); /// \brief Reset this object to get ready for a new set of SSA updates with @@ -133,31 +133,31 @@ private: class LoadAndStorePromoter { protected: SSAUpdater &SSA; + public: LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts, SSAUpdater &S, StringRef Name = StringRef()); virtual ~LoadAndStorePromoter() {} - + /// \brief This does the promotion. /// /// Insts is a list of loads and stores to promote, and Name is the basename /// for the PHIs to insert. After this is complete, the loads and stores are /// removed from the code. void run(const SmallVectorImpl<Instruction*> &Insts) const; - - + /// \brief Return true if the specified instruction is in the Inst list. /// /// The Insts list is the one passed into the constructor. Clients should /// implement this with a more efficient version if possible. virtual bool isInstInList(Instruction *I, const SmallVectorImpl<Instruction*> &Insts) const; - + /// \brief This hook is invoked after all the stores are found and inserted as /// available values. virtual void doExtraRewritesBeforeFinalDeletion() const { } - + /// \brief Clients can choose to implement this to get notified right before /// a load is RAUW'd another value. virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const { diff --git a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h index a9adbd73c152..ed0841c46c27 100644 --- a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h +++ b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h @@ -17,12 +17,14 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { +#define DEBUG_TYPE "ssaupdater" + class CastInst; class PHINode; template<typename T> class SSAUpdaterTraits; @@ -52,8 +54,8 @@ private: PhiT *PHITag; // Marker for existing PHIs that match. BBInfo(BlkT *ThisBB, ValT V) - : BB(ThisBB), AvailableVal(V), DefBB(V ? this : 0), BlkNum(0), IDom(0), - NumPreds(0), Preds(0), PHITag(0) { } + : BB(ThisBB), AvailableVal(V), DefBB(V ? this : nullptr), BlkNum(0), + IDom(nullptr), NumPreds(0), Preds(nullptr), PHITag(nullptr) {} }; typedef DenseMap<BlkT*, ValT> AvailableValsTy; @@ -115,7 +117,7 @@ public: Traits::FindPredecessorBlocks(Info->BB, &Preds); Info->NumPreds = Preds.size(); if (Info->NumPreds == 0) - Info->Preds = 0; + Info->Preds = nullptr; else Info->Preds = static_cast<BBInfo**> (Allocator.Allocate(Info->NumPreds * sizeof(BBInfo*), @@ -148,7 +150,7 @@ public: // Now that we know what blocks are backwards-reachable from the starting // block, do a forward depth-first traversal to assign postorder numbers // to those blocks. - BBInfo *PseudoEntry = new (Allocator) BBInfo(0, 0); + BBInfo *PseudoEntry = new (Allocator) BBInfo(nullptr, 0); unsigned BlkNum = 1; // Initialize the worklist with the roots from the backward traversal. @@ -231,7 +233,7 @@ public: for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(), E = BlockList->rend(); I != E; ++I) { BBInfo *Info = *I; - BBInfo *NewIDom = 0; + BBInfo *NewIDom = nullptr; // Iterate through the block's predecessors. for (unsigned p = 0; p != Info->NumPreds; ++p) { @@ -386,7 +388,7 @@ public: // Match failed: clear all the PHITag values. for (typename BlockListTy::iterator I = BlockList->begin(), E = BlockList->end(); I != E; ++I) - (*I)->PHITag = 0; + (*I)->PHITag = nullptr; } } @@ -451,6 +453,8 @@ public: } }; +#undef DEBUG_TYPE // "ssaupdater" + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/SimplifyIndVar.h b/include/llvm/Transforms/Utils/SimplifyIndVar.h index 7e97e218fb0b..dcb1d67cbf75 100644 --- a/include/llvm/Transforms/Utils/SimplifyIndVar.h +++ b/include/llvm/Transforms/Utils/SimplifyIndVar.h @@ -16,12 +16,13 @@ #ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H #define LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/ValueHandle.h" namespace llvm { class CastInst; +class DominatorTree; class IVUsers; class Loop; class LPPassManager; @@ -31,16 +32,33 @@ class ScalarEvolution; /// Interface for visiting interesting IV users that are recognized but not /// simplified by this utility. class IVVisitor { +protected: + const DominatorTree *DT; + bool ShouldSplitOverflowIntrinsics; + virtual void anchor(); + public: + IVVisitor(): DT(nullptr), ShouldSplitOverflowIntrinsics(false) {} virtual ~IVVisitor() {} + + const DominatorTree *getDomTree() const { return DT; } + + bool shouldSplitOverflowInstrinsics() const { + return ShouldSplitOverflowIntrinsics; + } + void setSplitOverflowIntrinsics() { + ShouldSplitOverflowIntrinsics = true; + assert(DT && "Splitting overflow intrinsics requires a DomTree."); + } + virtual void visitCast(CastInst *Cast) = 0; }; /// simplifyUsersOfIV - Simplify instructions that use this induction variable /// by using ScalarEvolution to analyze the IV's recurrence. bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, LPPassManager *LPM, - SmallVectorImpl<WeakVH> &Dead, IVVisitor *V = NULL); + SmallVectorImpl<WeakVH> &Dead, IVVisitor *V = nullptr); /// SimplifyLoopIVs - Simplify users of induction variables within this /// loop. This does not actually change or add IVs. diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h index 6bb81be2fd5f..a2a5f9a45601 100644 --- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -30,6 +30,7 @@ namespace llvm { /// Impl - A pointer to the actual implementation of the library call /// simplifier. LibCallSimplifierImpl *Impl; + public: LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI, bool UnsafeFPShrink); diff --git a/include/llvm/Transforms/Utils/SpecialCaseList.h b/include/llvm/Transforms/Utils/SpecialCaseList.h deleted file mode 100644 index 34c28fc1cafe..000000000000 --- a/include/llvm/Transforms/Utils/SpecialCaseList.h +++ /dev/null @@ -1,110 +0,0 @@ -//===-- SpecialCaseList.h - special case list for sanitizers ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===// -// -// This is a utility class for instrumentation passes (like AddressSanitizer -// or ThreadSanitizer) to avoid instrumenting some functions or global -// variables based on a user-supplied list. -// -// The list can also specify categories for specific globals, which can be used -// to instruct an instrumentation pass to treat certain functions or global -// variables in a specific way, such as by omitting certain aspects of -// instrumentation while keeping others, or informing the instrumentation pass -// that a specific uninstrumentable function has certain semantics, thus -// allowing the pass to instrument callers according to those semantics. -// -// For example, AddressSanitizer uses the "init" category for globals whose -// initializers should not be instrumented, but which in all other respects -// should be instrumented. -// -// Each line contains a prefix, followed by a colon and a wild card expression, -// followed optionally by an equals sign and an instrumentation-specific -// category. Empty lines and lines starting with "#" are ignored. -// --- -// # Blacklisted items: -// fun:*_ZN4base6subtle* -// global:*global_with_bad_access_or_initialization* -// global:*global_with_initialization_issues*=init -// type:*Namespace::ClassName*=init -// src:file_with_tricky_code.cc -// src:ignore-global-initializers-issues.cc=init -// -// # Functions with pure functional semantics: -// fun:cos=functional -// fun:sin=functional -// --- -// Note that the wild card is in fact an llvm::Regex, but * is automatically -// replaced with .* -// This is similar to the "ignore" feature of ThreadSanitizer. -// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores -// -//===----------------------------------------------------------------------===// -// - -#include "llvm/ADT/StringMap.h" - -namespace llvm { -class Function; -class GlobalAlias; -class GlobalVariable; -class MemoryBuffer; -class Module; -class Regex; -class StringRef; - -class SpecialCaseList { - public: - /// Parses the special case list from a file. If Path is empty, returns - /// an empty special case list. On failure, returns 0 and writes an error - /// message to string. - static SpecialCaseList *create(const StringRef Path, std::string &Error); - /// Parses the special case list from a memory buffer. On failure, returns - /// 0 and writes an error message to string. - static SpecialCaseList *create(const MemoryBuffer *MB, std::string &Error); - /// Parses the special case list from a file. On failure, reports a fatal - /// error. - static SpecialCaseList *createOrDie(const StringRef Path); - - ~SpecialCaseList(); - - /// Returns whether either this function or its source file are listed in the - /// given category, which may be omitted to search the empty category. - bool isIn(const Function &F, const StringRef Category = StringRef()) const; - - /// Returns whether this global, its type or its source file are listed in the - /// given category, which may be omitted to search the empty category. - bool isIn(const GlobalVariable &G, - const StringRef Category = StringRef()) const; - - /// Returns whether this global alias is listed in the given category, which - /// may be omitted to search the empty category. - /// - /// If GA aliases a function, the alias's name is matched as a function name - /// would be. Similarly, aliases of globals are matched like globals. - bool isIn(const GlobalAlias &GA, - const StringRef Category = StringRef()) const; - - /// Returns whether this module is listed in the given category, which may be - /// omitted to search the empty category. - bool isIn(const Module &M, const StringRef Category = StringRef()) const; - - private: - SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION; - SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION; - - struct Entry; - StringMap<StringMap<Entry> > Entries; - - SpecialCaseList(); - /// Parses just-constructed SpecialCaseList entries from a memory buffer. - bool parse(const MemoryBuffer *MB, std::string &Error); - - bool inSectionCategory(const StringRef Section, const StringRef Query, - const StringRef Category) const; -}; - -} // namespace llvm diff --git a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h index 933c85c51609..7ac2572f9af3 100644 --- a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h +++ b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -24,15 +24,16 @@ namespace llvm { struct UnifyFunctionExitNodes : public FunctionPass { BasicBlock *ReturnBlock, *UnwindBlock, *UnreachableBlock; + public: static char ID; // Pass identification, replacement for typeid UnifyFunctionExitNodes() : FunctionPass(ID), - ReturnBlock(0), UnwindBlock(0) { + ReturnBlock(nullptr), UnwindBlock(nullptr) { initializeUnifyFunctionExitNodesPass(*PassRegistry::getPassRegistry()); } // We can preserve non-critical-edgeness when we unify function exit nodes - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; // getReturn|Unwind|UnreachableBlock - Return the new single (or nonexistent) // return, unwind, or unreachable basic blocks in the CFG. @@ -41,7 +42,7 @@ public: BasicBlock *getUnwindBlock() const { return UnwindBlock; } BasicBlock *getUnreachableBlock() const { return UnreachableBlock; } - virtual bool runOnFunction(Function &F); + bool runOnFunction(Function &F) override; }; Pass *createUnifyFunctionExitNodesPass(); diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h index f175e8371e79..aaadd7d48bdc 100644 --- a/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/include/llvm/Transforms/Utils/UnrollLoop.h @@ -21,13 +21,14 @@ namespace llvm { class Loop; class LoopInfo; class LPPassManager; +class Pass; bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime, - unsigned TripMultiple, LoopInfo* LI, LPPassManager* LPM); + unsigned TripMultiple, LoopInfo *LI, Pass *PP, + LPPassManager *LPM); bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI, LPPassManager* LPM); - } #endif diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h index d56ac07690fd..5774763575d3 100644 --- a/include/llvm/Transforms/Utils/ValueMapper.h +++ b/include/llvm/Transforms/Utils/ValueMapper.h @@ -15,7 +15,7 @@ #ifndef LLVM_TRANSFORMS_UTILS_VALUEMAPPER_H #define LLVM_TRANSFORMS_UTILS_VALUEMAPPER_H -#include "llvm/ADT/ValueMap.h" +#include "llvm/IR/ValueMap.h" namespace llvm { class Value; @@ -28,7 +28,7 @@ namespace llvm { virtual void anchor(); // Out of line method. public: virtual ~ValueMapTypeRemapper() {} - + /// remapType - The client should implement this method if they want to /// remap types while mapping values. virtual Type *remapType(Type *SrcTy) = 0; @@ -46,53 +46,52 @@ namespace llvm { /// lazily. virtual Value *materializeValueFor(Value *V) = 0; }; - + /// RemapFlags - These are flags that the value mapping APIs allow. enum RemapFlags { RF_None = 0, - + /// RF_NoModuleLevelChanges - If this flag is set, the remapper knows that /// only local values within a function (such as an instruction or argument) /// are mapped, not global values like functions and global metadata. RF_NoModuleLevelChanges = 1, - + /// RF_IgnoreMissingEntries - If this flag is set, the remapper ignores /// entries that are not in the value map. If it is unset, it aborts if an /// operand is asked to be remapped which doesn't exist in the mapping. RF_IgnoreMissingEntries = 2 }; - + static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) { return RemapFlags(unsigned(LHS)|unsigned(RHS)); } - + Value *MapValue(const Value *V, ValueToValueMapTy &VM, RemapFlags Flags = RF_None, - ValueMapTypeRemapper *TypeMapper = 0, - ValueMaterializer *Materializer = 0); + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr); void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags = RF_None, - ValueMapTypeRemapper *TypeMapper = 0, - ValueMaterializer *Materializer = 0); - + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr); + /// MapValue - provide versions that preserve type safety for MDNode and /// Constants. inline MDNode *MapValue(const MDNode *V, ValueToValueMapTy &VM, RemapFlags Flags = RF_None, - ValueMapTypeRemapper *TypeMapper = 0, - ValueMaterializer *Materializer = 0) { + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr) { return cast<MDNode>(MapValue((const Value*)V, VM, Flags, TypeMapper, Materializer)); } inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM, RemapFlags Flags = RF_None, - ValueMapTypeRemapper *TypeMapper = 0, - ValueMaterializer *Materializer = 0) { + ValueMapTypeRemapper *TypeMapper = nullptr, + ValueMaterializer *Materializer = nullptr) { return cast<Constant>(MapValue((const Value*)V, VM, Flags, TypeMapper, Materializer)); } - } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/VectorUtils.h b/include/llvm/Transforms/Utils/VectorUtils.h new file mode 100644 index 000000000000..44a7149eee98 --- /dev/null +++ b/include/llvm/Transforms/Utils/VectorUtils.h @@ -0,0 +1,195 @@ +//===- llvm/Transforms/Utils/VectorUtils.h - Vector utilities -*- C++ -*-=====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines some vectorizer utilities. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H +#define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H + +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/Target/TargetLibraryInfo.h" + +namespace llvm { + +/// \brief Identify if the intrinsic is trivially vectorizable. +/// +/// This method returns true if the intrinsic's argument types are all +/// scalars for the scalar form of the intrinsic and all vectors for +/// the vector form of the intrinsic. +static inline bool isTriviallyVectorizable(Intrinsic::ID ID) { + switch (ID) { + case Intrinsic::sqrt: + case Intrinsic::sin: + case Intrinsic::cos: + case Intrinsic::exp: + case Intrinsic::exp2: + case Intrinsic::log: + case Intrinsic::log10: + case Intrinsic::log2: + case Intrinsic::fabs: + case Intrinsic::copysign: + case Intrinsic::floor: + case Intrinsic::ceil: + case Intrinsic::trunc: + case Intrinsic::rint: + case Intrinsic::nearbyint: + case Intrinsic::round: + case Intrinsic::bswap: + case Intrinsic::ctpop: + case Intrinsic::pow: + case Intrinsic::fma: + case Intrinsic::fmuladd: + case Intrinsic::ctlz: + case Intrinsic::cttz: + case Intrinsic::powi: + return true; + default: + return false; + } +} + +static bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID, + unsigned ScalarOpdIdx) { + switch (ID) { + case Intrinsic::ctlz: + case Intrinsic::cttz: + case Intrinsic::powi: + return (ScalarOpdIdx == 1); + default: + return false; + } +} + +static Intrinsic::ID checkUnaryFloatSignature(const CallInst &I, + Intrinsic::ID ValidIntrinsicID) { + if (I.getNumArgOperands() != 1 || + !I.getArgOperand(0)->getType()->isFloatingPointTy() || + I.getType() != I.getArgOperand(0)->getType() || + !I.onlyReadsMemory()) + return Intrinsic::not_intrinsic; + + return ValidIntrinsicID; +} + +static Intrinsic::ID checkBinaryFloatSignature(const CallInst &I, + Intrinsic::ID ValidIntrinsicID) { + if (I.getNumArgOperands() != 2 || + !I.getArgOperand(0)->getType()->isFloatingPointTy() || + !I.getArgOperand(1)->getType()->isFloatingPointTy() || + I.getType() != I.getArgOperand(0)->getType() || + I.getType() != I.getArgOperand(1)->getType() || + !I.onlyReadsMemory()) + return Intrinsic::not_intrinsic; + + return ValidIntrinsicID; +} + +static Intrinsic::ID +getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI) { + // If we have an intrinsic call, check if it is trivially vectorizable. + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) { + Intrinsic::ID ID = II->getIntrinsicID(); + if (isTriviallyVectorizable(ID) || ID == Intrinsic::lifetime_start || + ID == Intrinsic::lifetime_end) + return ID; + else + return Intrinsic::not_intrinsic; + } + + if (!TLI) + return Intrinsic::not_intrinsic; + + LibFunc::Func Func; + Function *F = CI->getCalledFunction(); + // We're going to make assumptions on the semantics of the functions, check + // that the target knows that it's available in this environment and it does + // not have local linkage. + if (!F || F->hasLocalLinkage() || !TLI->getLibFunc(F->getName(), Func)) + return Intrinsic::not_intrinsic; + + // Otherwise check if we have a call to a function that can be turned into a + // vector intrinsic. + switch (Func) { + default: + break; + case LibFunc::sin: + case LibFunc::sinf: + case LibFunc::sinl: + return checkUnaryFloatSignature(*CI, Intrinsic::sin); + case LibFunc::cos: + case LibFunc::cosf: + case LibFunc::cosl: + return checkUnaryFloatSignature(*CI, Intrinsic::cos); + case LibFunc::exp: + case LibFunc::expf: + case LibFunc::expl: + return checkUnaryFloatSignature(*CI, Intrinsic::exp); + case LibFunc::exp2: + case LibFunc::exp2f: + case LibFunc::exp2l: + return checkUnaryFloatSignature(*CI, Intrinsic::exp2); + case LibFunc::log: + case LibFunc::logf: + case LibFunc::logl: + return checkUnaryFloatSignature(*CI, Intrinsic::log); + case LibFunc::log10: + case LibFunc::log10f: + case LibFunc::log10l: + return checkUnaryFloatSignature(*CI, Intrinsic::log10); + case LibFunc::log2: + case LibFunc::log2f: + case LibFunc::log2l: + return checkUnaryFloatSignature(*CI, Intrinsic::log2); + case LibFunc::fabs: + case LibFunc::fabsf: + case LibFunc::fabsl: + return checkUnaryFloatSignature(*CI, Intrinsic::fabs); + case LibFunc::copysign: + case LibFunc::copysignf: + case LibFunc::copysignl: + return checkBinaryFloatSignature(*CI, Intrinsic::copysign); + case LibFunc::floor: + case LibFunc::floorf: + case LibFunc::floorl: + return checkUnaryFloatSignature(*CI, Intrinsic::floor); + case LibFunc::ceil: + case LibFunc::ceilf: + case LibFunc::ceill: + return checkUnaryFloatSignature(*CI, Intrinsic::ceil); + case LibFunc::trunc: + case LibFunc::truncf: + case LibFunc::truncl: + return checkUnaryFloatSignature(*CI, Intrinsic::trunc); + case LibFunc::rint: + case LibFunc::rintf: + case LibFunc::rintl: + return checkUnaryFloatSignature(*CI, Intrinsic::rint); + case LibFunc::nearbyint: + case LibFunc::nearbyintf: + case LibFunc::nearbyintl: + return checkUnaryFloatSignature(*CI, Intrinsic::nearbyint); + case LibFunc::round: + case LibFunc::roundf: + case LibFunc::roundl: + return checkUnaryFloatSignature(*CI, Intrinsic::round); + case LibFunc::pow: + case LibFunc::powf: + case LibFunc::powl: + return checkBinaryFloatSignature(*CI, Intrinsic::pow); + } + + return Intrinsic::not_intrinsic; +} + +} // llvm namespace + +#endif diff --git a/include/llvm/Transforms/Vectorize.h b/include/llvm/Transforms/Vectorize.h index 823c5fba745e..aec3993d68fc 100644 --- a/include/llvm/Transforms/Vectorize.h +++ b/include/llvm/Transforms/Vectorize.h @@ -47,6 +47,9 @@ struct VectorizeConfig { /// @brief Vectorize floating-point math intrinsics. bool VectorizeMath; + /// @brief Vectorize bit intrinsics. + bool VectorizeBitManipulations; + /// @brief Vectorize the fused-multiply-add intrinsic. bool VectorizeFMA; @@ -114,7 +117,8 @@ createBBVectorizePass(const VectorizeConfig &C = VectorizeConfig()); // // LoopVectorize - Create a loop vectorization pass. // -Pass *createLoopVectorizePass(bool NoUnrolling = false); +Pass *createLoopVectorizePass(bool NoUnrolling = false, + bool AlwaysVectorize = true); //===----------------------------------------------------------------------===// // diff --git a/include/llvm/module.modulemap b/include/llvm/module.modulemap new file mode 100644 index 000000000000..1790a7242e5b --- /dev/null +++ b/include/llvm/module.modulemap @@ -0,0 +1,177 @@ +module LLVM_Analysis { + requires cplusplus + umbrella "Analysis" + module * { export * } + exclude header "Analysis/BlockFrequencyInfoImpl.h" +} + +module LLVM_AsmParser { requires cplusplus umbrella "AsmParser" module * { export * } } + +// A module covering CodeGen/ and Target/. These are intertwined +// and codependent, and thus notionally form a single module. +module LLVM_Backend { + requires cplusplus + + module CodeGen { + umbrella "CodeGen" + module * { export * } + + // FIXME: Why is this excluded? + exclude header "CodeGen/MachineValueType.h" + + // Exclude these; they're intended to be included into only a single + // translation unit (or none) and aren't part of this module. + exclude header "CodeGen/CommandFlags.h" + exclude header "CodeGen/LinkAllAsmWriterComponents.h" + exclude header "CodeGen/LinkAllCodegenComponents.h" + } + + module Target { + umbrella "Target" + module * { export * } + } + + // FIXME: Where should this go? + module Analysis_BlockFrequencyInfoImpl { + header "Analysis/BlockFrequencyInfoImpl.h" + export * + } +} + +module LLVM_Bitcode { requires cplusplus umbrella "Bitcode" module * { export * } } +module LLVM_Config { requires cplusplus umbrella "Config" module * { export * } } +module LLVM_DebugInfo { requires cplusplus umbrella "DebugInfo" module * { export * } } +module LLVM_ExecutionEngine { + requires cplusplus + + umbrella "ExecutionEngine" + module * { export * } + + // Exclude this; it's an optional component of the ExecutionEngine. + exclude header "ExecutionEngine/OProfileWrapper.h" + + // Exclude these; they're intended to be included into only a single + // translation unit (or none) and aren't part of this module. + exclude header "ExecutionEngine/JIT.h" + exclude header "ExecutionEngine/MCJIT.h" + exclude header "ExecutionEngine/Interpreter.h" +} + +module LLVM_IR { + requires cplusplus + + // FIXME: Is this the right place for these? + module Pass { header "Pass.h" export * } + module PassSupport { header "PassSupport.h" export * } + module PassAnalysisSupport { header "PassAnalysisSupport.h" export * } + module PassRegistry { header "PassRegistry.h" export * } + module InitializePasses { header "InitializePasses.h" export * } + + umbrella "IR" + module * { export * } + + // We cannot have llvm/PassManager.h and llvm/IR/PassManager.h in the same TU, + // so we can't include llvm/IR/PassManager.h in the IR module. + exclude header "IR/PassManager.h" + exclude header "IR/LegacyPassManager.h" + + // Exclude this; it's intended for (repeated) textual inclusion. + exclude header "IR/Instruction.def" +} + +module LLVM_LegacyPassManager { + requires cplusplus + module CompatInterface { header "PassManager.h" export * } + module Implementation { header "IR/LegacyPassManager.h" export * } +} + +module LLVM_IR_PassManager { + requires cplusplus + // FIXME PR19358: This doesn't work! conflict LLVM_LegacyPassManager, "cannot use legacy pass manager and new pass manager in same file" + header "IR/PassManager.h" + export * +} + +module LLVM_IRReader { requires cplusplus umbrella "IRReader" module * { export * } } +module LLVM_LineEditor { requires cplusplus umbrella "LineEditor" module * { export * } } +module LLVM_LTO { requires cplusplus umbrella "LTO" module * { export * } } + +module LLVM_MC { + requires cplusplus + + // FIXME: Mislayered? + module Support_TargetRegistry { + header "Support/TargetRegistry.h" + export * + } + + umbrella "MC" + module * { export * } + + // Exclude this; it's fundamentally non-modular. + exclude header "MC/MCTargetOptionsCommandFlags.h" +} + +module LLVM_Object { requires cplusplus umbrella "Object" module * { export * } } +module LLVM_Option { requires cplusplus umbrella "Option" module * { export * } } +module LLVM_TableGen { requires cplusplus umbrella "TableGen" module * { export * } } + +module LLVM_Transforms { + requires cplusplus + umbrella "Transforms" + module * { export * } + + // FIXME: Excluded because it does bad things with the legacy pass manager. + exclude header "Transforms/IPO/PassManagerBuilder.h" +} + +// A module covering ADT/ and Support/. These are intertwined and +// codependent, and notionally form a single module. +module LLVM_Utils { + module ADT { + requires cplusplus + + umbrella "ADT" + module * { export * } + } + + module Support { + requires cplusplus + + umbrella "Support" + module * { export * } + + // Exclude this; it's only included on Solaris. + exclude header "Support/Solaris.h" + + // Exclude this; it's only included on AIX and fundamentally non-modular. + exclude header "Support/AIXDataTypesFix.h" + + // Exclude this; it's fundamentally non-modular. + exclude header "Support/Debug.h" + + // Exclude this; it's fundamentally non-modular. + exclude header "Support/PluginLoader.h" + + // Exclude this; it's a weirdly-factored part of llvm-gcov and conflicts + // with the Analysis module (which also defines an llvm::GCOVOptions). + exclude header "Support/GCOV.h" + + // FIXME: Mislayered? + exclude header "Support/TargetRegistry.h" + } +} + +module LLVM_CodeGen_MachineValueType { + requires cplusplus + header "CodeGen/MachineValueType.h" + export * +} + +// This is used for a $src == $build compilation. Otherwise we use +// LLVM_Support_DataTypes_Build, defined in a module map that is +// copied into the build area. +module LLVM_Support_DataTypes_Src { + header "llvm/Support/DataTypes.h" + export * +} diff --git a/include/llvm/module.modulemap.build b/include/llvm/module.modulemap.build new file mode 100644 index 000000000000..7150fe93935f --- /dev/null +++ b/include/llvm/module.modulemap.build @@ -0,0 +1,5 @@ +// This is copied into the build area for a $src != $build compilation. +module LLVM_Support_DataTypes { + header "Support/DataTypes.h" + export * +} |