diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /include | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2 |
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'include')
401 files changed, 15480 insertions, 9062 deletions
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 9953d52..50c5e3a 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; @@ -167,7 +158,8 @@ typedef enum { LLVMAddressSafety = 1ULL << 32, LLVMStackProtectStrongAttribute = 1ULL<<33, LLVMCold = 1ULL << 34, - LLVMOptimizeNone = 1ULL << 35 + LLVMOptimizeNone = 1ULL << 35, + LLVMInAllocaAttribute = 1ULL << 36 */ } LLVMAttribute; @@ -283,8 +275,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 +291,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, @@ -1688,6 +1686,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 +1700,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 +1709,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 +2667,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); diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h index 79bcfcd..8f31150 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 3564312..7cdf0d7 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 d0a23be..5001afb 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/Support.h b/include/llvm-c/Support.h index 7f03ede..4e6ff22 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 e159411..d4993e7 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/Scalar.h b/include/llvm-c/Transforms/Scalar.h index 355e8dc..9b820b2 100644 --- a/include/llvm-c/Transforms/Scalar.h +++ b/include/llvm-c/Transforms/Scalar.h @@ -41,6 +41,9 @@ void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM); /** See llvm::createDeadStoreEliminationPass function. */ void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM); +/** See llvm::createScalarizerPass function. */ +void LLVMAddScalarizerPass(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 89f54b7..049c4d7 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,18 +65,23 @@ 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_model; - /** opaque reference to a loaded object module */ typedef struct LTOModule* lto_module_t; @@ -86,6 +94,8 @@ extern "C" { /** * Returns a printable string. + * + * \since prior to LTO_API_VERSION=3 */ extern const char* lto_get_version(void); @@ -93,12 +103,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 +120,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 +130,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 +139,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 +150,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 +160,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 +188,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 +223,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 +232,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 +241,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 +359,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 +368,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,12 +378,16 @@ 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, @@ -266,6 +396,8 @@ lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, /** * Tells LTO optimization passes that this symbol must be preserved * because it is referenced by native code or a command line option. + * + * \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 +406,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 +419,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 +428,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 +437,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 +446,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/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 43a7866..acfefe9 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(); /// @} @@ -411,6 +412,7 @@ public: /// @} APFloat &operator=(const APFloat &); + APFloat &operator=(APFloat &&); /// \brief Overload to compute a hash code for an APFloat value. /// diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index d494ad2..aa3c3f6 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 ad035a7..053deff 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; } diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index e5562c3..fcf280d 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -12,6 +12,7 @@ #include "llvm/ADT/None.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" #include <vector> namespace llvm { @@ -76,7 +77,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,6 +121,13 @@ namespace llvm { return Data[Length-1]; } + // copy - Allocate copy in BumpPtrAllocator and return ArrayRef<T> to it. + ArrayRef<T> copy(BumpPtrAllocator &Allocator) { + T *Buff = Allocator.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) diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 8fb538f..b531820 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -58,14 +58,14 @@ 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; } }; @@ -98,12 +98,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; } -#endif ~BitVector() { std::free(Bits); @@ -240,7 +238,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 +265,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 +277,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 +304,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 +318,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 +330,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 +459,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES const BitVector &operator=(BitVector &&RHS) { if (this == &RHS) return *this; @@ -472,7 +471,6 @@ public: 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 ce322cc..037989f 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -161,7 +161,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 +176,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 +216,6 @@ public: return FindAndConstruct(Key).second; } -#if LLVM_HAS_RVALUE_REFERENCES value_type& FindAndConstruct(KeyT &&Key) { BucketT *TheBucket; if (LookupBucketFor(Key, TheBucket)) @@ -230,7 +227,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 +285,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 +399,6 @@ private: return TheBucket; } -#if LLVM_HAS_RVALUE_REFERENCES BucketT *InsertIntoBucket(const KeyT &Key, ValueT &&Value, BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); @@ -420,7 +415,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 @@ -555,12 +549,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 +577,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES DenseMap& operator=(DenseMap &&other) { this->destroyAll(); operator delete(Buckets); @@ -593,7 +584,6 @@ public: swap(other); return *this; } -#endif void copyFrom(const DenseMap& other) { this->destroyAll(); @@ -719,12 +709,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 +753,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 +772,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 +782,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 +794,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 +802,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES SmallDenseMap& operator=(SmallDenseMap &&other) { this->destroyAll(); deallocateBuckets(); @@ -822,7 +809,6 @@ public: swap(other); return *this; } -#endif void copyFrom(const SmallDenseMap& other) { this->destroyAll(); @@ -830,7 +816,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 +852,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 +868,7 @@ public: return; } - LargeRep OldRep = llvm_move(*getLargeRep()); + LargeRep OldRep = std::move(*getLargeRep()); getLargeRep()->~LargeRep(); if (AtLeast <= InlineBuckets) { Small = true; @@ -991,7 +977,8 @@ 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; diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index d699ad5..1d8c39c 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -27,7 +27,9 @@ 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; + explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {} bool empty() const { return TheMap.empty(); } @@ -54,11 +56,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/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index 1d81772..2256ee7 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -249,7 +249,6 @@ 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()!"); diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h index 1b2c94c..188010d 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 @@ -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); } diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index e434417..4bffd8e 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -109,7 +109,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. /// @@ -352,24 +353,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 +378,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); @@ -451,7 +452,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 +735,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/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index b8b8861..729e37f 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,7 +135,7 @@ namespace llvm { template <typename T> class IntrusiveRefCntPtr { T* Obj; - typedef IntrusiveRefCntPtr this_type; + public: typedef T element_type; @@ -123,7 +149,6 @@ namespace llvm { retain(); } -#if LLVM_HAS_RVALUE_REFERENCES IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) { S.Obj = 0; } @@ -132,7 +157,6 @@ namespace llvm { IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.getPtr()) { S.Obj = 0; } -#endif template <class X> IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S) diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index f6fcb08..7fd1570 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 { @@ -97,7 +95,7 @@ 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); } diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 194e53f..ae8344d 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 index 6b9e42e..034bcfd 100644 --- a/include/llvm/ADT/OwningPtr.h +++ b/include/llvm/ADT/OwningPtr.h @@ -17,6 +17,7 @@ #include "llvm/Support/Compiler.h" #include <cassert> #include <cstddef> +#include <memory> namespace llvm { @@ -32,13 +33,22 @@ class OwningPtr { 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; } + + OwningPtr(std::unique_ptr<T> Other) : Ptr(Other.release()) {} + + OwningPtr &operator=(std::unique_ptr<T> Other) { + reset(Other.release()); + return *this; + } + +#if LLVM_HAS_RVALUE_REFERENCE_THIS + operator std::unique_ptr<T>() && { return std::unique_ptr<T>(take()); } #endif ~OwningPtr() { @@ -63,6 +73,10 @@ public: return Tmp; } + T *release() { return take(); } + + std::unique_ptr<T> take_unique() { return std::unique_ptr<T>(take()); } + T &operator*() const { assert(Ptr && "Cannot dereference null pointer"); return *Ptr; @@ -96,14 +110,12 @@ class OwningArrayPtr { 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; diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index 0cfd470..45a40db 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 05d362f..8cbe8d1 100644 --- a/include/llvm/ADT/PointerUnion.h +++ b/include/llvm/ADT/PointerUnion.h @@ -15,8 +15,8 @@ #ifndef LLVM_ADT_POINTERUNION_H #define LLVM_ADT_POINTERUNION_H -#include "llvm/Support/Compiler.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Compiler.h" namespace llvm { diff --git a/include/llvm/ADT/SCCIterator.h b/include/llvm/ADT/SCCIterator.h index 8ce4fd5..58ac149 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 @@ -27,90 +29,111 @@ namespace llvm { -//===----------------------------------------------------------------------===// +/// \brief Enumerate the SCCs of a directed graph in reverse topological order +/// of the SCC DAG. /// -/// scc_iterator - 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 std::iterator<std::forward_iterator_tag, + std::vector<typename GT::NodeType>, ptrdiff_t> { + typedef typename GT::NodeType NodeType; typedef typename GT::ChildIteratorType ChildItTy; - typedef std::vector<NodeType*> SccTy; + 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; + // 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; + // 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; // A single "visit" within the non-recursive DFS traversal. void DFSVisitOne(NodeType *N) { - ++visitNum; // Global counter for the visit order + ++visitNum; 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"; + 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 } // The stack-based DFS traversal; defined below. void DFSVisitChildren() { assert(!VisitStack.empty()); - while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { + while (VisitStack.back().NextChild != + GT::child_end(VisitStack.back().Node)) { // TOS has at least one more child so continue DFS - NodeType *childN = *VisitStack.back().second++; - if (!nodeVisitNumbers.count(childN)) { + 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 = nodeVisitNumbers[childN]; - if (MinVisitNumStack.back() > childNum) - MinVisitNumStack.back() = childNum; + unsigned childNum = Visited->second; + if (VisitStack.back().MinVisited > childNum) + VisitStack.back().MinVisited = childNum; } } // Compute the next SCC using the DFS traversal. void GetNextSCC() { - assert(VisitStack.size() == MinVisitNumStack.size()); - CurrentSCC.clear(); // Prepare to compute the next SCC + 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(); + + // 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(); - 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"; + // 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; @@ -132,36 +155,38 @@ class scc_iterator 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. + inline 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 inline scc_iterator begin(const GraphT &G) { + return scc_iterator(GT::getEntryNode(G)); + } + static inline scc_iterator end(const GraphT &) { return scc_iterator(); } - // Direct loop termination test: I.isAtEnd() is more efficient than I == end() + /// \brief Direct loop termination test which is more efficient than + /// comparison with \c end(). inline bool isAtEnd() const { assert(!CurrentSCC.empty() || VisitStack.empty()); return CurrentSCC.empty(); } - inline bool operator==(const _Self& x) const { + inline bool operator==(const scc_iterator &x) const { return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC; } - inline bool operator!=(const _Self& x) const { return !operator==(x); } + inline bool operator!=(const scc_iterator &x) const { return !operator==(x); } - // Iterator traversal: forward iteration only - inline _Self& operator++() { // Preincrement + inline scc_iterator &operator++() { GetNextSCC(); return *this; } - inline _Self operator++(int) { // Postincrement - _Self tmp = *this; ++*this; return tmp; + inline scc_iterator operator++(int) { + scc_iterator 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; @@ -171,21 +196,24 @@ public: 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. + /// \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 { assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); - if (CurrentSCC.size() > 1) return true; + 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) + for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE; + ++CI) if (*CI == N) return true; return false; } - /// 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 +221,23 @@ public: } }; - -// 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 3aa8183..ab6884f 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 { @@ -95,8 +97,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 +141,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 { @@ -327,6 +255,163 @@ 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 + } // End llvm namespace #endif diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h index 5eda37c..1e7d237 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 86949b2..e965bc4 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -153,11 +153,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()) @@ -506,7 +504,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES const SmallBitVector &operator=(SmallBitVector &&RHS) { if (this != &RHS) { clear(); @@ -514,7 +511,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 bd0d883..67104f3 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,15 +60,17 @@ 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: bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { return size() == 0; } @@ -128,13 +130,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 +166,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 +231,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 +262,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. + unsigned count(PtrType Ptr) const { + return count_imp(PtrTraits::getAsVoidPointer(Ptr)) ? 1 : 0; } template <typename IterT> @@ -279,18 +281,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 5dfe924..6f36234 100644 --- a/include/llvm/ADT/SmallSet.h +++ b/include/llvm/ADT/SmallSet.h @@ -39,16 +39,19 @@ class SmallSet { public: SmallSet() {} - bool empty() const { return Vector.empty() && Set.empty(); } + bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const { + return Vector.empty() && Set.empty(); + } + unsigned 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. + unsigned 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 2cfb5b9..e569f54 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 505aa8d..0a4140e 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 @@ -244,7 +233,6 @@ public: goto Retry; } -#if LLVM_HAS_RVALUE_REFERENCES void push_back(T &&Elt) { if (this->EndX < this->CapacityX) { Retry: @@ -255,8 +243,7 @@ public: this->grow(); goto Retry; } -#endif - + void pop_back() { this->setEnd(this->end()-1); this->end()->~T(); @@ -428,11 +415,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 +484,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)); @@ -532,7 +514,6 @@ public: I = this->begin()+EltNo; goto Retry; } -#endif iterator insert(iterator I, const T &Elt) { if (I == this->end()) { // Important special case for empty vector. @@ -673,9 +654,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 +772,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. @@ -855,7 +833,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 +871,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 +887,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 +896,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 7a10f85..706f248 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -382,7 +382,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 7f2a6f7..797a898 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 @@ -245,16 +249,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"); @@ -354,9 +348,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]); diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index 267a340..b46ccc9 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -118,6 +118,10 @@ 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; DenseT Dense; @@ -198,9 +202,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 +228,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(); + unsigned count(const KeyT &Key) const { + return find(Key) == end() ? 0 : 1; } /// insert - Attempts to insert a new element. diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h index 56dbb5b..a0b3fe7 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. /// diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index 0838ebe..4e74cf6 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -26,19 +26,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; @@ -149,10 +136,8 @@ public: InitType InitVal) { unsigned KeyLength = static_cast<unsigned>(KeyEnd-KeyStart); - // 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,15 +146,12 @@ public: static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); // Default construct the value. - new (NewItem) StringMapEntry(KeyLength); + new (NewItem) StringMapEntry(KeyLength, InitVal); // Copy the string information. char *StrBuffer = const_cast<char*>(NewItem->getKeyData()); memcpy(StrBuffer, KeyStart, 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; } @@ -313,6 +295,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; } @@ -404,7 +387,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); } }; diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index ec0c284..0514d7b 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -10,7 +10,7 @@ #ifndef LLVM_ADT_STRINGREF_H #define LLVM_ADT_STRINGREF_H -#include "llvm/Support/type_traits.h" +#include "llvm/Support/Allocator.h" #include <algorithm> #include <cassert> #include <cstring> @@ -124,6 +124,13 @@ namespace llvm { return Data[Length-1]; } + // copy - Allocate copy in BumpPtrAllocator and return StringRef to it. + StringRef copy(BumpPtrAllocator &Allocator) { + char *S = Allocator.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 { @@ -333,7 +340,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 +351,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 +560,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/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index cc0e7b6..1df8d66 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,7 +68,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES TinyPtrVector(TinyPtrVector &&RHS) : Val(RHS.Val) { RHS.Val = (EltTy)0; } @@ -98,7 +95,6 @@ public: RHS.Val = (EltTy)0; return *this; } -#endif // implicit conversion operator to ArrayRef. operator ArrayRef<EltTy>() const { @@ -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 84e0b29..185003d 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -46,32 +46,36 @@ 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, // ARM: arm64 + 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 }; enum VendorType { UnknownVendor, @@ -120,10 +124,21 @@ public: GNUEABI, GNUEABIHF, GNUX32, + CODE16, EABI, - MachO, + EABIHF, Android, - ELF + + MSVC, + Itanium, + Cygnus, + }; + enum ObjectFormatType { + UnknownObjectFormat, + + COFF, + ELF, + MachO, }; private: @@ -141,13 +156,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); @@ -186,6 +204,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,9 +335,29 @@ public: return isMacOSX() || isiOS(); } + bool isWindowsMSVCEnvironment() const { + return getOS() == Triple::Win32 && + (getEnvironment() == Triple::UnknownEnvironment || + getEnvironment() == Triple::MSVC); + } + + bool isKnownWindowsMSVCEnvironment() const { + return getOS() == Triple::Win32 && getEnvironment() == Triple::MSVC; + } + + 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. @@ -341,18 +382,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 +415,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); diff --git a/include/llvm/ADT/iterator_range.h b/include/llvm/ADT/iterator_range.h new file mode 100644 index 0000000..4f2f321 --- /dev/null +++ b/include/llvm/ADT/iterator_range.h @@ -0,0 +1,45 @@ +//===- 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; } +}; +} + +#endif diff --git a/include/llvm/ADT/polymorphic_ptr.h b/include/llvm/ADT/polymorphic_ptr.h deleted file mode 100644 index b8d8d71..0000000 --- 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 efafbbd..a06a562 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(0), TLI(0), AA(0) {} 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. diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index da00707..72e75ec 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 { @@ -282,8 +282,8 @@ 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 &operator=(Value *V); diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h index 817a441..5488847 100644 --- a/include/llvm/Analysis/BlockFrequencyImpl.h +++ b/include/llvm/Analysis/BlockFrequencyImpl.h @@ -48,7 +48,7 @@ class BlockFrequencyImpl { typedef GraphTraits< Inverse<BlockT *> > GT; - const uint32_t EntryFreq; + static const uint64_t EntryFreq = 1 << 14; std::string getBlockName(BasicBlock *BB) const { return BB->getName().str(); @@ -67,7 +67,8 @@ class BlockFrequencyImpl { void setBlockFreq(BlockT *BB, BlockFrequency Freq) { Freqs[BB] = Freq; - DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = " << Freq << "\n"); + DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = "; + printBlockFreq(dbgs(), Freq) << "\n"); } /// getEdgeFreq - Return edge frequency based on SRC frequency and Src -> Dst @@ -81,8 +82,9 @@ class BlockFrequencyImpl { /// void incBlockFreq(BlockT *BB, BlockFrequency Freq) { Freqs[BB] += Freq; - DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += " << Freq - << " --> " << Freqs[BB] << "\n"); + DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += "; + printBlockFreq(dbgs(), Freq) << " --> "; + printBlockFreq(dbgs(), Freqs[BB]) << "\n"); } // All blocks in postorder. @@ -157,7 +159,7 @@ class BlockFrequencyImpl { return; } - if(BlockT *Pred = getSingleBlockPred(BB)) { + if (BlockT *Pred = getSingleBlockPred(BB)) { if (BlocksInLoop.count(Pred)) setBlockFreq(BB, getEdgeFreq(Pred, BB)); // TODO: else? irreducible, ignore it for now. @@ -194,7 +196,8 @@ class BlockFrequencyImpl { 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"); + DEBUG(dbgs() << "Loop header scaled to "; + printBlockFreq(dbgs(), Freqs[BB]) << ".\n"); } /// doLoop - Propagate block frequency down through the loop. @@ -256,14 +259,15 @@ class BlockFrequencyImpl { BranchProbability LEP = BranchProbability(N, D); LoopExitProb.insert(std::make_pair(Head, LEP)); DEBUG(dbgs() << "LoopExitProb[" << getBlockName(Head) << "] = " << LEP - << " from 1 - " << BackFreq << " / " << getBlockFreq(Head) - << ".\n"); + << " from 1 - "; + printBlockFreq(dbgs(), BackFreq) << " / "; + printBlockFreq(dbgs(), getBlockFreq(Head)) << ".\n"); } friend class BlockFrequencyInfo; friend class MachineBlockFrequencyInfo; - BlockFrequencyImpl() : EntryFreq(BlockFrequency::getEntryFrequency()) { } + BlockFrequencyImpl() { } void doFunction(FunctionT *fn, BlockProbInfoT *bpi) { Fn = fn; @@ -312,6 +316,9 @@ class BlockFrequencyImpl { } public: + + uint64_t getEntryFreq() { return EntryFreq; } + /// 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 @@ -325,14 +332,15 @@ public: 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"; + OS << " " << getBlockName(BB) << " = "; + printBlockFreq(OS, 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"; + << " = "; printBlockFreq(OS, getEdgeFreq(BB, Succ)) << "\n"; } } } @@ -340,6 +348,30 @@ public: void dump() const { print(dbgs()); } + + // Utility method that looks up the block frequency associated with BB and + // prints it to OS. + raw_ostream &printBlockFreq(raw_ostream &OS, + const BlockT *BB) { + return printBlockFreq(OS, getBlockFreq(BB)); + } + + raw_ostream &printBlockFreq(raw_ostream &OS, + const BlockFrequency &Freq) const { + // Convert fixed-point number to decimal. + uint64_t Frequency = Freq.getFrequency(); + OS << Frequency / EntryFreq << "."; + uint64_t Rem = Frequency % EntryFreq; + uint64_t Eps = 1; + do { + Rem *= 10; + Eps *= 10; + OS << Rem / EntryFreq; + Rem = Rem % EntryFreq; + } while (Rem >= Eps/2); + return OS; + } + }; } diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h index a123d0b..2f701d9 100644 --- a/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/include/llvm/Analysis/BlockFrequencyInfo.h @@ -27,8 +27,9 @@ class BlockFrequencyImpl; /// BlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate /// IR basic block frequencies. class BlockFrequencyInfo : public FunctionPass { - - BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> *BFI; + typedef BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> + ImplType; + std::unique_ptr<ImplType> BFI; public: static char ID; @@ -37,10 +38,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 +52,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/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 4ff7121..4a6a280 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 = 0) 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 e5683c8..02e3b45 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 { diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h index 39e90eb..e6d2ed1 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/CallGraph.h b/include/llvm/Analysis/CallGraph.h index d00c2ed..9a6a4a7 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 e609dac..667e171 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 8edabfe..eccf1f8 100644 --- a/include/llvm/Analysis/CaptureTracking.h +++ b/include/llvm/Analysis/CaptureTracking.h @@ -45,12 +45,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 086934d..04b39c1 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/ConstantsScanner.h b/include/llvm/Analysis/ConstantsScanner.h index cdaf68d..d3d0a44 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 0fc1c2d..ff3392a 100644 --- a/include/llvm/Analysis/DOTGraphTraitsPass.h +++ b/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -19,50 +19,62 @@ 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 +82,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 +144,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 ea8cecf..a142828 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -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; @@ -918,10 +918,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 * = 0) 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 a2e0675..4dcea2d 100644 --- a/include/llvm/Analysis/DominanceFrontier.h +++ b/include/llvm/Analysis/DominanceFrontier.h @@ -18,7 +18,7 @@ #ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_H #define LLVM_ANALYSIS_DOMINANCEFRONTIER_H -#include "llvm/Analysis/Dominators.h" +#include "llvm/IR/Dominators.h" #include <map> #include <set> @@ -51,7 +51,7 @@ public: /// bool isPostDominator() const { return IsPostDominators; } - virtual void releaseMemory() { Frontiers.clear(); } + void releaseMemory() override { Frontiers.clear(); } // Accessor interface: typedef DomSetMapType::iterator iterator; @@ -142,7 +142,7 @@ public: /// print - Convert to human readable form /// - virtual void print(raw_ostream &OS, const Module* = 0) const; + void print(raw_ostream &OS, const Module* = 0) const override; /// dump - Dump the dominance frontier to dbgs(). void dump() const; @@ -167,18 +167,18 @@ public: return Roots[0]; } - virtual bool runOnFunction(Function &) { + bool runOnFunction(Function &) override { Frontiers.clear(); - DominatorTree &DT = getAnalysis<DominatorTree>(); + DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); Roots = DT.getRoots(); assert(Roots.size() == 1 && "Only one entry block for forward domfronts!"); calculate(DT, DT[Roots[0]]); return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); - AU.addRequired<DominatorTree>(); + AU.addRequired<DominatorTreeWrapperPass>(); } const DomSetType &calculate(const DominatorTree &DT, diff --git a/include/llvm/Analysis/FindUsedTypes.h b/include/llvm/Analysis/FindUsedTypes.h index b22cb88..574c947 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 c982801..c6bb494 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* = 0) 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 383f697..aaed716 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/Interval.h b/include/llvm/Analysis/Interval.h index 5ce1260..01eba3f 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 22067c4..73aff76 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 8cade58..05248bd 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 { @@ -53,7 +53,7 @@ public: } // 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* = 0) const override; // getRootInterval() - Return the root interval that contains the starting // block of the function. @@ -81,7 +81,7 @@ public: } // 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/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h new file mode 100644 index 0000000..74b0c8e --- /dev/null +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -0,0 +1,337 @@ +//===- 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/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.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; + 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 std::iterator<std::bidirectional_iterator_tag, Node *, + ptrdiff_t, Node *, Node *> { + friend class LazyCallGraph; + friend class LazyCallGraph::Node; + typedef std::iterator<std::bidirectional_iterator_tag, Node *, ptrdiff_t, + Node *, Node *> BaseT; + + /// \brief Nonce type to select the constructor for the end iterator. + struct IsAtEndT {}; + + LazyCallGraph &G; + NodeVectorImplT::iterator NI; + + // Build the begin iterator for a node. + explicit iterator(LazyCallGraph &G, NodeVectorImplT &Nodes) + : G(G), NI(Nodes.begin()) {} + + // Build the end iterator for a node. This is selected purely by overload. + iterator(LazyCallGraph &G, NodeVectorImplT &Nodes, IsAtEndT /*Nonce*/) + : G(G), NI(Nodes.end()) {} + + public: + iterator(const iterator &Arg) : G(Arg.G), NI(Arg.NI) {} + iterator(iterator &&Arg) : G(Arg.G), NI(std::move(Arg.NI)) {} + iterator &operator=(iterator Arg) { + std::swap(Arg, *this); + return *this; + } + + bool operator==(const iterator &Arg) { return NI == Arg.NI; } + bool operator!=(const iterator &Arg) { return !operator==(Arg); } + + reference operator*() const { + if (NI->is<Node *>()) + return NI->get<Node *>(); + + Function *F = NI->get<Function *>(); + Node *ChildN = G.get(*F); + *NI = ChildN; + return ChildN; + } + pointer operator->() const { return operator*(); } + + iterator &operator++() { + ++NI; + return *this; + } + iterator operator++(int) { + iterator prev = *this; + ++*this; + return prev; + } + + iterator &operator--() { + --NI; + return *this; + } + iterator operator--(int) { + iterator next = *this; + --*this; + return next; + } + }; + + /// \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); + + /// \brief Copy constructor. + /// + /// This does a deep copy of the graph. It does no verification that the + /// graph remains valid for the module. It is also relatively expensive. + LazyCallGraph(const LazyCallGraph &G); + + /// \brief Move constructor. + /// + /// This is a deep move. It leaves G in an undefined but destroyable state. + /// Any other operation on G is likely to fail. + LazyCallGraph(LazyCallGraph &&G); + + /// \brief Copy and move assignment. + LazyCallGraph &operator=(LazyCallGraph RHS) { + std::swap(*this, RHS); + return *this; + } + + iterator begin() { return iterator(*this, EntryNodes); } + iterator end() { return iterator(*this, EntryNodes, iterator::IsAtEndT()); } + + /// \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 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); + } + +private: + Module &M; + + /// \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 Set of the entry nodes to the graph. + SmallPtrSet<Function *, 4> EntryNodeSet; + + /// \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 copy a node from another graph into this one. + Node *copyInto(const Node &OtherN); + + /// \brief Helper to move a node from another graph into this one. + Node *moveInto(Node &&OtherN); +}; + +/// \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 LazyCallGraph::Node { + friend class LazyCallGraph; + + LazyCallGraph &G; + Function &F; + mutable NodeVectorT Callees; + SmallPtrSet<Function *, 4> CalleeSet; + + /// \brief Basic constructor implements the scanning of F into Callees and + /// CalleeSet. + Node(LazyCallGraph &G, Function &F); + + /// \brief Constructor used when copying a node from one graph to another. + Node(LazyCallGraph &G, const Node &OtherN); + + /// \brief Constructor used when moving a node from one graph to another. + Node(LazyCallGraph &G, Node &&OtherN); + +public: + typedef LazyCallGraph::iterator iterator; + + Function &getFunction() const { + return F; + }; + + iterator begin() const { return iterator(G, Callees); } + iterator end() const { return iterator(G, Callees, iterator::IsAtEndT()); } + + /// Equality is defined as address equality. + bool operator==(const Node &N) const { return this == &N; } + bool operator!=(const Node &N) const { return !operator==(N); } +}; + +// 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 197e94e..a4cb806 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -26,7 +26,7 @@ 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; @@ -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 c01b210..481015e 100644 --- a/include/llvm/Analysis/LibCallAliasAnalysis.h +++ b/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -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 f5a9e96..0f0bc23 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, diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 62f5aca..aeeea3c 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; @@ -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 // @@ -639,15 +654,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 = 0) 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 c98cb58..dd2dc28 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 { @@ -322,7 +324,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 5926610..726e286 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 91224ad..ff4bc22 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); @@ -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 47afd1b..123d435 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; @@ -323,24 +322,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 @@ -415,7 +415,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 d7a3dd8..6d70edd 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,7 @@ 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(0) { // 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 a5d098e..9494b7d 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(); diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index 88ebab4..d330755 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 1802fe8..572d5d7 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 { @@ -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 e873195..4d55408 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -28,6 +28,7 @@ #define LLVM_ANALYSIS_REGIONINFO_H #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Analysis/DominanceFrontier.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Support/Allocator.h" @@ -312,11 +313,11 @@ public: /// The toplevel region represents the whole function. bool isTopLevelRegion() const { return exit == NULL; } - /// @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; @@ -495,13 +496,11 @@ 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 BasicBlock, + BasicBlock>::type *> { + typedef df_iterator<typename std::conditional<IsConst, const BasicBlock, + BasicBlock>::type *> super; + public: typedef block_iterator_wrapper<IsConst> Self; typedef typename super::pointer pointer; @@ -545,6 +544,21 @@ public: 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()); + } //@} /// @name Element Iterators @@ -632,7 +646,7 @@ class RegionInfo : public FunctionPass { // Calculate - detecte all regions in function and build the region tree. void Calculate(Function& F); - void releaseMemory(); + void releaseMemory() override; // updateStatistics - Update statistic about created regions. void updateStatistics(Region *R); @@ -649,10 +663,10 @@ public: /// @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; + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void print(raw_ostream &OS, const Module *) const override; + void verifyAnalysis() const override; //@} /// @brief Get the smallest region that contains a BasicBlock. diff --git a/include/llvm/Analysis/RegionIterator.h b/include/llvm/Analysis/RegionIterator.h index 8fd4263..ab4d0e0 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 { diff --git a/include/llvm/Analysis/RegionPass.h b/include/llvm/Analysis/RegionPass.h index 3907ad9..bd51c49 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 d7f6178..06489d8 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,8 +207,8 @@ 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); }; @@ -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. @@ -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, @@ -784,6 +803,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 +894,11 @@ 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; + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void print(raw_ostream &OS, const Module* = 0) const override; + void verifyAnalysis() const override; private: /// Compute the backedge taken count knowing the interval difference, the @@ -880,13 +906,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 4433be0..9162735 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 { @@ -94,7 +94,7 @@ namespace llvm { explicit SCEVExpander(ScalarEvolution &se, const char *name) : SE(se), IVName(name), IVIncInsertLoop(0), IVIncInsertPos(0), CanonicalMode(true), LSRMode(false), - Builder(se.getContext(), TargetFolder(se.TD)) { + Builder(se.getContext(), TargetFolder(se.DL)) { #ifndef NDEBUG DebugType = ""; #endif @@ -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 9cd902a..ed8c133 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -410,8 +410,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 +563,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 +633,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 +649,7 @@ namespace llvm { private: ScalarEvolution &SE; ValueToValueMap ⤅ + bool InterpretConsts; }; typedef DenseMap<const Loop*, const SCEV*> LoopToScevMapT; diff --git a/include/llvm/Support/TargetFolder.h b/include/llvm/Analysis/TargetFolder.h index 5c1978d..8a7fc7c 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 diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index 4f47562..2ac6ffa 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; @@ -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 @@ -316,9 +328,10 @@ public: /// \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. diff --git a/include/llvm/Analysis/Verifier.h b/include/llvm/Analysis/Verifier.h deleted file mode 100644 index ce8aeef..0000000 --- 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 b971c53..165c46d 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 02b9bd9..0000000 --- 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 6b89ae0..0000000 --- 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 0000000..898cd52 --- /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 dc5e095..fcbf426 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; diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index f40a0d1..ef88a88 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. diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index b3d2466..7e6831b 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -370,7 +370,8 @@ 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 }; } // End bitc namespace diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 78f40ca..0918e92 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. @@ -52,21 +50,16 @@ namespace llvm { LLVMContext &Context, std::string *ErrMsg = 0); - /// 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 32ffca7..0f5c63d 100644 --- a/include/llvm/CMakeLists.txt +++ b/include/llvm/CMakeLists.txt @@ -2,12 +2,13 @@ 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() diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index b2cc704..5f2bbd6 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -17,19 +17,18 @@ #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 SDNode; class SDValue; class SelectionDAG; +class TargetLowering; +struct EVT; /// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence /// of insertvalue or extractvalue indices that identify a member, return diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 4bda0f1..d96d810 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -16,13 +16,16 @@ #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 AsmPrinterHandler; class BlockAddress; + class ByteStreamer; class GCStrategy; class Constant; class ConstantArray; @@ -41,9 +44,11 @@ namespace llvm { class MCAsmInfo; class MCCFIInstruction; class MCContext; + class MCInst; class MCInstrInfo; class MCSection; class MCStreamer; + class MCSubtargetInfo; class MCSymbol; class MDNode; class DwarfDebug; @@ -110,20 +115,28 @@ namespace llvm { /// 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) {} + }; + /// Handlers - a vector of all debug/EH info emitters we should use. + /// This vector maintains ownership of the emitters. + SmallVector<HandlerInfo, 1> Handlers; + /// 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; } + DwarfDebug *getDwarfDebug() { return DD; } /// isVerbose - Return true if assembly output should contain comments. /// @@ -139,12 +152,20 @@ namespace llvm { /// getDataLayout - Return information about data layout. const DataLayout &getDataLayout() const; + /// getSubtargetInfo - Return information about subtarget. + const MCSubtargetInfo &getSubtargetInfo() const; + + void EmitToStreamer(MCStreamer &S, const MCInst &Inst); + /// getTargetTriple - Return the target triple string. StringRef getTargetTriple() const; /// getCurrentSection() - 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; //===------------------------------------------------------------------===// @@ -153,20 +174,20 @@ namespace llvm { /// getAnalysisUsage - Record analysis usage. /// - void getAnalysisUsage(AnalysisUsage &AU) const; + void getAnalysisUsage(AnalysisUsage &AU) const override; /// 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); + bool doInitialization(Module &M) override; /// doFinalization - Shut down the asmprinter. If you override this in your /// pass, you must make sure to call it explicitly. - bool doFinalization(Module &M); + bool doFinalization(Module &M) override; /// runOnMachineFunction - Emit the specified function out to the /// OutStreamer. - virtual bool runOnMachineFunction(MachineFunction &MF) { + bool runOnMachineFunction(MachineFunction &MF) override { SetupMachineFunction(MF); EmitFunctionHeader(); EmitFunctionBody(); @@ -189,7 +210,7 @@ namespace llvm { /// function. void EmitFunctionBody(); - void emitPrologLabel(const MachineInstr &MI); + void emitCFIInstruction(const MachineInstr &MI); enum CFIMoveType { CFI_M_None, @@ -200,11 +221,6 @@ namespace llvm { bool needsSEHMoves(); - /// 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; - /// 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 @@ -270,6 +286,9 @@ namespace llvm { llvm_unreachable("EmitInstruction not implemented"); } + /// GetCPISymbol - Return the symbol for the specified constant pool entry. + virtual MCSymbol *GetCPISymbol(unsigned CPID) const; + virtual void EmitFunctionEntryLabel(); virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); @@ -298,27 +317,21 @@ namespace llvm { /// GetTempSymbol - Return the MCSymbol corresponding to the assembler /// temporary label with the specified stem and unique ID. - MCSymbol *GetTempSymbol(StringRef Name, unsigned ID) const; + MCSymbol *GetTempSymbol(Twine Name, unsigned ID) const; /// GetTempSymbol - Return an assembler temporary label with the specified /// stem. - MCSymbol *GetTempSymbol(StringRef Name) const; - + MCSymbol *GetTempSymbol(Twine 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; + /// 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; /// 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; @@ -418,7 +431,7 @@ namespace llvm { virtual unsigned getISAEncoding() { return 0; } /// EmitDwarfRegOp - Emit dwarf register operation. - virtual void EmitDwarfRegOp(const MachineLocation &MLoc, + virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc, bool Indirect) const; //===------------------------------------------------------------------===// @@ -460,6 +473,15 @@ namespace llvm { 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. diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index a18f433..50bbb0d 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. }; @@ -347,6 +348,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 uint16_t *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,6 +404,11 @@ public: ByValRegs.clear(); } + // Rewind byval registers tracking info. + void rewindByValRegsInfo() { + InRegsParamsProceed = 0; + } + ParmContext getCallOrPrologue() const { return CallOrPrologue; } private: diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index bc8dce3..02a4bb5 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -19,6 +19,7 @@ #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; @@ -85,9 +86,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")); @@ -210,4 +208,30 @@ cl::opt<std::string> StartAfter("start-after", cl::value_desc("pass-name"), cl::init("")); +// Common utility function tightly tied to the options listed here. Initializes +// a TargetOptions object with CodeGen flags and returns it. +static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { + 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.EnableSegmentedStacks = SegmentedStacks; + Options.UseInitArray = UseInitArray; + return Options; +} + #endif diff --git a/include/llvm/CodeGen/EdgeBundles.h b/include/llvm/CodeGen/EdgeBundles.h index e8a4a2d..2899fe1 100644 --- a/include/llvm/CodeGen/EdgeBundles.h +++ b/include/llvm/CodeGen/EdgeBundles.h @@ -55,8 +55,8 @@ 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. diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 1e0ef6b..aeffbd4 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -17,22 +17,22 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/ValueTypes.h" namespace llvm { class AllocaInst; class Constant; class ConstantFP; +class DataLayout; class FunctionLoweringInfo; class Instruction; class LoadInst; +class MVT; class MachineConstantPool; +class MachineFrameInfo; class MachineFunction; class MachineInstr; -class MachineFrameInfo; class MachineRegisterInfo; -class DataLayout; class TargetInstrInfo; class TargetLibraryInfo; class TargetLowering; @@ -51,9 +51,9 @@ protected: 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 +87,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. diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 50d320f..06e7aaa 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 diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index 1070d29..ea94542 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -35,8 +35,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/Pass.h" -#include "llvm/Support/DebugLoc.h" namespace llvm { class AsmPrinter; diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index 456d2dc..bb170c8 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 48a0523..89b0908 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -603,7 +603,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, @@ -702,6 +702,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 68389dd..9e6ab7d 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 9a73214..bb0df2e 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,12 +248,12 @@ 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; @@ -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,38 +298,39 @@ 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. diff --git a/include/llvm/CodeGen/LatencyPriorityQueue.h b/include/llvm/CodeGen/LatencyPriorityQueue.h index d454347..d566da8 100644 --- a/include/llvm/CodeGen/LatencyPriorityQueue.h +++ b/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -47,21 +47,21 @@ 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() { + void releaseState() override { SUnits = 0; } @@ -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 26563a6..e0593f8 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -21,9 +21,9 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.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> namespace llvm { @@ -44,32 +44,35 @@ typedef std::pair<const MachineInstr *, const MachineInstr *> InsnRange; /// class LexicalScopes { public: - LexicalScopes() : MF(NULL), CurrentFnLexicalScope(NULL) { } - virtual ~LexicalScopes(); + LexicalScopes() : MF(NULL), CurrentFnLexicalScope(NULL) {} + ~LexicalScopes(); - /// 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; } - /// 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. @@ -104,7 +107,6 @@ public: void dump(); private: - /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If /// not available then create new lexical scope. LexicalScope *getOrCreateLexicalScope(DebugLoc DL); @@ -123,8 +125,9 @@ private: 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; @@ -133,10 +136,11 @@ private: /// contained LexicalScope*s. DenseMap<const MDNode *, LexicalScope *> LexicalScopeMap; - /// InlinedLexicalScopeMap - Tracks inlined function scopes in current function. + /// InlinedLexicalScopeMap - Tracks inlined function scopes in current + /// function. DenseMap<DebugLoc, LexicalScope *> InlinedLexicalScopeMap; - /// AbstractScopeMap - These scopes are not included LexicalScopeMap. + /// AbstractScopeMap - These scopes are not included LexicalScopeMap. /// AbstractScopes owns its LexicalScope*s. DenseMap<const MDNode *, LexicalScope *> AbstractScopeMap; @@ -153,26 +157,23 @@ private: /// 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) { + : 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; } + 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; } + SmallVectorImpl<InsnRange> &getRanges() { return Ranges; } /// addChild - Add a child scope. void addChild(LexicalScope *S) { Children.push_back(S); } @@ -189,7 +190,7 @@ public: /// extendInsnRange - Extend the current instruction range covered by /// this scope. void extendInsnRange(const MachineInstr *MI) { - assert (FirstInsn && "MI Range is not open!"); + assert(FirstInsn && "MI Range is not open!"); LastInsn = MI; if (Parent) Parent->extendInsnRange(MI); @@ -199,7 +200,7 @@ public: /// 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!"); + assert(LastInsn && "Last insn missing!"); Ranges.push_back(InsnRange(FirstInsn, LastInsn)); FirstInsn = NULL; LastInsn = NULL; @@ -219,28 +220,28 @@ public: } // 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; } + 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. + 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. + 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 diff --git a/include/llvm/CodeGen/LinkAllAsmWriterComponents.h b/include/llvm/CodeGen/LinkAllAsmWriterComponents.h index 722b0de..c3046da 100644 --- a/include/llvm/CodeGen/LinkAllAsmWriterComponents.h +++ b/include/llvm/CodeGen/LinkAllAsmWriterComponents.h @@ -18,7 +18,6 @@ #include "llvm/CodeGen/GCs.h" #include <cstdlib> -#ifndef ANDROID_TARGET_BUILD namespace { struct ForceAsmWriterLinking { ForceAsmWriterLinking() { @@ -35,6 +34,5 @@ namespace { } } ForceAsmWriterLinking; // Force link by creating a global definition. } -#endif #endif // LLVM_CODEGEN_LINKALLASMWRITERCOMPONENTS_H diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 3a9fef6..41d126a 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -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; @@ -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; diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index d8437f0..5492593 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)) @@ -252,14 +255,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* = 0) 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/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h new file mode 100644 index 0000000..c93eaf5 --- /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(0), 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 7edf67c..4ce39e3 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. diff --git a/include/llvm/CodeGen/LiveRegMatrix.h b/include/llvm/CodeGen/LiveRegMatrix.h index 7a3e9e8..28b819b 100644 --- a/include/llvm/CodeGen/LiveRegMatrix.h +++ b/include/llvm/CodeGen/LiveRegMatrix.h @@ -59,9 +59,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 02b9c55..0000000 --- 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 92c35f7..ac32a9c 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* = 0) const override; }; } diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index dc735f7..a4a5fcc 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 7717809..5e86e75 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -363,6 +363,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 +503,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 +542,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), @@ -608,6 +611,9 @@ public: void dump() const; void print(raw_ostream &OS, SlotIndexes* = 0) const; + // Printing method used by LoopInfo. + void printAsOperand(raw_ostream &OS, bool PrintType = true); + /// getNumber - MachineBasicBlocks are uniquely numbered at the function /// level, unless they're not in a MachineFunction yet, in which case this /// will return -1. @@ -655,8 +661,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 +750,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 a9c7bf7..f3ef87c 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 // @@ -28,9 +28,9 @@ class BlockFrequencyImpl; /// MachineBlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate /// machine basic block frequencies. class MachineBlockFrequencyInfo : public MachineFunctionPass { - - BlockFrequencyImpl<MachineBasicBlock, MachineFunction, - MachineBranchProbabilityInfo> *MBFI; + typedef BlockFrequencyImpl<MachineBasicBlock, MachineFunction, + MachineBranchProbabilityInfo> ImplType; + std::unique_ptr<ImplType> MBFI; public: static char ID; @@ -39,9 +39,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 +51,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 c59948f..7ba7495 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 9e41e6e..f729ced 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 { diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index e41d206..f1ae0bf 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 022634d..1dedd74 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 @@ -501,7 +519,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 = 0); /// CreateSpillStackObject - Create a new statically sized stack object that /// represents a spill slot, returning a nonnegative identifier to represent @@ -521,7 +539,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 c886e25..652d63d 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,15 +218,14 @@ 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 @@ -427,6 +426,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 112f07e..36f1c66 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 04881e5..50a1f6e 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 cccab81..f5dc75e 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -22,13 +22,13 @@ #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/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 { @@ -287,11 +287,25 @@ public: const_mop_iterator operands_begin() const { return Operands; } const_mop_iterator operands_end() const { return Operands + NumOperands; } + inline iterator_range<mop_iterator> operands() { + return iterator_range<mop_iterator>(operands_begin(), operands_end()); + } + inline iterator_range<const_mop_iterator> operands() const { + return iterator_range<const_mop_iterator>(operands_begin(), 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; } + inline iterator_range<mmo_iterator> memoperands() { + return iterator_range<mmo_iterator>(memoperands_begin(), memoperands_end()); + } + inline 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 +637,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. @@ -701,7 +715,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: @@ -830,6 +844,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. @@ -1038,6 +1083,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 diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index df01371..d7eb706 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -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/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index b058ecb..4fbd46b 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 00a55b5..f01b8eb 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -134,6 +134,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; } diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 460c08c..28f4544 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 { @@ -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. /// @@ -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 @@ -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 40f3580..57bdb4c 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -43,21 +43,23 @@ 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) + 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: @@ -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. @@ -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; @@ -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: diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h index 90ee7f4..cd212ab 100644 --- a/include/llvm/CodeGen/MachinePassRegistry.h +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -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 ca09aef..a6f9f3d 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 = 0) const override; }; } //end of namespace llvm diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 58ca907..2285130 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" @@ -200,32 +201,118 @@ 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); } + 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(0); } + + 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(0); } + + 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). bool reg_empty(unsigned RegNo) const { return reg_begin(RegNo) == reg_end(); } /// 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); } + 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(0); + } + + 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(0); + } + + 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. bool reg_nodbg_empty(unsigned RegNo) const { @@ -233,12 +320,46 @@ 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); } + 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(0); } + + 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(0); } + + 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). bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); } @@ -253,12 +374,46 @@ 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); } + 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(0); } + + 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(0); } + + 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. bool use_empty(unsigned RegNo) const { return use_begin(RegNo) == use_end(); } @@ -274,12 +429,55 @@ 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); } + 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(0); + } + + 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(0); + } + + 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. bool use_nodbg_empty(unsigned RegNo) const { @@ -401,6 +599,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 +754,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 +766,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 = 0; + 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; @@ -589,6 +812,70 @@ public: // 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. @@ -605,52 +892,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(0) {} + + 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 == 0; } - 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(); } }; diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h index edf93d1..8fc367e 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 @@ -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 7782895..c54300c 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 @@ -93,6 +93,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 +155,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 +205,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,19 +214,15 @@ 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; - /// Topo - A topological ordering for SUnits which permits fast IsReachable /// and similar queries. ScheduleDAGTopologicalSort Topo; @@ -290,32 +230,11 @@ protected: /// 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; - /// 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,15 +245,12 @@ 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, MachineSchedStrategy *S, bool IsPostRA): + ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, IsPostRA, + /*RemoveKillFlags=*/IsPostRA, C->LIS), + AA(C->AA), SchedImpl(S), Topo(SUnits, &ExitSU), CurrentTop(), + CurrentBottom(), NextClusterPred(NULL), NextClusterSucc(NULL) { #ifndef NDEBUG NumInstrsScheduled = 0; #endif @@ -342,8 +258,8 @@ public: virtual ~ScheduleDAGMI(); - /// \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 @@ -374,16 +290,105 @@ 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, MachineSchedStrategy *S): + ScheduleDAGMI(C, S, /*IsPostRA=*/false), RegClassInfo(C->RegClassInfo), + DFSResult(0), 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 +408,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 +417,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 +441,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 +452,286 @@ 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; + } + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + void dump(); +#endif +}; + +/// 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 operand latency as an upper bound on the number of + // times we should retry the pending queue because of a hazard. + unsigned MaxObservedLatency; +#endif + +public: + /// Pending queues extend the ready queues with the same ID and the + /// PendingFlag set. + SchedBoundary(unsigned ID, const Twine &Name): + DAG(0), SchedModel(0), Rem(0), Available(ID, Name+".A"), + Pending(ID << LogMaxQID, Name+".P"), + HazardRec(0) { + 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 }; } // namespace llvm diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h index 9794707..dc0bc1d 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; diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h new file mode 100644 index 0000000..84053ca --- /dev/null +++ b/include/llvm/CodeGen/MachineValueType.h @@ -0,0 +1,578 @@ +//===- 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" + +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 0000000..1646334 --- /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 != 0 && "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 aca0a91..07c3337 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-existant) node. + static NodeId invalidNodeId() { + return std::numeric_limits<NodeId>::max(); + } - typedef std::set<NodeId> AdjEdgeList; + /// \brief Returns a value representing an invalid (non-existant) 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 == nullptr && "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 != nullptr && "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 8bcbb9e..0000000 --- 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 e26ca02..0000000 --- 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 c355c2c..0000000 --- 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 08f8b98..69a9d83 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 0000000..a55a060 --- /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 0000000..79ff6b4 --- /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(0) {} + ~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; + + 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 091805d..3556e60 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 ae4a2fa..5d68f86 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -207,9 +207,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: @@ -221,6 +221,13 @@ public: return 0; } + /// Similar to createMachineScheduler but used when postRA machine scheduling + /// is enabled. + virtual ScheduleDAGInstrs * + createPostMachineScheduler(MachineSchedContext *C) const { + return 0; + } + protected: // Helper to verify the analysis is really immutable. void setOpt(bool &Opt, bool Val); @@ -363,6 +370,10 @@ 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 = 0); + /// MachineLoopInfo - This pass is a loop analysis pass. extern char &MachineLoopInfoID; @@ -403,6 +414,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; @@ -568,6 +582,11 @@ 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; + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h index 705086c..0af8915 100644 --- a/include/llvm/CodeGen/PseudoSourceValue.h +++ b/include/llvm/CodeGen/PseudoSourceValue.h @@ -29,7 +29,7 @@ namespace llvm { /// printCustom - Implement printing for PseudoSourceValue. This is called /// from Value::print or Value's operator<<. /// - virtual void printCustom(raw_ostream &O) const; + void printCustom(raw_ostream &O) const override; public: explicit PseudoSourceValue(enum ValueTy Subclass = PseudoSourceValueVal); @@ -93,13 +93,13 @@ namespace llvm { return V->getValueID() == FixedStackPseudoSourceValueVal; } - 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 7472e5a..efd7c61 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 = 0); } #endif /* LLVM_CODEGEN_REGALLOCPBQP_H */ diff --git a/include/llvm/CodeGen/ResourcePriorityQueue.h b/include/llvm/CodeGen/ResourcePriorityQueue.h index f20a9fc..7ae9111 100644 --- a/include/llvm/CodeGen/ResourcePriorityQueue.h +++ b/include/llvm/CodeGen/ResourcePriorityQueue.h @@ -81,17 +81,17 @@ 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() { + void releaseState() override { SUnits = 0; } @@ -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/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index ccba1b0..4886e5c 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -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: @@ -316,7 +324,8 @@ namespace llvm { 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), + isScheduleLow(false), isCloned(false), isUnbuffered(false), + hasReservedResource(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -330,7 +339,8 @@ namespace llvm { 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), + isScheduleLow(false), isCloned(false), isUnbuffered(false), + hasReservedResource(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -343,7 +353,8 @@ namespace llvm { 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), + isScheduleLow(false), isCloned(false), isUnbuffered(false), + hasReservedResource(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index fe4f3c2..72bbe8b 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, + bool RemoveKillFlags = false, LiveIntervals *LIS = 0); virtual ~ScheduleDAGInstrs() {} + bool isPostRA() const { return IsPostRA; } + /// \brief Expose LiveIntervals for use in DAG mutators and such. LiveIntervals *getLIS() const { return LIS; } @@ -219,20 +229,31 @@ 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. diff --git a/include/llvm/CodeGen/ScheduleHazardRecognizer.h b/include/llvm/CodeGen/ScheduleHazardRecognizer.h index 9dfa344..8a40e72 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 c2103fb..fbbbb0c 100644 --- a/include/llvm/CodeGen/ScoreboardHazardRecognizer.h +++ b/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -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 82becca..a30656a 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>; @@ -169,7 +168,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 +267,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 +278,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'. @@ -401,18 +397,22 @@ public: //===--------------------------------------------------------------------===// // 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. @@ -692,12 +692,14 @@ public: SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo, unsigned Alignment, - AtomicOrdering Ordering, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Cmp, SDValue Swp, MachineMemOperand *MMO, - AtomicOrdering Ordering, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); /// getAtomic - Gets a node for an atomic op, produces result (if relevant) @@ -726,9 +728,13 @@ 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, + SDValue *Ops, unsigned NumOps, MachineMemOperand *MMO, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); + SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList, + SDValue *Ops, unsigned NumOps, 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, @@ -1143,7 +1149,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); } diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index b5ec8cb..b92b6ec 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, diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 70c15e6..fd915b0 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -29,9 +29,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> @@ -70,6 +70,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. @@ -116,7 +120,7 @@ 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); } SDValue getValue(unsigned R) const { @@ -141,6 +145,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; @@ -404,7 +412,7 @@ public: /// 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 @@ -1085,15 +1093,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 +1127,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 +1140,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 +1149,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, 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,6 +1167,16 @@ 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; @@ -1246,9 +1276,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 +1292,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 +1519,16 @@ 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; + + /// getConstantSplatValue - Check if this is a constant splat, and if so, + /// return the splat value only if it is a ConstantSDNode. Otherwise + /// return nullptr. This is a simpler form of isConstantSplat. + /// Get the constant splat only if you care about the splat value. + ConstantSDNode *getConstantSplatValue() const; + + bool isConstant() const; static inline bool classof(const SDNode *N) { return N->getOpcode() == ISD::BUILD_VECTOR; diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 984796a..1cc34d5 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -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; @@ -545,7 +545,7 @@ namespace llvm { std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), start); if (itr == idx2MBBMap.end()) { - itr = prior(itr); + itr = std::prev(itr); return itr->second; } @@ -553,7 +553,7 @@ namespace llvm { if (itr->first < end) return 0; - itr = prior(itr); + itr = std::prev(itr); if (itr->first <= start) return itr->second; @@ -581,11 +581,11 @@ namespace llvm { 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. @@ -638,7 +638,7 @@ 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; diff --git a/include/llvm/CodeGen/StackMapLivenessAnalysis.h b/include/llvm/CodeGen/StackMapLivenessAnalysis.h new file mode 100644 index 0000000..6ba7256 --- /dev/null +++ b/include/llvm/CodeGen/StackMapLivenessAnalysis.h @@ -0,0 +1,65 @@ +//===--- 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 stackmap or 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 stackmap or +/// patchpoint intrinsic if present. +/// +/// This is an optional pass that has to be explicitly enabled via the +/// -enable-stackmap-liveness and/or -enable-patchpoint-liveness flag. The pass +/// skips functions that don't have any stackmap or patchpoint intrinsics. The +/// information provided by this pass is optional and not required by the +/// aformentioned intrinsics 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 e90f22e..a62ab6e 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> @@ -92,19 +94,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) : AP(AP) {} /// \brief Generate a stackmap record for a stackmap instruction. /// @@ -121,15 +132,19 @@ public: private: typedef SmallVector<Location, 8> LocationVec; + typedef SmallVector<LiveOutReg, 8> LiveOutVec; + typedef MapVector<const MCSymbol *, uint64_t> FnStackSizeMap; struct CallsiteInfo { const MCExpr *CSOffsetExpr; - unsigned ID; + uint64_t ID; LocationVec Locations; + LiveOutVec LiveOuts; CallsiteInfo() : CSOffsetExpr(0), ID(0) {} - CallsiteInfo(const MCExpr *CSOffsetExpr, unsigned ID, - LocationVec Locations) - : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations) {} + CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID, + LocationVec &Locations, LiveOutVec &LiveOuts) + : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations), + LiveOuts(LiveOuts) {} }; typedef std::vector<CallsiteInfo> CallsiteInfoList; @@ -155,16 +170,29 @@ private: }; 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); diff --git a/include/llvm/CodeGen/StackProtector.h b/include/llvm/CodeGen/StackProtector.h index d09a933..0b8b8c0 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; @@ -114,13 +114,14 @@ public: 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 5b22c9c..16fed32 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -38,81 +38,81 @@ 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 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 = 65535) const override; + const MCSection * + getStaticDtorSection(unsigned Priority = 65535) 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 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 +121,25 @@ 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; }; } // end namespace llvm diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index 8ef26b7..4e178d0 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -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 79f3233..8cf26fa 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 @@ -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 3bc6ebd..89b5a9f 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 = 0) const override; void dump() const; }; diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 5c72ad8..ea1e75a 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -212,6 +212,9 @@ /* 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} @@ -495,6 +498,9 @@ /* Linker version detected at compile time. */ #undef HOST_LINK_VERSION +/* Define if we link Polly to the tools */ +#cmakedefine LINK_POLLY_INTO_TOOLS + /* Installation directory for binary executables */ #cmakedefine LLVM_BINDIR "${LLVM_BINDIR}" diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index dcec8f8..6b8dbb7 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -3,9 +3,6 @@ #ifndef CONFIG_H #define CONFIG_H -/* Define if building universal (internal helper macro) */ -#undef AC_APPLE_UNIVERSAL_BUILD - /* Bug report URL. */ #undef BUG_REPORT_URL @@ -36,27 +33,6 @@ /* 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 @@ -66,9 +42,6 @@ /* 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 @@ -78,6 +51,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 @@ -94,12 +71,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 @@ -112,15 +83,9 @@ /* 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 @@ -205,8 +170,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 @@ -254,9 +219,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 @@ -300,9 +262,6 @@ /* 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 @@ -312,9 +271,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 @@ -333,9 +289,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 @@ -363,9 +316,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 @@ -641,26 +591,16 @@ /* Minor version of the LLVM API */ #undef LLVM_VERSION_MINOR -/* 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 +/* Patch version of the LLVM API */ +#undef LLVM_VERSION_PATCH -/* 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 @@ -673,9 +613,6 @@ /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME -/* Define to the home page for this package. */ -#undef PACKAGE_URL - /* Define to the version of this package. */ #undef PACKAGE_VERSION @@ -700,24 +637,6 @@ /* Type of 1st arg on ELM Callback */ #undef WIN32_ELMCB_PCSTR -/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most - significant byte first (like Motorola and SPARC, unlike Intel). */ -#if defined AC_APPLE_UNIVERSAL_BUILD -# if defined __BIG_ENDIAN__ -# define WORDS_BIGENDIAN 1 -# endif -#else -# ifndef WORDS_BIGENDIAN -# undef WORDS_BIGENDIAN -# endif -#endif - -/* 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 80616ef..65116cb 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -121,7 +121,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/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index a1a4642..69a4f8d 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -105,8 +105,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/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 233084d..4dca870 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,6 +48,11 @@ 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. class ExecutionEngineState { @@ -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; @@ -125,7 +130,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); @@ -204,9 +209,36 @@ 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(object::ObjectFile *O) { + llvm_unreachable( + "ExecutionEngine subclass doesn't implement addObjectFile."); + } + + /// 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, @@ -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 NULL; } + /// 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 @@ -550,7 +600,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 diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index ed66102..8daf2bd 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 { diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h index af2a926..071a42b 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" @@ -49,7 +48,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 +56,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 +68,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 076f4b1..1a13647 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) {} @@ -45,9 +45,9 @@ public: // 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 +61,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 3ad2e50..70dd1cb 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 diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index b832438..8d7b81b 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -21,6 +21,10 @@ namespace llvm { +namespace object { + class ObjectFile; +} + class RuntimeDyldImpl; class ObjectImage; @@ -32,6 +36,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 +51,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(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 +84,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/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index fd6e41f..f68028b 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -48,19 +48,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 +72,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 = 0) override; /// \brief Invalidate instruction cache for code sections. /// diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index eb6ed46..7c1ebf6 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -59,7 +59,12 @@ public: /// 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 +91,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 37b47c3..a8d52f6 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 c23ba0f..9eccf40 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -71,6 +71,7 @@ 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 @@ -201,7 +202,7 @@ public: /// index `1'. class AttributeSet { public: - enum AttrIndex LLVM_ENUM_INT_TYPE(unsigned) { + enum AttrIndex : unsigned { ReturnIndex = 0U, FunctionIndex = ~0U }; @@ -402,10 +403,6 @@ public: 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(); diff --git a/include/llvm/AutoUpgrade.h b/include/llvm/IR/AutoUpgrade.h index c774782..076ed4a 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,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_AUTOUPGRADE_H -#define LLVM_AUTOUPGRADE_H +#ifndef LLVM_IR_AUTOUPGRADE_H +#define LLVM_IR_AUTOUPGRADE_H namespace llvm { class CallInst; diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 3bdc95d..1adc254 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -116,6 +116,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(); diff --git a/include/llvm/Support/CFG.h b/include/llvm/IR/CFG.h index 74ec726..c8be8bd 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 2d52a89..dd8e04f 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 2a1c5ca..ec46103 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" @@ -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 @@ -257,6 +265,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); } diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 4437af2..af44e8a 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, @@ -129,7 +137,13 @@ namespace CallingConv { /// convention differs from the more common \c X86_64_SysV convention /// in a number of ways, most notably in that XMM registers used to pass /// arguments are shadowed by GPRs, and vice versa. - X86_64_Win64 = 79 + X86_64_Win64 = 79, + + /// \brief The calling convention used for __cdecl methods on win32. + /// Differs from the C calling convention only in that the order of the + /// first parameter and the sret parameter are swapped. + X86_CDeclMethod = 80 + }; } // End CallingConv namespace diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index 26bad1d..f03e3dd 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) {} diff --git a/include/llvm/Support/ConstantFolder.h b/include/llvm/IR/ConstantFolder.h index 4aad952..86668f7 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" diff --git a/include/llvm/Support/ConstantRange.h b/include/llvm/IR/ConstantRange.h index f757c6e..86988de 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. diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index dac20c9..ed7a70f 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); @@ -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) { @@ -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. @@ -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) { @@ -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 bac1679..7d87a69 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,8 +72,9 @@ 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, @@ -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 @@ -110,7 +112,8 @@ namespace llvm { StringRef Dir, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, - StringRef SplitName = StringRef()); + StringRef SplitName = StringRef(), + DebugEmissionKind Kind = FullDebug); /// createFile - Create a file descriptor to hold debugging information /// for a file. @@ -415,10 +418,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); @@ -439,7 +445,7 @@ namespace llvm { /// 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 +466,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 +479,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,7 +497,7 @@ namespace llvm { DIGlobalVariable createStaticVariable(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, - DIType Ty, bool isLocalToUnit, llvm::Value *Val, + DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val, MDNode *Decl = NULL); @@ -506,13 +512,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 +537,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 +548,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. @@ -627,12 +633,14 @@ 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 @@ -655,7 +663,7 @@ namespace llvm { /// variable /// @param Line Line number DIImportedEntity createImportedDeclaration(DIScope Context, - DIDescriptor Decl, + DIScope Decl, unsigned Line); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 10630a2..59dca63 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -34,6 +34,7 @@ class Type; class IntegerType; class StructType; class StructLayout; +class Triple; class GlobalVariable; class LLVMContext; template<typename T> @@ -45,8 +46,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 +78,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 +143,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 +169,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(0) { + 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(0) { *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 +219,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 +234,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 +292,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 +383,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; @@ -408,6 +443,23 @@ public: assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!"); return (Val + (Alignment-1)) & ~UIntTy(Alignment-1); } +}; + +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 768cf4e..f7244b8 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: @@ -194,6 +197,13 @@ 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; @@ -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. @@ -282,6 +293,11 @@ protected: public: explicit DIType(const MDNode *N = 0) : 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,6 +329,12 @@ 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 @@ -377,7 +399,6 @@ public: 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); @@ -420,6 +441,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; @@ -470,6 +492,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. @@ -501,6 +536,7 @@ public: 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; }; @@ -533,6 +569,13 @@ public: bool Verify() const; }; +/// DIUnspecifiedParameter - This is a wrapper for unspecified parameters. +class DIUnspecifiedParameter : public DIDescriptor { +public: + explicit DIUnspecifiedParameter(const MDNode *N = 0) : DIDescriptor(N) {} + bool Verify() const; +}; + /// DITemplateTypeParameter - This is a wrapper for template type parameter. class DITemplateTypeParameter : public DIDescriptor { public: @@ -586,7 +629,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); } @@ -617,7 +660,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 { @@ -650,7 +693,9 @@ public: /// 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 +717,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 +772,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 +788,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 +861,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 +881,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,11 +914,11 @@ 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. diff --git a/include/llvm/Support/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 05f31d7..50b5d54 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,10 +12,10 @@ // //===----------------------------------------------------------------------===// -#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; @@ -89,6 +89,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); /// getAsMDNode - This method converts the compressed DebugLoc node into a /// DILocation compatible MDNode. diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index e279e60..71d9973 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -249,7 +249,7 @@ 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 = 0) const; /// hasName - Return true if this is a named struct that has a non-empty name. bool hasName() const { return SymbolTableEntry != 0; } @@ -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 0000000..49eb1b0 --- /dev/null +++ b/include/llvm/IR/DiagnosticInfo.h @@ -0,0 +1,240 @@ +//===- 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/ADT/ArrayRef.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +// Forward declarations. +class DiagnosticPrinter; +class Function; +class Instruction; +class Twine; +class Value; + +/// \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_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(NULL) {} + + /// \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(NULL) {} + + /// \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; + + /// Hand rolled RTTI. + 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; + + /// Hand rolled RTTI. + 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; + + /// Hand rolled RTTI. + 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(NULL), + LineNum(0), Msg(Msg) {} + + /// \see DiagnosticInfo::print. + void print(DiagnosticPrinter &DP) const override; + + /// Hand rolled RTTI. + 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 occured. If 0, no line number will + /// be emitted in the message. + unsigned LineNum; + + /// Message to report. + 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 0000000..411c781 --- /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 0000000..86bbe39 --- /dev/null +++ b/include/llvm/IR/Dominators.h @@ -0,0 +1,190 @@ +//===- 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; + + inline DomTreeNode *operator[](BasicBlock *BB) const { + return getNode(BB); + } + + // 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 = 0) const override; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index bba7ecd..cb43bba 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -18,6 +18,7 @@ #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" @@ -335,7 +336,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 +349,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 +405,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 +425,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; diff --git a/include/llvm/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index 8efe50a..6717bc8 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,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_GVMATERIALIZER_H -#define LLVM_GVMATERIALIZER_H +#ifndef LLVM_IR_GVMATERIALIZER_H +#define LLVM_IR_GVMATERIALIZER_H #include "llvm/Support/system_error.h" diff --git a/include/llvm/Support/GetElementPtrTypeIterator.h b/include/llvm/IR/GetElementPtrTypeIterator.h index aacb531..f2722d6 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" diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index fec61a7..2ca481a 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -49,12 +49,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; /// set/getAliasee - These methods retrive and set alias target. void setAliasee(Constant *GV); @@ -64,23 +64,15 @@ public: Constant *getAliasee() { return getOperand(0); } - /// getAliasedGlobal() - Aliasee can be either global or bitcast of - /// global. This method retrives the global for both aliasee flavours. + + /// 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. GlobalValue *getAliasedGlobal(); const GlobalValue *getAliasedGlobal() const { return const_cast<GlobalAlias *>(this)->getAliasedGlobal(); } - /// 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); - } - static bool isValidLinkage(LinkageTypes L) { return isExternalLinkage(L) || isLocalLinkage(L) || isWeakLinkage(L) || isLinkOnceLinkage(L); diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 4f20a31..59c320d 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -40,10 +40,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 +51,19 @@ 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) { + Visibility(DefaultVisibility), Alignment(0), UnnamedAddr(0), + DllStorageClass(DefaultStorageClass), Parent(0) { setName(Name); } @@ -69,6 +73,7 @@ protected: 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 Module *Parent; // The containing module. std::string Section; // Section to emit this into, empty mean default public: @@ -91,11 +96,26 @@ public: return Visibility == ProtectedVisibility; } void setVisibility(VisibilityTypes V) { Visibility = V; } - + + 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 !Section.empty(); } const std::string &getSection() const { return Section; } - void setSection(StringRef S) { Section = S; } - + void setSection(StringRef S) { + assert((getValueID() != Value::GlobalAliasVal || S.empty()) && + "GlobalAlias should not have a section!"); + 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. @@ -136,21 +156,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; @@ -169,11 +176,8 @@ public: /// 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 @@ -181,14 +185,10 @@ public: /// 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); } @@ -204,13 +204,7 @@ public: 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); } @@ -267,7 +261,7 @@ public: /// @} /// 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. @@ -286,6 +280,8 @@ public: 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 660092d..a82740f 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -174,21 +174,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 8d1432d..79ee7b7 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; @@ -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,11 @@ 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 32-bit floating point value. Type *getFloatTy() { return Type::getFloatTy(Context); @@ -638,7 +649,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); } @@ -660,7 +671,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); } @@ -832,11 +843,15 @@ public: } Value *CreateBinOp(Instruction::BinaryOps Opc, - Value *LHS, Value *RHS, const Twine &Name = "") { + Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = 0) { 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 = "", @@ -915,13 +930,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, diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h new file mode 100644 index 0000000..2f78c83 --- /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 3398a83..ac19089 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 ac936a1..75e93bd 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 de7206d..1cdcd55 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 e12bb03..e1a5130 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -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 @@ -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) { @@ -385,7 +385,7 @@ 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, @@ -582,6 +582,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 @@ -642,7 +647,7 @@ protected: 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 diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index 5721d8f..928dc07 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. /// @@ -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; } diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 0843d8f..06d7287 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,7 +58,7 @@ 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); @@ -101,7 +102,7 @@ public: /// by the instruction. /// unsigned getAlignment() const { - return (1u << getSubclassDataFromInstruction()) >> 1; + return (1u << (getSubclassDataFromInstruction() & 31)) >> 1; } void setAlignment(unsigned Align); @@ -110,6 +111,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,7 +151,7 @@ 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); @@ -256,7 +271,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) { @@ -383,7 +398,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) { @@ -449,19 +464,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, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope, Instruction *InsertBefore = 0); 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 @@ -482,13 +502,20 @@ public: 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 +525,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 +555,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 +610,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, @@ -721,7 +775,7 @@ 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 = "", @@ -923,7 +977,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 +1109,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,15 +1228,11 @@ 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, @@ -1245,6 +1295,22 @@ 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 { @@ -1450,7 +1516,7 @@ 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 = "", @@ -1505,7 +1571,7 @@ 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 = "", @@ -1545,7 +1611,7 @@ class ExtractElementInst : public Instruction { 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, @@ -1606,7 +1672,7 @@ class InsertElementInst : public Instruction { 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, @@ -1659,7 +1725,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 @@ -1760,7 +1826,7 @@ 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, @@ -1871,7 +1937,7 @@ class InsertValueInst : public Instruction { 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) { @@ -2006,7 +2072,7 @@ 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). @@ -2086,8 +2152,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,7 +2263,7 @@ 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). @@ -2296,7 +2361,7 @@ private: 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) { @@ -2329,9 +2394,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 <> @@ -2368,7 +2433,7 @@ class BranchInst : public TerminatorInst { 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) { return new(1) BranchInst(IfTrue, InsertBefore); @@ -2428,9 +2493,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 +2539,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 @@ -2721,9 +2786,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,7 +2831,7 @@ 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) { @@ -2819,9 +2884,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,7 +2923,7 @@ 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, @@ -2889,6 +2954,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 { @@ -2970,6 +3049,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 +3123,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; @@ -3093,7 +3178,7 @@ class ResumeInst : public TerminatorInst { explicit ResumeInst(Value *Exn, Instruction *InsertBefore=0); 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) { return new(1) ResumeInst(Exn, InsertBefore); @@ -3118,9 +3203,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,7 +3227,7 @@ 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 @@ -3162,9 +3247,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,7 +3260,7 @@ 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 @@ -3211,7 +3296,7 @@ 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 @@ -3247,7 +3332,7 @@ 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 @@ -3283,7 +3368,7 @@ 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 @@ -3319,7 +3404,7 @@ 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 @@ -3355,7 +3440,7 @@ 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 @@ -3391,7 +3476,7 @@ 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 @@ -3427,7 +3512,7 @@ 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 @@ -3463,7 +3548,7 @@ 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 @@ -3515,7 +3600,7 @@ public: ); /// \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,7 +3624,7 @@ 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 @@ -3587,7 +3672,7 @@ 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 @@ -3624,7 +3709,7 @@ 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 diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index 8344c56..e053f78 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 473e525..839bbbd 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -79,7 +79,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 +98,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 ded6cc1..6a48f17 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>; @@ -285,10 +293,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 +326,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 +463,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]>; @@ -511,6 +517,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 //===----------------------------------------------------------------------===// @@ -518,6 +529,7 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty], include "llvm/IR/IntrinsicsPowerPC.td" include "llvm/IR/IntrinsicsX86.td" include "llvm/IR/IntrinsicsARM.td" +include "llvm/IR/IntrinsicsARM64.td" include "llvm/IR/IntrinsicsAArch64.td" include "llvm/IR/IntrinsicsXCore.td" include "llvm/IR/IntrinsicsHexagon.td" diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td index 68af8c1..61c0e5d 100644 --- a/include/llvm/IR/IntrinsicsAArch64.td +++ b/include/llvm/IR/IntrinsicsAArch64.td @@ -36,27 +36,11 @@ def int_aarch64_neon_xtn : // 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 : +def int_aarch64_neon_vcvtxn : 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 : +def int_aarch64_neon_vcvtzs : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; -def int_aarch64_neon_fcvtzu : +def int_aarch64_neon_vcvtzu : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; // Vector maxNum (Floating Point) @@ -84,7 +68,7 @@ class Neon_N3V_Intrinsic [IntrNoMem]>; class Neon_N2V_Narrow_Intrinsic : Intrinsic<[llvm_anyvector_ty], - [LLVMExtendedElementVectorType<0>, llvm_i32_ty], + [LLVMExtendedType<0>, llvm_i32_ty], [IntrNoMem]>; // Vector rounding shift right by immediate (Signed) @@ -107,9 +91,6 @@ def int_aarch64_neon_vuqrshrn : Neon_N2V_Narrow_Intrinsic; 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; @@ -117,30 +98,34 @@ 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; +def int_aarch64_neon_vmaxv : + Intrinsic<[llvm_float_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vminv : + Intrinsic<[llvm_float_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vmaxnmv : + Intrinsic<[llvm_float_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_aarch64_neon_vminnmv : + Intrinsic<[llvm_float_ty], [llvm_v4f32_ty], [IntrNoMem]>; // Vector Table Lookup. def int_aarch64_neon_vtbl1 : Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; + [llvm_v16i8_ty, LLVMMatchType<0>], [IntrNoMem]>; def int_aarch64_neon_vtbl2 : Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<0>], + [llvm_v16i8_ty, llvm_v16i8_ty, LLVMMatchType<0>], [IntrNoMem]>; def int_aarch64_neon_vtbl3 : Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, LLVMMatchType<0>], [IntrNoMem]>; def int_aarch64_neon_vtbl4 : Intrinsic<[llvm_anyvector_ty], - [llvm_anyvector_ty, LLVMMatchType<1>, LLVMMatchType<1>, - LLVMMatchType<1>, LLVMMatchType<0>], [IntrNoMem]>; + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, LLVMMatchType<0>], [IntrNoMem]>; // Vector Table Extension. // Some elements of the destination vector may not be updated, so the original @@ -148,23 +133,23 @@ def int_aarch64_neon_vtbl4 : // arguments after that are the table. def int_aarch64_neon_vtbx1 : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<0>], + [LLVMMatchType<0>, llvm_v16i8_ty, LLVMMatchType<0>], [IntrNoMem]>; def int_aarch64_neon_vtbx2 : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, - LLVMMatchType<0>], [IntrNoMem]>; + [LLVMMatchType<0>, llvm_v16i8_ty, llvm_v16i8_ty, + LLVMMatchType<0>], [IntrNoMem]>; def int_aarch64_neon_vtbx3 : Intrinsic<[llvm_anyvector_ty], - [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>, - LLVMMatchType<1>, LLVMMatchType<0>], [IntrNoMem]>; + [LLVMMatchType<0>, llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, 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>], + [LLVMMatchType<0>, llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_v16i8_ty, LLVMMatchType<0>], [IntrNoMem]>; // Vector Load/store @@ -233,74 +218,118 @@ def int_aarch64_neon_vqrshlu : Neon_2Arg_Intrinsic; 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]>; + Intrinsic<[llvm_anyfloat_ty], [llvm_anyvector_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]>; + Intrinsic<[llvm_anyfloat_ty], [llvm_anyvector_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]>; + Intrinsic<[llvm_anyfloat_ty], [llvm_anyvector_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]>; + Intrinsic<[llvm_anyfloat_ty], [llvm_anyvector_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]>; + Intrinsic<[llvm_anyfloat_ty], [llvm_anyvector_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]>; +def int_aarch64_neon_vcvtint2fps : + Intrinsic<[llvm_anyfloat_ty], [llvm_anyvector_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]>; +def int_aarch64_neon_vcvtint2fpu : + Intrinsic<[llvm_anyfloat_ty], [llvm_anyvector_ty], [IntrNoMem]>; + +// Scalar Floating-point Convert +def int_aarch64_neon_fcvtxn : + Intrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtns : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtnu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtps : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtpu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtms : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtmu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtas : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtau : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtzs : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty], [IntrNoMem]>; +def int_aarch64_neon_fcvtzu : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty], [IntrNoMem]>; + +// Scalar Floating-point Reciprocal Estimate. +def int_aarch64_neon_vrecpe : + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; // Scalar Floating-point Reciprocal Exponent -def int_aarch64_neon_vrecpx : Neon_1Arg_Intrinsic; +def int_aarch64_neon_vrecpx : + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; -class Neon_Cmp_Intrinsic - : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_anyvector_ty], - [IntrNoMem]>; +// Scalar Floating-point Reciprocal Square Root Estimate +def int_aarch64_neon_vrsqrte : + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + +// Scalar Floating-point Reciprocal Step +def int_aarch64_neon_vrecps : + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +// Scalar Floating-point Reciprocal Square Root Step +def int_aarch64_neon_vrsqrts : + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +// Compare with vector operands. +class Neon_Cmp_Intrinsic : + Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_anyvector_ty], + [IntrNoMem]>; + +// Floating-point compare with scalar operands. +class Neon_Float_Cmp_Intrinsic : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty, llvm_anyfloat_ty], + [IntrNoMem]>; // Scalar Compare Equal def int_aarch64_neon_vceq : Neon_Cmp_Intrinsic; +def int_aarch64_neon_fceq : Neon_Float_Cmp_Intrinsic; // Scalar Compare Greater-Than or Equal def int_aarch64_neon_vcge : Neon_Cmp_Intrinsic; def int_aarch64_neon_vchs : Neon_Cmp_Intrinsic; +def int_aarch64_neon_fcge : Neon_Float_Cmp_Intrinsic; +def int_aarch64_neon_fchs : Neon_Float_Cmp_Intrinsic; // Scalar Compare Less-Than or Equal def int_aarch64_neon_vclez : Neon_Cmp_Intrinsic; +def int_aarch64_neon_fclez : Neon_Float_Cmp_Intrinsic; // Scalar Compare Less-Than def int_aarch64_neon_vcltz : Neon_Cmp_Intrinsic; +def int_aarch64_neon_fcltz : Neon_Float_Cmp_Intrinsic; // Scalar Compare Greater-Than def int_aarch64_neon_vcgt : Neon_Cmp_Intrinsic; def int_aarch64_neon_vchi : Neon_Cmp_Intrinsic; +def int_aarch64_neon_fcgt : Neon_Float_Cmp_Intrinsic; +def int_aarch64_neon_fchi : Neon_Float_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; - +def int_aarch64_neon_fcage : Neon_Float_Cmp_Intrinsic; + // Scalar Floating-point Absolute Compare Greater Than def int_aarch64_neon_vcagt : Neon_Cmp_Intrinsic; +def int_aarch64_neon_fcagt : Neon_Float_Cmp_Intrinsic; // Scalar Signed Saturating Accumulated of Unsigned Value def int_aarch64_neon_vuqadd : Neon_2Arg_Intrinsic; @@ -313,7 +342,9 @@ def int_aarch64_neon_vabs : Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty], [IntrNoMem]>; // Scalar Absolute Difference -def int_aarch64_neon_vabd : Neon_2Arg_Intrinsic; +def int_aarch64_neon_vabd : + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; // Scalar Negate Value def int_aarch64_neon_vneg : @@ -325,6 +356,9 @@ def int_aarch64_neon_vqdmlal : Neon_3Arg_Long_Intrinsic; // Signed Saturating Doubling Multiply-Subtract Long def int_aarch64_neon_vqdmlsl : Neon_3Arg_Long_Intrinsic; +def int_aarch64_neon_vmull_p64 : + Intrinsic<[llvm_v16i8_ty], [llvm_v1i64_ty, llvm_v1i64_ty], [IntrNoMem]>; + class Neon_2Arg_ShiftImm_Intrinsic : Intrinsic<[llvm_v1i64_ty], [llvm_v1i64_ty, llvm_i32_ty], [IntrNoMem]>; @@ -355,34 +389,19 @@ def int_aarch64_neon_vqshlu_n : Neon_N2V_Intrinsic; 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]>; +def int_aarch64_neon_vcvtfxs2fp_n : + Intrinsic<[llvm_anyfloat_ty], [llvm_anyvector_ty, llvm_i32_ty], [IntrNoMem]>; // 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]>; +def int_aarch64_neon_vcvtfxu2fp_n : + Intrinsic<[llvm_anyfloat_ty], [llvm_anyvector_ty, llvm_i32_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]>; +def int_aarch64_neon_vcvtfp2fxs_n : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; // 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]>; - -class Neon_SHA_Intrinsic - : Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v1i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; +def int_aarch64_neon_vcvtfp2fxu_n : + Intrinsic<[llvm_anyvector_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; -def int_aarch64_neon_sha1c : Neon_SHA_Intrinsic; -def int_aarch64_neon_sha1m : Neon_SHA_Intrinsic; -def int_aarch64_neon_sha1p : Neon_SHA_Intrinsic; } diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index 0b50d64..482f98e 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -38,12 +38,20 @@ 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]>; @@ -123,20 +131,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 +147,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 +156,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 +229,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 +288,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 +464,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/IntrinsicsARM64.td b/include/llvm/IR/IntrinsicsARM64.td new file mode 100644 index 0000000..d7f307e --- /dev/null +++ b/include/llvm/IR/IntrinsicsARM64.td @@ -0,0 +1,628 @@ +//===- IntrinsicsARM64.td - Defines ARM64 intrinsics -------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the ARM64-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "arm64" in { + +def int_arm64_ldxr : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty]>; +def int_arm64_stxr : Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_anyptr_ty]>; +def int_arm64_clrex : Intrinsic<[]>; + +def int_arm64_ldxp : Intrinsic<[llvm_i64_ty, llvm_i64_ty], [llvm_ptr_ty]>; +def int_arm64_stxp : Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_i64_ty, + llvm_ptr_ty]>; + +def int_arm64_sdiv : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, + LLVMMatchType<0>], [IntrNoMem]>; +def int_arm64_udiv : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, + LLVMMatchType<0>], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// Advanced SIMD (NEON) + +let TargetPrefix = "arm64" in { // All intrinsics start with "llvm.arm64.". + 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 + +let Properties = [IntrNoMem] in { + // Vector Add Across Lanes + def int_arm64_neon_saddv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_arm64_neon_uaddv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_arm64_neon_faddv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; + + // Vector Long Add Across Lanes + def int_arm64_neon_saddlv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_arm64_neon_uaddlv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + + // Vector Halving Add + def int_arm64_neon_shadd : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_uhadd : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Rounding Halving Add + def int_arm64_neon_srhadd : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_urhadd : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Saturating Add + def int_arm64_neon_sqadd : AdvSIMD_2IntArg_Intrinsic; + def int_arm64_neon_suqadd : AdvSIMD_2IntArg_Intrinsic; + def int_arm64_neon_usqadd : AdvSIMD_2IntArg_Intrinsic; + def int_arm64_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_arm64_neon_addhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; + + // Vector Rounding Add High-Half + def int_arm64_neon_raddhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; + + // Vector Saturating Doubling Multiply High + def int_arm64_neon_sqdmulh : AdvSIMD_2IntArg_Intrinsic; + + // Vector Saturating Rounding Doubling Multiply High + def int_arm64_neon_sqrdmulh : AdvSIMD_2IntArg_Intrinsic; + + // Vector Polynominal Multiply + def int_arm64_neon_pmul : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Long Multiply + def int_arm64_neon_smull : AdvSIMD_2VectorArg_Long_Intrinsic; + def int_arm64_neon_umull : AdvSIMD_2VectorArg_Long_Intrinsic; + def int_arm64_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_arm64_neon_pmull64 : + Intrinsic<[llvm_v16i8_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + + // Vector Extending Multiply + def int_arm64_neon_fmulx : AdvSIMD_2FloatArg_Intrinsic; + + // Vector Saturating Doubling Long Multiply + def int_arm64_neon_sqdmull : AdvSIMD_2VectorArg_Long_Intrinsic; + def int_arm64_neon_sqdmulls_scalar + : Intrinsic<[llvm_i64_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + + // Vector Halving Subtract + def int_arm64_neon_shsub : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_uhsub : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Saturating Subtract + def int_arm64_neon_sqsub : AdvSIMD_2IntArg_Intrinsic; + def int_arm64_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_arm64_neon_subhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; + + // Vector Rounding Subtract High-Half + def int_arm64_neon_rsubhn : AdvSIMD_2VectorArg_Narrow_Intrinsic; + + // Vector Compare Absolute Greater-than-or-equal + def int_arm64_neon_facge : AdvSIMD_2Arg_FloatCompare_Intrinsic; + + // Vector Compare Absolute Greater-than + def int_arm64_neon_facgt : AdvSIMD_2Arg_FloatCompare_Intrinsic; + + // Vector Absolute Difference + def int_arm64_neon_sabd : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_uabd : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_fabd : AdvSIMD_2VectorArg_Intrinsic; + + // Scalar Absolute Difference + def int_arm64_sisd_fabd : AdvSIMD_2Scalar_Float_Intrinsic; + + // Vector Max + def int_arm64_neon_smax : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_umax : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_fmax : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_fmaxnmp : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Max Across Lanes + def int_arm64_neon_smaxv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_arm64_neon_umaxv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_arm64_neon_fmaxv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; + def int_arm64_neon_fmaxnmv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; + + // Vector Min + def int_arm64_neon_smin : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_umin : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_fmin : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_fminnmp : AdvSIMD_2VectorArg_Intrinsic; + + // Vector Min/Max Number + def int_arm64_neon_fminnm : AdvSIMD_2FloatArg_Intrinsic; + def int_arm64_neon_fmaxnm : AdvSIMD_2FloatArg_Intrinsic; + + // Vector Min Across Lanes + def int_arm64_neon_sminv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_arm64_neon_uminv : AdvSIMD_1VectorArg_Int_Across_Intrinsic; + def int_arm64_neon_fminv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; + def int_arm64_neon_fminnmv : AdvSIMD_1VectorArg_Float_Across_Intrinsic; + + // Pairwise Add + def int_arm64_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_arm64_neon_saddlp : AdvSIMD_1VectorArg_Expand_Intrinsic; + def int_arm64_neon_uaddlp : AdvSIMD_1VectorArg_Expand_Intrinsic; + + // Folding Maximum + def int_arm64_neon_smaxp : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_umaxp : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_fmaxp : AdvSIMD_2VectorArg_Intrinsic; + + // Folding Minimum + def int_arm64_neon_sminp : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_uminp : AdvSIMD_2VectorArg_Intrinsic; + def int_arm64_neon_fminp : AdvSIMD_2VectorArg_Intrinsic; + + // Reciprocal Estimate/Step + def int_arm64_neon_frecps : AdvSIMD_2FloatArg_Intrinsic; + def int_arm64_neon_frsqrts : AdvSIMD_2FloatArg_Intrinsic; + + // Reciprocal Exponent + def int_arm64_neon_frecpx : AdvSIMD_1FloatArg_Intrinsic; + + // Vector Saturating Shift Left + def int_arm64_neon_sqshl : AdvSIMD_2IntArg_Intrinsic; + def int_arm64_neon_uqshl : AdvSIMD_2IntArg_Intrinsic; + + // Vector Rounding Shift Left + def int_arm64_neon_srshl : AdvSIMD_2IntArg_Intrinsic; + def int_arm64_neon_urshl : AdvSIMD_2IntArg_Intrinsic; + + // Vector Saturating Rounding Shift Left + def int_arm64_neon_sqrshl : AdvSIMD_2IntArg_Intrinsic; + def int_arm64_neon_uqrshl : AdvSIMD_2IntArg_Intrinsic; + + // Vector Signed->Unsigned Shift Left by Constant + def int_arm64_neon_sqshlu : AdvSIMD_2IntArg_Intrinsic; + + // Vector Signed->Unsigned Narrowing Saturating Shift Right by Constant + def int_arm64_neon_sqshrun : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + + // Vector Signed->Unsigned Rounding Narrowing Saturating Shift Right by Const + def int_arm64_neon_sqrshrun : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + + // Vector Narrowing Shift Right by Constant + def int_arm64_neon_sqshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + def int_arm64_neon_uqshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + + // Vector Rounding Narrowing Shift Right by Constant + def int_arm64_neon_rshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + + // Vector Rounding Narrowing Saturating Shift Right by Constant + def int_arm64_neon_sqrshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + def int_arm64_neon_uqrshrn : AdvSIMD_2Arg_Scalar_Narrow_Intrinsic; + + // Vector Shift Left + def int_arm64_neon_sshl : AdvSIMD_2IntArg_Intrinsic; + def int_arm64_neon_ushl : AdvSIMD_2IntArg_Intrinsic; + + // Vector Widening Shift Left by Constant + def int_arm64_neon_shll : AdvSIMD_2VectorArg_Scalar_Wide_BySize_Intrinsic; + def int_arm64_neon_sshll : AdvSIMD_2VectorArg_Scalar_Wide_Intrinsic; + def int_arm64_neon_ushll : AdvSIMD_2VectorArg_Scalar_Wide_Intrinsic; + + // Vector Shift Right by Constant and Insert + def int_arm64_neon_vsri : AdvSIMD_3VectorArg_Scalar_Intrinsic; + + // Vector Shift Left by Constant and Insert + def int_arm64_neon_vsli : AdvSIMD_3VectorArg_Scalar_Intrinsic; + + // Vector Saturating Narrow + def int_arm64_neon_scalar_sqxtn: AdvSIMD_1IntArg_Narrow_Intrinsic; + def int_arm64_neon_scalar_uqxtn : AdvSIMD_1IntArg_Narrow_Intrinsic; + def int_arm64_neon_sqxtn : AdvSIMD_1VectorArg_Narrow_Intrinsic; + def int_arm64_neon_uqxtn : AdvSIMD_1VectorArg_Narrow_Intrinsic; + + // Vector Saturating Extract and Unsigned Narrow + def int_arm64_neon_scalar_sqxtun : AdvSIMD_1IntArg_Narrow_Intrinsic; + def int_arm64_neon_sqxtun : AdvSIMD_1VectorArg_Narrow_Intrinsic; + + // Vector Absolute Value + def int_arm64_neon_abs : AdvSIMD_1IntArg_Intrinsic; + + // Vector Saturating Absolute Value + def int_arm64_neon_sqabs : AdvSIMD_1IntArg_Intrinsic; + + // Vector Saturating Negation + def int_arm64_neon_sqneg : AdvSIMD_1IntArg_Intrinsic; + + // Vector Count Leading Sign Bits + def int_arm64_neon_cls : AdvSIMD_1VectorArg_Intrinsic; + + // Vector Reciprocal Estimate + def int_arm64_neon_urecpe : AdvSIMD_1VectorArg_Intrinsic; + def int_arm64_neon_frecpe : AdvSIMD_1FloatArg_Intrinsic; + + // Vector Square Root Estimate + def int_arm64_neon_ursqrte : AdvSIMD_1VectorArg_Intrinsic; + def int_arm64_neon_frsqrte : AdvSIMD_1FloatArg_Intrinsic; + + // Vector Bitwise Reverse + def int_arm64_neon_rbit : AdvSIMD_1VectorArg_Intrinsic; + + // Vector Conversions Between Half-Precision and Single-Precision. + def int_arm64_neon_vcvtfp2hf + : Intrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>; + def int_arm64_neon_vcvthf2fp + : Intrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>; + + // Vector Conversions Between Floating-point and Fixed-point. + def int_arm64_neon_vcvtfp2fxs : AdvSIMD_CvtFPToFx_Intrinsic; + def int_arm64_neon_vcvtfp2fxu : AdvSIMD_CvtFPToFx_Intrinsic; + def int_arm64_neon_vcvtfxs2fp : AdvSIMD_CvtFxToFP_Intrinsic; + def int_arm64_neon_vcvtfxu2fp : AdvSIMD_CvtFxToFP_Intrinsic; + + // Vector FP->Int Conversions + def int_arm64_neon_fcvtas : AdvSIMD_FPToIntRounding_Intrinsic; + def int_arm64_neon_fcvtau : AdvSIMD_FPToIntRounding_Intrinsic; + def int_arm64_neon_fcvtms : AdvSIMD_FPToIntRounding_Intrinsic; + def int_arm64_neon_fcvtmu : AdvSIMD_FPToIntRounding_Intrinsic; + def int_arm64_neon_fcvtns : AdvSIMD_FPToIntRounding_Intrinsic; + def int_arm64_neon_fcvtnu : AdvSIMD_FPToIntRounding_Intrinsic; + def int_arm64_neon_fcvtps : AdvSIMD_FPToIntRounding_Intrinsic; + def int_arm64_neon_fcvtpu : AdvSIMD_FPToIntRounding_Intrinsic; + def int_arm64_neon_fcvtzs : AdvSIMD_FPToIntRounding_Intrinsic; + def int_arm64_neon_fcvtzu : AdvSIMD_FPToIntRounding_Intrinsic; + + // Vector FP Rounding: only ties to even is unrepresented by a normal + // intrinsic. + def int_arm64_neon_frintn : AdvSIMD_1FloatArg_Intrinsic; + + // Scalar FP->Int conversions + + // Vector FP Inexact Narrowing + def int_arm64_neon_fcvtxn : AdvSIMD_1VectorArg_Expand_Intrinsic; + + // Scalar FP Inexact Narrowing + def int_arm64_sisd_fcvtxn : Intrinsic<[llvm_float_ty], [llvm_double_ty], + [IntrNoMem]>; +} + +let TargetPrefix = "arm64" in { // All intrinsics start with "llvm.arm64.". + 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_arm64_neon_vcopy_lane: AdvSIMD_2Vector2Index_Intrinsic; + +let TargetPrefix = "arm64" in { // All intrinsics start with "llvm.arm64.". + 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_arm64_neon_ld1x2 : AdvSIMD_2Vec_Load_Intrinsic; +def int_arm64_neon_ld1x3 : AdvSIMD_3Vec_Load_Intrinsic; +def int_arm64_neon_ld1x4 : AdvSIMD_4Vec_Load_Intrinsic; + +def int_arm64_neon_st1x2 : AdvSIMD_2Vec_Store_Intrinsic; +def int_arm64_neon_st1x3 : AdvSIMD_3Vec_Store_Intrinsic; +def int_arm64_neon_st1x4 : AdvSIMD_4Vec_Store_Intrinsic; + +def int_arm64_neon_ld2 : AdvSIMD_2Vec_Load_Intrinsic; +def int_arm64_neon_ld3 : AdvSIMD_3Vec_Load_Intrinsic; +def int_arm64_neon_ld4 : AdvSIMD_4Vec_Load_Intrinsic; + +def int_arm64_neon_ld2lane : AdvSIMD_2Vec_Load_Lane_Intrinsic; +def int_arm64_neon_ld3lane : AdvSIMD_3Vec_Load_Lane_Intrinsic; +def int_arm64_neon_ld4lane : AdvSIMD_4Vec_Load_Lane_Intrinsic; + +def int_arm64_neon_ld2r : AdvSIMD_2Vec_Load_Intrinsic; +def int_arm64_neon_ld3r : AdvSIMD_3Vec_Load_Intrinsic; +def int_arm64_neon_ld4r : AdvSIMD_4Vec_Load_Intrinsic; + +def int_arm64_neon_st2 : AdvSIMD_2Vec_Store_Intrinsic; +def int_arm64_neon_st3 : AdvSIMD_3Vec_Store_Intrinsic; +def int_arm64_neon_st4 : AdvSIMD_4Vec_Store_Intrinsic; + +def int_arm64_neon_st2lane : AdvSIMD_2Vec_Store_Lane_Intrinsic; +def int_arm64_neon_st3lane : AdvSIMD_3Vec_Store_Lane_Intrinsic; +def int_arm64_neon_st4lane : AdvSIMD_4Vec_Store_Lane_Intrinsic; + +let TargetPrefix = "arm64" in { // All intrinsics start with "llvm.arm64.". + 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_arm64_neon_tbl1 : AdvSIMD_Tbl1_Intrinsic; +def int_arm64_neon_tbl2 : AdvSIMD_Tbl2_Intrinsic; +def int_arm64_neon_tbl3 : AdvSIMD_Tbl3_Intrinsic; +def int_arm64_neon_tbl4 : AdvSIMD_Tbl4_Intrinsic; + +def int_arm64_neon_tbx1 : AdvSIMD_Tbx1_Intrinsic; +def int_arm64_neon_tbx2 : AdvSIMD_Tbx2_Intrinsic; +def int_arm64_neon_tbx3 : AdvSIMD_Tbx3_Intrinsic; +def int_arm64_neon_tbx4 : AdvSIMD_Tbx4_Intrinsic; + +let TargetPrefix = "arm64" 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_arm64_crypto_aese : Crypto_AES_DataKey_Intrinsic; +def int_arm64_crypto_aesd : Crypto_AES_DataKey_Intrinsic; +def int_arm64_crypto_aesmc : Crypto_AES_Data_Intrinsic; +def int_arm64_crypto_aesimc : Crypto_AES_Data_Intrinsic; + +// SHA1 +def int_arm64_crypto_sha1c : Crypto_SHA_5Hash4Schedule_Intrinsic; +def int_arm64_crypto_sha1p : Crypto_SHA_5Hash4Schedule_Intrinsic; +def int_arm64_crypto_sha1m : Crypto_SHA_5Hash4Schedule_Intrinsic; +def int_arm64_crypto_sha1h : Crypto_SHA_1Hash_Intrinsic; + +def int_arm64_crypto_sha1su0 : Crypto_SHA_12Schedule_Intrinsic; +def int_arm64_crypto_sha1su1 : Crypto_SHA_8Schedule_Intrinsic; + +// SHA256 +def int_arm64_crypto_sha256h : Crypto_SHA_8Hash4Schedule_Intrinsic; +def int_arm64_crypto_sha256h2 : Crypto_SHA_8Hash4Schedule_Intrinsic; +def int_arm64_crypto_sha256su0 : Crypto_SHA_8Schedule_Intrinsic; +def int_arm64_crypto_sha256su1 : Crypto_SHA_12Schedule_Intrinsic; + +//===----------------------------------------------------------------------===// +// CRC32 + +let TargetPrefix = "arm64" in { + +def int_arm64_crc32b : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm64_crc32cb : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm64_crc32h : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm64_crc32ch : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm64_crc32w : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm64_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +def int_arm64_crc32x : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; +def int_arm64_crc32cx : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i64_ty], + [IntrNoMem]>; +} diff --git a/include/llvm/IR/IntrinsicsMips.td b/include/llvm/IR/IntrinsicsMips.td index 42c5821..3455761 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 a372c22..7f72ce8 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">, diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 4c5718f..8f64b5d 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -536,6 +536,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<[], [], []>; } //===----------------------------------------------------------------------===// @@ -1246,6 +1248,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 @@ -1313,6 +1321,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 +1345,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 +1408,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 +1454,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 +1570,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 +1716,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 +1767,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 +1791,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 @@ -1758,68 +1842,68 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_gather_d_pd : GCCBuiltin<"__builtin_ia32_gatherd_pd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_d_pd_256 : GCCBuiltin<"__builtin_ia32_gatherd_pd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_q_pd : GCCBuiltin<"__builtin_ia32_gatherq_pd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_q_pd_256 : GCCBuiltin<"__builtin_ia32_gatherq_pd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_d_ps : GCCBuiltin<"__builtin_ia32_gatherd_ps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_d_ps_256 : GCCBuiltin<"__builtin_ia32_gatherd_ps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_q_ps : GCCBuiltin<"__builtin_ia32_gatherq_ps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_q_ps_256 : GCCBuiltin<"__builtin_ia32_gatherq_ps256">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_d_q : GCCBuiltin<"__builtin_ia32_gatherd_q">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_d_q_256 : GCCBuiltin<"__builtin_ia32_gatherd_q256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_q_q : GCCBuiltin<"__builtin_ia32_gatherq_q">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_q_q_256 : GCCBuiltin<"__builtin_ia32_gatherq_q256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_d_d : GCCBuiltin<"__builtin_ia32_gatherd_d">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_d_d_256 : GCCBuiltin<"__builtin_ia32_gatherd_d256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_q_d : GCCBuiltin<"__builtin_ia32_gatherq_d">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx2_gather_q_d_256 : GCCBuiltin<"__builtin_ia32_gatherq_d256">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrReadMem]>; + [IntrReadArgMem]>; } // Misc. @@ -2592,6 +2676,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 +2731,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 +2790,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 +2891,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 +2917,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], - [IntrNoMem]>; - def int_x86_avx512_rcp28_pd_512 : GCCBuiltin<"__builtin_ia32_rcp28pd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], - [IntrNoMem]>; - def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_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_sd : GCCBuiltin<"__builtin_ia32_rcp28sd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_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_rsqrt28_ps_512 : GCCBuiltin<"__builtin_ia32_rsqrt28ps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_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_rsqrt28_pd_512 : GCCBuiltin<"__builtin_ia32_rsqrt28pd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_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_ss : GCCBuiltin<"__builtin_ia32_rsqrt28ss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_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_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]>; } @@ -2909,28 +3002,28 @@ 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], - [IntrReadMem]>; + [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], - [IntrReadMem]>; + [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], - [IntrReadMem]>; + [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], - [IntrReadMem]>; + [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], - [IntrReadMem]>; + [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], - [IntrReadMem]>; + [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], @@ -2938,12 +3031,12 @@ let TargetPrefix = "x86" in { def int_x86_avx512_gather_qps_512 : GCCBuiltin<"__builtin_ia32_gatherqps512">, Intrinsic<[llvm_v8f32_ty], [llvm_v8i64_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrReadMem]>; + [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], - [IntrReadMem]>; + [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], @@ -2955,7 +3048,7 @@ let TargetPrefix = "x86" in { 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], - [IntrReadMem]>; + [IntrReadArgMem]>; def int_x86_avx512_gather_dpq_512 : GCCBuiltin<"__builtin_ia32_gatherdpq512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty, llvm_ptr_ty, @@ -3045,62 +3138,62 @@ let TargetPrefix = "x86" in { // 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], - []>; - def int_x86_avx512_conflict_q_maskz_512: - GCCBuiltin<"__builtin_ia32_maskz_conflictq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i1_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 bf345d4..b614e1e 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 dd379ae..ae4859a 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,6 +27,7 @@ class Twine; class Instruction; class Module; class SMDiagnostic; +class DiagnosticInfo; template <typename T> class SmallVectorImpl; /// This is an important class for using LLVM in a threaded context. It @@ -64,6 +65,11 @@ 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); + /// 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 @@ -82,6 +88,33 @@ 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 = 0); + + /// 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); /// 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 501a9db..cb18df8 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 fa1436e..c967a6b 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 d256a3e..5c9dccd 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 @@ -127,7 +127,7 @@ public: : P(p), V(0), 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; }; @@ -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 c0914b1..1f6bbbc 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" @@ -65,7 +68,7 @@ public: // 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 (-" @@ -74,11 +77,11 @@ public: } 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 ce81b54..c07b2bd 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -174,11 +174,8 @@ public: /// 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); + ConstantInt *Off = ConstantInt::get(Type::getInt64Ty(Context), Offset); + Value *Ops[3] = { createString(Name), Parent, Off }; return MDNode::get(Context, Ops); } diff --git a/include/llvm/Target/Mangler.h b/include/llvm/IR/Mangler.h index eee7bf6..c1ba585 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 9659c2e..d054fbb 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(0), 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. @@ -239,6 +276,24 @@ public: /// 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 b30a9a3..f0d4002 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -15,13 +15,15 @@ #ifndef LLVM_IR_MODULE_H #define LLVM_IR_MODULE_H -#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/iterator_range.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 "llvm/Support/system_error.h" namespace llvm { @@ -142,12 +144,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 +152,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,12 +197,20 @@ 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 + 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. + // 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 +231,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; } @@ -260,7 +258,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; } @@ -464,18 +463,13 @@ public: /// 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. + 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. + error_code materializeAllPermanently(); /// @} /// @name Direct access to the globals list, functions list, and symbol table @@ -524,6 +518,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 +547,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 +571,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 diff --git a/include/llvm/Support/NoFolder.h b/include/llvm/IR/NoFolder.h index ecfbbaa..a9cdfc3 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 5b9bee7..888cabf 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 833547a..c6c530c 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>(0)) == 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>(0)) == 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 = 0); 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 = 0); + + 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 0; + + 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 = 0; + 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 240bb81..2efb294 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 c5fb780..bf18dfe 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 { diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index 3cfb84e..742a0d3 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: @@ -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 = 0) 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 = 0) const; }; // Printing of types. diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 12cd150..340572a 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#UserLayout +/// +/// 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(0) { 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 505bdeb..061bc91 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -19,6 +19,7 @@ #ifndef LLVM_IR_USER_H #define LLVM_IR_USER_H +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Value.h" #include "llvm/Support/ErrorHandling.h" @@ -112,11 +113,19 @@ 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 @@ -156,6 +165,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 +178,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(0); } /// replaceUsesOfWith - Replaces all references to the "From" definition with @@ -194,12 +206,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 e1361fe..d5b9f11 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -14,11 +14,12 @@ #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 { @@ -36,6 +37,7 @@ class InlineAsm; class Instruction; class LLVMContext; class MDNode; +class Module; class StringRef; class Twine; class Type; @@ -60,7 +62,7 @@ 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 { @@ -74,6 +76,96 @@ protected: unsigned char SubclassOptionalData : 7; private: + 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); + } + }; + + 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(); } + }; + /// SubclassData - This member is defined by this class, but is not used for /// anything. Subclasses can use it to hold whatever state they find useful. /// This field is initialized to zero by the ctor. @@ -106,6 +198,13 @@ public: /// void print(raw_ostream &O, AssemblyAnnotationWriter *AAW = 0) 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 = 0) const; + /// All values are typed, get the type of this value. /// Type *getType() const { return VTy; } @@ -143,16 +242,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 == 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 diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/IR/ValueHandle.h index bc02ba3..9b5e11a 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" diff --git a/include/llvm/ADT/ValueMap.h b/include/llvm/IR/ValueMap.h index b4fed7a..42da529 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> @@ -198,7 +198,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,7 +209,7 @@ 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); @@ -220,7 +220,7 @@ 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. diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h new file mode 100644 index 0000000..9a2f402 --- /dev/null +++ b/include/llvm/IR/Verifier.h @@ -0,0 +1,75 @@ +//===- 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 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 = 0); + +/// \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 = 0); + +/// \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); + +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/InitializePasses.h b/include/llvm/InitializePasses.h index aefb3c0..9b9f234 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&); @@ -73,7 +74,7 @@ void initializeArgPromotionPass(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 +91,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&); @@ -110,7 +112,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 +122,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&); @@ -209,9 +212,9 @@ 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&); @@ -246,7 +249,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 +258,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 +268,7 @@ void initializeLoopVectorizePass(PassRegistry&); void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); +void initializeStackMapLivenessPass(PassRegistry&); } #endif diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index c478bd9..5433991 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,16 +36,17 @@ #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; @@ -79,9 +80,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 +98,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,14 +108,15 @@ 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(); @@ -133,6 +133,10 @@ private: llvm::Mangler &Mangler); bool determineTarget(std::string &errMsg); + static void DiagnosticHandler(const llvm::DiagnosticInfo &DI, void *Context); + + void DiagnosticHandler2(const llvm::DiagnosticInfo &DI); + typedef llvm::StringMap<uint8_t> StringSet; llvm::LLVMContext &Context; @@ -148,6 +152,8 @@ private: std::string MCpu; std::string NativeObjectPath; llvm::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 f4693c8..1e4fa1b 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/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCContext.h" -#include "llvm/Target/Mangler.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/Target/TargetMachine.h" #include <string> #include <vector> @@ -47,8 +47,12 @@ private: const llvm::GlobalValue *symbol; }; - llvm::OwningPtr<llvm::Module> _module; - llvm::OwningPtr<llvm::TargetMachine> _target; + std::unique_ptr<llvm::Module> _module; + std::unique_ptr<llvm::TargetMachine> _target; + llvm::MCObjectFileInfo ObjFileInfo; + 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 @@ -95,7 +99,8 @@ public: std::string& errMsg); static LTOModule *makeLTOModule(const void *mem, size_t length, llvm::TargetOptions options, - std::string &errMsg); + std::string &errMsg, + llvm::StringRef path = ""); /// getTargetTriple - Return the Module's target triple. const char *getTargetTriple() { @@ -127,6 +132,30 @@ public: return NULL; } + /// getDependentLibraryCount - Get the number of dependent libraries + uint32_t getDependentLibraryCount() { + return _deplibs.size(); + } + + /// getDependentLibrary - Get the dependent library at the specified index. + const char *getDependentLibrary(uint32_t index) { + if (index < _deplibs.size()) + return _deplibs[index]; + return NULL; + } + + /// getLinkerOptCount - Get the number of linker options + uint32_t getLinkerOptCount() { + return _linkeropts.size(); + } + + /// getLinkerOpt - Get the linker option at the specified index. + const char *getLinkerOpt(uint32_t index) { + if (index < _linkeropts.size()) + return _linkeropts[index]; + return NULL; + } + /// getLLVVMModule - Return the Module. llvm::Module *getLLVVMModule() { return _module.get(); } @@ -136,6 +165,10 @@ public: } private: + /// parseMetadata - Parse metadata from the module + // FIXME: it only parses "Linker Options" metadata at the moment + void parseMetadata(); + /// 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); @@ -189,8 +222,9 @@ private: 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 a MemoryBuffer from a memory range with an optional name. + static llvm::MemoryBuffer *makeBuffer(const void *mem, size_t length, + llvm::StringRef name = ""); }; #endif // LTO_MODULE_H diff --git a/include/llvm/LineEditor/LineEditor.h b/include/llvm/LineEditor/LineEditor.h new file mode 100644 index 0000000..42839ed --- /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/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include <stdio.h> +#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 4c1aaca..2b0604a 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 8183fa2..1603250 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" @@ -129,6 +129,7 @@ namespace { (void) llvm::createJumpThreadingPass(); (void) llvm::createUnifyFunctionExitNodesPass(); (void) llvm::createInstCountPass(); + (void) llvm::createConstantHoistingPass(); (void) llvm::createCodeGenPreparePass(); (void) llvm::createEarlyCSEPass(); (void) llvm::createGVNPass(); @@ -139,9 +140,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*)0); + (void) llvm::createPrintFunctionPass(*(llvm::raw_ostream*)0); + (void) llvm::createPrintBasicBlockPass(*(llvm::raw_ostream*)0); (void) llvm::createModuleDebugInfoPrinterPass(); (void) llvm::createPartialInliningPass(); (void) llvm::createLintPass(); @@ -154,6 +155,7 @@ namespace { (void) llvm::createSLPVectorizerPass(); (void) llvm::createBBVectorizePass(); (void) llvm::createPartiallyInlineLibCallsPass(); + (void) llvm::createScalarizerPass(); (void)new llvm::IntervalPartition(); (void)new llvm::FindUsedTypes(); diff --git a/include/llvm/Linker.h b/include/llvm/Linker/Linker.h index 4f37459..42b2cb3 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,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#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> @@ -30,7 +30,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 +52,8 @@ class Linker { private: Module *Composite; SmallPtrSet<StructType*, 32> IdentifiedStructTypes; + + bool SuppressWarnings; }; } // End llvm namespace diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index f946f41..82b65fd 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 7a99394..037a24f 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -82,7 +82,7 @@ namespace llvm { /// 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. + /// 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, @@ -101,10 +101,6 @@ namespace llvm { /// 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 "#" @@ -115,19 +111,17 @@ namespace llvm { /// 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 "." + /// 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. + const char *PrivateGlobalPrefix; // Defaults to "L" - /// 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 "" + /// 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. + const char *LinkerPrivateGlobalPrefix; // Defaults to "". /// InlineAsmStart/End - If these are nonempty, they contain a directive to /// emit before and after an inline assembly statement. @@ -198,20 +192,10 @@ namespace llvm { /// 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 @@ -266,13 +250,16 @@ namespace llvm { /// global as being a weak undefined symbol. const char *WeakRefDirective; // Defaults to NULL. - /// WeakDefDirective - This directive, if non-null, is used to declare a - /// global as being a weak defined symbol. - const char *WeakDefDirective; // Defaults to NULL. + /// True if we have a directive to declare a global as being a weak + /// defined symbol. + bool HasWeakDefDirective; // Defaults to false. - /// LinkOnceDirective - This directive, if non-null is used to declare a - /// global as being a weak defined symbol. This is used on cygwin/mingw. - const char *LinkOnceDirective; // Defaults to NULL. + /// 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. @@ -303,22 +290,37 @@ namespace llvm { /// 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; + /// UseParensForSymbolVariant - True if target uses parens to indicate the + /// symbol variant instead of @. For example, foo(plt) instead of foo@plt. + bool UseParensForSymbolVariant; // Defaults to false; + //===--- 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(); - // 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; @@ -371,7 +373,7 @@ namespace llvm { unsigned Encoding, MCStreamer &Streamer) const; - const MCExpr * + virtual const MCExpr * getExprForFDESymbol(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const; @@ -384,10 +386,6 @@ namespace llvm { return UsesELFSectionDirectiveForBSS; } - bool hasMicrosoftFastStdCallMangling() const { - return HasMicrosoftFastStdCallMangling; - } - bool needsDwarfSectionOffsetDirective() const { return NeedsDwarfSectionOffsetDirective; } @@ -414,9 +412,13 @@ namespace llvm { const char *getSeparatorString() const { return SeparatorString; } + + /// This indicates the column (zero-based) at which asm comments should be + /// printed. unsigned getCommentColumn() const { - return CommentColumn; + return 40; } + const char *getCommentString() const { return CommentString; } @@ -427,15 +429,16 @@ namespace llvm { const char *getDebugLabelSuffix() const { return DebugLabelSuffix; } - - const char *getGlobalPrefix() const { - return GlobalPrefix; - } const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } + bool hasLinkerPrivateGlobalPrefix() const { + return LinkerPrivateGlobalPrefix[0] != '\0'; + } const char *getLinkerPrivateGlobalPrefix() const { - return LinkerPrivateGlobalPrefix; + if (hasLinkerPrivateGlobalPrefix()) + return LinkerPrivateGlobalPrefix; + return getPrivateGlobalPrefix(); } const char *getInlineAsmStart() const { return InlineAsmStart; @@ -470,9 +473,6 @@ namespace llvm { const char *getAscizDirective() const { return AscizDirective; } - const char *getAlignDirective() const { - return AlignDirective; - } bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; } @@ -497,8 +497,11 @@ namespace llvm { bool hasIdentDirective() const { return HasIdentDirective; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } const char *getWeakRefDirective() const { return WeakRefDirective; } - const char *getWeakDefDirective() const { return WeakDefDirective; } - const char *getLinkOnceDirective() const { return LinkOnceDirective; } + bool hasWeakDefDirective() const { return HasWeakDefDirective; } + bool hasWeakDefCanBeHiddenDirective() const { + return HasWeakDefCanBeHiddenDirective; + } + bool hasLinkOnceDirective() const { return HasLinkOnceDirective; } MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;} MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { @@ -528,9 +531,15 @@ namespace llvm { 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); @@ -539,6 +548,20 @@ namespace llvm { 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; + } }; } diff --git a/include/llvm/MC/MCAsmInfoCOFF.h b/include/llvm/MC/MCAsmInfoCOFF.h index 7286151..56444f3 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/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 0cf2b1d..34b760c 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -15,17 +15,16 @@ #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> #include <vector> // FIXME: Shouldn't be needed. -namespace mcld { -class Layout; -} - namespace llvm { class raw_ostream; class MCAsmLayout; @@ -37,6 +36,7 @@ class MCFragment; class MCObjectWriter; class MCSection; class MCSectionData; +class MCSubtargetInfo; class MCSymbol; class MCSymbolData; class MCValue; @@ -44,7 +44,6 @@ class MCAsmBackend; class MCFragment : public ilist_node<MCFragment> { friend class MCAsmLayout; - friend class mcld::Layout; MCFragment(const MCFragment&) LLVM_DELETED_FUNCTION; void operator=(const MCFragment&) LLVM_DELETED_FUNCTION; @@ -53,16 +52,14 @@ public: enum FragmentType { FT_Align, FT_Data, + FT_Compressed, FT_CompactEncodedInst, FT_Fill, FT_Relaxable, FT_Org, FT_Dwarf, FT_DwarfFrame, - FT_LEB, - FT_Region, - FT_Reloc, - FT_Target + FT_LEB }; private: @@ -72,8 +69,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 @@ -151,11 +147,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; } @@ -166,6 +162,7 @@ public: return false; case MCFragment::FT_Relaxable: case MCFragment::FT_CompactEncodedInst: + case MCFragment::FT_Compressed: case MCFragment::FT_Data: return true; } @@ -176,7 +173,7 @@ public: /// data and also have fixups registered. /// class MCEncodedFragmentWithFixups : public MCEncodedFragment { - virtual void anchor(); + void anchor() override; public: MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, @@ -200,14 +197,15 @@ public: static bool classof(const MCFragment *F) { MCFragment::FragmentType Kind = F->getKind(); - return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data; + return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data || + Kind == MCFragment::FT_Compressed; } }; /// 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; @@ -219,6 +217,11 @@ class MCDataFragment : public MCEncodedFragmentWithFixups { /// Fixups - The list of fixups in this fragment. SmallVector<MCFixup, 4> Fixups; +protected: + MCDataFragment(MCFragment::FragmentType FType, MCSectionData *SD = 0) + : MCEncodedFragmentWithFixups(FType, SD), HasInstructions(false), + AlignToBundleEnd(false) {} + public: MCDataFragment(MCSectionData *SD = 0) : MCEncodedFragmentWithFixups(FT_Data, SD), @@ -226,41 +229,54 @@ public: { } - 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; + return F->getKind() == MCFragment::FT_Data || + F->getKind() == MCFragment::FT_Compressed; } }; +class MCCompressedFragment: public MCDataFragment { + mutable SmallVector<char, 32> CompressedContents; +public: + MCCompressedFragment(MCSectionData *SD = nullptr) + : MCDataFragment(FT_Compressed, SD) {} + const SmallVectorImpl<char> &getCompressedContents() const; + using MCDataFragment::getContents; + SmallVectorImpl<char> &getContents() override; +}; + /// This is a compact (memory-size-wise) fragment for holding an encoded /// instruction (non-relaxable) that has no fixups registered. When applicable, /// it can be used instead of MCDataFragment and lead to lower memory /// 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; @@ -272,15 +288,15 @@ public: { } - 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; @@ -291,11 +307,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; @@ -303,31 +324,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 = 0) + : 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; @@ -836,6 +861,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; @@ -846,7 +880,7 @@ private: MCCodeEmitter &Emitter; - MCObjectWriter *Writer; + MCObjectWriter &Writer; raw_ostream &OS; @@ -898,6 +932,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. @@ -944,8 +984,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 @@ -979,6 +1019,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. /// @@ -1003,9 +1053,7 @@ public: MCCodeEmitter &getEmitter() const { return Emitter; } - MCObjectWriter &getWriter() const { return *Writer; } - - void setWriter(MCObjectWriter &ObjectWriter); + MCObjectWriter &getWriter() const { return Writer; } /// Finish - Do final processing and write the object to the output stream. /// \p Writer is used for custom object writer (as the MCJIT does), @@ -1132,6 +1180,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 /// @{ @@ -1152,6 +1213,10 @@ public: return *Entry; } + bool hasSymbolData(const MCSymbol &Symbol) const { + return SymbolMap.lookup(&Symbol) != 0; + } + MCSymbolData &getSymbolData(const MCSymbol &Symbol) const { MCSymbolData *Entry = SymbolMap.lookup(&Symbol); assert(Entry && "Missing symbol data!"); diff --git a/include/llvm/MC/MCAtom.h b/include/llvm/MC/MCAtom.h index eab32d6..e9d0fba 100644 --- a/include/llvm/MC/MCAtom.h +++ b/include/llvm/MC/MCAtom.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/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index 9bfa08e..d3b5617 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 c8b6626..9091ed9 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -28,7 +28,7 @@ namespace llvm { class MCSection; class MCSymbol; class MCLabel; - class MCDwarfFile; + struct MCDwarfFile; class MCDwarfLoc; class MCObjectFileInfo; class MCRegisterInfo; @@ -70,6 +70,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 +90,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 +116,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; @@ -146,16 +152,8 @@ namespace llvm { /// 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; @@ -164,6 +162,9 @@ namespace llvm { 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, @@ -192,6 +193,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 +205,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 @@ -278,6 +283,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 +296,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, @@ -300,31 +306,38 @@ namespace llvm { 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()) + for (const auto &FileTable : MCDwarfLineTablesCUMap) + if (!FileTable.second.getMCDwarfFiles().empty()) return true; return false; } - const SmallVectorImpl<MCDwarfFile *> &getMCDwarfFiles(unsigned CUID = 0) { - return MCDwarfFilesCUMap[CUID]; + const std::map<unsigned, MCDwarfLineTable> &getMCDwarfLineTables() const { + return MCDwarfLineTablesCUMap; } - const SmallVectorImpl<StringRef> &getMCDwarfDirs(unsigned CUID = 0) { - return MCDwarfDirsCUMap[CUID]; + + MCDwarfLineTable &getMCDwarfLineTable(unsigned CUID) { + return MCDwarfLineTablesCUMap[CUID]; } - const DenseMap<const MCSection *, MCLineSection *> - &getMCLineSections() const { - return MCLineSections; + const MCDwarfLineTable &getMCDwarfLineTable(unsigned CUID) const { + auto I = MCDwarfLineTablesCUMap.find(CUID); + assert(I != MCDwarfLineTablesCUMap.end()); + return I->second; } - const std::vector<const MCSection *> &getMCLineSectionOrder() const { - return MCLineSectionOrder; + + const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles(unsigned CUID = 0) { + return getMCDwarfLineTable(CUID).getMCDwarfFiles(); } - void addMCLineSection(const MCSection *Sec, MCLineSection *Line) { - MCLineSections[Sec] = Line; - MCLineSectionOrder.push_back(Sec); + const SmallVectorImpl<std::string> &getMCDwarfDirs(unsigned CUID = 0) { + return getMCDwarfLineTable(CUID).getMCDwarfDirs(); + } + + 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 +345,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,7 +372,9 @@ namespace llvm { bool getGenDwarfForAssembly() { return GenDwarfForAssembly; } void setGenDwarfForAssembly(bool Value) { GenDwarfForAssembly = Value; } unsigned getGenDwarfFileNumber() { return GenDwarfFileNumber; } - unsigned nextGenDwarfFileNumber() { return ++GenDwarfFileNumber; } + void setGenDwarfFileNumber(unsigned FileNumber) { + GenDwarfFileNumber = FileNumber; + } const MCSection *getGenDwarfSection() { return GenDwarfSection; } void setGenDwarfSection(const MCSection *Sec) { GenDwarfSection = Sec; } MCSymbol *getGenDwarfSectionStartSym() { return GenDwarfSectionStartSym; } diff --git a/include/llvm/MC/MCDirectives.h b/include/llvm/MC/MCDirectives.h index 0461766..f9d66e0 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 83f26ef..d545fc7 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -11,8 +11,8 @@ #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 +56,9 @@ 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) + : GetOpInfo(0), SymbolLookUp(0), DisInfo(0), Ctx(0), STI(STI), + Symbolizer(), CommentStream(0) {} virtual ~MCDisassembler(); @@ -102,7 +101,7 @@ private: 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,14 +114,14 @@ 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); + void setSymbolizer(std::unique_ptr<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); + std::unique_ptr<MCRelocationInfo> &RelInfo); LLVMOpInfoCallback getLLVMOpInfoCallback() const { return GetOpInfo; } LLVMSymbolLookupCallback getLLVMSymbolLookupCallback() const { diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 65b920b..6e77c6c 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -15,12 +15,17 @@ #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; @@ -36,41 +41,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 { @@ -172,58 +151,107 @@ public: }; /// 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(MCStreamer *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(MCStreamer *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 +270,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 @@ -438,7 +466,7 @@ struct MCDwarfFrameInfo { MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), Function(0), Instructions(), PersonalityEncoding(), LsdaEncoding(0), CompactUnwindEncoding(0), - IsSignalFrame(false) {} + IsSignalFrame(false), IsSimple(false) {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *Personality; @@ -449,6 +477,7 @@ struct MCDwarfFrameInfo { unsigned LsdaEncoding; uint32_t CompactUnwindEncoding; bool IsSignalFrame; + bool IsSimple; }; class MCDwarfFrameEmitter { diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 92ad1b1..127f162 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -20,30 +20,10 @@ class MCAssembler; class MCFixup; class MCFragment; class MCObjectWriter; +class MCSectionData; class MCSymbol; 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 +52,9 @@ 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(unsigned Type) const; /// @name Accessors /// @{ @@ -107,16 +77,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 4e24dcf..ebd5d57 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -29,70 +29,68 @@ 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 EmitDebugLabel(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); + MCSymbolData &getOrCreateSymbolData(const MCSymbol *Symbol) override; - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); + void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; - virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment); + void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) 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 EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, + 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) override; - virtual void EmitFileDirective(StringRef Filename); + void EmitFileDirective(StringRef Filename) override; - virtual void EmitIdent(StringRef IdentString); + void EmitIdent(StringRef IdentString) override; - virtual void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned); + void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned) override; - virtual void Flush(); + void Flush() override; - virtual void FinishImpl(); + void FinishImpl() override; -private: - virtual void EmitInstToFragment(const MCInst &Inst); - virtual void EmitInstToData(const MCInst &Inst); + void EmitBundleAlignMode(unsigned AlignPow2) override; + void EmitBundleLock(bool AlignToEnd) override; + void EmitBundleUnlock() override; - virtual void EmitBundleAlignMode(unsigned AlignPow2); - virtual void EmitBundleLock(bool AlignToEnd); - virtual void EmitBundleUnlock(); +private: + void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override; + void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; void fixSymbolsInTLSFixups(const MCExpr *expr); @@ -107,13 +105,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 d0e1dac..5b82a58 100644 --- a/include/llvm/MC/MCELFSymbolFlags.h +++ b/include/llvm/MC/MCELFSymbolFlags.h @@ -21,10 +21,12 @@ 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. + ELF_Other_Shift = 16 // Shift value for llvm local flags, + // not part of the final object file }; enum ELFSymbolFlags { @@ -49,8 +51,7 @@ namespace llvm { 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_Other_ThumbFunc = (1 << ELF_Other_Shift) }; } // end namespace llvm diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index 5d55974..0033a54 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -15,6 +15,7 @@ #include "llvm/Support/DataTypes.h" namespace llvm { +class MCAsmInfo; class MCAsmLayout; class MCAssembler; class MCContext; @@ -90,7 +91,7 @@ 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; /// FindAssociatedSection - Find the "associated section" for this expression, /// which is currently defined as the absolute section for constants, or @@ -157,19 +158,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 @@ -258,9 +264,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 +292,7 @@ public: /// @{ const MCSymbol &getSymbol() const { return *Symbol; } + const MCAsmInfo &getMCAsmInfo() const { return *MAI; } VariantKind getKind() const { return Kind; } diff --git a/include/llvm/MC/MCExternalSymbolizer.h b/include/llvm/MC/MCExternalSymbolizer.h index c942adc..cab9152 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 { @@ -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 16e9eb7..e6d675f 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" @@ -87,6 +88,8 @@ public: MCFixupKind getKind() const { return MCFixupKind(Kind); } + MCSymbolRefExpr::VariantKind getAccessVariant() const; + uint32_t getOffset() const { return Offset; } void setOffset(uint32_t Value) { Offset = Value; } diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h index 17bfd15..e921f76 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/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h new file mode 100644 index 0000000..3b0d933 --- /dev/null +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -0,0 +1,194 @@ +//===- 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 { + std::string Buffer; + raw_string_ostream OutStream(Buffer); + 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 3ba6e65..e7d5bbd 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 /// @{ @@ -121,7 +120,7 @@ public: /// @name Lifetime management Methods /// @{ - virtual void reset(); + void reset() override; /// @} @@ -154,9 +153,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 +230,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 +248,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/MCModuleYAML.h b/include/llvm/MC/MCModuleYAML.h index 281e3d8..c4ae829 100644 --- a/include/llvm/MC/MCModuleYAML.h +++ b/include/llvm/MC/MCModuleYAML.h @@ -16,7 +16,6 @@ #ifndef LLVM_MC_MCMODULEYAML_H #define LLVM_MC_MCMODULEYAML_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCModule.h" #include "llvm/Support/raw_ostream.h" @@ -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/MCObjectDisassembler.h b/include/llvm/MC/MCObjectDisassembler.h index 0d87d33..5b935db 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 c48dcb0..1c5c19e 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -39,6 +39,11 @@ protected: /// 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. unsigned PersonalityEncoding; @@ -129,6 +134,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; @@ -201,6 +208,9 @@ public: bool getSupportsWeakOmittedEHFrame() const { return SupportsWeakOmittedEHFrame; } + bool getSupportsCompactUnwindWithoutEHFrame() const { + return SupportsCompactUnwindWithoutEHFrame; + } bool getCommDirectiveSupportsAlignment() const { return CommDirectiveSupportsAlignment; } @@ -262,6 +272,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 +293,10 @@ public: return DwarfAddrSection; } + const MCSection *getCOFFDebugSymbolsSection() const { + return COFFDebugSymbolsSection; + } + const MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; } @@ -353,8 +369,16 @@ 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; diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 5667544..a42b7a05 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; @@ -35,22 +36,23 @@ class MCObjectStreamer : public MCStreamer { MCSectionData *CurSectionData; MCSectionData::iterator CurInsertionPoint; - 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; } protected: MCSectionData *getCurrentSectionData() const { @@ -76,47 +78,45 @@ public: /// @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 EmitDebugLabel(MCSymbol *Symbol) override; + void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; + void EmitValueImpl(const MCExpr *Value, unsigned Size) 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) override; + void EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, + const MCSymbol *Label) override; + 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; }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectSymbolizer.h b/include/llvm/MC/MCObjectSymbolizer.h index 64b932e..f75b7f5 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 4939a3f..55c828c 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 1b3ab57..f36011c 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -36,7 +36,7 @@ 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); @@ -44,9 +44,11 @@ public: void setBuffer(const MemoryBuffer *buf, const char *ptr = NULL); - 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 53b380f..e3d4181 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 1d15534..0389caa 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -118,6 +118,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/MCSchedule.h b/include/llvm/MC/MCSchedule.h index 6881e1d..d1ab411 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,7 +154,7 @@ 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; diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index 944bfcb..de2678a 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -31,8 +31,7 @@ namespace llvm { enum SectionVariant { SV_COFF = 0, SV_ELF, - SV_MachO, - SV_LDContext + SV_MachO }; private: diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 45c84ae..aa02d9a 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -69,10 +69,10 @@ 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; } @@ -81,11 +81,10 @@ class MCSymbol; void setSelection(int Selection, const MCSectionCOFF *Assoc = 0) 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 5979915..89c02cc 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.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" @@ -59,9 +60,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 +75,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 d7e88ea..a5a2089 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 0b1fe6e..8ee60c1 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,70 @@ 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(); }; // 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); + + 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,7 +147,7 @@ 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; @@ -135,10 +175,8 @@ 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); @@ -161,15 +199,18 @@ protected: public: virtual ~MCStreamer(); + 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(); } @@ -197,6 +238,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 +256,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() {} @@ -303,22 +354,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,6 +371,8 @@ 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); @@ -350,12 +389,16 @@ 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 MCSymbolData &getOrCreateSymbolData(const MCSymbol *Symbol); /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. /// @@ -368,7 +411,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. /// @@ -407,9 +450,14 @@ public: /// EndCOFFSymbolDef - Marks the end of the symbol definition. virtual void EndCOFFSymbolDef() = 0; + /// 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. @@ -419,6 +467,10 @@ public: /// virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) = 0; + /// \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. /// /// @param Symbol - The common symbol to emit. @@ -587,8 +639,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. @@ -605,12 +658,14 @@ public: 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); @@ -647,7 +702,7 @@ public: /// 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) = 0; /// \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 @@ -698,12 +753,11 @@ 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 useCFI, + 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,7 +765,8 @@ 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); + bool RelaxAll = false, + bool LabelSections = false); /// createWinCOFFStreamer - Create a machine code streamer which will /// generate Microsoft COFF format object files. @@ -723,18 +778,10 @@ MCStreamer *createWinCOFFStreamer(MCContext &Ctx, MCAsmBackend &TAB, /// 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/MCSymbol.h b/include/llvm/MC/MCSymbol.h index fe92755..ea14da1 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -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 e42a214..cbbb591 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 d132a73..0073136 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -10,8 +10,8 @@ #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" namespace llvm { class MCStreamer; diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index a4e7301..f4ea511 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -24,9 +24,16 @@ 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 +44,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; } @@ -53,12 +62,13 @@ public: void dump() const; static MCValue get(const MCSymbolRefExpr *SymA, const MCSymbolRefExpr *SymB=0, - int64_t Val = 0) { + 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; } @@ -67,6 +77,7 @@ public: R.Cst = Val; R.SymA = 0; R.SymB = 0; + R.RefKind = 0; return R; } diff --git a/include/llvm/MC/MachineLocation.h b/include/llvm/MC/MachineLocation.h index b3fbee7..2a18615 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/Object/Archive.h b/include/llvm/Object/Archive.h index 1cba519..4fae76f 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" @@ -90,8 +91,13 @@ public: error_code getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, bool FullPath = false) const; + error_code getMemoryBuffer(std::unique_ptr<MemoryBuffer> &Result, + bool FullPath = false) const; - error_code getAsBinary(OwningPtr<Binary> &Result) const; + error_code getAsBinary(OwningPtr<Binary> &Result, + LLVMContext *Context = 0) const; + error_code getAsBinary(std::unique_ptr<Binary> &Result, + LLVMContext *Context = 0) const; }; class child_iterator { @@ -163,6 +169,7 @@ public: }; Archive(MemoryBuffer *source, error_code &ec); + static ErrorOr<Archive *> create(MemoryBuffer *Source); enum Kind { K_GNU, @@ -174,11 +181,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 a3f5625..b10e40a 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; @@ -30,15 +32,18 @@ private: Binary(const Binary &other) LLVM_DELETED_FUNCTION; unsigned int TypeID; + bool BufferOwned; protected: MemoryBuffer *Data; - Binary(unsigned int Type, MemoryBuffer *Source); + Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned = true); enum { ID_Archive, ID_MachOUniversalBinary, + ID_IR, // LLVM IR + // Object and children. ID_StartObjects, ID_COFF, @@ -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); @@ -113,13 +126,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); +/// to the Binary if successful. If an error is returned, +/// Source is destroyed by createBinary before returning. +ErrorOr<Binary *> createBinary(MemoryBuffer *Source, LLVMContext *Context = 0); +ErrorOr<Binary *> createBinary(StringRef Path); } } diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index e05ae6c..6e05c2d 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,6 +265,22 @@ 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; @@ -220,104 +297,143 @@ 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; + 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(); + error_code initSymbolTablePtr(); + error_code initImportTablePtr(); + 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; + error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override; + error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; + error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; + void moveSectionNext(DataRefImpl &Sec) const override; + error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const override; + error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const override; + error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + 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; + bool section_rel_empty(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; + error_code + getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + error_code + getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + + error_code getLibraryNext(DataRefImpl LibData, + LibraryRef &Result) const override; + 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(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); + 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; + export_directory_iterator export_directory_begin() const; + export_directory_iterator export_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 getPE32PlusHeader(const pe32plus_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; @@ -325,7 +441,7 @@ public: 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); + Res = reinterpret_cast<const T *>(s); return ec; } error_code getSymbolName(const coff_symbol *symbol, StringRef &Res) const; @@ -335,24 +451,23 @@ public: error_code getSectionContents(const coff_section *Sec, ArrayRef<uint8_t> &Res) const; + error_code getVaPtr(uint64_t VA, uintptr_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; - 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(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; + void moveNext(); error_code getName(StringRef &Result) const; error_code @@ -362,7 +477,31 @@ public: 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(0) {} + 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(); + + error_code getDllName(StringRef &Result) const; + error_code getOrdinalBase(uint32_t &Result) const; + error_code getOrdinal(uint32_t &Result) const; + error_code getExportRVA(uint32_t &Result) const; + 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 3fa3ec6..b5f9ccc 100644 --- a/include/llvm/Object/COFFYAML.h +++ b/include/llvm/Object/COFFYAML.h @@ -14,6 +14,7 @@ #ifndef LLVM_OBJECT_COFFYAML_H #define LLVM_OBJECT_COFFYAML_H +#include "llvm/ADT/Optional.h" #include "llvm/Object/YAML.h" #include "llvm/Support/COFF.h" @@ -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; @@ -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); }; @@ -120,6 +145,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 6c000bb..824e06e 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -33,8 +33,6 @@ #include <limits> #include <utility> -#include <ctype.h> - namespace llvm { namespace object { @@ -53,8 +51,8 @@ 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> diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 962a3e2..2958067 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,52 @@ 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 - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const; + void moveSymbolNext(DataRefImpl &Symb) const override; + error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override; + error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; + error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const override; + error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; + + error_code getLibraryNext(DataRefImpl Data, + LibraryRef &Result) const override; + error_code getLibraryPath(DataRefImpl Data, StringRef &Res) const override; + + void moveSectionNext(DataRefImpl &Sec) const override; + error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const override; + error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const override; + 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; + bool section_rel_empty(DataRefImpl Sec) const override; + section_iterator getRelocatedSection(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; + error_code getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + error_code getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; uint64_t getROffset(DataRefImpl Rel) const; StringRef getRelocationTypeName(uint32_t Type) const; @@ -165,31 +165,31 @@ protected: bool isDyldELFObject; public: - ELFObjectFile(MemoryBuffer *Object, error_code &ec); + ELFObjectFile(MemoryBuffer *Object, error_code &EC, bool BufferOwned = true); 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; - 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; const ELFFile<ELFT> *getELFFile() const { return &EF; } @@ -208,10 +208,8 @@ 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> @@ -219,7 +217,7 @@ 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; } @@ -233,49 +231,15 @@ error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef, 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 { - 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; - case ELF::SHN_ABS: - 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; - } -} - -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: @@ -285,38 +249,21 @@ error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, Result = ESym->st_value; return object_error::success; default: - ESec = EF.getSection(ESym); + break; } - 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; + const Elf_Ehdr *Header = EF.getHeader(); + Result = ESym->st_value; - // Clear the ARM/Thumb indicator flag. - if (EF.getHeader()->e_machine == ELF::EM_ARM) - Result &= ~1; + // Clear the ARM/Thumb indicator flag. + if (EF.getHeader()->e_machine == ELF::EM_ARM && + ESym->getType() == ELF::STT_FUNC) + Result &= ~1; - if (IsRelocatable && ESec != 0) - Result += ESec->sh_addr; - return object_error::success; - default: - Result = UnknownAddressOrSize; - return object_error::success; - } + if (Header->e_type == ELF::ET_REL) + Result += EF.getSection(ESym)->sh_addr; + + return object_error::success; } template <class ELFT> @@ -368,11 +315,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 +331,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,10 +341,7 @@ 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> @@ -406,7 +350,7 @@ error_code ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb, 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,18 +360,8 @@ 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> @@ -435,7 +369,7 @@ 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; } @@ -563,15 +497,21 @@ ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const { } template <class ELFT> +bool ELFObjectFile<ELFT>::section_rel_empty(DataRefImpl Sec) const { + const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p); + return S->sh_size == 0; +} + +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 +519,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 +541,7 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { } } if (!symbolIdx) - return end_symbols(); + return symbol_end(); const Elf_Shdr *SymSec = EF.getSection(sec->sh_link); @@ -626,6 +563,9 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { template <class ELFT> error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, uint64_t &Result) const { + assert((EF.getHeader()->e_type == ELF::ET_EXEC || + EF.getHeader()->e_type == ELF::ET_DYN) && + "Only executable and shared objects files have relocation addresses"); Result = getROffset(Rel); return object_error::success; } @@ -633,6 +573,8 @@ error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, template <class ELFT> 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; } @@ -743,7 +685,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 +725,7 @@ error_code ELFObjectFile<ELFT>::getRelocationValueString( } case ELF::EM_ARM: case ELF::EM_HEXAGON: + case ELF::EM_MIPS: res = *SymName; break; default: @@ -812,40 +755,41 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const { } template <class ELFT> -ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) +ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec, + bool BufferOwned) : ObjectFile(getELFType(static_cast<endianness>(ELFT::TargetEndianness) == support::little, ELFT::Is64Bits), - Object), + Object, BufferOwned), EF(Object, 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 +807,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(); @@ -896,7 +840,7 @@ error_code ELFObjectFile<ELFT>::getLibraryPath(DataRefImpl Data, } 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 +866,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 +884,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"; } @@ -967,6 +918,13 @@ unsigned ELFObjectFile<ELFT>::getArch() const { : 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 +932,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 error_code getELFRelocationAddend(const RelocationRef R, + int64_t &Addend) { const ObjectFile *Obj = R.getObjectFile(); DataRefImpl DRI = R.getRawDataRefImpl(); // Little-endian 32-bit @@ -997,12 +955,30 @@ 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 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 fca965f..1eba660 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -37,6 +37,8 @@ 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) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) @@ -50,6 +52,7 @@ struct FileHeader { ELF_ELFOSABI OSABI; ELF_ET Type; ELF_EM Machine; + ELF_EF Flags; llvm::yaml::Hex64 Entry; }; struct Symbol { @@ -118,6 +121,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); }; diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index 8b0570b..779c747 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -41,10 +41,10 @@ inline error_code make_error_code(object_error e) { } // end namespace object. -template <> struct is_error_code_enum<object::object_error> : true_type { }; +template <> struct is_error_code_enum<object::object_error> : std::true_type {}; -template <> struct is_error_code_enum<object::object_error::Impl> : true_type { -}; +template <> +struct is_error_code_enum<object::object_error::Impl> : std::true_type {}; } // end namespace llvm. diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h new file mode 100644 index 0000000..78f5b2b --- /dev/null +++ b/include/llvm/Object/IRObjectFile.h @@ -0,0 +1,46 @@ +//===- 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; + +public: + IRObjectFile(MemoryBuffer *Object, error_code &EC, LLVMContext &Context, + bool BufferOwned); + void moveSymbolNext(DataRefImpl &Symb) const override; + 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; + + static inline bool classof(const Binary *v) { + return v->isIR(); + } +}; +} +} + +#endif diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 100613a..f242611 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -38,7 +38,7 @@ public: 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; @@ -57,76 +57,73 @@ public: }; 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; + error_code &EC, bool BufferOwned = true); + + void moveSymbolNext(DataRefImpl &Symb) const override; + error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const override; + error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; + error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const override; + error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const override; + uint32_t getSymbolFlags(DataRefImpl Symb) const override; + error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const override; + + void moveSectionNext(DataRefImpl &Sec) const override; + error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; + error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const override; + error_code isSectionText(DataRefImpl Sec, bool &Res) const override; + error_code isSectionData(DataRefImpl Sec, bool &Res) const override; + error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; + error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const override; + error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; + error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; + error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const override; + 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; + bool section_rel_empty(DataRefImpl Sec) const override; + + void moveRelocationNext(DataRefImpl &Rel) const override; + error_code getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const override; + error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const override; + symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; + error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const override; + error_code getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + error_code getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const override; + error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const override; + + error_code getLibraryNext(DataRefImpl LibData, + LibraryRef &Res) const override; + error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const override; // 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; + section_iterator section_begin() const override; + section_iterator section_end() const override; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; + library_iterator needed_library_begin() const override; + library_iterator needed_library_end() const override; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; + uint8_t getBytesInAddress() const override; - virtual uint8_t getBytesInAddress() const; + StringRef getFileFormatName() const override; + unsigned getArch() const override; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; - - 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 +176,8 @@ 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::any_relocation_info getRelocation(DataRefImpl Rel) const; MachO::data_in_code_entry getDice(DataRefImpl Rel) const; @@ -223,13 +222,10 @@ 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 diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index c5d1359..9b1afd2 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -14,10 +14,10 @@ #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/Support/ErrorOr.h" #include "llvm/Support/MachO.h" namespace llvm { @@ -52,7 +52,7 @@ public: ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } uint32_t getCPUType() const { return Header.cputype; } - error_code getAsObjectFile(OwningPtr<ObjectFile> &Result) const; + error_code getAsObjectFile(std::unique_ptr<ObjectFile> &Result) const; }; class object_iterator { @@ -77,6 +77,7 @@ public: }; MachOUniversalBinary(MemoryBuffer *Source, error_code &ec); + static ErrorOr<MachOUniversalBinary*> create(MemoryBuffer *Source); object_iterator begin_objects() const { return ObjectForArch(this, 0); @@ -93,7 +94,7 @@ public: } error_code getObjectForArch(Triple::ArchType Arch, - OwningPtr<ObjectFile> &Result) const; + std::unique_ptr<ObjectFile> &Result) const; }; } diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 9aea639..8298b63 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. @@ -100,7 +44,7 @@ public: 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; @@ -143,9 +87,10 @@ public: 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; @@ -166,8 +111,13 @@ public: error_code containsSymbol(SymbolRef S, bool &Result) const; - relocation_iterator begin_relocations() const; - relocation_iterator end_relocations() const; + relocation_iterator relocation_begin() const; + relocation_iterator relocation_end() const; + typedef iterator_range<relocation_iterator> relocation_iterator_range; + relocation_iterator_range relocations() const { + return relocation_iterator_range(relocation_begin(), relocation_end()); + } + bool relocation_empty() const; section_iterator getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; @@ -175,13 +125,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,25 +140,8 @@ 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; /// Returns the symbol virtual address (i.e. address at which it will be /// mapped). @@ -221,17 +152,29 @@ public: 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; - /// @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; - /// @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 @@ -258,18 +201,16 @@ public: }; 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, MemoryBuffer *Source, bool BufferOwned = true); const uint8_t *base() const { return reinterpret_cast<const uint8_t *>(Data->getBufferStart()); @@ -284,23 +225,19 @@ 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; + error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; 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; // Same as above for SectionRef. friend class SectionRef; - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const = 0; + virtual void moveSectionNext(DataRefImpl &Sec) 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; @@ -319,12 +256,12 @@ protected: 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 bool section_rel_empty(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 void moveRelocationNext(DataRefImpl &Rel) const = 0; virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const =0; virtual error_code getRelocationOffset(DataRefImpl Rel, @@ -347,18 +284,21 @@ protected: virtual 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. @@ -376,74 +316,95 @@ public: /// @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(MemoryBuffer *Object, + bool BufferOwned, + sys::fs::file_magic Type); + static ErrorOr<ObjectFile *> createObjectFile(MemoryBuffer *Object) { + return createObjectFile(Object, true, 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(MemoryBuffer *Object, + bool BufferOwned = true); + static ErrorOr<ObjectFile *> createELFObjectFile(MemoryBuffer *Object, + bool BufferOwned = true); + static ErrorOr<ObjectFile *> createMachOObjectFile(MemoryBuffer *Object, + bool BufferOwned = true); }; // 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; -} - -inline bool SymbolRef::operator<(const SymbolRef &Other) const { - return SymbolPimpl < Other.SymbolPimpl; -} - -inline error_code SymbolRef::getNext(SymbolRef &Result) const { - return OwningObject->getSymbolNext(SymbolPimpl, Result); -} + : BasicSymbolRef(SymbolP, Owner) {} inline error_code SymbolRef::getName(StringRef &Result) const { - return OwningObject->getSymbolName(SymbolPimpl, Result); + return getObject()->getSymbolName(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getAddress(uint64_t &Result) const { - return OwningObject->getSymbolAddress(SymbolPimpl, Result); + return getObject()->getSymbolAddress(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getFileOffset(uint64_t &Result) const { - return OwningObject->getSymbolFileOffset(SymbolPimpl, Result); + uint64_t Address; + if (error_code EC = getAddress(Address)) + return EC; + if (Address == UnknownAddressOrSize) { + Result = UnknownAddressOrSize; + return object_error::success; + } + + const ObjectFile *Obj = getObject(); + section_iterator SecI(Obj->section_begin()); + if (error_code EC = getSection(SecI)) + return EC; + + if (SecI == Obj->section_end()) { + Result = UnknownAddressOrSize; + return object_error::success; + } + + uint64_t SectionAddress; + if (error_code EC = SecI->getAddress(SectionAddress)) + return EC; + + uint64_t OffsetInSection = Address - SectionAddress; + + StringRef SecContents; + if (error_code EC = SecI->getContents(SecContents)) + return EC; + + // FIXME: this is a hack. + uint64_t SectionOffset = (uint64_t)SecContents.data() - (uint64_t)Obj->base(); + + Result = SectionOffset + OffsetInSection; + return object_error::success; } inline error_code SymbolRef::getAlignment(uint32_t &Result) const { - return OwningObject->getSymbolAlignment(SymbolPimpl, Result); + return getObject()->getSymbolAlignment(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getSize(uint64_t &Result) const { - return OwningObject->getSymbolSize(SymbolPimpl, Result); -} - -inline error_code SymbolRef::getFlags(uint32_t &Result) const { - return OwningObject->getSymbolFlags(SymbolPimpl, Result); + return getObject()->getSymbolSize(getRawDataRefImpl(), Result); } inline error_code SymbolRef::getSection(section_iterator &Result) const { - return OwningObject->getSymbolSection(SymbolPimpl, Result); + return getObject()->getSymbolSection(getRawDataRefImpl(), 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); + return getObject()->getSymbolType(getRawDataRefImpl(), Result); } -inline DataRefImpl SymbolRef::getRawDataRefImpl() const { - return SymbolPimpl; +inline const ObjectFile *SymbolRef::getObject() const { + const SymbolicFile *O = BasicSymbolRef::getObject(); + return cast<ObjectFile>(O); } @@ -457,12 +418,16 @@ 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 { @@ -514,18 +479,22 @@ inline error_code SectionRef::isReadOnlyData(bool &Result) const { } inline error_code SectionRef::containsSymbol(SymbolRef S, bool &Result) const { - return OwningObject->sectionContainsSymbol(SectionPimpl, S.SymbolPimpl, - Result); + 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); } +inline bool SectionRef::relocation_empty() const { + return OwningObject->section_rel_empty(SectionPimpl); +} + inline section_iterator SectionRef::getRelocatedSection() const { return OwningObject->getRelocatedSection(SectionPimpl); } @@ -544,8 +513,8 @@ 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 { diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 97912fe..a3aaf17 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(); @@ -239,6 +277,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 +317,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 0000000..bead2c3 --- /dev/null +++ b/include/llvm/Object/SymbolicFile.h @@ -0,0 +1,194 @@ +//===- 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_FormatSpecific = 1U << 5 // Specific to the object file format + // (e.g. section symbols) + }; + + BasicSymbolRef() : OwningObject(NULL) { } + BasicSymbolRef(DataRefImpl SymbolP, const SymbolicFile *Owner); + + bool operator==(const BasicSymbolRef &Other) const; + bool operator<(const BasicSymbolRef &Other) const; + + void moveNext(); + + 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, MemoryBuffer *Source, bool BufferOwned); + + // virtual interface. + virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; + + virtual 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(); + } + + // construction aux. + static ErrorOr<SymbolicFile *> createIRObjectFile(MemoryBuffer *Object, + LLVMContext &Context, + bool BufferOwned = true); + + static ErrorOr<SymbolicFile *> createSymbolicFile(MemoryBuffer *Object, + bool BufferOwned, + sys::fs::file_magic Type, + LLVMContext *Context); + + static ErrorOr<SymbolicFile *> createSymbolicFile(MemoryBuffer *Object) { + return createSymbolicFile(Object, true, sys::fs::file_magic::unknown, 0); + } + 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 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/ArgList.h b/include/llvm/Option/ArgList.h index 06ba679..98ba6ec 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -307,11 +307,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 +323,7 @@ public: unsigned MakeIndex(StringRef String0) const; unsigned MakeIndex(StringRef String0, StringRef String1) const; - virtual const char *MakeArgString(StringRef Str) const; + const char *MakeArgString(StringRef Str) const override; /// @} }; @@ -341,11 +341,11 @@ public: 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(); } @@ -362,7 +362,7 @@ public: SynthesizedArgs.push_back(A); } - virtual const char *MakeArgString(StringRef Str) const; + 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/Pass.h b/include/llvm/Pass.h index 35ec022..ff700cf 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -235,17 +235,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 +268,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 +295,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 +331,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 +352,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/PassRegistry.h b/include/llvm/PassRegistry.h index f49c953..756b1b8 100644 --- a/include/llvm/PassRegistry.h +++ b/include/llvm/PassRegistry.h @@ -17,9 +17,9 @@ #ifndef LLVM_PASSREGISTRY_H #define LLVM_PASSREGISTRY_H +#include "llvm-c/Core.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CBindingWrapping.h" -#include "llvm-c/Core.h" namespace llvm { diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h index ccc7934..baee77f 100644 --- a/include/llvm/PassSupport.h +++ b/include/llvm/PassSupport.h @@ -30,6 +30,7 @@ namespace llvm { +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 @@ -39,6 +40,7 @@ namespace llvm { class PassInfo { public: typedef Pass* (*NormalCtor_t)(); + typedef Pass *(*TargetMachineCtor_t)(TargetMachine *); private: const char *const PassName; // Nice name for Pass @@ -50,22 +52,26 @@ private: 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) + NormalCtor_t normal, bool isCFGOnly, bool is_analysis, + TargetMachineCtor_t machine = NULL) : PassName(name), PassArgument(arg), PassID(pi), IsCFGOnlyPass(isCFGOnly), - IsAnalysis(is_analysis), IsAnalysisGroup(false), NormalCtor(normal) { } + 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(0) { } + IsAnalysis(false), IsAnalysisGroup(true), NormalCtor(0), + TargetMachineCtor(0) {} /// getPassName - Return the friendly name for the pass, never returns null /// @@ -107,6 +113,16 @@ public: 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; @@ -182,6 +198,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 diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h new file mode 100644 index 0000000..d8f3ca6 --- /dev/null +++ b/include/llvm/ProfileData/InstrProf.h @@ -0,0 +1,56 @@ +//=-- 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 "llvm/Support/system_error.h" + +namespace llvm { + +const error_category &instrprof_category(); + +struct instrprof_error { + enum ErrorType { + success = 0, + eof, + bad_magic, + bad_header, + unsupported_version, + too_large, + truncated, + malformed, + unknown_function, + hash_mismatch, + count_mismatch, + counter_overflow + }; + ErrorType V; + + instrprof_error(ErrorType V) : V(V) {} + operator ErrorType() const { return V; } +}; + +inline error_code make_error_code(instrprof_error E) { + return error_code(static_cast<int>(E), instrprof_category()); +} + +template <> struct is_error_code_enum<instrprof_error> : std::true_type {}; +template <> struct is_error_code_enum<instrprof_error::ErrorType> + : std::true_type {}; + +} // end namespace llvm + +#endif // LLVM_PROFILEDATA_INSTRPROF_H_ diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h new file mode 100644 index 0000000..2c070b9 --- /dev/null +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -0,0 +1,196 @@ +//=-- 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/ProfileData/InstrProf.h" +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Endian.h" + +#include <iterator> + +namespace llvm { + +class InstrProfReader; + +/// Profiling information for a single function. +struct InstrProfRecord { + 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 { + error_code LastError; +public: + InstrProfReader() : LastError(instrprof_error::success) {} + virtual ~InstrProfReader() {} + + /// Read the header. Required before reading first record. + virtual error_code readHeader() = 0; + /// Read a single record. + virtual error_code readNextRecord(InstrProfRecord &Record) = 0; + /// Iterator over profile data. + InstrProfIterator begin() { return InstrProfIterator(this); } + InstrProfIterator end() { return InstrProfIterator(); } + +protected: + /// Set the current error_code and return same. + error_code error(error_code EC) { + LastError = EC; + return EC; + } + + /// Clear the current error code and return a successful one. + 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. + error_code getError() { return LastError; } + + /// Factory method to create an appropriately typed reader for the given + /// instrprof file. + static 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. + error_code readHeader() override { return success(); } + /// Read a single record. + 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; + + RawInstrProfReader(const TextInstrProfReader &) LLVM_DELETED_FUNCTION; + RawInstrProfReader &operator=(const TextInstrProfReader &) + LLVM_DELETED_FUNCTION; +public: + RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) + : DataBuffer(std::move(DataBuffer)) { } + + static bool hasFormat(const MemoryBuffer &DataBuffer); + error_code readHeader() override; + error_code readNextRecord(InstrProfRecord &Record) override; + +private: + error_code readHeader(const RawHeader &Header); + template <class IntT> + IntT swap(IntT Int) const { + return ShouldSwapBytes ? sys::SwapByteOrder(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; + +} // 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 0000000..f818fa0 --- /dev/null +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -0,0 +1,49 @@ +//=-- 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. + error_code addFunctionCounts(StringRef FunctionName, uint64_t FunctionHash, + ArrayRef<uint64_t> Counters); + /// Ensure that all data is written to disk. + void write(raw_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 0000000..69732fc --- /dev/null +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -0,0 +1,189 @@ +//===-- 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_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_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 0000000..c7ac54a --- /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/AlignOf.h b/include/llvm/Support/AlignOf.h index bba3424..061d5ac 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 397f50f..0641322 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -17,14 +17,19 @@ #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; }; +template <typename T> struct ReferenceAdder { + typedef T &result; +}; +template <typename T> struct ReferenceAdder<T &> { + typedef T result; +}; class MallocAllocator { public: @@ -35,15 +40,15 @@ public: void *Allocate(size_t Size, size_t /*Alignment*/) { return malloc(Size); } - template <typename T> - T *Allocate() { return static_cast<T*>(malloc(sizeof(T))); } + template <typename T> T *Allocate() { + return static_cast<T *>(malloc(sizeof(T))); + } - template <typename T> - T *Allocate(size_t Num) { - return static_cast<T*>(malloc(sizeof(T)*Num)); + template <typename T> T *Allocate(size_t Num) { + return static_cast<T *>(malloc(sizeof(T) * Num)); } - void Deallocate(const void *Ptr) { free(const_cast<void*>(Ptr)); } + void Deallocate(const void *Ptr) { free(const_cast<void *>(Ptr)); } void PrintStats() const {} }; @@ -77,128 +82,224 @@ class MallocSlabAllocator : public SlabAllocator { MallocAllocator Allocator; public: - MallocSlabAllocator() : Allocator() { } + MallocSlabAllocator() : Allocator() {} virtual ~MallocSlabAllocator(); - virtual MemSlab *Allocate(size_t Size) LLVM_OVERRIDE; - virtual void Deallocate(MemSlab *Slab) LLVM_OVERRIDE; + MemSlab *Allocate(size_t Size) override; + void Deallocate(MemSlab *Slab) override; }; -/// 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; - - /// SlabSize - Allocate data into slabs of this size unless we get an - /// allocation above SizeThreshold. - size_t SlabSize; - - /// SizeThreshold - For any allocation larger than this threshold, we should - /// allocate a separate slab. - size_t SizeThreshold; - - /// \brief the default allocator used if one is not provided - MallocSlabAllocator DefaultSlabAllocator; +/// \brief Non-templated base class for the \c BumpPtrAllocatorImpl template. +class BumpPtrAllocatorBase { +public: + void Deallocate(const void * /*Ptr*/) {} + void PrintStats() const; - /// 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; + /// \brief Returns the total physical memory allocated by this allocator. + size_t getTotalMemory() const; - /// CurSlab - The slab that we are currently allocating into. - /// +protected: + /// \brief The slab that we are currently allocating into. MemSlab *CurSlab; - /// CurPtr - The current pointer into the current slab. This points to the - /// next free byte in the slab. - char *CurPtr; - - /// End - The end of the current slab. + /// \brief How many bytes we've allocated. /// - char *End; - - /// BytesAllocated - This field tracks how many bytes we've allocated, so - /// that we can compute how much space was wasted. + /// Used so that we can compute how much space was wasted. size_t BytesAllocated; - /// 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); - - /// StartNewSlab - Allocate a new slab and move the bump pointers over into - /// the new slab. Modifies CurPtr and End. - void StartNewSlab(); + BumpPtrAllocatorBase() : CurSlab(0), BytesAllocated(0) {} +}; - /// DeallocateSlabs - Deallocate all memory slabs after and including this - /// one. - void DeallocateSlabs(MemSlab *Slab); +/// \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. +template <size_t SlabSize = 4096, size_t SizeThreshold = SlabSize> +class BumpPtrAllocatorImpl : public BumpPtrAllocatorBase { + BumpPtrAllocatorImpl(const BumpPtrAllocatorImpl &) LLVM_DELETED_FUNCTION; + void operator=(const BumpPtrAllocatorImpl &) LLVM_DELETED_FUNCTION; - 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(); - - /// Reset - Deallocate all but the current slab and reset the current pointer + 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."); + + BumpPtrAllocatorImpl() + : Allocator(DefaultSlabAllocator), NumSlabs(0) {} + BumpPtrAllocatorImpl(SlabAllocator &Allocator) + : Allocator(Allocator), NumSlabs(0) {} + ~BumpPtrAllocatorImpl() { DeallocateSlabs(CurSlab); } + + /// \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(); + void Reset() { + if (!CurSlab) + return; + DeallocateSlabs(CurSlab->NextPtr); + CurSlab->NextPtr = 0; + CurPtr = (char *)(CurSlab + 1); + End = ((char *)CurSlab) + CurSlab->Size; + BytesAllocated = 0; + } - /// Allocate - Allocate space at the specified alignment. - /// - void *Allocate(size_t Size, size_t Alignment); + /// \brief Allocate space at the specified alignment. + void *Allocate(size_t Size, size_t Alignment) { + if (!CurSlab) // 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; + } - /// Allocate space, but do not construct, one object. - /// - template <typename T> - T *Allocate() { - return static_cast<T*>(Allocate(sizeof(T),AlignOf<T>::Alignment)); + // If Size is really big, allocate a separate slab for it. + size_t PaddedSize = Size + sizeof(MemSlab) + Alignment - 1; + if (PaddedSize > SizeThreshold) { + ++NumSlabs; + MemSlab *NewSlab = Allocator.Allocate(PaddedSize); + + // Put the new slab after the current slab, since we are not allocating + // into it. + NewSlab->NextPtr = CurSlab->NextPtr; + CurSlab->NextPtr = NewSlab; + + Ptr = alignPtr((char *)(NewSlab + 1), Alignment); + assert((uintptr_t)Ptr + Size <= (uintptr_t)NewSlab + NewSlab->Size); + __msan_allocated_memory(Ptr, Size); + return Ptr; + } + + // 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; } - /// 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 Allocate space for one object without constructing it. + template <typename T> T *Allocate() { + return static_cast<T *>(Allocate(sizeof(T), AlignOf<T>::Alignment)); } - /// Allocate space for a specific count of elements and with a specified - /// alignment. - template <typename T> - T *Allocate(size_t Num, size_t Alignment) { + /// \brief Allocate space for an array of objects without constructing them. + template <typename T> T *Allocate(size_t Num) { + return static_cast<T *>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment)); + } + + /// \brief Allocate space for an array of objects with the specified alignment + /// and without constructing them. + 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)); + size_t EltSize = (sizeof(T) + Alignment - 1) & (-Alignment); + return static_cast<T *>(Allocate(Num * EltSize, Alignment)); } - void Deallocate(const void * /*Ptr*/) {} + size_t GetNumSlabs() const { return NumSlabs; } - unsigned GetNumSlabs() const; +private: + /// \brief The default allocator used if one is not provided. + MallocSlabAllocator DefaultSlabAllocator; - void PrintStats() const; - - /// Compute the total physical memory allocated by this allocator. - size_t getTotalMemory() const; + /// \brief 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; + + /// \brief The current pointer into the current slab. + /// + /// This points to the next free byte in the slab. + char *CurPtr; + + /// \brief The end of the current slab. + char *End; + + /// \brief How many slabs we've allocated. + /// + /// Used to scale the size of each slab and reduce the number of allocations + /// for extremely heavy memory use scenarios. + size_t NumSlabs; + + /// \brief Allocate a new slab and move the bump pointers over into the new + /// slab, modifying CurPtr and End. + void StartNewSlab() { + ++NumSlabs; + // 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. + // FIXME: Currently, this count includes special slabs for objects above the + // size threshold. That will be fixed in a subsequent commit to make the + // growth even more predictable. + size_t AllocatedSlabSize = + SlabSize * ((size_t)1 << std::min<size_t>(30, NumSlabs / 128)); + + MemSlab *NewSlab = Allocator.Allocate(AllocatedSlabSize); + NewSlab->NextPtr = CurSlab; + CurSlab = NewSlab; + CurPtr = (char *)(CurSlab + 1); + End = ((char *)CurSlab) + CurSlab->Size; + } + + /// \brief Deallocate all memory slabs after and including this one. + void DeallocateSlabs(MemSlab *Slab) { + while (Slab) { + MemSlab *NextSlab = Slab->NextPtr; +#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(Slab + 1, Slab->Size - sizeof(MemSlab)); + memset(Slab + 1, 0xCD, Slab->Size - sizeof(MemSlab)); +#endif + Allocator.Deallocate(Slab); + Slab = NextSlab; + --NumSlabs; + } + } + + 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(); - } + SpecificBumpPtrAllocator() : Allocator() {} + SpecificBumpPtrAllocator(SlabAllocator &allocator) : Allocator(allocator) {} + + ~SpecificBumpPtrAllocator() { DestroyAll(); } /// 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 @@ -206,27 +307,28 @@ public: 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>()); + char *End = Slab == Allocator.CurSlab ? Allocator.CurPtr + : (char *)Slab + Slab->Size; + for (char *Ptr = (char *)(Slab + 1); Ptr < End; Ptr += sizeof(T)) { + Ptr = alignPtr(Ptr, alignOf<T>()); if (Ptr + sizeof(T) <= End) - reinterpret_cast<T*>(Ptr)->~T(); + reinterpret_cast<T *>(Ptr)->~T(); } Slab = Slab->NextPtr; } 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 <size_t SlabSize, size_t SizeThreshold> +void * +operator new(size_t Size, + llvm::BumpPtrAllocatorImpl<SlabSize, SizeThreshold> &Allocator) { struct S { char c; union { @@ -236,10 +338,12 @@ 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 <size_t SlabSize, size_t SizeThreshold> +void operator delete(void *, + llvm::BumpPtrAllocatorImpl<SlabSize, SizeThreshold> &) {} #endif // LLVM_SUPPORT_ALLOCATOR_H diff --git a/include/llvm/Support/ArrayRecycler.h b/include/llvm/Support/ArrayRecycler.h index c7e0cba..e974332 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; @@ -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 21879e7..dae520b 100644 --- a/include/llvm/Support/BlockFrequency.h +++ b/include/llvm/Support/BlockFrequency.h @@ -25,7 +25,6 @@ class BranchProbability; 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 @@ -35,9 +34,6 @@ class BlockFrequency { 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,6 +55,9 @@ public: BlockFrequency &operator+=(const BlockFrequency &Freq); const BlockFrequency operator+(const BlockFrequency &Freq) const; + /// \brief Shift block frequency to the right by count digits saturating to 1. + BlockFrequency &operator>>=(const unsigned count); + /// \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); @@ -78,12 +77,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/COFF.h b/include/llvm/Support/COFF.h index 9cc3989..dca7fc6 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, @@ -334,7 +341,7 @@ namespace COFF { uint32_t TotalSize; uint32_t PointerToLinenumber; uint32_t PointerToNextFunction; - uint8_t unused[2]; + char unused[2]; }; struct AuxiliarybfAndefSymbol { @@ -369,7 +376,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 +464,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 +479,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 +494,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,6 +545,8 @@ 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. @@ -611,6 +632,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 d70acbf..689f590 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,7 +243,8 @@ 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) { +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +cast_or_null(Y *Val) { if (Val == 0) return 0; assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); return cast<X>(Val); @@ -261,19 +260,21 @@ 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; } template <class X, class Y> -inline typename cast_retty<X, Y>::ret_type dyn_cast(Y &Val) { +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y>::ret_type +dyn_cast(Y &Val) { return isa<X>(Val) ? cast<X>(Val) : 0; } template <class X, class Y> -inline typename cast_retty<X, Y *>::ret_type dyn_cast(Y *Val) { +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +dyn_cast(Y *Val) { return isa<X>(Val) ? cast<X>(Val) : 0; } @@ -281,7 +282,8 @@ inline typename cast_retty<X, Y *>::ret_type dyn_cast(Y *Val) { // value is accepted. // template <class X, class Y> -inline typename cast_retty<X, Y*>::ret_type dyn_cast_or_null(Y *Val) { +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) : 0; } diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 4efb6a6..e49a97e 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> @@ -149,8 +148,8 @@ private: public: OptionCategory(const char *const Name, const char *const Description = 0) : 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). @@ -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... @@ -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 0; } 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 0; } 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,7 +1062,7 @@ class opt_storage { DataType *Location; // Where to store the object... OptionValue<DataType> Default; - void check() const { + void check_location() const { assert(Location != 0 && "cl::location(...) not specified for a command " "line option with external storage, " "or cl::init specified before cl::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(); @@ -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,17 +1645,21 @@ 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); } // 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()) diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 860f43e..1edcd45 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,21 @@ # 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 /// \brief Does the compiler support r-value reference *this? @@ -63,51 +73,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 +104,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 +291,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 +326,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 bef9146..80eff5c 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> namespace llvm { class MemoryBuffer; -template<typename T> class OwningPtr; class StringRef; namespace zlib { @@ -33,21 +33,21 @@ 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, + std::unique_ptr<MemoryBuffer> &CompressedBuffer, CompressionLevel Level = DefaultCompression); Status uncompress(StringRef InputBuffer, - OwningPtr<MemoryBuffer> &UncompressedBuffer, + std::unique_ptr<MemoryBuffer> &UncompressedBuffer, size_t UncompressedSize); uint32_t crc32(StringRef Buffer); diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index 4c0a5e2..4500efe 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -46,6 +46,17 @@ class CrashRecoveryContext { void *Impl; CrashRecoveryContextCleanup *head; + /// An adaptor to convert an arbitrary functor into a void(void*), void* pair. + template<typename T> struct FunctorAdaptor { + T Fn; + static void invoke(void *Data) { + return static_cast<FunctorAdaptor<T>*>(Data)->Fn(); + } + typedef void Callback(void*); + Callback *fn() { return &invoke; } + void *arg() { return this; } + }; + public: CrashRecoveryContext() : Impl(0), head(0) {} ~CrashRecoveryContext(); @@ -76,6 +87,11 @@ public: /// RunSafely has returned false. Clients can use getBacktrace() to retrieve /// the backtrace of the crash on failures. bool RunSafely(void (*Fn)(void*), void *UserData); + template<typename Functor> + bool RunSafely(Functor Fn) { + FunctorAdaptor<Functor> Adaptor = { Fn }; + return RunSafely(Adaptor.fn(), Adaptor.arg()); + } /// \brief Execute the provide callback function (with the given arguments) in /// a protected context which is run in another thread (optionally with a @@ -84,6 +100,11 @@ public: /// See RunSafely() and llvm_execute_on_thread(). bool RunSafelyOnThread(void (*Fn)(void*), void *UserData, unsigned RequestedStackSize = 0); + template<typename Functor> + bool RunSafelyOnThread(Functor Fn, unsigned RequestedStackSize = 0) { + FunctorAdaptor<Functor> Adaptor = { Fn }; + return RunSafelyOnThread(Adaptor.fn(), Adaptor.arg(), 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 a09ccaa..0000000 --- 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/Dwarf.h b/include/llvm/Support/Dwarf.h index 23bbd1c..ca31644 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. @@ -68,7 +68,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 +129,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 +175,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 +270,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 +341,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 +623,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 +771,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/ELF.h b/include/llvm/Support/ELF.h index 2868f35..7b10ebd 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -651,7 +651,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 +801,12 @@ 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_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI //ARCH_ASE @@ -837,7 +839,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 +880,9 @@ enum { R_MIPS_TLS_TPREL_HI16 = 49, R_MIPS_TLS_TPREL_LO16 = 50, R_MIPS_GLOB_DAT = 51, + 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,11 +894,14 @@ 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. @@ -1087,6 +1094,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 +1225,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. @@ -1178,7 +1273,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 +1365,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 @@ -1492,7 +1587,7 @@ enum { }; // Segment flag bits. -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { PF_X = 1, // Execute PF_W = 2, // Write PF_R = 4, // Read diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 0d35849..2c5ab74 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,6 +34,7 @@ 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)) @@ -42,6 +42,7 @@ inline value_type byte_swap(value_type 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 0000000..89c66d3 --- /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/ErrorOr.h b/include/llvm/Support/ErrorOr.h index d5b11cb..becd957 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -19,15 +19,10 @@ #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 <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,32 @@ 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<is_error_code_enum<E>::value || + is_error_condition_enum<E>::value, + void *>::type = 0) : HasError(true) { - new (getError()) error_code(make_error_code(ErrorCode)); + new (getErrorStorage()) error_code(make_error_code(ErrorCode)); } ErrorOr(llvm::error_code EC) : HasError(true) { - new (getError()) error_code(EC); + new (getErrorStorage()) 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 +129,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES ErrorOr(ErrorOr &&Other) { moveConstruct(std::move(Other)); } @@ -164,31 +148,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(); } + + error_code getError() const { + return HasError ? *getErrorStorage() : error_code::success(); } pointer operator ->() { - return toPointer(get()); + return toPointer(getStorage()); } reference operator *() { - return *get(); + return *getStorage(); } private: @@ -197,11 +180,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()) error_code(Other.getError()); } } @@ -224,17 +207,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()) error_code(Other.getError()); } } @@ -246,7 +228,6 @@ private: this->~ErrorOr(); new (this) ErrorOr(std::move(Other)); } -#endif pointer toPointer(pointer Val) { return Val; @@ -256,23 +237,23 @@ 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() { + error_code *getErrorStorage() { assert(HasError && "Cannot get error when a value exists!"); return reinterpret_cast<error_code*>(ErrorStorage.buffer); } - const error_code *getError() const { - return const_cast<ErrorOr<T> *>(this)->getError(); + const error_code *getErrorStorage() const { + return const_cast<ErrorOr<T> *>(this)->getErrorStorage(); } @@ -284,8 +265,8 @@ private: }; template<class T, class E> -typename enable_if_c<is_error_code_enum<E>::value || - is_error_condition_enum<E>::value, bool>::type +typename std::enable_if<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; } diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index cbc9c46..1884a24 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -43,6 +43,9 @@ public: static error_code create(StringRef FilePath, size_t Size, OwningPtr<FileOutputBuffer> &Result, unsigned Flags = 0); + static 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() { @@ -83,7 +86,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 d301f84..b511a8e 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -28,7 +28,6 @@ #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" @@ -39,6 +38,7 @@ #include <iterator> #include <stack> #include <string> +#include <tuple> #include <vector> #ifdef HAVE_SYS_STAT_H @@ -49,10 +49,9 @@ namespace llvm { namespace sys { namespace fs { -/// file_type - An "enum class" enumeration for the file system's view of the -/// type. +/// An "enum class" enumeration for the file system's view of the type. struct file_type { - enum _ { + enum Impl { status_error, file_not_found, regular_file, @@ -65,12 +64,11 @@ struct file_type { type_unknown }; - file_type(_ v) : v_(v) {} - explicit file_type(int v) : v_(_(v)) {} - operator int() const {return v_;} + file_type(Impl V) : V(V) {} + operator Impl() const { return V; } private: - int v_; + Impl V; }; /// space_info - Self explanatory. @@ -137,8 +135,7 @@ 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; } @@ -272,51 +269,42 @@ private: /// platform specific error_code. 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. +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. +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. +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. +error_code create_link(const Twine &to, const Twine &from); /// @brief Get the current path. /// @@ -328,34 +316,10 @@ 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. +error_code remove(const Twine &path, bool IgnoreNonExisting = true); /// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). /// @@ -490,8 +454,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, @@ -504,21 +467,6 @@ bool is_other(file_status status); /// 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); - /// @brief Get file status as if by POSIX stat(). /// /// @param path Input path. @@ -545,6 +493,11 @@ inline error_code file_size(const Twine &Path, uint64_t &Result) { return error_code::success(); } +/// @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::not_supported on platforms +/// where the functionality isn't available. error_code setLastModificationAndAccessTime(int FD, TimeValue Time); /// @brief Is status available? @@ -621,9 +574,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) { @@ -704,10 +660,8 @@ private: 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. diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h index 79c59e4..873b8df 100644 --- a/include/llvm/Support/FileUtilities.h +++ b/include/llvm/Support/FileUtilities.h @@ -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 aaa54e1..a62801f 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -84,7 +84,7 @@ 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); } }; @@ -102,7 +102,7 @@ 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); } }; @@ -121,7 +121,7 @@ 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); } }; @@ -142,7 +142,7 @@ 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); } }; @@ -165,7 +165,7 @@ 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); } }; diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index df1f218..78c4809 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). @@ -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 0aa716a..902f2db 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,69 @@ 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) + : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), + PreservePaths(P), UncondBranch(U) {} + + bool AllBlocks; + bool BranchInfo; + bool BranchCount; + bool FuncCoverage; + bool PreservePaths; + bool UncondBranch; +}; + /// 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 +204,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 +230,188 @@ private: /// (.gcno and .gcda). class GCOVFile { public: - GCOVFile() : Functions(), RunCount(0), ProgramCount(0) {} + GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0), + ProgramCount(0) {} ~GCOVFile(); - bool read(GCOVBuffer &Buffer); - void dump(); + bool readGCNO(GCOVBuffer &Buffer); + bool readGCDA(GCOVBuffer &Buffer); + uint32_t getChecksum() const { return Checksum; } + void dump() const; void collectLineCounts(FileInfo &FI); private: + bool GCNOInitialized; + GCOV::GCOVVersion Version; + uint32_t Checksum; SmallVector<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) {} + typedef SmallVectorImpl<GCOVBlock *>::const_iterator BlockIterator; + + GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {} ~GCOVFunction(); - bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format); + 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<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 { + BlockLines Blocks; + FunctionLines Functions; + }; + + 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) { + LineInfo[Filename].Blocks[Line-1].push_back(Block); + } + void addFunctionLine(StringRef Filename, uint32_t Line, + const GCOVFunction *Function) { + 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 GCNOFile, StringRef GCDAFile); private: - StringMap<LineCounts> LineInfo; + void printFunctionSummary(raw_fd_ostream &OS, + const FunctionVector &Funcs) const; + void printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block, + uint32_t LineIndex, uint32_t &BlockNo) const; + void printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block, + GCOVCoverage &Coverage, uint32_t &EdgeNo); + void printUncondBranchInfo(raw_fd_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 3aa0beb..6878844 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. /// @@ -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; @@ -216,7 +210,7 @@ protected: 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. @@ -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()) @@ -346,12 +340,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 == NULL) + 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,7 +360,7 @@ public: /// Note that this is not a constant time operation! /// bool properlyDominates(const DomTreeNodeBase<NodeT> *A, - const DomTreeNodeBase<NodeT> *B) { + const DomTreeNodeBase<NodeT> *B) const { if (A == 0 || B == 0) return false; if (A == B) @@ -372,7 +368,7 @@ public: 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 +386,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 +421,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!"); @@ -590,13 +586,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 +605,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 +616,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())); @@ -643,7 +639,7 @@ protected: assert(IDom || this->DomTreeNodes[NULL]); 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); @@ -693,7 +689,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 +701,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 +712,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 c0f95cb..f6bb8f4 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 { diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h index 28c4cc7..8f4bf3c 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 3d73792..9ef5fe6 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -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 0000000..7077656 --- /dev/null +++ b/include/llvm/Support/LineIterator.h @@ -0,0 +1,84 @@ +//===- 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 <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, ptrdiff_t> { + const MemoryBuffer *Buffer; + char CommentMarker; + + unsigned LineNumber; + StringRef CurrentLine; + +public: + /// \brief Default construct an "end" iterator. + line_iterator() : Buffer(0) {} + + /// \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/MD5.h b/include/llvm/Support/MD5.h index b2b8c2d..4eb8507 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 897a611..ef06a41 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,7 +148,9 @@ 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 = 0x00u, @@ -171,10 +174,12 @@ namespace llvm { S_THREAD_LOCAL_ZEROFILL = 0x12u, S_THREAD_LOCAL_VARIABLES = 0x13u, S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14u, - S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15u + 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 = 0x80000000u, @@ -348,7 +353,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 +408,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 +772,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; }; @@ -893,7 +927,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,12 +942,13 @@ 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 @@ -973,7 +1008,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 +1016,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/MathExtras.h b/include/llvm/Support/MathExtras.h index ff41608..f1f7b4f 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. @@ -541,6 +541,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 +565,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 a08c796..8251fcd 100644 --- a/include/llvm/Support/Memory.h +++ b/include/llvm/Support/Memory.h @@ -95,7 +95,7 @@ namespace sys { /// 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 diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index ff22fb6..578c7e8 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -14,11 +14,12 @@ #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 <memory> namespace llvm { @@ -66,7 +67,11 @@ public: /// 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, + static error_code getFile(Twine Filename, OwningPtr<MemoryBuffer> &Result, + int64_t FileSize = -1, + bool RequiresNullTerminator = true); + static error_code getFile(Twine Filename, + std::unique_ptr<MemoryBuffer> &Result, int64_t FileSize = -1, bool RequiresNullTerminator = true); @@ -76,6 +81,9 @@ public: static error_code getOpenFileSlice(int FD, const char *Filename, OwningPtr<MemoryBuffer> &Result, uint64_t MapSize, int64_t Offset); + static error_code getOpenFileSlice(int FD, const char *Filename, + std::unique_ptr<MemoryBuffer> &Result, + uint64_t MapSize, int64_t Offset); /// Given an already-open file descriptor, read the file and return a /// MemoryBuffer. @@ -83,6 +91,10 @@ public: OwningPtr<MemoryBuffer> &Result, uint64_t FileSize, bool RequiresNullTerminator = true); + static error_code getOpenFile(int FD, const char *Filename, + std::unique_ptr<MemoryBuffer> &Result, + uint64_t FileSize, + bool RequiresNullTerminator = true); /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note /// that InputData must be null terminated if RequiresNullTerminator is true. @@ -111,14 +123,18 @@ public: /// 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); + static error_code getSTDIN(OwningPtr<MemoryBuffer> &Result); + static error_code getSTDIN(std::unique_ptr<MemoryBuffer> &Result); /// 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, + OwningPtr<MemoryBuffer> &Result, + int64_t FileSize = -1); + static error_code getFileOrSTDIN(StringRef Filename, + std::unique_ptr<MemoryBuffer> &Result, int64_t FileSize = -1); //===--------------------------------------------------------------------===// diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h index b2afe1b..ba18529 100644 --- a/include/llvm/Support/Path.h +++ b/include/llvm/Support/Path.h @@ -306,6 +306,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 4f68fca..914141a 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 2172036..7f6441e 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 "llvm/Support/system_error.h" 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) /// @{ diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 00571a4..a1067a6 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -52,27 +52,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(); /// 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 diff --git a/include/llvm/Support/Recycler.h b/include/llvm/Support/Recycler.h index bcc561d..e97f36a 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 3d071be..2eea369 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 = NULL; + } ~Regex(); /// isValid - returns the error encountered during regex compilation, or @@ -81,6 +93,9 @@ namespace llvm { /// 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/StreamableMemoryObject.h b/include/llvm/Support/StreamableMemoryObject.h index e823d48..0259630 100644 --- a/include/llvm/Support/StreamableMemoryObject.h +++ b/include/llvm/Support/StreamableMemoryObject.h @@ -11,10 +11,11 @@ #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/MemoryObject.h" +#include <cassert> +#include <memory> #include <vector> namespace llvm { @@ -38,7 +39,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 +47,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 +55,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 +71,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,14 +105,12 @@ 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 @@ -120,8 +118,8 @@ public: assert(0 && "getPointer in streaming memory objects not allowed"); return NULL; } - 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 +135,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 diff --git a/include/llvm/Support/StringRefMemoryObject.h b/include/llvm/Support/StringRefMemoryObject.h index 994fa34..8a349ea 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/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index 9ecee3b..8e7478c 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> @@ -46,15 +46,12 @@ namespace llvm { class MCRelocationInfo; class MCTargetAsmParser; 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, + MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); @@ -79,7 +76,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); @@ -128,12 +125,12 @@ 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, @@ -154,9 +151,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; @@ -421,11 +417,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 MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, STI, RelaxAll, NoExecStack); } @@ -433,7 +430,6 @@ namespace llvm { MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, - bool useLoc, bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, @@ -441,10 +437,10 @@ namespace llvm { MCAsmBackend *TAB, bool ShowInst) const { if (AsmStreamerCtorFn) - return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, useCFI, + return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useCFI, useDwarfDirectory, InstPrint, CE, TAB, ShowInst); - return llvm::createAsmStreamer(Ctx, 0, OS, isVerboseAsm, useLoc, useCFI, + return llvm::createAsmStreamer(Ctx, OS, isVerboseAsm, useCFI, useDwarfDirectory, InstPrint, CE, TAB, ShowInst); } @@ -490,7 +486,6 @@ namespace llvm { explicit iterator(Target *T) : Current(T) {} friend struct TargetRegistry; public: - iterator(const iterator &I) : Current(I.Current) {} iterator() : Current(0) {} bool operator==(const iterator &x) const { @@ -578,14 +573,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 @@ -831,15 +825,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; } }; diff --git a/include/llvm/Support/TimeValue.h b/include/llvm/Support/TimeValue.h index 2785408..ee0e286 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/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h index a2191ad..88f8ccc 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/UnicodeCharRanges.h b/include/llvm/Support/UnicodeCharRanges.h index 86faa38..734d323 100644 --- a/include/llvm/Support/UnicodeCharRanges.h +++ b/include/llvm/Support/UnicodeCharRanges.h @@ -16,7 +16,6 @@ #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" #include "llvm/Support/raw_ostream.h" - #include <algorithm> namespace llvm { @@ -40,7 +39,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 +66,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; diff --git a/include/llvm/Support/Valgrind.h b/include/llvm/Support/Valgrind.h index 7ae40af..cebf75c 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 ecce713..7ca218e 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/YAMLParser.h b/include/llvm/Support/YAMLParser.h index 7020449..5194b52 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 { @@ -97,8 +95,8 @@ 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; }; @@ -116,7 +114,7 @@ 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 @@ -157,7 +155,7 @@ public: } protected: - OwningPtr<Document> &Doc; + std::unique_ptr<Document> &Doc; SMRange SourceRange; void operator delete(void *) throw() {} @@ -176,9 +174,9 @@ private: /// 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) { @@ -192,9 +190,9 @@ public: /// 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()); @@ -234,13 +232,10 @@ 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(0), Value(0) {} /// @brief Parse and return the key. /// @@ -256,7 +251,7 @@ public: /// @returns The value, or nullptr if failed() == true. Node *getValue(); - virtual void skip() LLVM_OVERRIDE { + void skip() override { getKey()->skip(); getValue()->skip(); } @@ -346,7 +341,7 @@ void skip(CollectionType &C) { /// Name: _main /// Scope: Global class MappingNode : public Node { - virtual void anchor(); + void anchor() override; public: enum MappingType { MT_Block, @@ -354,7 +349,7 @@ 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) {} @@ -370,7 +365,7 @@ public: iterator end() { return iterator(); } - virtual void skip() LLVM_OVERRIDE { + void skip() override { yaml::skip(*this); } @@ -396,7 +391,7 @@ private: /// - Hello /// - World class SequenceNode : public Node { - virtual void anchor(); + void anchor() override; public: enum SequenceType { ST_Block, @@ -411,7 +406,7 @@ 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), @@ -431,7 +426,7 @@ public: iterator end() { return iterator(); } - virtual void skip() LLVM_OVERRIDE { + void skip() override { yaml::skip(*this); } @@ -452,10 +447,10 @@ private: /// 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(); @@ -532,7 +527,7 @@ private: class document_iterator { public: document_iterator() : Doc(0) {} - document_iterator(OwningPtr<Document> &D) : Doc(&D) {} + document_iterator(std::unique_ptr<Document> &D) : Doc(&D) {} bool operator ==(const document_iterator &Other) { if (isAtEnd() || Other.isAtEnd()) @@ -559,16 +554,14 @@ public: return *Doc->get(); } - OwningPtr<Document> &operator ->() { - return *Doc; - } + std::unique_ptr<Document> &operator->() { return *Doc; } private: bool isAtEnd() const { return !Doc || !*Doc; } - OwningPtr<Document> *Doc; + std::unique_ptr<Document> *Doc; }; } diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index c19eb23..ea217c3 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,17 @@ #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/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" - namespace llvm { namespace yaml { @@ -45,6 +43,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); }; @@ -227,6 +227,23 @@ public: static bool const value = (sizeof(test<MappingTraits<T> >(0)) == 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> >(0)) == 1); +}; + + // Test if SequenceTraits<T> is defined on type T. template <class T> @@ -248,7 +265,7 @@ public: // 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: @@ -278,7 +295,7 @@ public: // 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 > { }; @@ -302,7 +319,7 @@ public: 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,7 +327,15 @@ 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: @@ -318,7 +343,7 @@ public: IO(void *Ctxt=NULL); virtual ~IO(); - virtual bool outputting() const = 0; + virtual bool outputting() = 0; virtual unsigned beginSequence() = 0; virtual bool preflightElement(unsigned, void *&) = 0; @@ -388,7 +413,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 +422,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 +439,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 +492,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 +500,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,7 +513,7 @@ 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; @@ -484,21 +534,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(); @@ -538,6 +608,12 @@ struct ScalarTraits<StringRef> { static void output(const StringRef &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, StringRef &); }; + +template<> +struct ScalarTraits<std::string> { + static void output(const std::string &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, std::string &); +}; template<> struct ScalarTraits<uint8_t> { @@ -697,32 +773,30 @@ public: // Check if there was an syntax or semantic error during parsing. llvm::error_code error(); - static bool classof(const IO *io) { return !io->outputting(); } - 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 &) override; + void setError(const Twine &message) override; + bool canElideEmptySequence() override; class HNode { virtual void anchor(); @@ -735,7 +809,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 +819,7 @@ private: }; class ScalarHNode : public HNode { - virtual void anchor(); + void anchor() override; public: ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } @@ -802,15 +876,15 @@ public: void 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; + llvm::error_code EC; + llvm::BumpPtrAllocator StringAllocator; + llvm::yaml::document_iterator DocIterator; + std::vector<bool> BitValuesUsed; + HNode *CurrentNode; + bool ScalarMatchFound; }; @@ -825,31 +899,29 @@ public: Output(llvm::raw_ostream &, void *Ctxt=NULL); 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 &) 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. @@ -942,7 +1014,7 @@ struct ScalarTraits<Hex64> { // 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 +1030,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 +1041,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 +1051,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 +1061,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 +1078,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 +1092,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 +1106,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 +1147,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 9000306..3114199 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(); diff --git a/include/llvm/Support/raw_os_ostream.h b/include/llvm/Support/raw_os_ostream.h index 4385721..04cf3b6 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 ec7e06b..0240035 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -322,14 +322,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 +347,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 +373,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 +427,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 +451,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 +477,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 index 43dace6..4ca4b06 100644 --- a/include/llvm/Support/system_error.h +++ b/include/llvm/Support/system_error.h @@ -48,10 +48,10 @@ const error_category& generic_category(); const error_category& system_category(); template <class T> struct is_error_code_enum - : public false_type {}; + : public std::false_type {}; template <class T> struct is_error_condition_enum - : public false_type {}; + : public std::false_type {}; class error_code { @@ -203,7 +203,7 @@ enum class errc wrong_protocol_type // EPROTOTYPE }; -template <> struct is_error_condition_enum<errc> : true_type { } +template <> struct is_error_condition_enum<errc> : std::true_type { } error_code make_error_code(errc e); error_condition make_error_condition(errc e); @@ -225,7 +225,6 @@ template <> struct hash<std::error_code>; */ #include "llvm/Config/llvm-config.h" -#include "llvm/Support/type_traits.h" #include <cerrno> #include <string> @@ -474,11 +473,11 @@ namespace llvm { // is_error_code_enum -template <class Tp> struct is_error_code_enum : public false_type {}; +template <class Tp> struct is_error_code_enum : public std::false_type {}; // is_error_condition_enum -template <class Tp> struct is_error_condition_enum : public false_type {}; +template <class Tp> struct is_error_condition_enum : public std::false_type {}; // Some error codes are not present on all platforms, so we provide equivalents // for them: @@ -613,9 +612,9 @@ enum _ { operator int() const {return v_;} }; -template <> struct is_error_condition_enum<errc> : true_type { }; +template <> struct is_error_condition_enum<errc> : std::true_type { }; -template <> struct is_error_condition_enum<errc::_> : true_type { }; +template <> struct is_error_condition_enum<errc::_> : std::true_type { }; class error_condition; class error_code; @@ -629,8 +628,8 @@ class error_category public: virtual ~error_category(); -private: error_category(); +private: error_category(const error_category&) LLVM_DELETED_FUNCTION; error_category& operator=(const error_category&) LLVM_DELETED_FUNCTION; @@ -653,7 +652,7 @@ public: class _do_message : public error_category { public: - virtual std::string message(int ev) const LLVM_OVERRIDE; + std::string message(int ev) const override; }; const error_category& generic_category(); @@ -675,7 +674,7 @@ public: : _val_(_val), _cat_(&_cat) {} template <class E> - error_condition(E _e, typename enable_if_c< + error_condition(E _e, typename std::enable_if< is_error_condition_enum<E>::value >::type* = 0) {*this = make_error_condition(_e);} @@ -686,13 +685,12 @@ public: } 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;} + typename std::enable_if<is_error_condition_enum<E>::value, + error_condition &>::type + operator=(E _e) { + *this = make_error_condition(_e); + return *this; + } void clear() { _val_ = 0; @@ -737,7 +735,7 @@ public: : _val_(_val), _cat_(&_cat) {} template <class E> - error_code(E _e, typename enable_if_c< + error_code(E _e, typename std::enable_if< is_error_code_enum<E>::value >::type* = 0) { *this = make_error_code(_e); @@ -749,13 +747,11 @@ public: } 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;} + typename std::enable_if<is_error_code_enum<E>::value, error_code &>::type + operator=(E _e) { + *this = make_error_code(_e); + return *this; + } void clear() { _val_ = 0; @@ -892,9 +888,9 @@ enum _ { }; -template <> struct is_error_code_enum<windows_error> : true_type { }; +template <> struct is_error_code_enum<windows_error> : std::true_type { }; -template <> struct is_error_code_enum<windows_error::_> : true_type { }; +template <> struct is_error_code_enum<windows_error::_> : std::true_type { }; inline error_code make_error_code(windows_error e) { return error_code(static_cast<int>(e), system_category()); diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index 906e97c..70953a9 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 2d0a2b4..17ac418 100644 --- a/include/llvm/TableGen/Error.h +++ b/include/llvm/TableGen/Error.h @@ -27,9 +27,9 @@ 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; diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 50352bd..2bed006 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -150,28 +150,28 @@ 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 0; } + Init *convertValue( ListInit *LI) override { return 0; } + Init *convertValue(VarBitInit *VB) override { return (Init*)VB; } + Init *convertValue( DefInit *DI) override { return 0; } + Init *convertValue( DagInit *DI) override { return 0; } + 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; }; @@ -189,28 +189,28 @@ 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 0; } + Init *convertValue( ListInit *LI) override { return 0; } + Init *convertValue(VarBitInit *VB) override { return 0; } + Init *convertValue( DefInit *DI) override { return 0; } + Init *convertValue( DagInit *DI) override { return 0; } + 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; }; @@ -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 0; } + Init *convertValue( ListInit *LI) override { return 0; } + Init *convertValue(VarBitInit *VB) override { return 0; } + Init *convertValue( DefInit *DI) override { return 0; } + Init *convertValue( DagInit *DI) override { return 0; } + 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 @@ -263,26 +263,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 0; } + Init *convertValue( BitsInit *BI) override { return 0; } + Init *convertValue( IntInit *II) override { return 0; } + Init *convertValue(StringInit *SI) override { return (Init*)SI; } + Init *convertValue( ListInit *LI) override { return 0; } + 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 0; } + Init *convertValue( DefInit *DI) override { return 0; } + Init *convertValue( DagInit *DI) override { return 0; } + 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); } }; @@ -302,29 +302,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 0; } + Init *convertValue( BitsInit *BI) override { return 0; } + Init *convertValue( IntInit *II) override { return 0; } + Init *convertValue(StringInit *SI) override { return 0; } + Init *convertValue( ListInit *LI) override; + Init *convertValue(VarBitInit *VB) override { return 0; } + Init *convertValue( DefInit *DI) override { return 0; } + Init *convertValue( DagInit *DI) override { return 0; } + 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 @@ -339,25 +339,25 @@ 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 0; } + Init *convertValue( BitsInit *BI) override { return 0; } + Init *convertValue( IntInit *II) override { return 0; } + Init *convertValue(StringInit *SI) override { return 0; } + Init *convertValue( ListInit *LI) override { return 0; } + Init *convertValue(VarBitInit *VB) override { return 0; } + Init *convertValue( DefInit *DI) override { return 0; } + 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); } }; @@ -379,28 +379,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 0; } + Init *convertValue( BitsInit *BI) override { return 0; } + Init *convertValue( IntInit *II) override { return 0; } + Init *convertValue(StringInit *SI) override { return 0; } + Init *convertValue( ListInit *LI) override { return 0; } + Init *convertValue(VarBitInit *VB) override { return 0; } + 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 0; } + 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. @@ -569,16 +569,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 @@ -594,7 +594,7 @@ 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,16 +602,16 @@ 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 "?"; } }; @@ -623,7 +623,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 +633,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 +667,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,11 +683,11 @@ 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]; } @@ -713,23 +713,23 @@ 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); } }; @@ -745,7 +745,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 +755,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"); } }; @@ -806,10 +806,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 +818,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,10 +833,10 @@ 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"); } }; @@ -866,14 +866,14 @@ 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; }; @@ -899,14 +899,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,11 +916,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; }; /// BinOpInit - !op (X, Y) - Combine two inits. @@ -946,14 +946,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 +968,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. @@ -1000,15 +1000,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,13 +1027,13 @@ 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; }; @@ -1057,7 +1057,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,23 +1067,23 @@ 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(); } }; @@ -1110,17 +1110,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 +1149,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 +1159,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 +1185,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,21 +1193,21 @@ 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"); } }; @@ -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"); } }; @@ -1614,7 +1612,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; diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 3f6eae6..facb89a 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -685,6 +685,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 +723,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 +823,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; } } @@ -947,7 +970,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 +980,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 9cc52a5..a660403 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,6 +43,8 @@ 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 @@ -68,6 +71,9 @@ 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; } diff --git a/include/llvm/Target/TargetCallingConv.td b/include/llvm/Target/TargetCallingConv.td index c1bef28..9d1dc38 100644 --- a/include/llvm/Target/TargetCallingConv.td +++ b/include/llvm/Target/TargetCallingConv.td @@ -89,11 +89,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/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h index 46eaef2..d4f9f23 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 5ab04f7..2f6445f 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -28,9 +28,9 @@ #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/Target/TargetCallingConv.h" #include "llvm/Target/TargetMachine.h" #include <climits> @@ -48,8 +48,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 +145,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 +175,30 @@ public: return true; } + /// Return true if multiple condition registers are available. + bool hasMultipleConditionRegisters() const { + return HasMultipleConditionRegisters; + } + /// 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; } + virtual bool shouldSplitVectorType(EVT /*VT*/) const { return false; } + + // 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 +237,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 @@ -604,8 +641,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. @@ -707,14 +745,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*/ = 0) const { return false; } @@ -880,13 +920,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 +966,15 @@ 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 not to expand sequence of operations into a /// separate sequences that increases the amount of flow control. void setJumpIsExpensive(bool isExpensive = true) { @@ -1166,6 +1215,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 +1330,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 +1377,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 +1387,13 @@ 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 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 @@ -1681,10 +1754,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 @@ -1853,6 +1934,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, @@ -1931,12 +2020,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); }; @@ -2060,6 +2150,12 @@ 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 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 @@ -2078,6 +2174,18 @@ public: return NULL; } + /// 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 /// illegal operand type but legal result types. It replaces the /// LowerOperation callback in the type Legalizer. The reason we can not do @@ -2127,6 +2235,10 @@ public: return 0; } + + bool verifyReturnAddressArgumentIsConstant(SDValue Op, + SelectionDAG &DAG) const; + //===--------------------------------------------------------------------===// // Inline Asm Support hooks // @@ -2190,15 +2302,6 @@ 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), diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 284b6bb..cdb7ea6 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,91 +44,88 @@ class TargetLoweringObjectFile : public MCObjectFileInfo { public: MCContext &getContext() const { return *Ctx; } - TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(0) {} - + TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(0), DL(0) {} + 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. + /// 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; - - /// getKindForGlobal - Classify the specified global variable into a set of - /// target independent categories embodied in SectionKind. + + /// 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 { + 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 0; } - - /// 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; @@ -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 0; + } + + /// \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 11b0f5f..ce3f866 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; @@ -85,9 +87,9 @@ protected: // Can only create subclasses. unsigned MCRelaxAll : 1; unsigned MCNoExecStack : 1; unsigned MCSaveTempLabels : 1; - unsigned MCUseLoc : 1; unsigned MCUseCFI : 1; unsigned MCUseDwarfDirectory : 1; + unsigned RequireStructuredCFG : 1; public: virtual ~TargetMachine(); @@ -108,7 +110,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 @@ -156,6 +158,9 @@ public: return 0; } + bool requiresStructuredCFG() const { return RequireStructuredCFG; } + void setRequiresStructuredCFG(bool Value) { RequireStructuredCFG = Value; } + /// hasMCRelaxAll - Check whether all machine code instructions should be /// relaxed. bool hasMCRelaxAll() const { return MCRelaxAll; } @@ -178,12 +183,6 @@ public: /// 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; } @@ -292,6 +291,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 +312,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 +321,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 = 0, + AnalysisID StopAfter = 0) override; /// addPassesToEmitMachineCode - Add passes to the specified pass manager to /// get machine code emitted. This uses a JITCodeEmitter object to handle @@ -331,19 +332,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 bd74cb9..abb3eca 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 e77be0e..1f87343 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -42,70 +42,17 @@ namespace llvm { 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) - {} - - TargetOptions(const TargetOptions& rhs) - : PrintMachineCode(rhs.PrintMachineCode), - NoFramePointerElim(rhs.NoFramePointerElim), - LessPreciseFPMADOption(rhs.LessPreciseFPMADOption), - UnsafeFPMath(rhs.UnsafeFPMath), - NoInfsFPMath(rhs.NoInfsFPMath), - NoNaNsFPMath(rhs.NoNaNsFPMath), - HonorSignDependentRoundingFPMathOption(rhs.HonorSignDependentRoundingFPMathOption), - UseSoftFloat(rhs.UseSoftFloat), - NoZerosInBSS(rhs.NoZerosInBSS), - JITEmitDebugInfo(rhs.JITEmitDebugInfo), - JITEmitDebugInfoToDisk(rhs.JITEmitDebugInfoToDisk), - GuaranteedTailCallOpt(rhs.GuaranteedTailCallOpt), - DisableTailCalls(rhs.DisableTailCalls), - StackAlignmentOverride(rhs.StackAlignmentOverride), - EnableFastISel(rhs.EnableFastISel), - PositionIndependentExecutable(rhs.PositionIndependentExecutable), - EnableSegmentedStacks(rhs.EnableSegmentedStacks), - UseInitArray(rhs.UseInitArray), - TrapFuncName(rhs.TrapFuncName), - FloatABIType(rhs.FloatABIType), - AllowFPOpFusion(rhs.AllowFPOpFusion) - {} - - TargetOptions& operator =(const TargetOptions& rhs) - { - if (&rhs == this) - return *this; - - PrintMachineCode = rhs.PrintMachineCode; - NoFramePointerElim = rhs.NoFramePointerElim; - LessPreciseFPMADOption = rhs.LessPreciseFPMADOption; - UnsafeFPMath = rhs.UnsafeFPMath; - NoInfsFPMath = rhs.NoInfsFPMath; - NoNaNsFPMath = rhs.NoNaNsFPMath; - HonorSignDependentRoundingFPMathOption = rhs.HonorSignDependentRoundingFPMathOption; - UseSoftFloat = rhs.UseSoftFloat; - NoZerosInBSS = rhs.NoZerosInBSS; - JITEmitDebugInfo = rhs.JITEmitDebugInfo; - JITEmitDebugInfoToDisk = rhs.JITEmitDebugInfoToDisk; - GuaranteedTailCallOpt = rhs.GuaranteedTailCallOpt; - DisableTailCalls = rhs.DisableTailCalls; - StackAlignmentOverride = rhs.StackAlignmentOverride; - EnableFastISel = rhs.EnableFastISel; - PositionIndependentExecutable = rhs.PositionIndependentExecutable; - EnableSegmentedStacks = rhs.EnableSegmentedStacks; - UseInitArray = rhs.UseInitArray; - TrapFuncName = rhs.TrapFuncName; - FloatABIType = rhs.FloatABIType; - AllowFPOpFusion = rhs.AllowFPOpFusion; - return *this; - } + EnableSegmentedStacks(false), UseInitArray(false), + DisableIntegratedAS(false), CompressDebugSections(false), + TrapFuncName(""), FloatABIType(FloatABI::Default), + AllowFPOpFusion(FPOpFusion::Standard) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -211,6 +158,12 @@ namespace llvm { /// constructors. unsigned UseInitArray : 1; + /// Disable the integrated assembler. + unsigned DisableIntegratedAS : 1; + + /// Compress DWARF debug sections. + unsigned CompressDebugSections : 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. diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 958bea6..b0c21c1 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -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"); } diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index 9d4858a..b4d0c44 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -114,14 +114,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 d94bdc6..16cfff1 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -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]>; @@ -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 3474ee4..98a5149 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -31,10 +31,10 @@ 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); diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h index 7f51c51..334fb1c 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(); @@ -78,20 +78,24 @@ ModulePass *createGlobalDCEPass(); /// 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 +191,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 43a0ac8..6a644ad 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 2788774..42b6b27 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -111,7 +111,6 @@ public: bool BBVectorize; bool SLPVectorize; bool LoopVectorize; - bool LateVectorize; bool RerollLoops; private: diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index 2de15aa..b527546 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -66,14 +66,12 @@ ModulePass *createGCOVProfilerPass(const GCOVOptions &Options = // Insert AddressSanitizer (address sanity checking) instrumentation FunctionPass *createAddressSanitizerFunctionPass( bool CheckInitOrder = true, bool CheckUseAfterReturn = false, - bool CheckLifetime = false, StringRef BlacklistFile = StringRef(), - bool ZeroBaseShadow = false); + bool CheckLifetime = false, StringRef BlacklistFile = StringRef()); ModulePass *createAddressSanitizerModulePass( - bool CheckInitOrder = true, StringRef BlacklistFile = StringRef(), - bool ZeroBaseShadow = false); + bool CheckInitOrder = true, StringRef BlacklistFile = StringRef()); // Insert MemorySanitizer instrumentation (detection of uninitialized reads) -FunctionPass *createMemorySanitizerPass(bool TrackOrigins = false, +FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0, StringRef BlacklistFile = StringRef()); // Insert ThreadSanitizer (race detection) instrumentation diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 1521c4c..7267222 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -142,6 +142,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(); //===----------------------------------------------------------------------===// // @@ -262,16 +264,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; //===----------------------------------------------------------------------===// @@ -312,9 +308,9 @@ 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(); //===----------------------------------------------------------------------===// // @@ -370,6 +366,17 @@ 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(); + } // 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 0000000..4e4f02c --- /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 65cafe2..4d5e305 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -18,7 +18,7 @@ // 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 { @@ -183,27 +183,47 @@ 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(Value *Cond, Instruction *SplitBefore, + bool Unreachable, + MDNode *BranchWeights = 0); -TerminatorInst *SplitBlockAndInsertIfThen(Instruction *Cmp, - bool Unreachable, MDNode *BranchWeights = 0); + +/// 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 = 0); /// /// GetIfCondition - Check whether BB is the merge point of a if-region. @@ -211,9 +231,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 181ed07..0f39ada 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -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, diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index 3ec1329..96c6508 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 { @@ -109,7 +109,7 @@ 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, @@ -151,7 +151,7 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, SmallVectorImpl<ReturnInst*> &Returns, const char *NameSuffix = "", ClonedCodeInfo *CodeInfo = 0, - const DataLayout *TD = 0, + const DataLayout *DL = 0, Instruction *TheCall = 0); @@ -159,13 +159,13 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, /// 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 = 0, const DataLayout *DL = 0) + : 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. diff --git a/include/llvm/Transforms/Utils/CmpInstAnalysis.h b/include/llvm/Transforms/Utils/CmpInstAnalysis.h index 488d7a5..22469e0 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 // diff --git a/include/llvm/Transforms/Utils/IntegerDivision.h b/include/llvm/Transforms/Utils/IntegerDivision.h index 27d3c58..55e8b66 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 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 the above 32bit routine, therefore adequate for targets with - /// little or no support for less than 32 bit arithmetic. + /// 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 5586c15..c68fd06 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 { diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h index 4745eba..64e18ca1 100644 --- a/include/llvm/Transforms/Utils/LoopUtils.h +++ b/include/llvm/Transforms/Utils/LoopUtils.h @@ -15,12 +15,49 @@ #define LLVM_TRANSFORMS_UTILS_LOOPUTILS_H namespace llvm { - +class AliasAnalysis; +class BasicBlock; +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 = 0, ScalarEvolution *SE = 0); + +/// \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 = 0); + +/// \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 = 0); + } #endif diff --git a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h index a9adbd7..0f3da16 100644 --- a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h +++ b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h @@ -17,9 +17,9 @@ #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 { diff --git a/include/llvm/Transforms/Utils/SimplifyIndVar.h b/include/llvm/Transforms/Utils/SimplifyIndVar.h index 7e97e21..dedeca3 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,9 +32,25 @@ 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(NULL), 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; }; diff --git a/include/llvm/Transforms/Utils/SpecialCaseList.h b/include/llvm/Transforms/Utils/SpecialCaseList.h index 34c28fc..508a6df 100644 --- a/include/llvm/Transforms/Utils/SpecialCaseList.h +++ b/include/llvm/Transforms/Utils/SpecialCaseList.h @@ -43,7 +43,9 @@ // http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores // //===----------------------------------------------------------------------===// -// + +#ifndef LLVM_TRANSFORMS_UTILS_SPECIALCASELIST_H +#define LLVM_TRANSFORMS_UTILS_SPECIALCASELIST_H #include "llvm/ADT/StringMap.h" @@ -108,3 +110,5 @@ class SpecialCaseList { }; } // namespace llvm + +#endif // LLVM_TRANSFORMS_UTILS_SPECIALCASELIST_H diff --git a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h index 933c85c..79a70cf 100644 --- a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h +++ b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -32,7 +32,7 @@ public: } // 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 +41,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 f175e83..0bbd572 100644 --- a/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/include/llvm/Transforms/Utils/UnrollLoop.h @@ -21,9 +21,11 @@ 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); diff --git a/include/llvm/Transforms/Utils/ValueMapper.h b/include/llvm/Transforms/Utils/ValueMapper.h index d56ac07..e96610e 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; diff --git a/include/llvm/Transforms/Vectorize.h b/include/llvm/Transforms/Vectorize.h index 823c5fb..e93b39a 100644 --- a/include/llvm/Transforms/Vectorize.h +++ b/include/llvm/Transforms/Vectorize.h @@ -114,7 +114,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); //===----------------------------------------------------------------------===// // |