diff options
Diffstat (limited to 'contrib/llvm/include')
723 files changed, 31562 insertions, 12665 deletions
diff --git a/contrib/llvm/include/llvm-c/Comdat.h b/contrib/llvm/include/llvm-c/Comdat.h new file mode 100644 index 000000000000..499996d68a53 --- /dev/null +++ b/contrib/llvm/include/llvm-c/Comdat.h @@ -0,0 +1,75 @@ +/*===-- llvm-c/Comdat.h - Module Comdat C 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 defines the C interface to COMDAT. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_COMDAT_H +#define LLVM_C_COMDAT_H + +#include "llvm-c/Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + LLVMAnyComdatSelectionKind, ///< The linker may choose any COMDAT. + LLVMExactMatchComdatSelectionKind, ///< The data referenced by the COMDAT must + ///< be the same. + LLVMLargestComdatSelectionKind, ///< The linker will choose the largest + ///< COMDAT. + LLVMNoDuplicatesComdatSelectionKind, ///< No other Module may specify this + ///< COMDAT. + LLVMSameSizeComdatSelectionKind ///< The data referenced by the COMDAT must be + ///< the same size. +} LLVMComdatSelectionKind; + +/** + * Return the Comdat in the module with the specified name. It is created + * if it didn't already exist. + * + * @see llvm::Module::getOrInsertComdat() + */ +LLVMComdatRef LLVMGetOrInsertComdat(LLVMModuleRef M, const char *Name); + +/** + * Get the Comdat assigned to the given global object. + * + * @see llvm::GlobalObject::getComdat() + */ +LLVMComdatRef LLVMGetComdat(LLVMValueRef V); + +/** + * Assign the Comdat to the given global object. + * + * @see llvm::GlobalObject::setComdat() + */ +void LLVMSetComdat(LLVMValueRef V, LLVMComdatRef C); + +/* + * Get the conflict resolution selection kind for the Comdat. + * + * @see llvm::Comdat::getSelectionKind() + */ +LLVMComdatSelectionKind LLVMGetComdatSelectionKind(LLVMComdatRef C); + +/* + * Set the conflict resolution selection kind for the Comdat. + * + * @see llvm::Comdat::setSelectionKind() + */ +void LLVMSetComdatSelectionKind(LLVMComdatRef C, LLVMComdatSelectionKind Kind); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/contrib/llvm/include/llvm-c/Core.h b/contrib/llvm/include/llvm-c/Core.h index 8238c09f9dd0..6792219f8730 100644 --- a/contrib/llvm/include/llvm-c/Core.h +++ b/contrib/llvm/include/llvm-c/Core.h @@ -187,19 +187,60 @@ typedef enum { } LLVMVisibility; typedef enum { + LLVMNoUnnamedAddr, /**< Address of the GV is significant. */ + LLVMLocalUnnamedAddr, /**< Address of the GV is locally insignificant. */ + LLVMGlobalUnnamedAddr /**< Address of the GV is globally insignificant. */ +} LLVMUnnamedAddr; + +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, - LLVMWebKitJSCallConv = 12, - LLVMAnyRegCallConv = 13, - LLVMX86StdcallCallConv = 64, - LLVMX86FastcallCallConv = 65 + LLVMCCallConv = 0, + LLVMFastCallConv = 8, + LLVMColdCallConv = 9, + LLVMGHCCallConv = 10, + LLVMHiPECallConv = 11, + LLVMWebKitJSCallConv = 12, + LLVMAnyRegCallConv = 13, + LLVMPreserveMostCallConv = 14, + LLVMPreserveAllCallConv = 15, + LLVMSwiftCallConv = 16, + LLVMCXXFASTTLSCallConv = 17, + LLVMX86StdcallCallConv = 64, + LLVMX86FastcallCallConv = 65, + LLVMARMAPCSCallConv = 66, + LLVMARMAAPCSCallConv = 67, + LLVMARMAAPCSVFPCallConv = 68, + LLVMMSP430INTRCallConv = 69, + LLVMX86ThisCallCallConv = 70, + LLVMPTXKernelCallConv = 71, + LLVMPTXDeviceCallConv = 72, + LLVMSPIRFUNCCallConv = 75, + LLVMSPIRKERNELCallConv = 76, + LLVMIntelOCLBICallConv = 77, + LLVMX8664SysVCallConv = 78, + LLVMWin64CallConv = 79, + LLVMX86VectorCallCallConv = 80, + LLVMHHVMCallConv = 81, + LLVMHHVMCCallConv = 82, + LLVMX86INTRCallConv = 83, + LLVMAVRINTRCallConv = 84, + LLVMAVRSIGNALCallConv = 85, + LLVMAVRBUILTINCallConv = 86, + LLVMAMDGPUVSCallConv = 87, + LLVMAMDGPUGSCallConv = 88, + LLVMAMDGPUPSCallConv = 89, + LLVMAMDGPUCSCallConv = 90, + LLVMAMDGPUKERNELCallConv = 91, + LLVMX86RegCallCallConv = 92, + LLVMAMDGPUHSCallConv = 93, + LLVMMSP430BUILTINCallConv = 94, + LLVMAMDGPULSCallConv = 95, + LLVMAMDGPUESCallConv = 96 } LLVMCallConv; typedef enum { @@ -335,6 +376,62 @@ typedef enum { LLVMDSNote } LLVMDiagnosticSeverity; +typedef enum { + LLVMInlineAsmDialectATT, + LLVMInlineAsmDialectIntel +} LLVMInlineAsmDialect; + +typedef enum { + /** + * Emits an error if two values disagree, otherwise the resulting value is + * that of the operands. + * + * @see Module::ModFlagBehavior::Error + */ + LLVMModuleFlagBehaviorError, + /** + * Emits a warning if two values disagree. The result value will be the + * operand for the flag from the first module being linked. + * + * @see Module::ModFlagBehavior::Warning + */ + LLVMModuleFlagBehaviorWarning, + /** + * Adds a requirement that another module flag be present and have a + * specified value after linking is performed. The value must be a metadata + * pair, where the first element of the pair is the ID of the module flag + * to be restricted, and the second element of the pair is the value the + * module flag should be restricted to. This behavior can be used to + * restrict the allowable results (via triggering of an error) of linking + * IDs with the **Override** behavior. + * + * @see Module::ModFlagBehavior::Require + */ + LLVMModuleFlagBehaviorRequire, + /** + * Uses the specified value, regardless of the behavior or value of the + * other module. If both modules specify **Override**, but the values + * differ, an error will be emitted. + * + * @see Module::ModFlagBehavior::Override + */ + LLVMModuleFlagBehaviorOverride, + /** + * Appends the two values, which are required to be metadata nodes. + * + * @see Module::ModFlagBehavior::Append + */ + LLVMModuleFlagBehaviorAppend, + /** + * Appends the two values, which are required to be metadata + * nodes. However, duplicate entries in the second list are dropped + * during the append operation. + * + * @see Module::ModFlagBehavior::AppendUnique + */ + LLVMModuleFlagBehaviorAppendUnique, +} LLVMModuleFlagBehavior; + /** * Attribute index are either LLVMAttributeReturnIndex, * LLVMAttributeFunctionIndex or a parameter number from 1 to N. @@ -566,6 +663,27 @@ const char *LLVMGetModuleIdentifier(LLVMModuleRef M, size_t *Len); void LLVMSetModuleIdentifier(LLVMModuleRef M, const char *Ident, size_t Len); /** + * Obtain the module's original source file name. + * + * @param M Module to obtain the name of + * @param Len Out parameter which holds the length of the returned string + * @return The original source file name of M + * @see Module::getSourceFileName() + */ +const char *LLVMGetSourceFileName(LLVMModuleRef M, size_t *Len); + +/** + * Set the original source file name of a module to a string Name with length + * Len. + * + * @param M The module to set the source file name of + * @param Name The string to set M's source file name to + * @param Len Length of Name + * @see Module::setSourceFileName() + */ +void LLVMSetSourceFileName(LLVMModuleRef M, const char *Name, size_t Len); + +/** * Obtain the data layout for a module. * * @see Module::getDataLayoutStr() @@ -599,6 +717,64 @@ const char *LLVMGetTarget(LLVMModuleRef M); void LLVMSetTarget(LLVMModuleRef M, const char *Triple); /** + * Returns the module flags as an array of flag-key-value triples. The caller + * is responsible for freeing this array by calling + * \c LLVMDisposeModuleFlagsMetadata. + * + * @see Module::getModuleFlagsMetadata() + */ +LLVMModuleFlagEntry *LLVMCopyModuleFlagsMetadata(LLVMModuleRef M, size_t *Len); + +/** + * Destroys module flags metadata entries. + */ +void LLVMDisposeModuleFlagsMetadata(LLVMModuleFlagEntry *Entries); + +/** + * Returns the flag behavior for a module flag entry at a specific index. + * + * @see Module::ModuleFlagEntry::Behavior + */ +LLVMModuleFlagBehavior +LLVMModuleFlagEntriesGetFlagBehavior(LLVMModuleFlagEntry *Entries, + unsigned Index); + +/** + * Returns the key for a module flag entry at a specific index. + * + * @see Module::ModuleFlagEntry::Key + */ +const char *LLVMModuleFlagEntriesGetKey(LLVMModuleFlagEntry *Entries, + unsigned Index, size_t *Len); + +/** + * Returns the metadata for a module flag entry at a specific index. + * + * @see Module::ModuleFlagEntry::Val + */ +LLVMMetadataRef LLVMModuleFlagEntriesGetMetadata(LLVMModuleFlagEntry *Entries, + unsigned Index); + +/** + * Add a module-level flag to the module-level flags metadata if it doesn't + * already exist. + * + * @see Module::getModuleFlag() + */ +LLVMMetadataRef LLVMGetModuleFlag(LLVMModuleRef M, + const char *Key, size_t KeyLen); + +/** + * Add a module-level flag to the module-level flags metadata if it doesn't + * already exist. + * + * @see Module::addModuleFlag() + */ +void LLVMAddModuleFlag(LLVMModuleRef M, LLVMModuleFlagBehavior Behavior, + const char *Key, size_t KeyLen, + LLVMMetadataRef Val); + +/** * Dump a representation of a module to stderr. * * @see Module::dump() @@ -623,11 +799,36 @@ LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename, char *LLVMPrintModuleToString(LLVMModuleRef M); /** + * Get inline assembly for a module. + * + * @see Module::getModuleInlineAsm() + */ +const char *LLVMGetModuleInlineAsm(LLVMModuleRef M, size_t *Len); + +/** * Set inline assembly for a module. * * @see Module::setModuleInlineAsm() */ -void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm); +void LLVMSetModuleInlineAsm2(LLVMModuleRef M, const char *Asm, size_t Len); + +/** + * Append inline assembly to a module. + * + * @see Module::appendModuleInlineAsm() + */ +void LLVMAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm, size_t Len); + +/** + * Create the specified uniqued inline asm string. + * + * @see InlineAsm::get() + */ +LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, + char *AsmString, size_t AsmStringSize, + char *Constraints, size_t ConstraintsSize, + LLVMBool HasSideEffects, LLVMBool IsAlignStack, + LLVMInlineAsmDialect Dialect); /** * Obtain the context to which this module is associated. @@ -718,6 +919,9 @@ LLVMValueRef LLVMGetNextFunction(LLVMValueRef Fn); */ LLVMValueRef LLVMGetPreviousFunction(LLVMValueRef Fn); +/** Deprecated: Use LLVMSetModuleInlineAsm2 instead. */ +void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm); + /** * @} */ @@ -1292,14 +1496,14 @@ LLVMValueKind LLVMGetValueKind(LLVMValueRef Val); * * @see llvm::Value::getName() */ -const char *LLVMGetValueName(LLVMValueRef Val); +const char *LLVMGetValueName2(LLVMValueRef Val, size_t *Length); /** * Set the string name of a value. * * @see llvm::Value::setName() */ -void LLVMSetValueName(LLVMValueRef Val, const char *Name); +void LLVMSetValueName2(LLVMValueRef Val, const char *Name, size_t NameLen); /** * Dump a representation of a value to stderr. @@ -1351,6 +1555,11 @@ LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val); LLVMValueRef LLVMIsAMDString(LLVMValueRef Val); +/** Deprecated: Use LLVMGetValueName2 instead. */ +const char *LLVMGetValueName(LLVMValueRef Val); +/** Deprecated: Use LLVMSetValueName2 instead. */ +void LLVMSetValueName(LLVMValueRef Val, const char *Name); + /** * @} */ @@ -1793,10 +2002,12 @@ LLVMValueRef LLVMConstExtractValue(LLVMValueRef AggConstant, unsigned *IdxList, LLVMValueRef LLVMConstInsertValue(LLVMValueRef AggConstant, LLVMValueRef ElementValueConstant, unsigned *IdxList, unsigned NumIdx); +LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB); + +/** Deprecated: Use LLVMGetInlineAsm instead. */ LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty, const char *AsmString, const char *Constraints, LLVMBool HasSideEffects, LLVMBool IsAlignStack); -LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB); /** * @} @@ -1823,7 +2034,12 @@ LLVMVisibility LLVMGetVisibility(LLVMValueRef Global); void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz); LLVMDLLStorageClass LLVMGetDLLStorageClass(LLVMValueRef Global); void LLVMSetDLLStorageClass(LLVMValueRef Global, LLVMDLLStorageClass Class); +LLVMUnnamedAddr LLVMGetUnnamedAddress(LLVMValueRef Global); +void LLVMSetUnnamedAddress(LLVMValueRef Global, LLVMUnnamedAddr UnnamedAddr); + +/** Deprecated: Use LLVMGetUnnamedAddress instead. */ LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global); +/** Deprecated: Use LLVMSetUnnamedAddress instead. */ void LLVMSetUnnamedAddr(LLVMValueRef Global, LLVMBool HasUnnamedAddr); /** @@ -1902,6 +2118,56 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee, const char *Name); /** + * Obtain a GlobalAlias value from a Module by its name. + * + * The returned value corresponds to a llvm::GlobalAlias value. + * + * @see llvm::Module::getNamedAlias() + */ +LLVMValueRef LLVMGetNamedGlobalAlias(LLVMModuleRef M, + const char *Name, size_t NameLen); + +/** + * Obtain an iterator to the first GlobalAlias in a Module. + * + * @see llvm::Module::alias_begin() + */ +LLVMValueRef LLVMGetFirstGlobalAlias(LLVMModuleRef M); + +/** + * Obtain an iterator to the last GlobalAlias in a Module. + * + * @see llvm::Module::alias_end() + */ +LLVMValueRef LLVMGetLastGlobalAlias(LLVMModuleRef M); + +/** + * Advance a GlobalAlias iterator to the next GlobalAlias. + * + * Returns NULL if the iterator was already at the end and there are no more + * global aliases. + */ +LLVMValueRef LLVMGetNextGlobalAlias(LLVMValueRef GA); + +/** + * Decrement a GlobalAlias iterator to the previous GlobalAlias. + * + * Returns NULL if the iterator was already at the beginning and there are + * no previous global aliases. + */ +LLVMValueRef LLVMGetPreviousGlobalAlias(LLVMValueRef GA); + +/** + * Retrieve the target value of an alias. + */ +LLVMValueRef LLVMAliasGetAliasee(LLVMValueRef Alias); + +/** + * Set the target value of an alias. + */ +void LLVMAliasSetAliasee(LLVMValueRef Alias, LLVMValueRef Aliasee); + +/** * @} */ @@ -2523,11 +2789,12 @@ LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst); /** * Obtain the argument count for a call instruction. * - * This expects an LLVMValueRef that corresponds to a llvm::CallInst or - * llvm::InvokeInst. + * This expects an LLVMValueRef that corresponds to a llvm::CallInst, + * llvm::InvokeInst, or llvm:FuncletPadInst. * * @see llvm::CallInst::getNumArgOperands() * @see llvm::InvokeInst::getNumArgOperands() + * @see llvm::FuncletPadInst::getNumArgOperands() */ unsigned LLVMGetNumArgOperands(LLVMValueRef Instr); @@ -2612,9 +2879,12 @@ LLVMBasicBlockRef LLVMGetNormalDest(LLVMValueRef InvokeInst); /** * Return the unwind destination basic block. * - * This only works on llvm::InvokeInst instructions. + * Works on llvm::InvokeInst, llvm::CleanupReturnInst, and + * llvm::CatchSwitchInst instructions. * * @see llvm::InvokeInst::getUnwindDest() + * @see llvm::CleanupReturnInst::getUnwindDest() + * @see llvm::CatchSwitchInst::getUnwindDest() */ LLVMBasicBlockRef LLVMGetUnwindDest(LLVMValueRef InvokeInst); @@ -2630,9 +2900,12 @@ void LLVMSetNormalDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B); /** * Set the unwind destination basic block. * - * This only works on llvm::InvokeInst instructions. + * Works on llvm::InvokeInst, llvm::CleanupReturnInst, and + * llvm::CatchSwitchInst instructions. * * @see llvm::InvokeInst::setUnwindDest() + * @see llvm::CleanupReturnInst::setUnwindDest() + * @see llvm::CatchSwitchInst::setUnwindDest() */ void LLVMSetUnwindDest(LLVMValueRef InvokeInst, LLVMBasicBlockRef B); @@ -2861,11 +3134,26 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, const char *Name); +LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef); + +/* Exception Handling */ +LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn); LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef PersFn, unsigned NumClauses, const char *Name); -LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn); -LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef); +LLVMValueRef LLVMBuildCleanupRet(LLVMBuilderRef B, LLVMValueRef CatchPad, + LLVMBasicBlockRef BB); +LLVMValueRef LLVMBuildCatchRet(LLVMBuilderRef B, LLVMValueRef CatchPad, + LLVMBasicBlockRef BB); +LLVMValueRef LLVMBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); +LLVMValueRef LLVMBuildCleanupPad(LLVMBuilderRef B, LLVMValueRef ParentPad, + LLVMValueRef *Args, unsigned NumArgs, + const char *Name); +LLVMValueRef LLVMBuildCatchSwitch(LLVMBuilderRef B, LLVMValueRef ParentPad, + LLVMBasicBlockRef UnwindBB, + unsigned NumHandlers, const char *Name); /* Add a case to the switch instruction */ void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal, @@ -2889,6 +3177,51 @@ LLVMBool LLVMIsCleanup(LLVMValueRef LandingPad); /* Set the 'cleanup' flag in the landingpad instruction */ void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val); +/* Add a destination to the catchswitch instruction */ +void LLVMAddHandler(LLVMValueRef CatchSwitch, LLVMBasicBlockRef Dest); + +/* Get the number of handlers on the catchswitch instruction */ +unsigned LLVMGetNumHandlers(LLVMValueRef CatchSwitch); + +/** + * Obtain the basic blocks acting as handlers for a catchswitch instruction. + * + * The Handlers parameter should point to a pre-allocated array of + * LLVMBasicBlockRefs at least LLVMGetNumHandlers() large. On return, the + * first LLVMGetNumHandlers() entries in the array will be populated + * with LLVMBasicBlockRef instances. + * + * @param CatchSwitch The catchswitch instruction to operate on. + * @param Handlers Memory address of an array to be filled with basic blocks. + */ +void LLVMGetHandlers(LLVMValueRef CatchSwitch, LLVMBasicBlockRef *Handlers); + +/* Funclets */ + +/* Get the number of funcletpad arguments. */ +LLVMValueRef LLVMGetArgOperand(LLVMValueRef Funclet, unsigned i); + +/* Set a funcletpad argument at the given index. */ +void LLVMSetArgOperand(LLVMValueRef Funclet, unsigned i, LLVMValueRef value); + +/** + * Get the parent catchswitch instruction of a catchpad instruction. + * + * This only works on llvm::CatchPadInst instructions. + * + * @see llvm::CatchPadInst::getCatchSwitch() + */ +LLVMValueRef LLVMGetParentCatchSwitch(LLVMValueRef CatchPad); + +/** + * Set the parent catchswitch instruction of a catchpad instruction. + * + * This only works on llvm::CatchPadInst instructions. + * + * @see llvm::CatchPadInst::setCatchSwitch() + */ +void LLVMSetParentCatchSwitch(LLVMValueRef CatchPad, LLVMValueRef CatchSwitch); + /* Arithmetic */ LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); @@ -3186,7 +3519,7 @@ LLVMBool LLVMInitializeFunctionPassManager(LLVMPassManagerRef FPM); @see llvm::FunctionPassManager::run(Function&) */ LLVMBool LLVMRunFunctionPassManager(LLVMPassManagerRef FPM, LLVMValueRef F); -/** Finalizes all of the function passes scheduled in in the function pass +/** Finalizes all of the function passes scheduled in the function pass manager. Returns 1 if any of the passes modified the module, 0 otherwise. @see llvm::FunctionPassManager::doFinalization */ LLVMBool LLVMFinalizeFunctionPassManager(LLVMPassManagerRef FPM); diff --git a/contrib/llvm/include/llvm-c/DataTypes.h b/contrib/llvm/include/llvm-c/DataTypes.h new file mode 100644 index 000000000000..7081c83ffc2b --- /dev/null +++ b/contrib/llvm/include/llvm-c/DataTypes.h @@ -0,0 +1,90 @@ +/*===-- include/llvm-c/DataTypes.h - Define fixed size 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 contains definitions to figure out the size of _HOST_ data types.*| +|* This file is important because different host OS's define different macros,*| +|* which makes portability tough. This file exports the following *| +|* definitions: *| +|* *| +|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| +|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| +|* *| +|* No library is required when using these functions. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +/* Please leave this file C-compatible. */ + +#ifndef LLVM_C_DATATYPES_H +#define LLVM_C_DATATYPES_H + +#ifdef __cplusplus +#include <cmath> +#else +#include <math.h> +#endif + +#include <inttypes.h> +#include <stdint.h> + +#ifndef _MSC_VER + +#if !defined(UINT32_MAX) +# error "The standard header <cstdint> is not C++11 compliant. Must #define "\ + "__STDC_LIMIT_MACROS before #including llvm-c/DataTypes.h" +#endif + +#if !defined(UINT32_C) +# error "The standard header <cstdint> is not C++11 compliant. Must #define "\ + "__STDC_CONSTANT_MACROS before #including llvm-c/DataTypes.h" +#endif + +/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ +#include <sys/types.h> + +#ifdef _AIX +// GCC is strict about defining large constants: they must have LL modifier. +#undef INT64_MAX +#undef INT64_MIN +#endif + +#else /* _MSC_VER */ +#ifdef __cplusplus +#include <cstddef> +#include <cstdlib> +#else +#include <stddef.h> +#include <stdlib.h> +#endif +#include <sys/types.h> + +#if defined(_WIN64) +typedef signed __int64 ssize_t; +#else +typedef signed int ssize_t; +#endif /* _WIN64 */ + +#endif /* _MSC_VER */ + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* LLVM_C_DATATYPES_H */ diff --git a/contrib/llvm/include/llvm-c/DebugInfo.h b/contrib/llvm/include/llvm-c/DebugInfo.h index d17c690be4da..cee6755f1874 100644 --- a/contrib/llvm/include/llvm-c/DebugInfo.h +++ b/contrib/llvm/include/llvm-c/DebugInfo.h @@ -52,6 +52,11 @@ typedef enum { LLVMDIFlagBitField = 1 << 19, LLVMDIFlagNoReturn = 1 << 20, LLVMDIFlagMainSubprogram = 1 << 21, + LLVMDIFlagTypePassByValue = 1 << 22, + LLVMDIFlagTypePassByReference = 1 << 23, + LLVMDIFlagFixedEnum = 1 << 24, + LLVMDIFlagThunk = 1 << 25, + LLVMDIFlagTrivial = 1 << 26, LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5), LLVMDIFlagAccessibility = LLVMDIFlagPrivate | LLVMDIFlagProtected | LLVMDIFlagPublic, @@ -120,6 +125,11 @@ typedef enum { } LLVMDWARFEmissionKind; /** + * An LLVM DWARF type encoding. + */ +typedef unsigned LLVMDWARFTypeEncoding; + +/** * The current debug metadata version number. */ unsigned LLVMDebugMetadataVersion(void); @@ -211,6 +221,158 @@ LLVMDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename, size_t DirectoryLen); /** + * Creates a new descriptor for a module with the specified parent scope. + * \param Builder The \c DIBuilder. + * \param ParentScope The parent scope containing this module declaration. + * \param Name Module name. + * \param NameLen The length of the C string passed to \c Name. + * \param ConfigMacros A space-separated shell-quoted list of -D macro + definitions as they would appear on a command line. + * \param ConfigMacrosLen The length of the C string passed to \c ConfigMacros. + * \param IncludePath The path to the module map file. + * \param IncludePathLen The length of the C string passed to \c IncludePath. + * \param ISysRoot The Clang system root (value of -isysroot). + * \param ISysRootLen The length of the C string passed to \c ISysRoot. + */ +LLVMMetadataRef +LLVMDIBuilderCreateModule(LLVMDIBuilderRef Builder, LLVMMetadataRef ParentScope, + const char *Name, size_t NameLen, + const char *ConfigMacros, size_t ConfigMacrosLen, + const char *IncludePath, size_t IncludePathLen, + const char *ISysRoot, size_t ISysRootLen); + +/** + * Creates a new descriptor for a namespace with the specified parent scope. + * \param Builder The \c DIBuilder. + * \param ParentScope The parent scope containing this module declaration. + * \param Name NameSpace name. + * \param NameLen The length of the C string passed to \c Name. + * \param ExportSymbols Whether or not the namespace exports symbols, e.g. + * this is true of C++ inline namespaces. + */ +LLVMMetadataRef +LLVMDIBuilderCreateNameSpace(LLVMDIBuilderRef Builder, + LLVMMetadataRef ParentScope, + const char *Name, size_t NameLen, + LLVMBool ExportSymbols); + +/** + * Create a new descriptor for the specified subprogram. + * \param Builder The \c DIBuilder. + * \param Scope Function scope. + * \param Name Function name. + * \param NameLen Length of enumeration name. + * \param LinkageName Mangled function name. + * \param LinkageNameLen Length of linkage name. + * \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 IsDefinition True if this is a function definition. + * \param ScopeLine Set to the beginning of the scope this starts + * \param Flags E.g.: \c LLVMDIFlagLValueReference. These flags are + * used to emit dwarf attributes. + * \param IsOptimized True if optimization is ON. + */ +LLVMMetadataRef LLVMDIBuilderCreateFunction( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *LinkageName, size_t LinkageNameLen, + LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, + LLVMBool IsLocalToUnit, LLVMBool IsDefinition, + unsigned ScopeLine, LLVMDIFlags Flags, LLVMBool IsOptimized); + +/** + * Create a descriptor for a lexical block with the specified parent context. + * \param Builder The \c DIBuilder. + * \param Scope Parent lexical block. + * \param File Source file. + * \param Line The line in the source file. + * \param Column The column in the source file. + */ +LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, + LLVMMetadataRef File, unsigned Line, unsigned Column); + +/** + * Create a descriptor for a lexical block with a new file attached. + * \param Builder The \c DIBuilder. + * \param Scope Lexical block. + * \param File Source file. + * \param Discriminator DWARF path discriminator value. + */ +LLVMMetadataRef +LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + LLVMMetadataRef File, + unsigned Discriminator); + +/** + * Create a descriptor for an imported namespace. Suitable for e.g. C++ + * using declarations. + * \param Builder The \c DIBuilder. + * \param Scope The scope this module is imported into + * \param File File where the declaration is located. + * \param Line Line number of the declaration. + */ +LLVMMetadataRef +LLVMDIBuilderCreateImportedModuleFromNamespace(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + LLVMMetadataRef NS, + LLVMMetadataRef File, + unsigned Line); + +/** + * Create a descriptor for an imported module that aliases another + * imported entity descriptor. + * \param Builder The \c DIBuilder. + * \param Scope The scope this module is imported into + * \param ImportedEntity Previous imported entity to alias. + * \param File File where the declaration is located. + * \param Line Line number of the declaration. + */ +LLVMMetadataRef +LLVMDIBuilderCreateImportedModuleFromAlias(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + LLVMMetadataRef ImportedEntity, + LLVMMetadataRef File, + unsigned Line); + +/** + * Create a descriptor for an imported module. + * \param Builder The \c DIBuilder. + * \param Scope The scope this module is imported into + * \param M The module being imported here + * \param File File where the declaration is located. + * \param Line Line number of the declaration. + */ +LLVMMetadataRef +LLVMDIBuilderCreateImportedModuleFromModule(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + LLVMMetadataRef M, + LLVMMetadataRef File, + unsigned Line); + +/** + * Create a descriptor for an imported function, type, or variable. Suitable + * for e.g. FORTRAN-style USE declarations. + * \param Builder The DIBuilder. + * \param Scope The scope this module is imported into. + * \param Decl The declaration (or definition) of a function, type, + or variable. + * \param File File where the declaration is located. + * \param Line Line number of the declaration. + * \param Name A name that uniquely identifies this imported declaration. + * \param NameLen The length of the C string passed to \c Name. + */ +LLVMMetadataRef +LLVMDIBuilderCreateImportedDeclaration(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + LLVMMetadataRef Decl, + LLVMMetadataRef File, + unsigned Line, + const char *Name, size_t NameLen); + +/** * Creates a new DebugLocation that describes a source location. * \param Line The line in the source file. * \param Column The column in the source file. @@ -225,6 +387,768 @@ LLVMDIBuilderCreateDebugLocation(LLVMContextRef Ctx, unsigned Line, unsigned Column, LLVMMetadataRef Scope, LLVMMetadataRef InlinedAt); +/** + * Get the line number of this debug location. + * \param Location The debug location. + * + * @see DILocation::getLine() + */ +unsigned LLVMDILocationGetLine(LLVMMetadataRef Location); + +/** + * Get the column number of this debug location. + * \param Location The debug location. + * + * @see DILocation::getColumn() + */ +unsigned LLVMDILocationGetColumn(LLVMMetadataRef Location); + +/** + * Get the local scope associated with this debug location. + * \param Location The debug location. + * + * @see DILocation::getScope() + */ +LLVMMetadataRef LLVMDILocationGetScope(LLVMMetadataRef Location); + +/** + * Create a type array. + * \param Builder The DIBuilder. + * \param Data The type elements. + * \param NumElements Number of type elements. + */ +LLVMMetadataRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef Builder, + LLVMMetadataRef *Data, + size_t NumElements); + +/** + * Create subroutine type. + * \param Builder The DIBuilder. + * \param File The file in which the subroutine resides. + * \param ParameterTypes An array of subroutine parameter types. This + * includes return type at 0th index. + * \param NumParameterTypes The number of parameter types in \c ParameterTypes + * \param Flags E.g.: \c LLVMDIFlagLValueReference. + * These flags are used to emit dwarf attributes. + */ +LLVMMetadataRef +LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Builder, + LLVMMetadataRef File, + LLVMMetadataRef *ParameterTypes, + unsigned NumParameterTypes, + LLVMDIFlags Flags); + +/** + * Create debugging information entry for an enumeration. + * \param Builder The DIBuilder. + * \param Scope Scope in which this enumeration is defined. + * \param Name Enumeration name. + * \param NameLen Length of enumeration name. + * \param File File where this member is defined. + * \param LineNumber Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param Elements Enumeration elements. + * \param NumElements Number of enumeration elements. + * \param ClassTy Underlying type of a C++11/ObjC fixed enum. + */ +LLVMMetadataRef LLVMDIBuilderCreateEnumerationType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef *Elements, + unsigned NumElements, LLVMMetadataRef ClassTy); + +/** + * Create debugging information entry for a union. + * \param Builder The DIBuilder. + * \param Scope Scope in which this union is defined. + * \param Name Union name. + * \param NameLen Length of union name. + * \param File File where this member is defined. + * \param LineNumber Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param Flags Flags to encode member attribute, e.g. private + * \param Elements Union elements. + * \param NumElements Number of union elements. + * \param RunTimeLang Optional parameter, Objective-C runtime version. + * \param UniqueId A unique identifier for the union. + * \param UniqueIdLen Length of unique identifier. + */ +LLVMMetadataRef LLVMDIBuilderCreateUnionType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags, + LLVMMetadataRef *Elements, unsigned NumElements, unsigned RunTimeLang, + const char *UniqueId, size_t UniqueIdLen); + + +/** + * Create debugging information entry for an array. + * \param Builder The DIBuilder. + * \param Size Array size. + * \param AlignInBits Alignment. + * \param Ty Element type. + * \param Subscripts Subscripts. + * \param NumSubscripts Number of subscripts. + */ +LLVMMetadataRef +LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Builder, uint64_t Size, + uint32_t AlignInBits, LLVMMetadataRef Ty, + LLVMMetadataRef *Subscripts, + unsigned NumSubscripts); + +/** + * Create debugging information entry for a vector type. + * \param Builder The DIBuilder. + * \param Size Vector size. + * \param AlignInBits Alignment. + * \param Ty Element type. + * \param Subscripts Subscripts. + * \param NumSubscripts Number of subscripts. + */ +LLVMMetadataRef +LLVMDIBuilderCreateVectorType(LLVMDIBuilderRef Builder, uint64_t Size, + uint32_t AlignInBits, LLVMMetadataRef Ty, + LLVMMetadataRef *Subscripts, + unsigned NumSubscripts); + +/** + * Create a DWARF unspecified type. + * \param Builder The DIBuilder. + * \param Name The unspecified type's name. + * \param NameLen Length of type name. + */ +LLVMMetadataRef +LLVMDIBuilderCreateUnspecifiedType(LLVMDIBuilderRef Builder, const char *Name, + size_t NameLen); + +/** + * Create debugging information entry for a basic + * type. + * \param Builder The DIBuilder. + * \param Name Type name. + * \param NameLen Length of type name. + * \param SizeInBits Size of the type. + * \param Encoding DWARF encoding code, e.g. \c LLVMDWARFTypeEncoding_float. + */ +LLVMMetadataRef +LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Builder, const char *Name, + size_t NameLen, uint64_t SizeInBits, + LLVMDWARFTypeEncoding Encoding); + +/** + * Create debugging information entry for a pointer. + * \param Builder The DIBuilder. + * \param PointeeTy Type pointed by this pointer. + * \param SizeInBits Size. + * \param AlignInBits Alignment. (optional, pass 0 to ignore) + * \param AddressSpace DWARF address space. (optional, pass 0 to ignore) + * \param Name Pointer type name. (optional) + * \param NameLen Length of pointer type name. (optional) + */ +LLVMMetadataRef LLVMDIBuilderCreatePointerType( + LLVMDIBuilderRef Builder, LLVMMetadataRef PointeeTy, + uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace, + const char *Name, size_t NameLen); + +/** + * Create debugging information entry for a struct. + * \param Builder The DIBuilder. + * \param Scope Scope in which this struct is defined. + * \param Name Struct name. + * \param NameLen Struct name length. + * \param File File where this member is defined. + * \param LineNumber Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param Flags Flags to encode member attribute, e.g. private + * \param Elements Struct elements. + * \param NumElements Number of struct elements. + * \param RunTimeLang Optional parameter, Objective-C runtime version. + * \param VTableHolder The object containing the vtable for the struct. + * \param UniqueId A unique identifier for the struct. + * \param UniqueIdLen Length of the unique identifier for the struct. + */ +LLVMMetadataRef LLVMDIBuilderCreateStructType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, LLVMDIFlags Flags, + LLVMMetadataRef DerivedFrom, LLVMMetadataRef *Elements, + unsigned NumElements, unsigned RunTimeLang, LLVMMetadataRef VTableHolder, + const char *UniqueId, size_t UniqueIdLen); + +/** + * Create debugging information entry for a member. + * \param Builder The DIBuilder. + * \param Scope Member scope. + * \param Name Member name. + * \param NameLen Length of member name. + * \param File File where this member is defined. + * \param LineNo Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param OffsetInBits Member offset. + * \param Flags Flags to encode member attribute, e.g. private + * \param Ty Parent type. + */ +LLVMMetadataRef LLVMDIBuilderCreateMemberType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNo, + uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, + LLVMDIFlags Flags, LLVMMetadataRef Ty); + +/** + * Create debugging information entry for a + * C++ static data member. + * \param Builder The DIBuilder. + * \param Scope Member scope. + * \param Name Member name. + * \param NameLen Length of member name. + * \param File File where this member is declared. + * \param LineNumber Line number. + * \param Type Type of the static member. + * \param Flags Flags to encode member attribute, e.g. private. + * \param ConstantVal Const initializer of the member. + * \param AlignInBits Member alignment. + */ +LLVMMetadataRef +LLVMDIBuilderCreateStaticMemberType( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, + LLVMMetadataRef Type, LLVMDIFlags Flags, LLVMValueRef ConstantVal, + uint32_t AlignInBits); + +/** + * Create debugging information entry for a pointer to member. + * \param Builder The DIBuilder. + * \param PointeeType Type pointed to by this pointer. + * \param ClassType Type for which this pointer points to members of. + * \param SizeInBits Size. + * \param AlignInBits Alignment. + * \param Flags Flags. + */ +LLVMMetadataRef +LLVMDIBuilderCreateMemberPointerType(LLVMDIBuilderRef Builder, + LLVMMetadataRef PointeeType, + LLVMMetadataRef ClassType, + uint64_t SizeInBits, + uint32_t AlignInBits, + LLVMDIFlags Flags); +/** + * Create debugging information entry for Objective-C instance variable. + * \param Builder The DIBuilder. + * \param Name Member name. + * \param NameLen The length of the C string passed to \c Name. + * \param File File where this member is defined. + * \param LineNo Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param OffsetInBits Member offset. + * \param Flags Flags to encode member attribute, e.g. private + * \param Ty Parent type. + * \param PropertyNode Property associated with this ivar. + */ +LLVMMetadataRef +LLVMDIBuilderCreateObjCIVar(LLVMDIBuilderRef Builder, + const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNo, + uint64_t SizeInBits, uint32_t AlignInBits, + uint64_t OffsetInBits, LLVMDIFlags Flags, + LLVMMetadataRef Ty, LLVMMetadataRef PropertyNode); + +/** + * Create debugging information entry for Objective-C property. + * \param Builder The DIBuilder. + * \param Name Property name. + * \param NameLen The length of the C string passed to \c Name. + * \param File File where this property is defined. + * \param LineNo Line number. + * \param GetterName Name of the Objective C property getter selector. + * \param GetterNameLen The length of the C string passed to \c GetterName. + * \param SetterName Name of the Objective C property setter selector. + * \param SetterNameLen The length of the C string passed to \c SetterName. + * \param PropertyAttributes Objective C property attributes. + * \param Ty Type. + */ +LLVMMetadataRef +LLVMDIBuilderCreateObjCProperty(LLVMDIBuilderRef Builder, + const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNo, + const char *GetterName, size_t GetterNameLen, + const char *SetterName, size_t SetterNameLen, + unsigned PropertyAttributes, + LLVMMetadataRef Ty); + +/** + * Create a uniqued DIType* clone with FlagObjectPointer and FlagArtificial set. + * \param Builder The DIBuilder. + * \param Type The underlying type to which this pointer points. + */ +LLVMMetadataRef +LLVMDIBuilderCreateObjectPointerType(LLVMDIBuilderRef Builder, + LLVMMetadataRef Type); + +/** + * Create debugging information entry for a qualified + * type, e.g. 'const int'. + * \param Builder The DIBuilder. + * \param Tag Tag identifying type, + * e.g. LLVMDWARFTypeQualifier_volatile_type + * \param Type Base Type. + */ +LLVMMetadataRef +LLVMDIBuilderCreateQualifiedType(LLVMDIBuilderRef Builder, unsigned Tag, + LLVMMetadataRef Type); + +/** + * Create debugging information entry for a c++ + * style reference or rvalue reference type. + * \param Builder The DIBuilder. + * \param Tag Tag identifying type, + * \param Type Base Type. + */ +LLVMMetadataRef +LLVMDIBuilderCreateReferenceType(LLVMDIBuilderRef Builder, unsigned Tag, + LLVMMetadataRef Type); + +/** + * Create C++11 nullptr type. + * \param Builder The DIBuilder. + */ +LLVMMetadataRef +LLVMDIBuilderCreateNullPtrType(LLVMDIBuilderRef Builder); + +/** + * Create debugging information entry for a typedef. + * \param Builder The DIBuilder. + * \param Type Original type. + * \param Name Typedef name. + * \param File File where this type is defined. + * \param LineNo Line number. + * \param Scope The surrounding context for the typedef. + */ +LLVMMetadataRef +LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Builder, LLVMMetadataRef Type, + const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNo, + LLVMMetadataRef Scope); + +/** + * Create debugging information entry to establish inheritance relationship + * between two types. + * \param Builder The DIBuilder. + * \param Ty Original type. + * \param BaseTy Base type. Ty is inherits from base. + * \param BaseOffset Base offset. + * \param VBPtrOffset Virtual base pointer offset. + * \param Flags Flags to describe inheritance attribute, e.g. private + */ +LLVMMetadataRef +LLVMDIBuilderCreateInheritance(LLVMDIBuilderRef Builder, + LLVMMetadataRef Ty, LLVMMetadataRef BaseTy, + uint64_t BaseOffset, uint32_t VBPtrOffset, + LLVMDIFlags Flags); + +/** + * Create a permanent forward-declared type. + * \param Builder The DIBuilder. + * \param Tag A unique tag for this type. + * \param Name Type name. + * \param NameLen Length of type name. + * \param Scope Type scope. + * \param File File where this type is defined. + * \param Line Line number where this type is defined. + * \param RuntimeLang Indicates runtime version for languages like + * Objective-C. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param UniqueIdentifier A unique identifier for the type. + * \param UniqueIdentifierLen Length of the unique identifier. + */ +LLVMMetadataRef LLVMDIBuilderCreateForwardDecl( + LLVMDIBuilderRef Builder, unsigned Tag, const char *Name, + size_t NameLen, LLVMMetadataRef Scope, LLVMMetadataRef File, unsigned Line, + unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits, + const char *UniqueIdentifier, size_t UniqueIdentifierLen); + +/** + * Create a temporary forward-declared type. + * \param Builder The DIBuilder. + * \param Tag A unique tag for this type. + * \param Name Type name. + * \param NameLen Length of type name. + * \param Scope Type scope. + * \param File File where this type is defined. + * \param Line Line number where this type is defined. + * \param RuntimeLang Indicates runtime version for languages like + * Objective-C. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param Flags Flags. + * \param UniqueIdentifier A unique identifier for the type. + * \param UniqueIdentifierLen Length of the unique identifier. + */ +LLVMMetadataRef +LLVMDIBuilderCreateReplaceableCompositeType( + LLVMDIBuilderRef Builder, unsigned Tag, const char *Name, + size_t NameLen, LLVMMetadataRef Scope, LLVMMetadataRef File, unsigned Line, + unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits, + LLVMDIFlags Flags, const char *UniqueIdentifier, + size_t UniqueIdentifierLen); + +/** + * Create debugging information entry for a bit field member. + * \param Builder The DIBuilder. + * \param Scope Member scope. + * \param Name Member name. + * \param NameLen Length of member name. + * \param File File where this member is defined. + * \param LineNumber Line number. + * \param SizeInBits Member size. + * \param OffsetInBits Member offset. + * \param StorageOffsetInBits Member storage offset. + * \param Flags Flags to encode member attribute. + * \param Type Parent type. + */ +LLVMMetadataRef +LLVMDIBuilderCreateBitFieldMemberType(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNumber, + uint64_t SizeInBits, + uint64_t OffsetInBits, + uint64_t StorageOffsetInBits, + LLVMDIFlags Flags, LLVMMetadataRef Type); + +/** + * Create debugging information entry for a class. + * \param Scope Scope in which this class is defined. + * \param Name Class name. + * \param NameLen The length of the C string passed to \c Name. + * \param File File where this member is defined. + * \param LineNumber Line number. + * \param SizeInBits Member size. + * \param AlignInBits Member alignment. + * \param OffsetInBits Member offset. + * \param Flags Flags to encode member attribute, e.g. private. + * \param DerivedFrom Debug info of the base class of this type. + * \param Elements Class members. + * \param NumElements Number of class elements. + * \param VTableHolder Debug info of the base class that contains vtable + * for this type. This is used in + * DW_AT_containing_type. See DWARF documentation + * for more info. + * \param TemplateParamsNode Template type parameters. + * \param UniqueIdentifier A unique identifier for the type. + * \param UniqueIdentifierLen Length of the unique identifier. + */ +LLVMMetadataRef LLVMDIBuilderCreateClassType(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, + uint32_t AlignInBits, uint64_t OffsetInBits, LLVMDIFlags Flags, + LLVMMetadataRef DerivedFrom, + LLVMMetadataRef *Elements, unsigned NumElements, + LLVMMetadataRef VTableHolder, LLVMMetadataRef TemplateParamsNode, + const char *UniqueIdentifier, size_t UniqueIdentifierLen); + +/** + * Create a uniqued DIType* clone with FlagArtificial set. + * \param Builder The DIBuilder. + * \param Type The underlying type. + */ +LLVMMetadataRef +LLVMDIBuilderCreateArtificialType(LLVMDIBuilderRef Builder, + LLVMMetadataRef Type); + +/** + * Get the name of this DIType. + * \param DType The DIType. + * \param Length The length of the returned string. + * + * @see DIType::getName() + */ +const char *LLVMDITypeGetName(LLVMMetadataRef DType, size_t *Length); + +/** + * Get the size of this DIType in bits. + * \param DType The DIType. + * + * @see DIType::getSizeInBits() + */ +uint64_t LLVMDITypeGetSizeInBits(LLVMMetadataRef DType); + +/** + * Get the offset of this DIType in bits. + * \param DType The DIType. + * + * @see DIType::getOffsetInBits() + */ +uint64_t LLVMDITypeGetOffsetInBits(LLVMMetadataRef DType); + +/** + * Get the alignment of this DIType in bits. + * \param DType The DIType. + * + * @see DIType::getAlignInBits() + */ +uint32_t LLVMDITypeGetAlignInBits(LLVMMetadataRef DType); + +/** + * Get the source line where this DIType is declared. + * \param DType The DIType. + * + * @see DIType::getLine() + */ +unsigned LLVMDITypeGetLine(LLVMMetadataRef DType); + +/** + * Get the flags associated with this DIType. + * \param DType The DIType. + * + * @see DIType::getFlags() + */ +LLVMDIFlags LLVMDITypeGetFlags(LLVMMetadataRef DType); + +/** + * Create a descriptor for a value range. + * \param Builder The DIBuilder. + * \param LowerBound Lower bound of the subrange, e.g. 0 for C, 1 for Fortran. + * \param Count Count of elements in the subrange. + */ +LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Builder, + int64_t LowerBound, + int64_t Count); + +/** + * Create an array of DI Nodes. + * \param Builder The DIBuilder. + * \param Data The DI Node elements. + * \param NumElements Number of DI Node elements. + */ +LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Builder, + LLVMMetadataRef *Data, + size_t NumElements); + +/** + * Create a new descriptor for the specified variable which has a complex + * address expression for its address. + * \param Builder The DIBuilder. + * \param Addr An array of complex address operations. + * \param Length Length of the address operation array. + */ +LLVMMetadataRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Builder, + int64_t *Addr, size_t Length); + +/** + * Create a new descriptor for the specified variable that does not have an + * address, but does have a constant value. + * \param Builder The DIBuilder. + * \param Value The constant value. + */ +LLVMMetadataRef +LLVMDIBuilderCreateConstantValueExpression(LLVMDIBuilderRef Builder, + int64_t Value); + +/** + * Create a new descriptor for the specified variable. + * \param Scope Variable scope. + * \param Name Name of the variable. + * \param NameLen The length of the C string passed to \c Name. + * \param Linkage Mangled name of the variable. + * \param LinkLen The length of the C string passed to \c Linkage. + * \param File File where this variable is defined. + * \param LineNo Line number. + * \param Ty Variable Type. + * \param LocalToUnit Boolean flag indicate whether this variable is + * externally visible or not. + * \param Expr The location of the global relative to the attached + * GlobalVariable. + * \param Decl Reference to the corresponding declaration. + * \param AlignInBits Variable alignment(or 0 if no alignment attr was + * specified) + */ +LLVMMetadataRef +LLVMDIBuilderCreateGlobalVariableExpression(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + const char *Name, size_t NameLen, + const char *Linkage, size_t LinkLen, + LLVMMetadataRef File, + unsigned LineNo, + LLVMMetadataRef Ty, + LLVMBool LocalToUnit, + LLVMMetadataRef Expr, + LLVMMetadataRef Decl, + uint32_t AlignInBits); +/** + * Create a new temporary \c MDNode. Suitable for use in constructing cyclic + * \c MDNode structures. A temporary \c MDNode is not uniqued, may be RAUW'd, + * and must be manually deleted with \c LLVMDisposeTemporaryMDNode. + * \param Ctx The context in which to construct the temporary node. + * \param Data The metadata elements. + * \param NumElements Number of metadata elements. + */ +LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef Ctx, LLVMMetadataRef *Data, + size_t NumElements); + +/** + * Deallocate a temporary node. + * + * Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining + * references will be reset. + * \param TempNode The temporary metadata node. + */ +void LLVMDisposeTemporaryMDNode(LLVMMetadataRef TempNode); + +/** + * Replace all uses of temporary metadata. + * \param TempTargetMetadata The temporary metadata node. + * \param Replacement The replacement metadata node. + */ +void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef TempTargetMetadata, + LLVMMetadataRef Replacement); + +/** + * Create a new descriptor for the specified global variable that is temporary + * and meant to be RAUWed. + * \param Scope Variable scope. + * \param Name Name of the variable. + * \param NameLen The length of the C string passed to \c Name. + * \param Linkage Mangled name of the variable. + * \param LnkLen The length of the C string passed to \c Linkage. + * \param File File where this variable is defined. + * \param LineNo Line number. + * \param Ty Variable Type. + * \param LocalToUnit Boolean flag indicate whether this variable is + * externally visible or not. + * \param Decl Reference to the corresponding declaration. + * \param AlignInBits Variable alignment(or 0 if no alignment attr was + * specified) + */ +LLVMMetadataRef +LLVMDIBuilderCreateTempGlobalVariableFwdDecl(LLVMDIBuilderRef Builder, + LLVMMetadataRef Scope, + const char *Name, size_t NameLen, + const char *Linkage, size_t LnkLen, + LLVMMetadataRef File, + unsigned LineNo, + LLVMMetadataRef Ty, + LLVMBool LocalToUnit, + LLVMMetadataRef Decl, + uint32_t AlignInBits); + +/** + * Insert a new llvm.dbg.declare intrinsic call before the given instruction. + * \param Builder The DIBuilder. + * \param Storage The storage of the variable to declare. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Instr Instruction acting as a location for the new intrinsic. + */ +LLVMValueRef LLVMDIBuilderInsertDeclareBefore( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMValueRef Instr); + +/** + * Insert a new llvm.dbg.declare intrinsic call at the end of the given basic + * block. If the basic block has a terminator instruction, the intrinsic is + * inserted before that terminator instruction. + * \param Builder The DIBuilder. + * \param Storage The storage of the variable to declare. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Block Basic block acting as a location for the new intrinsic. + */ +LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd( + LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, LLVMMetadataRef DebugLoc, LLVMBasicBlockRef Block); + +/** + * Insert a new llvm.dbg.value intrinsic call before the given instruction. + * \param Builder The DIBuilder. + * \param Val The value of the variable. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Instr Instruction acting as a location for the new intrinsic. + */ +LLVMValueRef LLVMDIBuilderInsertDbgValueBefore(LLVMDIBuilderRef Builder, + LLVMValueRef Val, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, + LLVMMetadataRef DebugLoc, + LLVMValueRef Instr); + +/** + * Insert a new llvm.dbg.value intrinsic call at the end of the given basic + * block. If the basic block has a terminator instruction, the intrinsic is + * inserted before that terminator instruction. + * \param Builder The DIBuilder. + * \param Val The value of the variable. + * \param VarInfo The variable's debug info descriptor. + * \param Expr A complex location expression for the variable. + * \param DebugLoc Debug info location. + * \param Block Basic block acting as a location for the new intrinsic. + */ +LLVMValueRef LLVMDIBuilderInsertDbgValueAtEnd(LLVMDIBuilderRef Builder, + LLVMValueRef Val, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, + LLVMMetadataRef DebugLoc, + LLVMBasicBlockRef Block); + +/** + * Create a new descriptor for a local auto variable. + * \param Builder The DIBuilder. + * \param Scope The local scope the variable is declared in. + * \param Name Variable name. + * \param NameLen Length of variable name. + * \param File File where this variable is defined. + * \param LineNo Line number. + * \param Ty Metadata describing the type of the variable. + * \param AlwaysPreserve If true, this descriptor will survive optimizations. + * \param Flags Flags. + * \param AlignInBits Variable alignment. + */ +LLVMMetadataRef LLVMDIBuilderCreateAutoVariable( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, + LLVMBool AlwaysPreserve, LLVMDIFlags Flags, uint32_t AlignInBits); + +/** + * Create a new descriptor for a function parameter variable. + * \param Builder The DIBuilder. + * \param Scope The local scope the variable is declared in. + * \param Name Variable name. + * \param NameLen Length of variable name. + * \param ArgNo Unique argument number for this variable; starts at 1. + * \param File File where this variable is defined. + * \param LineNo Line number. + * \param Ty Metadata describing the type of the variable. + * \param AlwaysPreserve If true, this descriptor will survive optimizations. + * \param Flags Flags. + */ +LLVMMetadataRef LLVMDIBuilderCreateParameterVariable( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, unsigned ArgNo, LLVMMetadataRef File, unsigned LineNo, + LLVMMetadataRef Ty, LLVMBool AlwaysPreserve, LLVMDIFlags Flags); + +/** + * Get the metadata of the subprogram attached to a function. + * + * @see llvm::Function::getSubprogram() + */ +LLVMMetadataRef LLVMGetSubprogram(LLVMValueRef Func); + +/** + * Set the subprogram attached to a function. + * + * @see llvm::Function::setSubprogram() + */ +void LLVMSetSubprogram(LLVMValueRef Func, LLVMMetadataRef SP); + #ifdef __cplusplus } /* end extern "C" */ #endif diff --git a/contrib/llvm/include/llvm-c/Disassembler.h b/contrib/llvm/include/llvm-c/Disassembler.h index d6f92e505d3c..5e80b95848cf 100644 --- a/contrib/llvm/include/llvm-c/Disassembler.h +++ b/contrib/llvm/include/llvm-c/Disassembler.h @@ -15,12 +15,7 @@ #ifndef LLVM_C_DISASSEMBLER_H #define LLVM_C_DISASSEMBLER_H -#include "llvm/Support/DataTypes.h" -#ifdef __cplusplus -#include <cstddef> -#else -#include <stddef.h> -#endif +#include "llvm-c/DisassemblerTypes.h" /** * @defgroup LLVMCDisassembler Disassembler @@ -29,146 +24,6 @@ * @{ */ -/** - * An opaque reference to a disassembler context. - */ -typedef void *LLVMDisasmContextRef; - -/** - * The type for the operand information call back function. This is called to - * get the symbolic information for an operand of an instruction. Typically - * this is from the relocation information, symbol table, etc. That block of - * information is saved when the disassembler context is created and passed to - * the call back in the DisInfo parameter. The instruction containing operand - * is at the PC parameter. For some instruction sets, there can be more than - * one operand with symbolic information. To determine the symbolic operand - * information for each operand, the bytes for the specific operand in the - * instruction are specified by the Offset parameter and its byte widith is the - * size parameter. For instructions sets with fixed widths and one symbolic - * operand per instruction, the Offset parameter will be zero and Size parameter - * will be the instruction width. The information is returned in TagBuf and is - * Triple specific with its specific information defined by the value of - * TagType for that Triple. If symbolic information is returned the function - * returns 1, otherwise it returns 0. - */ -typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC, - uint64_t Offset, uint64_t Size, - int TagType, void *TagBuf); - -/** - * The initial support in LLVM MC for the most general form of a relocatable - * expression is "AddSymbol - SubtractSymbol + Offset". For some Darwin targets - * this full form is encoded in the relocation information so that AddSymbol and - * SubtractSymbol can be link edited independent of each other. Many other - * platforms only allow a relocatable expression of the form AddSymbol + Offset - * to be encoded. - * - * The LLVMOpInfoCallback() for the TagType value of 1 uses the struct - * LLVMOpInfo1. The value of the relocatable expression for the operand, - * including any PC adjustment, is passed in to the call back in the Value - * field. The symbolic information about the operand is returned using all - * the fields of the structure with the Offset of the relocatable expression - * returned in the Value field. It is possible that some symbols in the - * relocatable expression were assembly temporary symbols, for example - * "Ldata - LpicBase + constant", and only the Values of the symbols without - * symbol names are present in the relocation information. The VariantKind - * type is one of the Target specific #defines below and is used to print - * operands like "_foo@GOT", ":lower16:_foo", etc. - */ -struct LLVMOpInfoSymbol1 { - uint64_t Present; /* 1 if this symbol is present */ - const char *Name; /* symbol name if not NULL */ - uint64_t Value; /* symbol value if name is NULL */ -}; - -struct LLVMOpInfo1 { - struct LLVMOpInfoSymbol1 AddSymbol; - struct LLVMOpInfoSymbol1 SubtractSymbol; - uint64_t Value; - uint64_t VariantKind; -}; - -/** - * The operand VariantKinds for symbolic disassembly. - */ -#define LLVMDisassembler_VariantKind_None 0 /* all targets */ - -/** - * The ARM target VariantKinds. - */ -#define LLVMDisassembler_VariantKind_ARM_HI16 1 /* :upper16: */ -#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. - * It is passed the block information is saved when the disassembler context is - * created and the ReferenceValue to look up as a symbol. If no symbol is found - * for the ReferenceValue NULL is returned. The ReferenceType of the - * instruction is passed indirectly as is the PC of the instruction in - * ReferencePC. If the output reference can be determined its type is returned - * indirectly in ReferenceType along with ReferenceName if any, or that is set - * to NULL. - */ -typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, - uint64_t ReferenceValue, - uint64_t *ReferenceType, - uint64_t ReferencePC, - const char **ReferenceName); -/** - * The reference types on input and output. - */ -/* No input reference type or no output reference type. */ -#define LLVMDisassembler_ReferenceType_InOut_None 0 - -/* The input reference is from a branch instruction. */ -#define LLVMDisassembler_ReferenceType_In_Branch 1 -/* 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. */ -#define LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr 2 -/* The output reference is to a cstring address in a literal pool. */ -#define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3 - -/* The output reference is to a Objective-C CoreFoundation string. */ -#define LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref 4 -/* The output reference is to a Objective-C message. */ -#define LLVMDisassembler_ReferenceType_Out_Objc_Message 5 -/* The output reference is to a Objective-C message ref. */ -#define LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref 6 -/* The output reference is to a Objective-C selector ref. */ -#define LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref 7 -/* 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/contrib/llvm/include/llvm-c/DisassemblerTypes.h b/contrib/llvm/include/llvm-c/DisassemblerTypes.h new file mode 100644 index 000000000000..e8754ac77055 --- /dev/null +++ b/contrib/llvm/include/llvm-c/DisassemblerTypes.h @@ -0,0 +1,160 @@ +/*===-- llvm-c/DisassemblerTypedefs.h -----------------------------*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_DISASSEMBLER_TYPES_H +#define LLVM_DISASSEMBLER_TYPES_H + +#include "llvm-c/DataTypes.h" +#ifdef __cplusplus +#include <cstddef> +#else +#include <stddef.h> +#endif + +/** + * An opaque reference to a disassembler context. + */ +typedef void *LLVMDisasmContextRef; + +/** + * The type for the operand information call back function. This is called to + * get the symbolic information for an operand of an instruction. Typically + * this is from the relocation information, symbol table, etc. That block of + * information is saved when the disassembler context is created and passed to + * the call back in the DisInfo parameter. The instruction containing operand + * is at the PC parameter. For some instruction sets, there can be more than + * one operand with symbolic information. To determine the symbolic operand + * information for each operand, the bytes for the specific operand in the + * instruction are specified by the Offset parameter and its byte widith is the + * size parameter. For instructions sets with fixed widths and one symbolic + * operand per instruction, the Offset parameter will be zero and Size parameter + * will be the instruction width. The information is returned in TagBuf and is + * Triple specific with its specific information defined by the value of + * TagType for that Triple. If symbolic information is returned the function + * returns 1, otherwise it returns 0. + */ +typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC, + uint64_t Offset, uint64_t Size, + int TagType, void *TagBuf); + +/** + * The initial support in LLVM MC for the most general form of a relocatable + * expression is "AddSymbol - SubtractSymbol + Offset". For some Darwin targets + * this full form is encoded in the relocation information so that AddSymbol and + * SubtractSymbol can be link edited independent of each other. Many other + * platforms only allow a relocatable expression of the form AddSymbol + Offset + * to be encoded. + * + * The LLVMOpInfoCallback() for the TagType value of 1 uses the struct + * LLVMOpInfo1. The value of the relocatable expression for the operand, + * including any PC adjustment, is passed in to the call back in the Value + * field. The symbolic information about the operand is returned using all + * the fields of the structure with the Offset of the relocatable expression + * returned in the Value field. It is possible that some symbols in the + * relocatable expression were assembly temporary symbols, for example + * "Ldata - LpicBase + constant", and only the Values of the symbols without + * symbol names are present in the relocation information. The VariantKind + * type is one of the Target specific #defines below and is used to print + * operands like "_foo@GOT", ":lower16:_foo", etc. + */ +struct LLVMOpInfoSymbol1 { + uint64_t Present; /* 1 if this symbol is present */ + const char *Name; /* symbol name if not NULL */ + uint64_t Value; /* symbol value if name is NULL */ +}; + +struct LLVMOpInfo1 { + struct LLVMOpInfoSymbol1 AddSymbol; + struct LLVMOpInfoSymbol1 SubtractSymbol; + uint64_t Value; + uint64_t VariantKind; +}; + +/** + * The operand VariantKinds for symbolic disassembly. + */ +#define LLVMDisassembler_VariantKind_None 0 /* all targets */ + +/** + * The ARM target VariantKinds. + */ +#define LLVMDisassembler_VariantKind_ARM_HI16 1 /* :upper16: */ +#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. + * It is passed the block information is saved when the disassembler context is + * created and the ReferenceValue to look up as a symbol. If no symbol is found + * for the ReferenceValue NULL is returned. The ReferenceType of the + * instruction is passed indirectly as is the PC of the instruction in + * ReferencePC. If the output reference can be determined its type is returned + * indirectly in ReferenceType along with ReferenceName if any, or that is set + * to NULL. + */ +typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, + uint64_t ReferenceValue, + uint64_t *ReferenceType, + uint64_t ReferencePC, + const char **ReferenceName); +/** + * The reference types on input and output. + */ +/* No input reference type or no output reference type. */ +#define LLVMDisassembler_ReferenceType_InOut_None 0 + +/* The input reference is from a branch instruction. */ +#define LLVMDisassembler_ReferenceType_In_Branch 1 +/* 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. */ +#define LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr 2 +/* The output reference is to a cstring address in a literal pool. */ +#define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3 + +/* The output reference is to a Objective-C CoreFoundation string. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref 4 +/* The output reference is to a Objective-C message. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Message 5 +/* The output reference is to a Objective-C message ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref 6 +/* The output reference is to a Objective-C selector ref. */ +#define LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref 7 +/* 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 + +#endif diff --git a/contrib/llvm/include/llvm-c/ExecutionEngine.h b/contrib/llvm/include/llvm-c/ExecutionEngine.h index 51830fe139c6..49ae6fee45f0 100644 --- a/contrib/llvm/include/llvm-c/ExecutionEngine.h +++ b/contrib/llvm/include/llvm-c/ExecutionEngine.h @@ -182,6 +182,13 @@ LLVMMCJITMemoryManagerRef LLVMCreateSimpleMCJITMemoryManager( void LLVMDisposeMCJITMemoryManager(LLVMMCJITMemoryManagerRef MM); +/*===-- JIT Event Listener functions -------------------------------------===*/ + +LLVMJITEventListenerRef LLVMCreateGDBRegistrationListener(void); +LLVMJITEventListenerRef LLVMCreateIntelJITEventListener(void); +LLVMJITEventListenerRef LLVMCreateOprofileJITEventListener(void); +LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void); + /** * @} */ diff --git a/contrib/llvm/include/llvm-c/Initialization.h b/contrib/llvm/include/llvm-c/Initialization.h index 90c8396f7ad3..e45eafb139f2 100644 --- a/contrib/llvm/include/llvm-c/Initialization.h +++ b/contrib/llvm/include/llvm-c/Initialization.h @@ -37,6 +37,7 @@ void LLVMInitializeScalarOpts(LLVMPassRegistryRef R); void LLVMInitializeObjCARCOpts(LLVMPassRegistryRef R); void LLVMInitializeVectorization(LLVMPassRegistryRef R); void LLVMInitializeInstCombine(LLVMPassRegistryRef R); +void LLVMInitializeAggressiveInstCombiner(LLVMPassRegistryRef R); void LLVMInitializeIPO(LLVMPassRegistryRef R); void LLVMInitializeInstrumentation(LLVMPassRegistryRef R); void LLVMInitializeAnalysis(LLVMPassRegistryRef R); diff --git a/contrib/llvm/include/llvm-c/OrcBindings.h b/contrib/llvm/include/llvm-c/OrcBindings.h index abb3ac6a7f03..9497f0d40776 100644 --- a/contrib/llvm/include/llvm-c/OrcBindings.h +++ b/contrib/llvm/include/llvm-c/OrcBindings.h @@ -29,9 +29,8 @@ extern "C" { #endif -typedef struct LLVMOpaqueSharedModule *LLVMSharedModuleRef; typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef; -typedef uint32_t LLVMOrcModuleHandle; +typedef uint64_t LLVMOrcModuleHandle; typedef uint64_t LLVMOrcTargetAddress; typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name, void *LookupCtx); typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack, @@ -40,33 +39,6 @@ typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack, typedef enum { LLVMOrcErrSuccess = 0, LLVMOrcErrGeneric } LLVMOrcErrorCode; /** - * Turn an LLVMModuleRef into an LLVMSharedModuleRef. - * - * The JIT uses shared ownership for LLVM modules, since it is generally - * difficult to know when the JIT will be finished with a module (and the JIT - * has no way of knowing when a user may be finished with one). - * - * Calling this method with an LLVMModuleRef creates a shared-pointer to the - * module, and returns a reference to this shared pointer. - * - * The shared module should be disposed when finished with by calling - * LLVMOrcDisposeSharedModule (not LLVMDisposeModule). The Module will be - * deleted when the last shared pointer owner relinquishes it. - */ - -LLVMSharedModuleRef LLVMOrcMakeSharedModule(LLVMModuleRef Mod); - -/** - * Dispose of a shared module. - * - * The module should not be accessed after this call. The module will be - * deleted once all clients (including the JIT itself) have released their - * shared pointers. - */ - -void LLVMOrcDisposeSharedModuleRef(LLVMSharedModuleRef SharedMod); - -/** * Create an ORC JIT stack. * * The client owns the resulting stack, and must call OrcDisposeInstance(...) @@ -125,8 +97,7 @@ LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack, */ LLVMOrcErrorCode LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, - LLVMOrcModuleHandle *RetHandle, - LLVMSharedModuleRef Mod, + LLVMOrcModuleHandle *RetHandle, LLVMModuleRef Mod, LLVMOrcSymbolResolverFn SymbolResolver, void *SymbolResolverCtx); @@ -135,8 +106,7 @@ LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, */ LLVMOrcErrorCode LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, - LLVMOrcModuleHandle *RetHandle, - LLVMSharedModuleRef Mod, + LLVMOrcModuleHandle *RetHandle, LLVMModuleRef Mod, LLVMOrcSymbolResolverFn SymbolResolver, void *SymbolResolverCtx); @@ -171,10 +141,33 @@ LLVMOrcErrorCode LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack, const char *SymbolName); /** + * Get symbol address from JIT instance, searching only the specified + * handle. + */ +LLVMOrcErrorCode LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack, + LLVMOrcTargetAddress *RetAddr, + LLVMOrcModuleHandle H, + const char *SymbolName); + +/** * Dispose of an ORC JIT stack. */ LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack); +/** + * Register a JIT Event Listener. + * + * A NULL listener is ignored. + */ +void LLVMOrcRegisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L); + +/** + * Unegister a JIT Event Listener. + * + * A NULL listener is ignored. + */ +void LLVMOrcUnregisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L); + #ifdef __cplusplus } #endif /* extern "C" */ diff --git a/contrib/llvm/include/llvm-c/Support.h b/contrib/llvm/include/llvm-c/Support.h index 6de184ccab49..37d5d72ff5dc 100644 --- a/contrib/llvm/include/llvm-c/Support.h +++ b/contrib/llvm/include/llvm-c/Support.h @@ -14,8 +14,8 @@ #ifndef LLVM_C_SUPPORT_H #define LLVM_C_SUPPORT_H +#include "llvm-c/DataTypes.h" #include "llvm-c/Types.h" -#include "llvm/Support/DataTypes.h" #ifdef __cplusplus extern "C" { diff --git a/contrib/llvm/include/llvm-c/TargetMachine.h b/contrib/llvm/include/llvm-c/TargetMachine.h index f4f7f7698c45..7f672b5d10d6 100644 --- a/contrib/llvm/include/llvm-c/TargetMachine.h +++ b/contrib/llvm/include/llvm-c/TargetMachine.h @@ -137,6 +137,18 @@ LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleR disposed with LLVMDisposeMessage. */ char* LLVMGetDefaultTargetTriple(void); +/** Normalize a target triple. The result needs to be disposed with + LLVMDisposeMessage. */ +char* LLVMNormalizeTargetTriple(const char* triple); + +/** Get the host CPU as a string. The result needs to be disposed with + LLVMDisposeMessage. */ +char* LLVMGetHostCPUName(void); + +/** Get the host CPU's features as a string. The result needs to be disposed + with LLVMDisposeMessage. */ +char* LLVMGetHostCPUFeatures(void); + /** Adds the target-specific analysis passes to the pass manager. */ void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM); diff --git a/contrib/llvm/include/llvm-c/Transforms/InstCombine.h b/contrib/llvm/include/llvm-c/Transforms/InstCombine.h new file mode 100644 index 000000000000..e1c1572d53dc --- /dev/null +++ b/contrib/llvm/include/llvm-c/Transforms/InstCombine.h @@ -0,0 +1,43 @@ +/*===-- Scalar.h - Scalar Transformation Library C Interface ----*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMInstCombine.a, which *| +|* combines instructions to form fewer, simple IR instructions. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_INSTCOMBINE_H +#define LLVM_C_TRANSFORMS_INSTCOMBINE_H + +#include "llvm-c/Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup LLVMCTransformsInstCombine Instruction Combining transformations + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createInstructionCombiningPass function. */ +void LLVMAddInstructionCombiningPass(LLVMPassManagerRef PM); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + +#endif + diff --git a/contrib/llvm/include/llvm-c/Transforms/Scalar.h b/contrib/llvm/include/llvm-c/Transforms/Scalar.h index 8991e0904849..f55cdce86be9 100644 --- a/contrib/llvm/include/llvm-c/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm-c/Transforms/Scalar.h @@ -35,6 +35,9 @@ extern "C" { /** See llvm::createAggressiveDCEPass function. */ void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM); +/** See llvm::createAggressiveInstCombinerPass function. */ +void LLVMAddAggressiveInstCombinerPass(LLVMPassManagerRef PM); + /** See llvm::createBitTrackingDCEPass function. */ void LLVMAddBitTrackingDCEPass(LLVMPassManagerRef PM); @@ -86,6 +89,9 @@ void LLVMAddLoopRerollPass(LLVMPassManagerRef PM); /** See llvm::createLoopUnrollPass function. */ void LLVMAddLoopUnrollPass(LLVMPassManagerRef PM); +/** See llvm::createLoopUnrollAndJamPass function. */ +void LLVMAddLoopUnrollAndJamPass(LLVMPassManagerRef PM); + /** See llvm::createLoopUnswitchPass function. */ void LLVMAddLoopUnswitchPass(LLVMPassManagerRef PM); @@ -95,12 +101,6 @@ void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); /** See llvm::createPartiallyInlineLibCallsPass function. */ void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM); -/** See llvm::createLowerSwitchPass function. */ -void LLVMAddLowerSwitchPass(LLVMPassManagerRef PM); - -/** See llvm::createPromoteMemoryToRegisterPass function. */ -void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); - /** See llvm::createReassociatePass function. */ void LLVMAddReassociatePass(LLVMPassManagerRef PM); diff --git a/contrib/llvm/include/llvm-c/Transforms/Utils.h b/contrib/llvm/include/llvm-c/Transforms/Utils.h new file mode 100644 index 000000000000..f171f7fbbe3e --- /dev/null +++ b/contrib/llvm/include/llvm-c/Transforms/Utils.h @@ -0,0 +1,50 @@ +/*===-- Utils.h - Transformation Utils Library C Interface ------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to libLLVMTransformUtils.a, which *| +|* implements various transformation utilities of the LLVM IR. *| +|* *| +|* Many exotic languages can interoperate with C code but have a harder time *| +|* with C++ due to name mangling. So in addition to C, this interface enables *| +|* tools written in such languages. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_TRANSFORMS_UTILS_H +#define LLVM_C_TRANSFORMS_UTILS_H + +#include "llvm-c/Types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup LLVMCTransformsUtils Transformation Utilities + * @ingroup LLVMCTransforms + * + * @{ + */ + +/** See llvm::createLowerSwitchPass function. */ +void LLVMAddLowerSwitchPass(LLVMPassManagerRef PM); + +/** See llvm::createPromoteMemoryToRegisterPass function. */ +void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /* defined(__cplusplus) */ + +#endif + diff --git a/contrib/llvm/include/llvm-c/Transforms/Vectorize.h b/contrib/llvm/include/llvm-c/Transforms/Vectorize.h index cf8306aee762..e3f9961acfb1 100644 --- a/contrib/llvm/include/llvm-c/Transforms/Vectorize.h +++ b/contrib/llvm/include/llvm-c/Transforms/Vectorize.h @@ -33,9 +33,6 @@ extern "C" { * @{ */ -/** DEPRECATED - Use LLVMAddSLPVectorizePass */ -void LLVMAddBBVectorizePass(LLVMPassManagerRef PM); - /** See llvm::createLoopVectorizePass function. */ void LLVMAddLoopVectorizePass(LLVMPassManagerRef PM); diff --git a/contrib/llvm/include/llvm-c/Types.h b/contrib/llvm/include/llvm-c/Types.h index d63ea4de933d..4a33542e86cc 100644 --- a/contrib/llvm/include/llvm-c/Types.h +++ b/contrib/llvm/include/llvm-c/Types.h @@ -7,14 +7,14 @@ |* *| |*===----------------------------------------------------------------------===*| |* *| -|* This file defines types used by the the C interface to LLVM. *| +|* This file defines types used by the C interface to LLVM. *| |* *| \*===----------------------------------------------------------------------===*/ #ifndef LLVM_C_TYPES_H #define LLVM_C_TYPES_H -#include "llvm/Support/DataTypes.h" +#include "llvm-c/DataTypes.h" #ifdef __cplusplus extern "C" { @@ -135,6 +135,21 @@ typedef struct LLVMOpaqueAttributeRef *LLVMAttributeRef; typedef struct LLVMOpaqueDiagnosticInfo *LLVMDiagnosticInfoRef; /** + * @see llvm::Comdat + */ +typedef struct LLVMComdat *LLVMComdatRef; + +/** + * @see llvm::Module::ModuleFlagEntry + */ +typedef struct LLVMOpaqueModuleFlagEntry LLVMModuleFlagEntry; + +/** + * @see llvm::JITEventListener + */ +typedef struct LLVMOpaqueJITEventListener *LLVMJITEventListenerRef; + +/** * @} */ diff --git a/contrib/llvm/include/llvm-c/lto.h b/contrib/llvm/include/llvm-c/lto.h index 55f3e46c45ed..1acd610f70ac 100644 --- a/contrib/llvm/include/llvm-c/lto.h +++ b/contrib/llvm/include/llvm-c/lto.h @@ -44,7 +44,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 21 +#define LTO_API_VERSION 22 /** * \since prior to LTO_API_VERSION=3 @@ -190,7 +190,7 @@ lto_module_create_from_memory_with_path(const void* mem, size_t length, const char *path); /** - * \brief Loads an object file in its own context. + * Loads an object file in its own context. * * Loads an object file in its own LLVMContext. This function call is * thread-safe. However, modules created this way should not be merged into an @@ -205,7 +205,7 @@ lto_module_create_in_local_context(const void *mem, size_t length, const char *path); /** - * \brief Loads an object file in the codegen context. + * Loads an object file in the codegen context. * * Loads an object file into the same context as \c cg. The module is safe to * add using \a lto_codegen_add_module(). @@ -345,7 +345,7 @@ extern lto_code_gen_t lto_codegen_create(void); /** - * \brief Instantiate a code generator in its own context. + * Instantiate a code generator in its own context. * * Instantiates a code generator in its own context. Modules added via \a * lto_codegen_add_module() must have all been created in the same context, @@ -539,7 +539,7 @@ lto_codegen_set_should_internalize(lto_code_gen_t cg, lto_bool_t ShouldInternalize); /** - * \brief Set whether to embed uselists in bitcode. + * Set whether to embed uselists in bitcode. * * Sets whether \a lto_codegen_write_merged_modules() should embed uselists in * output bitcode. This should be turned on for all -save-temps output. @@ -784,7 +784,7 @@ extern void thinlto_codegen_set_cache_dir(thinlto_code_gen_t cg, /** * Sets the cache pruning interval (in seconds). A negative value disables the * pruning. An unspecified default value will be applied, and a value of 0 will - * be ignored. + * force prunning to occur. * * \since LTO_API_VERSION=18 */ @@ -793,7 +793,7 @@ extern void thinlto_codegen_set_cache_pruning_interval(thinlto_code_gen_t cg, /** * Sets the maximum cache size that can be persistent across build, in terms of - * percentage of the available space on the the disk. Set to 100 to indicate + * percentage of the available space on the disk. Set to 100 to indicate * no limit, 50 to indicate that the cache size will not be left over half the * available space. A value over 100 will be reduced to 100, a value of 0 will * be ignored. An unspecified default value will be applied. @@ -817,6 +817,28 @@ extern void thinlto_codegen_set_cache_entry_expiration(thinlto_code_gen_t cg, unsigned expiration); /** + * Sets the maximum size of the cache directory (in bytes). A value over the + * amount of available space on the disk will be reduced to the amount of + * available space. An unspecified default value will be applied. A value of 0 + * will be ignored. + * + * \since LTO_API_VERSION=22 + */ +extern void thinlto_codegen_set_cache_size_bytes(thinlto_code_gen_t cg, + unsigned max_size_bytes); + +/** + * Sets the maximum number of files in the cache directory. An unspecified + * default value will be applied. A value of 0 will be ignored. + * + * \since LTO_API_VERSION=22 + */ +extern void thinlto_codegen_set_cache_size_files(thinlto_code_gen_t cg, + unsigned max_size_files); + + + +/** * @} // endgroup LLVMCTLTO_CACHING */ diff --git a/contrib/llvm/include/llvm/ADT/APFloat.h b/contrib/llvm/include/llvm/ADT/APFloat.h index 6c0b6ae78ae3..5c59af4c04ba 100644 --- a/contrib/llvm/include/llvm/ADT/APFloat.h +++ b/contrib/llvm/include/llvm/ADT/APFloat.h @@ -1215,7 +1215,7 @@ inline APFloat abs(APFloat X) { return X; } -/// \brief Returns the negated value of the argument. +/// Returns the negated value of the argument. inline APFloat neg(APFloat X) { X.changeSign(); return X; diff --git a/contrib/llvm/include/llvm/ADT/APInt.h b/contrib/llvm/include/llvm/ADT/APInt.h index c81363cc16b7..6bf6b22fb010 100644 --- a/contrib/llvm/include/llvm/ADT/APInt.h +++ b/contrib/llvm/include/llvm/ADT/APInt.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file implements a class to represent arbitrary precision +/// This file implements a class to represent arbitrary precision /// integral constant values and operations on them. /// //===----------------------------------------------------------------------===// @@ -40,7 +40,7 @@ inline APInt operator-(APInt); // APInt Class //===----------------------------------------------------------------------===// -/// \brief Class for arbitrary precision integers. +/// Class for arbitrary precision integers. /// /// APInt is a functional replacement for common case unsigned integer type like /// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width @@ -78,6 +78,12 @@ public: APINT_BITS_PER_WORD = APINT_WORD_SIZE * CHAR_BIT }; + enum class Rounding { + DOWN, + TOWARD_ZERO, + UP, + }; + static const WordType WORD_MAX = ~WordType(0); private: @@ -94,7 +100,7 @@ private: friend class APSInt; - /// \brief Fast internal constructor + /// Fast internal constructor /// /// This constructor is used only internally for speed of construction of /// temporaries. It is unsafe for general use so it is not public. @@ -102,19 +108,19 @@ private: U.pVal = val; } - /// \brief Determine if this APInt just has one word to store value. + /// Determine if this APInt just has one word to store value. /// /// \returns true if the number of bits <= 64, false otherwise. bool isSingleWord() const { return BitWidth <= APINT_BITS_PER_WORD; } - /// \brief Determine which word a bit is in. + /// Determine which word a bit is in. /// /// \returns the word position for the specified bit position. static unsigned whichWord(unsigned bitPosition) { return bitPosition / APINT_BITS_PER_WORD; } - /// \brief Determine which bit in a word a bit is in. + /// Determine which bit in a word a bit is in. /// /// \returns the bit position in a word for the specified bit position /// in the APInt. @@ -122,7 +128,7 @@ private: return bitPosition % APINT_BITS_PER_WORD; } - /// \brief Get a single bit mask. + /// Get a single bit mask. /// /// \returns a uint64_t with only bit at "whichBit(bitPosition)" set /// This method generates and returns a uint64_t (word) mask for a single @@ -132,7 +138,7 @@ private: return 1ULL << whichBit(bitPosition); } - /// \brief Clear unused high order bits + /// Clear unused high order bits /// /// This method is used internally to clear the top "N" bits in the high order /// word that are not used by the APInt. This is needed after the most @@ -151,7 +157,7 @@ private: return *this; } - /// \brief Get the word corresponding to a bit position + /// Get the word corresponding to a bit position /// \returns the corresponding word for the specified bit position. uint64_t getWord(unsigned bitPosition) const { return isSingleWord() ? U.VAL : U.pVal[whichWord(bitPosition)]; @@ -162,7 +168,7 @@ private: /// value of any bits upon return. Caller should populate the bits after. void reallocate(unsigned NewBitWidth); - /// \brief Convert a char array into an APInt + /// Convert a char array into an APInt /// /// \param radix 2, 8, 10, 16, or 36 /// Converts a string into a number. The string must be non-empty @@ -176,7 +182,7 @@ private: /// result to hold the input. void fromString(unsigned numBits, StringRef str, uint8_t radix); - /// \brief An internal division function for dividing APInts. + /// An internal division function for dividing APInts. /// /// This is used by the toString method to divide by the radix. It simply /// provides a more convenient form of divide for internal use since KnuthDiv @@ -258,7 +264,7 @@ public: /// \name Constructors /// @{ - /// \brief Create a new APInt of numBits width, initialized as val. + /// Create a new APInt of numBits width, initialized as val. /// /// If isSigned is true then val is treated as if it were a signed value /// (i.e. as an int64_t) and the appropriate sign extension to the bit width @@ -279,7 +285,7 @@ public: } } - /// \brief Construct an APInt of numBits width, initialized as bigVal[]. + /// Construct an APInt of numBits width, initialized as bigVal[]. /// /// Note that bigVal.size() can be smaller or larger than the corresponding /// bit width but any extraneous bits will be dropped. @@ -297,7 +303,7 @@ public: /// constructor. APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); - /// \brief Construct an APInt from a string representation. + /// Construct an APInt from a string representation. /// /// This constructor interprets the string \p str in the given radix. The /// interpretation stops when the first character that is not suitable for the @@ -311,7 +317,7 @@ public: APInt(unsigned numBits, StringRef str, uint8_t radix); /// Simply makes *this a copy of that. - /// @brief Copy Constructor. + /// Copy Constructor. APInt(const APInt &that) : BitWidth(that.BitWidth) { if (isSingleWord()) U.VAL = that.U.VAL; @@ -319,26 +325,26 @@ public: initSlowCase(that); } - /// \brief Move Constructor. + /// Move Constructor. APInt(APInt &&that) : BitWidth(that.BitWidth) { memcpy(&U, &that.U, sizeof(U)); that.BitWidth = 0; } - /// \brief Destructor. + /// Destructor. ~APInt() { if (needsCleanup()) delete[] U.pVal; } - /// \brief Default constructor that creates an uninteresting APInt + /// Default constructor that creates an uninteresting APInt /// representing a 1-bit zero value. /// /// This is useful for object deserialization (pair this with the static /// method Read). explicit APInt() : BitWidth(1) { U.VAL = 0; } - /// \brief Returns whether this instance allocated memory. + /// Returns whether this instance allocated memory. bool needsCleanup() const { return !isSingleWord(); } /// Used to insert APInt objects, or objects that contain APInt objects, into @@ -349,33 +355,33 @@ public: /// \name Value Tests /// @{ - /// \brief Determine sign of this APInt. + /// Determine sign of this APInt. /// /// This tests the high bit of this APInt to determine if it is set. /// /// \returns true if this APInt is negative, false otherwise bool isNegative() const { return (*this)[BitWidth - 1]; } - /// \brief Determine if this APInt Value is non-negative (>= 0) + /// Determine if this APInt Value is non-negative (>= 0) /// /// This tests the high bit of the APInt to determine if it is unset. bool isNonNegative() const { return !isNegative(); } - /// \brief Determine if sign bit of this APInt is set. + /// Determine if sign bit of this APInt is set. /// /// This tests the high bit of this APInt to determine if it is set. /// /// \returns true if this APInt has its sign bit set, false otherwise. bool isSignBitSet() const { return (*this)[BitWidth-1]; } - /// \brief Determine if sign bit of this APInt is clear. + /// Determine if sign bit of this APInt is clear. /// /// This tests the high bit of this APInt to determine if it is clear. /// /// \returns true if this APInt has its sign bit clear, false otherwise. bool isSignBitClear() const { return !isSignBitSet(); } - /// \brief Determine if this APInt Value is positive. + /// Determine if this APInt Value is positive. /// /// This tests if the value of this APInt is positive (> 0). Note /// that 0 is not a positive value. @@ -383,7 +389,7 @@ public: /// \returns true if this APInt is positive. bool isStrictlyPositive() const { return isNonNegative() && !isNullValue(); } - /// \brief Determine if all bits are set + /// Determine if all bits are set /// /// This checks to see if the value has all bits of the APInt are set or not. bool isAllOnesValue() const { @@ -392,13 +398,13 @@ public: return countTrailingOnesSlowCase() == BitWidth; } - /// \brief Determine if all bits are clear + /// Determine if all bits are clear /// /// This checks to see if the value has all bits of the APInt are clear or /// not. bool isNullValue() const { return !*this; } - /// \brief Determine if this is a value of 1. + /// Determine if this is a value of 1. /// /// This checks to see if the value of this APInt is one. bool isOneValue() const { @@ -407,13 +413,13 @@ public: return countLeadingZerosSlowCase() == BitWidth - 1; } - /// \brief Determine if this is the largest unsigned value. + /// Determine if this is the largest unsigned value. /// /// This checks to see if the value of this APInt is the maximum unsigned /// value for the APInt's bit width. bool isMaxValue() const { return isAllOnesValue(); } - /// \brief Determine if this is the largest signed value. + /// Determine if this is the largest signed value. /// /// This checks to see if the value of this APInt is the maximum signed /// value for the APInt's bit width. @@ -423,13 +429,13 @@ public: return !isNegative() && countTrailingOnesSlowCase() == BitWidth - 1; } - /// \brief Determine if this is the smallest unsigned value. + /// Determine if this is the smallest unsigned value. /// /// This checks to see if the value of this APInt is the minimum unsigned /// value for the APInt's bit width. bool isMinValue() const { return isNullValue(); } - /// \brief Determine if this is the smallest signed value. + /// Determine if this is the smallest signed value. /// /// This checks to see if the value of this APInt is the minimum signed /// value for the APInt's bit width. @@ -439,19 +445,19 @@ public: return isNegative() && countTrailingZerosSlowCase() == BitWidth - 1; } - /// \brief Check if this APInt has an N-bits unsigned integer value. + /// Check if this APInt has an N-bits unsigned integer value. bool isIntN(unsigned N) const { assert(N && "N == 0 ???"); return getActiveBits() <= N; } - /// \brief Check if this APInt has an N-bits signed integer value. + /// Check if this APInt has an N-bits signed integer value. bool isSignedIntN(unsigned N) const { assert(N && "N == 0 ???"); return getMinSignedBits() <= N; } - /// \brief Check if this APInt's value is a power of two greater than zero. + /// Check if this APInt's value is a power of two greater than zero. /// /// \returns true if the argument APInt value is a power of two > 0. bool isPowerOf2() const { @@ -460,12 +466,12 @@ public: return countPopulationSlowCase() == 1; } - /// \brief Check if the APInt's value is returned by getSignMask. + /// Check if the APInt's value is returned by getSignMask. /// /// \returns true if this is the value returned by getSignMask. bool isSignMask() const { return isMinSignedValue(); } - /// \brief Convert APInt to a boolean value. + /// Convert APInt to a boolean value. /// /// This converts the APInt to a boolean value as a test against zero. bool getBoolValue() const { return !!*this; } @@ -476,7 +482,7 @@ public: return ugt(Limit) ? Limit : getZExtValue(); } - /// \brief Check if the APInt consists of a repeated bit pattern. + /// Check if the APInt consists of a repeated bit pattern. /// /// e.g. 0x01010101 satisfies isSplat(8). /// \param SplatSizeInBits The size of the pattern in bits. Must divide bit @@ -505,7 +511,7 @@ public: return (Ones > 0) && ((Ones + countLeadingZerosSlowCase()) == BitWidth); } - /// \brief Return true if this APInt value contains a sequence of ones with + /// Return true if this APInt value contains a sequence of ones with /// the remainder zero. bool isShiftedMask() const { if (isSingleWord()) @@ -519,29 +525,29 @@ public: /// \name Value Generators /// @{ - /// \brief Gets maximum unsigned value of APInt for specific bit width. + /// Gets maximum unsigned value of APInt for specific bit width. static APInt getMaxValue(unsigned numBits) { return getAllOnesValue(numBits); } - /// \brief Gets maximum signed value of APInt for a specific bit width. + /// Gets maximum signed value of APInt for a specific bit width. static APInt getSignedMaxValue(unsigned numBits) { APInt API = getAllOnesValue(numBits); API.clearBit(numBits - 1); return API; } - /// \brief Gets minimum unsigned value of APInt for a specific bit width. + /// Gets minimum unsigned value of APInt for a specific bit width. static APInt getMinValue(unsigned numBits) { return APInt(numBits, 0); } - /// \brief Gets minimum signed value of APInt for a specific bit width. + /// Gets minimum signed value of APInt for a specific bit width. static APInt getSignedMinValue(unsigned numBits) { APInt API(numBits, 0); API.setBit(numBits - 1); return API; } - /// \brief Get the SignMask for a specific bit width. + /// Get the SignMask for a specific bit width. /// /// This is just a wrapper function of getSignedMinValue(), and it helps code /// readability when we want to get a SignMask. @@ -549,19 +555,19 @@ public: return getSignedMinValue(BitWidth); } - /// \brief Get the all-ones value. + /// Get the all-ones value. /// /// \returns the all-ones value for an APInt of the specified bit-width. static APInt getAllOnesValue(unsigned numBits) { return APInt(numBits, WORD_MAX, true); } - /// \brief Get the '0' value. + /// Get the '0' value. /// /// \returns the '0' value for an APInt of the specified bit-width. static APInt getNullValue(unsigned numBits) { return APInt(numBits, 0); } - /// \brief Compute an APInt containing numBits highbits from this APInt. + /// Compute an APInt containing numBits highbits from this APInt. /// /// Get an APInt with the same BitWidth as this APInt, just zero mask /// the low bits and right shift to the least significant bit. @@ -569,7 +575,7 @@ public: /// \returns the high "numBits" bits of this APInt. APInt getHiBits(unsigned numBits) const; - /// \brief Compute an APInt containing numBits lowbits from this APInt. + /// Compute an APInt containing numBits lowbits from this APInt. /// /// Get an APInt with the same BitWidth as this APInt, just zero mask /// the high bits. @@ -577,14 +583,14 @@ public: /// \returns the low "numBits" bits of this APInt. APInt getLoBits(unsigned numBits) const; - /// \brief Return an APInt with exactly one bit set in the result. + /// Return an APInt with exactly one bit set in the result. static APInt getOneBitSet(unsigned numBits, unsigned BitNo) { APInt Res(numBits, 0); Res.setBit(BitNo); return Res; } - /// \brief Get a value with a block of bits set. + /// Get a value with a block of bits set. /// /// Constructs an APInt value that has a contiguous range of bits set. The /// bits from loBit (inclusive) to hiBit (exclusive) will be set. All other @@ -603,7 +609,7 @@ public: return Res; } - /// \brief Get a value with upper bits starting at loBit set. + /// Get a value with upper bits starting at loBit set. /// /// Constructs an APInt value that has a contiguous range of bits set. The /// bits from loBit (inclusive) to numBits (exclusive) will be set. All other @@ -620,7 +626,7 @@ public: return Res; } - /// \brief Get a value with high bits set + /// Get a value with high bits set /// /// Constructs an APInt value that has the top hiBitsSet bits set. /// @@ -632,7 +638,7 @@ public: return Res; } - /// \brief Get a value with low bits set + /// Get a value with low bits set /// /// Constructs an APInt value that has the bottom loBitsSet bits set. /// @@ -644,10 +650,10 @@ public: return Res; } - /// \brief Return a value containing V broadcasted over NewLen bits. + /// Return a value containing V broadcasted over NewLen bits. static APInt getSplat(unsigned NewLen, const APInt &V); - /// \brief Determine if two APInts have the same value, after zero-extending + /// Determine if two APInts have the same value, after zero-extending /// one of them (if needed!) to ensure that the bit-widths match. static bool isSameValue(const APInt &I1, const APInt &I2) { if (I1.getBitWidth() == I2.getBitWidth()) @@ -659,7 +665,7 @@ public: return I1.zext(I2.getBitWidth()) == I2; } - /// \brief Overload to compute a hash_code for an APInt value. + /// Overload to compute a hash_code for an APInt value. friend hash_code hash_value(const APInt &Arg); /// This function returns a pointer to the internal storage of the APInt. @@ -675,7 +681,7 @@ public: /// \name Unary Operators /// @{ - /// \brief Postfix increment operator. + /// Postfix increment operator. /// /// Increments *this by 1. /// @@ -686,12 +692,12 @@ public: return API; } - /// \brief Prefix increment operator. + /// Prefix increment operator. /// /// \returns *this incremented by one APInt &operator++(); - /// \brief Postfix decrement operator. + /// Postfix decrement operator. /// /// Decrements *this by 1. /// @@ -702,12 +708,12 @@ public: return API; } - /// \brief Prefix decrement operator. + /// Prefix decrement operator. /// /// \returns *this decremented by one. APInt &operator--(); - /// \brief Logical negation operator. + /// Logical negation operator. /// /// Performs logical negation operation on this APInt. /// @@ -722,7 +728,7 @@ public: /// \name Assignment Operators /// @{ - /// \brief Copy assignment operator. + /// Copy assignment operator. /// /// \returns *this after assignment of RHS. APInt &operator=(const APInt &RHS) { @@ -737,8 +743,13 @@ public: return *this; } - /// @brief Move assignment operator. + /// Move assignment operator. APInt &operator=(APInt &&that) { +#ifdef _MSC_VER + // The MSVC std::shuffle implementation still does self-assignment. + if (this == &that) + return *this; +#endif assert(this != &that && "Self-move not supported"); if (!isSingleWord()) delete[] U.pVal; @@ -753,7 +764,7 @@ public: return *this; } - /// \brief Assignment operator. + /// Assignment operator. /// /// The RHS value is assigned to *this. If the significant bits in RHS exceed /// the bit width, the excess bits are truncated. If the bit width is larger @@ -771,7 +782,7 @@ public: return *this; } - /// \brief Bitwise AND assignment operator. + /// Bitwise AND assignment operator. /// /// Performs a bitwise AND operation on this APInt and RHS. The result is /// assigned to *this. @@ -786,7 +797,7 @@ public: return *this; } - /// \brief Bitwise AND assignment operator. + /// Bitwise AND assignment operator. /// /// Performs a bitwise AND operation on this APInt and RHS. RHS is /// logically zero-extended or truncated to match the bit-width of @@ -801,7 +812,7 @@ public: return *this; } - /// \brief Bitwise OR assignment operator. + /// Bitwise OR assignment operator. /// /// Performs a bitwise OR operation on this APInt and RHS. The result is /// assigned *this; @@ -816,7 +827,7 @@ public: return *this; } - /// \brief Bitwise OR assignment operator. + /// Bitwise OR assignment operator. /// /// Performs a bitwise OR operation on this APInt and RHS. RHS is /// logically zero-extended or truncated to match the bit-width of @@ -831,7 +842,7 @@ public: return *this; } - /// \brief Bitwise XOR assignment operator. + /// Bitwise XOR assignment operator. /// /// Performs a bitwise XOR operation on this APInt and RHS. The result is /// assigned to *this. @@ -846,7 +857,7 @@ public: return *this; } - /// \brief Bitwise XOR assignment operator. + /// Bitwise XOR assignment operator. /// /// Performs a bitwise XOR operation on this APInt and RHS. RHS is /// logically zero-extended or truncated to match the bit-width of @@ -861,7 +872,7 @@ public: return *this; } - /// \brief Multiplication assignment operator. + /// Multiplication assignment operator. /// /// Multiplies this APInt by RHS and assigns the result to *this. /// @@ -869,7 +880,7 @@ public: APInt &operator*=(const APInt &RHS); APInt &operator*=(uint64_t RHS); - /// \brief Addition assignment operator. + /// Addition assignment operator. /// /// Adds RHS to *this and assigns the result to *this. /// @@ -877,7 +888,7 @@ public: APInt &operator+=(const APInt &RHS); APInt &operator+=(uint64_t RHS); - /// \brief Subtraction assignment operator. + /// Subtraction assignment operator. /// /// Subtracts RHS from *this and assigns the result to *this. /// @@ -885,7 +896,7 @@ public: APInt &operator-=(const APInt &RHS); APInt &operator-=(uint64_t RHS); - /// \brief Left-shift assignment function. + /// Left-shift assignment function. /// /// Shifts *this left by shiftAmt and assigns the result to *this. /// @@ -903,7 +914,7 @@ public: return *this; } - /// \brief Left-shift assignment function. + /// Left-shift assignment function. /// /// Shifts *this left by shiftAmt and assigns the result to *this. /// @@ -914,22 +925,22 @@ public: /// \name Binary Operators /// @{ - /// \brief Multiplication operator. + /// Multiplication operator. /// /// Multiplies this APInt by RHS and returns the result. APInt operator*(const APInt &RHS) const; - /// \brief Left logical shift operator. + /// Left logical shift operator. /// /// Shifts this APInt left by \p Bits and returns the result. APInt operator<<(unsigned Bits) const { return shl(Bits); } - /// \brief Left logical shift operator. + /// Left logical shift operator. /// /// Shifts this APInt left by \p Bits and returns the result. APInt operator<<(const APInt &Bits) const { return shl(Bits); } - /// \brief Arithmetic right-shift function. + /// Arithmetic right-shift function. /// /// Arithmetic right-shift this APInt by shiftAmt. APInt ashr(unsigned ShiftAmt) const { @@ -953,7 +964,7 @@ public: ashrSlowCase(ShiftAmt); } - /// \brief Logical right-shift function. + /// Logical right-shift function. /// /// Logical right-shift this APInt by shiftAmt. APInt lshr(unsigned shiftAmt) const { @@ -975,7 +986,7 @@ public: lshrSlowCase(ShiftAmt); } - /// \brief Left-shift function. + /// Left-shift function. /// /// Left-shift this APInt by shiftAmt. APInt shl(unsigned shiftAmt) const { @@ -984,13 +995,13 @@ public: return R; } - /// \brief Rotate left by rotateAmt. + /// Rotate left by rotateAmt. APInt rotl(unsigned rotateAmt) const; - /// \brief Rotate right by rotateAmt. + /// Rotate right by rotateAmt. APInt rotr(unsigned rotateAmt) const; - /// \brief Arithmetic right-shift function. + /// Arithmetic right-shift function. /// /// Arithmetic right-shift this APInt by shiftAmt. APInt ashr(const APInt &ShiftAmt) const { @@ -1002,7 +1013,7 @@ public: /// Arithmetic right-shift this APInt by shiftAmt in place. void ashrInPlace(const APInt &shiftAmt); - /// \brief Logical right-shift function. + /// Logical right-shift function. /// /// Logical right-shift this APInt by shiftAmt. APInt lshr(const APInt &ShiftAmt) const { @@ -1014,7 +1025,7 @@ public: /// Logical right-shift this APInt by ShiftAmt in place. void lshrInPlace(const APInt &ShiftAmt); - /// \brief Left-shift function. + /// Left-shift function. /// /// Left-shift this APInt by shiftAmt. APInt shl(const APInt &ShiftAmt) const { @@ -1023,28 +1034,31 @@ public: return R; } - /// \brief Rotate left by rotateAmt. + /// Rotate left by rotateAmt. APInt rotl(const APInt &rotateAmt) const; - /// \brief Rotate right by rotateAmt. + /// Rotate right by rotateAmt. APInt rotr(const APInt &rotateAmt) const; - /// \brief Unsigned division operation. + /// Unsigned division operation. /// /// Perform an unsigned divide operation on this APInt by RHS. Both this and /// RHS are treated as unsigned quantities for purposes of this division. /// - /// \returns a new APInt value containing the division result + /// \returns a new APInt value containing the division result, rounded towards + /// zero. APInt udiv(const APInt &RHS) const; APInt udiv(uint64_t RHS) const; - /// \brief Signed division function for APInt. + /// Signed division function for APInt. /// /// Signed divide this APInt by APInt RHS. + /// + /// The result is rounded towards zero. APInt sdiv(const APInt &RHS) const; APInt sdiv(int64_t RHS) const; - /// \brief Unsigned remainder operation. + /// Unsigned remainder operation. /// /// Perform an unsigned remainder operation on this APInt with RHS being the /// divisor. Both this and RHS are treated as unsigned quantities for purposes @@ -1056,13 +1070,13 @@ public: APInt urem(const APInt &RHS) const; uint64_t urem(uint64_t RHS) const; - /// \brief Function for signed remainder operation. + /// Function for signed remainder operation. /// /// Signed remainder operation on APInt. APInt srem(const APInt &RHS) const; int64_t srem(int64_t RHS) const; - /// \brief Dual division/remainder interface. + /// Dual division/remainder interface. /// /// Sometimes it is convenient to divide two APInt values and obtain both the /// quotient and remainder. This function does both operations in the same @@ -1090,7 +1104,7 @@ public: APInt sshl_ov(const APInt &Amt, bool &Overflow) const; APInt ushl_ov(const APInt &Amt, bool &Overflow) const; - /// \brief Array-indexing support. + /// Array-indexing support. /// /// \returns the bit value at bitPosition bool operator[](unsigned bitPosition) const { @@ -1102,7 +1116,7 @@ public: /// \name Comparison Operators /// @{ - /// \brief Equality operator. + /// Equality operator. /// /// Compares this APInt with RHS for the validity of the equality /// relationship. @@ -1113,7 +1127,7 @@ public: return EqualSlowCase(RHS); } - /// \brief Equality operator. + /// Equality operator. /// /// Compares this APInt with a uint64_t for the validity of the equality /// relationship. @@ -1123,7 +1137,7 @@ public: return (isSingleWord() || getActiveBits() <= 64) && getZExtValue() == Val; } - /// \brief Equality comparison. + /// Equality comparison. /// /// Compares this APInt with RHS for the validity of the equality /// relationship. @@ -1131,7 +1145,7 @@ public: /// \returns true if *this == Val bool eq(const APInt &RHS) const { return (*this) == RHS; } - /// \brief Inequality operator. + /// Inequality operator. /// /// Compares this APInt with RHS for the validity of the inequality /// relationship. @@ -1139,7 +1153,7 @@ public: /// \returns true if *this != Val bool operator!=(const APInt &RHS) const { return !((*this) == RHS); } - /// \brief Inequality operator. + /// Inequality operator. /// /// Compares this APInt with a uint64_t for the validity of the inequality /// relationship. @@ -1147,7 +1161,7 @@ public: /// \returns true if *this != Val bool operator!=(uint64_t Val) const { return !((*this) == Val); } - /// \brief Inequality comparison + /// Inequality comparison /// /// Compares this APInt with RHS for the validity of the inequality /// relationship. @@ -1155,7 +1169,7 @@ public: /// \returns true if *this != Val bool ne(const APInt &RHS) const { return !((*this) == RHS); } - /// \brief Unsigned less than comparison + /// Unsigned less than comparison /// /// Regards both *this and RHS as unsigned quantities and compares them for /// the validity of the less-than relationship. @@ -1163,7 +1177,7 @@ public: /// \returns true if *this < RHS when both are considered unsigned. bool ult(const APInt &RHS) const { return compare(RHS) < 0; } - /// \brief Unsigned less than comparison + /// Unsigned less than comparison /// /// Regards both *this as an unsigned quantity and compares it with RHS for /// the validity of the less-than relationship. @@ -1174,7 +1188,7 @@ public: return (isSingleWord() || getActiveBits() <= 64) && getZExtValue() < RHS; } - /// \brief Signed less than comparison + /// Signed less than comparison /// /// Regards both *this and RHS as signed quantities and compares them for /// validity of the less-than relationship. @@ -1182,7 +1196,7 @@ public: /// \returns true if *this < RHS when both are considered signed. bool slt(const APInt &RHS) const { return compareSigned(RHS) < 0; } - /// \brief Signed less than comparison + /// Signed less than comparison /// /// Regards both *this as a signed quantity and compares it with RHS for /// the validity of the less-than relationship. @@ -1193,7 +1207,7 @@ public: : getSExtValue() < RHS; } - /// \brief Unsigned less or equal comparison + /// Unsigned less or equal comparison /// /// Regards both *this and RHS as unsigned quantities and compares them for /// validity of the less-or-equal relationship. @@ -1201,7 +1215,7 @@ public: /// \returns true if *this <= RHS when both are considered unsigned. bool ule(const APInt &RHS) const { return compare(RHS) <= 0; } - /// \brief Unsigned less or equal comparison + /// Unsigned less or equal comparison /// /// Regards both *this as an unsigned quantity and compares it with RHS for /// the validity of the less-or-equal relationship. @@ -1209,7 +1223,7 @@ public: /// \returns true if *this <= RHS when considered unsigned. bool ule(uint64_t RHS) const { return !ugt(RHS); } - /// \brief Signed less or equal comparison + /// Signed less or equal comparison /// /// Regards both *this and RHS as signed quantities and compares them for /// validity of the less-or-equal relationship. @@ -1217,7 +1231,7 @@ public: /// \returns true if *this <= RHS when both are considered signed. bool sle(const APInt &RHS) const { return compareSigned(RHS) <= 0; } - /// \brief Signed less or equal comparison + /// Signed less or equal comparison /// /// Regards both *this as a signed quantity and compares it with RHS for the /// validity of the less-or-equal relationship. @@ -1225,7 +1239,7 @@ public: /// \returns true if *this <= RHS when considered signed. bool sle(uint64_t RHS) const { return !sgt(RHS); } - /// \brief Unsigned greather than comparison + /// Unsigned greather than comparison /// /// Regards both *this and RHS as unsigned quantities and compares them for /// the validity of the greater-than relationship. @@ -1233,7 +1247,7 @@ public: /// \returns true if *this > RHS when both are considered unsigned. bool ugt(const APInt &RHS) const { return !ule(RHS); } - /// \brief Unsigned greater than comparison + /// Unsigned greater than comparison /// /// Regards both *this as an unsigned quantity and compares it with RHS for /// the validity of the greater-than relationship. @@ -1244,7 +1258,7 @@ public: return (!isSingleWord() && getActiveBits() > 64) || getZExtValue() > RHS; } - /// \brief Signed greather than comparison + /// Signed greather than comparison /// /// Regards both *this and RHS as signed quantities and compares them for the /// validity of the greater-than relationship. @@ -1252,7 +1266,7 @@ public: /// \returns true if *this > RHS when both are considered signed. bool sgt(const APInt &RHS) const { return !sle(RHS); } - /// \brief Signed greater than comparison + /// Signed greater than comparison /// /// Regards both *this as a signed quantity and compares it with RHS for /// the validity of the greater-than relationship. @@ -1263,7 +1277,7 @@ public: : getSExtValue() > RHS; } - /// \brief Unsigned greater or equal comparison + /// Unsigned greater or equal comparison /// /// Regards both *this and RHS as unsigned quantities and compares them for /// validity of the greater-or-equal relationship. @@ -1271,7 +1285,7 @@ public: /// \returns true if *this >= RHS when both are considered unsigned. bool uge(const APInt &RHS) const { return !ult(RHS); } - /// \brief Unsigned greater or equal comparison + /// Unsigned greater or equal comparison /// /// Regards both *this as an unsigned quantity and compares it with RHS for /// the validity of the greater-or-equal relationship. @@ -1279,7 +1293,7 @@ public: /// \returns true if *this >= RHS when considered unsigned. bool uge(uint64_t RHS) const { return !ult(RHS); } - /// \brief Signed greather or equal comparison + /// Signed greater or equal comparison /// /// Regards both *this and RHS as signed quantities and compares them for /// validity of the greater-or-equal relationship. @@ -1287,7 +1301,7 @@ public: /// \returns true if *this >= RHS when both are considered signed. bool sge(const APInt &RHS) const { return !slt(RHS); } - /// \brief Signed greater or equal comparison + /// Signed greater or equal comparison /// /// Regards both *this as a signed quantity and compares it with RHS for /// the validity of the greater-or-equal relationship. @@ -1316,13 +1330,13 @@ public: /// \name Resizing Operators /// @{ - /// \brief Truncate to new width. + /// Truncate to new width. /// /// Truncate the APInt to a specified width. It is an error to specify a width /// that is greater than or equal to the current width. APInt trunc(unsigned width) const; - /// \brief Sign extend to a new width. + /// Sign extend to a new width. /// /// This operation sign extends the APInt to a new width. If the high order /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. @@ -1330,32 +1344,32 @@ public: /// current width. APInt sext(unsigned width) const; - /// \brief Zero extend to a new width. + /// Zero extend to a new width. /// /// This operation zero extends the APInt to a new width. The high order bits /// are filled with 0 bits. It is an error to specify a width that is less /// than or equal to the current width. APInt zext(unsigned width) const; - /// \brief Sign extend or truncate to width + /// Sign extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is sign /// extended, truncated, or left alone to make it that width. APInt sextOrTrunc(unsigned width) const; - /// \brief Zero extend or truncate to width + /// Zero extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is zero /// extended, truncated, or left alone to make it that width. APInt zextOrTrunc(unsigned width) const; - /// \brief Sign extend or truncate to width + /// Sign extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is sign /// extended, or left alone to make it that width. APInt sextOrSelf(unsigned width) const; - /// \brief Zero extend or truncate to width + /// Zero extend or truncate to width /// /// Make this APInt have the bit width given by \p width. The value is zero /// extended, or left alone to make it that width. @@ -1365,7 +1379,7 @@ public: /// \name Bit Manipulation Operators /// @{ - /// \brief Set every bit to 1. + /// Set every bit to 1. void setAllBits() { if (isSingleWord()) U.VAL = WORD_MAX; @@ -1376,7 +1390,7 @@ public: clearUnusedBits(); } - /// \brief Set a given bit to 1. + /// Set a given bit to 1. /// /// Set the given bit to 1 whose position is given as "bitPosition". void setBit(unsigned BitPosition) { @@ -1427,7 +1441,7 @@ public: return setBits(BitWidth - hiBits, BitWidth); } - /// \brief Set every bit to 0. + /// Set every bit to 0. void clearAllBits() { if (isSingleWord()) U.VAL = 0; @@ -1435,7 +1449,7 @@ public: memset(U.pVal, 0, getNumWords() * APINT_WORD_SIZE); } - /// \brief Set a given bit to 0. + /// Set a given bit to 0. /// /// Set the given bit to 0 whose position is given as "bitPosition". void clearBit(unsigned BitPosition) { @@ -1452,7 +1466,7 @@ public: clearBit(BitWidth - 1); } - /// \brief Toggle every bit to its opposite value. + /// Toggle every bit to its opposite value. void flipAllBits() { if (isSingleWord()) { U.VAL ^= WORD_MAX; @@ -1462,7 +1476,7 @@ public: } } - /// \brief Toggles a given bit to its opposite value. + /// Toggles a given bit to its opposite value. /// /// Toggle a given bit to its opposite value whose position is given /// as "bitPosition". @@ -1484,17 +1498,17 @@ public: /// \name Value Characterization Functions /// @{ - /// \brief Return the number of bits in the APInt. + /// Return the number of bits in the APInt. unsigned getBitWidth() const { return BitWidth; } - /// \brief Get the number of words. + /// Get the number of words. /// /// Here one word's bitwidth equals to that of uint64_t. /// /// \returns the number of words to hold the integer value of this APInt. unsigned getNumWords() const { return getNumWords(BitWidth); } - /// \brief Get the number of words. + /// Get the number of words. /// /// *NOTE* Here one word's bitwidth equals to that of uint64_t. /// @@ -1504,14 +1518,14 @@ public: return ((uint64_t)BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; } - /// \brief Compute the number of active bits in the value + /// Compute the number of active bits in the value /// /// This function returns the number of active bits which is defined as the /// bit width minus the number of leading zeros. This is used in several /// computations to see how "wide" the value is. unsigned getActiveBits() const { return BitWidth - countLeadingZeros(); } - /// \brief Compute the number of active words in the value of this APInt. + /// Compute the number of active words in the value of this APInt. /// /// This is used in conjunction with getActiveData to extract the raw value of /// the APInt. @@ -1520,7 +1534,7 @@ public: return numActiveBits ? whichWord(numActiveBits - 1) + 1 : 1; } - /// \brief Get the minimum bit size for this signed APInt + /// Get the minimum bit size for this signed APInt /// /// Computes the minimum bit width for this APInt while considering it to be a /// signed (and probably negative) value. If the value is not negative, this @@ -1534,7 +1548,7 @@ public: return getActiveBits() + 1; } - /// \brief Get zero extended value + /// Get zero extended value /// /// This method attempts to return the value of this APInt as a zero extended /// uint64_t. The bitwidth must be <= 64 or the value must fit within a @@ -1546,7 +1560,7 @@ public: return U.pVal[0]; } - /// \brief Get sign extended value + /// Get sign extended value /// /// This method attempts to return the value of this APInt as a sign extended /// int64_t. The bit width must be <= 64 or the value must fit within an @@ -1558,13 +1572,13 @@ public: return int64_t(U.pVal[0]); } - /// \brief Get bits required for string value. + /// Get bits required for string value. /// /// This method determines how many bits are required to hold the APInt /// equivalent of the string given by \p str. static unsigned getBitsNeeded(StringRef str, uint8_t radix); - /// \brief The APInt version of the countLeadingZeros functions in + /// The APInt version of the countLeadingZeros functions in /// MathExtras.h. /// /// It counts the number of zeros from the most significant bit to the first @@ -1580,7 +1594,7 @@ public: return countLeadingZerosSlowCase(); } - /// \brief Count the number of leading one bits. + /// Count the number of leading one bits. /// /// This function is an APInt version of the countLeadingOnes /// functions in MathExtras.h. It counts the number of ones from the most @@ -1600,7 +1614,7 @@ public: return isNegative() ? countLeadingOnes() : countLeadingZeros(); } - /// \brief Count the number of trailing zero bits. + /// Count the number of trailing zero bits. /// /// This function is an APInt version of the countTrailingZeros /// functions in MathExtras.h. It counts the number of zeros from the least @@ -1614,7 +1628,7 @@ public: return countTrailingZerosSlowCase(); } - /// \brief Count the number of trailing one bits. + /// Count the number of trailing one bits. /// /// This function is an APInt version of the countTrailingOnes /// functions in MathExtras.h. It counts the number of ones from the least @@ -1628,7 +1642,7 @@ public: return countTrailingOnesSlowCase(); } - /// \brief Count the number of bits set. + /// Count the number of bits set. /// /// This function is an APInt version of the countPopulation functions /// in MathExtras.h. It counts the number of 1 bits in the APInt value. @@ -1662,7 +1676,7 @@ public: toString(Str, Radix, true, false); } - /// \brief Return the APInt as a std::string. + /// Return the APInt as a std::string. /// /// Note that this is an inefficient method. It is better to pass in a /// SmallVector/SmallString to the methods above to avoid thrashing the heap @@ -1676,16 +1690,16 @@ public: /// Value. APInt reverseBits() const; - /// \brief Converts this APInt to a double value. + /// Converts this APInt to a double value. double roundToDouble(bool isSigned) const; - /// \brief Converts this unsigned APInt to a double value. + /// Converts this unsigned APInt to a double value. double roundToDouble() const { return roundToDouble(false); } - /// \brief Converts this signed APInt to a double value. + /// Converts this signed APInt to a double value. double signedRoundToDouble() const { return roundToDouble(true); } - /// \brief Converts APInt bits to a double + /// Converts APInt bits to a double /// /// The conversion does not do a translation from integer to double, it just /// re-interprets the bits as a double. Note that it is valid to do this on @@ -1694,7 +1708,7 @@ public: return BitsToDouble(getWord(0)); } - /// \brief Converts APInt bits to a double + /// Converts APInt bits to a double /// /// The conversion does not do a translation from integer to float, it just /// re-interprets the bits as a float. Note that it is valid to do this on @@ -1703,7 +1717,7 @@ public: return BitsToFloat(getWord(0)); } - /// \brief Converts a double to APInt bits. + /// Converts a double to APInt bits. /// /// The conversion does not do a translation from double to integer, it just /// re-interprets the bits of the double. @@ -1711,7 +1725,7 @@ public: return APInt(sizeof(double) * CHAR_BIT, DoubleToBits(V)); } - /// \brief Converts a float to APInt bits. + /// Converts a float to APInt bits. /// /// The conversion does not do a translation from float to integer, it just /// re-interprets the bits of the float. @@ -1770,10 +1784,10 @@ public: return logBase2(); } - /// \brief Compute the square root + /// Compute the square root APInt sqrt() const; - /// \brief Get the absolute value; + /// Get the absolute value; /// /// If *this is < 0 then return -(*this), otherwise *this; APInt abs() const { @@ -1924,7 +1938,7 @@ public: /// Set the least significant BITS and clear the rest. static void tcSetLeastSignificantBits(WordType *, unsigned, unsigned bits); - /// \brief debug method + /// debug method void dump() const; /// @} @@ -1947,7 +1961,7 @@ inline bool operator==(uint64_t V1, const APInt &V2) { return V2 == V1; } inline bool operator!=(uint64_t V1, const APInt &V2) { return V2 != V1; } -/// \brief Unary bitwise complement operator. +/// Unary bitwise complement operator. /// /// \returns an APInt that is the bitwise complement of \p v. inline APInt operator~(APInt v) { @@ -2080,27 +2094,27 @@ inline APInt operator*(uint64_t LHS, APInt b) { namespace APIntOps { -/// \brief Determine the smaller of two APInts considered to be signed. +/// Determine the smaller of two APInts considered to be signed. inline const APInt &smin(const APInt &A, const APInt &B) { return A.slt(B) ? A : B; } -/// \brief Determine the larger of two APInts considered to be signed. +/// Determine the larger of two APInts considered to be signed. inline const APInt &smax(const APInt &A, const APInt &B) { return A.sgt(B) ? A : B; } -/// \brief Determine the smaller of two APInts considered to be signed. +/// Determine the smaller of two APInts considered to be signed. inline const APInt &umin(const APInt &A, const APInt &B) { return A.ult(B) ? A : B; } -/// \brief Determine the larger of two APInts considered to be unsigned. +/// Determine the larger of two APInts considered to be unsigned. inline const APInt &umax(const APInt &A, const APInt &B) { return A.ugt(B) ? A : B; } -/// \brief Compute GCD of two unsigned APInt values. +/// Compute GCD of two unsigned APInt values. /// /// This function returns the greatest common divisor of the two APInt values /// using Stein's algorithm. @@ -2108,44 +2122,50 @@ inline const APInt &umax(const APInt &A, const APInt &B) { /// \returns the greatest common divisor of A and B. APInt GreatestCommonDivisor(APInt A, APInt B); -/// \brief Converts the given APInt to a double value. +/// Converts the given APInt to a double value. /// /// Treats the APInt as an unsigned value for conversion purposes. inline double RoundAPIntToDouble(const APInt &APIVal) { return APIVal.roundToDouble(); } -/// \brief Converts the given APInt to a double value. +/// Converts the given APInt to a double value. /// /// Treats the APInt as a signed value for conversion purposes. inline double RoundSignedAPIntToDouble(const APInt &APIVal) { return APIVal.signedRoundToDouble(); } -/// \brief Converts the given APInt to a float vlalue. +/// Converts the given APInt to a float vlalue. inline float RoundAPIntToFloat(const APInt &APIVal) { return float(RoundAPIntToDouble(APIVal)); } -/// \brief Converts the given APInt to a float value. +/// Converts the given APInt to a float value. /// /// Treast the APInt as a signed value for conversion purposes. inline float RoundSignedAPIntToFloat(const APInt &APIVal) { return float(APIVal.signedRoundToDouble()); } -/// \brief Converts the given double value into a APInt. +/// Converts the given double value into a APInt. /// /// This function convert a double value to an APInt value. APInt RoundDoubleToAPInt(double Double, unsigned width); -/// \brief Converts a float value into a APInt. +/// Converts a float value into a APInt. /// /// Converts a float value into an APInt value. inline APInt RoundFloatToAPInt(float Float, unsigned width) { return RoundDoubleToAPInt(double(Float), width); } +/// Return A unsign-divided by B, rounded by the given rounding mode. +APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM); + +/// Return A sign-divided by B, rounded by the given rounding mode. +APInt RoundingSDiv(const APInt &A, const APInt &B, APInt::Rounding RM); + } // End of APIntOps namespace // See friend declaration above. This additional declaration is required in diff --git a/contrib/llvm/include/llvm/ADT/APSInt.h b/contrib/llvm/include/llvm/ADT/APSInt.h index dabbf3314bd0..7ee2c4c62fce 100644 --- a/contrib/llvm/include/llvm/ADT/APSInt.h +++ b/contrib/llvm/include/llvm/ADT/APSInt.h @@ -72,7 +72,7 @@ public: } using APInt::toString; - /// \brief Get the correctly-extended \c int64_t value. + /// Get the correctly-extended \c int64_t value. int64_t getExtValue() const { assert(getMinSignedBits() <= 64 && "Too many bits for int64_t"); return isSigned() ? getSExtValue() : getZExtValue(); @@ -279,13 +279,13 @@ public: : APInt::getSignedMinValue(numBits), Unsigned); } - /// \brief Determine if two APSInts have the same value, zero- or + /// Determine if two APSInts have the same value, zero- or /// sign-extending as needed. static bool isSameValue(const APSInt &I1, const APSInt &I2) { return !compareValues(I1, I2); } - /// \brief Compare underlying values of two numbers. + /// Compare underlying values of two numbers. static int compareValues(const APSInt &I1, const APSInt &I2) { if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) return I1.IsUnsigned ? I1.compare(I2) : I1.compareSigned(I2); diff --git a/contrib/llvm/include/llvm/ADT/Any.h b/contrib/llvm/include/llvm/ADT/Any.h new file mode 100644 index 000000000000..c64c39987542 --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/Any.h @@ -0,0 +1,150 @@ +//===- Any.h - Generic type erased holder of any type -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Any, a non-template class modeled in the spirit of +// std::any. The idea is to provide a type-safe replacement for C's void*. +// It can hold a value of any copy-constructible copy-assignable type +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ANY_H +#define LLVM_ADT_ANY_H + +#include "llvm/ADT/STLExtras.h" + +#include <cassert> +#include <memory> +#include <type_traits> + +namespace llvm { + +class Any { + template <typename T> struct TypeId { static const char Id; }; + + struct StorageBase { + virtual ~StorageBase() = default; + virtual std::unique_ptr<StorageBase> clone() const = 0; + virtual const void *id() const = 0; + }; + + template <typename T> struct StorageImpl : public StorageBase { + explicit StorageImpl(const T &Value) : Value(Value) {} + + explicit StorageImpl(T &&Value) : Value(std::move(Value)) {} + + std::unique_ptr<StorageBase> clone() const override { + return llvm::make_unique<StorageImpl<T>>(Value); + } + + const void *id() const override { return &TypeId<T>::Id; } + + T Value; + + private: + StorageImpl &operator=(const StorageImpl &Other) = delete; + StorageImpl(const StorageImpl &Other) = delete; + }; + +public: + Any() = default; + + Any(const Any &Other) + : Storage(Other.Storage ? Other.Storage->clone() : nullptr) {} + + // When T is Any or T is not copy-constructible we need to explicitly disable + // the forwarding constructor so that the copy constructor gets selected + // instead. + template < + typename T, + typename std::enable_if< + llvm::conjunction< + llvm::negation<std::is_same<typename std::decay<T>::type, Any>>, + std::is_copy_constructible<typename std::decay<T>::type>>::value, + int>::type = 0> + Any(T &&Value) { + using U = typename std::decay<T>::type; + Storage = llvm::make_unique<StorageImpl<U>>(std::forward<T>(Value)); + } + + Any(Any &&Other) : Storage(std::move(Other.Storage)) {} + + Any &swap(Any &Other) { + std::swap(Storage, Other.Storage); + return *this; + } + + Any &operator=(Any Other) { + Storage = std::move(Other.Storage); + return *this; + } + + bool hasValue() const { return !!Storage; } + + void reset() { Storage.reset(); } + +private: + template <class T> friend T any_cast(const Any &Value); + template <class T> friend T any_cast(Any &Value); + template <class T> friend T any_cast(Any &&Value); + template <class T> friend const T *any_cast(const Any *Value); + template <class T> friend T *any_cast(Any *Value); + template <typename T> friend bool any_isa(const Any &Value); + + std::unique_ptr<StorageBase> Storage; +}; + +template <typename T> const char Any::TypeId<T>::Id = 0; + + +template <typename T> bool any_isa(const Any &Value) { + if (!Value.Storage) + return false; + using U = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + return Value.Storage->id() == &Any::TypeId<U>::Id; +} + +template <class T> T any_cast(const Any &Value) { + using U = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + return static_cast<T>(*any_cast<U>(&Value)); +} + +template <class T> T any_cast(Any &Value) { + using U = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + return static_cast<T>(*any_cast<U>(&Value)); +} + +template <class T> T any_cast(Any &&Value) { + using U = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + return static_cast<T>(std::move(*any_cast<U>(&Value))); +} + +template <class T> const T *any_cast(const Any *Value) { + using U = + typename std::remove_cv<typename std::remove_reference<T>::type>::type; + assert(Value && any_isa<T>(*Value) && "Bad any cast!"); + if (!Value || !any_isa<U>(*Value)) + return nullptr; + return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value; +} + +template <class T> T *any_cast(Any *Value) { + using U = typename std::decay<T>::type; + assert(Value && any_isa<U>(*Value) && "Bad any cast!"); + if (!Value || !any_isa<U>(*Value)) + return nullptr; + return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value; +} + +} // end namespace llvm + +#endif // LLVM_ADT_ANY_H diff --git a/contrib/llvm/include/llvm/ADT/ArrayRef.h b/contrib/llvm/include/llvm/ADT/ArrayRef.h index 5f7a769ddac4..9cb25b09c6cb 100644 --- a/contrib/llvm/include/llvm/ADT/ArrayRef.h +++ b/contrib/llvm/include/llvm/ADT/ArrayRef.h @@ -184,51 +184,51 @@ namespace llvm { /// slice(n) - Chop off the first N elements of the array. ArrayRef<T> slice(size_t N) const { return slice(N, size() - N); } - /// \brief Drop the first \p N elements of the array. + /// Drop the first \p N elements of the array. ArrayRef<T> drop_front(size_t N = 1) const { assert(size() >= N && "Dropping more elements than exist"); return slice(N, size() - N); } - /// \brief Drop the last \p N elements of the array. + /// Drop the last \p N elements of the array. ArrayRef<T> drop_back(size_t N = 1) const { assert(size() >= N && "Dropping more elements than exist"); return slice(0, size() - N); } - /// \brief Return a copy of *this with the first N elements satisfying the + /// Return a copy of *this with the first N elements satisfying the /// given predicate removed. template <class PredicateT> ArrayRef<T> drop_while(PredicateT Pred) const { return ArrayRef<T>(find_if_not(*this, Pred), end()); } - /// \brief Return a copy of *this with the first N elements not satisfying + /// Return a copy of *this with the first N elements not satisfying /// the given predicate removed. template <class PredicateT> ArrayRef<T> drop_until(PredicateT Pred) const { return ArrayRef<T>(find_if(*this, Pred), end()); } - /// \brief Return a copy of *this with only the first \p N elements. + /// Return a copy of *this with only the first \p N elements. ArrayRef<T> take_front(size_t N = 1) const { if (N >= size()) return *this; return drop_back(size() - N); } - /// \brief Return a copy of *this with only the last \p N elements. + /// Return a copy of *this with only the last \p N elements. ArrayRef<T> take_back(size_t N = 1) const { if (N >= size()) return *this; return drop_front(size() - N); } - /// \brief Return the first N elements of this Array that satisfy the given + /// Return the first N elements of this Array that satisfy the given /// predicate. template <class PredicateT> ArrayRef<T> take_while(PredicateT Pred) const { return ArrayRef<T>(begin(), find_if_not(*this, Pred)); } - /// \brief Return the first N elements of this Array that don't satisfy the + /// Return the first N elements of this Array that don't satisfy the /// given predicate. template <class PredicateT> ArrayRef<T> take_until(PredicateT Pred) const { return ArrayRef<T>(begin(), find_if(*this, Pred)); @@ -358,7 +358,7 @@ namespace llvm { return slice(N, this->size() - N); } - /// \brief Drop the first \p N elements of the array. + /// Drop the first \p N elements of the array. MutableArrayRef<T> drop_front(size_t N = 1) const { assert(this->size() >= N && "Dropping more elements than exist"); return slice(N, this->size() - N); @@ -369,42 +369,42 @@ namespace llvm { return slice(0, this->size() - N); } - /// \brief Return a copy of *this with the first N elements satisfying the + /// Return a copy of *this with the first N elements satisfying the /// given predicate removed. template <class PredicateT> MutableArrayRef<T> drop_while(PredicateT Pred) const { return MutableArrayRef<T>(find_if_not(*this, Pred), end()); } - /// \brief Return a copy of *this with the first N elements not satisfying + /// Return a copy of *this with the first N elements not satisfying /// the given predicate removed. template <class PredicateT> MutableArrayRef<T> drop_until(PredicateT Pred) const { return MutableArrayRef<T>(find_if(*this, Pred), end()); } - /// \brief Return a copy of *this with only the first \p N elements. + /// Return a copy of *this with only the first \p N elements. MutableArrayRef<T> take_front(size_t N = 1) const { if (N >= this->size()) return *this; return drop_back(this->size() - N); } - /// \brief Return a copy of *this with only the last \p N elements. + /// Return a copy of *this with only the last \p N elements. MutableArrayRef<T> take_back(size_t N = 1) const { if (N >= this->size()) return *this; return drop_front(this->size() - N); } - /// \brief Return the first N elements of this Array that satisfy the given + /// Return the first N elements of this Array that satisfy the given /// predicate. template <class PredicateT> MutableArrayRef<T> take_while(PredicateT Pred) const { return MutableArrayRef<T>(begin(), find_if_not(*this, Pred)); } - /// \brief Return the first N elements of this Array that don't satisfy the + /// Return the first N elements of this Array that don't satisfy the /// given predicate. template <class PredicateT> MutableArrayRef<T> take_until(PredicateT Pred) const { diff --git a/contrib/llvm/include/llvm/ADT/BitVector.h b/contrib/llvm/include/llvm/ADT/BitVector.h index 99147fec4d4c..438c7d84c581 100644 --- a/contrib/llvm/include/llvm/ADT/BitVector.h +++ b/contrib/llvm/include/llvm/ADT/BitVector.h @@ -779,7 +779,7 @@ public: } private: - /// \brief Perform a logical left shift of \p Count words by moving everything + /// Perform a logical left shift of \p Count words by moving everything /// \p Count words to the right in memory. /// /// While confusing, words are stored from least significant at Bits[0] to @@ -810,7 +810,7 @@ private: clear_unused_bits(); } - /// \brief Perform a logical right shift of \p Count words by moving those + /// Perform a logical right shift of \p Count words by moving those /// words to the left in memory. See wordShl for more information. /// void wordShr(uint32_t Count) { @@ -828,7 +828,8 @@ private: } MutableArrayRef<BitWord> allocate(size_t NumWords) { - BitWord *RawBits = (BitWord *)std::malloc(NumWords * sizeof(BitWord)); + BitWord *RawBits = static_cast<BitWord *>( + safe_malloc(NumWords * sizeof(BitWord))); return MutableArrayRef<BitWord>(RawBits, NumWords); } @@ -867,8 +868,8 @@ private: void grow(unsigned NewSize) { size_t NewCapacity = std::max<size_t>(NumBitWords(NewSize), Bits.size() * 2); assert(NewCapacity > 0 && "realloc-ing zero space"); - BitWord *NewBits = - (BitWord *)std::realloc(Bits.data(), NewCapacity * sizeof(BitWord)); + BitWord *NewBits = static_cast<BitWord *>( + safe_realloc(Bits.data(), NewCapacity * sizeof(BitWord))); Bits = MutableArrayRef<BitWord>(NewBits, NewCapacity); clear_unused_bits(); } diff --git a/contrib/llvm/include/llvm/ADT/CachedHashString.h b/contrib/llvm/include/llvm/ADT/CachedHashString.h index a56a6213a073..d8f0e7afdd49 100644 --- a/contrib/llvm/include/llvm/ADT/CachedHashString.h +++ b/contrib/llvm/include/llvm/ADT/CachedHashString.h @@ -43,6 +43,7 @@ public: } StringRef val() const { return StringRef(P, Size); } + const char *data() const { return P; } uint32_t size() const { return Size; } uint32_t hash() const { return Hash; } }; diff --git a/contrib/llvm/include/llvm/ADT/DenseMapInfo.h b/contrib/llvm/include/llvm/ADT/DenseMapInfo.h index a96904c7dbbf..5d12b424fb37 100644 --- a/contrib/llvm/include/llvm/ADT/DenseMapInfo.h +++ b/contrib/llvm/include/llvm/ADT/DenseMapInfo.h @@ -262,6 +262,13 @@ template <typename T> struct DenseMapInfo<ArrayRef<T>> { } }; +template <> struct DenseMapInfo<hash_code> { + static inline hash_code getEmptyKey() { return hash_code(-1); } + static inline hash_code getTombstoneKey() { return hash_code(-2); } + static unsigned getHashValue(hash_code val) { return val; } + static bool isEqual(hash_code LHS, hash_code RHS) { return LHS == RHS; } +}; + } // end namespace llvm #endif // LLVM_ADT_DENSEMAPINFO_H diff --git a/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h b/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h index e964d7fa2391..1f3766d3c9de 100644 --- a/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h +++ b/contrib/llvm/include/llvm/ADT/DepthFirstIterator.h @@ -177,7 +177,7 @@ public: return *this; } - /// \brief Skips all children of the current node and traverses to next node + /// Skips all children of the current node and traverses to next node /// /// Note: This function takes care of incrementing the iterator. If you /// always increment and call this function, you risk walking off the end. diff --git a/contrib/llvm/include/llvm/ADT/EpochTracker.h b/contrib/llvm/include/llvm/ADT/EpochTracker.h index db39ba4e0c50..49ef192364e8 100644 --- a/contrib/llvm/include/llvm/ADT/EpochTracker.h +++ b/contrib/llvm/include/llvm/ADT/EpochTracker.h @@ -17,7 +17,6 @@ #define LLVM_ADT_EPOCH_TRACKER_H #include "llvm/Config/abi-breaking.h" -#include "llvm/Config/llvm-config.h" #include <cstdint> @@ -25,7 +24,7 @@ namespace llvm { #if LLVM_ENABLE_ABI_BREAKING_CHECKS -/// \brief A base class for data structure classes wishing to make iterators +/// A base class for data structure classes wishing to make iterators /// ("handles") pointing into themselves fail-fast. When building without /// asserts, this class is empty and does nothing. /// @@ -40,15 +39,15 @@ class DebugEpochBase { public: DebugEpochBase() : Epoch(0) {} - /// \brief Calling incrementEpoch invalidates all handles pointing into the + /// Calling incrementEpoch invalidates all handles pointing into the /// calling instance. void incrementEpoch() { ++Epoch; } - /// \brief The destructor calls incrementEpoch to make use-after-free bugs + /// The destructor calls incrementEpoch to make use-after-free bugs /// more likely to crash deterministically. ~DebugEpochBase() { incrementEpoch(); } - /// \brief A base class for iterator classes ("handles") that wish to poll for + /// A base class for iterator classes ("handles") that wish to poll for /// iterator invalidating modifications in the underlying data structure. /// When LLVM is built without asserts, this class is empty and does nothing. /// @@ -66,12 +65,12 @@ public: explicit HandleBase(const DebugEpochBase *Parent) : EpochAddress(&Parent->Epoch), EpochAtCreation(Parent->Epoch) {} - /// \brief Returns true if the DebugEpochBase this Handle is linked to has + /// Returns true if the DebugEpochBase this Handle is linked to has /// not called incrementEpoch on itself since the creation of this /// HandleBase instance. bool isHandleInSync() const { return *EpochAddress == EpochAtCreation; } - /// \brief Returns a pointer to the epoch word stored in the data structure + /// Returns a pointer to the epoch word stored in the data structure /// this handle points into. Can be used to check if two iterators point /// into the same data structure. const void *getEpochAddress() const { return EpochAddress; } diff --git a/contrib/llvm/include/llvm/ADT/FunctionExtras.h b/contrib/llvm/include/llvm/ADT/FunctionExtras.h new file mode 100644 index 000000000000..2b75dc6ac219 --- /dev/null +++ b/contrib/llvm/include/llvm/ADT/FunctionExtras.h @@ -0,0 +1,293 @@ +//===- FunctionExtras.h - Function type erasure utilities -------*- 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 collection of function (or more generally, callable) +/// type erasure utilities supplementing those provided by the standard library +/// in `<function>`. +/// +/// It provides `unique_function`, which works like `std::function` but supports +/// move-only callable objects. +/// +/// Future plans: +/// - Add a `function` that provides const, volatile, and ref-qualified support, +/// which doesn't work with `std::function`. +/// - Provide support for specifying multiple signatures to type erase callable +/// objects with an overload set, such as those produced by generic lambdas. +/// - Expand to include a copyable utility that directly replaces std::function +/// but brings the above improvements. +/// +/// Note that LLVM's utilities are greatly simplified by not supporting +/// allocators. +/// +/// If the standard library ever begins to provide comparable facilities we can +/// consider switching to those. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_FUNCTION_EXTRAS_H +#define LLVM_ADT_FUNCTION_EXTRAS_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/type_traits.h" +#include <memory> + +namespace llvm { + +template <typename FunctionT> class unique_function; + +template <typename ReturnT, typename... ParamTs> +class unique_function<ReturnT(ParamTs...)> { + static constexpr size_t InlineStorageSize = sizeof(void *) * 3; + + // MSVC has a bug and ICEs if we give it a particular dependent value + // expression as part of the `std::conditional` below. To work around this, + // we build that into a template struct's constexpr bool. + template <typename T> struct IsSizeLessThanThresholdT { + static constexpr bool value = sizeof(T) <= (2 * sizeof(void *)); + }; + + // Provide a type function to map parameters that won't observe extra copies + // or moves and which are small enough to likely pass in register to values + // and all other types to l-value reference types. We use this to compute the + // types used in our erased call utility to minimize copies and moves unless + // doing so would force things unnecessarily into memory. + // + // The heuristic used is related to common ABI register passing conventions. + // It doesn't have to be exact though, and in one way it is more strict + // because we want to still be able to observe either moves *or* copies. + template <typename T> + using AdjustedParamT = typename std::conditional< + !std::is_reference<T>::value && + llvm::is_trivially_copy_constructible<T>::value && + llvm::is_trivially_move_constructible<T>::value && + IsSizeLessThanThresholdT<T>::value, + T, T &>::type; + + // The type of the erased function pointer we use as a callback to dispatch to + // the stored callable when it is trivial to move and destroy. + using CallPtrT = ReturnT (*)(void *CallableAddr, + AdjustedParamT<ParamTs>... Params); + using MovePtrT = void (*)(void *LHSCallableAddr, void *RHSCallableAddr); + using DestroyPtrT = void (*)(void *CallableAddr); + + /// A struct to hold a single trivial callback with sufficient alignment for + /// our bitpacking. + struct alignas(8) TrivialCallback { + CallPtrT CallPtr; + }; + + /// A struct we use to aggregate three callbacks when we need full set of + /// operations. + struct alignas(8) NonTrivialCallbacks { + CallPtrT CallPtr; + MovePtrT MovePtr; + DestroyPtrT DestroyPtr; + }; + + // Create a pointer union between either a pointer to a static trivial call + // pointer in a struct or a pointer to a static struct of the call, move, and + // destroy pointers. + using CallbackPointerUnionT = + PointerUnion<TrivialCallback *, NonTrivialCallbacks *>; + + // The main storage buffer. This will either have a pointer to out-of-line + // storage or an inline buffer storing the callable. + union StorageUnionT { + // For out-of-line storage we keep a pointer to the underlying storage and + // the size. This is enough to deallocate the memory. + struct OutOfLineStorageT { + void *StoragePtr; + size_t Size; + size_t Alignment; + } OutOfLineStorage; + static_assert( + sizeof(OutOfLineStorageT) <= InlineStorageSize, + "Should always use all of the out-of-line storage for inline storage!"); + + // For in-line storage, we just provide an aligned character buffer. We + // provide three pointers worth of storage here. + typename std::aligned_storage<InlineStorageSize, alignof(void *)>::type + InlineStorage; + } StorageUnion; + + // A compressed pointer to either our dispatching callback or our table of + // dispatching callbacks and the flag for whether the callable itself is + // stored inline or not. + PointerIntPair<CallbackPointerUnionT, 1, bool> CallbackAndInlineFlag; + + bool isInlineStorage() const { return CallbackAndInlineFlag.getInt(); } + + bool isTrivialCallback() const { + return CallbackAndInlineFlag.getPointer().template is<TrivialCallback *>(); + } + + CallPtrT getTrivialCallback() const { + return CallbackAndInlineFlag.getPointer().template get<TrivialCallback *>()->CallPtr; + } + + NonTrivialCallbacks *getNonTrivialCallbacks() const { + return CallbackAndInlineFlag.getPointer() + .template get<NonTrivialCallbacks *>(); + } + + void *getInlineStorage() { return &StorageUnion.InlineStorage; } + + void *getOutOfLineStorage() { + return StorageUnion.OutOfLineStorage.StoragePtr; + } + size_t getOutOfLineStorageSize() const { + return StorageUnion.OutOfLineStorage.Size; + } + size_t getOutOfLineStorageAlignment() const { + return StorageUnion.OutOfLineStorage.Alignment; + } + + void setOutOfLineStorage(void *Ptr, size_t Size, size_t Alignment) { + StorageUnion.OutOfLineStorage = {Ptr, Size, Alignment}; + } + + template <typename CallableT> + static ReturnT CallImpl(void *CallableAddr, AdjustedParamT<ParamTs>... Params) { + return (*reinterpret_cast<CallableT *>(CallableAddr))( + std::forward<ParamTs>(Params)...); + } + + template <typename CallableT> + static void MoveImpl(void *LHSCallableAddr, void *RHSCallableAddr) noexcept { + new (LHSCallableAddr) + CallableT(std::move(*reinterpret_cast<CallableT *>(RHSCallableAddr))); + } + + template <typename CallableT> + static void DestroyImpl(void *CallableAddr) noexcept { + reinterpret_cast<CallableT *>(CallableAddr)->~CallableT(); + } + +public: + unique_function() = default; + unique_function(std::nullptr_t /*null_callable*/) {} + + ~unique_function() { + if (!CallbackAndInlineFlag.getPointer()) + return; + + // Cache this value so we don't re-check it after type-erased operations. + bool IsInlineStorage = isInlineStorage(); + + if (!isTrivialCallback()) + getNonTrivialCallbacks()->DestroyPtr( + IsInlineStorage ? getInlineStorage() : getOutOfLineStorage()); + + if (!IsInlineStorage) + deallocate_buffer(getOutOfLineStorage(), getOutOfLineStorageSize(), + getOutOfLineStorageAlignment()); + } + + unique_function(unique_function &&RHS) noexcept { + // Copy the callback and inline flag. + CallbackAndInlineFlag = RHS.CallbackAndInlineFlag; + + // If the RHS is empty, just copying the above is sufficient. + if (!RHS) + return; + + if (!isInlineStorage()) { + // The out-of-line case is easiest to move. + StorageUnion.OutOfLineStorage = RHS.StorageUnion.OutOfLineStorage; + } else if (isTrivialCallback()) { + // Move is trivial, just memcpy the bytes across. + memcpy(getInlineStorage(), RHS.getInlineStorage(), InlineStorageSize); + } else { + // Non-trivial move, so dispatch to a type-erased implementation. + getNonTrivialCallbacks()->MovePtr(getInlineStorage(), + RHS.getInlineStorage()); + } + + // Clear the old callback and inline flag to get back to as-if-null. + RHS.CallbackAndInlineFlag = {}; + +#ifndef NDEBUG + // In debug builds, we also scribble across the rest of the storage. + memset(RHS.getInlineStorage(), 0xAD, InlineStorageSize); +#endif + } + + unique_function &operator=(unique_function &&RHS) noexcept { + if (this == &RHS) + return *this; + + // Because we don't try to provide any exception safety guarantees we can + // implement move assignment very simply by first destroying the current + // object and then move-constructing over top of it. + this->~unique_function(); + new (this) unique_function(std::move(RHS)); + return *this; + } + + template <typename CallableT> unique_function(CallableT Callable) { + bool IsInlineStorage = true; + void *CallableAddr = getInlineStorage(); + if (sizeof(CallableT) > InlineStorageSize || + alignof(CallableT) > alignof(decltype(StorageUnion.InlineStorage))) { + IsInlineStorage = false; + // Allocate out-of-line storage. FIXME: Use an explicit alignment + // parameter in C++17 mode. + auto Size = sizeof(CallableT); + auto Alignment = alignof(CallableT); + CallableAddr = allocate_buffer(Size, Alignment); + setOutOfLineStorage(CallableAddr, Size, Alignment); + } + + // Now move into the storage. + new (CallableAddr) CallableT(std::move(Callable)); + + // See if we can create a trivial callback. We need the callable to be + // trivially moved and trivially destroyed so that we don't have to store + // type erased callbacks for those operations. + // + // FIXME: We should use constexpr if here and below to avoid instantiating + // the non-trivial static objects when unnecessary. While the linker should + // remove them, it is still wasteful. + if (llvm::is_trivially_move_constructible<CallableT>::value && + std::is_trivially_destructible<CallableT>::value) { + // We need to create a nicely aligned object. We use a static variable + // for this because it is a trivial struct. + static TrivialCallback Callback = { &CallImpl<CallableT> }; + + CallbackAndInlineFlag = {&Callback, IsInlineStorage}; + return; + } + + // Otherwise, we need to point at an object that contains all the different + // type erased behaviors needed. Create a static instance of the struct type + // here and then use a pointer to that. + static NonTrivialCallbacks Callbacks = { + &CallImpl<CallableT>, &MoveImpl<CallableT>, &DestroyImpl<CallableT>}; + + CallbackAndInlineFlag = {&Callbacks, IsInlineStorage}; + } + + ReturnT operator()(ParamTs... Params) { + void *CallableAddr = + isInlineStorage() ? getInlineStorage() : getOutOfLineStorage(); + + return (isTrivialCallback() + ? getTrivialCallback() + : getNonTrivialCallbacks()->CallPtr)(CallableAddr, Params...); + } + + explicit operator bool() const { + return (bool)CallbackAndInlineFlag.getPointer(); + } +}; + +} // end namespace llvm + +#endif // LLVM_ADT_FUNCTION_H diff --git a/contrib/llvm/include/llvm/ADT/GraphTraits.h b/contrib/llvm/include/llvm/ADT/GraphTraits.h index 225d9eb847f0..27c647f4bbbd 100644 --- a/contrib/llvm/include/llvm/ADT/GraphTraits.h +++ b/contrib/llvm/include/llvm/ADT/GraphTraits.h @@ -47,6 +47,19 @@ struct GraphTraits { // static nodes_iterator nodes_end (GraphType *G) // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + // typedef EdgeRef - Type of Edge token in the graph, which should + // be cheap to copy. + // typedef ChildEdgeIteratorType - Type used to iterate over children edges in + // graph, dereference to a EdgeRef. + + // static ChildEdgeIteratorType child_edge_begin(NodeRef) + // static ChildEdgeIteratorType child_edge_end(NodeRef) + // Return iterators that point to the beginning and ending of the + // edge list for the given callgraph node. + // + // static NodeRef edge_dest(EdgeRef) + // Return the destination node of an edge. + // static unsigned size (GraphType *G) // Return total number of nodes in the graph @@ -111,6 +124,13 @@ inverse_children(const typename GraphTraits<GraphType>::NodeRef &G) { GraphTraits<Inverse<GraphType>>::child_end(G)); } +template <class GraphType> +iterator_range<typename GraphTraits<GraphType>::ChildEdgeIteratorType> +children_edges(const typename GraphTraits<GraphType>::NodeRef &G) { + return make_range(GraphTraits<GraphType>::child_edge_begin(G), + GraphTraits<GraphType>::child_edge_end(G)); +} + } // end namespace llvm #endif // LLVM_ADT_GRAPHTRAITS_H diff --git a/contrib/llvm/include/llvm/ADT/Hashing.h b/contrib/llvm/include/llvm/ADT/Hashing.h index c3b574102f69..9f830baa4243 100644 --- a/contrib/llvm/include/llvm/ADT/Hashing.h +++ b/contrib/llvm/include/llvm/ADT/Hashing.h @@ -57,7 +57,7 @@ namespace llvm { -/// \brief An opaque object representing a hash code. +/// An opaque object representing a hash code. /// /// This object represents the result of hashing some entity. It is intended to /// be used to implement hashtables or other hashing-based data structures. @@ -73,14 +73,14 @@ class hash_code { size_t value; public: - /// \brief Default construct a hash_code. + /// Default construct a hash_code. /// Note that this leaves the value uninitialized. hash_code() = default; - /// \brief Form a hash code directly from a numerical value. + /// Form a hash code directly from a numerical value. hash_code(size_t value) : value(value) {} - /// \brief Convert the hash code to its numerical value for use. + /// Convert the hash code to its numerical value for use. /*explicit*/ operator size_t() const { return value; } friend bool operator==(const hash_code &lhs, const hash_code &rhs) { @@ -90,11 +90,11 @@ public: return lhs.value != rhs.value; } - /// \brief Allow a hash_code to be directly run through hash_value. + /// Allow a hash_code to be directly run through hash_value. friend size_t hash_value(const hash_code &code) { return code.value; } }; -/// \brief Compute a hash_code for any integer value. +/// Compute a hash_code for any integer value. /// /// Note that this function is intended to compute the same hash_code for /// a particular value without regard to the pre-promotion type. This is in @@ -105,21 +105,21 @@ template <typename T> 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. +/// Compute a hash_code for a pointer's address. /// /// N.B.: This hashes the *address*. Not the value and not the type. template <typename T> hash_code hash_value(const T *ptr); -/// \brief Compute a hash_code for a pair of objects. +/// Compute a hash_code for a pair of objects. template <typename T, typename U> hash_code hash_value(const std::pair<T, U> &arg); -/// \brief Compute a hash_code for a standard string. +/// Compute a hash_code for a standard string. template <typename T> hash_code hash_value(const std::basic_string<T> &arg); -/// \brief Override the execution seed with a fixed value. +/// Override the execution seed with a fixed value. /// /// This hashing library uses a per-execution seed designed to change on each /// run with high probability in order to ensure that the hash codes are not @@ -164,7 +164,7 @@ static const uint64_t k1 = 0xb492b66fbe98f273ULL; static const uint64_t k2 = 0x9ae16a3b2f90404fULL; static const uint64_t k3 = 0xc949d7c7509e6557ULL; -/// \brief Bitwise right rotate. +/// Bitwise right rotate. /// Normally this will compile to a single instruction, especially if the /// shift is a manifest constant. inline uint64_t rotate(uint64_t val, size_t shift) { @@ -254,13 +254,13 @@ inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) { return k2 ^ seed; } -/// \brief The intermediate state used during hashing. +/// The intermediate state used during hashing. /// Currently, the algorithm for computing hash codes is based on CityHash and /// keeps 56 bytes of arbitrary state. struct hash_state { uint64_t h0, h1, h2, h3, h4, h5, h6; - /// \brief Create a new hash_state structure and initialize it based on the + /// Create a new hash_state structure and initialize it based on the /// seed and the first 64-byte chunk. /// This effectively performs the initial mix. static hash_state create(const char *s, uint64_t seed) { @@ -272,7 +272,7 @@ struct hash_state { return state; } - /// \brief Mix 32-bytes from the input sequence into the 16-bytes of 'a' + /// Mix 32-bytes from the input sequence into the 16-bytes of 'a' /// and 'b', including whatever is already in 'a' and 'b'. static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) { a += fetch64(s); @@ -284,7 +284,7 @@ struct hash_state { a += c; } - /// \brief Mix in a 64-byte buffer of data. + /// Mix in a 64-byte buffer of data. /// We mix all 64 bytes even when the chunk length is smaller, but we /// record the actual length. void mix(const char *s) { @@ -302,7 +302,7 @@ struct hash_state { std::swap(h2, h0); } - /// \brief Compute the final 64-bit hash code value based on the current + /// Compute the final 64-bit hash code value based on the current /// state and the length of bytes hashed. uint64_t finalize(size_t length) { return hash_16_bytes(hash_16_bytes(h3, h5) + shift_mix(h1) * k1 + h2, @@ -311,7 +311,7 @@ struct hash_state { }; -/// \brief A global, fixed seed-override variable. +/// A global, fixed seed-override variable. /// /// This variable can be set using the \see llvm::set_fixed_execution_seed /// function. See that function for details. Do not, under any circumstances, @@ -332,7 +332,7 @@ inline size_t get_execution_seed() { } -/// \brief Trait to indicate whether a type's bits can be hashed directly. +/// Trait to indicate whether a type's bits can be hashed directly. /// /// A type trait which is true if we want to combine values for hashing by /// reading the underlying data. It is false if values of this type must @@ -359,14 +359,14 @@ template <typename T, typename U> struct is_hashable_data<std::pair<T, U> > (sizeof(T) + sizeof(U)) == sizeof(std::pair<T, U>))> {}; -/// \brief Helper to get the hashable data representation for a type. +/// 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 std::enable_if<is_hashable_data<T>::value, T>::type get_hashable_data(const T &value) { return value; } -/// \brief Helper to get the hashable data representation for a type. +/// Helper to get the hashable data representation for a type. /// This variant is enabled when we must first call hash_value and use the /// result as our data. template <typename T> @@ -376,7 +376,7 @@ get_hashable_data(const T &value) { return hash_value(value); } -/// \brief Helper to store data from a value into a buffer and advance the +/// Helper to store data from a value into a buffer and advance the /// pointer into that buffer. /// /// This routine first checks whether there is enough space in the provided @@ -395,7 +395,7 @@ bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value, return true; } -/// \brief Implement the combining of integral values into a hash_code. +/// Implement the combining of integral values into a hash_code. /// /// This overload is selected when the value type of the iterator is /// integral. Rather than computing a hash_code for each object and then @@ -435,7 +435,7 @@ hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) { return state.finalize(length); } -/// \brief Implement the combining of integral values into a hash_code. +/// Implement the combining of integral values into a hash_code. /// /// This overload is selected when the value type of the iterator is integral /// and when the input iterator is actually a pointer. Rather than computing @@ -470,7 +470,7 @@ hash_combine_range_impl(ValueT *first, ValueT *last) { } // namespace hashing -/// \brief Compute a hash_code for a sequence of values. +/// Compute a hash_code for a sequence of values. /// /// This hashes a sequence of values. It produces the same hash_code as /// 'hash_combine(a, b, c, ...)', but can run over arbitrary sized sequences @@ -486,7 +486,7 @@ hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) { namespace hashing { namespace detail { -/// \brief Helper class to manage the recursive combining of hash_combine +/// Helper class to manage the recursive combining of hash_combine /// arguments. /// /// This class exists to manage the state and various calls involved in the @@ -499,14 +499,14 @@ struct hash_combine_recursive_helper { const size_t seed; public: - /// \brief Construct a recursive hash combining helper. + /// Construct a recursive hash combining helper. /// /// This sets up the state for a recursive hash combine, including getting /// the seed and buffer setup. hash_combine_recursive_helper() : seed(get_execution_seed()) {} - /// \brief Combine one chunk of data into the current in-flight hash. + /// Combine one chunk of data into the current in-flight hash. /// /// This merges one chunk of data into the hash. First it tries to buffer /// the data. If the buffer is full, it hashes the buffer into its @@ -547,7 +547,7 @@ public: return buffer_ptr; } - /// \brief Recursive, variadic combining method. + /// Recursive, variadic combining method. /// /// This function recurses through each argument, combining that argument /// into a single hash. @@ -560,7 +560,7 @@ public: return combine(length, buffer_ptr, buffer_end, args...); } - /// \brief Base case for recursive, variadic combining. + /// Base case for recursive, variadic combining. /// /// The base case when combining arguments recursively is reached when all /// arguments have been handled. It flushes the remaining buffer and @@ -588,7 +588,7 @@ public: } // namespace detail } // namespace hashing -/// \brief Combine values into a single hash_code. +/// Combine values into a single hash_code. /// /// This routine accepts a varying number of arguments of any type. It will /// attempt to combine them into a single hash_code. For user-defined types it @@ -610,7 +610,7 @@ template <typename ...Ts> hash_code hash_combine(const Ts &...args) { namespace hashing { namespace detail { -/// \brief Helper to hash the value of a single integer. +/// Helper to hash the value of a single integer. /// /// Overloads for smaller integer types are not provided to ensure consistent /// behavior in the presence of integral promotions. Essentially, diff --git a/contrib/llvm/include/llvm/ADT/ImmutableList.h b/contrib/llvm/include/llvm/ADT/ImmutableList.h index 60d63e09d426..1f5e9813798d 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableList.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableList.h @@ -166,7 +166,7 @@ public: if (ownsAllocator()) delete &getAllocator(); } - ImmutableList<T> concat(const T& Head, ImmutableList<T> Tail) { + LLVM_NODISCARD ImmutableList<T> concat(const T &Head, ImmutableList<T> Tail) { // Profile the new list to see if it already exists in our cache. FoldingSetNodeID ID; void* InsertPos; @@ -188,7 +188,7 @@ public: return L; } - ImmutableList<T> add(const T& D, ImmutableList<T> L) { + LLVM_NODISCARD ImmutableList<T> add(const T& D, ImmutableList<T> L) { return concat(D, L); } diff --git a/contrib/llvm/include/llvm/ADT/ImmutableMap.h b/contrib/llvm/include/llvm/ADT/ImmutableMap.h index 10d1e1f0139b..cbc27ff17ccf 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableMap.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableMap.h @@ -114,12 +114,13 @@ public: ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); } - ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) { + LLVM_NODISCARD ImmutableMap add(ImmutableMap Old, key_type_ref K, + data_type_ref D) { TreeTy *T = F.add(Old.Root, std::pair<key_type,data_type>(K,D)); return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); } - ImmutableMap remove(ImmutableMap Old, key_type_ref K) { + LLVM_NODISCARD ImmutableMap remove(ImmutableMap Old, key_type_ref K) { TreeTy *T = F.remove(Old.Root,K); return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); } diff --git a/contrib/llvm/include/llvm/ADT/ImmutableSet.h b/contrib/llvm/include/llvm/ADT/ImmutableSet.h index 9d580c5a3d41..b1d5f4ac42e4 100644 --- a/contrib/llvm/include/llvm/ADT/ImmutableSet.h +++ b/contrib/llvm/include/llvm/ADT/ImmutableSet.h @@ -1017,7 +1017,7 @@ public: /// of this operation is logarithmic in the size of the original set. /// The memory allocated to represent the set is released when the /// factory object that created the set is destroyed. - ImmutableSet add(ImmutableSet Old, value_type_ref V) { + LLVM_NODISCARD ImmutableSet add(ImmutableSet Old, value_type_ref V) { TreeTy *NewT = F.add(Old.Root, V); return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT); } @@ -1029,7 +1029,7 @@ public: /// of this operation is logarithmic in the size of the original set. /// The memory allocated to represent the set is released when the /// factory object that created the set is destroyed. - ImmutableSet remove(ImmutableSet Old, value_type_ref V) { + LLVM_NODISCARD ImmutableSet remove(ImmutableSet Old, value_type_ref V) { TreeTy *NewT = F.remove(Old.Root, V); return ImmutableSet(Canonicalize ? F.getCanonicalTree(NewT) : NewT); } diff --git a/contrib/llvm/include/llvm/ADT/MapVector.h b/contrib/llvm/include/llvm/ADT/MapVector.h index 3d78f4b203c8..47b4987f210a 100644 --- a/contrib/llvm/include/llvm/ADT/MapVector.h +++ b/contrib/llvm/include/llvm/ADT/MapVector.h @@ -36,13 +36,17 @@ template<typename KeyT, typename ValueT, typename MapType = DenseMap<KeyT, unsigned>, typename VectorType = std::vector<std::pair<KeyT, ValueT>>> class MapVector { - using value_type = typename VectorType::value_type; - using size_type = typename VectorType::size_type; - MapType Map; VectorType Vector; + static_assert( + std::is_integral<typename MapType::mapped_type>::value, + "The mapped_type of the specified Map must be an integral type"); + public: + using value_type = typename VectorType::value_type; + using size_type = typename VectorType::size_type; + using iterator = typename VectorType::iterator; using const_iterator = typename VectorType::const_iterator; using reverse_iterator = typename VectorType::reverse_iterator; @@ -93,9 +97,9 @@ public: } ValueT &operator[](const KeyT &Key) { - std::pair<KeyT, unsigned> Pair = std::make_pair(Key, 0); + std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(Key, 0); std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair); - unsigned &I = Result.first->second; + auto &I = Result.first->second; if (Result.second) { Vector.push_back(std::make_pair(Key, ValueT())); I = Vector.size() - 1; @@ -112,9 +116,9 @@ public: } std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { - std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0); + std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0); std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair); - unsigned &I = Result.first->second; + auto &I = Result.first->second; if (Result.second) { Vector.push_back(std::make_pair(KV.first, KV.second)); I = Vector.size() - 1; @@ -125,9 +129,9 @@ public: std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { // Copy KV.first into the map, then move it into the vector. - std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0); + std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0); std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair); - unsigned &I = Result.first->second; + auto &I = Result.first->second; if (Result.second) { Vector.push_back(std::move(KV)); I = Vector.size() - 1; @@ -153,14 +157,14 @@ public: (Vector.begin() + Pos->second); } - /// \brief Remove the last element from the vector. + /// Remove the last element from the vector. void pop_back() { typename MapType::iterator Pos = Map.find(Vector.back().first); Map.erase(Pos); Vector.pop_back(); } - /// \brief Remove the element given by Iterator. + /// Remove the element given by Iterator. /// /// Returns an iterator to the element following the one which was removed, /// which may be end(). @@ -183,7 +187,7 @@ public: return Next; } - /// \brief Remove all elements with the key value Key. + /// Remove all elements with the key value Key. /// /// Returns the number of elements removed. size_type erase(const KeyT &Key) { @@ -194,7 +198,7 @@ public: return 1; } - /// \brief Remove the elements that match the predicate. + /// Remove the elements that match the predicate. /// /// Erase all elements that match \c Pred in a single pass. Takes linear /// time. @@ -223,7 +227,7 @@ void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) { Vector.erase(O, Vector.end()); } -/// \brief A MapVector that performs no allocations if smaller than a certain +/// A MapVector that performs no allocations if smaller than a certain /// size. template <typename KeyT, typename ValueT, unsigned N> struct SmallMapVector diff --git a/contrib/llvm/include/llvm/ADT/None.h b/contrib/llvm/include/llvm/ADT/None.h index c7a99c61994e..4b6bc1e005b5 100644 --- a/contrib/llvm/include/llvm/ADT/None.h +++ b/contrib/llvm/include/llvm/ADT/None.h @@ -17,7 +17,7 @@ #define LLVM_ADT_NONE_H namespace llvm { -/// \brief A simple null object to allow implicit construction of Optional<T> +/// A simple null object to allow implicit construction of Optional<T> /// and similar types without having to spell out the specialization's name. // (constant value 1 in an attempt to workaround MSVC build issue... ) enum class NoneType { None = 1 }; diff --git a/contrib/llvm/include/llvm/ADT/Optional.h b/contrib/llvm/include/llvm/ADT/Optional.h index 2811d5c1e21b..353e5d0ec9df 100644 --- a/contrib/llvm/include/llvm/ADT/Optional.h +++ b/contrib/llvm/include/llvm/ADT/Optional.h @@ -27,124 +27,164 @@ namespace llvm { -template <typename T> class Optional { +namespace optional_detail { +/// Storage for any type. +template <typename T, bool IsPodLike> struct OptionalStorage { AlignedCharArrayUnion<T> storage; bool hasVal = false; -public: - using value_type = T; - - Optional(NoneType) {} - explicit Optional() {} - - Optional(const T &y) : hasVal(true) { new (storage.buffer) T(y); } + OptionalStorage() = default; - Optional(const Optional &O) : hasVal(O.hasVal) { + OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); } + OptionalStorage(const OptionalStorage &O) : hasVal(O.hasVal) { if (hasVal) - new (storage.buffer) T(*O); + new (storage.buffer) T(*O.getPointer()); } - - Optional(T &&y) : hasVal(true) { new (storage.buffer) T(std::forward<T>(y)); } - - Optional(Optional<T> &&O) : hasVal(O) { - if (O) { - new (storage.buffer) T(std::move(*O)); - O.reset(); + OptionalStorage(T &&y) : hasVal(true) { + new (storage.buffer) T(std::forward<T>(y)); + } + OptionalStorage(OptionalStorage &&O) : hasVal(O.hasVal) { + if (O.hasVal) { + new (storage.buffer) T(std::move(*O.getPointer())); } } - ~Optional() { reset(); } - - Optional &operator=(T &&y) { + OptionalStorage &operator=(T &&y) { if (hasVal) - **this = std::move(y); + *getPointer() = std::move(y); else { new (storage.buffer) T(std::move(y)); hasVal = true; } return *this; } - - Optional &operator=(Optional &&O) { - if (!O) + OptionalStorage &operator=(OptionalStorage &&O) { + if (!O.hasVal) reset(); else { - *this = std::move(*O); - O.reset(); + *this = std::move(*O.getPointer()); } return *this; } - /// Create a new object by constructing it in place with the given arguments. - template <typename... ArgTypes> void emplace(ArgTypes &&... Args) { - reset(); - hasVal = true; - new (storage.buffer) T(std::forward<ArgTypes>(Args)...); - } - - static inline Optional create(const T *y) { - return y ? Optional(*y) : Optional(); - } - // FIXME: these assignments (& the equivalent const T&/const Optional& ctors) // could be made more efficient by passing by value, possibly unifying them // with the rvalue versions above - but this could place a different set of // requirements (notably: the existence of a default ctor) when implemented // in that way. Careful SFINAE to avoid such pitfalls would be required. - Optional &operator=(const T &y) { + OptionalStorage &operator=(const T &y) { if (hasVal) - **this = y; + *getPointer() = y; else { new (storage.buffer) T(y); hasVal = true; } return *this; } - - Optional &operator=(const Optional &O) { - if (!O) + OptionalStorage &operator=(const OptionalStorage &O) { + if (!O.hasVal) reset(); else - *this = *O; + *this = *O.getPointer(); return *this; } + ~OptionalStorage() { reset(); } + void reset() { if (hasVal) { - (**this).~T(); + (*getPointer()).~T(); hasVal = false; } } - const T *getPointer() const { - assert(hasVal); - return reinterpret_cast<const T *>(storage.buffer); - } T *getPointer() { assert(hasVal); return reinterpret_cast<T *>(storage.buffer); } - const T &getValue() const LLVM_LVALUE_FUNCTION { + const T *getPointer() const { assert(hasVal); - return *getPointer(); + return reinterpret_cast<const T *>(storage.buffer); } - T &getValue() LLVM_LVALUE_FUNCTION { - assert(hasVal); - return *getPointer(); +}; + +#if !defined(__GNUC__) || defined(__clang__) // GCC up to GCC7 miscompiles this. +/// Storage for trivially copyable types only. +template <typename T> struct OptionalStorage<T, true> { + AlignedCharArrayUnion<T> storage; + bool hasVal = false; + + OptionalStorage() = default; + + OptionalStorage(const T &y) : hasVal(true) { new (storage.buffer) T(y); } + OptionalStorage &operator=(const T &y) { + *reinterpret_cast<T *>(storage.buffer) = y; + hasVal = true; + return *this; } - explicit operator bool() const { return hasVal; } - bool hasValue() const { return hasVal; } - const T *operator->() const { return getPointer(); } - T *operator->() { return getPointer(); } - const T &operator*() const LLVM_LVALUE_FUNCTION { - assert(hasVal); - return *getPointer(); + void reset() { hasVal = false; } +}; +#endif +} // namespace optional_detail + +template <typename T> class Optional { + optional_detail::OptionalStorage<T, isPodLike<T>::value> Storage; + +public: + using value_type = T; + + constexpr Optional() {} + constexpr Optional(NoneType) {} + + Optional(const T &y) : Storage(y) {} + Optional(const Optional &O) = default; + + Optional(T &&y) : Storage(std::forward<T>(y)) {} + Optional(Optional &&O) = default; + + Optional &operator=(T &&y) { + Storage = std::move(y); + return *this; } - T &operator*() LLVM_LVALUE_FUNCTION { - assert(hasVal); - return *getPointer(); + Optional &operator=(Optional &&O) = default; + + /// Create a new object by constructing it in place with the given arguments. + template <typename... ArgTypes> void emplace(ArgTypes &&... Args) { + reset(); + Storage.hasVal = true; + new (getPointer()) T(std::forward<ArgTypes>(Args)...); + } + + static inline Optional create(const T *y) { + return y ? Optional(*y) : Optional(); + } + + Optional &operator=(const T &y) { + Storage = y; + return *this; + } + Optional &operator=(const Optional &O) = default; + + void reset() { Storage.reset(); } + + const T *getPointer() const { + assert(Storage.hasVal); + return reinterpret_cast<const T *>(Storage.storage.buffer); + } + T *getPointer() { + assert(Storage.hasVal); + return reinterpret_cast<T *>(Storage.storage.buffer); } + const T &getValue() const LLVM_LVALUE_FUNCTION { return *getPointer(); } + T &getValue() LLVM_LVALUE_FUNCTION { return *getPointer(); } + + explicit operator bool() const { return Storage.hasVal; } + bool hasValue() const { return Storage.hasVal; } + const T *operator->() const { return getPointer(); } + T *operator->() { return getPointer(); } + const T &operator*() const LLVM_LVALUE_FUNCTION { return *getPointer(); } + T &operator*() LLVM_LVALUE_FUNCTION { return *getPointer(); } template <typename U> constexpr T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { @@ -152,14 +192,8 @@ public: } #if LLVM_HAS_RVALUE_REFERENCE_THIS - T &&getValue() && { - assert(hasVal); - return std::move(*getPointer()); - } - T &&operator*() && { - assert(hasVal); - return std::move(*getPointer()); - } + T &&getValue() && { return std::move(*getPointer()); } + T &&operator*() && { return std::move(*getPointer()); } template <typename U> T getValueOr(U &&value) && { diff --git a/contrib/llvm/include/llvm/ADT/PackedVector.h b/contrib/llvm/include/llvm/ADT/PackedVector.h index 95adc2926813..3d53c49536d0 100644 --- a/contrib/llvm/include/llvm/ADT/PackedVector.h +++ b/contrib/llvm/include/llvm/ADT/PackedVector.h @@ -65,7 +65,7 @@ protected: } }; -/// \brief Store a vector of values using a specific number of bits for each +/// Store a vector of values using a specific number of bits for each /// value. Both signed and unsigned types can be used, e.g /// @code /// PackedVector<signed, 2> vec; diff --git a/contrib/llvm/include/llvm/ADT/PointerUnion.h b/contrib/llvm/include/llvm/ADT/PointerUnion.h index 4276859e9254..315e58336cba 100644 --- a/contrib/llvm/include/llvm/ADT/PointerUnion.h +++ b/contrib/llvm/include/llvm/ADT/PointerUnion.h @@ -346,6 +346,12 @@ struct PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3>> { }; }; +template <typename PT1, typename PT2, typename PT3> +bool operator<(PointerUnion3<PT1, PT2, PT3> lhs, + PointerUnion3<PT1, PT2, PT3> rhs) { + return lhs.getOpaqueValue() < rhs.getOpaqueValue(); +} + /// A pointer union of four pointer types. See documentation for PointerUnion /// for usage. template <typename PT1, typename PT2, typename PT3, typename PT4> diff --git a/contrib/llvm/include/llvm/ADT/SCCIterator.h b/contrib/llvm/include/llvm/ADT/SCCIterator.h index 784a58dc002f..ab1dc4613be0 100644 --- a/contrib/llvm/include/llvm/ADT/SCCIterator.h +++ b/contrib/llvm/include/llvm/ADT/SCCIterator.h @@ -33,7 +33,7 @@ namespace llvm { -/// \brief Enumerate the SCCs of a directed graph in reverse topological order +/// Enumerate the SCCs of a directed graph in reverse topological order /// of the SCC DAG. /// /// This is implemented using Tarjan's DFS algorithm using an internal stack to @@ -104,7 +104,7 @@ public: } static scc_iterator end(const GraphT &) { return scc_iterator(); } - /// \brief Direct loop termination test which is more efficient than + /// Direct loop termination test which is more efficient than /// comparison with \c end(). bool isAtEnd() const { assert(!CurrentSCC.empty() || VisitStack.empty()); @@ -125,7 +125,7 @@ public: return CurrentSCC; } - /// \brief Test if the current SCC has a loop. + /// 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. @@ -222,12 +222,12 @@ bool scc_iterator<GraphT, GT>::hasLoop() const { return false; } -/// \brief Construct the begin iterator for a deduced graph type T. +/// 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); } -/// \brief Construct the end iterator for a deduced graph type T. +/// 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); } diff --git a/contrib/llvm/include/llvm/ADT/STLExtras.h b/contrib/llvm/include/llvm/ADT/STLExtras.h index bcd992b4a716..94365dd9ced1 100644 --- a/contrib/llvm/include/llvm/ADT/STLExtras.h +++ b/contrib/llvm/include/llvm/ADT/STLExtras.h @@ -36,6 +36,10 @@ #include <type_traits> #include <utility> +#ifdef EXPENSIVE_CHECKS +#include <random> // for std::mt19937 +#endif + namespace llvm { // Only used by compiler if both template types are the same. Useful when @@ -54,6 +58,19 @@ using ValueOfRange = typename std::remove_reference<decltype( } // end namespace detail //===----------------------------------------------------------------------===// +// Extra additions to <type_traits> +//===----------------------------------------------------------------------===// + +template <typename T> +struct negation : std::integral_constant<bool, !bool(T::value)> {}; + +template <typename...> struct conjunction : std::true_type {}; +template <typename B1> struct conjunction<B1> : B1 {}; +template <typename B1, typename... Bn> +struct conjunction<B1, Bn...> + : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {}; + +//===----------------------------------------------------------------------===// // Extra additions to <functional> //===----------------------------------------------------------------------===// @@ -101,6 +118,7 @@ class function_ref<Ret(Params...)> { public: function_ref() = default; + function_ref(std::nullptr_t) {} template <typename Callable> function_ref(Callable &&callable, @@ -266,60 +284,121 @@ auto reverse( /// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; }); /// // R contains { 1, 3 }. /// \endcode -template <typename WrappedIteratorT, typename PredicateT> -class filter_iterator +/// +/// Note: filter_iterator_base implements support for forward iteration. +/// filter_iterator_impl exists to provide support for bidirectional iteration, +/// conditional on whether the wrapped iterator supports it. +template <typename WrappedIteratorT, typename PredicateT, typename IterTag> +class filter_iterator_base : public iterator_adaptor_base< - filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT, + filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>, + WrappedIteratorT, typename std::common_type< - std::forward_iterator_tag, - typename std::iterator_traits< - WrappedIteratorT>::iterator_category>::type> { + IterTag, typename std::iterator_traits< + WrappedIteratorT>::iterator_category>::type> { using BaseT = iterator_adaptor_base< - filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT, + filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>, + WrappedIteratorT, typename std::common_type< - std::forward_iterator_tag, - typename std::iterator_traits<WrappedIteratorT>::iterator_category>:: - type>; + IterTag, typename std::iterator_traits< + WrappedIteratorT>::iterator_category>::type>; - struct PayloadType { - WrappedIteratorT End; - PredicateT Pred; - }; - - Optional<PayloadType> Payload; +protected: + WrappedIteratorT End; + PredicateT Pred; void findNextValid() { - assert(Payload && "Payload should be engaged when findNextValid is called"); - while (this->I != Payload->End && !Payload->Pred(*this->I)) + while (this->I != End && !Pred(*this->I)) BaseT::operator++(); } - // Construct the begin iterator. The begin iterator requires to know where end - // is, so that it can properly stop when it hits end. - filter_iterator(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred) - : BaseT(std::move(Begin)), - Payload(PayloadType{std::move(End), std::move(Pred)}) { + // Construct the iterator. The begin iterator needs to know where the end + // is, so that it can properly stop when it gets there. The end iterator only + // needs the predicate to support bidirectional iteration. + filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End, + PredicateT Pred) + : BaseT(Begin), End(End), Pred(Pred) { findNextValid(); } - // Construct the end iterator. It's not incrementable, so Payload doesn't - // have to be engaged. - filter_iterator(WrappedIteratorT End) : BaseT(End) {} - public: using BaseT::operator++; - filter_iterator &operator++() { + filter_iterator_base &operator++() { BaseT::operator++(); findNextValid(); return *this; } +}; + +/// Specialization of filter_iterator_base for forward iteration only. +template <typename WrappedIteratorT, typename PredicateT, + typename IterTag = std::forward_iterator_tag> +class filter_iterator_impl + : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> { + using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>; + +public: + filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, + PredicateT Pred) + : BaseT(Begin, End, Pred) {} +}; + +/// Specialization of filter_iterator_base for bidirectional iteration. +template <typename WrappedIteratorT, typename PredicateT> +class filter_iterator_impl<WrappedIteratorT, PredicateT, + std::bidirectional_iterator_tag> + : public filter_iterator_base<WrappedIteratorT, PredicateT, + std::bidirectional_iterator_tag> { + using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, + std::bidirectional_iterator_tag>; + void findPrevValid() { + while (!this->Pred(*this->I)) + BaseT::operator--(); + } + +public: + using BaseT::operator--; + + filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, + PredicateT Pred) + : BaseT(Begin, End, Pred) {} + + filter_iterator_impl &operator--() { + BaseT::operator--(); + findPrevValid(); + return *this; + } +}; + +namespace detail { - template <typename RT, typename PT> - friend iterator_range<filter_iterator<detail::IterOfRange<RT>, PT>> - make_filter_range(RT &&, PT); +template <bool is_bidirectional> struct fwd_or_bidi_tag_impl { + using type = std::forward_iterator_tag; }; +template <> struct fwd_or_bidi_tag_impl<true> { + using type = std::bidirectional_iterator_tag; +}; + +/// Helper which sets its type member to forward_iterator_tag if the category +/// of \p IterT does not derive from bidirectional_iterator_tag, and to +/// bidirectional_iterator_tag otherwise. +template <typename IterT> struct fwd_or_bidi_tag { + using type = typename fwd_or_bidi_tag_impl<std::is_base_of< + std::bidirectional_iterator_tag, + typename std::iterator_traits<IterT>::iterator_category>::value>::type; +}; + +} // namespace detail + +/// Defines filter_iterator to a suitable specialization of +/// filter_iterator_impl, based on the underlying iterator's category. +template <typename WrappedIteratorT, typename PredicateT> +using filter_iterator = filter_iterator_impl< + WrappedIteratorT, PredicateT, + typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>; + /// Convenience function that takes a range of elements and a predicate, /// and return a new filter_iterator range. /// @@ -332,10 +411,11 @@ iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>> make_filter_range(RangeT &&Range, PredicateT Pred) { using FilterIteratorT = filter_iterator<detail::IterOfRange<RangeT>, PredicateT>; - return make_range(FilterIteratorT(std::begin(std::forward<RangeT>(Range)), - std::end(std::forward<RangeT>(Range)), - std::move(Pred)), - FilterIteratorT(std::end(std::forward<RangeT>(Range)))); + return make_range( + FilterIteratorT(std::begin(std::forward<RangeT>(Range)), + std::end(std::forward<RangeT>(Range)), Pred), + FilterIteratorT(std::end(std::forward<RangeT>(Range)), + std::end(std::forward<RangeT>(Range)), Pred)); } // forward declarations required by zip_shortest/zip_first @@ -644,7 +724,7 @@ detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) { // Extra additions to <utility> //===----------------------------------------------------------------------===// -/// \brief Function object to check whether the first component of a std::pair +/// 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 { template <typename T> bool operator()(const T &lhs, const T &rhs) const { @@ -652,7 +732,7 @@ struct less_first { } }; -/// \brief Function object to check whether the second component of a std::pair +/// Function object to check whether the second component of a std::pair /// compares less than the second component of another std::pair. struct less_second { template <typename T> bool operator()(const T &lhs, const T &rhs) const { @@ -662,14 +742,14 @@ struct less_second { // A subset of N3658. More stuff can be added as-needed. -/// \brief Represents a compile-time sequence of integers. +/// Represents a compile-time sequence of integers. template <class T, T... I> struct integer_sequence { using value_type = T; static constexpr size_t size() { return sizeof...(I); } }; -/// \brief Alias for the common case of a sequence of size_ts. +/// Alias for the common case of a sequence of size_ts. template <size_t... I> struct index_sequence : integer_sequence<std::size_t, I...> {}; @@ -678,7 +758,7 @@ struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {}; template <std::size_t... I> struct build_index_impl<0, I...> : index_sequence<I...> {}; -/// \brief Creates a compile-time integer sequence for a parameter pack. +/// Creates a compile-time integer sequence for a parameter pack. template <class... Ts> struct index_sequence_for : build_index_impl<sizeof...(Ts)> {}; @@ -687,7 +767,7 @@ struct index_sequence_for : build_index_impl<sizeof...(Ts)> {}; template <int N> struct rank : rank<N - 1> {}; template <> struct rank<0> {}; -/// \brief traits class for checking whether type T is one of any of the given +/// traits class for checking whether type T is one of any of the given /// types in the variadic list. template <typename T, typename... Ts> struct is_one_of { static const bool value = false; @@ -699,7 +779,7 @@ struct is_one_of<T, U, Ts...> { std::is_same<T, U>::value || is_one_of<T, Ts...>::value; }; -/// \brief traits class for checking whether type T is a base class for all +/// traits class for checking whether type T is a base class for all /// the given types in the variadic list. template <typename T, typename... Ts> struct are_base_of { static const bool value = true; @@ -761,6 +841,10 @@ inline void array_pod_sort(IteratorTy Start, IteratorTy End) { // behavior with an empty sequence. auto NElts = End - Start; if (NElts <= 1) return; +#ifdef EXPENSIVE_CHECKS + std::mt19937 Generator(std::random_device{}()); + std::shuffle(Start, End, Generator); +#endif qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); } @@ -774,10 +858,34 @@ inline void array_pod_sort( // behavior with an empty sequence. auto NElts = End - Start; if (NElts <= 1) return; +#ifdef EXPENSIVE_CHECKS + std::mt19937 Generator(std::random_device{}()); + std::shuffle(Start, End, Generator); +#endif qsort(&*Start, NElts, sizeof(*Start), reinterpret_cast<int (*)(const void *, const void *)>(Compare)); } +// Provide wrappers to std::sort which shuffle the elements before sorting +// to help uncover non-deterministic behavior (PR35135). +template <typename IteratorTy> +inline void sort(IteratorTy Start, IteratorTy End) { +#ifdef EXPENSIVE_CHECKS + std::mt19937 Generator(std::random_device{}()); + std::shuffle(Start, End, Generator); +#endif + std::sort(Start, End); +} + +template <typename IteratorTy, typename Compare> +inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) { +#ifdef EXPENSIVE_CHECKS + std::mt19937 Generator(std::random_device{}()); + std::shuffle(Start, End, Generator); +#endif + std::sort(Start, End, Comp); +} + //===----------------------------------------------------------------------===// // Extra additions to <algorithm> //===----------------------------------------------------------------------===// @@ -861,6 +969,11 @@ OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) { return std::copy_if(adl_begin(Range), adl_end(Range), Out, P); } +template <typename R, typename OutputIt> +OutputIt copy(R &&Range, OutputIt Out) { + return std::copy(adl_begin(Range), adl_end(Range), Out); +} + /// Wrapper function around std::find to detect if an element exists /// in a container. template <typename R, typename E> @@ -905,7 +1018,7 @@ auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { return std::lower_bound(adl_begin(Range), adl_end(Range), I); } -/// \brief Given a range of type R, iterate the entire range and return a +/// Given a range of type R, iterate the entire range and return a /// SmallVector with elements of the vector. This is useful, for example, /// when you want to iterate a range and then sort the results. template <unsigned Size, typename R> @@ -926,13 +1039,25 @@ void erase_if(Container &C, UnaryPredicate P) { C.erase(remove_if(C, P), C.end()); } +/// Get the size of a range. This is a wrapper function around std::distance +/// which is only enabled when the operation is O(1). +template <typename R> +auto size(R &&Range, typename std::enable_if< + std::is_same<typename std::iterator_traits<decltype( + Range.begin())>::iterator_category, + std::random_access_iterator_tag>::value, + void>::type * = nullptr) + -> decltype(std::distance(Range.begin(), Range.end())) { + return std::distance(Range.begin(), Range.end()); +} + //===----------------------------------------------------------------------===// // Extra additions to <memory> //===----------------------------------------------------------------------===// // Implement make_unique according to N3656. -/// \brief Constructs a `new T()` with the given args and returns a +/// Constructs a `new T()` with the given args and returns a /// `unique_ptr<T>` which owns the object. /// /// Example: @@ -945,7 +1070,7 @@ 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 +/// 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. diff --git a/contrib/llvm/include/llvm/ADT/ScopeExit.h b/contrib/llvm/include/llvm/ADT/ScopeExit.h index 4e64352c77df..bd13755fa999 100644 --- a/contrib/llvm/include/llvm/ADT/ScopeExit.h +++ b/contrib/llvm/include/llvm/ADT/ScopeExit.h @@ -25,14 +25,26 @@ namespace detail { template <typename Callable> class scope_exit { Callable ExitFunction; + bool Engaged = true; // False once moved-from or release()d. public: template <typename Fp> explicit scope_exit(Fp &&F) : ExitFunction(std::forward<Fp>(F)) {} - scope_exit(scope_exit &&Rhs) : ExitFunction(std::move(Rhs.ExitFunction)) {} + scope_exit(scope_exit &&Rhs) + : ExitFunction(std::move(Rhs.ExitFunction)), Engaged(Rhs.Engaged) { + Rhs.release(); + } + scope_exit(const scope_exit &) = delete; + scope_exit &operator=(scope_exit &&) = delete; + scope_exit &operator=(const scope_exit &) = delete; - ~scope_exit() { ExitFunction(); } + void release() { Engaged = false; } + + ~scope_exit() { + if (Engaged) + ExitFunction(); + } }; } // end namespace detail diff --git a/contrib/llvm/include/llvm/ADT/SetVector.h b/contrib/llvm/include/llvm/ADT/SetVector.h index 04ed52fc543f..3d6781041320 100644 --- a/contrib/llvm/include/llvm/ADT/SetVector.h +++ b/contrib/llvm/include/llvm/ADT/SetVector.h @@ -31,7 +31,7 @@ namespace llvm { -/// \brief A vector that has set insertion semantics. +/// A vector that has set insertion semantics. /// /// This adapter class provides a way to keep a set of things that also has the /// property of a deterministic iteration order. The order of iteration is the @@ -52,10 +52,10 @@ public: using const_reverse_iterator = typename vector_type::const_reverse_iterator; using size_type = typename vector_type::size_type; - /// \brief Construct an empty SetVector + /// Construct an empty SetVector SetVector() = default; - /// \brief Initialize a SetVector with a range of elements + /// Initialize a SetVector with a range of elements template<typename It> SetVector(It Start, It End) { insert(Start, End); @@ -69,75 +69,75 @@ public: return std::move(vector_); } - /// \brief Determine if the SetVector is empty or not. + /// Determine if the SetVector is empty or not. bool empty() const { return vector_.empty(); } - /// \brief Determine the number of elements in the SetVector. + /// Determine the number of elements in the SetVector. size_type size() const { return vector_.size(); } - /// \brief Get an iterator to the beginning of the SetVector. + /// Get an iterator to the beginning of the SetVector. iterator begin() { return vector_.begin(); } - /// \brief Get a const_iterator to the beginning of the SetVector. + /// Get a const_iterator to the beginning of the SetVector. const_iterator begin() const { return vector_.begin(); } - /// \brief Get an iterator to the end of the SetVector. + /// Get an iterator to the end of the SetVector. iterator end() { return vector_.end(); } - /// \brief Get a const_iterator to the end of the SetVector. + /// Get a const_iterator to the end of the SetVector. const_iterator end() const { return vector_.end(); } - /// \brief Get an reverse_iterator to the end of the SetVector. + /// Get an reverse_iterator to the end of the SetVector. reverse_iterator rbegin() { return vector_.rbegin(); } - /// \brief Get a const_reverse_iterator to the end of the SetVector. + /// Get a const_reverse_iterator to the end of the SetVector. const_reverse_iterator rbegin() const { return vector_.rbegin(); } - /// \brief Get a reverse_iterator to the beginning of the SetVector. + /// Get a reverse_iterator to the beginning of the SetVector. reverse_iterator rend() { return vector_.rend(); } - /// \brief Get a const_reverse_iterator to the beginning of the SetVector. + /// Get a const_reverse_iterator to the beginning of the SetVector. const_reverse_iterator rend() const { return vector_.rend(); } - /// \brief Return the first element of the SetVector. + /// Return the first element of the SetVector. const T &front() const { assert(!empty() && "Cannot call front() on empty SetVector!"); return vector_.front(); } - /// \brief Return the last element of the SetVector. + /// Return the last element of the SetVector. const T &back() const { assert(!empty() && "Cannot call back() on empty SetVector!"); return vector_.back(); } - /// \brief Index into the SetVector. + /// Index into the SetVector. const_reference operator[](size_type n) const { assert(n < vector_.size() && "SetVector access out of range!"); return vector_[n]; } - /// \brief Insert a new element into the SetVector. + /// Insert a new element into the SetVector. /// \returns true if the element was inserted into the SetVector. bool insert(const value_type &X) { bool result = set_.insert(X).second; @@ -146,7 +146,7 @@ public: return result; } - /// \brief Insert a range of elements into the SetVector. + /// Insert a range of elements into the SetVector. template<typename It> void insert(It Start, It End) { for (; Start != End; ++Start) @@ -154,7 +154,7 @@ public: vector_.push_back(*Start); } - /// \brief Remove an item from the set vector. + /// Remove an item from the set vector. bool remove(const value_type& X) { if (set_.erase(X)) { typename vector_type::iterator I = find(vector_, X); @@ -183,7 +183,7 @@ public: return vector_.erase(NI); } - /// \brief Remove items from the set vector based on a predicate function. + /// Remove items from the set vector based on a predicate function. /// /// This is intended to be equivalent to the following code, if we could /// write it: @@ -206,19 +206,19 @@ public: return true; } - /// \brief Count the number of elements of a given key in the SetVector. + /// Count the number of elements of a given key in the SetVector. /// \returns 0 if the element is not in the SetVector, 1 if it is. size_type count(const key_type &key) const { return set_.count(key); } - /// \brief Completely clear the SetVector + /// Completely clear the SetVector void clear() { set_.clear(); vector_.clear(); } - /// \brief Remove the last element of the SetVector. + /// Remove the last element of the SetVector. void pop_back() { assert(!empty() && "Cannot remove an element from an empty SetVector!"); set_.erase(back()); @@ -239,7 +239,7 @@ public: return vector_ != that.vector_; } - /// \brief Compute This := This u S, return whether 'This' changed. + /// Compute This := This u S, return whether 'This' changed. /// TODO: We should be able to use set_union from SetOperations.h, but /// SetVector interface is inconsistent with DenseSet. template <class STy> @@ -254,7 +254,7 @@ public: return Changed; } - /// \brief Compute This := This - B + /// Compute This := This - B /// TODO: We should be able to use set_subtract from SetOperations.h, but /// SetVector interface is inconsistent with DenseSet. template <class STy> @@ -265,7 +265,7 @@ public: } private: - /// \brief A wrapper predicate designed for use with std::remove_if. + /// A wrapper predicate designed for use with std::remove_if. /// /// This predicate wraps a predicate suitable for use with std::remove_if to /// call set_.erase(x) on each element which is slated for removal. @@ -292,7 +292,7 @@ private: vector_type vector_; ///< The vector. }; -/// \brief A SetVector that performs no allocations if smaller than +/// A SetVector that performs no allocations if smaller than /// a certain size. template <typename T, unsigned N> class SmallSetVector @@ -300,7 +300,7 @@ class SmallSetVector public: SmallSetVector() = default; - /// \brief Initialize a SmallSetVector with a range of elements + /// Initialize a SmallSetVector with a range of elements template<typename It> SmallSetVector(It Start, It End) { this->insert(Start, End); diff --git a/contrib/llvm/include/llvm/ADT/SmallPtrSet.h b/contrib/llvm/include/llvm/ADT/SmallPtrSet.h index 78ea613af693..db08e40257ba 100644 --- a/contrib/llvm/include/llvm/ADT/SmallPtrSet.h +++ b/contrib/llvm/include/llvm/ADT/SmallPtrSet.h @@ -335,7 +335,7 @@ struct RoundUpToPowerOfTwo { enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val }; }; -/// \brief A templated base class for \c SmallPtrSet which provides the +/// 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 diff --git a/contrib/llvm/include/llvm/ADT/SmallSet.h b/contrib/llvm/include/llvm/ADT/SmallSet.h index d52d0f07f9a6..5d84627714bc 100644 --- a/contrib/llvm/include/llvm/ADT/SmallSet.h +++ b/contrib/llvm/include/llvm/ADT/SmallSet.h @@ -17,21 +17,120 @@ #include "llvm/ADT/None.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/type_traits.h" #include <cstddef> #include <functional> #include <set> +#include <type_traits> #include <utility> namespace llvm { +/// SmallSetIterator - This class implements a const_iterator for SmallSet by +/// delegating to the underlying SmallVector or Set iterators. +template <typename T, unsigned N, typename C> +class SmallSetIterator + : public iterator_facade_base<SmallSetIterator<T, N, C>, + std::forward_iterator_tag, T> { +private: + using SetIterTy = typename std::set<T, C>::const_iterator; + using VecIterTy = typename SmallVector<T, N>::const_iterator; + using SelfTy = SmallSetIterator<T, N, C>; + + /// Iterators to the parts of the SmallSet containing the data. They are set + /// depending on isSmall. + union { + SetIterTy SetIter; + VecIterTy VecIter; + }; + + bool isSmall; + +public: + SmallSetIterator(SetIterTy SetIter) : SetIter(SetIter), isSmall(false) {} + + SmallSetIterator(VecIterTy VecIter) : VecIter(VecIter), isSmall(true) {} + + // Spell out destructor, copy/move constructor and assignment operators for + // MSVC STL, where set<T>::const_iterator is not trivially copy constructible. + ~SmallSetIterator() { + if (isSmall) + VecIter.~VecIterTy(); + else + SetIter.~SetIterTy(); + } + + SmallSetIterator(const SmallSetIterator &Other) : isSmall(Other.isSmall) { + if (isSmall) + VecIter = Other.VecIter; + else + // Use placement new, to make sure SetIter is properly constructed, even + // if it is not trivially copy-able (e.g. in MSVC). + new (&SetIter) SetIterTy(Other.SetIter); + } + + SmallSetIterator(SmallSetIterator &&Other) : isSmall(Other.isSmall) { + if (isSmall) + VecIter = std::move(Other.VecIter); + else + // Use placement new, to make sure SetIter is properly constructed, even + // if it is not trivially copy-able (e.g. in MSVC). + new (&SetIter) SetIterTy(std::move(Other.SetIter)); + } + + SmallSetIterator& operator=(const SmallSetIterator& Other) { + // Call destructor for SetIter, so it gets properly destroyed if it is + // not trivially destructible in case we are setting VecIter. + if (!isSmall) + SetIter.~SetIterTy(); + + isSmall = Other.isSmall; + if (isSmall) + VecIter = Other.VecIter; + else + new (&SetIter) SetIterTy(Other.SetIter); + return *this; + } + + SmallSetIterator& operator=(SmallSetIterator&& Other) { + // Call destructor for SetIter, so it gets properly destroyed if it is + // not trivially destructible in case we are setting VecIter. + if (!isSmall) + SetIter.~SetIterTy(); + + isSmall = Other.isSmall; + if (isSmall) + VecIter = std::move(Other.VecIter); + else + new (&SetIter) SetIterTy(std::move(Other.SetIter)); + return *this; + } + + bool operator==(const SmallSetIterator &RHS) const { + if (isSmall != RHS.isSmall) + return false; + if (isSmall) + return VecIter == RHS.VecIter; + return SetIter == RHS.SetIter; + } + + SmallSetIterator &operator++() { // Preincrement + if (isSmall) + VecIter++; + else + SetIter++; + return *this; + } + + const T &operator*() const { return isSmall ? *VecIter : *SetIter; } +}; + /// SmallSet - This maintains a set of unique values, optimizing for the case /// when the set is small (less than N). In this case, the set can be /// maintained with no mallocs. If the set gets large, we expand to using an /// std::set to maintain reasonable lookup times. -/// -/// Note that this set does not provide a way to iterate over members in the -/// set. template <typename T, unsigned N, typename C = std::less<T>> class SmallSet { /// Use a SmallVector to hold the elements here (even though it will never @@ -50,6 +149,7 @@ class SmallSet { public: using size_type = size_t; + using const_iterator = SmallSetIterator<T, N, C>; SmallSet() = default; @@ -121,6 +221,18 @@ public: Set.clear(); } + const_iterator begin() const { + if (isSmall()) + return {Vector.begin()}; + return {Set.begin()}; + } + + const_iterator end() const { + if (isSmall()) + return {Vector.end()}; + return {Set.end()}; + } + private: bool isSmall() const { return Set.empty(); } diff --git a/contrib/llvm/include/llvm/ADT/SmallVector.h b/contrib/llvm/include/llvm/ADT/SmallVector.h index a9ac98d1ad4c..acb4426b4f45 100644 --- a/contrib/llvm/include/llvm/ADT/SmallVector.h +++ b/contrib/llvm/include/llvm/ADT/SmallVector.h @@ -18,6 +18,7 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemAlloc.h" #include "llvm/Support/type_traits.h" #include "llvm/Support/ErrorHandling.h" #include <algorithm> @@ -37,28 +38,42 @@ namespace llvm { /// This is all the non-templated stuff common to all SmallVectors. class SmallVectorBase { protected: - void *BeginX, *EndX, *CapacityX; + void *BeginX; + unsigned Size = 0, Capacity; -protected: - SmallVectorBase(void *FirstEl, size_t Size) - : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {} + SmallVectorBase() = delete; + SmallVectorBase(void *FirstEl, size_t Capacity) + : BeginX(FirstEl), Capacity(Capacity) {} /// This is an implementation of the grow() method which only works /// on POD-like data types and is out of line to reduce code duplication. - void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize); + void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize); public: - /// This returns size()*sizeof(T). - size_t size_in_bytes() const { - return size_t((char*)EndX - (char*)BeginX); - } + size_t size() const { return Size; } + size_t capacity() const { return Capacity; } + + LLVM_NODISCARD bool empty() const { return !Size; } - /// capacity_in_bytes - This returns capacity()*sizeof(T). - size_t capacity_in_bytes() const { - return size_t((char*)CapacityX - (char*)BeginX); + /// Set the array size to \p N, which the current array must have enough + /// capacity for. + /// + /// This does not construct or destroy any elements in the vector. + /// + /// Clients can use this in conjunction with capacity() to write past the end + /// of the buffer when they know that more elements are available, and only + /// update the size later. This avoids the cost of value initializing elements + /// which will only be overwritten. + void set_size(size_t Size) { + assert(Size <= capacity()); + this->Size = Size; } +}; - LLVM_NODISCARD bool empty() const { return BeginX == EndX; } +/// Figure out the offset of the first element. +template <class T, typename = void> struct SmallVectorAlignmentAndSize { + AlignedCharArrayUnion<SmallVectorBase> Base; + AlignedCharArrayUnion<T> FirstEl; }; /// This is the part of SmallVectorTemplateBase which does not depend on whether @@ -66,36 +81,34 @@ public: /// to avoid unnecessarily requiring T to be complete. template <typename T, typename = void> class SmallVectorTemplateCommon : public SmallVectorBase { -private: - template <typename, unsigned> friend struct SmallVectorStorage; - - // Allocate raw space for N elements of type T. If T has a ctor or dtor, we - // don't want it to be automatically run, so we need to represent the space as - // something else. Use an array of char of sufficient alignment. - using U = AlignedCharArrayUnion<T>; - U FirstEl; + /// Find the address of the first element. For this pointer math to be valid + /// with small-size of 0 for T with lots of alignment, it's important that + /// SmallVectorStorage is properly-aligned even for small-size of 0. + void *getFirstEl() const { + return const_cast<void *>(reinterpret_cast<const void *>( + reinterpret_cast<const char *>(this) + + offsetof(SmallVectorAlignmentAndSize<T>, FirstEl))); + } // Space after 'FirstEl' is clobbered, do not add any instance vars after it. protected: - SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(&FirstEl, Size) {} + SmallVectorTemplateCommon(size_t Size) + : SmallVectorBase(getFirstEl(), Size) {} - void grow_pod(size_t MinSizeInBytes, size_t TSize) { - SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize); + void grow_pod(size_t MinCapacity, size_t TSize) { + SmallVectorBase::grow_pod(getFirstEl(), MinCapacity, TSize); } /// Return true if this is a smallvector which has not had dynamic /// memory allocated for it. - bool isSmall() const { - return BeginX == static_cast<const void*>(&FirstEl); - } + bool isSmall() const { return BeginX == getFirstEl(); } /// Put this vector in a state of being small. void resetToSmall() { - BeginX = EndX = CapacityX = &FirstEl; + BeginX = getFirstEl(); + Size = Capacity = 0; // FIXME: Setting Capacity to 0 is suspect. } - void setEnd(T *P) { this->EndX = P; } - public: using size_type = size_t; using difference_type = ptrdiff_t; @@ -117,27 +130,20 @@ public: LLVM_ATTRIBUTE_ALWAYS_INLINE const_iterator begin() const { return (const_iterator)this->BeginX; } LLVM_ATTRIBUTE_ALWAYS_INLINE - iterator end() { return (iterator)this->EndX; } + iterator end() { return begin() + size(); } LLVM_ATTRIBUTE_ALWAYS_INLINE - const_iterator end() const { return (const_iterator)this->EndX; } - -protected: - iterator capacity_ptr() { return (iterator)this->CapacityX; } - const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} + const_iterator end() const { return begin() + size(); } -public: // reverse iterator creation methods. reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin());} - LLVM_ATTRIBUTE_ALWAYS_INLINE - size_type size() const { return end()-begin(); } + size_type size_in_bytes() const { return size() * sizeof(T); } size_type max_size() const { return size_type(-1) / sizeof(T); } - /// Return the total number of elements in the currently allocated buffer. - size_t capacity() const { return capacity_ptr() - begin(); } + size_t capacity_in_bytes() const { return capacity() * sizeof(T); } /// Return a pointer to the vector's buffer, even if empty(). pointer data() { return pointer(begin()); } @@ -210,21 +216,21 @@ protected: public: void push_back(const T &Elt) { - if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + if (LLVM_UNLIKELY(this->size() >= this->capacity())) this->grow(); ::new ((void*) this->end()) T(Elt); - this->setEnd(this->end()+1); + this->set_size(this->size() + 1); } void push_back(T &&Elt) { - if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + if (LLVM_UNLIKELY(this->size() >= this->capacity())) this->grow(); ::new ((void*) this->end()) T(::std::move(Elt)); - this->setEnd(this->end()+1); + this->set_size(this->size() + 1); } void pop_back() { - this->setEnd(this->end()-1); + this->set_size(this->size() - 1); this->end()->~T(); } }; @@ -232,15 +238,13 @@ public: // Define this out-of-line to dissuade the C++ compiler from inlining it. template <typename T, bool isPodLike> void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { - size_t CurCapacity = this->capacity(); - size_t CurSize = this->size(); + if (MinSize > UINT32_MAX) + report_bad_alloc_error("SmallVector capacity overflow during allocation"); + // Always grow, even from zero. - size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2)); - if (NewCapacity < MinSize) - NewCapacity = MinSize; - T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T))); - if (NewElts == nullptr) - report_bad_alloc_error("Allocation of SmallVector element failed."); + size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + 2)); + NewCapacity = std::min(std::max(NewCapacity, MinSize), size_t(UINT32_MAX)); + T *NewElts = static_cast<T*>(llvm::safe_malloc(NewCapacity*sizeof(T))); // Move the elements over. this->uninitialized_move(this->begin(), this->end(), NewElts); @@ -252,9 +256,8 @@ void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { if (!this->isSmall()) free(this->begin()); - this->setEnd(NewElts+CurSize); this->BeginX = NewElts; - this->CapacityX = this->begin()+NewCapacity; + this->Capacity = NewCapacity; } @@ -301,21 +304,17 @@ protected: /// Double the size of the allocated memory, guaranteeing space for at /// least one more element or MinSize if specified. - void grow(size_t MinSize = 0) { - this->grow_pod(MinSize*sizeof(T), sizeof(T)); - } + void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); } public: void push_back(const T &Elt) { - if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + if (LLVM_UNLIKELY(this->size() >= this->capacity())) this->grow(); memcpy(this->end(), &Elt, sizeof(T)); - this->setEnd(this->end()+1); + this->set_size(this->size() + 1); } - void pop_back() { - this->setEnd(this->end()-1); - } + void pop_back() { this->set_size(this->size() - 1); } }; /// This class consists of common code factored out of the SmallVector class to @@ -332,16 +331,13 @@ public: protected: // Default ctor - Initialize to empty. explicit SmallVectorImpl(unsigned N) - : SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) { - } + : SmallVectorTemplateBase<T, isPodLike<T>::value>(N) {} public: SmallVectorImpl(const SmallVectorImpl &) = delete; ~SmallVectorImpl() { - // Destroy the constructed elements in the vector. - this->destroy_range(this->begin(), this->end()); - + // Subclass has already destructed this vector's elements. // If this wasn't grown from the inline copy, deallocate the old space. if (!this->isSmall()) free(this->begin()); @@ -349,31 +345,31 @@ public: void clear() { this->destroy_range(this->begin(), this->end()); - this->EndX = this->BeginX; + this->Size = 0; } void resize(size_type N) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); - this->setEnd(this->begin()+N); + this->set_size(N); } else if (N > this->size()) { if (this->capacity() < N) this->grow(N); for (auto I = this->end(), E = this->begin() + N; I != E; ++I) new (&*I) T(); - this->setEnd(this->begin()+N); + this->set_size(N); } } void resize(size_type N, const T &NV) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); - this->setEnd(this->begin()+N); + this->set_size(N); } else if (N > this->size()) { if (this->capacity() < N) this->grow(N); std::uninitialized_fill(this->end(), this->begin()+N, NV); - this->setEnd(this->begin()+N); + this->set_size(N); } } @@ -398,23 +394,23 @@ public: void append(in_iter in_start, in_iter in_end) { size_type NumInputs = std::distance(in_start, in_end); // Grow allocated space if needed. - if (NumInputs > size_type(this->capacity_ptr()-this->end())) + if (NumInputs > this->capacity() - this->size()) this->grow(this->size()+NumInputs); // Copy the new elements over. this->uninitialized_copy(in_start, in_end, this->end()); - this->setEnd(this->end() + NumInputs); + this->set_size(this->size() + NumInputs); } /// Add the specified range to the end of the SmallVector. void append(size_type NumInputs, const T &Elt) { // Grow allocated space if needed. - if (NumInputs > size_type(this->capacity_ptr()-this->end())) + if (NumInputs > this->capacity() - this->size()) this->grow(this->size()+NumInputs); // Copy the new elements over. std::uninitialized_fill_n(this->end(), NumInputs, Elt); - this->setEnd(this->end() + NumInputs); + this->set_size(this->size() + NumInputs); } void append(std::initializer_list<T> IL) { @@ -428,7 +424,7 @@ public: clear(); if (this->capacity() < NumElts) this->grow(NumElts); - this->setEnd(this->begin()+NumElts); + this->set_size(NumElts); std::uninitialized_fill(this->begin(), this->end(), Elt); } @@ -475,7 +471,7 @@ public: iterator I = std::move(E, this->end(), S); // Drop the last elts. this->destroy_range(I, this->end()); - this->setEnd(I); + this->set_size(I - this->begin()); return(N); } @@ -488,7 +484,7 @@ public: assert(I >= this->begin() && "Insertion iterator is out of bounds."); assert(I <= this->end() && "Inserting past the end of the vector."); - if (this->EndX >= this->CapacityX) { + if (this->size() >= this->capacity()) { size_t EltNo = I-this->begin(); this->grow(); I = this->begin()+EltNo; @@ -497,12 +493,12 @@ public: ::new ((void*) this->end()) T(::std::move(this->back())); // Push everything else over. std::move_backward(I, this->end()-1, this->end()); - this->setEnd(this->end()+1); + this->set_size(this->size() + 1); // If we just moved the element we're inserting, be sure to update // the reference. T *EltPtr = &Elt; - if (I <= EltPtr && EltPtr < this->EndX) + if (I <= EltPtr && EltPtr < this->end()) ++EltPtr; *I = ::std::move(*EltPtr); @@ -518,7 +514,7 @@ public: assert(I >= this->begin() && "Insertion iterator is out of bounds."); assert(I <= this->end() && "Inserting past the end of the vector."); - if (this->EndX >= this->CapacityX) { + if (this->size() >= this->capacity()) { size_t EltNo = I-this->begin(); this->grow(); I = this->begin()+EltNo; @@ -526,12 +522,12 @@ public: ::new ((void*) this->end()) T(std::move(this->back())); // Push everything else over. std::move_backward(I, this->end()-1, this->end()); - this->setEnd(this->end()+1); + this->set_size(this->size() + 1); // If we just moved the element we're inserting, be sure to update // the reference. const T *EltPtr = &Elt; - if (I <= EltPtr && EltPtr < this->EndX) + if (I <= EltPtr && EltPtr < this->end()) ++EltPtr; *I = *EltPtr; @@ -577,7 +573,7 @@ public: // Move over the elements that we're about to overwrite. T *OldEnd = this->end(); - this->setEnd(this->end() + NumToInsert); + this->set_size(this->size() + NumToInsert); size_t NumOverwritten = OldEnd-I; this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); @@ -634,7 +630,7 @@ public: // Move over the elements that we're about to overwrite. T *OldEnd = this->end(); - this->setEnd(this->end() + NumToInsert); + this->set_size(this->size() + NumToInsert); size_t NumOverwritten = OldEnd-I; this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); @@ -654,10 +650,10 @@ public: } template <typename... ArgTypes> void emplace_back(ArgTypes &&... Args) { - if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + if (LLVM_UNLIKELY(this->size() >= this->capacity())) this->grow(); ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...); - this->setEnd(this->end() + 1); + this->set_size(this->size() + 1); } SmallVectorImpl &operator=(const SmallVectorImpl &RHS); @@ -676,20 +672,6 @@ public: return std::lexicographical_compare(this->begin(), this->end(), RHS.begin(), RHS.end()); } - - /// Set the array size to \p N, which the current array must have enough - /// capacity for. - /// - /// This does not construct or destroy any elements in the vector. - /// - /// Clients can use this in conjunction with capacity() to write past the end - /// of the buffer when they know that more elements are available, and only - /// update the size later. This avoids the cost of value initializing elements - /// which will only be overwritten. - void set_size(size_type N) { - assert(N <= this->capacity()); - this->setEnd(this->begin() + N); - } }; template <typename T> @@ -699,8 +681,8 @@ void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { // We can only avoid copying elements if neither vector is small. if (!this->isSmall() && !RHS.isSmall()) { std::swap(this->BeginX, RHS.BeginX); - std::swap(this->EndX, RHS.EndX); - std::swap(this->CapacityX, RHS.CapacityX); + std::swap(this->Size, RHS.Size); + std::swap(this->Capacity, RHS.Capacity); return; } if (RHS.size() > this->capacity()) @@ -718,15 +700,15 @@ void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { if (this->size() > RHS.size()) { size_t EltDiff = this->size() - RHS.size(); this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); - RHS.setEnd(RHS.end()+EltDiff); + RHS.set_size(RHS.size() + EltDiff); this->destroy_range(this->begin()+NumShared, this->end()); - this->setEnd(this->begin()+NumShared); + this->set_size(NumShared); } else if (RHS.size() > this->size()) { size_t EltDiff = RHS.size() - this->size(); this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); - this->setEnd(this->end() + EltDiff); + this->set_size(this->size() + EltDiff); this->destroy_range(RHS.begin()+NumShared, RHS.end()); - RHS.setEnd(RHS.begin()+NumShared); + RHS.set_size(NumShared); } } @@ -752,7 +734,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>:: this->destroy_range(NewEnd, this->end()); // Trim. - this->setEnd(NewEnd); + this->set_size(RHSSize); return *this; } @@ -762,7 +744,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>:: if (this->capacity() < RHSSize) { // Destroy current elements. this->destroy_range(this->begin(), this->end()); - this->setEnd(this->begin()); + this->set_size(0); CurSize = 0; this->grow(RHSSize); } else if (CurSize) { @@ -775,7 +757,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>:: this->begin()+CurSize); // Set end. - this->setEnd(this->begin()+RHSSize); + this->set_size(RHSSize); return *this; } @@ -789,8 +771,8 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { this->destroy_range(this->begin(), this->end()); if (!this->isSmall()) free(this->begin()); this->BeginX = RHS.BeginX; - this->EndX = RHS.EndX; - this->CapacityX = RHS.CapacityX; + this->Size = RHS.Size; + this->Capacity = RHS.Capacity; RHS.resetToSmall(); return *this; } @@ -807,7 +789,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { // Destroy excess elements and trim the bounds. this->destroy_range(NewEnd, this->end()); - this->setEnd(NewEnd); + this->set_size(RHSSize); // Clear the RHS. RHS.clear(); @@ -822,7 +804,7 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { if (this->capacity() < RHSSize) { // Destroy current elements. this->destroy_range(this->begin(), this->end()); - this->setEnd(this->begin()); + this->set_size(0); CurSize = 0; this->grow(RHSSize); } else if (CurSize) { @@ -835,22 +817,23 @@ SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { this->begin()+CurSize); // Set end. - this->setEnd(this->begin()+RHSSize); + this->set_size(RHSSize); RHS.clear(); return *this; } -/// Storage for the SmallVector elements which aren't contained in -/// SmallVectorTemplateCommon. There are 'N-1' elements here. The remaining '1' -/// element is in the base class. This is specialized for the N=1 and N=0 cases +/// Storage for the SmallVector elements. This is specialized for the N=0 case /// to avoid allocating unnecessary storage. template <typename T, unsigned N> struct SmallVectorStorage { - typename SmallVectorTemplateCommon<T>::U InlineElts[N - 1]; + AlignedCharArrayUnion<T> InlineElts[N]; }; -template <typename T> struct SmallVectorStorage<T, 1> {}; -template <typename T> struct SmallVectorStorage<T, 0> {}; + +/// We need the storage to be properly aligned even for small-size of 0 so that +/// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is +/// well-defined. +template <typename T> struct alignas(alignof(T)) SmallVectorStorage<T, 0> {}; /// This is a 'vector' (really, a variable-sized array), optimized /// for the case when the array is small. It contains some number of elements @@ -861,13 +844,15 @@ template <typename T> struct SmallVectorStorage<T, 0> {}; /// Note that this does not attempt to be exception safe. /// template <typename T, unsigned N> -class SmallVector : public SmallVectorImpl<T> { - /// Inline space for elements which aren't stored in the base class. - SmallVectorStorage<T, N> Storage; - +class SmallVector : public SmallVectorImpl<T>, SmallVectorStorage<T, N> { public: SmallVector() : SmallVectorImpl<T>(N) {} + ~SmallVector() { + // Destroy the constructed elements in the vector. + this->destroy_range(this->begin(), this->end()); + } + explicit SmallVector(size_t Size, const T &Value = T()) : SmallVectorImpl<T>(N) { this->assign(Size, Value); diff --git a/contrib/llvm/include/llvm/ADT/SparseMultiSet.h b/contrib/llvm/include/llvm/ADT/SparseMultiSet.h index c91e0d70f65a..3c8637621510 100644 --- a/contrib/llvm/include/llvm/ADT/SparseMultiSet.h +++ b/contrib/llvm/include/llvm/ADT/SparseMultiSet.h @@ -211,7 +211,7 @@ public: // The Sparse array doesn't actually need to be initialized, so malloc // would be enough here, but that will cause tools like valgrind to // complain about branching on uninitialized data. - Sparse = reinterpret_cast<SparseT*>(calloc(U, sizeof(SparseT))); + Sparse = static_cast<SparseT*>(safe_calloc(U, sizeof(SparseT))); Universe = U; } diff --git a/contrib/llvm/include/llvm/ADT/SparseSet.h b/contrib/llvm/include/llvm/ADT/SparseSet.h index 25ade8831922..74cc6dab8c74 100644 --- a/contrib/llvm/include/llvm/ADT/SparseSet.h +++ b/contrib/llvm/include/llvm/ADT/SparseSet.h @@ -22,6 +22,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" #include <cassert> #include <cstdint> #include <cstdlib> @@ -163,7 +164,7 @@ public: // The Sparse array doesn't actually need to be initialized, so malloc // would be enough here, but that will cause tools like valgrind to // complain about branching on uninitialized data. - Sparse = reinterpret_cast<SparseT*>(calloc(U, sizeof(SparseT))); + Sparse = static_cast<SparseT*>(safe_calloc(U, sizeof(SparseT))); Universe = U; } diff --git a/contrib/llvm/include/llvm/ADT/Statistic.h b/contrib/llvm/include/llvm/ADT/Statistic.h index d5ebba409c3d..90c2eefceb6c 100644 --- a/contrib/llvm/include/llvm/ADT/Statistic.h +++ b/contrib/llvm/include/llvm/ADT/Statistic.h @@ -26,15 +26,24 @@ #ifndef LLVM_ADT_STATISTIC_H #define LLVM_ADT_STATISTIC_H -#include "llvm/Support/Atomic.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/Compiler.h" #include <atomic> #include <memory> +#include <vector> + +// Determine whether statistics should be enabled. We must do it here rather +// than in CMake because multi-config generators cannot determine this at +// configure time. +#if !defined(NDEBUG) || LLVM_FORCE_ENABLE_STATS +#define LLVM_ENABLE_STATS 1 +#endif namespace llvm { class raw_ostream; class raw_fd_ostream; +class StringRef; class Statistic { public: @@ -42,7 +51,7 @@ public: const char *Name; const char *Desc; std::atomic<unsigned> Value; - bool Initialized; + std::atomic<bool> Initialized; unsigned getValue() const { return Value.load(std::memory_order_relaxed); } const char *getDebugType() const { return DebugType; } @@ -61,7 +70,7 @@ public: // Allow use of this class as the value itself. operator unsigned() const { return getValue(); } -#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) +#if LLVM_ENABLE_STATS const Statistic &operator=(unsigned Val) { Value.store(Val, std::memory_order_relaxed); return init(); @@ -143,14 +152,12 @@ public: void updateMax(unsigned V) {} -#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) +#endif // LLVM_ENABLE_STATS protected: Statistic &init() { - bool tmp = Initialized; - sys::MemoryFence(); - if (!tmp) RegisterStatistic(); - TsanHappensAfter(this); + if (!Initialized.load(std::memory_order_acquire)) + RegisterStatistic(); return *this; } @@ -160,21 +167,21 @@ protected: // STATISTIC - A macro to make definition of statistics really simple. This // automatically passes the DEBUG_TYPE of the file into the statistic. #define STATISTIC(VARNAME, DESC) \ - static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, false} + static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, {false}} -/// \brief Enable the collection and printing of statistics. +/// Enable the collection and printing of statistics. void EnableStatistics(bool PrintOnExit = true); -/// \brief Check if statistics are enabled. +/// Check if statistics are enabled. bool AreStatisticsEnabled(); -/// \brief Return a file stream to print our output on. +/// Return a file stream to print our output on. std::unique_ptr<raw_fd_ostream> CreateInfoOutputFile(); -/// \brief Print statistics to the file returned by CreateInfoOutputFile(). +/// Print statistics to the file returned by CreateInfoOutputFile(). void PrintStatistics(); -/// \brief Print statistics to the given output stream. +/// Print statistics to the given output stream. void PrintStatistics(raw_ostream &OS); /// Print statistics in JSON format. This does include all global timers (\see @@ -183,6 +190,30 @@ void PrintStatistics(raw_ostream &OS); /// PrintStatisticsJSON(). void PrintStatisticsJSON(raw_ostream &OS); +/// Get the statistics. This can be used to look up the value of +/// statistics without needing to parse JSON. +/// +/// This function does not prevent statistics being updated by other threads +/// during it's execution. It will return the value at the point that it is +/// read. However, it will prevent new statistics from registering until it +/// completes. +const std::vector<std::pair<StringRef, unsigned>> GetStatistics(); + +/// Reset the statistics. This can be used to zero and de-register the +/// statistics in order to measure a compilation. +/// +/// When this function begins to call destructors prior to returning, all +/// statistics will be zero and unregistered. However, that might not remain the +/// case by the time this function finishes returning. Whether update from other +/// threads are lost or merely deferred until during the function return is +/// timing sensitive. +/// +/// Callers who intend to use this to measure statistics for a single +/// compilation should ensure that no compilations are in progress at the point +/// this function is called and that only one compilation executes until calling +/// GetStatistics(). +void ResetStatistics(); + } // end namespace llvm #endif // LLVM_ADT_STATISTIC_H diff --git a/contrib/llvm/include/llvm/ADT/StringExtras.h b/contrib/llvm/include/llvm/ADT/StringExtras.h index 60652f8c55c5..71b0e7527cb7 100644 --- a/contrib/llvm/include/llvm/ADT/StringExtras.h +++ b/contrib/llvm/include/llvm/ADT/StringExtras.h @@ -39,6 +39,16 @@ inline char hexdigit(unsigned X, bool LowerCase = false) { return X < 10 ? '0' + X : HexChar + X - 10; } +/// Given an array of c-style strings terminated by a null pointer, construct +/// a vector of StringRefs representing the same strings without the terminating +/// null string. +inline std::vector<StringRef> toStringRefArray(const char *const *Strings) { + std::vector<StringRef> Result; + while (*Strings) + Result.push_back(*Strings++); + return Result; +} + /// Construct a string ref from a boolean. inline StringRef toStringRef(bool B) { return StringRef(B ? "true" : "false"); } @@ -78,6 +88,26 @@ inline bool isAlpha(char C) { /// lowercase letter as classified by "C" locale. inline bool isAlnum(char C) { return isAlpha(C) || isDigit(C); } +/// Checks whether character \p C is valid ASCII (high bit is zero). +inline bool isASCII(char C) { return static_cast<unsigned char>(C) <= 127; } + +/// Checks whether all characters in S are ASCII. +inline bool isASCII(llvm::StringRef S) { + for (char C : S) + if (LLVM_UNLIKELY(!isASCII(C))) + return false; + return true; +} + +/// Checks whether character \p C is printable. +/// +/// Locale-independent version of the C standard library isprint whose results +/// may differ on different platforms. +inline bool isPrint(char C) { + unsigned char UC = static_cast<unsigned char>(C); + return (0x20 <= UC) && (UC <= 0x7E); +} + /// Returns the corresponding lowercase character if \p x is uppercase. inline char toLower(char x) { if (x >= 'A' && x <= 'Z') @@ -157,7 +187,7 @@ inline std::string fromHex(StringRef Input) { return Output; } -/// \brief Convert the string \p S to an integer of the specified type using +/// Convert the string \p S to an integer of the specified type using /// the radix \p Base. If \p Base is 0, auto-detects the radix. /// Returns true if the number was successfully converted, false otherwise. template <typename N> bool to_integer(StringRef S, N &Num, unsigned Base = 0) { @@ -232,19 +262,6 @@ void SplitString(StringRef Source, SmallVectorImpl<StringRef> &OutFragments, StringRef Delimiters = " \t\n\v\f\r"); -/// HashString - Hash function for strings. -/// -/// This is the Bernstein hash function. -// -// FIXME: Investigate whether a modified bernstein hash function performs -// better: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx -// X*33+c -> X*33^c -inline unsigned HashString(StringRef Str, unsigned Result = 0) { - for (StringRef::size_type i = 0, e = Str.size(); i != e; ++i) - Result = Result * 33 + (unsigned char)Str[i]; - return Result; -} - /// Returns the English suffix for an ordinal integer (-st, -nd, -rd, -th). inline StringRef getOrdinalSuffix(unsigned Val) { // It is critically important that we do this perfectly for @@ -264,9 +281,13 @@ inline StringRef getOrdinalSuffix(unsigned Val) { } } -/// PrintEscapedString - Print each character of the specified string, escaping -/// it if it is not printable or if it is an escape char. -void PrintEscapedString(StringRef Name, raw_ostream &Out); +/// Print each character of the specified string, escaping it if it is not +/// printable or if it is an escape char. +void printEscapedString(StringRef Name, raw_ostream &Out); + +/// Print each character of the specified string, escaping HTML special +/// characters. +void printHTMLEscaped(StringRef String, raw_ostream &Out); /// printLowerCase - Print each character as lowercase if it is uppercase. void printLowerCase(StringRef String, raw_ostream &Out); diff --git a/contrib/llvm/include/llvm/ADT/StringMap.h b/contrib/llvm/include/llvm/ADT/StringMap.h index 6c2830b44914..a9f83d3f5091 100644 --- a/contrib/llvm/include/llvm/ADT/StringMap.h +++ b/contrib/llvm/include/llvm/ADT/StringMap.h @@ -37,12 +37,12 @@ template<typename ValueTy> class StringMapKeyIterator; /// StringMapEntryBase - Shared base class of StringMapEntry instances. class StringMapEntryBase { - unsigned StrLen; + size_t StrLen; public: - explicit StringMapEntryBase(unsigned Len) : StrLen(Len) {} + explicit StringMapEntryBase(size_t Len) : StrLen(Len) {} - unsigned getKeyLength() const { return StrLen; } + size_t getKeyLength() const { return StrLen; } }; /// StringMapImpl - This is the base class of StringMap that is shared among @@ -127,10 +127,10 @@ class StringMapEntry : public StringMapEntryBase { public: ValueTy second; - explicit StringMapEntry(unsigned strLen) + explicit StringMapEntry(size_t strLen) : StringMapEntryBase(strLen), second() {} template <typename... InitTy> - StringMapEntry(unsigned strLen, InitTy &&... InitVals) + StringMapEntry(size_t strLen, InitTy &&... InitVals) : StringMapEntryBase(strLen), second(std::forward<InitTy>(InitVals)...) {} StringMapEntry(StringMapEntry &E) = delete; @@ -155,19 +155,16 @@ public: template <typename AllocatorTy, typename... InitTy> static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, InitTy &&... InitVals) { - unsigned KeyLength = Key.size(); + size_t KeyLength = Key.size(); // 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); + size_t AllocSize = sizeof(StringMapEntry) + KeyLength + 1; + size_t Alignment = alignof(StringMapEntry); StringMapEntry *NewItem = static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize,Alignment)); - - if (NewItem == nullptr) - report_bad_alloc_error("Allocation of StringMap entry failed."); + assert(NewItem && "Unhandled out-of-memory"); // Construct the value. new (NewItem) StringMapEntry(KeyLength, std::forward<InitTy>(InitVals)...); @@ -203,8 +200,7 @@ public: template<typename AllocatorTy> void Destroy(AllocatorTy &Allocator) { // Free memory referenced by the item. - unsigned AllocSize = - static_cast<unsigned>(sizeof(StringMapEntry)) + getKeyLength() + 1; + size_t AllocSize = sizeof(StringMapEntry) + getKeyLength() + 1; this->~StringMapEntry(); Allocator.Deallocate(static_cast<void *>(this), AllocSize); } diff --git a/contrib/llvm/include/llvm/ADT/StringRef.h b/contrib/llvm/include/llvm/ADT/StringRef.h index f6c93a858db1..a5ba5b59b5a3 100644 --- a/contrib/llvm/include/llvm/ADT/StringRef.h +++ b/contrib/llvm/include/llvm/ADT/StringRef.h @@ -201,7 +201,7 @@ namespace llvm { LLVM_NODISCARD int compare_numeric(StringRef RHS) const; - /// \brief Determine the edit distance between this string and another + /// Determine the edit distance between this string and another /// string. /// /// \param Other the string to compare this string against. @@ -725,10 +725,7 @@ namespace llvm { /// \returns The split substrings. LLVM_NODISCARD std::pair<StringRef, StringRef> split(char Separator) const { - size_t Idx = find(Separator); - if (Idx == npos) - return std::make_pair(*this, StringRef()); - return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); + return split(StringRef(&Separator, 1)); } /// Split into two substrings around the first occurrence of a separator @@ -749,6 +746,24 @@ namespace llvm { return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); } + /// Split into two substrings around the last occurrence of a separator + /// string. + /// + /// If \p Separator is in the string, then the result is a pair (LHS, RHS) + /// such that (*this == LHS + Separator + RHS) is true and RHS is + /// minimal. If \p Separator is not in the string, then the result is a + /// pair (LHS, RHS) where (*this == LHS) and (RHS == ""). + /// + /// \param Separator - The string to split on. + /// \return - The split substrings. + LLVM_NODISCARD + std::pair<StringRef, StringRef> rsplit(StringRef Separator) const { + size_t Idx = rfind(Separator); + if (Idx == npos) + return std::make_pair(*this, StringRef()); + return std::make_pair(slice(0, Idx), slice(Idx + Separator.size(), npos)); + } + /// Split into substrings around the occurrences of a separator string. /// /// Each substring is stored in \p A. If \p MaxSplit is >= 0, at most @@ -796,10 +811,7 @@ namespace llvm { /// \return - The split substrings. LLVM_NODISCARD std::pair<StringRef, StringRef> rsplit(char Separator) const { - size_t Idx = rfind(Separator); - if (Idx == npos) - return std::make_pair(*this, StringRef()); - return std::make_pair(slice(0, Idx), slice(Idx+1, npos)); + return rsplit(StringRef(&Separator, 1)); } /// Return string with consecutive \p Char characters starting from the @@ -855,6 +867,10 @@ namespace llvm { /// constexpr StringLiteral S("test"); /// class StringLiteral : public StringRef { + private: + constexpr StringLiteral(const char *Str, size_t N) : StringRef(Str, N) { + } + public: template <size_t N> constexpr StringLiteral(const char (&Str)[N]) @@ -867,6 +883,12 @@ namespace llvm { #endif : StringRef(Str, N - 1) { } + + // Explicit construction for strings like "foo\0bar". + template <size_t N> + static constexpr StringLiteral withInnerNUL(const char (&Str)[N]) { + return StringLiteral(Str, N - 1); + } }; /// @name StringRef Comparison Operators @@ -902,7 +924,7 @@ namespace llvm { /// @} - /// \brief Compute a hash_code for a StringRef. + /// Compute a hash_code for a StringRef. LLVM_NODISCARD hash_code hash_value(StringRef S); diff --git a/contrib/llvm/include/llvm/ADT/StringSwitch.h b/contrib/llvm/include/llvm/ADT/StringSwitch.h index 75577b7738ba..b7860b98ce5d 100644 --- a/contrib/llvm/include/llvm/ADT/StringSwitch.h +++ b/contrib/llvm/include/llvm/ADT/StringSwitch.h @@ -20,7 +20,7 @@ namespace llvm { -/// \brief A switch()-like statement whose cases are string literals. +/// A switch()-like statement whose cases are string literals. /// /// The StringSwitch class is a simple form of a switch() statement that /// determines whether the given string matches one of the given string @@ -41,216 +41,176 @@ namespace llvm { /// \endcode template<typename T, typename R = T> class StringSwitch { - /// \brief The string we are matching. - StringRef Str; + /// The string we are matching. + const StringRef Str; - /// \brief The pointer to the result of this switch statement, once known, + /// The pointer to the result of this switch statement, once known, /// null before that. - const T *Result; + Optional<T> Result; public: LLVM_ATTRIBUTE_ALWAYS_INLINE explicit StringSwitch(StringRef S) - : Str(S), Result(nullptr) { } + : Str(S), Result() { } // StringSwitch is not copyable. StringSwitch(const StringSwitch &) = delete; + + // StringSwitch is not assignable due to 'Str' being 'const'. void operator=(const StringSwitch &) = delete; + void operator=(StringSwitch &&other) = delete; - StringSwitch(StringSwitch &&other) { - *this = std::move(other); - } - StringSwitch &operator=(StringSwitch &&other) { - Str = other.Str; - Result = other.Result; - return *this; - } + StringSwitch(StringSwitch &&other) + : Str(other.Str), Result(std::move(other.Result)) { } ~StringSwitch() = default; // Case-sensitive case matchers - template<unsigned N> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch& Case(const char (&S)[N], const T& Value) { - assert(N); - if (!Result && N-1 == Str.size() && - (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) { - Result = &Value; + StringSwitch &Case(StringLiteral S, T Value) { + if (!Result && Str == S) { + Result = std::move(Value); } return *this; } - template<unsigned N> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch& EndsWith(const char (&S)[N], const T &Value) { - assert(N); - if (!Result && Str.size() >= N-1 && - (N == 1 || std::memcmp(S, Str.data() + Str.size() + 1 - N, N-1) == 0)) { - Result = &Value; + StringSwitch& EndsWith(StringLiteral S, T Value) { + if (!Result && Str.endswith(S)) { + Result = std::move(Value); } return *this; } - template<unsigned N> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch& StartsWith(const char (&S)[N], const T &Value) { - assert(N); - if (!Result && Str.size() >= N-1 && - (N == 1 || std::memcmp(S, Str.data(), N-1) == 0)) { - Result = &Value; + StringSwitch& StartsWith(StringLiteral S, T Value) { + if (!Result && Str.startswith(S)) { + Result = std::move(Value); } return *this; } - template<unsigned N0, unsigned N1> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1], - const T& Value) { + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, T Value) { return Case(S0, Value).Case(S1, Value); } - template<unsigned N0, unsigned N1, unsigned N2> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1], - const char (&S2)[N2], const T& Value) { + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + T Value) { return Case(S0, Value).Cases(S1, S2, Value); } - template<unsigned N0, unsigned N1, unsigned N2, unsigned N3> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1], - const char (&S2)[N2], const char (&S3)[N3], - const T& Value) { + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, T Value) { return Case(S0, Value).Cases(S1, S2, S3, Value); } - template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1], - const char (&S2)[N2], const char (&S3)[N3], - const char (&S4)[N4], const T& Value) { + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, T Value) { return Case(S0, Value).Cases(S1, S2, S3, S4, Value); } - template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, - unsigned N5> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1], - const char (&S2)[N2], const char (&S3)[N3], - const char (&S4)[N4], const char (&S5)[N5], - const T &Value) { + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, StringLiteral S5, + T Value) { return Case(S0, Value).Cases(S1, S2, S3, S4, S5, Value); } - template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, - unsigned N5, unsigned N6> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1], - const char (&S2)[N2], const char (&S3)[N3], - const char (&S4)[N4], const char (&S5)[N5], - const char (&S6)[N6], const T &Value) { + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, StringLiteral S5, + StringLiteral S6, T Value) { return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, Value); } - template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, - unsigned N5, unsigned N6, unsigned N7> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1], - const char (&S2)[N2], const char (&S3)[N3], - const char (&S4)[N4], const char (&S5)[N5], - const char (&S6)[N6], const char (&S7)[N7], - const T &Value) { + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, StringLiteral S5, + StringLiteral S6, StringLiteral S7, T Value) { return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, Value); } - template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, - unsigned N5, unsigned N6, unsigned N7, unsigned N8> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1], - const char (&S2)[N2], const char (&S3)[N3], - const char (&S4)[N4], const char (&S5)[N5], - const char (&S6)[N6], const char (&S7)[N7], - const char (&S8)[N8], const T &Value) { + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, StringLiteral S5, + StringLiteral S6, StringLiteral S7, StringLiteral S8, + T Value) { return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, Value); } - template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, - unsigned N5, unsigned N6, unsigned N7, unsigned N8, unsigned N9> LLVM_ATTRIBUTE_ALWAYS_INLINE - StringSwitch &Cases(const char (&S0)[N0], const char (&S1)[N1], - const char (&S2)[N2], const char (&S3)[N3], - const char (&S4)[N4], const char (&S5)[N5], - const char (&S6)[N6], const char (&S7)[N7], - const char (&S8)[N8], const char (&S9)[N9], - const T &Value) { + StringSwitch &Cases(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, StringLiteral S5, + StringLiteral S6, StringLiteral S7, StringLiteral S8, + StringLiteral S9, T Value) { return Case(S0, Value).Cases(S1, S2, S3, S4, S5, S6, S7, S8, S9, Value); } // Case-insensitive case matchers. - template <unsigned N> - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &CaseLower(const char (&S)[N], - const T &Value) { - if (!Result && Str.equals_lower(StringRef(S, N - 1))) - Result = &Value; + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch &CaseLower(StringLiteral S, T Value) { + if (!Result && Str.equals_lower(S)) + Result = std::move(Value); return *this; } - template <unsigned N> - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &EndsWithLower(const char (&S)[N], - const T &Value) { - if (!Result && Str.endswith_lower(StringRef(S, N - 1))) - Result = &Value; + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch &EndsWithLower(StringLiteral S, T Value) { + if (!Result && Str.endswith_lower(S)) + Result = Value; return *this; } - template <unsigned N> - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch &StartsWithLower(const char (&S)[N], - const T &Value) { - if (!Result && Str.startswith_lower(StringRef(S, N - 1))) - Result = &Value; + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch &StartsWithLower(StringLiteral S, T Value) { + if (!Result && Str.startswith_lower(S)) + Result = std::move(Value); return *this; } - template <unsigned N0, unsigned N1> - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & - CasesLower(const char (&S0)[N0], const char (&S1)[N1], const T &Value) { + + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, T Value) { return CaseLower(S0, Value).CaseLower(S1, Value); } - template <unsigned N0, unsigned N1, unsigned N2> - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & - CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2], - const T &Value) { + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, + T Value) { return CaseLower(S0, Value).CasesLower(S1, S2, Value); } - template <unsigned N0, unsigned N1, unsigned N2, unsigned N3> - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & - CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2], - const char (&S3)[N3], const T &Value) { + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, T Value) { return CaseLower(S0, Value).CasesLower(S1, S2, S3, Value); } - template <unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4> - LLVM_ATTRIBUTE_ALWAYS_INLINE StringSwitch & - CasesLower(const char (&S0)[N0], const char (&S1)[N1], const char (&S2)[N2], - const char (&S3)[N3], const char (&S4)[N4], const T &Value) { + LLVM_ATTRIBUTE_ALWAYS_INLINE + StringSwitch &CasesLower(StringLiteral S0, StringLiteral S1, StringLiteral S2, + StringLiteral S3, StringLiteral S4, T Value) { return CaseLower(S0, Value).CasesLower(S1, S2, S3, S4, Value); } + LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE - R Default(const T &Value) const { + R Default(T Value) { if (Result) - return *Result; + return std::move(*Result); return Value; } + LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE - operator R() const { + operator R() { assert(Result && "Fell off the end of a string-switch"); - return *Result; + return std::move(*Result); } }; diff --git a/contrib/llvm/include/llvm/ADT/TinyPtrVector.h b/contrib/llvm/include/llvm/ADT/TinyPtrVector.h index 73573d65e2b3..1b8e9aa658c3 100644 --- a/contrib/llvm/include/llvm/ADT/TinyPtrVector.h +++ b/contrib/llvm/include/llvm/ADT/TinyPtrVector.h @@ -108,6 +108,12 @@ public: return *this; } + TinyPtrVector(std::initializer_list<EltTy> IL) + : Val(IL.size() == 0 + ? PtrUnion() + : IL.size() == 1 ? PtrUnion(*IL.begin()) + : PtrUnion(new VecTy(IL.begin(), IL.end()))) {} + /// Constructor from an ArrayRef. /// /// This also is a constructor for individual array elements due to the single diff --git a/contrib/llvm/include/llvm/ADT/Triple.h b/contrib/llvm/include/llvm/ADT/Triple.h index 74fc8eb8ccbf..c95b16dd4e8c 100644 --- a/contrib/llvm/include/llvm/ADT/Triple.h +++ b/contrib/llvm/include/llvm/ADT/Triple.h @@ -101,6 +101,7 @@ public: enum SubArchType { NoSubArch, + ARMSubArch_v8_4a, ARMSubArch_v8_3a, ARMSubArch_v8_2a, ARMSubArch_v8_1a, @@ -144,7 +145,8 @@ public: AMD, Mesa, SUSE, - LastVendorType = SUSE + OpenEmbedded, + LastVendorType = OpenEmbedded }; enum OSType { UnknownOS, @@ -202,9 +204,7 @@ public: MSVC, Itanium, Cygnus, - AMDOpenCL, CoreCLR, - OpenCL, Simulator, // Simulator variants of other systems, e.g., Apple's iOS LastEnvironmentType = Simulator }; @@ -660,9 +660,29 @@ public: return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be; } - /// Tests wether the target supports comdat + /// Tests whether the target is MIPS 32-bit (little and big endian). + bool isMIPS32() const { + return getArch() == Triple::mips || getArch() == Triple::mipsel; + } + + /// Tests whether the target is MIPS 64-bit (little and big endian). + bool isMIPS64() const { + return getArch() == Triple::mips64 || getArch() == Triple::mips64el; + } + + /// Tests whether the target is MIPS (little and big endian, 32- or 64-bit). + bool isMIPS() const { + return isMIPS32() || isMIPS64(); + } + + /// Tests whether the target supports comdat bool supportsCOMDAT() const { - return !isOSBinFormatMachO() && !isOSBinFormatWasm(); + return !isOSBinFormatMachO(); + } + + /// Tests whether the target uses emulated TLS as default. + bool hasDefaultEmulatedTLS() const { + return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment(); } /// @} diff --git a/contrib/llvm/include/llvm/ADT/UniqueVector.h b/contrib/llvm/include/llvm/ADT/UniqueVector.h index b17fb2392baf..c86bedd07687 100644 --- a/contrib/llvm/include/llvm/ADT/UniqueVector.h +++ b/contrib/llvm/include/llvm/ADT/UniqueVector.h @@ -72,16 +72,16 @@ public: return Vector[ID - 1]; } - /// \brief Return an iterator to the start of the vector. + /// Return an iterator to the start of the vector. iterator begin() { return Vector.begin(); } - /// \brief Return an iterator to the start of the vector. + /// Return an iterator to the start of the vector. const_iterator begin() const { return Vector.begin(); } - /// \brief Return an iterator to the end of the vector. + /// Return an iterator to the end of the vector. iterator end() { return Vector.end(); } - /// \brief Return an iterator to the end of the vector. + /// Return an iterator to the end of the vector. const_iterator end() const { return Vector.end(); } /// size - Returns the number of entries in the vector. diff --git a/contrib/llvm/include/llvm/ADT/VariadicFunction.h b/contrib/llvm/include/llvm/ADT/VariadicFunction.h index 403130c623eb..9028abe4c72c 100644 --- a/contrib/llvm/include/llvm/ADT/VariadicFunction.h +++ b/contrib/llvm/include/llvm/ADT/VariadicFunction.h @@ -53,7 +53,7 @@ namespace llvm { #define LLVM_COMMA_JOIN31(x) LLVM_COMMA_JOIN30(x), x ## 30 #define LLVM_COMMA_JOIN32(x) LLVM_COMMA_JOIN31(x), x ## 31 -/// \brief Class which can simulate a type-safe variadic function. +/// Class which can simulate a type-safe variadic function. /// /// The VariadicFunction class template makes it easy to define /// type-safe variadic functions where all arguments have the same diff --git a/contrib/llvm/include/llvm/ADT/edit_distance.h b/contrib/llvm/include/llvm/ADT/edit_distance.h index 06a01b18a9fb..b2e8ec5c3f6d 100644 --- a/contrib/llvm/include/llvm/ADT/edit_distance.h +++ b/contrib/llvm/include/llvm/ADT/edit_distance.h @@ -22,7 +22,7 @@ namespace llvm { -/// \brief Determine the edit distance between two sequences. +/// Determine the edit distance between two sequences. /// /// \param FromArray the first sequence to compare. /// diff --git a/contrib/llvm/include/llvm/ADT/ilist.h b/contrib/llvm/include/llvm/ADT/ilist.h index a788f811e4c6..00bb6d528175 100644 --- a/contrib/llvm/include/llvm/ADT/ilist.h +++ b/contrib/llvm/include/llvm/ADT/ilist.h @@ -84,21 +84,11 @@ template <typename NodeTy> struct ilist_node_traits : ilist_alloc_traits<NodeTy>, ilist_callback_traits<NodeTy> {}; -/// Default template traits for intrusive list. -/// -/// By inheriting from this, you can easily use default implementations for all -/// common operations. -/// -/// TODO: Remove this customization point. Specializing ilist_traits is -/// already fully general. -template <typename NodeTy> -struct ilist_default_traits : public ilist_node_traits<NodeTy> {}; - /// Template traits for intrusive list. /// /// Customize callbacks and allocation semantics. template <typename NodeTy> -struct ilist_traits : public ilist_default_traits<NodeTy> {}; +struct ilist_traits : public ilist_node_traits<NodeTy> {}; /// Const traits should never be instantiated. template <typename Ty> struct ilist_traits<const Ty> {}; @@ -178,9 +168,6 @@ template <class IntrusiveListT, class TraitsT> class iplist_impl : public TraitsT, IntrusiveListT { typedef IntrusiveListT base_list_type; -protected: - typedef iplist_impl iplist_impl_type; - public: typedef typename base_list_type::pointer pointer; typedef typename base_list_type::const_pointer const_pointer; @@ -369,26 +356,26 @@ public: using base_list_type::sort; - /// \brief Get the previous node, or \c nullptr for the list head. + /// Get the previous node, or \c nullptr for the list head. pointer getPrevNode(reference N) const { auto I = N.getIterator(); if (I == begin()) return nullptr; return &*std::prev(I); } - /// \brief Get the previous node, or \c nullptr for the list head. + /// Get the previous node, or \c nullptr for the list head. const_pointer getPrevNode(const_reference N) const { return getPrevNode(const_cast<reference >(N)); } - /// \brief Get the next node, or \c nullptr for the list tail. + /// Get the next node, or \c nullptr for the list tail. pointer getNextNode(reference N) const { auto Next = std::next(N.getIterator()); if (Next == end()) return nullptr; return &*Next; } - /// \brief Get the next node, or \c nullptr for the list tail. + /// Get the next node, or \c nullptr for the list tail. const_pointer getNextNode(const_reference N) const { return getNextNode(const_cast<reference >(N)); } @@ -402,7 +389,7 @@ public: template <class T, class... Options> class iplist : public iplist_impl<simple_ilist<T, Options...>, ilist_traits<T>> { - typedef typename iplist::iplist_impl_type iplist_impl_type; + using iplist_impl_type = typename iplist::iplist_impl; public: iplist() = default; diff --git a/contrib/llvm/include/llvm/ADT/ilist_node.h b/contrib/llvm/include/llvm/ADT/ilist_node.h index 3362611697cb..dd0e6b4ec2b9 100644 --- a/contrib/llvm/include/llvm/ADT/ilist_node.h +++ b/contrib/llvm/include/llvm/ADT/ilist_node.h @@ -271,7 +271,7 @@ private: public: /// @name Adjacent Node Accessors /// @{ - /// \brief Get the previous node, or \c nullptr for the list head. + /// Get the previous node, or \c nullptr for the list head. NodeTy *getPrevNode() { // Should be separated to a reused function, but then we couldn't use auto // (and would need the type of the list). @@ -280,12 +280,12 @@ public: return List.getPrevNode(*static_cast<NodeTy *>(this)); } - /// \brief Get the previous node, or \c nullptr for the list head. + /// Get the previous node, or \c nullptr for the list head. const NodeTy *getPrevNode() const { return const_cast<ilist_node_with_parent *>(this)->getPrevNode(); } - /// \brief Get the next node, or \c nullptr for the list tail. + /// Get the next node, or \c nullptr for the list tail. NodeTy *getNextNode() { // Should be separated to a reused function, but then we couldn't use auto // (and would need the type of the list). @@ -294,7 +294,7 @@ public: return List.getNextNode(*static_cast<NodeTy *>(this)); } - /// \brief Get the next node, or \c nullptr for the list tail. + /// Get the next node, or \c nullptr for the list tail. const NodeTy *getNextNode() const { return const_cast<ilist_node_with_parent *>(this)->getNextNode(); } diff --git a/contrib/llvm/include/llvm/ADT/ilist_node_options.h b/contrib/llvm/include/llvm/ADT/ilist_node_options.h index c33df1eeb819..7ff4005f6757 100644 --- a/contrib/llvm/include/llvm/ADT/ilist_node_options.h +++ b/contrib/llvm/include/llvm/ADT/ilist_node_options.h @@ -11,7 +11,6 @@ #define LLVM_ADT_ILIST_NODE_OPTIONS_H #include "llvm/Config/abi-breaking.h" -#include "llvm/Config/llvm-config.h" #include <type_traits> diff --git a/contrib/llvm/include/llvm/ADT/iterator.h b/contrib/llvm/include/llvm/ADT/iterator.h index 711f8f221620..549c5221173d 100644 --- a/contrib/llvm/include/llvm/ADT/iterator.h +++ b/contrib/llvm/include/llvm/ADT/iterator.h @@ -19,7 +19,7 @@ namespace llvm { -/// \brief CRTP base class which implements the entire standard iterator facade +/// CRTP base class which implements the entire standard iterator facade /// in terms of a minimal subset of the interface. /// /// Use this when it is reasonable to implement most of the iterator @@ -183,7 +183,7 @@ public: } }; -/// \brief CRTP base class for adapting an iterator to a different type. +/// CRTP base class for adapting an iterator to a different type. /// /// This class can be used through CRTP to adapt one iterator into another. /// Typically this is done through providing in the derived class a custom \c @@ -274,7 +274,7 @@ public: ReferenceT operator*() const { return *I; } }; -/// \brief An iterator type that allows iterating over the pointees via some +/// An iterator type that allows iterating over the pointees via some /// other iterator. /// /// The typical usage of this is to expose a type that iterates over Ts, but @@ -288,7 +288,7 @@ template <typename WrappedIteratorT, decltype(**std::declval<WrappedIteratorT>())>::type> struct pointee_iterator : iterator_adaptor_base< - pointee_iterator<WrappedIteratorT>, WrappedIteratorT, + pointee_iterator<WrappedIteratorT, T>, WrappedIteratorT, typename std::iterator_traits<WrappedIteratorT>::iterator_category, T> { pointee_iterator() = default; @@ -311,7 +311,7 @@ make_pointee_range(RangeT &&Range) { template <typename WrappedIteratorT, typename T = decltype(&*std::declval<WrappedIteratorT>())> class pointer_iterator - : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT>, + : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT, T> { mutable T Ptr; diff --git a/contrib/llvm/include/llvm/ADT/iterator_range.h b/contrib/llvm/include/llvm/ADT/iterator_range.h index 3cbf6198eb60..2ba12866ecf3 100644 --- a/contrib/llvm/include/llvm/ADT/iterator_range.h +++ b/contrib/llvm/include/llvm/ADT/iterator_range.h @@ -24,7 +24,7 @@ namespace llvm { -/// \brief A range adaptor for a pair of iterators. +/// A range adaptor for a pair of iterators. /// /// This just wraps two iterators into a range-compatible interface. Nothing /// fancy at all. @@ -47,7 +47,7 @@ public: IteratorT end() const { return end_iterator; } }; -/// \brief Convenience function for iterating over sub-ranges. +/// Convenience function for iterating over sub-ranges. /// /// This provides a bit of syntactic sugar to make using sub-ranges /// in for loops a bit easier. Analogous to std::make_pair(). @@ -59,9 +59,10 @@ template <typename T> iterator_range<T> make_range(std::pair<T, T> p) { return iterator_range<T>(std::move(p.first), std::move(p.second)); } -template<typename T> -iterator_range<decltype(begin(std::declval<T>()))> drop_begin(T &&t, int n) { - return make_range(std::next(begin(t), n), end(t)); +template <typename T> +iterator_range<decltype(adl_begin(std::declval<T>()))> drop_begin(T &&t, + int n) { + return make_range(std::next(adl_begin(t), n), adl_end(t)); } } diff --git a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h index 362096b08e13..be3496bbd955 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -76,7 +76,7 @@ class Value; /// /// See docs/AliasAnalysis.html for more information on the specific meanings /// of these values. -enum AliasResult { +enum AliasResult : uint8_t { /// The two locations do not alias at all. /// /// This value is arranged to convert to false, while all other values @@ -91,13 +91,16 @@ enum AliasResult { MustAlias, }; +/// << operator for AliasResult. +raw_ostream &operator<<(raw_ostream &OS, AliasResult AR); + /// Flags indicating whether a memory access modifies or references memory. /// /// This is no access at all, a modification, a reference, or both /// a modification and a reference. These are specifically structured such that /// they form a three bit matrix and bit-tests for 'mod' or 'ref' or 'must' /// work with any of the possible values. -enum class ModRefInfo { +enum class ModRefInfo : uint8_t { /// Must is provided for completeness, but no routines will return only /// Must today. See definition of Must below. Must = 0, @@ -325,8 +328,8 @@ public: AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); /// A convenience wrapper around the primary \c alias interface. - AliasResult alias(const Value *V1, uint64_t V1Size, const Value *V2, - uint64_t V2Size) { + AliasResult alias(const Value *V1, LocationSize V1Size, const Value *V2, + LocationSize V2Size) { return alias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size)); } @@ -343,8 +346,8 @@ public: } /// A convenience wrapper around the \c isNoAlias helper interface. - bool isNoAlias(const Value *V1, uint64_t V1Size, const Value *V2, - uint64_t V2Size) { + bool isNoAlias(const Value *V1, LocationSize V1Size, const Value *V2, + LocationSize V2Size) { return isNoAlias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size)); } @@ -501,7 +504,7 @@ public: /// getModRefInfo (for call sites) - A convenience wrapper. ModRefInfo getModRefInfo(ImmutableCallSite CS, const Value *P, - uint64_t Size) { + LocationSize Size) { return getModRefInfo(CS, MemoryLocation(P, Size)); } @@ -512,7 +515,8 @@ public: } /// getModRefInfo (for calls) - A convenience wrapper. - ModRefInfo getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) { + ModRefInfo getModRefInfo(const CallInst *C, const Value *P, + LocationSize Size) { return getModRefInfo(C, MemoryLocation(P, Size)); } @@ -523,7 +527,8 @@ public: } /// getModRefInfo (for invokes) - A convenience wrapper. - ModRefInfo getModRefInfo(const InvokeInst *I, const Value *P, uint64_t Size) { + ModRefInfo getModRefInfo(const InvokeInst *I, const Value *P, + LocationSize Size) { return getModRefInfo(I, MemoryLocation(P, Size)); } @@ -532,7 +537,8 @@ public: ModRefInfo getModRefInfo(const LoadInst *L, const MemoryLocation &Loc); /// getModRefInfo (for loads) - A convenience wrapper. - ModRefInfo getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) { + ModRefInfo getModRefInfo(const LoadInst *L, const Value *P, + LocationSize Size) { return getModRefInfo(L, MemoryLocation(P, Size)); } @@ -541,7 +547,8 @@ public: ModRefInfo getModRefInfo(const StoreInst *S, const MemoryLocation &Loc); /// getModRefInfo (for stores) - A convenience wrapper. - ModRefInfo getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size) { + ModRefInfo getModRefInfo(const StoreInst *S, const Value *P, + LocationSize Size) { return getModRefInfo(S, MemoryLocation(P, Size)); } @@ -550,7 +557,8 @@ public: ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc); /// getModRefInfo (for fences) - A convenience wrapper. - ModRefInfo getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size) { + ModRefInfo getModRefInfo(const FenceInst *S, const Value *P, + LocationSize Size) { return getModRefInfo(S, MemoryLocation(P, Size)); } @@ -580,7 +588,8 @@ public: ModRefInfo getModRefInfo(const VAArgInst *I, const MemoryLocation &Loc); /// getModRefInfo (for va_args) - A convenience wrapper. - ModRefInfo getModRefInfo(const VAArgInst *I, const Value *P, uint64_t Size) { + ModRefInfo getModRefInfo(const VAArgInst *I, const Value *P, + LocationSize Size) { return getModRefInfo(I, MemoryLocation(P, Size)); } @@ -590,7 +599,7 @@ public: /// getModRefInfo (for catchpads) - A convenience wrapper. ModRefInfo getModRefInfo(const CatchPadInst *I, const Value *P, - uint64_t Size) { + LocationSize Size) { return getModRefInfo(I, MemoryLocation(P, Size)); } @@ -600,7 +609,7 @@ public: /// getModRefInfo (for catchrets) - A convenience wrapper. ModRefInfo getModRefInfo(const CatchReturnInst *I, const Value *P, - uint64_t Size) { + LocationSize Size) { return getModRefInfo(I, MemoryLocation(P, Size)); } @@ -646,7 +655,7 @@ public: /// A convenience wrapper for constructing the memory location. ModRefInfo getModRefInfo(const Instruction *I, const Value *P, - uint64_t Size) { + LocationSize Size) { return getModRefInfo(I, MemoryLocation(P, Size)); } @@ -659,7 +668,7 @@ public: /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2); - /// \brief Return information about whether a particular call site modifies + /// Return information about whether a particular call site modifies /// or reads the specified memory location \p MemLoc before instruction \p I /// in a BasicBlock. An ordered basic block \p OBB can be used to speed up /// instruction ordering queries inside the BasicBlock containing \p I. @@ -669,9 +678,9 @@ public: const MemoryLocation &MemLoc, DominatorTree *DT, OrderedBasicBlock *OBB = nullptr); - /// \brief A convenience wrapper to synthesize a memory location. + /// A convenience wrapper to synthesize a memory location. ModRefInfo callCapturesBefore(const Instruction *I, const Value *P, - uint64_t Size, DominatorTree *DT, + LocationSize Size, DominatorTree *DT, OrderedBasicBlock *OBB = nullptr) { return callCapturesBefore(I, MemoryLocation(P, Size), DT, OBB); } @@ -687,7 +696,7 @@ public: /// A convenience wrapper synthesizing a memory location. bool canBasicBlockModify(const BasicBlock &BB, const Value *P, - uint64_t Size) { + LocationSize Size) { return canBasicBlockModify(BB, MemoryLocation(P, Size)); } @@ -702,7 +711,7 @@ public: /// A convenience wrapper synthesizing a memory location. bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2, - const Value *Ptr, uint64_t Size, + const Value *Ptr, LocationSize Size, const ModRefInfo Mode) { return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode); } diff --git a/contrib/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h b/contrib/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h index cd2f631a01f4..0941814a56c3 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h +++ b/contrib/llvm/include/llvm/Analysis/AliasAnalysisEvaluator.h @@ -56,7 +56,7 @@ public: } ~AAEvaluator(); - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); private: diff --git a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h index 7da3ebabb8a3..c9680ff40d1e 100644 --- a/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h +++ b/contrib/llvm/include/llvm/Analysis/AliasSetTracker.h @@ -37,8 +37,8 @@ namespace llvm { class AliasSetTracker; class BasicBlock; class LoadInst; -class MemSetInst; -class MemTransferInst; +class AnyMemSetInst; +class AnyMemTransferInst; class raw_ostream; class StoreInst; class VAArgInst; @@ -52,7 +52,7 @@ class AliasSet : public ilist_node<AliasSet> { PointerRec **PrevInList = nullptr; PointerRec *NextInList = nullptr; AliasSet *AS = nullptr; - uint64_t Size = 0; + LocationSize Size = 0; AAMDNodes AAInfo; public: @@ -69,7 +69,7 @@ class AliasSet : public ilist_node<AliasSet> { return &NextInList; } - bool updateSizeAndAAInfo(uint64_t NewSize, const AAMDNodes &NewAAInfo) { + bool updateSizeAndAAInfo(LocationSize NewSize, const AAMDNodes &NewAAInfo) { bool SizeChanged = false; if (NewSize > Size) { Size = NewSize; @@ -91,7 +91,7 @@ class AliasSet : public ilist_node<AliasSet> { return SizeChanged; } - uint64_t getSize() const { return Size; } + LocationSize getSize() const { return Size; } /// Return the AAInfo, or null if there is no information or conflicting /// information. @@ -247,7 +247,7 @@ public: value_type *operator->() const { return &operator*(); } Value *getPointer() const { return CurNode->getValue(); } - uint64_t getSize() const { return CurNode->getSize(); } + LocationSize getSize() const { return CurNode->getSize(); } AAMDNodes getAAInfo() const { return CurNode->getAAInfo(); } iterator& operator++() { // Preincrement @@ -287,9 +287,8 @@ private: void removeFromTracker(AliasSetTracker &AST); - void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size, - const AAMDNodes &AAInfo, - bool KnownMustAlias = false); + void addPointer(AliasSetTracker &AST, PointerRec &Entry, LocationSize Size, + const AAMDNodes &AAInfo, bool KnownMustAlias = false); void addUnknownInst(Instruction *I, AliasAnalysis &AA); void removeUnknownInst(AliasSetTracker &AST, Instruction *I) { @@ -309,8 +308,8 @@ private: public: /// Return true if the specified pointer "may" (or must) alias one of the /// members in the set. - bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo, - AliasAnalysis &AA) const; + bool aliasesPointer(const Value *Ptr, LocationSize Size, + const AAMDNodes &AAInfo, AliasAnalysis &AA) const; bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const; }; @@ -364,12 +363,12 @@ public: /// These methods return true if inserting the instruction resulted in the /// addition of a new alias set (i.e., the pointer did not alias anything). /// - void add(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo); // Add a loc. + void add(Value *Ptr, LocationSize Size, const AAMDNodes &AAInfo); // Add a loc void add(LoadInst *LI); void add(StoreInst *SI); void add(VAArgInst *VAAI); - void add(MemSetInst *MSI); - void add(MemTransferInst *MTI); + void add(AnyMemSetInst *MSI); + void add(AnyMemTransferInst *MTI); void add(Instruction *I); // Dispatch to one of the other add methods... void add(BasicBlock &BB); // Add all instructions in basic block void add(const AliasSetTracker &AST); // Add alias relations from another AST @@ -384,12 +383,12 @@ public: /// argument is non-null, this method sets the value to true if a new alias /// set is created to contain the pointer (because the pointer didn't alias /// anything). - AliasSet &getAliasSetForPointer(Value *P, uint64_t Size, + AliasSet &getAliasSetForPointer(Value *P, LocationSize Size, const AAMDNodes &AAInfo); /// Return the alias set containing the location specified if one exists, /// otherwise return null. - AliasSet *getAliasSetForPointerIfExists(const Value *P, uint64_t Size, + AliasSet *getAliasSetForPointerIfExists(const Value *P, LocationSize Size, const AAMDNodes &AAInfo) { return mergeAliasSetsForPointer(P, Size, AAInfo); } @@ -446,9 +445,9 @@ private: return *Entry; } - AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo, + AliasSet &addPointer(Value *P, LocationSize Size, const AAMDNodes &AAInfo, AliasSet::AccessLattice E); - AliasSet *mergeAliasSetsForPointer(const Value *Ptr, uint64_t Size, + AliasSet *mergeAliasSetsForPointer(const Value *Ptr, LocationSize Size, const AAMDNodes &AAInfo); /// Merge all alias sets into a single set that is considered to alias any diff --git a/contrib/llvm/include/llvm/Analysis/AssumptionCache.h b/contrib/llvm/include/llvm/Analysis/AssumptionCache.h index c965e62a0216..46538b1fa86f 100644 --- a/contrib/llvm/include/llvm/Analysis/AssumptionCache.h +++ b/contrib/llvm/include/llvm/Analysis/AssumptionCache.h @@ -32,20 +32,20 @@ class Function; class raw_ostream; class Value; -/// \brief A cache of @llvm.assume calls within a function. +/// A cache of \@llvm.assume calls within a function. /// /// This cache provides fast lookup of assumptions within a function by caching /// them and amortizing the cost of scanning for them across all queries. Passes /// that create new assumptions are required to call registerAssumption() to -/// register any new @llvm.assume calls that they create. Deletions of -/// @llvm.assume calls do not require special handling. +/// register any new \@llvm.assume calls that they create. Deletions of +/// \@llvm.assume calls do not require special handling. class AssumptionCache { - /// \brief The function for which this cache is handling assumptions. + /// The function for which this cache is handling assumptions. /// /// We track this to lazily populate our assumptions. Function &F; - /// \brief Vector of weak value handles to calls of the @llvm.assume + /// Vector of weak value handles to calls of the \@llvm.assume /// intrinsic. SmallVector<WeakTrackingVH, 4> AssumeHandles; @@ -64,7 +64,7 @@ class AssumptionCache { friend AffectedValueCallbackVH; - /// \brief A map of values about which an assumption might be providing + /// A map of values about which an assumption might be providing /// information to the relevant set of assumptions. using AffectedValuesMap = DenseMap<AffectedValueCallbackVH, SmallVector<WeakTrackingVH, 1>, @@ -77,17 +77,17 @@ class AssumptionCache { /// Copy affected values in the cache for OV to be affected values for NV. void copyAffectedValuesInCache(Value *OV, Value *NV); - /// \brief Flag tracking whether we have scanned the function yet. + /// Flag tracking whether we have scanned the function yet. /// /// We want to be as lazy about this as possible, and so we scan the function /// at the last moment. bool Scanned = false; - /// \brief Scan the function for assumptions and add them to the cache. + /// Scan the function for assumptions and add them to the cache. void scanFunction(); public: - /// \brief Construct an AssumptionCache from a function by scanning all of + /// Construct an AssumptionCache from a function by scanning all of /// its instructions. AssumptionCache(Function &F) : F(F) {} @@ -98,17 +98,17 @@ public: return false; } - /// \brief Add an @llvm.assume intrinsic to this function's cache. + /// Add an \@llvm.assume intrinsic to this function's cache. /// /// The call passed in must be an instruction within this function and must /// not already be in the cache. void registerAssumption(CallInst *CI); - /// \brief Update the cache of values being affected by this assumption (i.e. + /// Update the cache of values being affected by this assumption (i.e. /// the values about which this assumption provides information). void updateAffectedValues(CallInst *CI); - /// \brief Clear the cache of @llvm.assume intrinsics for a function. + /// Clear the cache of \@llvm.assume intrinsics for a function. /// /// It will be re-scanned the next time it is requested. void clear() { @@ -117,7 +117,7 @@ public: Scanned = false; } - /// \brief Access the list of assumption handles currently tracked for this + /// Access the list of assumption handles currently tracked for this /// function. /// /// Note that these produce weak handles that may be null. The caller must @@ -131,7 +131,7 @@ public: return AssumeHandles; } - /// \brief Access the list of assumptions which affect this value. + /// Access the list of assumptions which affect this value. MutableArrayRef<WeakTrackingVH> assumptionsFor(const Value *V) { if (!Scanned) scanFunction(); @@ -144,7 +144,7 @@ public: } }; -/// \brief A function analysis which provides an \c AssumptionCache. +/// A function analysis which provides an \c AssumptionCache. /// /// This analysis is intended for use with the new pass manager and will vend /// assumption caches for a given function. @@ -161,7 +161,7 @@ public: } }; -/// \brief Printer pass for the \c AssumptionAnalysis results. +/// Printer pass for the \c AssumptionAnalysis results. class AssumptionPrinterPass : public PassInfoMixin<AssumptionPrinterPass> { raw_ostream &OS; @@ -171,7 +171,7 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief An immutable pass that tracks lazily created \c AssumptionCache +/// An immutable pass that tracks lazily created \c AssumptionCache /// objects. /// /// This is essentially a workaround for the legacy pass manager's weaknesses @@ -203,7 +203,7 @@ class AssumptionCacheTracker : public ImmutablePass { FunctionCallsMap AssumptionCaches; public: - /// \brief Get the cached assumptions for a function. + /// Get the cached assumptions for a function. /// /// If no assumptions are cached, this will scan the function. Otherwise, the /// existing cache will be returned. diff --git a/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h index 42e5e9714071..fa81539a9d6f 100644 --- a/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/BasicAliasAnalysis.h @@ -55,26 +55,27 @@ class BasicAAResult : public AAResultBase<BasicAAResult> { friend AAResultBase<BasicAAResult>; const DataLayout &DL; + const Function &F; const TargetLibraryInfo &TLI; AssumptionCache &AC; DominatorTree *DT; LoopInfo *LI; public: - BasicAAResult(const DataLayout &DL, const TargetLibraryInfo &TLI, - AssumptionCache &AC, DominatorTree *DT = nullptr, - LoopInfo *LI = nullptr) - : AAResultBase(), DL(DL), TLI(TLI), AC(AC), DT(DT), LI(LI) {} + BasicAAResult(const DataLayout &DL, const Function &F, + const TargetLibraryInfo &TLI, AssumptionCache &AC, + DominatorTree *DT = nullptr, LoopInfo *LI = nullptr) + : AAResultBase(), DL(DL), F(F), TLI(TLI), AC(AC), DT(DT), LI(LI) {} BasicAAResult(const BasicAAResult &Arg) - : AAResultBase(Arg), DL(Arg.DL), TLI(Arg.TLI), AC(Arg.AC), DT(Arg.DT), - LI(Arg.LI) {} - BasicAAResult(BasicAAResult &&Arg) - : AAResultBase(std::move(Arg)), DL(Arg.DL), TLI(Arg.TLI), AC(Arg.AC), + : AAResultBase(Arg), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI), AC(Arg.AC), DT(Arg.DT), LI(Arg.LI) {} + BasicAAResult(BasicAAResult &&Arg) + : AAResultBase(std::move(Arg)), DL(Arg.DL), F(Arg.F), TLI(Arg.TLI), + AC(Arg.AC), DT(Arg.DT), LI(Arg.LI) {} /// Handle invalidation events in the new pass manager. - bool invalidate(Function &F, const PreservedAnalyses &PA, + bool invalidate(Function &Fn, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv); AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB); @@ -94,7 +95,7 @@ public: /// Returns the behavior when calling the given function. For use when the /// call site is not known. - FunctionModRefBehavior getModRefBehavior(const Function *F); + FunctionModRefBehavior getModRefBehavior(const Function *Fn); private: // A linear transformation of a Value; this class represents ZExt(SExt(V, @@ -171,9 +172,9 @@ private: static bool isGEPBaseAtNegativeOffset(const GEPOperator *GEPOp, const DecomposedGEP &DecompGEP, const DecomposedGEP &DecompObject, - uint64_t ObjectAccessSize); + LocationSize ObjectAccessSize); - /// \brief A Heuristic for aliasGEP that searches for a constant offset + /// A Heuristic for aliasGEP that searches for a constant offset /// between the variables. /// /// GetLinearExpression has some limitations, as generally zext(%x + 1) @@ -183,31 +184,33 @@ private: /// the addition overflows. bool constantOffsetHeuristic(const SmallVectorImpl<VariableGEPIndex> &VarIndices, - uint64_t V1Size, uint64_t V2Size, int64_t BaseOffset, - AssumptionCache *AC, DominatorTree *DT); + LocationSize V1Size, LocationSize V2Size, + int64_t BaseOffset, AssumptionCache *AC, + DominatorTree *DT); bool isValueEqualInPotentialCycles(const Value *V1, const Value *V2); void GetIndexDifference(SmallVectorImpl<VariableGEPIndex> &Dest, const SmallVectorImpl<VariableGEPIndex> &Src); - AliasResult aliasGEP(const GEPOperator *V1, uint64_t V1Size, + AliasResult aliasGEP(const GEPOperator *V1, LocationSize V1Size, const AAMDNodes &V1AAInfo, const Value *V2, - uint64_t V2Size, const AAMDNodes &V2AAInfo, + LocationSize V2Size, const AAMDNodes &V2AAInfo, const Value *UnderlyingV1, const Value *UnderlyingV2); - AliasResult aliasPHI(const PHINode *PN, uint64_t PNSize, + AliasResult aliasPHI(const PHINode *PN, LocationSize PNSize, const AAMDNodes &PNAAInfo, const Value *V2, - uint64_t V2Size, const AAMDNodes &V2AAInfo, + LocationSize V2Size, const AAMDNodes &V2AAInfo, const Value *UnderV2); - AliasResult aliasSelect(const SelectInst *SI, uint64_t SISize, + AliasResult aliasSelect(const SelectInst *SI, LocationSize SISize, const AAMDNodes &SIAAInfo, const Value *V2, - uint64_t V2Size, const AAMDNodes &V2AAInfo, + LocationSize V2Size, const AAMDNodes &V2AAInfo, const Value *UnderV2); - AliasResult aliasCheck(const Value *V1, uint64_t V1Size, AAMDNodes V1AATag, - const Value *V2, uint64_t V2Size, AAMDNodes V2AATag, + AliasResult aliasCheck(const Value *V1, LocationSize V1Size, + AAMDNodes V1AATag, const Value *V2, + LocationSize V2Size, AAMDNodes V2AATag, const Value *O1 = nullptr, const Value *O2 = nullptr); }; diff --git a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h index 89370cbeeea1..ca12db6208b8 100644 --- a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfo.h @@ -65,17 +65,17 @@ public: /// floating points. BlockFrequency getBlockFreq(const BasicBlock *BB) const; - /// \brief Returns the estimated profile count of \p BB. + /// Returns the estimated profile count of \p BB. /// This computes the relative block frequency of \p BB and multiplies it by /// the enclosing function's count (if available) and returns the value. Optional<uint64_t> getBlockProfileCount(const BasicBlock *BB) const; - /// \brief Returns the estimated profile count of \p Freq. + /// Returns the estimated profile count of \p Freq. /// This uses the frequency \p Freq and multiplies it by /// the enclosing function's count (if available) and returns the value. Optional<uint64_t> getProfileCountFromFreq(uint64_t Freq) const; - /// \brief Returns true if \p BB is an irreducible loop header + /// Returns true if \p BB is an irreducible loop header /// block. Otherwise false. bool isIrrLoopHeader(const BasicBlock *BB); @@ -105,7 +105,7 @@ public: void print(raw_ostream &OS) const; }; -/// \brief Analysis pass which computes \c BlockFrequencyInfo. +/// Analysis pass which computes \c BlockFrequencyInfo. class BlockFrequencyAnalysis : public AnalysisInfoMixin<BlockFrequencyAnalysis> { friend AnalysisInfoMixin<BlockFrequencyAnalysis>; @@ -113,14 +113,14 @@ class BlockFrequencyAnalysis static AnalysisKey Key; public: - /// \brief Provide the result type for this analysis pass. + /// Provide the result type for this analysis pass. using Result = BlockFrequencyInfo; - /// \brief Run the analysis pass over a function and produce BFI. + /// Run the analysis pass over a function and produce BFI. Result run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Printer pass for the \c BlockFrequencyInfo results. +/// Printer pass for the \c BlockFrequencyInfo results. class BlockFrequencyPrinterPass : public PassInfoMixin<BlockFrequencyPrinterPass> { raw_ostream &OS; @@ -131,7 +131,7 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Legacy analysis pass which computes \c BlockFrequencyInfo. +/// Legacy analysis pass which computes \c BlockFrequencyInfo. class BlockFrequencyInfoWrapperPass : public FunctionPass { BlockFrequencyInfo BFI; diff --git a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h index 40c40b80bc89..25b2efd33c98 100644 --- a/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/contrib/llvm/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -66,7 +66,7 @@ struct IrreducibleGraph; // This is part of a workaround for a GCC 4.7 crash on lambdas. template <class BT> struct BlockEdgesAdder; -/// \brief Mass of a block. +/// Mass of a block. /// /// This class implements a sort of fixed-point fraction always between 0.0 and /// 1.0. getMass() == std::numeric_limits<uint64_t>::max() indicates a value of @@ -100,7 +100,7 @@ public: bool operator!() const { return isEmpty(); } - /// \brief Add another mass. + /// Add another mass. /// /// Adds another mass, saturating at \a isFull() rather than overflowing. BlockMass &operator+=(BlockMass X) { @@ -109,7 +109,7 @@ public: return *this; } - /// \brief Subtract another mass. + /// Subtract another mass. /// /// Subtracts another mass, saturating at \a isEmpty() rather than /// undeflowing. @@ -131,7 +131,7 @@ public: bool operator<(BlockMass X) const { return Mass < X.Mass; } bool operator>(BlockMass X) const { return Mass > X.Mass; } - /// \brief Convert to scaled number. + /// Convert to scaled number. /// /// Convert to \a ScaledNumber. \a isFull() gives 1.0, while \a isEmpty() /// gives slightly above 0.0. @@ -164,7 +164,7 @@ template <> struct isPodLike<bfi_detail::BlockMass> { static const bool value = true; }; -/// \brief Base class for BlockFrequencyInfoImpl +/// Base class for BlockFrequencyInfoImpl /// /// BlockFrequencyInfoImplBase has supporting data structures and some /// algorithms for BlockFrequencyInfoImplBase. Only algorithms that depend on @@ -177,7 +177,7 @@ public: using Scaled64 = ScaledNumber<uint64_t>; using BlockMass = bfi_detail::BlockMass; - /// \brief Representative of a block. + /// Representative of a block. /// /// This is a simple wrapper around an index into the reverse-post-order /// traversal of the blocks. @@ -206,13 +206,13 @@ public: } }; - /// \brief Stats about a block itself. + /// Stats about a block itself. struct FrequencyData { Scaled64 Scaled; uint64_t Integer; }; - /// \brief Data about a loop. + /// Data about a loop. /// /// Contains the data necessary to represent a loop as a pseudo-node once it's /// packaged. @@ -270,7 +270,7 @@ public: } }; - /// \brief Index of loop information. + /// Index of loop information. struct WorkingData { BlockNode Node; ///< This node. LoopData *Loop = nullptr; ///< The loop this block is inside. @@ -293,7 +293,7 @@ public: return Loop->Parent->Parent; } - /// \brief Resolve a node to its representative. + /// Resolve a node to its representative. /// /// Get the node currently representing Node, which could be a containing /// loop. @@ -320,7 +320,7 @@ public: return L; } - /// \brief Get the appropriate mass for a node. + /// Get the appropriate mass for a node. /// /// Get appropriate mass for Node. If Node is a loop-header (whose loop /// has been packaged), returns the mass of its pseudo-node. If it's a @@ -333,19 +333,19 @@ public: return Loop->Parent->Mass; } - /// \brief Has ContainingLoop been packaged up? + /// Has ContainingLoop been packaged up? bool isPackaged() const { return getResolvedNode() != Node; } - /// \brief Has Loop been packaged up? + /// Has Loop been packaged up? bool isAPackage() const { return isLoopHeader() && Loop->IsPackaged; } - /// \brief Has Loop been packaged up twice? + /// Has Loop been packaged up twice? bool isADoublePackage() const { return isDoubleLoopHeader() && Loop->Parent->IsPackaged; } }; - /// \brief Unscaled probability weight. + /// Unscaled probability weight. /// /// Probability weight for an edge in the graph (including the /// successor/target node). @@ -369,7 +369,7 @@ public: : Type(Type), TargetNode(TargetNode), Amount(Amount) {} }; - /// \brief Distribution of unscaled probability weight. + /// Distribution of unscaled probability weight. /// /// Distribution of unscaled probability weight to a set of successors. /// @@ -398,7 +398,7 @@ public: add(Node, Amount, Weight::Backedge); } - /// \brief Normalize the distribution. + /// Normalize the distribution. /// /// Combines multiple edges to the same \a Weight::TargetNode and scales /// down so that \a Total fits into 32-bits. @@ -413,26 +413,26 @@ public: void add(const BlockNode &Node, uint64_t Amount, Weight::DistType Type); }; - /// \brief Data about each block. This is used downstream. + /// Data about each block. This is used downstream. std::vector<FrequencyData> Freqs; - /// \brief Whether each block is an irreducible loop header. + /// Whether each block is an irreducible loop header. /// This is used downstream. SparseBitVector<> IsIrrLoopHeader; - /// \brief Loop data: see initializeLoops(). + /// Loop data: see initializeLoops(). std::vector<WorkingData> Working; - /// \brief Indexed information about loops. + /// Indexed information about loops. std::list<LoopData> Loops; - /// \brief Virtual destructor. + /// Virtual destructor. /// /// Need a virtual destructor to mask the compiler warning about /// getBlockName(). virtual ~BlockFrequencyInfoImplBase() = default; - /// \brief Add all edges out of a packaged loop to the distribution. + /// Add all edges out of a packaged loop to the distribution. /// /// Adds all edges from LocalLoopHead to Dist. Calls addToDist() to add each /// successor edge. @@ -441,7 +441,7 @@ public: bool addLoopSuccessorsToDist(const LoopData *OuterLoop, LoopData &Loop, Distribution &Dist); - /// \brief Add an edge to the distribution. + /// Add an edge to the distribution. /// /// Adds an edge to Succ to Dist. If \c LoopHead.isValid(), then whether the /// edge is local/exit/backedge is in the context of LoopHead. Otherwise, @@ -457,7 +457,7 @@ public: return *Working[Head.Index].Loop; } - /// \brief Analyze irreducible SCCs. + /// Analyze irreducible SCCs. /// /// Separate irreducible SCCs from \c G, which is an explict graph of \c /// OuterLoop (or the top-level function, if \c OuterLoop is \c nullptr). @@ -468,7 +468,7 @@ public: analyzeIrreducible(const bfi_detail::IrreducibleGraph &G, LoopData *OuterLoop, std::list<LoopData>::iterator Insert); - /// \brief Update a loop after packaging irreducible SCCs inside of it. + /// Update a loop after packaging irreducible SCCs inside of it. /// /// Update \c OuterLoop. Before finding irreducible control flow, it was /// partway through \a computeMassInLoop(), so \a LoopData::Exits and \a @@ -476,7 +476,7 @@ public: /// up need to be removed from \a OuterLoop::Nodes. void updateLoopWithIrreducible(LoopData &OuterLoop); - /// \brief Distribute mass according to a distribution. + /// Distribute mass according to a distribution. /// /// Distributes the mass in Source according to Dist. If LoopHead.isValid(), /// backedges and exits are stored in its entry in Loops. @@ -485,7 +485,7 @@ public: void distributeMass(const BlockNode &Source, LoopData *OuterLoop, Distribution &Dist); - /// \brief Compute the loop scale for a loop. + /// Compute the loop scale for a loop. void computeLoopScale(LoopData &Loop); /// Adjust the mass of all headers in an irreducible loop. @@ -500,19 +500,19 @@ public: void distributeIrrLoopHeaderMass(Distribution &Dist); - /// \brief Package up a loop. + /// Package up a loop. void packageLoop(LoopData &Loop); - /// \brief Unwrap loops. + /// Unwrap loops. void unwrapLoops(); - /// \brief Finalize frequency metrics. + /// Finalize frequency metrics. /// /// Calculates final frequencies and cleans up no-longer-needed data /// structures. void finalizeMetrics(); - /// \brief Clear all memory. + /// Clear all memory. void clear(); virtual std::string getBlockName(const BlockNode &Node) const; @@ -560,7 +560,7 @@ template <> struct TypeMap<MachineBasicBlock> { using LoopInfoT = MachineLoopInfo; }; -/// \brief Get the name of a MachineBasicBlock. +/// Get the name of a MachineBasicBlock. /// /// Get the name of a MachineBasicBlock. It's templated so that including from /// CodeGen is unnecessary (that would be a layering issue). @@ -574,13 +574,13 @@ template <class BlockT> std::string getBlockName(const BlockT *BB) { return (MachineName + "[" + BB->getName() + "]").str(); return MachineName.str(); } -/// \brief Get the name of a BasicBlock. +/// Get the name of a BasicBlock. template <> inline std::string getBlockName(const BasicBlock *BB) { assert(BB && "Unexpected nullptr"); return BB->getName().str(); } -/// \brief Graph of irreducible control flow. +/// Graph of irreducible control flow. /// /// This graph is used for determining the SCCs in a loop (or top-level /// function) that has irreducible control flow. @@ -619,7 +619,7 @@ struct IrreducibleGraph { std::vector<IrrNode> Nodes; SmallDenseMap<uint32_t, IrrNode *, 4> Lookup; - /// \brief Construct an explicit graph containing irreducible control flow. + /// Construct an explicit graph containing irreducible control flow. /// /// Construct an explicit graph of the control flow in \c OuterLoop (or the /// top-level function, if \c OuterLoop is \c nullptr). Uses \c @@ -687,7 +687,7 @@ void IrreducibleGraph::addEdges(const BlockNode &Node, } // end namespace bfi_detail -/// \brief Shared implementation for block frequency analysis. +/// Shared implementation for block frequency analysis. /// /// This is a shared implementation of BlockFrequencyInfo and /// MachineBlockFrequencyInfo, and calculates the relative frequencies of @@ -878,12 +878,12 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { return RPOT[Node.Index]; } - /// \brief Run (and save) a post-order traversal. + /// Run (and save) a post-order traversal. /// /// Saves a reverse post-order traversal of all the nodes in \a F. void initializeRPOT(); - /// \brief Initialize loop data. + /// Initialize loop data. /// /// Build up \a Loops using \a LoopInfo. \a LoopInfo gives us a mapping from /// each block to the deepest loop it's in, but we need the inverse. For each @@ -892,7 +892,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { /// the loop that are not in sub-loops. void initializeLoops(); - /// \brief Propagate to a block's successors. + /// Propagate to a block's successors. /// /// In the context of distributing mass through \c OuterLoop, divide the mass /// currently assigned to \c Node between its successors. @@ -900,7 +900,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { /// \return \c true unless there's an irreducible backedge. bool propagateMassToSuccessors(LoopData *OuterLoop, const BlockNode &Node); - /// \brief Compute mass in a particular loop. + /// Compute mass in a particular loop. /// /// Assign mass to \c Loop's header, and then for each block in \c Loop in /// reverse post-order, distribute mass to its successors. Only visits nodes @@ -910,7 +910,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { /// \return \c true unless there's an irreducible backedge. bool computeMassInLoop(LoopData &Loop); - /// \brief Try to compute mass in the top-level function. + /// Try to compute mass in the top-level function. /// /// Assign mass to the entry block, and then for each block in reverse /// post-order, distribute mass to its successors. Skips nodes that have @@ -920,7 +920,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { /// \return \c true unless there's an irreducible backedge. bool tryToComputeMassInFunction(); - /// \brief Compute mass in (and package up) irreducible SCCs. + /// Compute mass in (and package up) irreducible SCCs. /// /// Find the irreducible SCCs in \c OuterLoop, add them to \a Loops (in front /// of \c Insert), and call \a computeMassInLoop() on each of them. @@ -935,7 +935,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { void computeIrreducibleMass(LoopData *OuterLoop, std::list<LoopData>::iterator Insert); - /// \brief Compute mass in all loops. + /// Compute mass in all loops. /// /// For each loop bottom-up, call \a computeMassInLoop(). /// @@ -946,7 +946,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { /// \post \a computeMassInLoop() has returned \c true for every loop. void computeMassInLoops(); - /// \brief Compute mass in the top-level function. + /// Compute mass in the top-level function. /// /// Uses \a tryToComputeMassInFunction() and \a computeIrreducibleMass() to /// compute mass in the top-level function. @@ -994,7 +994,7 @@ public: const BranchProbabilityInfoT &getBPI() const { return *BPI; } - /// \brief Print the frequencies for the current function. + /// Print the frequencies for the current function. /// /// Prints the frequencies for the blocks in the current function. /// @@ -1030,8 +1030,9 @@ void BlockFrequencyInfoImpl<BT>::calculate(const FunctionT &F, Nodes.clear(); // Initialize. - DEBUG(dbgs() << "\nblock-frequency: " << F.getName() << "\n=================" - << std::string(F.getName().size(), '=') << "\n"); + LLVM_DEBUG(dbgs() << "\nblock-frequency: " << F.getName() + << "\n=================" + << std::string(F.getName().size(), '=') << "\n"); initializeRPOT(); initializeLoops(); @@ -1067,10 +1068,11 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::initializeRPOT() { assert(RPOT.size() - 1 <= BlockNode::getMaxIndex() && "More nodes in function than Block Frequency Info supports"); - DEBUG(dbgs() << "reverse-post-order-traversal\n"); + LLVM_DEBUG(dbgs() << "reverse-post-order-traversal\n"); for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) { BlockNode Node = getNode(I); - DEBUG(dbgs() << " - " << getIndex(I) << ": " << getBlockName(Node) << "\n"); + LLVM_DEBUG(dbgs() << " - " << getIndex(I) << ": " << getBlockName(Node) + << "\n"); Nodes[*I] = Node; } @@ -1081,7 +1083,7 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::initializeRPOT() { } template <class BT> void BlockFrequencyInfoImpl<BT>::initializeLoops() { - DEBUG(dbgs() << "loop-detection\n"); + LLVM_DEBUG(dbgs() << "loop-detection\n"); if (LI->empty()) return; @@ -1099,7 +1101,7 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::initializeLoops() { Loops.emplace_back(Parent, Header); Working[Header.Index].Loop = &Loops.back(); - DEBUG(dbgs() << " - loop = " << getBlockName(Header) << "\n"); + LLVM_DEBUG(dbgs() << " - loop = " << getBlockName(Header) << "\n"); for (const LoopT *L : *Loop) Q.emplace_back(L, &Loops.back()); @@ -1128,8 +1130,8 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::initializeLoops() { Working[Index].Loop = HeaderData.Loop; HeaderData.Loop->Nodes.push_back(Index); - DEBUG(dbgs() << " - loop = " << getBlockName(Header) - << ": member = " << getBlockName(Index) << "\n"); + LLVM_DEBUG(dbgs() << " - loop = " << getBlockName(Header) + << ": member = " << getBlockName(Index) << "\n"); } } @@ -1150,10 +1152,10 @@ template <class BT> void BlockFrequencyInfoImpl<BT>::computeMassInLoops() { template <class BT> bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) { // Compute mass in loop. - DEBUG(dbgs() << "compute-mass-in-loop: " << getLoopName(Loop) << "\n"); + LLVM_DEBUG(dbgs() << "compute-mass-in-loop: " << getLoopName(Loop) << "\n"); if (Loop.isIrreducible()) { - DEBUG(dbgs() << "isIrreducible = true\n"); + LLVM_DEBUG(dbgs() << "isIrreducible = true\n"); Distribution Dist; unsigned NumHeadersWithWeight = 0; Optional<uint64_t> MinHeaderWeight; @@ -1165,14 +1167,14 @@ bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) { IsIrrLoopHeader.set(Loop.Nodes[H].Index); Optional<uint64_t> HeaderWeight = Block->getIrrLoopHeaderWeight(); if (!HeaderWeight) { - DEBUG(dbgs() << "Missing irr loop header metadata on " - << getBlockName(HeaderNode) << "\n"); + LLVM_DEBUG(dbgs() << "Missing irr loop header metadata on " + << getBlockName(HeaderNode) << "\n"); HeadersWithoutWeight.insert(H); continue; } - DEBUG(dbgs() << getBlockName(HeaderNode) - << " has irr loop header weight " << HeaderWeight.getValue() - << "\n"); + LLVM_DEBUG(dbgs() << getBlockName(HeaderNode) + << " has irr loop header weight " + << HeaderWeight.getValue() << "\n"); NumHeadersWithWeight++; uint64_t HeaderWeightValue = HeaderWeight.getValue(); if (!MinHeaderWeight || HeaderWeightValue < MinHeaderWeight) @@ -1194,8 +1196,8 @@ bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) { assert(!getBlock(HeaderNode)->getIrrLoopHeaderWeight() && "Shouldn't have a weight metadata"); uint64_t MinWeight = MinHeaderWeight.getValue(); - DEBUG(dbgs() << "Giving weight " << MinWeight - << " to " << getBlockName(HeaderNode) << "\n"); + LLVM_DEBUG(dbgs() << "Giving weight " << MinWeight << " to " + << getBlockName(HeaderNode) << "\n"); if (MinWeight) Dist.addLocal(HeaderNode, MinWeight); } @@ -1224,7 +1226,7 @@ bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) { template <class BT> bool BlockFrequencyInfoImpl<BT>::tryToComputeMassInFunction() { // Compute mass in function. - DEBUG(dbgs() << "compute-mass-in-function\n"); + LLVM_DEBUG(dbgs() << "compute-mass-in-function\n"); assert(!Working.empty() && "no blocks in function"); assert(!Working[0].isLoopHeader() && "entry block is a loop header"); @@ -1276,9 +1278,10 @@ template <class BT> struct BlockEdgesAdder { template <class BT> void BlockFrequencyInfoImpl<BT>::computeIrreducibleMass( LoopData *OuterLoop, std::list<LoopData>::iterator Insert) { - DEBUG(dbgs() << "analyze-irreducible-in-"; - if (OuterLoop) dbgs() << "loop: " << getLoopName(*OuterLoop) << "\n"; - else dbgs() << "function\n"); + LLVM_DEBUG(dbgs() << "analyze-irreducible-in-"; + if (OuterLoop) dbgs() + << "loop: " << getLoopName(*OuterLoop) << "\n"; + else dbgs() << "function\n"); using namespace bfi_detail; @@ -1304,7 +1307,7 @@ template <class BT> bool BlockFrequencyInfoImpl<BT>::propagateMassToSuccessors(LoopData *OuterLoop, const BlockNode &Node) { - DEBUG(dbgs() << " - node: " << getBlockName(Node) << "\n"); + LLVM_DEBUG(dbgs() << " - node: " << getBlockName(Node) << "\n"); // Calculate probability for successors. Distribution Dist; if (auto *Loop = Working[Node.Index].getPackagedLoop()) { diff --git a/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h b/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h index 417b64978811..45277db46090 100644 --- a/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/contrib/llvm/include/llvm/Analysis/BranchProbabilityInfo.h @@ -38,7 +38,7 @@ class raw_ostream; class TargetLibraryInfo; class Value; -/// \brief Analysis providing branch probability information. +/// Analysis providing branch probability information. /// /// This is a function analysis which provides information on the relative /// probabilities of each "edge" in the function's CFG where such an edge is @@ -79,7 +79,7 @@ public: void print(raw_ostream &OS) const; - /// \brief Get an edge's probability, relative to other out-edges of the Src. + /// Get an edge's probability, relative to other out-edges of the Src. /// /// This routine provides access to the fractional probability between zero /// (0%) and one (100%) of this edge executing, relative to other edges @@ -88,7 +88,7 @@ public: BranchProbability getEdgeProbability(const BasicBlock *Src, unsigned IndexInSuccessors) const; - /// \brief Get the probability of going from Src to Dst. + /// Get the probability of going from Src to Dst. /// /// It returns the sum of all probabilities for edges from Src to Dst. BranchProbability getEdgeProbability(const BasicBlock *Src, @@ -97,19 +97,19 @@ public: BranchProbability getEdgeProbability(const BasicBlock *Src, succ_const_iterator Dst) const; - /// \brief Test if an edge is hot relative to other out-edges of the Src. + /// Test if an edge is hot relative to other out-edges of the Src. /// /// Check whether this edge out of the source block is 'hot'. We define hot /// as having a relative probability >= 80%. bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const; - /// \brief Retrieve the hot successor of a block if one exists. + /// Retrieve the hot successor of a block if one exists. /// /// Given a basic block, look through its successors and if one exists for /// which \see isEdgeHot would return true, return that successor block. const BasicBlock *getHotSucc(const BasicBlock *BB) const; - /// \brief Print an edge's probability. + /// Print an edge's probability. /// /// Retrieves an edge's probability similarly to \see getEdgeProbability, but /// then prints that probability to the provided stream. That stream is then @@ -117,7 +117,7 @@ public: raw_ostream &printEdgeProbability(raw_ostream &OS, const BasicBlock *Src, const BasicBlock *Dst) const; - /// \brief Set the raw edge probability for the given edge. + /// Set the raw edge probability for the given edge. /// /// This allows a pass to explicitly set the edge probability for an edge. It /// can be used when updating the CFG to update and preserve the branch @@ -179,13 +179,13 @@ private: DenseMap<Edge, BranchProbability> Probs; - /// \brief Track the last function we run over for printing. + /// Track the last function we run over for printing. const Function *LastF; - /// \brief Track the set of blocks directly succeeded by a returning block. + /// Track the set of blocks directly succeeded by a returning block. SmallPtrSet<const BasicBlock *, 16> PostDominatedByUnreachable; - /// \brief Track the set of blocks that always lead to a cold call. + /// Track the set of blocks that always lead to a cold call. SmallPtrSet<const BasicBlock *, 16> PostDominatedByColdCall; void updatePostDominatedByUnreachable(const BasicBlock *BB); @@ -201,7 +201,7 @@ private: bool calcInvokeHeuristics(const BasicBlock *BB); }; -/// \brief Analysis pass which computes \c BranchProbabilityInfo. +/// Analysis pass which computes \c BranchProbabilityInfo. class BranchProbabilityAnalysis : public AnalysisInfoMixin<BranchProbabilityAnalysis> { friend AnalysisInfoMixin<BranchProbabilityAnalysis>; @@ -209,14 +209,14 @@ class BranchProbabilityAnalysis static AnalysisKey Key; public: - /// \brief Provide the result type for this analysis pass. + /// Provide the result type for this analysis pass. using Result = BranchProbabilityInfo; - /// \brief Run the analysis pass over a function and produce BPI. + /// Run the analysis pass over a function and produce BPI. BranchProbabilityInfo run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Printer pass for the \c BranchProbabilityAnalysis results. +/// Printer pass for the \c BranchProbabilityAnalysis results. class BranchProbabilityPrinterPass : public PassInfoMixin<BranchProbabilityPrinterPass> { raw_ostream &OS; @@ -227,7 +227,7 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Legacy analysis pass which computes \c BranchProbabilityInfo. +/// Legacy analysis pass which computes \c BranchProbabilityInfo. class BranchProbabilityInfoWrapperPass : public FunctionPass { BranchProbabilityInfo BPI; diff --git a/contrib/llvm/include/llvm/Analysis/CFG.h b/contrib/llvm/include/llvm/Analysis/CFG.h index eab64176f0d7..cccdd1637411 100644 --- a/contrib/llvm/include/llvm/Analysis/CFG.h +++ b/contrib/llvm/include/llvm/Analysis/CFG.h @@ -49,7 +49,7 @@ unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ); bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, bool AllowIdenticalEdges = false); -/// \brief Determine whether instruction 'To' is reachable from 'From', +/// Determine whether instruction 'To' is reachable from 'From', /// returning true if uncertain. /// /// Determine whether there is a path from From to To within a single function. @@ -68,7 +68,7 @@ bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr); -/// \brief Determine whether block 'To' is reachable from 'From', returning +/// Determine whether block 'To' is reachable from 'From', returning /// true if uncertain. /// /// Determine whether there is a path from From to To within a single function. @@ -78,7 +78,7 @@ bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To, const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr); -/// \brief Determine whether there is at least one path from a block in +/// Determine whether there is at least one path from a block in /// 'Worklist' to 'StopBB', returning true if uncertain. /// /// Determine whether there is a path from at least one block in Worklist to @@ -89,6 +89,73 @@ bool isPotentiallyReachableFromMany(SmallVectorImpl<BasicBlock *> &Worklist, BasicBlock *StopBB, const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr); + +/// Return true if the control flow in \p RPOTraversal is irreducible. +/// +/// This is a generic implementation to detect CFG irreducibility based on loop +/// info analysis. It can be used for any kind of CFG (Loop, MachineLoop, +/// Function, MachineFunction, etc.) by providing an RPO traversal (\p +/// RPOTraversal) and the loop info analysis (\p LI) of the CFG. This utility +/// function is only recommended when loop info analysis is available. If loop +/// info analysis isn't available, please, don't compute it explicitly for this +/// purpose. There are more efficient ways to detect CFG irreducibility that +/// don't require recomputing loop info analysis (e.g., T1/T2 or Tarjan's +/// algorithm). +/// +/// Requirements: +/// 1) GraphTraits must be implemented for NodeT type. It is used to access +/// NodeT successors. +// 2) \p RPOTraversal must be a valid reverse post-order traversal of the +/// target CFG with begin()/end() iterator interfaces. +/// 3) \p LI must be a valid LoopInfoBase that contains up-to-date loop +/// analysis information of the CFG. +/// +/// This algorithm uses the information about reducible loop back-edges already +/// computed in \p LI. When a back-edge is found during the RPO traversal, the +/// algorithm checks whether the back-edge is one of the reducible back-edges in +/// loop info. If it isn't, the CFG is irreducible. For example, for the CFG +/// below (canonical irreducible graph) loop info won't contain any loop, so the +/// algorithm will return that the CFG is irreducible when checking the B <- +/// -> C back-edge. +/// +/// (A->B, A->C, B->C, C->B, C->D) +/// A +/// / \ +/// B<- ->C +/// | +/// D +/// +template <class NodeT, class RPOTraversalT, class LoopInfoT, + class GT = GraphTraits<NodeT>> +bool containsIrreducibleCFG(RPOTraversalT &RPOTraversal, const LoopInfoT &LI) { + /// Check whether the edge (\p Src, \p Dst) is a reducible loop backedge + /// according to LI. I.e., check if there exists a loop that contains Src and + /// where Dst is the loop header. + auto isProperBackedge = [&](NodeT Src, NodeT Dst) { + for (const auto *Lp = LI.getLoopFor(Src); Lp; Lp = Lp->getParentLoop()) { + if (Lp->getHeader() == Dst) + return true; + } + return false; + }; + + SmallPtrSet<NodeT, 32> Visited; + for (NodeT Node : RPOTraversal) { + Visited.insert(Node); + for (NodeT Succ : make_range(GT::child_begin(Node), GT::child_end(Node))) { + // Succ hasn't been visited yet + if (!Visited.count(Succ)) + continue; + // We already visited Succ, thus Node->Succ must be a backedge. Check that + // the head matches what we have in the loop information. Otherwise, we + // have an irreducible graph. + if (!isProperBackedge(Node, Succ)) + return true; + } + } + + return false; +} } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h index 6239d5309581..8ae72553ab94 100644 --- a/contrib/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/CFLAndersAliasAnalysis.h @@ -56,7 +56,7 @@ public: /// Evict the given function from cache void evict(const Function *Fn); - /// \brief Get the alias summary for the given function + /// Get the alias summary for the given function /// Return nullptr if the summary is not found or not available const cflaa::AliasSummary *getAliasSummary(const Function &); @@ -64,19 +64,19 @@ public: AliasResult alias(const MemoryLocation &, const MemoryLocation &); private: - /// \brief Ensures that the given function is available in the cache. + /// Ensures that the given function is available in the cache. /// Returns the appropriate entry from the cache. const Optional<FunctionInfo> &ensureCached(const Function &); - /// \brief Inserts the given Function into the cache. + /// Inserts the given Function into the cache. void scan(const Function &); - /// \brief Build summary for a given function + /// Build summary for a given function FunctionInfo buildInfoFrom(const Function &); const TargetLibraryInfo &TLI; - /// \brief Cached mapping of Functions to their StratifiedSets. + /// Cached mapping of Functions to their StratifiedSets. /// If a function's sets are currently being built, it is marked /// in the cache as an Optional without a value. This way, if we /// have any kind of recursion, it is discernable from a function diff --git a/contrib/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h index ee9e29046af8..09e366f11e18 100644 --- a/contrib/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/CFLSteensAliasAnalysis.h @@ -55,16 +55,16 @@ public: return false; } - /// \brief Inserts the given Function into the cache. + /// Inserts the given Function into the cache. void scan(Function *Fn); void evict(Function *Fn); - /// \brief Ensures that the given function is available in the cache. + /// Ensures that the given function is available in the cache. /// Returns the appropriate entry from the cache. const Optional<FunctionInfo> &ensureCached(Function *Fn); - /// \brief Get the alias summary for the given function + /// Get the alias summary for the given function /// Return nullptr if the summary is not found or not available const cflaa::AliasSummary *getAliasSummary(Function &Fn); @@ -92,7 +92,7 @@ public: private: const TargetLibraryInfo &TLI; - /// \brief Cached mapping of Functions to their StratifiedSets. + /// Cached mapping of Functions to their StratifiedSets. /// If a function's sets are currently being built, it is marked /// in the cache as an Optional without a value. This way, if we /// have any kind of recursion, it is discernable from a function diff --git a/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h b/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h index 8123cbad22ff..5e83ea2a6e2b 100644 --- a/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h +++ b/contrib/llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -119,7 +119,7 @@ extern template class AllAnalysesOn<LazyCallGraph::SCC>; extern template class AnalysisManager<LazyCallGraph::SCC, LazyCallGraph &>; -/// \brief The CGSCC analysis manager. +/// The CGSCC analysis manager. /// /// See the documentation for the AnalysisManager template for detail /// documentation. This type serves as a convenient way to refer to this @@ -140,7 +140,7 @@ PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, extern template class PassManager<LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, CGSCCUpdateResult &>; -/// \brief The CGSCC pass manager. +/// The CGSCC pass manager. /// /// See the documentation for the PassManager template for details. It runs /// a sequence of SCC passes over each SCC that the manager is run over. This @@ -175,10 +175,10 @@ public: explicit Result(CGSCCAnalysisManager &InnerAM, LazyCallGraph &G) : InnerAM(&InnerAM), G(&G) {} - /// \brief Accessor for the analysis manager. + /// Accessor for the analysis manager. CGSCCAnalysisManager &getManager() { return *InnerAM; } - /// \brief Handler for invalidation of the Module. + /// Handler for invalidation of the Module. /// /// If the proxy analysis itself is preserved, then we assume that the set of /// SCCs in the Module hasn't changed. Thus any pointers to SCCs in the @@ -302,7 +302,7 @@ struct CGSCCUpdateResult { &InlinedInternalEdges; }; -/// \brief The core module pass which does a post-order walk of the SCCs and +/// The core module pass which does a post-order walk of the SCCs and /// runs a CGSCC pass over each one. /// /// Designed to allow composition of a CGSCCPass(Manager) and @@ -338,7 +338,7 @@ public: return *this; } - /// \brief Runs the CGSCC pass across every SCC in the module. + /// Runs the CGSCC pass across every SCC in the module. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { // Setup the CGSCC analysis manager from its proxy. CGSCCAnalysisManager &CGAM = @@ -387,17 +387,17 @@ public: do { LazyCallGraph::RefSCC *RC = RCWorklist.pop_back_val(); if (InvalidRefSCCSet.count(RC)) { - DEBUG(dbgs() << "Skipping an invalid RefSCC...\n"); + LLVM_DEBUG(dbgs() << "Skipping an invalid RefSCC...\n"); continue; } assert(CWorklist.empty() && "Should always start with an empty SCC worklist"); - DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC - << "\n"); + LLVM_DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC + << "\n"); - // Push the initial SCCs in reverse post-order as we'll pop off the the + // Push the initial SCCs in reverse post-order as we'll pop off the // back and so see this in post-order. for (LazyCallGraph::SCC &C : llvm::reverse(*RC)) CWorklist.insert(&C); @@ -409,12 +409,13 @@ public: // other RefSCCs should be queued above, so we just need to skip both // scenarios here. if (InvalidSCCSet.count(C)) { - DEBUG(dbgs() << "Skipping an invalid SCC...\n"); + LLVM_DEBUG(dbgs() << "Skipping an invalid SCC...\n"); continue; } if (&C->getOuterRefSCC() != RC) { - DEBUG(dbgs() << "Skipping an SCC that is now part of some other " - "RefSCC...\n"); + LLVM_DEBUG(dbgs() + << "Skipping an SCC that is now part of some other " + "RefSCC...\n"); continue; } @@ -436,7 +437,8 @@ public: // If the CGSCC pass wasn't able to provide a valid updated SCC, // the current SCC may simply need to be skipped if invalid. if (UR.InvalidatedSCCs.count(C)) { - DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n"); + LLVM_DEBUG(dbgs() + << "Skipping invalidated root or island SCC!\n"); break; } // Check that we didn't miss any update scenario. @@ -464,9 +466,10 @@ public: // FIXME: If we ever start having RefSCC passes, we'll want to // iterate there too. if (UR.UpdatedC) - DEBUG(dbgs() << "Re-running SCC passes after a refinement of the " - "current SCC: " - << *UR.UpdatedC << "\n"); + LLVM_DEBUG(dbgs() + << "Re-running SCC passes after a refinement of the " + "current SCC: " + << *UR.UpdatedC << "\n"); // Note that both `C` and `RC` may at this point refer to deleted, // invalid SCC and RefSCCs respectively. But we will short circuit @@ -494,7 +497,7 @@ private: CGSCCPassT Pass; }; -/// \brief A function to deduce a function pass type and wrap it in the +/// A function to deduce a function pass type and wrap it in the /// templated adaptor. template <typename CGSCCPassT> ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT> @@ -517,7 +520,7 @@ public: public: explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {} - /// \brief Accessor for the analysis manager. + /// Accessor for the analysis manager. FunctionAnalysisManager &getManager() { return *FAM; } bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA, @@ -552,7 +555,7 @@ LazyCallGraph::SCC &updateCGAndAnalysisManagerForFunctionPass( LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR); -/// \brief Adaptor that maps from a SCC to its functions. +/// Adaptor that maps from a SCC to its functions. /// /// Designed to allow composition of a FunctionPass(Manager) and /// a CGSCCPassManager. Note that if this pass is constructed with a pointer @@ -585,7 +588,7 @@ public: return *this; } - /// \brief Runs the function pass across every function in the module. + /// Runs the function pass across every function in the module. PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR) { // Setup the function analysis manager from its proxy. @@ -601,7 +604,8 @@ public: // a pointer we can overwrite. LazyCallGraph::SCC *CurrentC = &C; - DEBUG(dbgs() << "Running function passes across an SCC: " << C << "\n"); + LLVM_DEBUG(dbgs() << "Running function passes across an SCC: " << C + << "\n"); PreservedAnalyses PA = PreservedAnalyses::all(); for (LazyCallGraph::Node *N : Nodes) { @@ -652,7 +656,7 @@ private: FunctionPassT Pass; }; -/// \brief A function to deduce a function pass type and wrap it in the +/// A function to deduce a function pass type and wrap it in the /// templated adaptor. template <typename FunctionPassT> CGSCCToFunctionPassAdaptor<FunctionPassT> @@ -757,9 +761,9 @@ public: if (!F) return false; - DEBUG(dbgs() << "Found devirutalized call from " - << CS.getParent()->getParent()->getName() << " to " - << F->getName() << "\n"); + LLVM_DEBUG(dbgs() << "Found devirutalized call from " + << CS.getParent()->getParent()->getName() << " to " + << F->getName() << "\n"); // We now have a direct call where previously we had an indirect call, // so iterate to process this devirtualization site. @@ -793,16 +797,18 @@ public: // Otherwise, if we've already hit our max, we're done. if (Iteration >= MaxIterations) { - DEBUG(dbgs() << "Found another devirtualization after hitting the max " - "number of repetitions (" - << MaxIterations << ") on SCC: " << *C << "\n"); + LLVM_DEBUG( + dbgs() << "Found another devirtualization after hitting the max " + "number of repetitions (" + << MaxIterations << ") on SCC: " << *C << "\n"); PA.intersect(std::move(PassPA)); break; } - DEBUG(dbgs() - << "Repeating an SCC pass after finding a devirtualization in: " - << *C << "\n"); + LLVM_DEBUG( + dbgs() + << "Repeating an SCC pass after finding a devirtualization in: " << *C + << "\n"); // Move over the new call counts in preparation for iterating. CallCounts = std::move(NewCallCounts); @@ -824,7 +830,7 @@ private: int MaxIterations; }; -/// \brief A function to deduce a function pass type and wrap it in the +/// A function to deduce a function pass type and wrap it in the /// templated adaptor. template <typename PassT> DevirtSCCRepeatedPass<PassT> createDevirtSCCRepeatedPass(PassT Pass, diff --git a/contrib/llvm/include/llvm/Analysis/CallGraph.h b/contrib/llvm/include/llvm/Analysis/CallGraph.h index c5687def3ebe..f109cf2fac4d 100644 --- a/contrib/llvm/include/llvm/Analysis/CallGraph.h +++ b/contrib/llvm/include/llvm/Analysis/CallGraph.h @@ -66,7 +66,7 @@ class CallGraphNode; class Module; class raw_ostream; -/// \brief The basic data container for the call graph of a \c Module of IR. +/// 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. /// @@ -77,25 +77,25 @@ class CallGraph { using FunctionMapTy = std::map<const Function *, std::unique_ptr<CallGraphNode>>; - /// \brief A map from \c Function* to \c CallGraphNode*. + /// A map from \c Function* to \c CallGraphNode*. FunctionMapTy FunctionMap; - /// \brief This node has edges to all external functions and those internal + /// This node has edges to all external functions and those internal /// functions that have their address taken. CallGraphNode *ExternalCallingNode; - /// \brief This node has edges to it from all functions making indirect calls + /// This node has edges to it from all functions making indirect calls /// or calling an external function. std::unique_ptr<CallGraphNode> CallsExternalNode; - /// \brief Replace the function represented by this node by another. + /// 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); - /// \brief Add a function to the call graph, and link the node to all of the + /// Add a function to the call graph, and link the node to all of the /// functions that it calls. void addToCallGraph(Function *F); @@ -110,7 +110,7 @@ public: using iterator = FunctionMapTy::iterator; using const_iterator = FunctionMapTy::const_iterator; - /// \brief Returns the module the call graph corresponds to. + /// Returns the module the call graph corresponds to. Module &getModule() const { return M; } inline iterator begin() { return FunctionMap.begin(); } @@ -118,21 +118,21 @@ public: inline const_iterator begin() const { return FunctionMap.begin(); } inline const_iterator end() const { return FunctionMap.end(); } - /// \brief Returns the call graph node for the provided function. + /// 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.get(); } - /// \brief Returns the call graph node for the provided function. + /// 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.get(); } - /// \brief Returns the \c CallGraphNode which is used to represent + /// Returns the \c CallGraphNode which is used to represent /// undetermined calls into the callgraph. CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; } @@ -145,7 +145,7 @@ public: // modified. // - /// \brief Unlink the function from this module, returning it. + /// 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 @@ -153,25 +153,25 @@ public: /// this is to dropAllReferences before calling this. Function *removeFunctionFromModule(CallGraphNode *CGN); - /// \brief Similar to operator[], but this will insert a new CallGraphNode for + /// Similar to operator[], but this will insert a new CallGraphNode for /// \c F if one does not already exist. CallGraphNode *getOrInsertFunction(const Function *F); }; -/// \brief A node in the call graph for a module. +/// 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 { public: - /// \brief A pair of the calling instruction (a call or invoke) + /// A pair of the calling instruction (a call or invoke) /// and the call graph node being called. using CallRecord = std::pair<WeakTrackingVH, CallGraphNode *>; public: using CalledFunctionsVector = std::vector<CallRecord>; - /// \brief Creates a node for the specified function. + /// Creates a node for the specified function. inline CallGraphNode(Function *F) : F(F) {} CallGraphNode(const CallGraphNode &) = delete; @@ -184,7 +184,7 @@ public: using iterator = std::vector<CallRecord>::iterator; using const_iterator = std::vector<CallRecord>::const_iterator; - /// \brief Returns the function that this call graph node represents. + /// Returns the function that this call graph node represents. Function *getFunction() const { return F; } inline iterator begin() { return CalledFunctions.begin(); } @@ -194,17 +194,17 @@ public: inline bool empty() const { return CalledFunctions.empty(); } inline unsigned size() const { return (unsigned)CalledFunctions.size(); } - /// \brief Returns the number of other CallGraphNodes in this CallGraph that + /// Returns the number of other CallGraphNodes in this CallGraph that /// reference this node in their callee list. unsigned getNumReferences() const { return NumReferences; } - /// \brief Returns the i'th called function. + /// Returns the i'th called function. CallGraphNode *operator[](unsigned i) const { assert(i < CalledFunctions.size() && "Invalid index"); return CalledFunctions[i].second; } - /// \brief Print out this call graph node. + /// Print out this call graph node. void dump() const; void print(raw_ostream &OS) const; @@ -213,7 +213,7 @@ public: // modified // - /// \brief Removes all edges from this CallGraphNode to any functions it + /// Removes all edges from this CallGraphNode to any functions it /// calls. void removeAllCalledFunctions() { while (!CalledFunctions.empty()) { @@ -222,14 +222,14 @@ public: } } - /// \brief Moves all the callee information from N to this node. + /// 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); } - /// \brief Adds a function to the list of functions called by this one. + /// Adds a function to the list of functions called by this one. void addCalledFunction(CallSite CS, CallGraphNode *M) { assert(!CS.getInstruction() || !CS.getCalledFunction() || !CS.getCalledFunction()->isIntrinsic() || @@ -244,23 +244,23 @@ public: CalledFunctions.pop_back(); } - /// \brief Removes the edge in the node for the specified call site. + /// 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); - /// \brief Removes all call edges from this node to the specified callee + /// 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); - /// \brief Removes one edge associated with a null callsite from this node to + /// Removes one edge associated with a null callsite from this node to /// the specified callee function. void removeOneAbstractEdgeTo(CallGraphNode *Callee); - /// \brief Replaces the edge in the node for the specified call site with a + /// 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. @@ -273,18 +273,18 @@ private: std::vector<CallRecord> CalledFunctions; - /// \brief The number of times that this CallGraphNode occurs in the + /// The number of times that this CallGraphNode occurs in the /// CalledFunctions array of this or other CallGraphNodes. unsigned NumReferences = 0; void DropRef() { --NumReferences; } void AddRef() { ++NumReferences; } - /// \brief A special function that should only be used by the CallGraph class. + /// 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. +/// 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 @@ -295,16 +295,16 @@ class CallGraphAnalysis : public AnalysisInfoMixin<CallGraphAnalysis> { static AnalysisKey Key; public: - /// \brief A formulaic type to inform clients of the result type. + /// A formulaic type to inform clients of the result type. using Result = CallGraph; - /// \brief Compute the \c CallGraph for the module \c M. + /// Compute the \c CallGraph for the module \c M. /// /// The real work here is done in the \c CallGraph constructor. CallGraph run(Module &M, ModuleAnalysisManager &) { return CallGraph(M); } }; -/// \brief Printer pass for the \c CallGraphAnalysis results. +/// Printer pass for the \c CallGraphAnalysis results. class CallGraphPrinterPass : public PassInfoMixin<CallGraphPrinterPass> { raw_ostream &OS; @@ -314,7 +314,7 @@ public: PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; -/// \brief The \c ModulePass which wraps up a \c CallGraph and the logic to +/// 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 @@ -330,7 +330,7 @@ public: CallGraphWrapperPass(); ~CallGraphWrapperPass() override; - /// \brief The internal \c CallGraph around which the rest of this interface + /// The internal \c CallGraph around which the rest of this interface /// is wrapped. const CallGraph &getCallGraph() const { return *G; } CallGraph &getCallGraph() { return *G; } @@ -338,7 +338,7 @@ public: using iterator = CallGraph::iterator; using const_iterator = CallGraph::const_iterator; - /// \brief Returns the module the call graph corresponds to. + /// Returns the module the call graph corresponds to. Module &getModule() const { return G->getModule(); } inline iterator begin() { return G->begin(); } @@ -346,15 +346,15 @@ public: 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. + /// 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. + /// 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 + /// Returns the \c CallGraphNode which is used to represent /// undetermined calls into the callgraph. CallGraphNode *getExternalCallingNode() const { return G->getExternalCallingNode(); @@ -369,7 +369,7 @@ public: // modified. // - /// \brief Unlink the function from this module, returning it. + /// 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 @@ -379,7 +379,7 @@ public: return G->removeFunctionFromModule(CGN); } - /// \brief Similar to operator[], but this will insert a new CallGraphNode for + /// 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); @@ -426,12 +426,14 @@ template <> struct GraphTraits<CallGraphNode *> { template <> struct GraphTraits<const CallGraphNode *> { using NodeRef = const CallGraphNode *; using CGNPairTy = CallGraphNode::CallRecord; + using EdgeRef = const CallGraphNode::CallRecord &; static NodeRef getEntryNode(const CallGraphNode *CGN) { return CGN; } static const CallGraphNode *CGNGetValue(CGNPairTy P) { return P.second; } using ChildIteratorType = mapped_iterator<CallGraphNode::const_iterator, decltype(&CGNGetValue)>; + using ChildEdgeIteratorType = CallGraphNode::const_iterator; static ChildIteratorType child_begin(NodeRef N) { return ChildIteratorType(N->begin(), &CGNGetValue); @@ -440,6 +442,13 @@ template <> struct GraphTraits<const CallGraphNode *> { static ChildIteratorType child_end(NodeRef N) { return ChildIteratorType(N->end(), &CGNGetValue); } + + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } + + static NodeRef edge_dest(EdgeRef E) { return E.second; } }; template <> diff --git a/contrib/llvm/include/llvm/Analysis/CaptureTracking.h b/contrib/llvm/include/llvm/Analysis/CaptureTracking.h index 8d2c095d8585..7a869a51233a 100644 --- a/contrib/llvm/include/llvm/Analysis/CaptureTracking.h +++ b/contrib/llvm/include/llvm/Analysis/CaptureTracking.h @@ -46,7 +46,7 @@ namespace llvm { /// to speed up capture-tracker queries. bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, bool StoreCaptures, const Instruction *I, - DominatorTree *DT, bool IncludeI = false, + const DominatorTree *DT, bool IncludeI = false, OrderedBasicBlock *OBB = nullptr); /// This callback is used in conjunction with PointerMayBeCaptured. In diff --git a/contrib/llvm/include/llvm/Analysis/CodeMetrics.h b/contrib/llvm/include/llvm/Analysis/CodeMetrics.h index 9e861ac18825..752902238522 100644 --- a/contrib/llvm/include/llvm/Analysis/CodeMetrics.h +++ b/contrib/llvm/include/llvm/Analysis/CodeMetrics.h @@ -29,7 +29,7 @@ class DataLayout; class TargetTransformInfo; class Value; -/// \brief Check whether a call will lower to something small. +/// Check whether a call will lower to something small. /// /// This tests checks whether this callsite will lower to something /// significantly cheaper than a traditional call, often a single @@ -37,64 +37,64 @@ class Value; /// return true, so will this function. bool callIsSmall(ImmutableCallSite CS); -/// \brief Utility to calculate the size and a few similar metrics for a set +/// Utility to calculate the size and a few similar metrics for a set /// of basic blocks. struct CodeMetrics { - /// \brief True if this function contains a call to setjmp or other functions + /// True if this function contains a call to setjmp or other functions /// with attribute "returns twice" without having the attribute itself. bool exposesReturnsTwice = false; - /// \brief True if this function calls itself. + /// True if this function calls itself. bool isRecursive = false; - /// \brief True if this function cannot be duplicated. + /// True if this function cannot be duplicated. /// /// True if this function contains one or more indirect branches, or it contains /// one or more 'noduplicate' instructions. bool notDuplicatable = false; - /// \brief True if this function contains a call to a convergent function. + /// True if this function contains a call to a convergent function. bool convergent = false; - /// \brief True if this function calls alloca (in the C sense). + /// True if this function calls alloca (in the C sense). bool usesDynamicAlloca = false; - /// \brief Number of instructions in the analyzed blocks. + /// Number of instructions in the analyzed blocks. unsigned NumInsts = false; - /// \brief Number of analyzed blocks. + /// Number of analyzed blocks. unsigned NumBlocks = false; - /// \brief Keeps track of basic block code size estimates. + /// Keeps track of basic block code size estimates. DenseMap<const BasicBlock *, unsigned> NumBBInsts; - /// \brief Keep track of the number of calls to 'big' functions. + /// Keep track of the number of calls to 'big' functions. unsigned NumCalls = false; - /// \brief The number of calls to internal functions with a single caller. + /// The number of calls to internal functions with a single caller. /// /// These are likely targets for future inlining, likely exposed by /// interleaved devirtualization. unsigned NumInlineCandidates = 0; - /// \brief How many instructions produce vector values. + /// How many instructions produce vector values. /// /// The inliner is more aggressive with inlining vector kernels. unsigned NumVectorInsts = 0; - /// \brief How many 'ret' instructions the blocks contain. + /// How many 'ret' instructions the blocks contain. unsigned NumRets = 0; - /// \brief Add information about a block to the current state. + /// Add information about a block to the current state. void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI, const SmallPtrSetImpl<const Value*> &EphValues); - /// \brief Collect a loop's ephemeral values (those used only by an assume + /// Collect a loop's ephemeral values (those used only by an assume /// or similar intrinsics in the loop). static void collectEphemeralValues(const Loop *L, AssumptionCache *AC, SmallPtrSetImpl<const Value *> &EphValues); - /// \brief Collect a functions's ephemeral values (those used only by an + /// Collect a functions's ephemeral values (those used only by an /// assume or similar intrinsics in the function). static void collectEphemeralValues(const Function *L, AssumptionCache *AC, SmallPtrSetImpl<const Value *> &EphValues); diff --git a/contrib/llvm/include/llvm/Analysis/ConstantFolding.h b/contrib/llvm/include/llvm/Analysis/ConstantFolding.h index 6d4eef412525..192c1abddcd2 100644 --- a/contrib/llvm/include/llvm/Analysis/ConstantFolding.h +++ b/contrib/llvm/include/llvm/Analysis/ConstantFolding.h @@ -73,19 +73,19 @@ ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr); -/// \brief Attempt to constant fold a binary operation with the specified +/// Attempt to constant fold a binary operation with the specified /// operands. If it fails, it returns a constant expression of the specified /// operands. Constant *ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS, Constant *RHS, const DataLayout &DL); -/// \brief Attempt to constant fold a select instruction with the specified +/// Attempt to constant fold a select instruction with the specified /// operands. The constant result is returned if successful; if not, null is /// returned. Constant *ConstantFoldSelectInstruction(Constant *Cond, Constant *V1, Constant *V2); -/// \brief Attempt to constant fold a cast with the specified operand. If it +/// Attempt to constant fold a cast with the specified operand. If it /// fails, it returns a constant expression of the specified operand. Constant *ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, const DataLayout &DL); @@ -96,25 +96,25 @@ Constant *ConstantFoldCastOperand(unsigned Opcode, Constant *C, Type *DestTy, Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, ArrayRef<unsigned> Idxs); -/// \brief Attempt to constant fold an extractvalue instruction with the +/// Attempt to constant fold an extractvalue instruction with the /// specified operands and indices. The constant result is returned if /// successful; if not, null is returned. Constant *ConstantFoldExtractValueInstruction(Constant *Agg, ArrayRef<unsigned> Idxs); -/// \brief Attempt to constant fold an insertelement instruction with the +/// Attempt to constant fold an insertelement instruction with the /// specified operands and indices. The constant result is returned if /// successful; if not, null is returned. Constant *ConstantFoldInsertElementInstruction(Constant *Val, Constant *Elt, Constant *Idx); -/// \brief Attempt to constant fold an extractelement instruction with the +/// Attempt to constant fold an extractelement instruction with the /// specified operands and indices. The constant result is returned if /// successful; if not, null is returned. Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx); -/// \brief Attempt to constant fold a shufflevector instruction with the +/// Attempt to constant fold a shufflevector instruction with the /// specified operands and indices. The constant result is returned if /// successful; if not, null is returned. Constant *ConstantFoldShuffleVectorInstruction(Constant *V1, Constant *V2, @@ -147,7 +147,13 @@ Constant *ConstantFoldCall(ImmutableCallSite CS, Function *F, ArrayRef<Constant *> Operands, const TargetLibraryInfo *TLI = nullptr); -/// \brief Check whether the given call has no side-effects. +/// ConstantFoldLoadThroughBitcast - try to cast constant to destination type +/// returning null if unsuccessful. Can cast pointer to pointer or pointer to +/// integer and vice versa if their sizes are equal. +Constant *ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, + const DataLayout &DL); + +/// Check whether the given call has no side-effects. /// Specifically checks for math routimes which sometimes set errno. bool isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI); } diff --git a/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h b/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h index 39f9c39c34e1..b7447a0547d5 100644 --- a/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h +++ b/contrib/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -20,7 +20,7 @@ namespace llvm { -/// \brief Default traits class for extracting a graph from an analysis pass. +/// 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 *> @@ -36,7 +36,7 @@ public: DOTGraphTraitsViewer(StringRef GraphName, char &ID) : FunctionPass(ID), Name(GraphName) {} - /// @brief Return true if this function should be processed. + /// Return true if this function should be processed. /// /// An implementation of this class my override this function to indicate that /// only certain functions should be viewed. @@ -78,7 +78,7 @@ public: DOTGraphTraitsPrinter(StringRef GraphName, char &ID) : FunctionPass(ID), Name(GraphName) {} - /// @brief Return true if this function should be processed. + /// Return true if this function should be processed. /// /// An implementation of this class my override this function to indicate that /// only certain functions should be printed. diff --git a/contrib/llvm/include/llvm/Analysis/DemandedBits.h b/contrib/llvm/include/llvm/Analysis/DemandedBits.h index ab8668256ba2..d4384609762d 100644 --- a/contrib/llvm/include/llvm/Analysis/DemandedBits.h +++ b/contrib/llvm/include/llvm/Analysis/DemandedBits.h @@ -96,15 +96,15 @@ class DemandedBitsAnalysis : public AnalysisInfoMixin<DemandedBitsAnalysis> { static AnalysisKey Key; public: - /// \brief Provide the result type for this analysis pass. + /// Provide the result type for this analysis pass. using Result = DemandedBits; - /// \brief Run the analysis pass over a function and produce demanded bits + /// Run the analysis pass over a function and produce demanded bits /// information. DemandedBits run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Printer pass for DemandedBits +/// Printer pass for DemandedBits class DemandedBitsPrinterPass : public PassInfoMixin<DemandedBitsPrinterPass> { raw_ostream &OS; diff --git a/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h index 90f33b8c42e5..c8ec737a2cb9 100644 --- a/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/DependenceAnalysis.h @@ -557,6 +557,17 @@ template <typename T> class ArrayRef; const SCEV *X, const SCEV *Y) const; + /// isKnownLessThan - Compare to see if S is less than Size + /// Another wrapper for isKnownNegative(S - max(Size, 1)) with some extra + /// checking if S is an AddRec and we can prove lessthan using the loop + /// bounds. + bool isKnownLessThan(const SCEV *S, const SCEV *Size) const; + + /// isKnownNonNegative - Compare to see if S is known not to be negative + /// Uses the fact that S comes from Ptr, which may be an inbound GEP, + /// Proving there is no wrapping going on. + bool isKnownNonNegative(const SCEV *S, const Value *Ptr) const; + /// collectUpperBound - All subscripts are the same type (on my machine, /// an i64). The loop bound may be a smaller type. collectUpperBound /// find the bound, if available, and zero extends it to the Type T. @@ -914,7 +925,7 @@ template <typename T> class ArrayRef; SmallVectorImpl<Subscript> &Pair); }; // class DependenceInfo - /// \brief AnalysisPass to compute dependence information in a function + /// AnalysisPass to compute dependence information in a function class DependenceAnalysis : public AnalysisInfoMixin<DependenceAnalysis> { public: typedef DependenceInfo Result; @@ -925,7 +936,7 @@ template <typename T> class ArrayRef; friend struct AnalysisInfoMixin<DependenceAnalysis>; }; // class DependenceAnalysis - /// \brief Legacy pass manager pass to access dependence information + /// Legacy pass manager pass to access dependence information class DependenceAnalysisWrapperPass : public FunctionPass { public: static char ID; // Class identification, replacement for typeinfo diff --git a/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h index aa2de571ba1b..328c8645d3c0 100644 --- a/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/DivergenceAnalysis.h @@ -13,6 +13,8 @@ // better decisions. // //===----------------------------------------------------------------------===// +#ifndef LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H +#define LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H #include "llvm/ADT/DenseSet.h" #include "llvm/IR/Function.h" @@ -35,14 +37,25 @@ public: // Print all divergent branches in the function. void print(raw_ostream &OS, const Module *) const override; - // Returns true if V is divergent. + // Returns true if V is divergent at its definition. + // + // Even if this function returns false, V may still be divergent when used + // in a different basic block. bool isDivergent(const Value *V) const { return DivergentValues.count(V); } // Returns true if V is uniform/non-divergent. + // + // Even if this function returns true, V may still be divergent when used + // in a different basic block. bool isUniform(const Value *V) const { return !isDivergent(V); } + // Keep the analysis results uptodate by removing an erased value. + void removeValue(const Value *V) { DivergentValues.erase(V); } + private: // Stores all divergent values. DenseSet<const Value *> DivergentValues; }; } // End llvm namespace + +#endif //LLVM_ANALYSIS_DIVERGENCE_ANALYSIS_H
\ No newline at end of file diff --git a/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h b/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h index a304dff18c79..d94c420d7177 100644 --- a/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h +++ b/contrib/llvm/include/llvm/Analysis/DominanceFrontier.h @@ -19,6 +19,7 @@ #define LLVM_ANALYSIS_DOMINANCEFRONTIER_H #include "llvm/ADT/GraphTraits.h" +#include "llvm/Config/llvm-config.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include "llvm/Support/GenericDomTree.h" @@ -179,7 +180,7 @@ extern template class DominanceFrontierBase<BasicBlock, false>; extern template class DominanceFrontierBase<BasicBlock, true>; extern template class ForwardDominanceFrontierBase<BasicBlock>; -/// \brief Analysis pass which computes a \c DominanceFrontier. +/// Analysis pass which computes a \c DominanceFrontier. class DominanceFrontierAnalysis : public AnalysisInfoMixin<DominanceFrontierAnalysis> { friend AnalysisInfoMixin<DominanceFrontierAnalysis>; @@ -187,14 +188,14 @@ class DominanceFrontierAnalysis static AnalysisKey Key; public: - /// \brief Provide the result type for this analysis pass. + /// Provide the result type for this analysis pass. using Result = DominanceFrontier; - /// \brief Run the analysis pass over a function and produce a dominator tree. + /// Run the analysis pass over a function and produce a dominator tree. DominanceFrontier run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Printer pass for the \c DominanceFrontier. +/// Printer pass for the \c DominanceFrontier. class DominanceFrontierPrinterPass : public PassInfoMixin<DominanceFrontierPrinterPass> { raw_ostream &OS; diff --git a/contrib/llvm/include/llvm/Analysis/DominanceFrontierImpl.h b/contrib/llvm/include/llvm/Analysis/DominanceFrontierImpl.h index dffb2e02b621..99224c0bf131 100644 --- a/contrib/llvm/include/llvm/Analysis/DominanceFrontierImpl.h +++ b/contrib/llvm/include/llvm/Analysis/DominanceFrontierImpl.h @@ -21,6 +21,7 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/DominanceFrontier.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/Debug.h" #include "llvm/Support/GenericDomTree.h" #include "llvm/Support/raw_ostream.h" diff --git a/contrib/llvm/include/llvm/Analysis/EHPersonalities.h b/contrib/llvm/include/llvm/Analysis/EHPersonalities.h index 2c45ab4693e6..fe0e65b828ca 100644 --- a/contrib/llvm/include/llvm/Analysis/EHPersonalities.h +++ b/contrib/llvm/include/llvm/Analysis/EHPersonalities.h @@ -32,10 +32,11 @@ enum class EHPersonality { MSVC_Win64SEH, MSVC_CXX, CoreCLR, - Rust + Rust, + Wasm_CXX }; -/// \brief See if the given exception handling personality function is one +/// See if the given exception handling personality function is one /// that we understand. If so, return a description of it; otherwise return /// Unknown. EHPersonality classifyEHPersonality(const Value *Pers); @@ -44,7 +45,7 @@ StringRef getEHPersonalityName(EHPersonality Pers); EHPersonality getDefaultEHPersonality(const Triple &T); -/// \brief Returns true if this personality function catches asynchronous +/// Returns true if this personality function catches asynchronous /// exceptions. inline bool isAsynchronousEHPersonality(EHPersonality Pers) { // The two SEH personality functions can catch asynch exceptions. We assume @@ -59,7 +60,7 @@ inline bool isAsynchronousEHPersonality(EHPersonality Pers) { llvm_unreachable("invalid enum"); } -/// \brief Returns true if this is a personality function that invokes +/// Returns true if this is a personality function that invokes /// handler funclets (which must return to it). inline bool isFuncletEHPersonality(EHPersonality Pers) { switch (Pers) { @@ -74,7 +75,23 @@ inline bool isFuncletEHPersonality(EHPersonality Pers) { llvm_unreachable("invalid enum"); } -/// \brief Return true if this personality may be safely removed if there +/// Returns true if this personality uses scope-style EH IR instructions: +/// catchswitch, catchpad/ret, and cleanuppad/ret. +inline bool isScopedEHPersonality(EHPersonality Pers) { + switch (Pers) { + case EHPersonality::MSVC_CXX: + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + case EHPersonality::CoreCLR: + case EHPersonality::Wasm_CXX: + return true; + default: + return false; + } + llvm_unreachable("invalid enum"); +} + +/// Return true if this personality may be safely removed if there /// are no invoke instructions remaining in the current function. inline bool isNoOpWithoutInvoke(EHPersonality Pers) { switch (Pers) { @@ -91,7 +108,7 @@ bool canSimplifyInvokeNoUnwind(const Function *F); typedef TinyPtrVector<BasicBlock *> ColorVector; -/// \brief If an EH funclet personality is in use (see isFuncletEHPersonality), +/// If an EH funclet personality is in use (see isFuncletEHPersonality), /// this will recompute which blocks are in which funclet. It is possible that /// some blocks are in multiple funclets. Consider this analysis to be /// expensive. diff --git a/contrib/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h b/contrib/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h index 8b1c10139de8..be3a28424cf5 100644 --- a/contrib/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/IndirectCallPromotionAnalysis.h @@ -48,7 +48,7 @@ private: public: ICallPromotionAnalysis(); - /// \brief Returns reference to array of InstrProfValueData for the given + /// Returns reference to array of InstrProfValueData for the given /// instruction \p I. /// /// The \p NumVals, \p TotalCount and \p NumCandidates diff --git a/contrib/llvm/include/llvm/Analysis/InlineCost.h b/contrib/llvm/include/llvm/Analysis/InlineCost.h index 985f3880ed3a..8c412057fb81 100644 --- a/contrib/llvm/include/llvm/Analysis/InlineCost.h +++ b/contrib/llvm/include/llvm/Analysis/InlineCost.h @@ -52,7 +52,7 @@ const int NoreturnPenalty = 10000; const unsigned TotalAllocaSizeRecursiveCaller = 1024; } -/// \brief Represents the cost of inlining a function. +/// Represents the cost of inlining a function. /// /// This supports special values for functions which should "always" or /// "never" be inlined. Otherwise, the cost represents a unitless amount; @@ -68,10 +68,10 @@ class InlineCost { NeverInlineCost = INT_MAX }; - /// \brief The estimated cost of inlining this callsite. + /// The estimated cost of inlining this callsite. const int Cost; - /// \brief The adjusted threshold against which this cost was computed. + /// The adjusted threshold against which this cost was computed. const int Threshold; // Trivial constructor, interesting logic in the factory functions below. @@ -90,7 +90,7 @@ public: return InlineCost(NeverInlineCost, 0); } - /// \brief Test whether the inline cost is low enough for inlining. + /// Test whether the inline cost is low enough for inlining. explicit operator bool() const { return Cost < Threshold; } @@ -99,20 +99,20 @@ public: bool isNever() const { return Cost == NeverInlineCost; } bool isVariable() const { return !isAlways() && !isNever(); } - /// \brief Get the inline cost estimate. + /// Get the inline cost estimate. /// It is an error to call this on an "always" or "never" InlineCost. int getCost() const { assert(isVariable() && "Invalid access of InlineCost"); return Cost; } - /// \brief Get the threshold against which the cost was computed + /// Get the threshold against which the cost was computed int getThreshold() const { assert(isVariable() && "Invalid access of InlineCost"); return Threshold; } - /// \brief Get the cost delta from the threshold for inlining. + /// Get the cost delta from the threshold for inlining. /// Only valid if the cost is of the variable kind. Returns a negative /// value if the cost is too high to inline. int getCostDelta() const { return Threshold - getCost(); } @@ -170,7 +170,7 @@ InlineParams getInlineParams(int Threshold); /// line options. If -inline-threshold option is not explicitly passed, /// the default threshold is computed from \p OptLevel and \p SizeOptLevel. /// An \p OptLevel value above 3 is considered an aggressive optimization mode. -/// \p SizeOptLevel of 1 corresponds to the the -Os flag and 2 corresponds to +/// \p SizeOptLevel of 1 corresponds to the -Os flag and 2 corresponds to /// the -Oz flag. InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel); @@ -178,7 +178,7 @@ InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel); /// and the call/return instruction. int getCallsiteCost(CallSite CS, const DataLayout &DL); -/// \brief Get an InlineCost object representing the cost of inlining this +/// Get an InlineCost object representing the cost of inlining this /// callsite. /// /// Note that a default threshold is passed into this function. This threshold @@ -195,7 +195,7 @@ InlineCost getInlineCost( Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI, ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE = nullptr); -/// \brief Get an InlineCost with the callee explicitly specified. +/// Get an InlineCost with the callee explicitly specified. /// This allows you to calculate the cost of inlining a function via a /// pointer. This behaves exactly as the version with no explicit callee /// parameter in all other respects. @@ -207,7 +207,7 @@ getInlineCost(CallSite CS, Function *Callee, const InlineParams &Params, Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI, ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE); -/// \brief Minimal filter to detect invalid constructs for inlining. +/// Minimal filter to detect invalid constructs for inlining. bool isInlineViable(Function &Callee); } diff --git a/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h b/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h index edaf4e9025bc..6b1950733246 100644 --- a/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h +++ b/contrib/llvm/include/llvm/Analysis/IteratedDominanceFrontier.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -/// \brief Compute iterated dominance frontiers using a linear time algorithm. +/// Compute iterated dominance frontiers using a linear time algorithm. /// /// The algorithm used here is based on: /// @@ -32,7 +32,7 @@ namespace llvm { -/// \brief Determine the iterated dominance frontier, given a set of defining +/// Determine the iterated dominance frontier, given a set of defining /// blocks, and optionally, a set of live-in blocks. /// /// In turn, the results can be used to place phi nodes. @@ -48,7 +48,7 @@ class IDFCalculator { IDFCalculator(DominatorTreeBase<BasicBlock, IsPostDom> &DT) : DT(DT), useLiveIn(false) {} - /// \brief Give the IDF calculator the set of blocks in which the value is + /// Give the IDF calculator the set of blocks in which the value is /// defined. This is equivalent to the set of starting blocks it should be /// calculating the IDF for (though later gets pruned based on liveness). /// @@ -57,7 +57,7 @@ class IDFCalculator { DefBlocks = &Blocks; } - /// \brief Give the IDF calculator the set of blocks in which the value is + /// Give the IDF calculator the set of blocks in which the value is /// live on entry to the block. This is used to prune the IDF calculation to /// not include blocks where any phi insertion would be dead. /// @@ -68,14 +68,14 @@ class IDFCalculator { useLiveIn = true; } - /// \brief Reset the live-in block set to be empty, and tell the IDF + /// Reset the live-in block set to be empty, and tell the IDF /// calculator to not use liveness anymore. void resetLiveInBlocks() { LiveInBlocks = nullptr; useLiveIn = false; } - /// \brief Calculate iterated dominance frontiers + /// Calculate iterated dominance frontiers /// /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in /// the file-level comment. It performs DF->IDF pruning using the live-in diff --git a/contrib/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h b/contrib/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h index 71ce0842f6a9..d1afb63d7e08 100644 --- a/contrib/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h +++ b/contrib/llvm/include/llvm/Analysis/LazyBlockFrequencyInfo.h @@ -75,7 +75,7 @@ private: const LoopInfoT *LI; }; -/// \brief This is an alternative analysis pass to +/// This is an alternative analysis pass to /// BlockFrequencyInfoWrapperPass. The difference is that with this pass the /// block frequencies are not computed when the analysis pass is executed but /// rather when the BFI result is explicitly requested by the analysis client. @@ -109,10 +109,10 @@ public: LazyBlockFrequencyInfoPass(); - /// \brief Compute and return the block frequencies. + /// Compute and return the block frequencies. BlockFrequencyInfo &getBFI() { return LBFI.getCalculated(); } - /// \brief Compute and return the block frequencies. + /// Compute and return the block frequencies. const BlockFrequencyInfo &getBFI() const { return LBFI.getCalculated(); } void getAnalysisUsage(AnalysisUsage &AU) const override; @@ -126,7 +126,7 @@ public: void print(raw_ostream &OS, const Module *M) const override; }; -/// \brief Helper for client passes to initialize dependent passes for LBFI. +/// Helper for client passes to initialize dependent passes for LBFI. void initializeLazyBFIPassPass(PassRegistry &Registry); } #endif diff --git a/contrib/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h b/contrib/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h index e1d404b1ada2..9e6bcfedcbb9 100644 --- a/contrib/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h +++ b/contrib/llvm/include/llvm/Analysis/LazyBranchProbabilityInfo.h @@ -26,7 +26,7 @@ class Function; class LoopInfo; class TargetLibraryInfo; -/// \brief This is an alternative analysis pass to +/// This is an alternative analysis pass to /// BranchProbabilityInfoWrapperPass. The difference is that with this pass the /// branch probabilities are not computed when the analysis pass is executed but /// rather when the BPI results is explicitly requested by the analysis client. @@ -89,10 +89,10 @@ public: LazyBranchProbabilityInfoPass(); - /// \brief Compute and return the branch probabilities. + /// Compute and return the branch probabilities. BranchProbabilityInfo &getBPI() { return LBPI->getCalculated(); } - /// \brief Compute and return the branch probabilities. + /// Compute and return the branch probabilities. const BranchProbabilityInfo &getBPI() const { return LBPI->getCalculated(); } void getAnalysisUsage(AnalysisUsage &AU) const override; @@ -106,10 +106,10 @@ public: void print(raw_ostream &OS, const Module *M) const override; }; -/// \brief Helper for client passes to initialize dependent passes for LBPI. +/// Helper for client passes to initialize dependent passes for LBPI. void initializeLazyBPIPassPass(PassRegistry &Registry); -/// \brief Simple trait class that provides a mapping between BPI passes and the +/// Simple trait class that provides a mapping between BPI passes and the /// corresponding BPInfo. template <typename PassT> struct BPIPassTrait { static PassT &getBPI(PassT *P) { return *P; } diff --git a/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h b/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h index 787c88cc6ec1..1a4fdb591427 100644 --- a/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h +++ b/contrib/llvm/include/llvm/Analysis/LazyValueInfo.h @@ -113,6 +113,13 @@ public: /// in LVI, so we need to pass it here as an argument. void printLVI(Function &F, DominatorTree &DTree, raw_ostream &OS); + /// Disables use of the DominatorTree within LVI. + void disableDT(); + + /// Enables use of the DominatorTree within LVI. Does nothing if the class + /// instance was initialized without a DT pointer. + void enableDT(); + // For old PM pass. Delete once LazyValueInfoWrapperPass is gone. void releaseMemory(); @@ -121,7 +128,7 @@ public: FunctionAnalysisManager::Invalidator &Inv); }; -/// \brief Analysis to compute lazy value information. +/// Analysis to compute lazy value information. class LazyValueAnalysis : public AnalysisInfoMixin<LazyValueAnalysis> { public: typedef LazyValueInfo Result; diff --git a/contrib/llvm/include/llvm/Analysis/Lint.h b/contrib/llvm/include/llvm/Analysis/Lint.h index 7c88b137ec3b..db5919fd91c7 100644 --- a/contrib/llvm/include/llvm/Analysis/Lint.h +++ b/contrib/llvm/include/llvm/Analysis/Lint.h @@ -26,12 +26,12 @@ class FunctionPass; class Module; class Function; -/// @brief Create a lint pass. +/// Create a lint pass. /// /// Check a module or function. FunctionPass *createLintPass(); -/// @brief Check a module. +/// Check a module. /// /// This should only be used for debugging, because it plays games with /// PassManagers and stuff. diff --git a/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h index 28154c873b70..0f3f2be9aeb4 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/LoopAccessAnalysis.h @@ -38,25 +38,25 @@ class SCEVUnionPredicate; class LoopAccessInfo; class OptimizationRemarkEmitter; -/// \brief Collection of parameters shared beetween the Loop Vectorizer and the +/// Collection of parameters shared beetween the Loop Vectorizer and the /// Loop Access Analysis. struct VectorizerParams { - /// \brief Maximum SIMD width. + /// Maximum SIMD width. static const unsigned MaxVectorWidth; - /// \brief VF as overridden by the user. + /// VF as overridden by the user. static unsigned VectorizationFactor; - /// \brief Interleave factor as overridden by the user. + /// Interleave factor as overridden by the user. static unsigned VectorizationInterleave; - /// \brief True if force-vector-interleave was specified by the user. + /// True if force-vector-interleave was specified by the user. static bool isInterleaveForced(); - /// \\brief When performing memory disambiguation checks at runtime do not + /// \When performing memory disambiguation checks at runtime do not /// make more than this number of comparisons. static unsigned RuntimeMemoryCheckThreshold; }; -/// \brief Checks memory dependences among accesses to the same underlying +/// Checks memory dependences among accesses to the same underlying /// object to determine whether there vectorization is legal or not (and at /// which vectorization factor). /// @@ -94,12 +94,12 @@ class MemoryDepChecker { public: typedef PointerIntPair<Value *, 1, bool> MemAccessInfo; typedef SmallVector<MemAccessInfo, 8> MemAccessInfoList; - /// \brief Set of potential dependent memory accesses. + /// Set of potential dependent memory accesses. typedef EquivalenceClasses<MemAccessInfo> DepCandidates; - /// \brief Dependece between memory access instructions. + /// Dependece between memory access instructions. struct Dependence { - /// \brief The type of the dependence. + /// The type of the dependence. enum DepType { // No dependence. NoDep, @@ -127,36 +127,36 @@ public: BackwardVectorizableButPreventsForwarding }; - /// \brief String version of the types. + /// String version of the types. static const char *DepName[]; - /// \brief Index of the source of the dependence in the InstMap vector. + /// Index of the source of the dependence in the InstMap vector. unsigned Source; - /// \brief Index of the destination of the dependence in the InstMap vector. + /// Index of the destination of the dependence in the InstMap vector. unsigned Destination; - /// \brief The type of the dependence. + /// The type of the dependence. DepType Type; Dependence(unsigned Source, unsigned Destination, DepType Type) : Source(Source), Destination(Destination), Type(Type) {} - /// \brief Return the source instruction of the dependence. + /// Return the source instruction of the dependence. Instruction *getSource(const LoopAccessInfo &LAI) const; - /// \brief Return the destination instruction of the dependence. + /// Return the destination instruction of the dependence. Instruction *getDestination(const LoopAccessInfo &LAI) const; - /// \brief Dependence types that don't prevent vectorization. + /// Dependence types that don't prevent vectorization. static bool isSafeForVectorization(DepType Type); - /// \brief Lexically forward dependence. + /// Lexically forward dependence. bool isForward() const; - /// \brief Lexically backward dependence. + /// Lexically backward dependence. bool isBackward() const; - /// \brief May be a lexically backward dependence type (includes Unknown). + /// May be a lexically backward dependence type (includes Unknown). bool isPossiblyBackward() const; - /// \brief Print the dependence. \p Instr is used to map the instruction + /// Print the dependence. \p Instr is used to map the instruction /// indices to instructions. void print(raw_ostream &OS, unsigned Depth, const SmallVectorImpl<Instruction *> &Instrs) const; @@ -167,7 +167,7 @@ public: ShouldRetryWithRuntimeCheck(false), SafeForVectorization(true), RecordDependences(true) {} - /// \brief Register the location (instructions are given increasing numbers) + /// Register the location (instructions are given increasing numbers) /// of a write access. void addAccess(StoreInst *SI) { Value *Ptr = SI->getPointerOperand(); @@ -176,7 +176,7 @@ public: ++AccessIdx; } - /// \brief Register the location (instructions are given increasing numbers) + /// Register the location (instructions are given increasing numbers) /// of a write access. void addAccess(LoadInst *LI) { Value *Ptr = LI->getPointerOperand(); @@ -185,29 +185,29 @@ public: ++AccessIdx; } - /// \brief Check whether the dependencies between the accesses are safe. + /// Check whether the dependencies between the accesses are safe. /// /// Only checks sets with elements in \p CheckDeps. bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoList &CheckDeps, const ValueToValueMap &Strides); - /// \brief No memory dependence was encountered that would inhibit + /// No memory dependence was encountered that would inhibit /// vectorization. bool isSafeForVectorization() const { return SafeForVectorization; } - /// \brief The maximum number of bytes of a vector register we can vectorize + /// The maximum number of bytes of a vector register we can vectorize /// the accesses safely with. uint64_t getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; } - /// \brief Return the number of elements that are safe to operate on + /// Return the number of elements that are safe to operate on /// simultaneously, multiplied by the size of the element in bits. uint64_t getMaxSafeRegisterWidth() const { return MaxSafeRegisterWidth; } - /// \brief In same cases when the dependency check fails we can still + /// In same cases when the dependency check fails we can still /// vectorize the loop with a dynamic array access check. bool shouldRetryWithRuntimeCheck() { return ShouldRetryWithRuntimeCheck; } - /// \brief Returns the memory dependences. If null is returned we exceeded + /// Returns the memory dependences. If null is returned we exceeded /// the MaxDependences threshold and this information is not /// available. const SmallVectorImpl<Dependence> *getDependences() const { @@ -216,13 +216,13 @@ public: void clearDependences() { Dependences.clear(); } - /// \brief The vector of memory access instructions. The indices are used as + /// The vector of memory access instructions. The indices are used as /// instruction identifiers in the Dependence class. const SmallVectorImpl<Instruction *> &getMemoryInstructions() const { return InstMap; } - /// \brief Generate a mapping between the memory instructions and their + /// Generate a mapping between the memory instructions and their /// indices according to program order. DenseMap<Instruction *, unsigned> generateInstructionOrderMap() const { DenseMap<Instruction *, unsigned> OrderMap; @@ -233,7 +233,7 @@ public: return OrderMap; } - /// \brief Find the set of instructions that read or write via \p Ptr. + /// Find the set of instructions that read or write via \p Ptr. SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr, bool isWrite) const; @@ -247,42 +247,42 @@ private: PredicatedScalarEvolution &PSE; const Loop *InnermostLoop; - /// \brief Maps access locations (ptr, read/write) to program order. + /// Maps access locations (ptr, read/write) to program order. DenseMap<MemAccessInfo, std::vector<unsigned> > Accesses; - /// \brief Memory access instructions in program order. + /// Memory access instructions in program order. SmallVector<Instruction *, 16> InstMap; - /// \brief The program order index to be used for the next instruction. + /// The program order index to be used for the next instruction. unsigned AccessIdx; // We can access this many bytes in parallel safely. uint64_t MaxSafeDepDistBytes; - /// \brief Number of elements (from consecutive iterations) that are safe to + /// Number of elements (from consecutive iterations) that are safe to /// operate on simultaneously, multiplied by the size of the element in bits. /// The size of the element is taken from the memory access that is most /// restrictive. uint64_t MaxSafeRegisterWidth; - /// \brief If we see a non-constant dependence distance we can still try to + /// If we see a non-constant dependence distance we can still try to /// vectorize this loop with runtime checks. bool ShouldRetryWithRuntimeCheck; - /// \brief No memory dependence was encountered that would inhibit + /// No memory dependence was encountered that would inhibit /// vectorization. bool SafeForVectorization; - //// \brief True if Dependences reflects the dependences in the + //// True if Dependences reflects the dependences in the //// loop. If false we exceeded MaxDependences and //// Dependences is invalid. bool RecordDependences; - /// \brief Memory dependences collected during the analysis. Only valid if + /// Memory dependences collected during the analysis. Only valid if /// RecordDependences is true. SmallVector<Dependence, 8> Dependences; - /// \brief Check whether there is a plausible dependence between the two + /// Check whether there is a plausible dependence between the two /// accesses. /// /// Access \p A must happen before \p B in program order. The two indices @@ -298,7 +298,7 @@ private: const MemAccessInfo &B, unsigned BIdx, const ValueToValueMap &Strides); - /// \brief Check whether the data dependence could prevent store-load + /// Check whether the data dependence could prevent store-load /// forwarding. /// /// \return false if we shouldn't vectorize at all or avoid larger @@ -306,7 +306,7 @@ private: bool couldPreventStoreLoadForward(uint64_t Distance, uint64_t TypeByteSize); }; -/// \brief Holds information about the memory runtime legality checks to verify +/// Holds information about the memory runtime legality checks to verify /// that a group of pointers do not overlap. class RuntimePointerChecking { public: @@ -355,13 +355,13 @@ public: unsigned ASId, const ValueToValueMap &Strides, PredicatedScalarEvolution &PSE); - /// \brief No run-time memory checking is necessary. + /// No run-time memory checking is necessary. bool empty() const { return Pointers.empty(); } /// A grouping of pointers. A single memcheck is required between /// two groups. struct CheckingPtrGroup { - /// \brief Create a new pointer checking group containing a single + /// Create a new pointer checking group containing a single /// pointer, with index \p Index in RtCheck. CheckingPtrGroup(unsigned Index, RuntimePointerChecking &RtCheck) : RtCheck(RtCheck), High(RtCheck.Pointers[Index].End), @@ -369,7 +369,7 @@ public: Members.push_back(Index); } - /// \brief Tries to add the pointer recorded in RtCheck at index + /// Tries to add the pointer recorded in RtCheck at index /// \p Index to this pointer checking group. We can only add a pointer /// to a checking group if we will still be able to get /// the upper and lower bounds of the check. Returns true in case @@ -390,7 +390,7 @@ public: SmallVector<unsigned, 2> Members; }; - /// \brief A memcheck which made up of a pair of grouped pointers. + /// A memcheck which made up of a pair of grouped pointers. /// /// These *have* to be const for now, since checks are generated from /// CheckingPtrGroups in LAI::addRuntimeChecks which is a const member @@ -399,24 +399,24 @@ public: typedef std::pair<const CheckingPtrGroup *, const CheckingPtrGroup *> PointerCheck; - /// \brief Generate the checks and store it. This also performs the grouping + /// Generate the checks and store it. This also performs the grouping /// of pointers to reduce the number of memchecks necessary. void generateChecks(MemoryDepChecker::DepCandidates &DepCands, bool UseDependencies); - /// \brief Returns the checks that generateChecks created. + /// Returns the checks that generateChecks created. const SmallVector<PointerCheck, 4> &getChecks() const { return Checks; } - /// \brief Decide if we need to add a check between two groups of pointers, + /// Decide if we need to add a check between two groups of pointers, /// according to needsChecking. bool needsChecking(const CheckingPtrGroup &M, const CheckingPtrGroup &N) const; - /// \brief Returns the number of run-time checks required according to + /// Returns the number of run-time checks required according to /// needsChecking. unsigned getNumberOfChecks() const { return Checks.size(); } - /// \brief Print the list run-time memory checks necessary. + /// Print the list run-time memory checks necessary. void print(raw_ostream &OS, unsigned Depth = 0) const; /// Print \p Checks. @@ -432,7 +432,7 @@ public: /// Holds a partitioning of pointers into "check groups". SmallVector<CheckingPtrGroup, 2> CheckingGroups; - /// \brief Check if pointers are in the same partition + /// Check if pointers are in the same partition /// /// \p PtrToPartition contains the partition number for pointers (-1 if the /// pointer belongs to multiple partitions). @@ -440,17 +440,17 @@ public: arePointersInSamePartition(const SmallVectorImpl<int> &PtrToPartition, unsigned PtrIdx1, unsigned PtrIdx2); - /// \brief Decide whether we need to issue a run-time check for pointer at + /// Decide whether we need to issue a run-time check for pointer at /// index \p I and \p J to prove their independence. bool needsChecking(unsigned I, unsigned J) const; - /// \brief Return PointerInfo for pointer at index \p PtrIdx. + /// Return PointerInfo for pointer at index \p PtrIdx. const PointerInfo &getPointerInfo(unsigned PtrIdx) const { return Pointers[PtrIdx]; } private: - /// \brief Groups pointers such that a single memcheck is required + /// Groups pointers such that a single memcheck is required /// between two different groups. This will clear the CheckingGroups vector /// and re-compute it. We will only group dependecies if \p UseDependencies /// is true, otherwise we will create a separate group for each pointer. @@ -464,12 +464,12 @@ private: /// Holds a pointer to the ScalarEvolution analysis. ScalarEvolution *SE; - /// \brief Set of run-time checks required to establish independence of + /// Set of run-time checks required to establish independence of /// otherwise may-aliasing pointers in the loop. SmallVector<PointerCheck, 4> Checks; }; -/// \brief Drive the analysis of memory accesses in the loop +/// Drive the analysis of memory accesses in the loop /// /// This class is responsible for analyzing the memory accesses of a loop. It /// collects the accesses and then its main helper the AccessAnalysis class @@ -503,7 +503,7 @@ public: return PtrRtChecking.get(); } - /// \brief Number of memchecks required to prove independence of otherwise + /// Number of memchecks required to prove independence of otherwise /// may-alias pointers. unsigned getNumRuntimePointerChecks() const { return PtrRtChecking->getNumberOfChecks(); @@ -521,7 +521,7 @@ public: unsigned getNumStores() const { return NumStores; } unsigned getNumLoads() const { return NumLoads;} - /// \brief Add code that checks at runtime if the accessed arrays overlap. + /// Add code that checks at runtime if the accessed arrays overlap. /// /// Returns a pair of instructions where the first element is the first /// instruction generated in possibly a sequence of instructions and the @@ -529,7 +529,7 @@ public: std::pair<Instruction *, Instruction *> addRuntimeChecks(Instruction *Loc) const; - /// \brief Generete the instructions for the checks in \p PointerChecks. + /// Generete the instructions for the checks in \p PointerChecks. /// /// Returns a pair of instructions where the first element is the first /// instruction generated in possibly a sequence of instructions and the @@ -539,32 +539,32 @@ public: const SmallVectorImpl<RuntimePointerChecking::PointerCheck> &PointerChecks) const; - /// \brief The diagnostics report generated for the analysis. E.g. why we + /// The diagnostics report generated for the analysis. E.g. why we /// couldn't analyze the loop. const OptimizationRemarkAnalysis *getReport() const { return Report.get(); } - /// \brief the Memory Dependence Checker which can determine the + /// the Memory Dependence Checker which can determine the /// loop-independent and loop-carried dependences between memory accesses. const MemoryDepChecker &getDepChecker() const { return *DepChecker; } - /// \brief Return the list of instructions that use \p Ptr to read or write + /// Return the list of instructions that use \p Ptr to read or write /// memory. SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr, bool isWrite) const { return DepChecker->getInstructionsForAccess(Ptr, isWrite); } - /// \brief If an access has a symbolic strides, this maps the pointer value to + /// If an access has a symbolic strides, this maps the pointer value to /// the stride symbol. const ValueToValueMap &getSymbolicStrides() const { return SymbolicStrides; } - /// \brief Pointer has a symbolic stride. + /// Pointer has a symbolic stride. bool hasStride(Value *V) const { return StrideSet.count(V); } - /// \brief Print the information about the memory accesses in the loop. + /// Print the information about the memory accesses in the loop. void print(raw_ostream &OS, unsigned Depth = 0) const; - /// \brief Checks existence of store to invariant address inside loop. + /// Checks existence of store to invariant address inside loop. /// If the loop has any store to invariant address, then it returns true, /// else returns false. bool hasStoreToLoopInvariantAddress() const { @@ -579,15 +579,15 @@ public: const PredicatedScalarEvolution &getPSE() const { return *PSE; } private: - /// \brief Analyze the loop. + /// Analyze the loop. void analyzeLoop(AliasAnalysis *AA, LoopInfo *LI, const TargetLibraryInfo *TLI, DominatorTree *DT); - /// \brief Check if the structure of the loop allows it to be analyzed by this + /// Check if the structure of the loop allows it to be analyzed by this /// pass. bool canAnalyzeLoop(); - /// \brief Save the analysis remark. + /// Save the analysis remark. /// /// LAA does not directly emits the remarks. Instead it stores it which the /// client can retrieve and presents as its own analysis @@ -595,7 +595,7 @@ private: OptimizationRemarkAnalysis &recordAnalysis(StringRef RemarkName, Instruction *Instr = nullptr); - /// \brief Collect memory access with loop invariant strides. + /// Collect memory access with loop invariant strides. /// /// Looks for accesses like "a[i * StrideA]" where "StrideA" is loop /// invariant. @@ -607,7 +607,7 @@ private: /// at runtime. Using std::unique_ptr to make using move ctor simpler. std::unique_ptr<RuntimePointerChecking> PtrRtChecking; - /// \brief the Memory Dependence Checker which can determine the + /// the Memory Dependence Checker which can determine the /// loop-independent and loop-carried dependences between memory accesses. std::unique_ptr<MemoryDepChecker> DepChecker; @@ -618,28 +618,28 @@ private: uint64_t MaxSafeDepDistBytes; - /// \brief Cache the result of analyzeLoop. + /// Cache the result of analyzeLoop. bool CanVecMem; - /// \brief Indicator for storing to uniform addresses. + /// Indicator for storing to uniform addresses. /// If a loop has write to a loop invariant address then it should be true. bool StoreToLoopInvariantAddress; - /// \brief The diagnostics report generated for the analysis. E.g. why we + /// The diagnostics report generated for the analysis. E.g. why we /// couldn't analyze the loop. std::unique_ptr<OptimizationRemarkAnalysis> Report; - /// \brief If an access has a symbolic strides, this maps the pointer value to + /// If an access has a symbolic strides, this maps the pointer value to /// the stride symbol. ValueToValueMap SymbolicStrides; - /// \brief Set of symbolic strides values. + /// Set of symbolic strides values. SmallPtrSet<Value *, 8> StrideSet; }; Value *stripIntegerCast(Value *V); -/// \brief Return the SCEV corresponding to a pointer with the symbolic stride +/// Return the SCEV corresponding to a pointer with the symbolic stride /// replaced with constant one, assuming the SCEV predicate associated with /// \p PSE is true. /// @@ -653,7 +653,7 @@ const SCEV *replaceSymbolicStrideSCEV(PredicatedScalarEvolution &PSE, const ValueToValueMap &PtrToStride, Value *Ptr, Value *OrigPtr = nullptr); -/// \brief If the pointer has a constant stride return it in units of its +/// If the pointer has a constant stride return it in units of its /// element size. Otherwise return zero. /// /// Ensure that it does not wrap in the address space, assuming the predicate @@ -667,12 +667,26 @@ int64_t getPtrStride(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp, const ValueToValueMap &StridesMap = ValueToValueMap(), bool Assume = false, bool ShouldCheckWrap = true); -/// \brief Returns true if the memory operations \p A and \p B are consecutive. +/// Attempt to sort the pointers in \p VL and return the sorted indices +/// in \p SortedIndices, if reordering is required. +/// +/// Returns 'true' if sorting is legal, otherwise returns 'false'. +/// +/// For example, for a given \p VL of memory accesses in program order, a[i+4], +/// a[i+0], a[i+1] and a[i+7], this function will sort the \p VL and save the +/// sorted indices in \p SortedIndices as a[i+0], a[i+1], a[i+4], a[i+7] and +/// saves the mask for actual memory accesses in program order in +/// \p SortedIndices as <1,2,0,3> +bool sortPtrAccesses(ArrayRef<Value *> VL, const DataLayout &DL, + ScalarEvolution &SE, + SmallVectorImpl<unsigned> &SortedIndices); + +/// Returns true if the memory operations \p A and \p B are consecutive. /// This is a simple API that does not depend on the analysis pass. bool isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL, ScalarEvolution &SE, bool CheckType = true); -/// \brief This analysis provides dependence information for the memory accesses +/// This analysis provides dependence information for the memory accesses /// of a loop. /// /// It runs the analysis for a loop on demand. This can be initiated by @@ -691,7 +705,7 @@ public: void getAnalysisUsage(AnalysisUsage &AU) const override; - /// \brief Query the result of the loop access information for the loop \p L. + /// Query the result of the loop access information for the loop \p L. /// /// If there is no cached result available run the analysis. const LoopAccessInfo &getInfo(Loop *L); @@ -701,11 +715,11 @@ public: LoopAccessInfoMap.clear(); } - /// \brief Print the result of the analysis when invoked with -analyze. + /// Print the result of the analysis when invoked with -analyze. void print(raw_ostream &OS, const Module *M = nullptr) const override; private: - /// \brief The cache. + /// The cache. DenseMap<Loop *, std::unique_ptr<LoopAccessInfo>> LoopAccessInfoMap; // The used analysis passes. @@ -716,7 +730,7 @@ private: LoopInfo *LI; }; -/// \brief This analysis provides dependence information for the memory +/// This analysis provides dependence information for the memory /// accesses of a loop. /// /// It runs the analysis for a loop on demand. This can be initiated by diff --git a/contrib/llvm/include/llvm/Analysis/LoopAnalysisManager.h b/contrib/llvm/include/llvm/Analysis/LoopAnalysisManager.h index 417ee979ce97..00e562c4f31f 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopAnalysisManager.h +++ b/contrib/llvm/include/llvm/Analysis/LoopAnalysisManager.h @@ -69,7 +69,7 @@ extern cl::opt<bool> EnableMSSALoopDependency; extern template class AllAnalysesOn<Loop>; extern template class AnalysisManager<Loop, LoopStandardAnalysisResults &>; -/// \brief The loop analysis manager. +/// The loop analysis manager. /// /// See the documentation for the AnalysisManager template for detail /// documentation. This typedef serves as a convenient way to refer to this diff --git a/contrib/llvm/include/llvm/Analysis/LoopInfo.h b/contrib/llvm/include/llvm/Analysis/LoopInfo.h index 28afc39727fa..30b29d66a1d1 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopInfo.h +++ b/contrib/llvm/include/llvm/Analysis/LoopInfo.h @@ -178,6 +178,12 @@ public: return DenseBlockSet; } + /// Return a direct, immutable handle to the blocks set. + const SmallPtrSetImpl<const BlockT *> &getBlocksSet() const { + assert(!isInvalid() && "Loop not in a valid state!"); + return DenseBlockSet; + } + /// Return true if this loop is no longer valid. The only valid use of this /// helper is "assert(L.isInvalid())" or equivalent, since IsInvalid is set to /// true by the destructor. In other words, if this accessor returns true, @@ -255,6 +261,20 @@ public: /// Otherwise return null. BlockT *getExitBlock() const; + /// Return true if no exit block for the loop has a predecessor that is + /// outside the loop. + bool hasDedicatedExits() const; + + /// Return all unique successor blocks of this loop. + /// These are the blocks _outside of the current loop_ which are branched to. + /// This assumes that loop exits are in canonical form, i.e. all exits are + /// dedicated exits. + void getUniqueExitBlocks(SmallVectorImpl<BlockT *> &ExitBlocks) const; + + /// If getUniqueExitBlocks would return exactly one block, return that block. + /// Otherwise return null. + BlockT *getUniqueExitBlock() const; + /// Edge type. typedef std::pair<const BlockT *, const BlockT *> Edge; @@ -438,7 +458,7 @@ extern template class LoopBase<BasicBlock, Loop>; /// in the CFG are necessarily loops. class Loop : public LoopBase<BasicBlock, Loop> { public: - /// \brief A range representing the start and end location of a loop. + /// A range representing the start and end location of a loop. class LocRange { DebugLoc Start; DebugLoc End; @@ -452,7 +472,7 @@ public: const DebugLoc &getStart() const { return Start; } const DebugLoc &getEnd() const { return End; } - /// \brief Check for null. + /// Check for null. /// explicit operator bool() const { return Start && End; } }; @@ -527,7 +547,7 @@ public: /// /// If this loop contains the same llvm.loop metadata on each branch to the /// header then the node is returned. If any latch instruction does not - /// contain llvm.loop or or if multiple latches contain different nodes then + /// contain llvm.loop or if multiple latches contain different nodes then /// 0 is returned. MDNode *getLoopID() const; /// Set the llvm.loop loop id metadata for this loop. @@ -547,20 +567,6 @@ public: /// unrolling pass is run more than once (which it generally is). void setLoopAlreadyUnrolled(); - /// Return true if no exit block for the loop has a predecessor that is - /// outside the loop. - bool hasDedicatedExits() const; - - /// Return all unique successor blocks of this loop. - /// These are the blocks _outside of the current loop_ which are branched to. - /// This assumes that loop exits are in canonical form, i.e. all exits are - /// dedicated exits. - void getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const; - - /// If getUniqueExitBlocks would return exactly one block, return that block. - /// Otherwise return null. - BasicBlock *getUniqueExitBlock() const; - void dump() const; void dumpVerbose() const; @@ -929,7 +935,7 @@ template <> struct GraphTraits<Loop *> { static ChildIteratorType child_end(NodeRef N) { return N->end(); } }; -/// \brief Analysis pass that exposes the \c LoopInfo for a function. +/// Analysis pass that exposes the \c LoopInfo for a function. class LoopAnalysis : public AnalysisInfoMixin<LoopAnalysis> { friend AnalysisInfoMixin<LoopAnalysis>; static AnalysisKey Key; @@ -940,7 +946,7 @@ public: LoopInfo run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Printer pass for the \c LoopAnalysis results. +/// Printer pass for the \c LoopAnalysis results. class LoopPrinterPass : public PassInfoMixin<LoopPrinterPass> { raw_ostream &OS; @@ -949,12 +955,12 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Verifier pass for the \c LoopAnalysis results. +/// Verifier pass for the \c LoopAnalysis results. struct LoopVerifierPass : public PassInfoMixin<LoopVerifierPass> { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief The legacy pass manager's analysis pass to compute loop information. +/// The legacy pass manager's analysis pass to compute loop information. class LoopInfoWrapperPass : public FunctionPass { LoopInfo LI; @@ -968,7 +974,7 @@ public: LoopInfo &getLoopInfo() { return LI; } const LoopInfo &getLoopInfo() const { return LI; } - /// \brief Calculate the natural loop information for a given function. + /// Calculate the natural loop information for a given function. bool runOnFunction(Function &F) override; void verifyAnalysis() const override; diff --git a/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h b/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h index b3a16b5369f7..941389858868 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h +++ b/contrib/llvm/include/llvm/Analysis/LoopInfoImpl.h @@ -82,6 +82,74 @@ BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const { return nullptr; } +template <class BlockT, class LoopT> +bool LoopBase<BlockT, LoopT>::hasDedicatedExits() const { + // Each predecessor of each exit block of a normal loop is contained + // within the loop. + SmallVector<BlockT *, 4> ExitBlocks; + getExitBlocks(ExitBlocks); + for (BlockT *EB : ExitBlocks) + for (BlockT *Predecessor : children<Inverse<BlockT *>>(EB)) + if (!contains(Predecessor)) + return false; + // All the requirements are met. + return true; +} + +template <class BlockT, class LoopT> +void LoopBase<BlockT, LoopT>::getUniqueExitBlocks( + SmallVectorImpl<BlockT *> &ExitBlocks) const { + typedef GraphTraits<BlockT *> BlockTraits; + typedef GraphTraits<Inverse<BlockT *>> InvBlockTraits; + + assert(hasDedicatedExits() && + "getUniqueExitBlocks assumes the loop has canonical form exits!"); + + SmallVector<BlockT *, 32> SwitchExitBlocks; + for (BlockT *Block : this->blocks()) { + SwitchExitBlocks.clear(); + for (BlockT *Successor : children<BlockT *>(Block)) { + // If block is inside the loop then it is not an exit block. + if (contains(Successor)) + continue; + + BlockT *FirstPred = *InvBlockTraits::child_begin(Successor); + + // If current basic block is this exit block's first predecessor then only + // insert exit block in to the output ExitBlocks vector. This ensures that + // same exit block is not inserted twice into ExitBlocks vector. + if (Block != FirstPred) + continue; + + // If a terminator has more then two successors, for example SwitchInst, + // then it is possible that there are multiple edges from current block to + // one exit block. + if (std::distance(BlockTraits::child_begin(Block), + BlockTraits::child_end(Block)) <= 2) { + ExitBlocks.push_back(Successor); + continue; + } + + // In case of multiple edges from current block to exit block, collect + // only one edge in ExitBlocks. Use switchExitBlocks to keep track of + // duplicate edges. + if (!is_contained(SwitchExitBlocks, Successor)) { + SwitchExitBlocks.push_back(Successor); + ExitBlocks.push_back(Successor); + } + } + } +} + +template <class BlockT, class LoopT> +BlockT *LoopBase<BlockT, LoopT>::getUniqueExitBlock() const { + SmallVector<BlockT *, 8> UniqueExitBlocks; + getUniqueExitBlocks(UniqueExitBlocks); + if (UniqueExitBlocks.size() == 1) + return UniqueExitBlocks[0]; + return nullptr; +} + /// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). template <class BlockT, class LoopT> void LoopBase<BlockT, LoopT>::getExitEdges( @@ -572,8 +640,8 @@ void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const { template <typename T> bool compareVectors(std::vector<T> &BB1, std::vector<T> &BB2) { - std::sort(BB1.begin(), BB1.end()); - std::sort(BB2.begin(), BB2.end()); + llvm::sort(BB1.begin(), BB1.end()); + llvm::sort(BB2.begin(), BB2.end()); return BB1 == BB2; } @@ -617,6 +685,15 @@ static void compareLoops(const LoopT *L, const LoopT *OtherL, std::vector<BlockT *> OtherBBs = OtherL->getBlocks(); assert(compareVectors(BBs, OtherBBs) && "Mismatched basic blocks in the loops!"); + + const SmallPtrSetImpl<const BlockT *> &BlocksSet = L->getBlocksSet(); + const SmallPtrSetImpl<const BlockT *> &OtherBlocksSet = L->getBlocksSet(); + assert(BlocksSet.size() == OtherBlocksSet.size() && + std::all_of(BlocksSet.begin(), BlocksSet.end(), + [&OtherBlocksSet](const BlockT *BB) { + return OtherBlocksSet.count(BB); + }) && + "Mismatched basic blocks in BlocksSets!"); } #endif @@ -636,6 +713,9 @@ void LoopInfoBase<BlockT, LoopT>::verify( LoopT *L = Entry.second; assert(Loops.count(L) && "orphaned loop"); assert(L->contains(BB) && "orphaned block"); + for (LoopT *ChildLoop : *L) + assert(!ChildLoop->contains(BB) && + "BBMap should point to the innermost loop containing BB"); } // Recompute LoopInfo to verify loops structure. diff --git a/contrib/llvm/include/llvm/Analysis/LoopIterator.h b/contrib/llvm/include/llvm/Analysis/LoopIterator.h index 461f74351821..91c54b23029b 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopIterator.h +++ b/contrib/llvm/include/llvm/Analysis/LoopIterator.h @@ -168,6 +168,25 @@ public: } }; +/// Wrapper class to LoopBlocksDFS that provides a standard begin()/end() +/// interface for the DFS reverse post-order traversal of blocks in a loop body. +class LoopBlocksRPO { +private: + LoopBlocksDFS DFS; + +public: + LoopBlocksRPO(Loop *Container) : DFS(Container) {} + + /// Traverse the loop blocks and store the DFS result. + void perform(LoopInfo *LI) { + DFS.perform(LI); + } + + /// Reverse iterate over the cached postorder blocks. + LoopBlocksDFS::RPOIterator begin() const { return DFS.beginRPO(); } + LoopBlocksDFS::RPOIterator end() const { return DFS.endRPO(); } +}; + /// Specialize po_iterator_storage to record postorder numbers. template<> class po_iterator_storage<LoopBlocksTraversal, true> { LoopBlocksTraversal &LBT; diff --git a/contrib/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h b/contrib/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h index 80f3e5fdcd43..f45bf0b223b8 100644 --- a/contrib/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h +++ b/contrib/llvm/include/llvm/Analysis/LoopUnrollAnalyzer.h @@ -57,7 +57,7 @@ public: using Base::visit; private: - /// \brief A cache of pointer bases and constant-folded offsets corresponding + /// A cache of pointer bases and constant-folded offsets corresponding /// to GEP (or derived from GEP) instructions. /// /// In order to find the base pointer one needs to perform non-trivial @@ -65,11 +65,11 @@ private: /// results saved. DenseMap<Value *, SimplifiedAddress> SimplifiedAddresses; - /// \brief SCEV expression corresponding to number of currently simulated + /// SCEV expression corresponding to number of currently simulated /// iteration. const SCEV *IterationNumber; - /// \brief A Value->Constant map for keeping values that we managed to + /// A Value->Constant map for keeping values that we managed to /// constant-fold on the given iteration. /// /// While we walk the loop instructions, we build up and maintain a mapping diff --git a/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h b/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h index 7d53e34938b7..5418128f16ef 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryBuiltins.h @@ -53,33 +53,33 @@ class Type; class UndefValue; class Value; -/// \brief Tests if a value is a call or invoke to a library function that +/// Tests if a value is a call or invoke to a library function that /// allocates or reallocates memory (either malloc, calloc, realloc, or strdup /// like). bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false); -/// \brief Tests if a value is a call or invoke to a function that returns a +/// Tests if a value is a call or invoke to a function that returns a /// NoAlias pointer (including malloc/calloc/realloc/strdup-like functions). bool isNoAliasFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false); -/// \brief Tests if a value is a call or invoke to a library function that +/// Tests if a value is a call or invoke to a library function that /// allocates uninitialized memory (such as malloc). bool isMallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false); -/// \brief Tests if a value is a call or invoke to a library function that +/// Tests if a value is a call or invoke to a library function that /// allocates zero-filled memory (such as calloc). bool isCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false); -/// \brief Tests if a value is a call or invoke to a library function that +/// Tests if a value is a call or invoke to a library function that /// allocates memory similar to malloc or calloc. bool isMallocOrCallocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false); -/// \brief Tests if a value is a call or invoke to a library function that +/// Tests if a value is a call or invoke to a library function that /// allocates memory (either malloc, calloc, or strdup like). bool isAllocLikeFn(const Value *V, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false); @@ -170,14 +170,14 @@ struct ObjectSizeOpts { bool NullIsUnknownSize = false; }; -/// \brief Compute the size of the object pointed by Ptr. Returns true and the +/// Compute the size of the object pointed by Ptr. Returns true and the /// object size in Size if successful, and false otherwise. In this context, by /// object we mean the region of memory starting at Ptr to the end of the /// underlying object pointed to by Ptr. bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, ObjectSizeOpts Opts = {}); -/// Try to turn a call to @llvm.objectsize into an integer value of the given +/// Try to turn a call to \@llvm.objectsize into an integer value of the given /// Type. Returns null on failure. /// If MustSucceed is true, this function will not return null, and may return /// conservative values governed by the second argument of the call to @@ -189,7 +189,7 @@ ConstantInt *lowerObjectSizeCall(IntrinsicInst *ObjectSize, using SizeOffsetType = std::pair<APInt, APInt>; -/// \brief Evaluate the size and offset of an object pointed to by a Value* +/// Evaluate the size and offset of an object pointed to by a Value* /// statically. Fails if size or offset are not known at compile time. class ObjectSizeOffsetVisitor : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> { @@ -248,7 +248,7 @@ private: using SizeOffsetEvalType = std::pair<Value *, Value *>; -/// \brief Evaluate the size and offset of an object pointed to by a Value*. +/// Evaluate the size and offset of an object pointed to by a Value*. /// May create code to compute the result at run-time. class ObjectSizeOffsetEvaluator : public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> { diff --git a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h index c2974525a6ff..1c6ec98dfedc 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -26,6 +26,7 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/PredIteratorCache.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/ErrorHandling.h" #include <cassert> @@ -302,7 +303,7 @@ private: /// The maximum size of the dereferences of the pointer. /// /// May be UnknownSize if the sizes are unknown. - uint64_t Size = MemoryLocation::UnknownSize; + LocationSize Size = MemoryLocation::UnknownSize; /// The AA tags associated with dereferences of the pointer. /// /// The members may be null if there are no tags or conflicting tags. @@ -314,7 +315,10 @@ private: /// Cache storing single nonlocal def for the instruction. /// It is set when nonlocal def would be found in function returning only /// local dependencies. - DenseMap<Instruction *, NonLocalDepResult> NonLocalDefsCache; + DenseMap<AssertingVH<const Value>, NonLocalDepResult> NonLocalDefsCache; + using ReverseNonLocalDefsCacheTy = + DenseMap<Instruction *, SmallPtrSet<const Value*, 4>>; + ReverseNonLocalDefsCacheTy ReverseNonLocalDefsCache; /// This map stores the cached results of doing a pointer lookup at the /// bottom of a block. diff --git a/contrib/llvm/include/llvm/Analysis/MemoryLocation.h b/contrib/llvm/include/llvm/Analysis/MemoryLocation.h index c1080742e83a..6b680000312c 100644 --- a/contrib/llvm/include/llvm/Analysis/MemoryLocation.h +++ b/contrib/llvm/include/llvm/Analysis/MemoryLocation.h @@ -27,8 +27,16 @@ class LoadInst; class StoreInst; class MemTransferInst; class MemIntrinsic; +class AtomicMemTransferInst; +class AtomicMemIntrinsic; +class AnyMemTransferInst; +class AnyMemIntrinsic; class TargetLibraryInfo; +// Represents the size of a MemoryLocation. Logically, it's an +// Optional<uint64_t>, with a special UnknownSize value from `MemoryLocation`. +using LocationSize = uint64_t; + /// Representation for a specific memory location. /// /// This abstraction can be used to represent a specific location in memory. @@ -55,7 +63,7 @@ public: /// virtual address space, because there are restrictions on stepping out of /// one object and into another. See /// http://llvm.org/docs/LangRef.html#pointeraliasing - uint64_t Size; + LocationSize Size; /// The metadata nodes which describes the aliasing of the location (each /// member is null if that kind of information is unavailable). @@ -90,17 +98,21 @@ public: /// Return a location representing the source of a memory transfer. static MemoryLocation getForSource(const MemTransferInst *MTI); + static MemoryLocation getForSource(const AtomicMemTransferInst *MTI); + static MemoryLocation getForSource(const AnyMemTransferInst *MTI); /// Return a location representing the destination of a memory set or /// transfer. static MemoryLocation getForDest(const MemIntrinsic *MI); + static MemoryLocation getForDest(const AtomicMemIntrinsic *MI); + static MemoryLocation getForDest(const AnyMemIntrinsic *MI); /// Return a location representing a particular argument of a call. static MemoryLocation getForArgument(ImmutableCallSite CS, unsigned ArgIdx, const TargetLibraryInfo &TLI); explicit MemoryLocation(const Value *Ptr = nullptr, - uint64_t Size = UnknownSize, + LocationSize Size = UnknownSize, const AAMDNodes &AATags = AAMDNodes()) : Ptr(Ptr), Size(Size), AATags(AATags) {} @@ -110,7 +122,7 @@ public: return Copy; } - MemoryLocation getWithNewSize(uint64_t NewSize) const { + MemoryLocation getWithNewSize(LocationSize NewSize) const { MemoryLocation Copy(*this); Copy.Size = NewSize; return Copy; @@ -137,7 +149,7 @@ template <> struct DenseMapInfo<MemoryLocation> { } static unsigned getHashValue(const MemoryLocation &Val) { return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^ - DenseMapInfo<uint64_t>::getHashValue(Val.Size) ^ + DenseMapInfo<LocationSize>::getHashValue(Val.Size) ^ DenseMapInfo<AAMDNodes>::getHashValue(Val.AATags); } static bool isEqual(const MemoryLocation &LHS, const MemoryLocation &RHS) { diff --git a/contrib/llvm/include/llvm/Analysis/MemorySSA.h b/contrib/llvm/include/llvm/Analysis/MemorySSA.h index d19f08453ee6..d445e4430e5c 100644 --- a/contrib/llvm/include/llvm/Analysis/MemorySSA.h +++ b/contrib/llvm/include/llvm/Analysis/MemorySSA.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief This file exposes an interface to building/using memory SSA to +/// This file exposes an interface to building/using memory SSA to /// walk memory instructions using a use/def graph. /// /// Memory SSA class builds an SSA form that links together memory access @@ -93,6 +93,7 @@ #include "llvm/IR/Use.h" #include "llvm/IR/User.h" #include "llvm/IR/Value.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" #include <algorithm> @@ -118,10 +119,10 @@ struct DefsOnlyTag {}; } // end namespace MSSAHelpers -enum { +enum : unsigned { // Used to signify what the default invalid ID is for MemoryAccess's // getID() - INVALID_MEMORYACCESS_ID = 0 + INVALID_MEMORYACCESS_ID = -1U }; template <class T> class memoryaccess_def_iterator_base; @@ -129,7 +130,7 @@ using memoryaccess_def_iterator = memoryaccess_def_iterator_base<MemoryAccess>; using const_memoryaccess_def_iterator = memoryaccess_def_iterator_base<const MemoryAccess>; -// \brief The base for all memory accesses. All memory accesses in a block are +// The base for all memory accesses. All memory accesses in a block are // linked together using an intrusive list. class MemoryAccess : public DerivedUser, @@ -158,11 +159,11 @@ public: void print(raw_ostream &OS) const; void dump() const; - /// \brief The user iterators for a memory access + /// The user iterators for a memory access using iterator = user_iterator; using const_iterator = const_user_iterator; - /// \brief This iterator walks over all of the defs in a given + /// This iterator walks over all of the defs in a given /// MemoryAccess. For MemoryPhi nodes, this walks arguments. For /// MemoryUse/MemoryDef, this walks the defining access. memoryaccess_def_iterator defs_begin(); @@ -170,7 +171,7 @@ public: memoryaccess_def_iterator defs_end(); const_memoryaccess_def_iterator defs_end() const; - /// \brief Get the iterators for the all access list and the defs only list + /// Get the iterators for the all access list and the defs only list /// We default to the all access list. AllAccessType::self_iterator getIterator() { return this->AllAccessType::getIterator(); @@ -204,11 +205,11 @@ protected: friend class MemoryUse; friend class MemoryUseOrDef; - /// \brief Used by MemorySSA to change the block of a MemoryAccess when it is + /// Used by MemorySSA to change the block of a MemoryAccess when it is /// moved. void setBlock(BasicBlock *BB) { Block = BB; } - /// \brief Used for debugging and tracking things about MemoryAccesses. + /// Used for debugging and tracking things about MemoryAccesses. /// Guaranteed unique among MemoryAccesses, no guarantees otherwise. inline unsigned getID() const; @@ -217,16 +218,24 @@ protected: : DerivedUser(Type::getVoidTy(C), Vty, nullptr, NumOperands, DeleteValue), Block(BB) {} + // Use deleteValue() to delete a generic MemoryAccess. + ~MemoryAccess() = default; + private: BasicBlock *Block; }; +template <> +struct ilist_alloc_traits<MemoryAccess> { + static void deleteNode(MemoryAccess *MA) { MA->deleteValue(); } +}; + inline raw_ostream &operator<<(raw_ostream &OS, const MemoryAccess &MA) { MA.print(OS); return OS; } -/// \brief Class that has the common methods + fields of memory uses/defs. It's +/// Class that has the common methods + fields of memory uses/defs. It's /// a little awkward to have, but there are many cases where we want either a /// use or def, and there are many cases where uses are needed (defs aren't /// acceptable), and vice-versa. @@ -239,10 +248,10 @@ public: DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess); - /// \brief Get the instruction that this MemoryUse represents. - Instruction *getMemoryInst() const { return MemoryInst; } + /// Get the instruction that this MemoryUse represents. + Instruction *getMemoryInst() const { return MemoryInstruction; } - /// \brief Get the access that produces the memory state used by this Use. + /// Get the access that produces the memory state used by this Use. MemoryAccess *getDefiningAccess() const { return getOperand(0); } static bool classof(const Value *MA) { @@ -255,7 +264,13 @@ public: inline MemoryAccess *getOptimized() const; inline void setOptimized(MemoryAccess *); - /// \brief Reset the ID of what this MemoryUse was optimized to, causing it to + // Retrieve AliasResult type of the optimized access. Ideally this would be + // returned by the caching walker and may go away in the future. + Optional<AliasResult> getOptimizedAccessType() const { + return OptimizedAccessAlias; + } + + /// Reset the ID of what this MemoryUse was optimized to, causing it to /// be rewalked by the walker if necessary. /// This really should only be called by tests. inline void resetOptimized(); @@ -266,20 +281,31 @@ protected: MemoryUseOrDef(LLVMContext &C, MemoryAccess *DMA, unsigned Vty, DeleteValueTy DeleteValue, Instruction *MI, BasicBlock *BB) - : MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInst(MI) { + : MemoryAccess(C, Vty, DeleteValue, BB, 1), MemoryInstruction(MI), + OptimizedAccessAlias(MayAlias) { setDefiningAccess(DMA); } - void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false) { + // Use deleteValue() to delete a generic MemoryUseOrDef. + ~MemoryUseOrDef() = default; + + void setOptimizedAccessType(Optional<AliasResult> AR) { + OptimizedAccessAlias = AR; + } + + void setDefiningAccess(MemoryAccess *DMA, bool Optimized = false, + Optional<AliasResult> AR = MayAlias) { if (!Optimized) { setOperand(0, DMA); return; } setOptimized(DMA); + setOptimizedAccessType(AR); } private: - Instruction *MemoryInst; + Instruction *MemoryInstruction; + Optional<AliasResult> OptimizedAccessAlias; }; template <> @@ -287,7 +313,7 @@ struct OperandTraits<MemoryUseOrDef> : public FixedNumOperandTraits<MemoryUseOrDef, 1> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUseOrDef, MemoryAccess) -/// \brief Represents read-only accesses to memory +/// Represents read-only accesses to memory /// /// In particular, the set of Instructions that will be represented by /// MemoryUse's is exactly the set of Instructions for which @@ -331,14 +357,14 @@ protected: private: static void deleteMe(DerivedUser *Self); - unsigned int OptimizedID = 0; + unsigned OptimizedID = INVALID_MEMORYACCESS_ID; }; template <> struct OperandTraits<MemoryUse> : public FixedNumOperandTraits<MemoryUse, 1> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryUse, MemoryAccess) -/// \brief Represents a read-write access to memory, whether it is a must-alias, +/// Represents a read-write access to memory, whether it is a must-alias, /// or a may-alias. /// /// In particular, the set of Instructions that will be represented by @@ -369,7 +395,9 @@ public: OptimizedID = getDefiningAccess()->getID(); } - MemoryAccess *getOptimized() const { return Optimized; } + MemoryAccess *getOptimized() const { + return cast_or_null<MemoryAccess>(Optimized); + } bool isOptimized() const { return getOptimized() && getDefiningAccess() && @@ -388,15 +416,15 @@ private: static void deleteMe(DerivedUser *Self); const unsigned ID; - MemoryAccess *Optimized = nullptr; - unsigned int OptimizedID = INVALID_MEMORYACCESS_ID; + unsigned OptimizedID = INVALID_MEMORYACCESS_ID; + WeakVH Optimized; }; template <> struct OperandTraits<MemoryDef> : public FixedNumOperandTraits<MemoryDef, 1> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryDef, MemoryAccess) -/// \brief Represents phi nodes for memory accesses. +/// Represents phi nodes for memory accesses. /// /// These have the same semantic as regular phi nodes, with the exception that /// only one phi will ever exist in a given basic block. @@ -476,10 +504,10 @@ public: const_op_range incoming_values() const { return operands(); } - /// \brief Return the number of incoming edges + /// Return the number of incoming edges unsigned getNumIncomingValues() const { return getNumOperands(); } - /// \brief Return incoming value number x + /// Return incoming value number x MemoryAccess *getIncomingValue(unsigned I) const { return getOperand(I); } void setIncomingValue(unsigned I, MemoryAccess *V) { assert(V && "PHI node got a null value!"); @@ -489,17 +517,17 @@ public: static unsigned getOperandNumForIncomingValue(unsigned I) { return I; } static unsigned getIncomingValueNumForOperand(unsigned I) { return I; } - /// \brief Return incoming basic block number @p i. + /// Return incoming basic block number @p i. BasicBlock *getIncomingBlock(unsigned I) const { return block_begin()[I]; } - /// \brief Return incoming basic block corresponding + /// Return incoming basic block corresponding /// to an operand of the PHI. BasicBlock *getIncomingBlock(const Use &U) const { assert(this == U.getUser() && "Iterator doesn't point to PHI's Uses?"); return getIncomingBlock(unsigned(&U - op_begin())); } - /// \brief Return incoming basic block corresponding + /// Return incoming basic block corresponding /// to value use iterator. BasicBlock *getIncomingBlock(MemoryAccess::const_user_iterator I) const { return getIncomingBlock(I.getUse()); @@ -510,7 +538,7 @@ public: block_begin()[I] = BB; } - /// \brief Add an incoming value to the end of the PHI list + /// Add an incoming value to the end of the PHI list void addIncoming(MemoryAccess *V, BasicBlock *BB) { if (getNumOperands() == ReservedSpace) growOperands(); // Get more space! @@ -520,7 +548,7 @@ public: setIncomingBlock(getNumOperands() - 1, BB); } - /// \brief Return the first index of the specified basic + /// Return the first index of the specified basic /// block in the value list for this PHI. Returns -1 if no instance. int getBasicBlockIndex(const BasicBlock *BB) const { for (unsigned I = 0, E = getNumOperands(); I != E; ++I) @@ -529,12 +557,53 @@ public: return -1; } - Value *getIncomingValueForBlock(const BasicBlock *BB) const { + MemoryAccess *getIncomingValueForBlock(const BasicBlock *BB) const { int Idx = getBasicBlockIndex(BB); assert(Idx >= 0 && "Invalid basic block argument!"); return getIncomingValue(Idx); } + // After deleting incoming position I, the order of incoming may be changed. + void unorderedDeleteIncoming(unsigned I) { + unsigned E = getNumOperands(); + assert(I < E && "Cannot remove out of bounds Phi entry."); + // MemoryPhi must have at least two incoming values, otherwise the MemoryPhi + // itself should be deleted. + assert(E >= 2 && "Cannot only remove incoming values in MemoryPhis with " + "at least 2 values."); + setIncomingValue(I, getIncomingValue(E - 1)); + setIncomingBlock(I, block_begin()[E - 1]); + setOperand(E - 1, nullptr); + block_begin()[E - 1] = nullptr; + setNumHungOffUseOperands(getNumOperands() - 1); + } + + // After deleting entries that satisfy Pred, remaining entries may have + // changed order. + template <typename Fn> void unorderedDeleteIncomingIf(Fn &&Pred) { + for (unsigned I = 0, E = getNumOperands(); I != E; ++I) + if (Pred(getIncomingValue(I), getIncomingBlock(I))) { + unorderedDeleteIncoming(I); + E = getNumOperands(); + --I; + } + assert(getNumOperands() >= 1 && + "Cannot remove all incoming blocks in a MemoryPhi."); + } + + // After deleting incoming block BB, the incoming blocks order may be changed. + void unorderedDeleteIncomingBlock(const BasicBlock *BB) { + unorderedDeleteIncomingIf( + [&](const MemoryAccess *, const BasicBlock *B) { return BB == B; }); + } + + // After deleting incoming memory access MA, the incoming accesses order may + // be changed. + void unorderedDeleteIncomingValue(const MemoryAccess *MA) { + unorderedDeleteIncomingIf( + [&](const MemoryAccess *M, const BasicBlock *) { return MA == M; }); + } + static bool classof(const Value *V) { return V->getValueID() == MemoryPhiVal; } @@ -546,7 +615,7 @@ public: protected: friend class MemorySSA; - /// \brief this is more complicated than the generic + /// this is more complicated than the generic /// User::allocHungoffUses, because we have to allocate Uses for the incoming /// values and pointers to the incoming blocks, all in one allocation. void allocHungoffUses(unsigned N) { @@ -558,7 +627,7 @@ private: const unsigned ID; unsigned ReservedSpace; - /// \brief This grows the operand list in response to a push_back style of + /// This grows the operand list in response to a push_back style of /// operation. This grows the number of ops by 1.5 times. void growOperands() { unsigned E = getNumOperands(); @@ -607,7 +676,7 @@ inline void MemoryUseOrDef::resetOptimized() { template <> struct OperandTraits<MemoryPhi> : public HungoffOperandTraits<2> {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(MemoryPhi, MemoryAccess) -/// \brief Encapsulates MemorySSA, including all data associated with memory +/// Encapsulates MemorySSA, including all data associated with memory /// accesses. class MemorySSA { public: @@ -616,7 +685,7 @@ public: MemorySSAWalker *getWalker(); - /// \brief Given a memory Mod/Ref'ing instruction, get the MemorySSA + /// Given a memory Mod/Ref'ing instruction, get the MemorySSA /// access associated with it. If passed a basic block gets the memory phi /// node that exists for that block, if there is one. Otherwise, this will get /// a MemoryUseOrDef. @@ -626,7 +695,7 @@ public: void dump() const; void print(raw_ostream &) const; - /// \brief Return true if \p MA represents the live on entry value + /// Return true if \p MA represents the live on entry value /// /// Loads and stores from pointer arguments and other global values may be /// defined by memory operations that do not occur in the current function, so @@ -650,14 +719,14 @@ public: using DefsList = simple_ilist<MemoryAccess, ilist_tag<MSSAHelpers::DefsOnlyTag>>; - /// \brief Return the list of MemoryAccess's for a given basic block. + /// Return the list of MemoryAccess's for a given basic block. /// /// This list is not modifiable by the user. const AccessList *getBlockAccesses(const BasicBlock *BB) const { return getWritableBlockAccesses(BB); } - /// \brief Return the list of MemoryDef's and MemoryPhi's for a given basic + /// Return the list of MemoryDef's and MemoryPhi's for a given basic /// block. /// /// This list is not modifiable by the user. @@ -665,19 +734,19 @@ public: return getWritableBlockDefs(BB); } - /// \brief Given two memory accesses in the same basic block, determine + /// Given two memory accesses in the same basic block, determine /// whether MemoryAccess \p A dominates MemoryAccess \p B. bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const; - /// \brief Given two memory accesses in potentially different blocks, + /// Given two memory accesses in potentially different blocks, /// determine whether MemoryAccess \p A dominates MemoryAccess \p B. bool dominates(const MemoryAccess *A, const MemoryAccess *B) const; - /// \brief Given a MemoryAccess and a Use, determine whether MemoryAccess \p A + /// Given a MemoryAccess and a Use, determine whether MemoryAccess \p A /// dominates Use \p B. bool dominates(const MemoryAccess *A, const Use &B) const; - /// \brief Verify that MemorySSA is self consistent (IE definitions dominate + /// Verify that MemorySSA is self consistent (IE definitions dominate /// all uses, uses appear in the right places). This is used by unit tests. void verifyMemorySSA() const; @@ -694,6 +763,7 @@ protected: void verifyDefUses(Function &F) const; void verifyDomination(Function &F) const; void verifyOrdering(Function &F) const; + void verifyDominationNumbers(const Function &F) const; // This is used by the use optimizer and updater. AccessList *getWritableBlockAccesses(const BasicBlock *BB) const { @@ -712,7 +782,7 @@ protected: // relies on the updater to fixup what it breaks, so it is not public. void moveTo(MemoryUseOrDef *What, BasicBlock *BB, AccessList::iterator Where); - void moveTo(MemoryUseOrDef *What, BasicBlock *BB, InsertionPlace Point); + void moveTo(MemoryAccess *What, BasicBlock *BB, InsertionPlace Point); // Rename the dominator tree branch rooted at BB. void renamePass(BasicBlock *BB, MemoryAccess *IncomingVal, @@ -748,8 +818,7 @@ private: MemoryPhi *createMemoryPhi(BasicBlock *BB); MemoryUseOrDef *createNewAccess(Instruction *); MemoryAccess *findDominatingDef(BasicBlock *, enum InsertionPlace); - void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &, - const DenseMap<const BasicBlock *, unsigned int> &); + void placePHINodes(const SmallPtrSetImpl<BasicBlock *> &); MemoryAccess *renameBlock(BasicBlock *, MemoryAccess *, bool); void renameSuccessorPhis(BasicBlock *, MemoryAccess *, bool); void renamePass(DomTreeNode *, MemoryAccess *IncomingVal, @@ -773,7 +842,7 @@ private: // corresponding list is empty. AccessMap PerBlockAccesses; DefsMap PerBlockDefs; - std::unique_ptr<MemoryAccess> LiveOnEntryDef; + std::unique_ptr<MemoryAccess, ValueDeleter> LiveOnEntryDef; // Domination mappings // Note that the numbering is local to a block, even though the map is @@ -831,7 +900,7 @@ public: Result run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Printer pass for \c MemorySSA. +/// Printer pass for \c MemorySSA. class MemorySSAPrinterPass : public PassInfoMixin<MemorySSAPrinterPass> { raw_ostream &OS; @@ -841,12 +910,12 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Verifier pass for \c MemorySSA. +/// Verifier pass for \c MemorySSA. struct MemorySSAVerifierPass : PassInfoMixin<MemorySSAVerifierPass> { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Legacy analysis pass which computes \c MemorySSA. +/// Legacy analysis pass which computes \c MemorySSA. class MemorySSAWrapperPass : public FunctionPass { public: MemorySSAWrapperPass(); @@ -867,7 +936,7 @@ private: std::unique_ptr<MemorySSA> MSSA; }; -/// \brief This is the generic walker interface for walkers of MemorySSA. +/// This is the generic walker interface for walkers of MemorySSA. /// Walkers are used to be able to further disambiguate the def-use chains /// MemorySSA gives you, or otherwise produce better info than MemorySSA gives /// you. @@ -885,7 +954,7 @@ public: using MemoryAccessSet = SmallVector<MemoryAccess *, 8>; - /// \brief Given a memory Mod/Ref/ModRef'ing instruction, calling this + /// Given a memory Mod/Ref/ModRef'ing instruction, calling this /// will give you the nearest dominating MemoryAccess that Mod's the location /// the instruction accesses (by skipping any def which AA can prove does not /// alias the location(s) accessed by the instruction given). @@ -917,7 +986,7 @@ public: /// but takes a MemoryAccess instead of an Instruction. virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *) = 0; - /// \brief Given a potentially clobbering memory access and a new location, + /// Given a potentially clobbering memory access and a new location, /// calling this will give you the nearest dominating clobbering MemoryAccess /// (by skipping non-aliasing def links). /// @@ -931,7 +1000,7 @@ public: virtual MemoryAccess *getClobberingMemoryAccess(MemoryAccess *, const MemoryLocation &) = 0; - /// \brief Given a memory access, invalidate anything this walker knows about + /// Given a memory access, invalidate anything this walker knows about /// that access. /// This API is used by walkers that store information to perform basic cache /// invalidation. This will be called by MemorySSA at appropriate times for @@ -946,7 +1015,7 @@ protected: MemorySSA *MSSA; }; -/// \brief A MemorySSAWalker that does no alias queries, or anything else. It +/// A MemorySSAWalker that does no alias queries, or anything else. It /// simply returns the links as they were constructed by the builder. class DoNothingMemorySSAWalker final : public MemorySSAWalker { public: @@ -962,7 +1031,7 @@ public: using MemoryAccessPair = std::pair<MemoryAccess *, MemoryLocation>; using ConstMemoryAccessPair = std::pair<const MemoryAccess *, MemoryLocation>; -/// \brief Iterator base class used to implement const and non-const iterators +/// Iterator base class used to implement const and non-const iterators /// over the defining accesses of a MemoryAccess. template <class T> class memoryaccess_def_iterator_base @@ -1035,7 +1104,7 @@ inline const_memoryaccess_def_iterator MemoryAccess::defs_end() const { return const_memoryaccess_def_iterator(); } -/// \brief GraphTraits for a MemoryAccess, which walks defs in the normal case, +/// GraphTraits for a MemoryAccess, which walks defs in the normal case, /// and uses in the inverse case. template <> struct GraphTraits<MemoryAccess *> { using NodeRef = MemoryAccess *; @@ -1055,7 +1124,7 @@ template <> struct GraphTraits<Inverse<MemoryAccess *>> { static ChildIteratorType child_end(NodeRef N) { return N->user_end(); } }; -/// \brief Provide an iterator that walks defs, giving both the memory access, +/// Provide an iterator that walks defs, giving both the memory access, /// and the current pointer location, updating the pointer location as it /// changes due to phi node translation. /// diff --git a/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h b/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h index b36b2f01dac6..38f08c1eebdc 100644 --- a/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h +++ b/contrib/llvm/include/llvm/Analysis/MemorySSAUpdater.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // \file -// \brief An automatic updater for MemorySSA that handles arbitrary insertion, +// An automatic updater for MemorySSA that handles arbitrary insertion, // deletion, and moves. It performs phi insertion where necessary, and // automatically updates the MemorySSA IR to be correct. // While updating loads or removing instructions is often easy enough to not @@ -33,6 +33,7 @@ #define LLVM_ANALYSIS_MEMORYSSAUPDATER_H #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/MemorySSA.h" #include "llvm/IR/BasicBlock.h" @@ -43,6 +44,7 @@ #include "llvm/IR/Use.h" #include "llvm/IR/User.h" #include "llvm/IR/Value.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -58,8 +60,13 @@ class raw_ostream; class MemorySSAUpdater { private: MemorySSA *MSSA; - SmallVector<MemoryPhi *, 8> InsertedPHIs; + + /// We use WeakVH rather than a costly deletion to deal with dangling pointers. + /// MemoryPhis are created eagerly and sometimes get zapped shortly afterwards. + SmallVector<WeakVH, 16> InsertedPHIs; + SmallPtrSet<BasicBlock *, 8> VisitedBlocks; + SmallSet<AssertingVH<MemoryPhi>, 8> NonOptPhis; public: MemorySSAUpdater(MemorySSA *MSSA) : MSSA(MSSA) {} @@ -86,6 +93,45 @@ public: void moveAfter(MemoryUseOrDef *What, MemoryUseOrDef *Where); void moveToPlace(MemoryUseOrDef *What, BasicBlock *BB, MemorySSA::InsertionPlace Where); + /// `From` block was spliced into `From` and `To`. + /// Move all accesses from `From` to `To` starting at instruction `Start`. + /// `To` is newly created BB, so empty of MemorySSA::MemoryAccesses. + /// Edges are already updated, so successors of `To` with MPhi nodes need to + /// update incoming block. + /// |------| |------| + /// | From | | From | + /// | | |------| + /// | | || + /// | | => \/ + /// | | |------| <- Start + /// | | | To | + /// |------| |------| + void moveAllAfterSpliceBlocks(BasicBlock *From, BasicBlock *To, + Instruction *Start); + /// `From` block was merged into `To`. All instructions were moved and + /// `From` is an empty block with successor edges; `From` is about to be + /// deleted. Move all accesses from `From` to `To` starting at instruction + /// `Start`. `To` may have multiple successors, `From` has a single + /// predecessor. `From` may have successors with MPhi nodes, replace their + /// incoming block with `To`. + /// |------| |------| + /// | To | | To | + /// |------| | | + /// || => | | + /// \/ | | + /// |------| | | <- Start + /// | From | | | + /// |------| |------| + void moveAllAfterMergeBlocks(BasicBlock *From, BasicBlock *To, + Instruction *Start); + /// BasicBlock Old had New, an empty BasicBlock, added directly before it, + /// and the predecessors in Preds that used to point to Old, now point to + /// New. If New is the only predecessor, move Old's Phi, if present, to New. + /// Otherwise, add a new Phi in New with appropriate incoming values, and + /// update the incoming values in Old's Phi node too, if present. + void + wireOldPredecessorsToNewImmediatePredecessor(BasicBlock *Old, BasicBlock *New, + ArrayRef<BasicBlock *> Preds); // The below are utility functions. Other than creation of accesses to pass // to insertDef, and removeAccess to remove accesses, you should generally @@ -93,7 +139,7 @@ public: // the edge cases right, and the above calls already operate in near-optimal // time bounds. - /// \brief Create a MemoryAccess in MemorySSA at a specified point in a block, + /// Create a MemoryAccess in MemorySSA at a specified point in a block, /// with a specified clobbering definition. /// /// Returns the new MemoryAccess. @@ -110,7 +156,7 @@ public: const BasicBlock *BB, MemorySSA::InsertionPlace Point); - /// \brief Create a MemoryAccess in MemorySSA before or after an existing + /// Create a MemoryAccess in MemorySSA before or after an existing /// MemoryAccess. /// /// Returns the new MemoryAccess. @@ -127,7 +173,7 @@ public: MemoryAccess *Definition, MemoryAccess *InsertPt); - /// \brief Remove a MemoryAccess from MemorySSA, including updating all + /// Remove a MemoryAccess from MemorySSA, including updating all /// definitions and uses. /// This should be called when a memory instruction that has a MemoryAccess /// associated with it is erased from the program. For example, if a store or @@ -135,18 +181,45 @@ public: /// on the MemoryAccess for that store/load. void removeMemoryAccess(MemoryAccess *); + /// Remove MemoryAccess for a given instruction, if a MemoryAccess exists. + /// This should be called when an instruction (load/store) is deleted from + /// the program. + void removeMemoryAccess(const Instruction *I) { + if (MemoryAccess *MA = MSSA->getMemoryAccess(I)) + removeMemoryAccess(MA); + } + + /// Remove all MemoryAcceses in a set of BasicBlocks about to be deleted. + /// Assumption we make here: all uses of deleted defs and phi must either + /// occur in blocks about to be deleted (thus will be deleted as well), or + /// they occur in phis that will simply lose an incoming value. + /// Deleted blocks still have successor info, but their predecessor edges and + /// Phi nodes may already be updated. Instructions in DeadBlocks should be + /// deleted after this call. + void removeBlocks(const SmallPtrSetImpl<BasicBlock *> &DeadBlocks); + + /// Get handle on MemorySSA. + MemorySSA* getMemorySSA() const { return MSSA; } + private: // Move What before Where in the MemorySSA IR. template <class WhereType> void moveTo(MemoryUseOrDef *What, BasicBlock *BB, WhereType Where); + // Move all memory accesses from `From` to `To` starting at `Start`. + // Restrictions apply, see public wrappers of this method. + void moveAllAccesses(BasicBlock *From, BasicBlock *To, Instruction *Start); MemoryAccess *getPreviousDef(MemoryAccess *); MemoryAccess *getPreviousDefInBlock(MemoryAccess *); - MemoryAccess *getPreviousDefFromEnd(BasicBlock *); - MemoryAccess *getPreviousDefRecursive(BasicBlock *); + MemoryAccess * + getPreviousDefFromEnd(BasicBlock *, + DenseMap<BasicBlock *, TrackingVH<MemoryAccess>> &); + MemoryAccess * + getPreviousDefRecursive(BasicBlock *, + DenseMap<BasicBlock *, TrackingVH<MemoryAccess>> &); MemoryAccess *recursePhi(MemoryAccess *Phi); template <class RangeType> MemoryAccess *tryRemoveTrivialPhi(MemoryPhi *Phi, RangeType &Operands); - void fixupDefs(const SmallVectorImpl<MemoryAccess *> &); + void fixupDefs(const SmallVectorImpl<WeakVH> &); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Analysis/MustExecute.h b/contrib/llvm/include/llvm/Analysis/MustExecute.h new file mode 100644 index 000000000000..8daf156567cd --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/MustExecute.h @@ -0,0 +1,64 @@ +//===- MustExecute.h - Is an instruction known to execute--------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// Contains a collection of routines for determining if a given instruction is +/// guaranteed to execute if a given point in control flow is reached. The most +/// common example is an instruction within a loop being provably executed if we +/// branch to the header of it's containing loop. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MUSTEXECUTE_H +#define LLVM_ANALYSIS_MUSTEXECUTE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Instruction.h" + +namespace llvm { + +class Instruction; +class DominatorTree; +class Loop; + +/// Captures loop safety information. +/// It keep information for loop & its header may throw exception or otherwise +/// exit abnormaly on any iteration of the loop which might actually execute +/// at runtime. The primary way to consume this infromation is via +/// isGuaranteedToExecute below, but some callers bailout or fallback to +/// alternate reasoning if a loop contains any implicit control flow. +struct LoopSafetyInfo { + bool MayThrow = false; // The current loop contains an instruction which + // may throw. + bool HeaderMayThrow = false; // Same as previous, but specific to loop header + // Used to update funclet bundle operands. + DenseMap<BasicBlock *, ColorVector> BlockColors; + + LoopSafetyInfo() = default; +}; + +/// Computes safety information for a loop checks loop body & header for +/// the possibility of may throw exception, it takes LoopSafetyInfo and loop as +/// argument. Updates safety information in LoopSafetyInfo argument. +/// Note: This is defined to clear and reinitialize an already initialized +/// LoopSafetyInfo. Some callers rely on this fact. +void computeLoopSafetyInfo(LoopSafetyInfo *, Loop *); + +/// Returns true if the instruction in a loop is guaranteed to execute at least +/// once (under the assumption that the loop is entered). +bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, + const Loop *CurLoop, + const LoopSafetyInfo *SafetyInfo); + +} + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h b/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h index db524ff64ecd..559c77c30811 100644 --- a/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h +++ b/contrib/llvm/include/llvm/Analysis/ObjCARCAliasAnalysis.h @@ -29,7 +29,7 @@ namespace llvm { namespace objcarc { -/// \brief This is a simple alias analysis implementation that uses knowledge +/// This is a simple alias analysis implementation that uses knowledge /// of ARC constructs to answer queries. /// /// TODO: This class could be generalized to know about other ObjC-specific diff --git a/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h b/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h index e80412a30564..07beb0bb60a3 100644 --- a/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h +++ b/contrib/llvm/include/llvm/Analysis/ObjCARCAnalysisUtils.h @@ -34,6 +34,7 @@ #include "llvm/IR/InstIterator.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" namespace llvm { @@ -43,10 +44,10 @@ class raw_ostream; namespace llvm { namespace objcarc { -/// \brief A handy option to enable/disable all ARC Optimizations. +/// A handy option to enable/disable all ARC Optimizations. extern bool EnableARCOpts; -/// \brief Test if the given module looks interesting to run ARC optimization +/// Test if the given module looks interesting to run ARC optimization /// on. inline bool ModuleHasARC(const Module &M) { return @@ -71,7 +72,7 @@ inline bool ModuleHasARC(const Module &M) { M.getNamedValue("clang.arc.use"); } -/// \brief This is a wrapper around getUnderlyingObject which also knows how to +/// This is a wrapper around getUnderlyingObject which also knows how to /// look through objc_retain and objc_autorelease calls, which we know to return /// their argument verbatim. inline const Value *GetUnderlyingObjCPtr(const Value *V, @@ -86,6 +87,18 @@ inline const Value *GetUnderlyingObjCPtr(const Value *V, return V; } +/// A wrapper for GetUnderlyingObjCPtr used for results memoization. +inline const Value * +GetUnderlyingObjCPtrCached(const Value *V, const DataLayout &DL, + DenseMap<const Value *, WeakTrackingVH> &Cache) { + if (auto InCache = Cache.lookup(V)) + return InCache; + + const Value *Computed = GetUnderlyingObjCPtr(V, DL); + Cache[V] = const_cast<Value *>(Computed); + return Computed; +} + /// The RCIdentity root of a value \p V is a dominating value U for which /// retaining or releasing U is equivalent to retaining or releasing V. In other /// words, ARC operations on \p V are equivalent to ARC operations on \p U. @@ -119,7 +132,7 @@ inline Value *GetRCIdentityRoot(Value *V) { return const_cast<Value *>(GetRCIdentityRoot((const Value *)V)); } -/// \brief Assuming the given instruction is one of the special calls such as +/// Assuming the given instruction is one of the special calls such as /// objc_retain or objc_release, return the RCIdentity root of the argument of /// the call. inline Value *GetArgRCIdentityRoot(Value *Inst) { @@ -136,7 +149,7 @@ inline bool IsNoopInstruction(const Instruction *I) { cast<GetElementPtrInst>(I)->hasAllZeroIndices()); } -/// \brief Test whether the given value is possible a retainable object pointer. +/// Test whether the given value is possible a retainable object pointer. inline bool IsPotentialRetainableObjPtr(const Value *Op) { // Pointers to static or stack storage are not valid retainable object // pointers. @@ -181,7 +194,7 @@ inline bool IsPotentialRetainableObjPtr(const Value *Op, return true; } -/// \brief Helper for GetARCInstKind. Determines what kind of construct CS +/// Helper for GetARCInstKind. Determines what kind of construct CS /// is. inline ARCInstKind GetCallSiteClass(ImmutableCallSite CS) { for (ImmutableCallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); @@ -192,7 +205,7 @@ inline ARCInstKind GetCallSiteClass(ImmutableCallSite CS) { return CS.onlyReadsMemory() ? ARCInstKind::None : ARCInstKind::Call; } -/// \brief Return true if this value refers to a distinct and identifiable +/// Return true if this value refers to a distinct and identifiable /// object. /// /// This is similar to AliasAnalysis's isIdentifiedObject, except that it uses diff --git a/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h b/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h index 02ff03578238..0b92d8b48356 100644 --- a/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h +++ b/contrib/llvm/include/llvm/Analysis/ObjCARCInstKind.h @@ -18,7 +18,7 @@ namespace objcarc { /// \enum ARCInstKind /// -/// \brief Equivalence classes of instructions in the ARC Model. +/// Equivalence classes of instructions in the ARC Model. /// /// Since we do not have "instructions" to represent ARC concepts in LLVM IR, /// we instead operate on equivalence classes of instructions. @@ -57,32 +57,32 @@ enum class ARCInstKind { raw_ostream &operator<<(raw_ostream &OS, const ARCInstKind Class); -/// \brief Test if the given class is a kind of user. +/// Test if the given class is a kind of user. bool IsUser(ARCInstKind Class); -/// \brief Test if the given class is objc_retain or equivalent. +/// Test if the given class is objc_retain or equivalent. bool IsRetain(ARCInstKind Class); -/// \brief Test if the given class is objc_autorelease or equivalent. +/// Test if the given class is objc_autorelease or equivalent. bool IsAutorelease(ARCInstKind Class); -/// \brief Test if the given class represents instructions which return their +/// Test if the given class represents instructions which return their /// argument verbatim. bool IsForwarding(ARCInstKind Class); -/// \brief Test if the given class represents instructions which do nothing if +/// Test if the given class represents instructions which do nothing if /// passed a null pointer. bool IsNoopOnNull(ARCInstKind Class); -/// \brief Test if the given class represents instructions which are always safe +/// Test if the given class represents instructions which are always safe /// to mark with the "tail" keyword. bool IsAlwaysTail(ARCInstKind Class); -/// \brief Test if the given class represents instructions which are never safe +/// Test if the given class represents instructions which are never safe /// to mark with the "tail" keyword. bool IsNeverTail(ARCInstKind Class); -/// \brief Test if the given class represents instructions which are always safe +/// Test if the given class represents instructions which are always safe /// to mark with the nounwind attribute. bool IsNoThrow(ARCInstKind Class); @@ -90,11 +90,11 @@ bool IsNoThrow(ARCInstKind Class); /// autoreleasepool pop. bool CanInterruptRV(ARCInstKind Class); -/// \brief Determine if F is one of the special known Functions. If it isn't, +/// Determine if F is one of the special known Functions. If it isn't, /// return ARCInstKind::CallOrUser. ARCInstKind GetFunctionClass(const Function *F); -/// \brief Determine which objc runtime call instruction class V belongs to. +/// Determine which objc runtime call instruction class V belongs to. /// /// This is similar to GetARCInstKind except that it only detects objc /// runtime calls. This allows it to be faster. diff --git a/contrib/llvm/include/llvm/Analysis/ObjectUtils.h b/contrib/llvm/include/llvm/Analysis/ObjectUtils.h deleted file mode 100644 index 2ad3b1717009..000000000000 --- a/contrib/llvm/include/llvm/Analysis/ObjectUtils.h +++ /dev/null @@ -1,42 +0,0 @@ -//===- Analysis/ObjectUtils.h - analysis utils for object files -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_OBJECT_UTILS_H -#define LLVM_ANALYSIS_OBJECT_UTILS_H - -#include "llvm/IR/GlobalVariable.h" - -namespace llvm { - -/// True if GV can be left out of the object symbol table. This is the case -/// for linkonce_odr values whose address is not significant. While legal, it is -/// not normally profitable to omit them from the .o symbol table. Using this -/// analysis makes sense when the information can be passed down to the linker -/// or we are in LTO. -inline bool canBeOmittedFromSymbolTable(const GlobalValue *GV) { - if (!GV->hasLinkOnceODRLinkage()) - return false; - - // We assume that anyone who sets global unnamed_addr on a non-constant knows - // what they're doing. - if (GV->hasGlobalUnnamedAddr()) - return true; - - // If it is a non constant variable, it needs to be uniqued across shared - // objects. - if (auto *Var = dyn_cast<GlobalVariable>(GV)) - if (!Var->isConstant()) - return false; - - return GV->hasAtLeastLocalUnnamedAddr(); -} - -} - -#endif diff --git a/contrib/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h b/contrib/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h index 26f32acdcda5..fa838696e2f8 100644 --- a/contrib/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h +++ b/contrib/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h @@ -40,7 +40,7 @@ public: OptimizationRemarkEmitter(const Function *F, BlockFrequencyInfo *BFI) : F(F), BFI(BFI) {} - /// \brief This variant can be used to generate ORE on demand (without the + /// This variant can be used to generate ORE on demand (without the /// analysis pass). /// /// Note that this ctor has a very different cost depending on whether @@ -66,11 +66,11 @@ public: bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &Inv); - /// \brief Output the remark via the diagnostic handler and to the + /// Output the remark via the diagnostic handler and to the /// optimization record file. void emit(DiagnosticInfoOptimizationBase &OptDiag); - /// \brief Take a lambda that returns a remark which will be emitted. Second + /// Take a lambda that returns a remark which will be emitted. Second /// argument is only used to restrict this to functions. template <typename T> void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { @@ -85,7 +85,7 @@ public: } } - /// \brief Whether we allow for extra compile-time budget to perform more + /// Whether we allow for extra compile-time budget to perform more /// analysis to produce fewer false positives. /// /// This is useful when reporting missed optimizations. In this case we can @@ -112,7 +112,7 @@ private: /// Similar but use value from \p OptDiag and update hotness there. void computeHotness(DiagnosticInfoIROptimization &OptDiag); - /// \brief Only allow verbose messages if we know we're filtering by hotness + /// Only allow verbose messages if we know we're filtering by hotness /// (BFI is only set in this case). bool shouldEmitVerbose() { return BFI != nullptr; } @@ -120,7 +120,7 @@ private: void operator=(const OptimizationRemarkEmitter &) = delete; }; -/// \brief Add a small namespace to avoid name clashes with the classes used in +/// Add a small namespace to avoid name clashes with the classes used in /// the streaming interface. We want these to be short for better /// write/readability. namespace ore { @@ -158,10 +158,10 @@ class OptimizationRemarkEmitterAnalysis static AnalysisKey Key; public: - /// \brief Provide the result typedef for this analysis pass. + /// Provide the result typedef for this analysis pass. typedef OptimizationRemarkEmitter Result; - /// \brief Run the analysis pass over a function and produce BFI. + /// Run the analysis pass over a function and produce BFI. Result run(Function &F, FunctionAnalysisManager &AM); }; } diff --git a/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h b/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h index 2e716af1f60d..0776aa626005 100644 --- a/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h +++ b/contrib/llvm/include/llvm/Analysis/OrderedBasicBlock.h @@ -33,28 +33,28 @@ class BasicBlock; class OrderedBasicBlock { private: - /// \brief Map a instruction to its position in a BasicBlock. + /// Map a instruction to its position in a BasicBlock. SmallDenseMap<const Instruction *, unsigned, 32> NumberedInsts; - /// \brief Keep track of last instruction inserted into \p NumberedInsts. + /// Keep track of last instruction inserted into \p NumberedInsts. /// It speeds up queries for uncached instructions by providing a start point /// for new queries in OrderedBasicBlock::comesBefore. BasicBlock::const_iterator LastInstFound; - /// \brief The position/number to tag the next instruction to be found. + /// The position/number to tag the next instruction to be found. unsigned NextInstPos; - /// \brief The source BasicBlock to map. + /// The source BasicBlock to map. const BasicBlock *BB; - /// \brief Given no cached results, find if \p A comes before \p B in \p BB. + /// Given no cached results, find if \p A comes before \p B in \p BB. /// Cache and number out instruction while walking \p BB. bool comesBefore(const Instruction *A, const Instruction *B); public: OrderedBasicBlock(const BasicBlock *BasicB); - /// \brief Find out whether \p A dominates \p B, meaning whether \p A + /// Find out whether \p A dominates \p B, meaning whether \p A /// comes before \p B in \p BB. This is a simplification that considers /// cached instruction positions and ignores other basic blocks, being /// only relevant to compare relative instructions positions inside \p BB. diff --git a/contrib/llvm/include/llvm/Analysis/PHITransAddr.h b/contrib/llvm/include/llvm/Analysis/PHITransAddr.h index f0f34f3a51f5..0a335b6be6c7 100644 --- a/contrib/llvm/include/llvm/Analysis/PHITransAddr.h +++ b/contrib/llvm/include/llvm/Analysis/PHITransAddr.h @@ -43,7 +43,7 @@ class PHITransAddr { /// TLI - The target library info if known, otherwise null. const TargetLibraryInfo *TLI; - /// A cache of @llvm.assume calls used by SimplifyInstruction. + /// A cache of \@llvm.assume calls used by SimplifyInstruction. AssumptionCache *AC; /// InstInputs - The inputs for our symbolic address. diff --git a/contrib/llvm/include/llvm/Analysis/Passes.h b/contrib/llvm/include/llvm/Analysis/Passes.h index 6d8f14fa32f9..09b28a0b0884 100644 --- a/contrib/llvm/include/llvm/Analysis/Passes.h +++ b/contrib/llvm/include/llvm/Analysis/Passes.h @@ -96,6 +96,14 @@ namespace llvm { // FunctionPass *createMemDerefPrinter(); + //===--------------------------------------------------------------------===// + // + // createMustExecutePrinter - This pass collects information about which + // instructions within a loop are guaranteed to execute if the loop header is + // entered and prints it with -analyze. + // + FunctionPass *createMustExecutePrinter(); + } #endif diff --git a/contrib/llvm/include/llvm/Analysis/PhiValues.h b/contrib/llvm/include/llvm/Analysis/PhiValues.h new file mode 100644 index 000000000000..6607b329c04f --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/PhiValues.h @@ -0,0 +1,143 @@ +//===- PhiValues.h - Phi Value Analysis -------------------------*- 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 PhiValues class, and associated passes, which can be +// used to find the underlying values of the phis in a function, i.e. the +// non-phi values that can be found by traversing the phi graph. +// +// This information is computed lazily and cached. If new phis are added to the +// function they are handled correctly, but if an existing phi has its operands +// modified PhiValues has to be notified by calling invalidateValue. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PHIVALUES_H +#define LLVM_ANALYSIS_PHIVALUES_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" + +namespace llvm { + +class Use; +class Value; +class PHINode; +class Function; + +/// Class for calculating and caching the underlying values of phis in a +/// function. +/// +/// Initially the PhiValues is empty, and gets incrementally populated whenever +/// it is queried. +class PhiValues { +public: + using ValueSet = SmallPtrSet<Value *, 4>; + + /// Construct an empty PhiValues. + PhiValues(const Function &F) : F(F) {} + + /// Get the underlying values of a phi. + /// + /// This returns the cached value if PN has previously been processed, + /// otherwise it processes it first. + const ValueSet &getValuesForPhi(const PHINode *PN); + + /// Notify PhiValues that the cached information using V is no longer valid + /// + /// Whenever a phi has its operands modified the cached values for that phi + /// (and the phis that use that phi) become invalid. A user of PhiValues has + /// to notify it of this by calling invalidateValue on either the operand or + /// the phi, which will then clear the relevant cached information. + void invalidateValue(const Value *V); + + /// Free the memory used by this class. + void releaseMemory(); + + /// Print out the values currently in the cache. + void print(raw_ostream &OS) const; + + /// Handle invalidation events in the new pass manager. + bool invalidate(Function &, const PreservedAnalyses &, + FunctionAnalysisManager::Invalidator &); + +private: + using PhiSet = SmallPtrSet<const PHINode *, 4>; + using ConstValueSet = SmallPtrSet<const Value *, 4>; + + /// The next depth number to be used by processPhi. + unsigned int NextDepthNumber = 1; + + /// Depth numbers of phis. Phis with the same depth number are part of the + /// same strongly connected component. + DenseMap<const PHINode *, unsigned int> DepthMap; + + /// Non-phi values reachable from each component. + DenseMap<unsigned int, ValueSet> NonPhiReachableMap; + + /// All values reachable from each component. + DenseMap<unsigned int, ConstValueSet> ReachableMap; + + /// The function that the PhiValues is for. + const Function &F; + + /// Process a phi so that its entries in the depth and reachable maps are + /// fully populated. + void processPhi(const PHINode *PN, SmallVector<const PHINode *, 8> &Stack); +}; + +/// The analysis pass which yields a PhiValues +/// +/// The analysis does nothing by itself, and just returns an empty PhiValues +/// which will get filled in as it's used. +class PhiValuesAnalysis : public AnalysisInfoMixin<PhiValuesAnalysis> { + friend AnalysisInfoMixin<PhiValuesAnalysis>; + static AnalysisKey Key; + +public: + using Result = PhiValues; + PhiValues run(Function &F, FunctionAnalysisManager &); +}; + +/// A pass for printing the PhiValues for a function. +/// +/// This pass doesn't print whatever information the PhiValues happens to hold, +/// but instead first uses the PhiValues to analyze all the phis in the function +/// so the complete information is printed. +class PhiValuesPrinterPass : public PassInfoMixin<PhiValuesPrinterPass> { + raw_ostream &OS; + +public: + explicit PhiValuesPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Wrapper pass for the legacy pass manager +class PhiValuesWrapperPass : public FunctionPass { + std::unique_ptr<PhiValues> Result; + +public: + static char ID; + PhiValuesWrapperPass(); + + PhiValues &getResult() { return *Result; } + const PhiValues &getResult() const { return *Result; } + + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/PostDominators.h b/contrib/llvm/include/llvm/Analysis/PostDominators.h index 381e65539c4e..f2dc8d135d71 100644 --- a/contrib/llvm/include/llvm/Analysis/PostDominators.h +++ b/contrib/llvm/include/llvm/Analysis/PostDominators.h @@ -26,15 +26,18 @@ class raw_ostream; /// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to /// compute the post-dominator tree. -struct PostDominatorTree : public PostDomTreeBase<BasicBlock> { +class PostDominatorTree : public PostDomTreeBase<BasicBlock> { +public: using Base = PostDomTreeBase<BasicBlock>; + PostDominatorTree() = default; + explicit PostDominatorTree(Function &F) { recalculate(F); } /// Handle invalidation explicitly. bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &); }; -/// \brief Analysis pass which computes a \c PostDominatorTree. +/// Analysis pass which computes a \c PostDominatorTree. class PostDominatorTreeAnalysis : public AnalysisInfoMixin<PostDominatorTreeAnalysis> { friend AnalysisInfoMixin<PostDominatorTreeAnalysis>; @@ -42,15 +45,15 @@ class PostDominatorTreeAnalysis static AnalysisKey Key; public: - /// \brief Provide the result type for this analysis pass. + /// Provide the result type for this analysis pass. using Result = PostDominatorTree; - /// \brief Run the analysis pass over a function and produce a post dominator + /// Run the analysis pass over a function and produce a post dominator /// tree. PostDominatorTree run(Function &F, FunctionAnalysisManager &); }; -/// \brief Printer pass for the \c PostDominatorTree. +/// Printer pass for the \c PostDominatorTree. class PostDominatorTreePrinterPass : public PassInfoMixin<PostDominatorTreePrinterPass> { raw_ostream &OS; @@ -75,6 +78,8 @@ struct PostDominatorTreeWrapperPass : public FunctionPass { bool runOnFunction(Function &F) override; + void verifyAnalysis() const override; + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } diff --git a/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h b/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h index 293033458429..58b67e74ba51 100644 --- a/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h +++ b/contrib/llvm/include/llvm/Analysis/ProfileSummaryInfo.h @@ -31,7 +31,7 @@ class BasicBlock; class BlockFrequencyInfo; class CallSite; class ProfileSummary; -/// \brief Analysis providing profile information. +/// Analysis providing profile information. /// /// This is an immutable analysis pass that provides ability to query global /// (program-level) profile information. The main APIs are isHotCount and @@ -59,16 +59,16 @@ public: ProfileSummaryInfo(ProfileSummaryInfo &&Arg) : M(Arg.M), Summary(std::move(Arg.Summary)) {} - /// \brief Returns true if profile summary is available. + /// Returns true if profile summary is available. bool hasProfileSummary() { return computeSummary(); } - /// \brief Returns true if module \c M has sample profile. + /// Returns true if module \c M has sample profile. bool hasSampleProfile() { return hasProfileSummary() && Summary->getKind() == ProfileSummary::PSK_Sample; } - /// \brief Returns true if module \c M has instrumentation profile. + /// Returns true if module \c M has instrumentation profile. bool hasInstrumentationProfile() { return hasProfileSummary() && Summary->getKind() == ProfileSummary::PSK_Instr; @@ -90,31 +90,37 @@ public: BlockFrequencyInfo *BFI); /// Returns true if the working set size of the code is considered huge. bool hasHugeWorkingSetSize(); - /// \brief Returns true if \p F has hot function entry. + /// Returns true if \p F has hot function entry. bool isFunctionEntryHot(const Function *F); /// Returns true if \p F contains hot code. bool isFunctionHotInCallGraph(const Function *F, BlockFrequencyInfo &BFI); - /// \brief Returns true if \p F has cold function entry. + /// Returns true if \p F has cold function entry. bool isFunctionEntryCold(const Function *F); /// Returns true if \p F contains only cold code. bool isFunctionColdInCallGraph(const Function *F, BlockFrequencyInfo &BFI); - /// \brief Returns true if \p F is a hot function. + /// Returns true if \p F is a hot function. bool isHotCount(uint64_t C); - /// \brief Returns true if count \p C is considered cold. + /// Returns true if count \p C is considered cold. bool isColdCount(uint64_t C); - /// \brief Returns true if BasicBlock \p B is considered hot. + /// Returns true if BasicBlock \p B is considered hot. bool isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI); - /// \brief Returns true if BasicBlock \p B is considered cold. + /// Returns true if BasicBlock \p B is considered cold. bool isColdBB(const BasicBlock *B, BlockFrequencyInfo *BFI); - /// \brief Returns true if CallSite \p CS is considered hot. + /// Returns true if CallSite \p CS is considered hot. bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI); - /// \brief Returns true if Callsite \p CS is considered cold. + /// Returns true if Callsite \p CS is considered cold. bool isColdCallSite(const CallSite &CS, BlockFrequencyInfo *BFI); - /// \brief Returns HotCountThreshold if set. + /// Returns HotCountThreshold if set. Recompute HotCountThreshold + /// if not set. + uint64_t getOrCompHotCountThreshold(); + /// Returns ColdCountThreshold if set. Recompute HotCountThreshold + /// if not set. + uint64_t getOrCompColdCountThreshold(); + /// Returns HotCountThreshold if set. uint64_t getHotCountThreshold() { return HotCountThreshold ? HotCountThreshold.getValue() : 0; } - /// \brief Returns ColdCountThreshold if set. + /// Returns ColdCountThreshold if set. uint64_t getColdCountThreshold() { return ColdCountThreshold ? ColdCountThreshold.getValue() : 0; } @@ -152,7 +158,7 @@ private: static AnalysisKey Key; }; -/// \brief Printer pass that uses \c ProfileSummaryAnalysis. +/// Printer pass that uses \c ProfileSummaryAnalysis. class ProfileSummaryPrinterPass : public PassInfoMixin<ProfileSummaryPrinterPass> { raw_ostream &OS; diff --git a/contrib/llvm/include/llvm/Analysis/PtrUseVisitor.h b/contrib/llvm/include/llvm/Analysis/PtrUseVisitor.h index 9f156a1a6029..b34b25c75040 100644 --- a/contrib/llvm/include/llvm/Analysis/PtrUseVisitor.h +++ b/contrib/llvm/include/llvm/Analysis/PtrUseVisitor.h @@ -47,7 +47,7 @@ namespace llvm { namespace detail { -/// \brief Implementation of non-dependent functionality for \c PtrUseVisitor. +/// Implementation of non-dependent functionality for \c PtrUseVisitor. /// /// See \c PtrUseVisitor for the public interface and detailed comments about /// usage. This class is just a helper base class which is not templated and @@ -55,7 +55,7 @@ namespace detail { /// PtrUseVisitor. class PtrUseVisitorBase { public: - /// \brief This class provides information about the result of a visit. + /// This class provides information about the result of a visit. /// /// After walking all the users (recursively) of a pointer, the basic /// infrastructure records some commonly useful information such as escape @@ -64,7 +64,7 @@ public: public: PtrInfo() : AbortedInfo(nullptr, false), EscapedInfo(nullptr, false) {} - /// \brief Reset the pointer info, clearing all state. + /// Reset the pointer info, clearing all state. void reset() { AbortedInfo.setPointer(nullptr); AbortedInfo.setInt(false); @@ -72,37 +72,37 @@ public: EscapedInfo.setInt(false); } - /// \brief Did we abort the visit early? + /// Did we abort the visit early? bool isAborted() const { return AbortedInfo.getInt(); } - /// \brief Is the pointer escaped at some point? + /// Is the pointer escaped at some point? bool isEscaped() const { return EscapedInfo.getInt(); } - /// \brief Get the instruction causing the visit to abort. + /// Get the instruction causing the visit to abort. /// \returns a pointer to the instruction causing the abort if one is /// available; otherwise returns null. Instruction *getAbortingInst() const { return AbortedInfo.getPointer(); } - /// \brief Get the instruction causing the pointer to escape. + /// Get the instruction causing the pointer to escape. /// \returns a pointer to the instruction which escapes the pointer if one /// is available; otherwise returns null. Instruction *getEscapingInst() const { return EscapedInfo.getPointer(); } - /// \brief Mark the visit as aborted. Intended for use in a void return. + /// Mark the visit as aborted. Intended for use in a void return. /// \param I The instruction which caused the visit to abort, if available. void setAborted(Instruction *I = nullptr) { AbortedInfo.setInt(true); AbortedInfo.setPointer(I); } - /// \brief Mark the pointer as escaped. Intended for use in a void return. + /// Mark the pointer as escaped. Intended for use in a void return. /// \param I The instruction which escapes the pointer, if available. void setEscaped(Instruction *I = nullptr) { EscapedInfo.setInt(true); EscapedInfo.setPointer(I); } - /// \brief Mark the pointer as escaped, and the visit as aborted. Intended + /// Mark the pointer as escaped, and the visit as aborted. Intended /// for use in a void return. /// \param I The instruction which both escapes the pointer and aborts the /// visit, if available. @@ -121,10 +121,10 @@ protected: /// \name Visitation infrastructure /// @{ - /// \brief The info collected about the pointer being visited thus far. + /// The info collected about the pointer being visited thus far. PtrInfo PI; - /// \brief A struct of the data needed to visit a particular use. + /// A struct of the data needed to visit a particular use. /// /// This is used to maintain a worklist fo to-visit uses. This is used to /// make the visit be iterative rather than recursive. @@ -135,10 +135,10 @@ protected: APInt Offset; }; - /// \brief The worklist of to-visit uses. + /// The worklist of to-visit uses. SmallVector<UseToVisit, 8> Worklist; - /// \brief A set of visited uses to break cycles in unreachable code. + /// A set of visited uses to break cycles in unreachable code. SmallPtrSet<Use *, 8> VisitedUses; /// @} @@ -147,14 +147,14 @@ protected: /// This state is reset for each instruction visited. /// @{ - /// \brief The use currently being visited. + /// The use currently being visited. Use *U; - /// \brief True if we have a known constant offset for the use currently + /// True if we have a known constant offset for the use currently /// being visited. bool IsOffsetKnown; - /// \brief The constant offset of the use if that is known. + /// The constant offset of the use if that is known. APInt Offset; /// @} @@ -163,13 +163,13 @@ protected: /// class, we can't create instances directly of this class. PtrUseVisitorBase(const DataLayout &DL) : DL(DL) {} - /// \brief Enqueue the users of this instruction in the visit worklist. + /// Enqueue the users of this instruction in the visit worklist. /// /// This will visit the users with the same offset of the current visit /// (including an unknown offset if that is the current state). void enqueueUsers(Instruction &I); - /// \brief Walk the operands of a GEP and adjust the offset as appropriate. + /// Walk the operands of a GEP and adjust the offset as appropriate. /// /// This routine does the heavy lifting of the pointer walk by computing /// offsets and looking through GEPs. @@ -178,7 +178,7 @@ protected: } // end namespace detail -/// \brief A base class for visitors over the uses of a pointer value. +/// A base class for visitors over the uses of a pointer value. /// /// Once constructed, a user can call \c visit on a pointer value, and this /// will walk its uses and visit each instruction using an InstVisitor. It also @@ -216,7 +216,7 @@ public: "Must pass the derived type to this template!"); } - /// \brief Recursively visit the uses of the given pointer. + /// Recursively visit the uses of the given pointer. /// \returns An info struct about the pointer. See \c PtrInfo for details. PtrInfo visitPtr(Instruction &I) { // This must be a pointer type. Get an integer type suitable to hold @@ -275,7 +275,7 @@ protected: enqueueUsers(GEPI); } - // No-op intrinsics which we know don't escape the pointer to to logic in + // No-op intrinsics which we know don't escape the pointer to logic in // some other function. void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) {} void visitMemIntrinsic(MemIntrinsic &I) {} diff --git a/contrib/llvm/include/llvm/Analysis/RegionInfo.h b/contrib/llvm/include/llvm/Analysis/RegionInfo.h index 719622359949..27f6cc197927 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionInfo.h +++ b/contrib/llvm/include/llvm/Analysis/RegionInfo.h @@ -42,6 +42,7 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Config/llvm-config.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/PassManager.h" @@ -62,7 +63,7 @@ class DominanceFrontier; class DominatorTree; class Loop; class LoopInfo; -struct PostDominatorTree; +class PostDominatorTree; class Region; template <class RegionTr> class RegionBase; class RegionInfo; @@ -102,7 +103,7 @@ struct RegionTraits<Function> { } }; -/// @brief Marker class to iterate over the elements of a Region in flat mode. +/// Marker class to iterate over the elements of a Region in flat mode. /// /// The class is used to either iterate in Flat mode or by not using it to not /// iterate in Flat mode. During a Flat mode iteration all Regions are entered @@ -112,7 +113,7 @@ struct RegionTraits<Function> { template <class GraphType> class FlatIt {}; -/// @brief A RegionNode represents a subregion or a BasicBlock that is part of a +/// A RegionNode represents a subregion or a BasicBlock that is part of a /// Region. template <class Tr> class RegionNodeBase { @@ -135,12 +136,12 @@ private: /// RegionNode. PointerIntPair<BlockT *, 1, bool> entry; - /// @brief The parent Region of this RegionNode. + /// The parent Region of this RegionNode. /// @see getParent() RegionT *parent; protected: - /// @brief Create a RegionNode. + /// Create a RegionNode. /// /// @param Parent The parent of this RegionNode. /// @param Entry The entry BasicBlock of the RegionNode. If this @@ -156,7 +157,7 @@ public: RegionNodeBase(const RegionNodeBase &) = delete; RegionNodeBase &operator=(const RegionNodeBase &) = delete; - /// @brief Get the parent Region of this RegionNode. + /// Get the parent Region of this RegionNode. /// /// The parent Region is the Region this RegionNode belongs to. If for /// example a BasicBlock is element of two Regions, there exist two @@ -166,7 +167,7 @@ public: /// @return Get the parent Region of this RegionNode. inline RegionT *getParent() const { return parent; } - /// @brief Get the entry BasicBlock of this RegionNode. + /// Get the entry BasicBlock of this RegionNode. /// /// If this RegionNode represents a BasicBlock this is just the BasicBlock /// itself, otherwise we return the entry BasicBlock of the Subregion @@ -174,7 +175,7 @@ public: /// @return The entry BasicBlock of this RegionNode. inline BlockT *getEntry() const { return entry.getPointer(); } - /// @brief Get the content of this RegionNode. + /// Get the content of this RegionNode. /// /// This can be either a BasicBlock or a subregion. Before calling getNodeAs() /// check the type of the content with the isSubRegion() function call. @@ -182,7 +183,7 @@ public: /// @return The content of this RegionNode. template <class T> inline T *getNodeAs() const; - /// @brief Is this RegionNode a subregion? + /// Is this RegionNode a subregion? /// /// @return True if it contains a subregion. False if it contains a /// BasicBlock. @@ -190,7 +191,7 @@ public: }; //===----------------------------------------------------------------------===// -/// @brief A single entry single exit Region. +/// A single entry single exit Region. /// /// A Region is a connected subgraph of a control flow graph that has exactly /// two connections to the remaining graph. It can be used to analyze or @@ -301,7 +302,7 @@ class RegionBase : public RegionNodeBase<Tr> { void verifyRegionNest() const; public: - /// @brief Create a new region. + /// Create a new region. /// /// @param Entry The entry basic block of the region. /// @param Exit The exit basic block of the region. @@ -318,25 +319,25 @@ public: /// Delete the Region and all its subregions. ~RegionBase(); - /// @brief Get the entry BasicBlock of the Region. + /// Get the entry BasicBlock of the Region. /// @return The entry BasicBlock of the region. BlockT *getEntry() const { return RegionNodeBase<Tr>::getEntry(); } - /// @brief Replace the entry basic block of the region with the new basic + /// Replace the entry basic block of the region with the new basic /// block. /// /// @param BB The new entry basic block of the region. void replaceEntry(BlockT *BB); - /// @brief Replace the exit basic block of the region with the new basic + /// Replace the exit basic block of the region with the new basic /// block. /// /// @param BB The new exit basic block of the region. void replaceExit(BlockT *BB); - /// @brief Recursively replace the entry basic block of the region. + /// Recursively replace the entry basic block of the region. /// /// This function replaces the entry basic block with a new basic block. It /// also updates all child regions that have the same entry basic block as @@ -345,7 +346,7 @@ public: /// @param NewEntry The new entry basic block. void replaceEntryRecursive(BlockT *NewEntry); - /// @brief Recursively replace the exit basic block of the region. + /// Recursively replace the exit basic block of the region. /// /// This function replaces the exit basic block with a new basic block. It /// also updates all child regions that have the same exit basic block as @@ -354,38 +355,38 @@ public: /// @param NewExit The new exit basic block. void replaceExitRecursive(BlockT *NewExit); - /// @brief Get the exit BasicBlock of the Region. + /// Get the exit BasicBlock of the Region. /// @return The exit BasicBlock of the Region, NULL if this is the TopLevel /// Region. BlockT *getExit() const { return exit; } - /// @brief Get the parent of the Region. + /// Get the parent of the Region. /// @return The parent of the Region or NULL if this is a top level /// Region. RegionT *getParent() const { return RegionNodeBase<Tr>::getParent(); } - /// @brief Get the RegionNode representing the current Region. + /// Get the RegionNode representing the current Region. /// @return The RegionNode representing the current Region. RegionNodeT *getNode() const { return const_cast<RegionNodeT *>( reinterpret_cast<const RegionNodeT *>(this)); } - /// @brief Get the nesting level of this Region. + /// Get the nesting level of this Region. /// /// An toplevel Region has depth 0. /// /// @return The depth of the region. unsigned getDepth() const; - /// @brief Check if a Region is the TopLevel region. + /// Check if a Region is the TopLevel region. /// /// The toplevel region represents the whole function. bool isTopLevelRegion() const { return exit == nullptr; } - /// @brief Return a new (non-canonical) region, that is obtained by joining + /// 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 @@ -393,43 +394,43 @@ public: /// NULL if such a basic block does not exist. RegionT *getExpandedRegion() const; - /// @brief Return the first block of this region's single entry edge, + /// Return the first block of this region's single entry edge, /// if existing. /// /// @return The BasicBlock starting this region's single entry edge, /// else NULL. BlockT *getEnteringBlock() const; - /// @brief Return the first block of this region's single exit edge, + /// Return the first block of this region's single exit edge, /// if existing. /// /// @return The BasicBlock starting this region's single exit edge, /// else NULL. BlockT *getExitingBlock() const; - /// @brief Collect all blocks of this region's single exit edge, if existing. + /// Collect all blocks of this region's single exit edge, if existing. /// /// @return True if this region contains all the predecessors of the exit. bool getExitingBlocks(SmallVectorImpl<BlockT *> &Exitings) const; - /// @brief Is this a simple region? + /// Is this a simple region? /// /// A region is simple if it has exactly one exit and one entry edge. /// /// @return True if the Region is simple. bool isSimple() const; - /// @brief Returns the name of the Region. + /// Returns the name of the Region. /// @return The Name of the Region. std::string getNameStr() const; - /// @brief Return the RegionInfo object, that belongs to this Region. + /// Return the RegionInfo object, that belongs to this Region. RegionInfoT *getRegionInfo() const { return RI; } /// PrintStyle - Print region in difference ways. enum PrintStyle { PrintNone, PrintBB, PrintRN }; - /// @brief Print the region. + /// Print the region. /// /// @param OS The output stream the Region is printed to. /// @param printTree Print also the tree of subregions. @@ -438,17 +439,17 @@ public: PrintStyle Style = PrintNone) const; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - /// @brief Print the region to stderr. + /// Print the region to stderr. void dump() const; #endif - /// @brief Check if the region contains a BasicBlock. + /// Check if the region contains a BasicBlock. /// /// @param BB The BasicBlock that might be contained in this Region. /// @return True if the block is contained in the region otherwise false. bool contains(const BlockT *BB) const; - /// @brief Check if the region contains another region. + /// Check if the region contains another region. /// /// @param SubRegion The region that might be contained in this Region. /// @return True if SubRegion is contained in the region otherwise false. @@ -462,14 +463,14 @@ public: SubRegion->getExit() == getExit()); } - /// @brief Check if the region contains an Instruction. + /// Check if the region contains an Instruction. /// /// @param Inst The Instruction that might be contained in this region. /// @return True if the Instruction is contained in the region otherwise /// false. bool contains(const InstT *Inst) const { return contains(Inst->getParent()); } - /// @brief Check if the region contains a loop. + /// Check if the region contains a loop. /// /// @param L The loop that might be contained in this region. /// @return True if the loop is contained in the region otherwise false. @@ -478,7 +479,7 @@ public: /// In that case true is returned. bool contains(const LoopT *L) const; - /// @brief Get the outermost loop in the region that contains a loop. + /// Get the outermost loop in the region that contains a loop. /// /// Find for a Loop L the outermost loop OuterL that is a parent loop of L /// and is itself contained in the region. @@ -488,7 +489,7 @@ public: /// exist or if the region describes the whole function. LoopT *outermostLoopInRegion(LoopT *L) const; - /// @brief Get the outermost loop in the region that contains a basic block. + /// Get the outermost loop in the region that contains a basic block. /// /// Find for a basic block BB the outermost loop L that contains BB and is /// itself contained in the region. @@ -499,13 +500,13 @@ public: /// exist or if the region describes the whole function. LoopT *outermostLoopInRegion(LoopInfoT *LI, BlockT *BB) const; - /// @brief Get the subregion that starts at a BasicBlock + /// Get the subregion that starts at a BasicBlock /// /// @param BB The BasicBlock the subregion should start. /// @return The Subregion if available, otherwise NULL. RegionT *getSubRegionNode(BlockT *BB) const; - /// @brief Get the RegionNode for a BasicBlock + /// Get the RegionNode for a BasicBlock /// /// @param BB The BasicBlock at which the RegionNode should start. /// @return If available, the RegionNode that represents the subregion @@ -513,38 +514,38 @@ public: /// representing BB. RegionNodeT *getNode(BlockT *BB) const; - /// @brief Get the BasicBlock RegionNode for a BasicBlock + /// Get the BasicBlock RegionNode for a BasicBlock /// /// @param BB The BasicBlock for which the RegionNode is requested. /// @return The RegionNode representing the BB. RegionNodeT *getBBNode(BlockT *BB) const; - /// @brief Add a new subregion to this Region. + /// Add a new subregion to this Region. /// /// @param SubRegion The new subregion that will be added. /// @param moveChildren Move the children of this region, that are also /// contained in SubRegion into SubRegion. void addSubRegion(RegionT *SubRegion, bool moveChildren = false); - /// @brief Remove a subregion from this Region. + /// Remove a subregion from this Region. /// /// The subregion is not deleted, as it will probably be inserted into another /// region. /// @param SubRegion The SubRegion that will be removed. RegionT *removeSubRegion(RegionT *SubRegion); - /// @brief Move all direct child nodes of this Region to another Region. + /// Move all direct child nodes of this Region to another Region. /// /// @param To The Region the child nodes will be transferred to. void transferChildrenTo(RegionT *To); - /// @brief Verify if the region is a correct region. + /// Verify if the region is a correct region. /// /// Check if this is a correctly build Region. This is an expensive check, as /// the complete CFG of the Region will be walked. void verifyRegion() const; - /// @brief Clear the cache for BB RegionNodes. + /// Clear the cache for BB RegionNodes. /// /// After calling this function the BasicBlock RegionNodes will be stored at /// different memory locations. RegionNodes obtained before this function is @@ -620,12 +621,12 @@ public: using block_range = iterator_range<block_iterator>; using const_block_range = iterator_range<const_block_iterator>; - /// @brief Returns a range view of the basic blocks in the region. + /// 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. + /// 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 { @@ -667,7 +668,7 @@ template <class Tr> inline raw_ostream &operator<<(raw_ostream &OS, const RegionNodeBase<Tr> &Node); //===----------------------------------------------------------------------===// -/// @brief Analysis that detects all canonical Regions. +/// Analysis that detects all canonical Regions. /// /// The RegionInfo pass detects all canonical regions in a function. The Regions /// are connected using the parent relation. This builds a Program Structure @@ -725,7 +726,7 @@ class RegionInfoBase { BBtoRegionMap BBtoRegion; protected: - /// \brief Update refences to a RegionInfoT held by the RegionT managed here + /// Update refences to a RegionInfoT held by the RegionT managed here /// /// This is a post-move helper. Regions hold references to the owning /// RegionInfo object. After a move these need to be fixed. @@ -739,7 +740,7 @@ protected: } private: - /// \brief Wipe this region tree's state without releasing any resources. + /// Wipe this region tree's state without releasing any resources. /// /// This is essentially a post-move helper only. It leaves the object in an /// assignable and destroyable state, but otherwise invalid. @@ -811,40 +812,40 @@ public: void releaseMemory(); - /// @brief Get the smallest region that contains a BasicBlock. + /// Get the smallest region that contains a BasicBlock. /// /// @param BB The basic block. /// @return The smallest region, that contains BB or NULL, if there is no /// region containing BB. RegionT *getRegionFor(BlockT *BB) const; - /// @brief Set the smallest region that surrounds a basic block. + /// Set the smallest region that surrounds a basic block. /// /// @param BB The basic block surrounded by a region. /// @param R The smallest region that surrounds BB. void setRegionFor(BlockT *BB, RegionT *R); - /// @brief A shortcut for getRegionFor(). + /// A shortcut for getRegionFor(). /// /// @param BB The basic block. /// @return The smallest region, that contains BB or NULL, if there is no /// region containing BB. RegionT *operator[](BlockT *BB) const; - /// @brief Return the exit of the maximal refined region, that starts at a + /// Return the exit of the maximal refined region, that starts at a /// BasicBlock. /// /// @param BB The BasicBlock the refined region starts. BlockT *getMaxRegionExit(BlockT *BB) const; - /// @brief Find the smallest region that contains two regions. + /// Find the smallest region that contains two regions. /// /// @param A The first region. /// @param B The second region. /// @return The smallest region containing A and B. RegionT *getCommonRegion(RegionT *A, RegionT *B) const; - /// @brief Find the smallest region that contains two basic blocks. + /// Find the smallest region that contains two basic blocks. /// /// @param A The first basic block. /// @param B The second basic block. @@ -853,13 +854,13 @@ public: return getCommonRegion(getRegionFor(A), getRegionFor(B)); } - /// @brief Find the smallest region that contains a set of regions. + /// Find the smallest region that contains a set of regions. /// /// @param Regions A vector of regions. /// @return The smallest region that contains all regions in Regions. RegionT *getCommonRegion(SmallVectorImpl<RegionT *> &Regions) const; - /// @brief Find the smallest region that contains a set of basic blocks. + /// Find the smallest region that contains a set of basic blocks. /// /// @param BBs A vector of basic blocks. /// @return The smallest region that contains all basic blocks in BBS. @@ -867,7 +868,7 @@ public: RegionT *getTopLevelRegion() const { return TopLevelRegion; } - /// @brief Clear the Node Cache for all Regions. + /// Clear the Node Cache for all Regions. /// /// @see Region::clearNodeCache() void clearNodeCache() { @@ -930,12 +931,12 @@ public: DominanceFrontier *DF); #ifndef NDEBUG - /// @brief Opens a viewer to show the GraphViz visualization of the regions. + /// Opens a viewer to show the GraphViz visualization of the regions. /// /// Useful during debugging as an alternative to dump(). void view(); - /// @brief Opens a viewer to show the GraphViz visualization of this region + /// Opens a viewer to show the GraphViz visualization of this region /// without instructions in the BasicBlocks. /// /// Useful during debugging as an alternative to dump(). @@ -967,7 +968,7 @@ public: //@} }; -/// \brief Analysis pass that exposes the \c RegionInfo for a function. +/// Analysis pass that exposes the \c RegionInfo for a function. class RegionInfoAnalysis : public AnalysisInfoMixin<RegionInfoAnalysis> { friend AnalysisInfoMixin<RegionInfoAnalysis>; @@ -979,7 +980,7 @@ public: RegionInfo run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Printer pass for the \c RegionInfo. +/// Printer pass for the \c RegionInfo. class RegionInfoPrinterPass : public PassInfoMixin<RegionInfoPrinterPass> { raw_ostream &OS; @@ -989,7 +990,7 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Verifier pass for the \c RegionInfo. +/// Verifier pass for the \c RegionInfo. struct RegionInfoVerifierPass : PassInfoMixin<RegionInfoVerifierPass> { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; diff --git a/contrib/llvm/include/llvm/Analysis/RegionInfoImpl.h b/contrib/llvm/include/llvm/Analysis/RegionInfoImpl.h index eb6baac2d5e4..5904214aa925 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionInfoImpl.h +++ b/contrib/llvm/include/llvm/Analysis/RegionInfoImpl.h @@ -22,6 +22,7 @@ #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionIterator.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -674,7 +675,7 @@ typename Tr::RegionT *RegionInfoBase<Tr>::createRegion(BlockT *entry, #ifdef EXPENSIVE_CHECKS region->verifyRegion(); #else - DEBUG(region->verifyRegion()); + LLVM_DEBUG(region->verifyRegion()); #endif updateStatistics(region); diff --git a/contrib/llvm/include/llvm/Analysis/RegionIterator.h b/contrib/llvm/include/llvm/Analysis/RegionIterator.h index 4f823cc82210..4fd92fcde20b 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionIterator.h +++ b/contrib/llvm/include/llvm/Analysis/RegionIterator.h @@ -26,7 +26,7 @@ namespace llvm { class BasicBlock; //===----------------------------------------------------------------------===// -/// @brief Hierarchical RegionNode successor iterator. +/// Hierarchical RegionNode successor iterator. /// /// This iterator iterates over all successors of a RegionNode. /// @@ -102,7 +102,7 @@ public: using Self = RNSuccIterator<NodeRef, BlockT, RegionT>; using value_type = typename super::value_type; - /// @brief Create begin iterator of a RegionNode. + /// Create begin iterator of a RegionNode. inline RNSuccIterator(NodeRef node) : Node(node, node->isSubRegion() ? ItRgBegin : ItBB), BItor(BlockTraits::child_begin(node->getEntry())) { @@ -115,7 +115,7 @@ public: advanceRegionSucc(); } - /// @brief Create an end iterator. + /// Create an end iterator. inline RNSuccIterator(NodeRef node, bool) : Node(node, node->isSubRegion() ? ItRgEnd : ItBB), BItor(BlockTraits::child_end(node->getEntry())) {} @@ -158,7 +158,7 @@ public: }; //===----------------------------------------------------------------------===// -/// @brief Flat RegionNode iterator. +/// Flat RegionNode iterator. /// /// The Flat Region iterator will iterate over all BasicBlock RegionNodes that /// are contained in the Region and its subregions. This is close to a virtual @@ -177,7 +177,7 @@ public: using Self = RNSuccIterator<FlatIt<NodeRef>, BlockT, RegionT>; using value_type = typename super::value_type; - /// @brief Create the iterator from a RegionNode. + /// Create the iterator from a RegionNode. /// /// Note that the incoming node must be a bb node, otherwise it will trigger /// an assertion when we try to get a BasicBlock. @@ -193,7 +193,7 @@ public: ++Itor; } - /// @brief Create an end iterator + /// Create an end iterator inline RNSuccIterator(NodeRef node, bool) : Node(node), Itor(BlockTraits::child_end(node->getEntry())) { assert(!Node->isSubRegion() && diff --git a/contrib/llvm/include/llvm/Analysis/RegionPass.h b/contrib/llvm/include/llvm/Analysis/RegionPass.h index 515b362e5407..b3da91c89cbd 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionPass.h +++ b/contrib/llvm/include/llvm/Analysis/RegionPass.h @@ -28,7 +28,7 @@ class RGPassManager; class Function; //===----------------------------------------------------------------------===// -/// @brief A pass that runs on each Region in a function. +/// A pass that runs on each Region in a function. /// /// RegionPass is managed by RGPassManager. class RegionPass : public Pass { @@ -39,7 +39,7 @@ public: /// @name To be implemented by every RegionPass /// //@{ - /// @brief Run the pass on a specific Region + /// Run the pass on a specific Region /// /// Accessing regions not contained in the current region is not allowed. /// @@ -49,7 +49,7 @@ public: /// @return True if the pass modifies this Region. virtual bool runOnRegion(Region *R, RGPassManager &RGM) = 0; - /// @brief Get a pass to print the LLVM IR in the region. + /// Get a pass to print the LLVM IR in the region. /// /// @param O The output stream to print the Region. /// @param Banner The banner to separate different printed passes. @@ -85,7 +85,7 @@ protected: bool skipRegion(Region &R) const; }; -/// @brief The pass manager to schedule RegionPasses. +/// The pass manager to schedule RegionPasses. class RGPassManager : public FunctionPass, public PMDataManager { std::deque<Region*> RQ; bool skipThisRegion; @@ -97,7 +97,7 @@ public: static char ID; explicit RGPassManager(); - /// @brief Execute all of the passes scheduled for execution. + /// Execute all of the passes scheduled for execution. /// /// @return True if any of the passes modifies the function. bool runOnFunction(Function &F) override; @@ -111,10 +111,10 @@ public: PMDataManager *getAsPMDataManager() override { return this; } Pass *getAsPass() override { return this; } - /// @brief Print passes managed by this manager. + /// Print passes managed by this manager. void dumpPassStructure(unsigned Offset) override; - /// @brief Get passes contained by this manager. + /// Get passes contained by this manager. Pass *getContainedPass(unsigned N) { assert(N < PassVector.size() && "Pass number out of range!"); Pass *FP = static_cast<Pass *>(PassVector[N]); diff --git a/contrib/llvm/include/llvm/Analysis/RegionPrinter.h b/contrib/llvm/include/llvm/Analysis/RegionPrinter.h index 8f0035cfd8e6..e132eaea5674 100644 --- a/contrib/llvm/include/llvm/Analysis/RegionPrinter.h +++ b/contrib/llvm/include/llvm/Analysis/RegionPrinter.h @@ -26,7 +26,7 @@ namespace llvm { FunctionPass *createRegionOnlyPrinterPass(); #ifndef NDEBUG - /// @brief Open a viewer to display the GraphViz vizualization of the analysis + /// Open a viewer to display the GraphViz vizualization of the analysis /// result. /// /// Practical to call in the debugger. @@ -35,7 +35,7 @@ namespace llvm { /// @param RI The analysis to display. void viewRegion(llvm::RegionInfo *RI); - /// @brief Analyze the regions of a function and open its GraphViz + /// Analyze the regions of a function and open its GraphViz /// visualization in a viewer. /// /// Useful to call in the debugger. @@ -46,7 +46,7 @@ namespace llvm { /// @param F Function to analyze. void viewRegion(const llvm::Function *F); - /// @brief Open a viewer to display the GraphViz vizualization of the analysis + /// Open a viewer to display the GraphViz vizualization of the analysis /// result. /// /// Useful to call in the debugger. @@ -55,7 +55,7 @@ namespace llvm { /// @param RI The analysis to display. void viewRegionOnly(llvm::RegionInfo *RI); - /// @brief Analyze the regions of a function and open its GraphViz + /// Analyze the regions of a function and open its GraphViz /// visualization in a viewer. /// /// Useful to call in the debugger. diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h index 21b72f3e13c2..89918e3c205b 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -587,7 +587,9 @@ public: const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getUMaxExpr(SmallVectorImpl<const SCEV *> &Operands); const SCEV *getSMinExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getSMinExpr(SmallVectorImpl<const SCEV *> &Operands); const SCEV *getUMinExpr(const SCEV *LHS, const SCEV *RHS); + const SCEV *getUMinExpr(SmallVectorImpl<const SCEV *> &Operands); const SCEV *getUnknown(Value *V); const SCEV *getCouldNotCompute(); @@ -650,6 +652,10 @@ public: /// then perform a umin operation with them. const SCEV *getUMinFromMismatchedTypes(const SCEV *LHS, const SCEV *RHS); + /// Promote the operands to the wider of the types using zero-extension, and + /// then perform a umin operation with them. N-ary function. + const SCEV *getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops); + /// Transitively follow the chain of pointer-type operands until reaching a /// SCEV that does not have a single pointer operand. This returns a /// SCEVUnknown pointer for well-formed pointer-type expressions, but corner @@ -678,7 +684,7 @@ public: const SCEV *LHS, const SCEV *RHS); /// Test whether the backedge of the loop is protected by a conditional - /// between LHS and RHS. This is used to to eliminate casts. + /// between LHS and RHS. This is used to eliminate casts. bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); @@ -764,6 +770,12 @@ public: /// loop bodies. void forgetLoop(const Loop *L); + // This method invokes forgetLoop for the outermost loop of the given loop + // \p L, making ScalarEvolution forget about all this subtree. This needs to + // be done whenever we make a transform that may affect the parameters of the + // outer loop, such as exit counts for branches. + void forgetTopmostLoop(const Loop *L); + /// This method should be called by the client when it has changed a value /// in a way that may effect its value, or which may disconnect it from a /// def-use chain linking it to a loop. @@ -829,11 +841,56 @@ public: /// Test if the given expression is known to be non-zero. bool isKnownNonZero(const SCEV *S); + /// Splits SCEV expression \p S into two SCEVs. One of them is obtained from + /// \p S by substitution of all AddRec sub-expression related to loop \p L + /// with initial value of that SCEV. The second is obtained from \p S by + /// substitution of all AddRec sub-expressions related to loop \p L with post + /// increment of this AddRec in the loop \p L. In both cases all other AddRec + /// sub-expressions (not related to \p L) remain the same. + /// If the \p S contains non-invariant unknown SCEV the function returns + /// CouldNotCompute SCEV in both values of std::pair. + /// For example, for SCEV S={0, +, 1}<L1> + {0, +, 1}<L2> and loop L=L1 + /// the function returns pair: + /// first = {0, +, 1}<L2> + /// second = {1, +, 1}<L1> + {0, +, 1}<L2> + /// We can see that for the first AddRec sub-expression it was replaced with + /// 0 (initial value) for the first element and to {1, +, 1}<L1> (post + /// increment value) for the second one. In both cases AddRec expression + /// related to L2 remains the same. + std::pair<const SCEV *, const SCEV *> SplitIntoInitAndPostInc(const Loop *L, + const SCEV *S); + + /// We'd like to check the predicate on every iteration of the most dominated + /// loop between loops used in LHS and RHS. + /// To do this we use the following list of steps: + /// 1. Collect set S all loops on which either LHS or RHS depend. + /// 2. If S is non-empty + /// a. Let PD be the element of S which is dominated by all other elements. + /// b. Let E(LHS) be value of LHS on entry of PD. + /// To get E(LHS), we should just take LHS and replace all AddRecs that are + /// attached to PD on with their entry values. + /// Define E(RHS) in the same way. + /// c. Let B(LHS) be value of L on backedge of PD. + /// To get B(LHS), we should just take LHS and replace all AddRecs that are + /// attached to PD on with their backedge values. + /// Define B(RHS) in the same way. + /// d. Note that E(LHS) and E(RHS) are automatically available on entry of PD, + /// so we can assert on that. + /// e. Return true if isLoopEntryGuardedByCond(Pred, E(LHS), E(RHS)) && + /// isLoopBackedgeGuardedByCond(Pred, B(LHS), B(RHS)) + bool isKnownViaInduction(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS); + /// Test if the given expression is known to satisfy the condition described /// by Pred, LHS, and RHS. bool isKnownPredicate(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); + /// Test if the condition described by Pred, LHS, RHS is known to be true on + /// every iteration of the loop of the recurrency LHS. + bool isKnownOnEveryIteration(ICmpInst::Predicate Pred, + const SCEVAddRecExpr *LHS, const SCEV *RHS); + /// Return true if, for all loop invariant X, the predicate "LHS `Pred` X" /// is monotonically increasing or decreasing. In the former case set /// `Increasing` to true and in the latter case set `Increasing` to false. @@ -1040,7 +1097,7 @@ private: /// The target library information for the target we are targeting. TargetLibraryInfo &TLI; - /// The tracker for @llvm.assume intrinsics in this function. + /// The tracker for \@llvm.assume intrinsics in this function. AssumptionCache &AC; /// The dominator tree. @@ -1094,6 +1151,12 @@ private: /// Mark predicate values currently being processed by isImpliedCond. SmallPtrSet<Value *, 6> PendingLoopPredicates; + /// Mark SCEVUnknown Phis currently being processed by getRangeRef. + SmallPtrSet<const PHINode *, 6> PendingPhiRanges; + + // Mark SCEVUnknown Phis currently being processed by isImpliedViaMerge. + SmallPtrSet<const PHINode *, 6> PendingMerges; + /// Set to true by isLoopBackedgeGuardedByCond when we're walking the set of /// conditions dominating the backedge of a loop. bool WalkingBEDominatingConds = false; @@ -1240,7 +1303,7 @@ private: /// If we allowed SCEV predicates to be generated when populating this /// vector, this information can contain them and therefore a /// SCEVPredicate argument should be added to getExact. - const SCEV *getExact(ScalarEvolution *SE, + const SCEV *getExact(const Loop *L, ScalarEvolution *SE, SCEVUnionPredicate *Predicates = nullptr) const; /// Return the number of times this loop exit may fall through to the back @@ -1424,8 +1487,7 @@ private: bool AllowPredicates = false); /// Compute the number of times the backedge of the specified loop will - /// execute if its exit condition were a conditional branch of ExitCond, - /// TBB, and FBB. + /// execute if its exit condition were a conditional branch of ExitCond. /// /// \p ControlsExit is true if ExitCond directly controls the exit /// branch. In this case, we can assume that the loop exits only if the @@ -1435,15 +1497,14 @@ private: /// If \p AllowPredicates is set, this call will try to use a minimal set of /// SCEV predicates in order to return an exact answer. ExitLimit computeExitLimitFromCond(const Loop *L, Value *ExitCond, - BasicBlock *TBB, BasicBlock *FBB, - bool ControlsExit, + bool ExitIfTrue, bool ControlsExit, bool AllowPredicates = false); // Helper functions for computeExitLimitFromCond to avoid exponential time // complexity. class ExitLimitCache { - // It may look like we need key on the whole (L, TBB, FBB, ControlsExit, + // It may look like we need key on the whole (L, ExitIfTrue, ControlsExit, // AllowPredicates) tuple, but recursive calls to // computeExitLimitFromCondCached from computeExitLimitFromCondImpl only // vary the in \c ExitCond and \c ControlsExit parameters. We remember the @@ -1451,43 +1512,39 @@ private: SmallDenseMap<PointerIntPair<Value *, 1>, ExitLimit> TripCountMap; const Loop *L; - BasicBlock *TBB; - BasicBlock *FBB; + bool ExitIfTrue; bool AllowPredicates; public: - ExitLimitCache(const Loop *L, BasicBlock *TBB, BasicBlock *FBB, - bool AllowPredicates) - : L(L), TBB(TBB), FBB(FBB), AllowPredicates(AllowPredicates) {} + ExitLimitCache(const Loop *L, bool ExitIfTrue, bool AllowPredicates) + : L(L), ExitIfTrue(ExitIfTrue), AllowPredicates(AllowPredicates) {} - Optional<ExitLimit> find(const Loop *L, Value *ExitCond, BasicBlock *TBB, - BasicBlock *FBB, bool ControlsExit, - bool AllowPredicates); + Optional<ExitLimit> find(const Loop *L, Value *ExitCond, bool ExitIfTrue, + bool ControlsExit, bool AllowPredicates); - void insert(const Loop *L, Value *ExitCond, BasicBlock *TBB, - BasicBlock *FBB, bool ControlsExit, bool AllowPredicates, - const ExitLimit &EL); + void insert(const Loop *L, Value *ExitCond, bool ExitIfTrue, + bool ControlsExit, bool AllowPredicates, const ExitLimit &EL); }; using ExitLimitCacheTy = ExitLimitCache; ExitLimit computeExitLimitFromCondCached(ExitLimitCacheTy &Cache, const Loop *L, Value *ExitCond, - BasicBlock *TBB, BasicBlock *FBB, + bool ExitIfTrue, bool ControlsExit, bool AllowPredicates); ExitLimit computeExitLimitFromCondImpl(ExitLimitCacheTy &Cache, const Loop *L, - Value *ExitCond, BasicBlock *TBB, - BasicBlock *FBB, bool ControlsExit, + Value *ExitCond, bool ExitIfTrue, + bool ControlsExit, bool AllowPredicates); /// Compute the number of times the backedge of the specified loop will /// execute if its exit condition were a conditional branch of the ICmpInst - /// ExitCond, TBB, and FBB. If AllowPredicates is set, this call will try + /// ExitCond and ExitIfTrue. If AllowPredicates is set, this call will try /// to use a minimal set of SCEV predicates in order to return an exact /// answer. ExitLimit computeExitLimitFromICmp(const Loop *L, ICmpInst *ExitCond, - BasicBlock *TBB, BasicBlock *FBB, + bool ExitIfTrue, bool IsSubExpr, bool AllowPredicates = false); @@ -1591,8 +1648,8 @@ private: /// Test whether the condition described by Pred, LHS, and RHS is true. /// Use only simple non-recursive types of checks, such as range analysis etc. - bool isKnownViaSimpleReasoning(ICmpInst::Predicate Pred, - const SCEV *LHS, const SCEV *RHS); + bool isKnownViaNonRecursiveReasoning(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS); /// Test whether the condition described by Pred, LHS, and RHS is true /// whenever the condition described by Pred, FoundLHS, and FoundRHS is @@ -1625,6 +1682,18 @@ private: const SCEV *FoundLHS, const SCEV *FoundRHS); + /// Test whether the condition described by Pred, LHS, and RHS is true + /// whenever the condition described by Pred, FoundLHS, and FoundRHS is + /// true. + /// + /// This routine tries to figure out predicate for Phis which are SCEVUnknown + /// if it is true for every possible incoming value from their respective + /// basic blocks. + bool isImpliedViaMerge(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, const SCEV *FoundRHS, + unsigned Depth); + /// If we know that the specified Phi is in the header of its containing /// loop, we know the loop executes a constant number of times, and the PHI /// node is just a recurrence involving constants, fold it. @@ -1764,10 +1833,22 @@ private: const SCEV *getOrCreateMulExpr(SmallVectorImpl<const SCEV *> &Ops, SCEV::NoWrapFlags Flags); + /// Return x if \p Val is f(x) where f is a 1-1 function. + const SCEV *stripInjectiveFunctions(const SCEV *Val) const; + + /// Find all of the loops transitively used in \p S, and fill \p LoopsUsed. + /// A loop is considered "used" by an expression if it contains + /// an add rec on said loop. + void getUsedLoops(const SCEV *S, SmallPtrSetImpl<const Loop *> &LoopsUsed); + /// Find all of the loops transitively used in \p S, and update \c LoopUsers /// accordingly. void addToLoopUseLists(const SCEV *S); + /// Try to match the pattern generated by getURemExpr(A, B). If successful, + /// Assign A and B to LHS and RHS, respectively. + bool matchURem(const SCEV *Expr, const SCEV *&LHS, const SCEV *&RHS); + FoldingSet<SCEV> UniqueSCEVs; FoldingSet<SCEVPredicate> UniquePreds; BumpPtrAllocator SCEVAllocator; diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h index 3df04e98bd24..58d42680d6bc 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -321,7 +321,7 @@ namespace llvm { /// Arrange for there to be a cast of V to Ty at IP, reusing an existing /// cast if a suitable one exists, moving an existing cast if a suitable one - /// exists but isn't in the right place, or or creating a new one. + /// exists but isn't in the right place, or creating a new one. Value *ReuseOrCreateCast(Value *V, Type *Ty, Instruction::CastOps Op, BasicBlock::iterator IP); @@ -335,6 +335,7 @@ namespace llvm { Value *expandAddToGEP(const SCEV *const *op_begin, const SCEV *const *op_end, PointerType *PTy, Type *Ty, Value *V); + Value *expandAddToGEP(const SCEV *Op, PointerType *PTy, Type *Ty, Value *V); /// Find a previous Value in ExprValueMap for expand. ScalarEvolution::ValueOffsetPair diff --git a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h index acf83455cdcd..42e76094eb2b 100644 --- a/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/contrib/llvm/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -350,9 +350,7 @@ class Type; /// Return an expression representing the value of this expression /// one iteration of the loop ahead. - const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const { - return cast<SCEVAddRecExpr>(SE.getAddExpr(this, getStepRecurrence(SE))); - } + const SCEVAddRecExpr *getPostIncExpr(ScalarEvolution &SE) const; /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const SCEV *S) { diff --git a/contrib/llvm/include/llvm/Analysis/SparsePropagation.h b/contrib/llvm/include/llvm/Analysis/SparsePropagation.h index 1b8df03b3a1b..defcf96afb25 100644 --- a/contrib/llvm/include/llvm/Analysis/SparsePropagation.h +++ b/contrib/llvm/include/llvm/Analysis/SparsePropagation.h @@ -238,7 +238,7 @@ SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getValueState(LatticeKey Key) { // If this value is untracked, don't add it to the map. if (LV == LatticeFunc->getUntrackedVal()) return LV; - return ValueState[Key] = LV; + return ValueState[Key] = std::move(LV); } template <class LatticeKey, class LatticeVal, class KeyInfo> @@ -250,7 +250,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::UpdateState(LatticeKey Key, // Update the state of the given LatticeKey and add its corresponding LLVM // value to the work list. - ValueState[Key] = LV; + ValueState[Key] = std::move(LV); if (Value *V = KeyInfo::getValueFromLatticeKey(Key)) ValueWorkList.push_back(V); } @@ -260,7 +260,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::MarkBlockExecutable( BasicBlock *BB) { if (!BBExecutable.insert(BB).second) return; - DEBUG(dbgs() << "Marking Block Executable: " << BB->getName() << "\n"); + LLVM_DEBUG(dbgs() << "Marking Block Executable: " << BB->getName() << "\n"); BBWorkList.push_back(BB); // Add the block to the work list! } @@ -270,8 +270,8 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::markEdgeExecutable( if (!KnownFeasibleEdges.insert(Edge(Source, Dest)).second) return; // This edge is already known to be executable! - DEBUG(dbgs() << "Marking Edge Executable: " << Source->getName() << " -> " - << Dest->getName() << "\n"); + LLVM_DEBUG(dbgs() << "Marking Edge Executable: " << Source->getName() + << " -> " << Dest->getName() << "\n"); if (BBExecutable.count(Dest)) { // The destination is already executable, but we just made an edge @@ -318,7 +318,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors( Constant *C = dyn_cast_or_null<Constant>(LatticeFunc->GetValueFromLatticeVal( - BCValue, BI->getCondition()->getType())); + std::move(BCValue), BI->getCondition()->getType())); if (!C || !isa<ConstantInt>(C)) { // Non-constant values can go either way. Succs[0] = Succs[1] = true; @@ -360,7 +360,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::getFeasibleSuccessors( return; Constant *C = dyn_cast_or_null<Constant>(LatticeFunc->GetValueFromLatticeVal( - SCValue, SI.getCondition()->getType())); + std::move(SCValue), SI.getCondition()->getType())); if (!C || !isa<ConstantInt>(C)) { // All destinations are executable! Succs.assign(TI.getNumSuccessors(), true); @@ -408,7 +408,8 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::visitPHINode(PHINode &PN) { LatticeFunc->ComputeInstructionState(PN, ChangedValues, *this); for (auto &ChangedValue : ChangedValues) if (ChangedValue.second != LatticeFunc->getUntrackedVal()) - UpdateState(ChangedValue.first, ChangedValue.second); + UpdateState(std::move(ChangedValue.first), + std::move(ChangedValue.second)); return; } @@ -477,7 +478,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::Solve() { Value *V = ValueWorkList.back(); ValueWorkList.pop_back(); - DEBUG(dbgs() << "\nPopped off V-WL: " << *V << "\n"); + LLVM_DEBUG(dbgs() << "\nPopped off V-WL: " << *V << "\n"); // "V" got into the work list because it made a transition. See if any // users are both live and in need of updating. @@ -492,7 +493,7 @@ void SparseSolver<LatticeKey, LatticeVal, KeyInfo>::Solve() { BasicBlock *BB = BBWorkList.back(); BBWorkList.pop_back(); - DEBUG(dbgs() << "\nPopped off BBWL: " << *BB); + LLVM_DEBUG(dbgs() << "\nPopped off BBWL: " << *BB); // Notify all instructions in this basic block that they are newly // executable. diff --git a/contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h b/contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h new file mode 100644 index 000000000000..87f4a0100b38 --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/SyntheticCountsUtils.h @@ -0,0 +1,52 @@ +//===- SyntheticCountsUtils.h - utilities for count propagation--*- 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 synthetic counts propagation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SYNTHETIC_COUNTS_UTILS_H +#define LLVM_ANALYSIS_SYNTHETIC_COUNTS_UTILS_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Support/ScaledNumber.h" + +namespace llvm { + +class CallGraph; +class Function; + +/// Class with methods to propagate synthetic entry counts. +/// +/// This class is templated on the type of the call graph and designed to work +/// with the traditional per-module callgraph and the summary callgraphs used in +/// ThinLTO. This contains only static methods and alias templates. +template <typename CallGraphType> class SyntheticCountsUtils { +public: + using Scaled64 = ScaledNumber<uint64_t>; + using CGT = GraphTraits<CallGraphType>; + using NodeRef = typename CGT::NodeRef; + using EdgeRef = typename CGT::EdgeRef; + using SccTy = std::vector<NodeRef>; + + using GetRelBBFreqTy = function_ref<Optional<Scaled64>(EdgeRef)>; + using GetCountTy = function_ref<uint64_t(NodeRef)>; + using AddCountTy = function_ref<void(NodeRef, uint64_t)>; + + static void propagate(const CallGraphType &CG, GetRelBBFreqTy GetRelBBFreq, + GetCountTy GetCount, AddCountTy AddCount); + +private: + static void propagateFromSCC(const SccTy &SCC, GetRelBBFreqTy GetRelBBFreq, + GetCountTy GetCount, AddCountTy AddCount); +}; +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def index a461ed813b9b..f94debba9c52 100644 --- a/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/contrib/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -119,6 +119,12 @@ TLI_DEFINE_STRING_INTERNAL("_ZdaPv") /// void operator delete[](void*, nothrow); TLI_DEFINE_ENUM_INTERNAL(ZdaPvRKSt9nothrow_t) TLI_DEFINE_STRING_INTERNAL("_ZdaPvRKSt9nothrow_t") +/// void operator delete[](void*, align_val_t); +TLI_DEFINE_ENUM_INTERNAL(ZdaPvSt11align_val_t) +TLI_DEFINE_STRING_INTERNAL("_ZdaPvSt11align_val_t") +/// void operator delete[](void*, align_val_t, nothrow) +TLI_DEFINE_ENUM_INTERNAL(ZdaPvSt11align_val_tRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZdaPvSt11align_val_tRKSt9nothrow_t") /// void operator delete[](void*, unsigned int); TLI_DEFINE_ENUM_INTERNAL(ZdaPvj) TLI_DEFINE_STRING_INTERNAL("_ZdaPvj") @@ -131,6 +137,12 @@ TLI_DEFINE_STRING_INTERNAL("_ZdlPv") /// void operator delete(void*, nothrow); TLI_DEFINE_ENUM_INTERNAL(ZdlPvRKSt9nothrow_t) TLI_DEFINE_STRING_INTERNAL("_ZdlPvRKSt9nothrow_t") +/// void operator delete(void*, align_val_t) +TLI_DEFINE_ENUM_INTERNAL(ZdlPvSt11align_val_t) +TLI_DEFINE_STRING_INTERNAL("_ZdlPvSt11align_val_t") +/// void operator delete(void*, align_val_t, nothrow) +TLI_DEFINE_ENUM_INTERNAL(ZdlPvSt11align_val_tRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZdlPvSt11align_val_tRKSt9nothrow_t") /// void operator delete(void*, unsigned int); TLI_DEFINE_ENUM_INTERNAL(ZdlPvj) TLI_DEFINE_STRING_INTERNAL("_ZdlPvj") @@ -143,24 +155,48 @@ TLI_DEFINE_STRING_INTERNAL("_Znaj") /// void *new[](unsigned int, nothrow); TLI_DEFINE_ENUM_INTERNAL(ZnajRKSt9nothrow_t) TLI_DEFINE_STRING_INTERNAL("_ZnajRKSt9nothrow_t") +/// void *new[](unsigned int, align_val_t) +TLI_DEFINE_ENUM_INTERNAL(ZnajSt11align_val_t) +TLI_DEFINE_STRING_INTERNAL("_ZnajSt11align_val_t") +/// void *new[](unsigned int, align_val_t, nothrow) +TLI_DEFINE_ENUM_INTERNAL(ZnajSt11align_val_tRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnajSt11align_val_tRKSt9nothrow_t") /// void *new[](unsigned long); TLI_DEFINE_ENUM_INTERNAL(Znam) TLI_DEFINE_STRING_INTERNAL("_Znam") /// void *new[](unsigned long, nothrow); TLI_DEFINE_ENUM_INTERNAL(ZnamRKSt9nothrow_t) TLI_DEFINE_STRING_INTERNAL("_ZnamRKSt9nothrow_t") +/// void *new[](unsigned long, align_val_t) +TLI_DEFINE_ENUM_INTERNAL(ZnamSt11align_val_t) +TLI_DEFINE_STRING_INTERNAL("_ZnamSt11align_val_t") +/// void *new[](unsigned long, align_val_t, nothrow) +TLI_DEFINE_ENUM_INTERNAL(ZnamSt11align_val_tRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnamSt11align_val_tRKSt9nothrow_t") /// void *new(unsigned int); TLI_DEFINE_ENUM_INTERNAL(Znwj) TLI_DEFINE_STRING_INTERNAL("_Znwj") /// void *new(unsigned int, nothrow); TLI_DEFINE_ENUM_INTERNAL(ZnwjRKSt9nothrow_t) TLI_DEFINE_STRING_INTERNAL("_ZnwjRKSt9nothrow_t") +/// void *new(unsigned int, align_val_t) +TLI_DEFINE_ENUM_INTERNAL(ZnwjSt11align_val_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwjSt11align_val_t") +/// void *new(unsigned int, align_val_t, nothrow) +TLI_DEFINE_ENUM_INTERNAL(ZnwjSt11align_val_tRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwjSt11align_val_tRKSt9nothrow_t") /// void *new(unsigned long); TLI_DEFINE_ENUM_INTERNAL(Znwm) TLI_DEFINE_STRING_INTERNAL("_Znwm") /// void *new(unsigned long, nothrow); TLI_DEFINE_ENUM_INTERNAL(ZnwmRKSt9nothrow_t) TLI_DEFINE_STRING_INTERNAL("_ZnwmRKSt9nothrow_t") +/// void *new(unsigned long, align_val_t) +TLI_DEFINE_ENUM_INTERNAL(ZnwmSt11align_val_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwmSt11align_val_t") +/// void *new(unsigned long, align_val_t, nothrow) +TLI_DEFINE_ENUM_INTERNAL(ZnwmSt11align_val_tRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwmSt11align_val_tRKSt9nothrow_t") /// double __acos_finite(double x); TLI_DEFINE_ENUM_INTERNAL(acos_finite) TLI_DEFINE_STRING_INTERNAL("__acos_finite") @@ -601,12 +637,18 @@ TLI_DEFINE_STRING_INTERNAL("ffsll") /// int fgetc(FILE *stream); TLI_DEFINE_ENUM_INTERNAL(fgetc) TLI_DEFINE_STRING_INTERNAL("fgetc") +/// int fgetc_unlocked(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fgetc_unlocked) +TLI_DEFINE_STRING_INTERNAL("fgetc_unlocked") /// int fgetpos(FILE *stream, fpos_t *pos); TLI_DEFINE_ENUM_INTERNAL(fgetpos) TLI_DEFINE_STRING_INTERNAL("fgetpos") /// char *fgets(char *s, int n, FILE *stream); TLI_DEFINE_ENUM_INTERNAL(fgets) TLI_DEFINE_STRING_INTERNAL("fgets") +/// char *fgets_unlocked(char *s, int n, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fgets_unlocked) +TLI_DEFINE_STRING_INTERNAL("fgets_unlocked") /// int fileno(FILE *stream); TLI_DEFINE_ENUM_INTERNAL(fileno) TLI_DEFINE_STRING_INTERNAL("fileno") @@ -673,12 +715,21 @@ TLI_DEFINE_STRING_INTERNAL("fprintf") /// int fputc(int c, FILE *stream); TLI_DEFINE_ENUM_INTERNAL(fputc) TLI_DEFINE_STRING_INTERNAL("fputc") +/// int fputc_unlocked(int c, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fputc_unlocked) +TLI_DEFINE_STRING_INTERNAL("fputc_unlocked") /// int fputs(const char *s, FILE *stream); TLI_DEFINE_ENUM_INTERNAL(fputs) TLI_DEFINE_STRING_INTERNAL("fputs") +/// int fputs_unlocked(const char *s, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fputs_unlocked) +TLI_DEFINE_STRING_INTERNAL("fputs_unlocked") /// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); TLI_DEFINE_ENUM_INTERNAL(fread) TLI_DEFINE_STRING_INTERNAL("fread") +/// size_t fread_unlocked(void *ptr, size_t size, size_t nitems, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fread_unlocked) +TLI_DEFINE_STRING_INTERNAL("fread_unlocked") /// void free(void *ptr); TLI_DEFINE_ENUM_INTERNAL(free) TLI_DEFINE_STRING_INTERNAL("free") @@ -736,6 +787,9 @@ TLI_DEFINE_STRING_INTERNAL("funlockfile") /// size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream); TLI_DEFINE_ENUM_INTERNAL(fwrite) TLI_DEFINE_STRING_INTERNAL("fwrite") +/// size_t fwrite_unlocked(const void *ptr, size_t size, size_t nitems, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fwrite_unlocked) +TLI_DEFINE_STRING_INTERNAL("fwrite_unlocked") /// int getc(FILE *stream); TLI_DEFINE_ENUM_INTERNAL(getc) TLI_DEFINE_STRING_INTERNAL("getc") @@ -745,6 +799,9 @@ TLI_DEFINE_STRING_INTERNAL("getc_unlocked") /// int getchar(void); TLI_DEFINE_ENUM_INTERNAL(getchar) TLI_DEFINE_STRING_INTERNAL("getchar") +/// int getchar_unlocked(void); +TLI_DEFINE_ENUM_INTERNAL(getchar_unlocked) +TLI_DEFINE_STRING_INTERNAL("getchar_unlocked") /// char *getenv(const char *name); TLI_DEFINE_ENUM_INTERNAL(getenv) TLI_DEFINE_STRING_INTERNAL("getenv") @@ -950,9 +1007,15 @@ TLI_DEFINE_STRING_INTERNAL("printf") /// int putc(int c, FILE *stream); TLI_DEFINE_ENUM_INTERNAL(putc) TLI_DEFINE_STRING_INTERNAL("putc") +/// int putc_unlocked(int c, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(putc_unlocked) +TLI_DEFINE_STRING_INTERNAL("putc_unlocked") /// int putchar(int c); TLI_DEFINE_ENUM_INTERNAL(putchar) TLI_DEFINE_STRING_INTERNAL("putchar") +/// int putchar_unlocked(int c); +TLI_DEFINE_ENUM_INTERNAL(putchar_unlocked) +TLI_DEFINE_STRING_INTERNAL("putchar_unlocked") /// int puts(const char *s); TLI_DEFINE_ENUM_INTERNAL(puts) TLI_DEFINE_STRING_INTERNAL("puts") diff --git a/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h b/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h index c20f20cfbe4d..59657cca40f5 100644 --- a/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/contrib/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -49,7 +49,7 @@ class Type; class User; class Value; -/// \brief Information about a load/store intrinsic defined by the target. +/// Information about a load/store intrinsic defined by the target. struct MemIntrinsicInfo { /// This is the pointer that the intrinsic is loading from or storing to. /// If this is non-null, then analysis/optimization passes can assume that @@ -73,18 +73,18 @@ struct MemIntrinsicInfo { } }; -/// \brief This pass provides access to the codegen interfaces that are needed +/// This pass provides access to the codegen interfaces that are needed /// for IR-level transformations. class TargetTransformInfo { public: - /// \brief Construct a TTI object using a type implementing the \c Concept + /// Construct a TTI object using a type implementing the \c Concept /// API below. /// /// This is used by targets to construct a TTI wrapping their target-specific /// implementaion that encodes appropriate costs for their target. template <typename T> TargetTransformInfo(T Impl); - /// \brief Construct a baseline TTI object using a minimal implementation of + /// Construct a baseline TTI object using a minimal implementation of /// the \c Concept API below. /// /// The TTI implementation will reflect the information in the DataLayout @@ -99,7 +99,7 @@ public: // out-of-line. ~TargetTransformInfo(); - /// \brief Handle the invalidation of this information. + /// Handle the invalidation of this information. /// /// When used as a result of \c TargetIRAnalysis this method will be called /// when the function this was computed for changes. When it returns false, @@ -114,7 +114,7 @@ public: /// \name Generic Target Information /// @{ - /// \brief The kind of cost model. + /// The kind of cost model. /// /// There are several different cost models that can be customized by the /// target. The normalization of each cost model may be target specific. @@ -124,7 +124,7 @@ public: TCK_CodeSize ///< Instruction code size. }; - /// \brief Query the cost of a specified instruction. + /// Query the cost of a specified instruction. /// /// Clients should use this interface to query the cost of an existing /// instruction. The instruction must have a valid parent (basic block). @@ -145,7 +145,7 @@ public: llvm_unreachable("Unknown instruction cost kind"); } - /// \brief Underlying constants for 'cost' values in this interface. + /// Underlying constants for 'cost' values in this interface. /// /// Many APIs in this interface return a cost. This enum defines the /// fundamental values that should be used to interpret (and produce) those @@ -169,7 +169,7 @@ public: TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86. }; - /// \brief Estimate the cost of a specific operation when lowered. + /// Estimate the cost of a specific operation when lowered. /// /// Note that this is designed to work on an arbitrary synthetic opcode, and /// thus work for hypothetical queries before an instruction has even been @@ -185,7 +185,7 @@ public: /// comments for a detailed explanation of the cost values. int getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy = nullptr) const; - /// \brief Estimate the cost of a GEP operation when lowered. + /// Estimate the cost of a GEP operation when lowered. /// /// The contract for this function is the same as \c getOperationCost except /// that it supports an interface that provides extra information specific to @@ -193,14 +193,14 @@ public: int getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef<const Value *> Operands) const; - /// \brief Estimate the cost of a EXT operation when lowered. + /// Estimate the cost of a EXT operation when lowered. /// /// The contract for this function is the same as \c getOperationCost except /// that it supports an interface that provides extra information specific to /// the EXT operation. int getExtCost(const Instruction *I, const Value *Src) const; - /// \brief Estimate the cost of a function call when lowered. + /// Estimate the cost of a function call when lowered. /// /// The contract for this is the same as \c getOperationCost except that it /// supports an interface that provides extra information specific to call @@ -211,13 +211,13 @@ public: /// The latter is only interesting for varargs function types. int getCallCost(FunctionType *FTy, int NumArgs = -1) const; - /// \brief Estimate the cost of calling a specific function when lowered. + /// Estimate the cost of calling a specific function when lowered. /// /// This overload adds the ability to reason about the particular function /// being called in the event it is a library call with special lowering. int getCallCost(const Function *F, int NumArgs = -1) const; - /// \brief Estimate the cost of calling a specific function when lowered. + /// Estimate the cost of calling a specific function when lowered. /// /// This overload allows specifying a set of candidate argument values. int getCallCost(const Function *F, ArrayRef<const Value *> Arguments) const; @@ -230,13 +230,13 @@ public: /// individual classes of instructions would be better. unsigned getInliningThresholdMultiplier() const; - /// \brief Estimate the cost of an intrinsic when lowered. + /// Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, ArrayRef<Type *> ParamTys) const; - /// \brief Estimate the cost of an intrinsic when lowered. + /// Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. int getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, @@ -248,7 +248,7 @@ public: unsigned getEstimatedNumberOfCaseClusters(const SwitchInst &SI, unsigned &JTSize) const; - /// \brief Estimate the cost of a given IR user when lowered. + /// Estimate the cost of a given IR user when lowered. /// /// This can estimate the cost of either a ConstantExpr or Instruction when /// lowered. It has two primary advantages over the \c getOperationCost and @@ -271,7 +271,7 @@ public: /// comments for a detailed explanation of the cost values. int getUserCost(const User *U, ArrayRef<const Value *> Operands) const; - /// \brief This is a helper function which calls the two-argument getUserCost + /// This is a helper function which calls the two-argument getUserCost /// with \p Operands which are the current operands U has. int getUserCost(const User *U) const { SmallVector<const Value *, 4> Operands(U->value_op_begin(), @@ -279,14 +279,14 @@ public: return getUserCost(U, Operands); } - /// \brief Return true if branch divergence exists. + /// Return true if branch divergence exists. /// /// Branch divergence has a significantly negative impact on GPU performance /// when threads in the same wavefront take different paths due to conditional /// branches. bool hasBranchDivergence() const; - /// \brief Returns whether V is a source of divergence. + /// Returns whether V is a source of divergence. /// /// This function provides the target-dependent information for /// the target-independent DivergenceAnalysis. DivergenceAnalysis first @@ -294,7 +294,7 @@ public: /// starting with the sources of divergence. bool isSourceOfDivergence(const Value *V) const; - // \brief Returns true for the target specific + // Returns true for the target specific // set of operations which produce uniform result // even taking non-unform arguments bool isAlwaysUniform(const Value *V) const; @@ -308,7 +308,7 @@ public: /// compared to the same memory location accessed through a pointer with a /// different address space. // - /// This is for for targets with different pointer representations which can + /// This is for targets with different pointer representations which can /// be converted with the addrspacecast instruction. If a pointer is converted /// to this address space, optimizations should attempt to replace the access /// with the source address space. @@ -317,7 +317,7 @@ public: /// optimize away. unsigned getFlatAddressSpace() const; - /// \brief Test whether calls to a function lower to actual program function + /// Test whether calls to a function lower to actual program function /// calls. /// /// The idea is to test whether the program is likely to require a 'call' @@ -422,9 +422,16 @@ public: bool AllowPeeling; /// Allow unrolling of all the iterations of the runtime loop remainder. bool UnrollRemainder; + /// Allow unroll and jam. Used to enable unroll and jam for the target. + bool UnrollAndJam; + /// Threshold for unroll and jam, for inner loop size. The 'Threshold' + /// value above is used during unroll and jam for the outer loop size. + /// This value is used in the same manner to limit the size of the inner + /// loop. + unsigned UnrollAndJamInnerLoopThreshold; }; - /// \brief Get target-customized preferences for the generic loop unrolling + /// Get target-customized preferences for the generic loop unrolling /// transformation. The caller will initialize UP with the current /// target-independent defaults. void getUnrollingPreferences(Loop *L, ScalarEvolution &, @@ -435,7 +442,7 @@ public: /// \name Scalar Target Information /// @{ - /// \brief Flags indicating the kind of support for population count. + /// Flags indicating the kind of support for population count. /// /// Compared to the SW implementation, HW support is supposed to /// significantly boost the performance when the population is dense, and it @@ -445,18 +452,18 @@ public: /// considered as "Slow". enum PopcntSupportKind { PSK_Software, PSK_SlowHardware, PSK_FastHardware }; - /// \brief Return true if the specified immediate is legal add immediate, that + /// 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. bool isLegalAddImmediate(int64_t Imm) const; - /// \brief Return true if the specified immediate is legal icmp immediate, + /// 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. bool isLegalICmpImmediate(int64_t Imm) const; - /// \brief Return true if the addressing mode represented by AM is legal for + /// 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. @@ -467,16 +474,25 @@ public: unsigned AddrSpace = 0, Instruction *I = nullptr) const; - /// \brief Return true if LSR cost of C1 is lower than C1. + /// Return true if LSR cost of C1 is lower than C1. bool isLSRCostLess(TargetTransformInfo::LSRCost &C1, TargetTransformInfo::LSRCost &C2) const; - /// \brief Return true if the target supports masked load/store + /// Return true if the target can fuse a compare and branch. + /// Loop-strength-reduction (LSR) uses that knowledge to adjust its cost + /// calculation for the instructions in a loop. + bool canMacroFuseCmp() const; + + /// \return True is LSR should make efforts to create/preserve post-inc + /// addressing mode expressions. + bool shouldFavorPostInc() const; + + /// Return true if the target supports masked load/store /// AVX2 and AVX-512 targets allow masks for consecutive load and store bool isLegalMaskedStore(Type *DataType) const; bool isLegalMaskedLoad(Type *DataType) const; - /// \brief Return true if the target supports masked gather/scatter + /// Return true if the target supports masked gather/scatter /// AVX-512 fully supports gather and scatter for vectors with 32 and 64 /// bits scalar type. bool isLegalMaskedScatter(Type *DataType) const; @@ -499,7 +515,7 @@ public: /// Return true if target doesn't mind addresses in vectors. bool prefersVectorizedAddressing() const; - /// \brief Return the cost of the scaling factor used in the addressing + /// Return the cost of the scaling factor used in the addressing /// mode represented by AM for this target, for a load/store /// of the specified type. /// If the AM is supported, the return value must be >= 0. @@ -509,38 +525,44 @@ public: bool HasBaseReg, int64_t Scale, unsigned AddrSpace = 0) const; - /// \brief Return true if the loop strength reduce pass should make + /// Return true if the loop strength reduce pass should make /// Instruction* based TTI queries to isLegalAddressingMode(). This is /// needed on SystemZ, where e.g. a memcpy can only have a 12 bit unsigned /// immediate offset and no index register. bool LSRWithInstrQueries() const; - /// \brief Return true if it's free to truncate a value of type Ty1 to type + /// 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. bool isTruncateFree(Type *Ty1, Type *Ty2) const; - /// \brief Return true if it is profitable to hoist instruction in the + /// Return true if it is profitable to hoist instruction in the /// then/else to before if. bool isProfitableToHoist(Instruction *I) const; - /// \brief Return true if this type is legal. + bool useAA() const; + + /// Return true if this type is legal. bool isTypeLegal(Type *Ty) const; - /// \brief Returns the target's jmp_buf alignment in bytes. + /// Returns the target's jmp_buf alignment in bytes. unsigned getJumpBufAlignment() const; - /// \brief Returns the target's jmp_buf size in bytes. + /// Returns the target's jmp_buf size in bytes. unsigned getJumpBufSize() const; - /// \brief Return true if switches should be turned into lookup tables for the + /// Return true if switches should be turned into lookup tables for the /// target. bool shouldBuildLookupTables() const; - /// \brief Return true if switches should be turned into lookup tables + /// Return true if switches should be turned into lookup tables /// containing this constant value for the target. bool shouldBuildLookupTablesForConstant(Constant *C) const; + /// Return true if the input function which is cold at all call sites, + /// should use coldcc calling convention. + bool useColdCCForColdCall(Function &F) const; + unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) const; unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args, @@ -551,10 +573,10 @@ public: /// the scalarization cost of a load/store. bool supportsEfficientVectorElementLoadStore() const; - /// \brief Don't restrict interleaved unrolling to small loops. + /// Don't restrict interleaved unrolling to small loops. bool enableAggressiveInterleaving(bool LoopHasReductions) const; - /// \brief If not nullptr, enable inline expansion of memcmp. IsZeroCmp is + /// If not nullptr, enable inline expansion of memcmp. IsZeroCmp is /// true if this is the expansion of memcmp(p1, p2, s) == 0. struct MemCmpExpansionOptions { // The list of available load sizes (in bytes), sorted in decreasing order. @@ -562,10 +584,10 @@ public: }; const MemCmpExpansionOptions *enableMemCmpExpansion(bool IsZeroCmp) const; - /// \brief Enable matching of interleaved access groups. + /// Enable matching of interleaved access groups. bool enableInterleavedAccessVectorization() const; - /// \brief Indicate that it is potentially unsafe to automatically vectorize + /// Indicate that it is potentially unsafe to automatically vectorize /// floating-point operations because the semantics of vector and scalar /// floating-point semantics may differ. For example, ARM NEON v7 SIMD math /// does not support IEEE-754 denormal numbers, while depending on the @@ -574,16 +596,16 @@ public: /// operations, shuffles, or casts. bool isFPVectorizationPotentiallyUnsafe() const; - /// \brief Determine if the target supports unaligned memory accesses. + /// Determine if the target supports unaligned memory accesses. bool allowsMisalignedMemoryAccesses(LLVMContext &Context, unsigned BitWidth, unsigned AddressSpace = 0, unsigned Alignment = 1, bool *Fast = nullptr) const; - /// \brief Return hardware support for population count. + /// Return hardware support for population count. PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; - /// \brief Return true if the hardware has a fast square-root instruction. + /// Return true if the hardware has a fast square-root instruction. bool haveFastSqrt(Type *Ty) const; /// Return true if it is faster to check if a floating-point value is NaN @@ -592,15 +614,15 @@ public: /// generally as cheap as checking for ordered/unordered. bool isFCmpOrdCheaperThanFCmpZero(Type *Ty) const; - /// \brief Return the expected cost of supporting the floating point operation + /// Return the expected cost of supporting the floating point operation /// of the specified type. int getFPOpCost(Type *Ty) const; - /// \brief Return the expected cost of materializing for the given integer + /// Return the expected cost of materializing for the given integer /// immediate of the specified type. int getIntImmCost(const APInt &Imm, Type *Ty) const; - /// \brief Return the expected cost of materialization for the given integer + /// 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. int getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, @@ -608,7 +630,7 @@ public: int getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, Type *Ty) const; - /// \brief Return the expected cost for the given integer when optimising + /// Return the expected cost for the given integer when optimising /// for size. This is different than the other integer immediate cost /// functions in that it is subtarget agnostic. This is useful when you e.g. /// target one ISA such as Aarch32 but smaller encodings could be possible @@ -622,11 +644,14 @@ public: /// \name Vector Target Information /// @{ - /// \brief The various kinds of shuffle patterns for vector queries. + /// The various kinds of shuffle patterns for vector queries. enum ShuffleKind { SK_Broadcast, ///< Broadcast element 0 to all other elements. SK_Reverse, ///< Reverse the order of the vector. - SK_Alternate, ///< Choose alternate elements from vector. + SK_Select, ///< Selects elements from the corresponding lane of + ///< either source operand. This is equivalent to a + ///< vector select with a constant condition operand. + SK_Transpose, ///< Transpose two vectors. SK_InsertSubvector, ///< InsertSubvector. Index indicates start offset. SK_ExtractSubvector,///< ExtractSubvector Index indicates start offset. SK_PermuteTwoSrc, ///< Merge elements from two source vectors into one @@ -635,7 +660,7 @@ public: ///< shuffle mask. }; - /// \brief Additional information about an operand's possible values. + /// 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). @@ -643,7 +668,7 @@ public: OK_NonUniformConstantValue // Operand is a non uniform constant value. }; - /// \brief Additional properties of an operand's values. + /// Additional properties of an operand's values. enum OperandValueProperties { OP_None = 0, OP_PowerOf2 = 1 }; /// \return The number of scalar or vector registers that the target has. @@ -657,6 +682,19 @@ public: /// \return The width of the smallest vector register type. unsigned getMinVectorRegisterBitWidth() const; + /// \return True if the vectorization factor should be chosen to + /// make the vector of the smallest element type match the size of a + /// vector register. For wider element types, this could result in + /// creating vectors that span multiple vector registers. + /// If false, the vectorization factor will be chosen based on the + /// size of the widest element type. + bool shouldMaximizeVectorBandwidth(bool OptSize) const; + + /// \return The minimum vectorization factor for types of given element + /// bit width, or 0 if there is no mimimum VF. The returned value only + /// applies when shouldMaximizeVectorBandwidth returns true. + unsigned getMinimumVF(unsigned ElemWidth) const; + /// \return True if it should be considered for address type promotion. /// \p AllowPromotionWithoutCommonHeader Set true if promoting \p I is /// profitable without finding other extensions fed by the same input. @@ -701,10 +739,20 @@ public: /// and the number of execution units in the CPU. unsigned getMaxInterleaveFactor(unsigned VF) const; - /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. - /// \p Args is an optional argument which holds the instruction operands - /// values so the TTI can analyize those values searching for special - /// cases\optimizations based on those values. + /// This is an approximation of reciprocal throughput of a math/logic op. + /// A higher cost indicates less expected throughput. + /// From Agner Fog's guides, reciprocal throughput is "the average number of + /// clock cycles per instruction when the instructions are not part of a + /// limiting dependency chain." + /// Therefore, costs should be scaled to account for multiple execution units + /// on the target that can process this type of instruction. For example, if + /// there are 5 scalar integer units and 2 vector integer units that can + /// calculate an 'add' in a single cycle, this model should indicate that the + /// cost of the vector add instruction is 2.5 times the cost of the scalar + /// add instruction. + /// \p Args is an optional argument which holds the instruction operands + /// values so the TTI can analyze those values searching for special + /// cases or optimizations based on those values. int getArithmeticInstrCost( unsigned Opcode, Type *Ty, OperandValueKind Opd1Info = OK_AnyValue, OperandValueKind Opd2Info = OK_AnyValue, @@ -773,7 +821,7 @@ public: ArrayRef<unsigned> Indices, unsigned Alignment, unsigned AddressSpace) const; - /// \brief Calculate the cost of performing a vector reduction. + /// Calculate the cost of performing a vector reduction. /// /// This is the cost of reducing the vector value of type \p Ty to a scalar /// value using the operation denoted by \p Opcode. The form of the reduction @@ -867,6 +915,21 @@ public: bool areInlineCompatible(const Function *Caller, const Function *Callee) const; + /// The type of load/store indexing. + enum MemIndexedMode { + MIM_Unindexed, ///< No indexing. + MIM_PreInc, ///< Pre-incrementing. + MIM_PreDec, ///< Pre-decrementing. + MIM_PostInc, ///< Post-incrementing. + MIM_PostDec ///< Post-decrementing. + }; + + /// \returns True if the specified indexed load for the given type is legal. + bool isIndexedLoadLegal(enum MemIndexedMode Mode, Type *Ty) const; + + /// \returns True if the specified indexed store for the given type is legal. + bool isIndexedStoreLegal(enum MemIndexedMode Mode, Type *Ty) const; + /// \returns The bitwidth of the largest vector type that should be used to /// load/store in the given address space. unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const; @@ -918,19 +981,19 @@ public: /// @} private: - /// \brief Estimate the latency of specified instruction. + /// Estimate the latency of specified instruction. /// Returns 1 as the default value. int getInstructionLatency(const Instruction *I) const; - /// \brief Returns the expected throughput cost of the instruction. + /// Returns the expected throughput cost of the instruction. /// Returns -1 if the cost is unknown. int getInstructionThroughput(const Instruction *I) const; - /// \brief The abstract base class used to type erase specific TTI + /// The abstract base class used to type erase specific TTI /// implementations. class Concept; - /// \brief The template model for the base class which wraps a concrete + /// The template model for the base class which wraps a concrete /// implementation in a type erased interface. template <typename T> class Model; @@ -974,6 +1037,8 @@ public: Instruction *I) = 0; virtual bool isLSRCostLess(TargetTransformInfo::LSRCost &C1, TargetTransformInfo::LSRCost &C2) = 0; + virtual bool canMacroFuseCmp() = 0; + virtual bool shouldFavorPostInc() const = 0; virtual bool isLegalMaskedStore(Type *DataType) = 0; virtual bool isLegalMaskedLoad(Type *DataType) = 0; virtual bool isLegalMaskedScatter(Type *DataType) = 0; @@ -987,11 +1052,13 @@ public: virtual bool LSRWithInstrQueries() = 0; virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0; virtual bool isProfitableToHoist(Instruction *I) = 0; + virtual bool useAA() = 0; virtual bool isTypeLegal(Type *Ty) = 0; virtual unsigned getJumpBufAlignment() = 0; virtual unsigned getJumpBufSize() = 0; virtual bool shouldBuildLookupTables() = 0; virtual bool shouldBuildLookupTablesForConstant(Constant *C) = 0; + virtual bool useColdCCForColdCall(Function &F) = 0; virtual unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) = 0; virtual unsigned getOperandsScalarizationOverhead(ArrayRef<const Value *> Args, @@ -1021,6 +1088,8 @@ public: virtual unsigned getNumberOfRegisters(bool Vector) = 0; virtual unsigned getRegisterBitWidth(bool Vector) const = 0; virtual unsigned getMinVectorRegisterBitWidth() = 0; + virtual bool shouldMaximizeVectorBandwidth(bool OptSize) const = 0; + virtual unsigned getMinimumVF(unsigned ElemWidth) const = 0; virtual bool shouldConsiderAddressTypePromotion( const Instruction &I, bool &AllowPromotionWithoutCommonHeader) = 0; virtual unsigned getCacheLineSize() = 0; @@ -1088,6 +1157,8 @@ public: unsigned RemainingBytes, unsigned SrcAlign, unsigned DestAlign) const = 0; virtual bool areInlineCompatible(const Function *Caller, const Function *Callee) const = 0; + virtual bool isIndexedLoadLegal(MemIndexedMode Mode, Type *Ty) const = 0; + virtual bool isIndexedStoreLegal(MemIndexedMode Mode,Type *Ty) const = 0; virtual unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const = 0; virtual bool isLegalToVectorizeLoad(LoadInst *LI) const = 0; virtual bool isLegalToVectorizeStore(StoreInst *SI) const = 0; @@ -1192,6 +1263,12 @@ public: TargetTransformInfo::LSRCost &C2) override { return Impl.isLSRCostLess(C1, C2); } + bool canMacroFuseCmp() override { + return Impl.canMacroFuseCmp(); + } + bool shouldFavorPostInc() const override { + return Impl.shouldFavorPostInc(); + } bool isLegalMaskedStore(Type *DataType) override { return Impl.isLegalMaskedStore(DataType); } @@ -1228,6 +1305,7 @@ public: bool isProfitableToHoist(Instruction *I) override { return Impl.isProfitableToHoist(I); } + bool useAA() override { return Impl.useAA(); } bool isTypeLegal(Type *Ty) override { return Impl.isTypeLegal(Ty); } unsigned getJumpBufAlignment() override { return Impl.getJumpBufAlignment(); } unsigned getJumpBufSize() override { return Impl.getJumpBufSize(); } @@ -1237,6 +1315,10 @@ public: bool shouldBuildLookupTablesForConstant(Constant *C) override { return Impl.shouldBuildLookupTablesForConstant(C); } + bool useColdCCForColdCall(Function &F) override { + return Impl.useColdCCForColdCall(F); + } + unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) override { return Impl.getScalarizationOverhead(Ty, Insert, Extract); @@ -1304,6 +1386,12 @@ public: unsigned getMinVectorRegisterBitWidth() override { return Impl.getMinVectorRegisterBitWidth(); } + bool shouldMaximizeVectorBandwidth(bool OptSize) const override { + return Impl.shouldMaximizeVectorBandwidth(OptSize); + } + unsigned getMinimumVF(unsigned ElemWidth) const override { + return Impl.getMinimumVF(ElemWidth); + } bool shouldConsiderAddressTypePromotion( const Instruction &I, bool &AllowPromotionWithoutCommonHeader) override { return Impl.shouldConsiderAddressTypePromotion( @@ -1442,6 +1530,12 @@ public: const Function *Callee) const override { return Impl.areInlineCompatible(Caller, Callee); } + bool isIndexedLoadLegal(MemIndexedMode Mode, Type *Ty) const override { + return Impl.isIndexedLoadLegal(Mode, Ty, getDataLayout()); + } + bool isIndexedStoreLegal(MemIndexedMode Mode, Type *Ty) const override { + return Impl.isIndexedStoreLegal(Mode, Ty, getDataLayout()); + } unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const override { return Impl.getLoadStoreVecRegBitWidth(AddrSpace); } @@ -1489,7 +1583,7 @@ template <typename T> TargetTransformInfo::TargetTransformInfo(T Impl) : TTIImpl(new Model<T>(Impl)) {} -/// \brief Analysis pass providing the \c TargetTransformInfo. +/// Analysis pass providing the \c TargetTransformInfo. /// /// The core idea of the TargetIRAnalysis is to expose an interface through /// which LLVM targets can analyze and provide information about the middle @@ -1504,13 +1598,13 @@ class TargetIRAnalysis : public AnalysisInfoMixin<TargetIRAnalysis> { public: typedef TargetTransformInfo Result; - /// \brief Default construct a target IR analysis. + /// Default construct a target IR analysis. /// /// This will use the module's datalayout to construct a baseline /// conservative TTI result. TargetIRAnalysis(); - /// \brief Construct an IR analysis pass around a target-provide callback. + /// Construct an IR analysis pass around a target-provide callback. /// /// The callback will be called with a particular function for which the TTI /// is needed and must return a TTI object for that function. @@ -1536,7 +1630,7 @@ private: friend AnalysisInfoMixin<TargetIRAnalysis>; static AnalysisKey Key; - /// \brief The callback used to produce a result. + /// The callback used to produce a result. /// /// We use a completely opaque callback so that targets can provide whatever /// mechanism they desire for constructing the TTI for a given function. @@ -1548,11 +1642,11 @@ private: /// the external TargetMachine, and that reference needs to never dangle. std::function<Result(const Function &)> TTICallback; - /// \brief Helper function used as the callback in the default constructor. + /// Helper function used as the callback in the default constructor. static Result getDefaultTTI(const Function &F); }; -/// \brief Wrapper pass for TargetTransformInfo. +/// Wrapper pass for TargetTransformInfo. /// /// This pass can be constructed from a TTI object which it stores internally /// and is queried by passes. @@ -1565,7 +1659,7 @@ class TargetTransformInfoWrapperPass : public ImmutablePass { public: static char ID; - /// \brief We must provide a default constructor for the pass but it should + /// We must provide a default constructor for the pass but it should /// never be used. /// /// Use the constructor below or call one of the creation routines. @@ -1576,7 +1670,7 @@ public: TargetTransformInfo &getTTI(const Function &F); }; -/// \brief Create an analysis pass wrapper around a TTI object. +/// Create an analysis pass wrapper around a TTI object. /// /// This analysis pass just holds the TTI instance and makes it available to /// clients. diff --git a/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h index 4c37402278ef..e14e2bd44034 100644 --- a/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/contrib/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -27,7 +27,7 @@ namespace llvm { -/// \brief Base class for use as a mix-in that aids implementing +/// Base class for use as a mix-in that aids implementing /// a TargetTransformInfo-compatible class. class TargetTransformInfoImplBase { protected: @@ -155,6 +155,7 @@ public: case Intrinsic::sideeffect: case Intrinsic::dbg_declare: case Intrinsic::dbg_value: + case Intrinsic::dbg_label: case Intrinsic::invariant_start: case Intrinsic::invariant_end: case Intrinsic::lifetime_start: @@ -246,6 +247,10 @@ public: C2.ScaleCost, C2.ImmCost, C2.SetupCost); } + bool canMacroFuseCmp() { return false; } + + bool shouldFavorPostInc() const { return false; } + bool isLegalMaskedStore(Type *DataType) { return false; } bool isLegalMaskedLoad(Type *DataType) { return false; } @@ -275,6 +280,8 @@ public: bool isProfitableToHoist(Instruction *I) { return true; } + bool useAA() { return false; } + bool isTypeLegal(Type *Ty) { return false; } unsigned getJumpBufAlignment() { return 0; } @@ -284,6 +291,8 @@ public: bool shouldBuildLookupTables() { return true; } bool shouldBuildLookupTablesForConstant(Constant *C) { return true; } + bool useColdCCForColdCall(Function &F) { return false; } + unsigned getScalarizationOverhead(Type *Ty, bool Insert, bool Extract) { return 0; } @@ -343,6 +352,10 @@ public: unsigned getMinVectorRegisterBitWidth() { return 128; } + bool shouldMaximizeVectorBandwidth(bool OptSize) const { return false; } + + unsigned getMinimumVF(unsigned ElemWidth) const { return 0; } + bool shouldConsiderAddressTypePromotion(const Instruction &I, bool &AllowPromotionWithoutCommonHeader) { @@ -507,6 +520,16 @@ public: Callee->getFnAttribute("target-features")); } + bool isIndexedLoadLegal(TTI::MemIndexedMode Mode, Type *Ty, + const DataLayout &DL) const { + return false; + } + + bool isIndexedStoreLegal(TTI::MemIndexedMode Mode, Type *Ty, + const DataLayout &DL) const { + return false; + } + unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const { return 128; } bool isLegalToVectorizeLoad(LoadInst *LI) const { return true; } @@ -629,7 +652,7 @@ protected: } }; -/// \brief CRTP base class for use as a mix-in that aids implementing +/// CRTP base class for use as a mix-in that aids implementing /// a TargetTransformInfo-compatible class. template <typename T> class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { diff --git a/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h b/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h index 422e153a5a78..6764563f6830 100644 --- a/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h +++ b/contrib/llvm/include/llvm/Analysis/TypeMetadataUtils.h @@ -35,13 +35,13 @@ struct DevirtCallSite { CallSite CS; }; -/// Given a call to the intrinsic @llvm.type.test, find all devirtualizable +/// Given a call to the intrinsic \@llvm.type.test, find all devirtualizable /// call sites based on the call and return them in DevirtCalls. void findDevirtualizableCallsForTypeTest( SmallVectorImpl<DevirtCallSite> &DevirtCalls, SmallVectorImpl<CallInst *> &Assumes, const CallInst *CI); -/// Given a call to the intrinsic @llvm.type.checked.load, find all +/// Given a call to the intrinsic \@llvm.type.checked.load, find all /// devirtualizable call sites based on the call and return them in DevirtCalls. void findDevirtualizableCallsForTypeCheckedLoad( SmallVectorImpl<DevirtCallSite> &DevirtCalls, diff --git a/contrib/llvm/include/llvm/Analysis/Utils/Local.h b/contrib/llvm/include/llvm/Analysis/Utils/Local.h new file mode 100644 index 000000000000..b4141bbff28d --- /dev/null +++ b/contrib/llvm/include/llvm/Analysis/Utils/Local.h @@ -0,0 +1,91 @@ +//===- Local.h - Functions to perform local transformations -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions perform various local transformations to the +// program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_UTILS_LOCAL_H +#define LLVM_ANALYSIS_UTILS_LOCAL_H + +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" + +namespace llvm { + +/// Given a getelementptr instruction/constantexpr, emit the code necessary to +/// compute the offset from the base pointer (without adding in the base +/// pointer). Return the result as a signed integer of intptr size. +/// When NoAssumptions is true, no assumptions about index computation not +/// overflowing is made. +template <typename IRBuilderTy> +Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP, + bool NoAssumptions = false) { + GEPOperator *GEPOp = cast<GEPOperator>(GEP); + Type *IntPtrTy = DL.getIntPtrType(GEP->getType()); + Value *Result = Constant::getNullValue(IntPtrTy); + + // If the GEP is inbounds, we know that none of the addressing operations will + // overflow in an unsigned sense. + bool isInBounds = GEPOp->isInBounds() && !NoAssumptions; + + // Build a mask for high order bits. + unsigned IntPtrWidth = IntPtrTy->getScalarType()->getIntegerBitWidth(); + uint64_t PtrSizeMask = + std::numeric_limits<uint64_t>::max() >> (64 - IntPtrWidth); + + gep_type_iterator GTI = gep_type_begin(GEP); + for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; + ++i, ++GTI) { + Value *Op = *i; + uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask; + if (Constant *OpC = dyn_cast<Constant>(Op)) { + if (OpC->isZeroValue()) + continue; + + // Handle a struct index, which adds its field offset to the pointer. + if (StructType *STy = GTI.getStructTypeOrNull()) { + if (OpC->getType()->isVectorTy()) + OpC = OpC->getSplatValue(); + + uint64_t OpValue = cast<ConstantInt>(OpC)->getZExtValue(); + Size = DL.getStructLayout(STy)->getElementOffset(OpValue); + + if (Size) + Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size), + GEP->getName()+".offs"); + continue; + } + + Constant *Scale = ConstantInt::get(IntPtrTy, Size); + Constant *OC = ConstantExpr::getIntegerCast(OpC, IntPtrTy, true /*SExt*/); + Scale = ConstantExpr::getMul(OC, Scale, isInBounds/*NUW*/); + // Emit an add instruction. + Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs"); + continue; + } + // Convert to correct type. + if (Op->getType() != IntPtrTy) + Op = Builder->CreateIntCast(Op, IntPtrTy, true, Op->getName()+".c"); + if (Size != 1) { + // We'll let instcombine(mul) convert this to a shl if possible. + Op = Builder->CreateMul(Op, ConstantInt::get(IntPtrTy, Size), + GEP->getName()+".idx", isInBounds /*NUW*/); + } + + // Emit an add instruction. + Result = Builder->CreateAdd(Op, Result, GEP->getName()+".offs"); + } + return Result; +} + +} + +#endif // LLVM_TRANSFORMS_UTILS_LOCAL_H diff --git a/contrib/llvm/include/llvm/Analysis/ValueLattice.h b/contrib/llvm/include/llvm/Analysis/ValueLattice.h index 18a43aafa8ca..0744ca617e48 100644 --- a/contrib/llvm/include/llvm/Analysis/ValueLattice.h +++ b/contrib/llvm/include/llvm/Analysis/ValueLattice.h @@ -49,14 +49,73 @@ class ValueLatticeElement { overdefined }; - /// Val: This stores the current lattice value along with the Constant* for - /// the constant if this is a 'constant' or 'notconstant' value. ValueLatticeElementTy Tag; - Constant *Val; - ConstantRange Range; + + /// The union either stores a pointer to a constant or a constant range, + /// associated to the lattice element. We have to ensure that Range is + /// initialized or destroyed when changing state to or from constantrange. + union { + Constant *ConstVal; + ConstantRange Range; + }; public: - ValueLatticeElement() : Tag(undefined), Val(nullptr), Range(1, true) {} + // Const and Range are initialized on-demand. + ValueLatticeElement() : Tag(undefined) {} + + /// Custom destructor to ensure Range is properly destroyed, when the object + /// is deallocated. + ~ValueLatticeElement() { + switch (Tag) { + case overdefined: + case undefined: + case constant: + case notconstant: + break; + case constantrange: + Range.~ConstantRange(); + break; + }; + } + + /// Custom copy constructor, to ensure Range gets initialized when + /// copying a constant range lattice element. + ValueLatticeElement(const ValueLatticeElement &Other) : Tag(undefined) { + *this = Other; + } + + /// Custom assignment operator, to ensure Range gets initialized when + /// assigning a constant range lattice element. + ValueLatticeElement &operator=(const ValueLatticeElement &Other) { + // If we change the state of this from constant range to non constant range, + // destroy Range. + if (isConstantRange() && !Other.isConstantRange()) + Range.~ConstantRange(); + + // If we change the state of this from a valid ConstVal to another a state + // without a valid ConstVal, zero the pointer. + if ((isConstant() || isNotConstant()) && !Other.isConstant() && + !Other.isNotConstant()) + ConstVal = nullptr; + + switch (Other.Tag) { + case constantrange: + if (!isConstantRange()) + new (&Range) ConstantRange(Other.Range); + else + Range = Other.Range; + break; + case constant: + case notconstant: + ConstVal = Other.ConstVal; + break; + case overdefined: + case undefined: + break; + } + Tag = Other.Tag; + return *this; + } static ValueLatticeElement get(Constant *C) { ValueLatticeElement Res; @@ -89,12 +148,12 @@ public: Constant *getConstant() const { assert(isConstant() && "Cannot get the constant of a non-constant!"); - return Val; + return ConstVal; } Constant *getNotConstant() const { assert(isNotConstant() && "Cannot get the constant of a non-notconstant!"); - return Val; + return ConstVal; } const ConstantRange &getConstantRange() const { @@ -104,10 +163,10 @@ public: } Optional<APInt> asConstantInteger() const { - if (isConstant() && isa<ConstantInt>(Val)) { - return cast<ConstantInt>(Val)->getValue(); - } else if (isConstantRange() && Range.isSingleElement()) { - return *Range.getSingleElement(); + if (isConstant() && isa<ConstantInt>(getConstant())) { + return cast<ConstantInt>(getConstant())->getValue(); + } else if (isConstantRange() && getConstantRange().isSingleElement()) { + return *getConstantRange().getSingleElement(); } return None; } @@ -116,6 +175,10 @@ private: void markOverdefined() { if (isOverdefined()) return; + if (isConstant() || isNotConstant()) + ConstVal = nullptr; + if (isConstantRange()) + Range.~ConstantRange(); Tag = overdefined; } @@ -132,7 +195,7 @@ private: "Marking constant with different value"); assert(isUndefined()); Tag = constant; - Val = V; + ConstVal = V; } void markNotConstant(Constant *V) { @@ -150,7 +213,7 @@ private: "Marking !constant with different value"); assert(isUndefined() || isConstant()); Tag = notconstant; - Val = V; + ConstVal = V; } void markConstantRange(ConstantRange NewR) { @@ -168,7 +231,7 @@ private: markOverdefined(); else { Tag = constantrange; - Range = std::move(NewR); + new (&Range) ConstantRange(std::move(NewR)); } } @@ -189,14 +252,14 @@ public: } if (isConstant()) { - if (RHS.isConstant() && Val == RHS.Val) + if (RHS.isConstant() && getConstant() == RHS.getConstant()) return false; markOverdefined(); return true; } if (isNotConstant()) { - if (RHS.isNotConstant() && Val == RHS.Val) + if (RHS.isNotConstant() && getNotConstant() == RHS.getNotConstant()) return false; markOverdefined(); return true; @@ -209,9 +272,11 @@ public: markOverdefined(); return true; } - ConstantRange NewR = Range.unionWith(RHS.getConstantRange()); + ConstantRange NewR = getConstantRange().unionWith(RHS.getConstantRange()); if (NewR.isFullSet()) markOverdefined(); + else if (NewR == getConstantRange()) + return false; else markConstantRange(std::move(NewR)); return true; @@ -223,24 +288,32 @@ public: return cast<ConstantInt>(getConstant()); } - bool satisfiesPredicate(CmpInst::Predicate Pred, - const ValueLatticeElement &Other) const { - // TODO: share with LVI getPredicateResult. - + /// Compares this symbolic value with Other using Pred and returns either + /// true, false or undef constants, or nullptr if the comparison cannot be + /// evaluated. + Constant *getCompare(CmpInst::Predicate Pred, Type *Ty, + const ValueLatticeElement &Other) const { if (isUndefined() || Other.isUndefined()) - return true; + return UndefValue::get(Ty); - if (isConstant() && Other.isConstant() && Pred == CmpInst::FCMP_OEQ) - return getConstant() == Other.getConstant(); + if (isConstant() && Other.isConstant()) + return ConstantExpr::getCompare(Pred, getConstant(), Other.getConstant()); // Integer constants are represented as ConstantRanges with single // elements. if (!isConstantRange() || !Other.isConstantRange()) - return false; + return nullptr; const auto &CR = getConstantRange(); const auto &OtherCR = Other.getConstantRange(); - return ConstantRange::makeSatisfyingICmpRegion(Pred, OtherCR).contains(CR); + if (ConstantRange::makeSatisfyingICmpRegion(Pred, OtherCR).contains(CR)) + return ConstantInt::getTrue(Ty); + if (ConstantRange::makeSatisfyingICmpRegion( + CmpInst::getInversePredicate(Pred), OtherCR) + .contains(CR)) + return ConstantInt::getFalse(Ty); + + return nullptr; } }; diff --git a/contrib/llvm/include/llvm/Analysis/ValueTracking.h b/contrib/llvm/include/llvm/Analysis/ValueTracking.h index 1fdb3cff5372..e6a219a8045b 100644 --- a/contrib/llvm/include/llvm/Analysis/ValueTracking.h +++ b/contrib/llvm/include/llvm/Analysis/ValueTracking.h @@ -101,6 +101,12 @@ class Value; const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); + /// Return true if the two given values are negation. + /// Currently can recoginze Value pair: + /// 1: <X, Y> if X = sub (0, Y) or Y = sub (0, X) + /// 2: <X, Y> if X = sub (A, B) and Y = sub (B, A) + bool isKnownNegation(const Value *X, const Value *Y, bool NeedNSW = false); + /// Returns true if the give value is known to be non-negative. bool isKnownNonNegative(const Value *V, const DataLayout &DL, unsigned Depth = 0, @@ -276,6 +282,22 @@ class Value; /// pointer, return 'len+1'. If we can't, return 0. uint64_t GetStringLength(const Value *V, unsigned CharSize = 8); + /// This function returns call pointer argument that is considered the same by + /// aliasing rules. You CAN'T use it to replace one value with another. + const Value *getArgumentAliasingToReturnedPointer(ImmutableCallSite CS); + inline Value *getArgumentAliasingToReturnedPointer(CallSite CS) { + return const_cast<Value *>( + getArgumentAliasingToReturnedPointer(ImmutableCallSite(CS))); + } + + // {launder,strip}.invariant.group returns pointer that aliases its argument, + // and it only captures pointer by returning it. + // These intrinsics are not marked as nocapture, because returning is + // considered as capture. The arguments are not marked as returned neither, + // because it would make it useless. + bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing( + ImmutableCallSite CS); + /// This method strips off any GEP address adjustments and pointer casts from /// the specified value, returning the original object being addressed. Note /// that the returned value has pointer type if the specified value does. If @@ -288,7 +310,7 @@ class Value; return GetUnderlyingObject(const_cast<Value *>(V), DL, MaxLookup); } - /// \brief This method is similar to GetUnderlyingObject except that it can + /// This method is similar to GetUnderlyingObject except that it can /// look through phi and select instructions and return multiple objects. /// /// If LoopInfo is passed, loop phis are further analyzed. If a pointer @@ -384,6 +406,11 @@ class Value; AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT); + OverflowResult computeOverflowForSignedMul(const Value *LHS, const Value *RHS, + const DataLayout &DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); OverflowResult computeOverflowForUnsignedAdd(const Value *LHS, const Value *RHS, const DataLayout &DL, @@ -401,6 +428,16 @@ class Value; AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); + OverflowResult computeOverflowForUnsignedSub(const Value *LHS, const Value *RHS, + const DataLayout &DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); + OverflowResult computeOverflowForSignedSub(const Value *LHS, const Value *RHS, + const DataLayout &DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); /// Returns true if the arithmetic part of the \p II 's result is /// used only along the paths control dependent on the computation @@ -423,6 +460,13 @@ class Value; /// though division by zero might cause undefined behavior. bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I); + /// Returns true if this block does not contain a potential implicit exit. + /// This is equivelent to saying that all instructions within the basic block + /// are guaranteed to transfer execution to their successor within the basic + /// block. This has the same assumptions w.r.t. undefined behavior as the + /// instruction variant of this function. + bool isGuaranteedToTransferExecutionToSuccessor(const BasicBlock *BB); + /// Return true if this function can prove that the instruction I /// is executed for every iteration of the loop L. /// @@ -454,7 +498,7 @@ class Value; /// the parent of I. bool programUndefinedIfFullPoison(const Instruction *PoisonI); - /// \brief Specific patterns of select instructions we can match. + /// Specific patterns of select instructions we can match. enum SelectPatternFlavor { SPF_UNKNOWN = 0, SPF_SMIN, /// Signed minimum @@ -467,7 +511,7 @@ class Value; SPF_NABS /// Negated absolute value }; - /// \brief Behavior when a floating point min/max is given one NaN and one + /// Behavior when a floating point min/max is given one NaN and one /// non-NaN as input. enum SelectPatternNaNBehavior { SPNB_NA = 0, /// NaN behavior not applicable. @@ -486,15 +530,18 @@ class Value; /// fcmp; select, does the fcmp have to be /// ordered? - /// \brief Return true if \p SPF is a min or a max pattern. + /// Return true if \p SPF is a min or a max pattern. static bool isMinOrMax(SelectPatternFlavor SPF) { - return !(SPF == SPF_UNKNOWN || SPF == SPF_ABS || SPF == SPF_NABS); + return SPF != SPF_UNKNOWN && SPF != SPF_ABS && SPF != SPF_NABS; } }; /// Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind /// and providing the out parameter results if we successfully match. /// + /// For ABS/NABS, LHS will be set to the input to the abs idiom. RHS will be + /// the negation instruction from the idiom. + /// /// If CastOp is not nullptr, also match MIN/MAX idioms where the type does /// not match that of the original select. If this is the case, the cast /// operation (one of Trunc,SExt,Zext) that must be done to transform the @@ -521,6 +568,19 @@ class Value; return Result; } + /// Return the canonical comparison predicate for the specified + /// minimum/maximum flavor. + CmpInst::Predicate getMinMaxPred(SelectPatternFlavor SPF, + bool Ordered = false); + + /// Return the inverse minimum/maximum flavor of the specified flavor. + /// For example, signed minimum is the inverse of signed maximum. + SelectPatternFlavor getInverseMinMaxFlavor(SelectPatternFlavor SPF); + + /// Return the canonical inverse comparison predicate for the specified + /// minimum/maximum flavor. + CmpInst::Predicate getInverseMinMaxPred(SelectPatternFlavor SPF); + /// Return true if RHS is known to be implied true by LHS. Return false if /// RHS is known to be implied false by LHS. Otherwise, return None if no /// implication can be made. diff --git a/contrib/llvm/include/llvm/Analysis/VectorUtils.h b/contrib/llvm/include/llvm/Analysis/VectorUtils.h index 6315e8408f05..9fde36d61091 100644 --- a/contrib/llvm/include/llvm/Analysis/VectorUtils.h +++ b/contrib/llvm/include/llvm/Analysis/VectorUtils.h @@ -33,50 +33,50 @@ namespace Intrinsic { enum ID : unsigned; } -/// \brief Identify if the intrinsic is trivially vectorizable. +/// Identify if the intrinsic is trivially vectorizable. /// This method returns true if the intrinsic's argument types are all /// scalars for the scalar form of the intrinsic and all vectors for /// the vector form of the intrinsic. bool isTriviallyVectorizable(Intrinsic::ID ID); -/// \brief Identifies if the intrinsic has a scalar operand. It checks for +/// Identifies if the intrinsic has a scalar operand. It checks for /// ctlz,cttz and powi special intrinsics whose argument is scalar. bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID, unsigned ScalarOpdIdx); -/// \brief Returns intrinsic ID for call. +/// Returns intrinsic ID for call. /// For the input call instruction it finds mapping intrinsic and returns /// its intrinsic ID, in case it does not found it return not_intrinsic. Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI, const TargetLibraryInfo *TLI); -/// \brief Find the operand of the GEP that should be checked for consecutive +/// Find the operand of the GEP that should be checked for consecutive /// stores. This ignores trailing indices that have no effect on the final /// pointer. unsigned getGEPInductionOperand(const GetElementPtrInst *Gep); -/// \brief If the argument is a GEP, then returns the operand identified by +/// If the argument is a GEP, then returns the operand identified by /// getGEPInductionOperand. However, if there is some other non-loop-invariant /// operand, it returns that instead. Value *stripGetElementPtr(Value *Ptr, ScalarEvolution *SE, Loop *Lp); -/// \brief If a value has only one user that is a CastInst, return it. +/// If a value has only one user that is a CastInst, return it. Value *getUniqueCastUse(Value *Ptr, Loop *Lp, Type *Ty); -/// \brief Get the stride of a pointer access in a loop. Looks for symbolic +/// Get the stride of a pointer access in a loop. Looks for symbolic /// strides "a[i*stride]". Returns the symbolic stride, or null otherwise. Value *getStrideFromPointer(Value *Ptr, ScalarEvolution *SE, Loop *Lp); -/// \brief Given a vector and an element number, see if the scalar value is +/// Given a vector and an element number, see if the scalar value is /// already around as a register, for example if it were inserted then extracted /// from the vector. Value *findScalarElement(Value *V, unsigned EltNo); -/// \brief Get splat value if the input is a splat vector or return nullptr. +/// Get splat value if the input is a splat vector or return nullptr. /// The value may be extracted from a splat constants vector or from /// a sequence of instructions that broadcast a single value into a vector. const Value *getSplatValue(const Value *V); -/// \brief Compute a map of integer instructions to their minimum legal type +/// Compute a map of integer instructions to their minimum legal type /// size. /// /// C semantics force sub-int-sized values (e.g. i8, i16) to be promoted to int @@ -124,7 +124,7 @@ computeMinimumValueSizes(ArrayRef<BasicBlock*> Blocks, /// This function always sets a (possibly null) value for each K in Kinds. Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL); -/// \brief Create an interleave shuffle mask. +/// Create an interleave shuffle mask. /// /// This function creates a shuffle mask for interleaving \p NumVecs vectors of /// vectorization factor \p VF into a single wide vector. The mask is of the @@ -138,7 +138,7 @@ Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL); Constant *createInterleaveMask(IRBuilder<> &Builder, unsigned VF, unsigned NumVecs); -/// \brief Create a stride shuffle mask. +/// Create a stride shuffle mask. /// /// This function creates a shuffle mask whose elements begin at \p Start and /// are incremented by \p Stride. The mask can be used to deinterleave an @@ -153,7 +153,7 @@ Constant *createInterleaveMask(IRBuilder<> &Builder, unsigned VF, Constant *createStrideMask(IRBuilder<> &Builder, unsigned Start, unsigned Stride, unsigned VF); -/// \brief Create a sequential shuffle mask. +/// Create a sequential shuffle mask. /// /// This function creates shuffle mask whose elements are sequential and begin /// at \p Start. The mask contains \p NumInts integers and is padded with \p @@ -167,7 +167,7 @@ Constant *createStrideMask(IRBuilder<> &Builder, unsigned Start, Constant *createSequentialMask(IRBuilder<> &Builder, unsigned Start, unsigned NumInts, unsigned NumUndefs); -/// \brief Concatenate a list of vectors. +/// Concatenate a list of vectors. /// /// This function generates code that concatenate the vectors in \p Vecs into a /// single large vector. The number of vectors should be greater than one, and diff --git a/contrib/llvm/include/llvm/AsmParser/Parser.h b/contrib/llvm/include/llvm/AsmParser/Parser.h index 5f02e488e5b1..285a7c022a24 100644 --- a/contrib/llvm/include/llvm/AsmParser/Parser.h +++ b/contrib/llvm/include/llvm/AsmParser/Parser.h @@ -21,50 +21,95 @@ namespace llvm { class Constant; class LLVMContext; class Module; +class ModuleSummaryIndex; struct SlotMapping; class SMDiagnostic; class Type; -/// This function is the main interface to the LLVM Assembly Parser. It parses +/// This function is a main interface to the LLVM Assembly Parser. It parses /// an ASCII file that (presumably) contains LLVM Assembly code. It returns a /// Module (intermediate representation) with the corresponding features. Note /// that this does not verify that the generated Module is valid, so you should /// run the verifier after parsing the file to check that it is okay. -/// \brief Parse LLVM Assembly from a file +/// Parse LLVM Assembly from a file /// \param Filename The name of the file to parse -/// \param Error Error result info. +/// \param Err Error result info. /// \param Context Context in which to allocate globals info. /// \param Slots The optional slot mapping that will be initialized during /// parsing. /// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier. /// This option should only be set to false by llvm-as /// for use inside the LLVM testuite! +/// \param DataLayoutString Override datalayout in the llvm assembly. std::unique_ptr<Module> -parseAssemblyFile(StringRef Filename, SMDiagnostic &Error, LLVMContext &Context, - SlotMapping *Slots = nullptr, bool UpgradeDebugInfo = true); +parseAssemblyFile(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, + SlotMapping *Slots = nullptr, bool UpgradeDebugInfo = true, + StringRef DataLayoutString = ""); /// The function is a secondary interface to the LLVM Assembly Parser. It parses /// an ASCII string that (presumably) contains LLVM Assembly code. It returns a /// Module (intermediate representation) with the corresponding features. Note /// that this does not verify that the generated Module is valid, so you should /// run the verifier after parsing the file to check that it is okay. -/// \brief Parse LLVM Assembly from a string +/// Parse LLVM Assembly from a string /// \param AsmString The string containing assembly -/// \param Error Error result info. +/// \param Err Error result info. /// \param Context Context in which to allocate globals info. /// \param Slots The optional slot mapping that will be initialized during /// parsing. /// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier. /// This option should only be set to false by llvm-as /// for use inside the LLVM testuite! +/// \param DataLayoutString Override datalayout in the llvm assembly. std::unique_ptr<Module> parseAssemblyString(StringRef AsmString, - SMDiagnostic &Error, + SMDiagnostic &Err, LLVMContext &Context, SlotMapping *Slots = nullptr, - bool UpgradeDebugInfo = true); + bool UpgradeDebugInfo = true, + StringRef DataLayoutString = ""); + +/// Holds the Module and ModuleSummaryIndex returned by the interfaces +/// that parse both. +struct ParsedModuleAndIndex { + std::unique_ptr<Module> Mod; + std::unique_ptr<ModuleSummaryIndex> Index; +}; + +/// This function is a main interface to the LLVM Assembly Parser. It parses +/// an ASCII file that (presumably) contains LLVM Assembly code, including +/// a module summary. It returns a Module (intermediate representation) and +/// a ModuleSummaryIndex with the corresponding features. Note that this does +/// not verify that the generated Module or Index are valid, so you should +/// run the verifier after parsing the file to check that they are okay. +/// Parse LLVM Assembly from a file +/// \param Filename The name of the file to parse +/// \param Err Error result info. +/// \param Context Context in which to allocate globals info. +/// \param Slots The optional slot mapping that will be initialized during +/// parsing. +/// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier. +/// This option should only be set to false by llvm-as +/// for use inside the LLVM testuite! +/// \param DataLayoutString Override datalayout in the llvm assembly. +ParsedModuleAndIndex +parseAssemblyFileWithIndex(StringRef Filename, SMDiagnostic &Err, + LLVMContext &Context, SlotMapping *Slots = nullptr, + bool UpgradeDebugInfo = true, + StringRef DataLayoutString = ""); + +/// This function is a main interface to the LLVM Assembly Parser. It parses +/// an ASCII file that (presumably) contains LLVM Assembly code for a module +/// summary. It returns a a ModuleSummaryIndex with the corresponding features. +/// Note that this does not verify that the generated Index is valid, so you +/// should run the verifier after parsing the file to check that it is okay. +/// Parse LLVM Assembly Index from a file +/// \param Filename The name of the file to parse +/// \param Err Error result info. +std::unique_ptr<ModuleSummaryIndex> +parseSummaryIndexAssemblyFile(StringRef Filename, SMDiagnostic &Err); /// parseAssemblyFile and parseAssemblyString are wrappers around this function. -/// \brief Parse LLVM Assembly from a MemoryBuffer. +/// Parse LLVM Assembly from a MemoryBuffer. /// \param F The MemoryBuffer containing assembly /// \param Err Error result info. /// \param Slots The optional slot mapping that will be initialized during @@ -72,10 +117,40 @@ std::unique_ptr<Module> parseAssemblyString(StringRef AsmString, /// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier. /// This option should only be set to false by llvm-as /// for use inside the LLVM testuite! +/// \param DataLayoutString Override datalayout in the llvm assembly. std::unique_ptr<Module> parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, LLVMContext &Context, SlotMapping *Slots = nullptr, - bool UpgradeDebugInfo = true); + bool UpgradeDebugInfo = true, + StringRef DataLayoutString = ""); + +/// Parse LLVM Assembly including the summary index from a MemoryBuffer. +/// +/// \param F The MemoryBuffer containing assembly with summary +/// \param Err Error result info. +/// \param Slots The optional slot mapping that will be initialized during +/// parsing. +/// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier. +/// This option should only be set to false by llvm-as +/// for use inside the LLVM testuite! +/// \param DataLayoutString Override datalayout in the llvm assembly. +/// +/// parseAssemblyFileWithIndex is a wrapper around this function. +ParsedModuleAndIndex parseAssemblyWithIndex(MemoryBufferRef F, + SMDiagnostic &Err, + LLVMContext &Context, + SlotMapping *Slots = nullptr, + bool UpgradeDebugInfo = true, + StringRef DataLayoutString = ""); + +/// Parse LLVM Assembly for summary index from a MemoryBuffer. +/// +/// \param F The MemoryBuffer containing assembly with summary +/// \param Err Error result info. +/// +/// parseSummaryIndexAssemblyFile is a wrapper around this function. +std::unique_ptr<ModuleSummaryIndex> +parseSummaryIndexAssembly(MemoryBufferRef F, SMDiagnostic &Err); /// This function is the low-level interface to the LLVM Assembly Parser. /// This is kept as an independent function instead of being inlined into @@ -84,6 +159,7 @@ std::unique_ptr<Module> parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, /// /// \param F The MemoryBuffer containing assembly /// \param M The module to add data to. +/// \param Index The index to add data to. /// \param Err Error result info. /// \param Slots The optional slot mapping that will be initialized during /// parsing. @@ -91,9 +167,11 @@ std::unique_ptr<Module> parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, /// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier. /// This option should only be set to false by llvm-as /// for use inside the LLVM testuite! -bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err, - SlotMapping *Slots = nullptr, - bool UpgradeDebugInfo = true); +/// \param DataLayoutString Override datalayout in the llvm assembly. +bool parseAssemblyInto(MemoryBufferRef F, Module *M, ModuleSummaryIndex *Index, + SMDiagnostic &Err, SlotMapping *Slots = nullptr, + bool UpgradeDebugInfo = true, + StringRef DataLayoutString = ""); /// Parse a type and a constant value in the given string. /// diff --git a/contrib/llvm/include/llvm/BinaryFormat/COFF.h b/contrib/llvm/include/llvm/BinaryFormat/COFF.h index a55c544dfe90..7b973c03cc80 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/COFF.h +++ b/contrib/llvm/include/llvm/BinaryFormat/COFF.h @@ -110,6 +110,9 @@ enum MachineTypes : unsigned { IMAGE_FILE_MACHINE_POWERPC = 0x1F0, IMAGE_FILE_MACHINE_POWERPCFP = 0x1F1, IMAGE_FILE_MACHINE_R4000 = 0x166, + IMAGE_FILE_MACHINE_RISCV32 = 0x5032, + IMAGE_FILE_MACHINE_RISCV64 = 0x5064, + IMAGE_FILE_MACHINE_RISCV128 = 0x5128, IMAGE_FILE_MACHINE_SH3 = 0x1A2, IMAGE_FILE_MACHINE_SH3DSP = 0x1A3, IMAGE_FILE_MACHINE_SH4 = 0x1A6, @@ -460,7 +463,7 @@ union Auxiliary { AuxiliarySectionDefinition SectionDefinition; }; -/// @brief The Import Directory Table. +/// The Import Directory Table. /// /// There is a single array of these and one entry per imported DLL. struct ImportDirectoryTableEntry { @@ -471,7 +474,7 @@ struct ImportDirectoryTableEntry { uint32_t ImportAddressTableRVA; }; -/// @brief The PE32 Import Lookup Table. +/// The PE32 Import Lookup Table. /// /// There is an array of these for each imported DLL. It represents either /// the ordinal to import from the target DLL, or a name to lookup and import @@ -482,32 +485,32 @@ struct ImportDirectoryTableEntry { struct ImportLookupTableEntry32 { uint32_t data; - /// @brief Is this entry specified by ordinal, or name? + /// Is this entry specified by ordinal, or name? bool isOrdinal() const { return data & 0x80000000; } - /// @brief Get the ordinal value of this entry. isOrdinal must be true. + /// Get the ordinal value of this entry. isOrdinal must be true. uint16_t getOrdinal() const { assert(isOrdinal() && "ILT entry is not an ordinal!"); return data & 0xFFFF; } - /// @brief Set the ordinal value and set isOrdinal to true. + /// Set the ordinal value and set isOrdinal to true. void setOrdinal(uint16_t o) { data = o; data |= 0x80000000; } - /// @brief Get the Hint/Name entry RVA. isOrdinal must be false. + /// Get the Hint/Name entry RVA. isOrdinal must be false. uint32_t getHintNameRVA() const { assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); return data; } - /// @brief Set the Hint/Name entry RVA and set isOrdinal to false. + /// Set the Hint/Name entry RVA and set isOrdinal to false. void setHintNameRVA(uint32_t rva) { data = rva; } }; -/// @brief The DOS compatible header at the front of all PEs. +/// The DOS compatible header at the front of all PEs. struct DOSHeader { uint16_t Magic; uint16_t UsedBytesInTheLastPage; diff --git a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def index 3ade3ea0d338..57e259615d0c 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -12,15 +12,15 @@ //===----------------------------------------------------------------------===// // TODO: Add other DW-based macros. -#if !(defined HANDLE_DW_TAG || defined HANDLE_DW_AT || \ - defined HANDLE_DW_FORM || defined HANDLE_DW_OP || \ - defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \ - defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_DEFAULTED || \ - defined HANDLE_DW_CC || defined HANDLE_DW_LNS || \ - defined HANDLE_DW_LNE || defined HANDLE_DW_LNCT || \ - defined HANDLE_DW_MACRO || defined HANDLE_DW_RLE || \ - defined HANDLE_DW_CFA || defined HANDLE_DW_APPLE_PROPERTY || \ - defined HANDLE_DW_UT || defined HANDLE_DWARF_SECTION) +#if !( \ + defined HANDLE_DW_TAG || defined HANDLE_DW_AT || defined HANDLE_DW_FORM || \ + defined HANDLE_DW_OP || defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \ + defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_DEFAULTED || \ + defined HANDLE_DW_CC || defined HANDLE_DW_LNS || defined HANDLE_DW_LNE || \ + defined HANDLE_DW_LNCT || defined HANDLE_DW_MACRO || \ + defined HANDLE_DW_RLE || defined HANDLE_DW_CFA || \ + defined HANDLE_DW_APPLE_PROPERTY || defined HANDLE_DW_UT || \ + defined HANDLE_DWARF_SECTION || defined HANDLE_DW_IDX) #error "Missing macro definition of HANDLE_DW*" #endif @@ -96,6 +96,10 @@ #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) #endif +#ifndef HANDLE_DW_IDX +#define HANDLE_DW_IDX(ID, NAME) +#endif + HANDLE_DW_TAG(0x0000, null, 2, DWARF) HANDLE_DW_TAG(0x0001, array_type, 2, DWARF) HANDLE_DW_TAG(0x0002, class_type, 2, DWARF) @@ -704,6 +708,7 @@ HANDLE_DW_CC(0x03, nocall) HANDLE_DW_CC(0x04, pass_by_reference) HANDLE_DW_CC(0x05, pass_by_value) // Vendor extensions: +HANDLE_DW_CC(0x40, GNU_renesas_sh) HANDLE_DW_CC(0x41, GNU_borland_fastcall_i386) HANDLE_DW_CC(0xb0, BORLAND_safecall) HANDLE_DW_CC(0xb1, BORLAND_stdcall) @@ -713,6 +718,22 @@ HANDLE_DW_CC(0xb4, BORLAND_msreturn) HANDLE_DW_CC(0xb5, BORLAND_thiscall) HANDLE_DW_CC(0xb6, BORLAND_fastcall) HANDLE_DW_CC(0xc0, LLVM_vectorcall) +HANDLE_DW_CC(0xc1, LLVM_Win64) +HANDLE_DW_CC(0xc2, LLVM_X86_64SysV) +HANDLE_DW_CC(0xc3, LLVM_AAPCS) +HANDLE_DW_CC(0xc4, LLVM_AAPCS_VFP) +HANDLE_DW_CC(0xc5, LLVM_IntelOclBicc) +HANDLE_DW_CC(0xc6, LLVM_SpirFunction) +HANDLE_DW_CC(0xc7, LLVM_OpenCLKernel) +HANDLE_DW_CC(0xc8, LLVM_Swift) +HANDLE_DW_CC(0xc9, LLVM_PreserveMost) +HANDLE_DW_CC(0xca, LLVM_PreserveAll) +HANDLE_DW_CC(0xcb, LLVM_X86RegCall) +// From GCC source code (include/dwarf2.h): This DW_CC_ value is not currently +// generated by any toolchain. It is used internally to GDB to indicate OpenCL C +// functions that have been compiled with the IBM XL C for OpenCL compiler and use +// a non-platform calling convention for passing OpenCL C vector types. +HANDLE_DW_CC(0xff, GDB_IBM_OpenCL) // Line Number Extended Opcode Encodings HANDLE_DW_LNE(0x01, end_sequence) @@ -743,6 +764,9 @@ HANDLE_DW_LNCT(0x02, directory_index) HANDLE_DW_LNCT(0x03, timestamp) HANDLE_DW_LNCT(0x04, size) HANDLE_DW_LNCT(0x05, MD5) +// A vendor extension until http://dwarfstd.org/ShowIssue.php?issue=180201.1 is +// accepted and incorporated into the next DWARF standard. +HANDLE_DW_LNCT(0x2001, LLVM_source) // DWARF v5 Macro information. HANDLE_DW_MACRO(0x01, define) @@ -836,14 +860,17 @@ HANDLE_DWARF_SECTION(DebugAranges, ".debug_aranges", "debug-aranges") HANDLE_DWARF_SECTION(DebugInfo, ".debug_info", "debug-info") HANDLE_DWARF_SECTION(DebugTypes, ".debug_types", "debug-types") HANDLE_DWARF_SECTION(DebugLine, ".debug_line", "debug-line") +HANDLE_DWARF_SECTION(DebugLineStr, ".debug_line_str", "debug-line-str") HANDLE_DWARF_SECTION(DebugLoc, ".debug_loc", "debug-loc") HANDLE_DWARF_SECTION(DebugFrame, ".debug_frame", "debug-frame") HANDLE_DWARF_SECTION(DebugMacro, ".debug_macro", "debug-macro") -HANDLE_DWARF_SECTION(DebugRanges, ".debug_ranges", "debug-ranges") +HANDLE_DWARF_SECTION(DebugNames, ".debug_names", "debug-names") HANDLE_DWARF_SECTION(DebugPubnames, ".debug_pubnames", "debug-pubnames") HANDLE_DWARF_SECTION(DebugPubtypes, ".debug_pubtypes", "debug-pubtypes") HANDLE_DWARF_SECTION(DebugGnuPubnames, ".debug_gnu_pubnames", "debug-gnu-pubnames") HANDLE_DWARF_SECTION(DebugGnuPubtypes, ".debug_gnu_pubtypes", "debug-gnu-pubtypes") +HANDLE_DWARF_SECTION(DebugRanges, ".debug_ranges", "debug-ranges") +HANDLE_DWARF_SECTION(DebugRnglists, ".debug_rnglists", "debug-rnglists") HANDLE_DWARF_SECTION(DebugStr, ".debug_str", "debug-str") HANDLE_DWARF_SECTION(DebugStrOffsets, ".debug_str_offsets", "debug-str-offsets") HANDLE_DWARF_SECTION(DebugCUIndex, ".debug_cu_index", "debug-cu-index") @@ -855,6 +882,12 @@ HANDLE_DWARF_SECTION(AppleNamespaces, ".apple_namespaces", "apple-namespaces") HANDLE_DWARF_SECTION(AppleObjC, ".apple_objc", "apple-objc") HANDLE_DWARF_SECTION(GdbIndex, ".gdb_index", "gdb-index") +HANDLE_DW_IDX(0x01, compile_unit) +HANDLE_DW_IDX(0x02, type_unit) +HANDLE_DW_IDX(0x03, die_offset) +HANDLE_DW_IDX(0x04, parent) +HANDLE_DW_IDX(0x05, type_hash) + #undef HANDLE_DW_TAG #undef HANDLE_DW_AT @@ -874,3 +907,4 @@ HANDLE_DWARF_SECTION(GdbIndex, ".gdb_index", "gdb-index") #undef HANDLE_DW_APPLE_PROPERTY #undef HANDLE_DW_UT #undef HANDLE_DWARF_SECTION +#undef HANDLE_DW_IDX diff --git a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h index a0e5367b412c..9036f405eaea 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h +++ b/contrib/llvm/include/llvm/BinaryFormat/Dwarf.h @@ -20,8 +20,12 @@ #ifndef LLVM_BINARYFORMAT_DWARF_H #define LLVM_BINARYFORMAT_DWARF_H +#include "llvm/ADT/Optional.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadicDetails.h" namespace llvm { class StringRef; @@ -57,6 +61,9 @@ enum LLVMConstants : uint32_t { DWARF_VENDOR_MIPS = 6 }; +/// Constants that define the DWARF format as 32 or 64 bit. +enum DwarfFormat : uint8_t { DWARF32, DWARF64 }; + /// Special ID values that distinguish a CIE from a FDE in DWARF CFI. /// Not inside an enum because a 64-bit value is needed. /// @{ @@ -125,7 +132,7 @@ enum LocationAtom { DW_OP_LLVM_fragment = 0x1000 ///< Only used in LLVM metadata. }; -enum TypeKind { +enum TypeKind : uint8_t { #define HANDLE_DW_ATE(ID, NAME, VERSION, VENDOR) DW_ATE_##NAME = ID, #include "llvm/BinaryFormat/Dwarf.def" DW_ATE_lo_user = 0x80, @@ -325,6 +332,13 @@ enum UnitType : unsigned char { DW_UT_hi_user = 0xff }; +enum Index { +#define HANDLE_DW_IDX(ID, NAME) DW_IDX_##NAME = ID, +#include "llvm/BinaryFormat/Dwarf.def" + DW_IDX_lo_user = 0x2000, + DW_IDX_hi_user = 0x3fff +}; + inline bool isUnitType(uint8_t UnitType) { switch (UnitType) { case DW_UT_compile: @@ -354,13 +368,16 @@ inline bool isUnitType(dwarf::Tag T) { // Constants for the DWARF v5 Accelerator Table Proposal enum AcceleratorTable { // Data layout descriptors. - DW_ATOM_null = 0u, // Marker as the end of a list of atoms. + DW_ATOM_null = 0u, /// Marker as the end of a list of atoms. DW_ATOM_die_offset = 1u, // DIE offset in the debug_info section. DW_ATOM_cu_offset = 2u, // Offset of the compile unit header that contains the // item in question. DW_ATOM_die_tag = 3u, // A tag entry. DW_ATOM_type_flags = 4u, // Set of flags for a type. + DW_ATOM_type_type_flags = 5u, // Dsymutil type extension. + DW_ATOM_qual_name_hash = 6u, // Dsymutil qualified hash extension. + // DW_ATOM_type_flags values. // Always set for C++, only set for ObjC if this is the @implementation for a @@ -390,8 +407,8 @@ enum GDBIndexEntryLinkage { GIEL_EXTERNAL, GIEL_STATIC }; /// \defgroup DwarfConstantsDumping Dwarf constants dumping functions /// /// All these functions map their argument's value back to the -/// corresponding enumerator name or return nullptr if the value isn't -/// known. +/// corresponding enumerator name or return an empty StringRef if the value +/// isn't known. /// /// @{ StringRef TagString(unsigned Tag); @@ -410,16 +427,17 @@ StringRef CaseString(unsigned Case); StringRef ConventionString(unsigned Convention); StringRef InlineCodeString(unsigned Code); StringRef ArrayOrderString(unsigned Order); -StringRef DiscriminantString(unsigned Discriminant); StringRef LNStandardString(unsigned Standard); StringRef LNExtendedString(unsigned Encoding); StringRef MacinfoString(unsigned Encoding); +StringRef RangeListEncodingString(unsigned Encoding); StringRef CallFrameString(unsigned Encoding); StringRef ApplePropertyString(unsigned); StringRef UnitTypeString(unsigned); StringRef AtomTypeString(unsigned Atom); StringRef GDBIndexEntryKindString(GDBIndexEntryKind Kind); StringRef GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage); +StringRef IndexString(unsigned Idx); /// @} /// \defgroup DwarfConstantsParsing Dwarf constants parsing functions @@ -471,6 +489,49 @@ unsigned AttributeEncodingVendor(TypeKind E); unsigned LanguageVendor(SourceLanguage L); /// @} +/// A helper struct providing information about the byte size of DW_FORM +/// values that vary in size depending on the DWARF version, address byte +/// size, or DWARF32/DWARF64. +struct FormParams { + uint16_t Version; + uint8_t AddrSize; + DwarfFormat Format; + + /// The definition of the size of form DW_FORM_ref_addr depends on the + /// version. In DWARF v2 it's the size of an address; after that, it's the + /// size of a reference. + uint8_t getRefAddrByteSize() const { + if (Version == 2) + return AddrSize; + return getDwarfOffsetByteSize(); + } + + /// The size of a reference is determined by the DWARF 32/64-bit format. + uint8_t getDwarfOffsetByteSize() const { + switch (Format) { + case DwarfFormat::DWARF32: + return 4; + case DwarfFormat::DWARF64: + return 8; + } + llvm_unreachable("Invalid Format value"); + } + + explicit operator bool() const { return Version && AddrSize; } +}; + +/// Get the fixed byte size for a given form. +/// +/// If the form has a fixed byte size, then an Optional with a value will be +/// returned. If the form is always encoded using a variable length storage +/// format (ULEB or SLEB numbers or blocks) then None will be returned. +/// +/// \param Form DWARF form to get the fixed byte size for. +/// \param Params DWARF parameters to help interpret forms. +/// \returns Optional<uint8_t> value with the fixed byte size or None if +/// \p Form doesn't have a fixed byte size. +Optional<uint8_t> getFixedFormByteSize(dwarf::Form Form, FormParams Params); + /// Tells whether the specified form is defined in the specified version, /// or is an extension if extensions are allowed. bool isValidFormForVersion(Form F, unsigned Version, bool ExtensionsOk = true); @@ -479,6 +540,10 @@ bool isValidFormForVersion(Form F, unsigned Version, bool ExtensionsOk = true); /// for attribute Attr. StringRef AttributeValueString(uint16_t Attr, unsigned Val); +/// Returns the symbolic string representing Val when used as a value +/// for atom Atom. +StringRef AtomValueString(uint16_t Atom, unsigned Val); + /// Describes an entry of the various gnu_pub* debug sections. /// /// The gnu_pub* kind looks like: @@ -514,14 +579,46 @@ private: }; }; -/// Constants that define the DWARF format as 32 or 64 bit. -enum DwarfFormat : uint8_t { DWARF32, DWARF64 }; +template <typename Enum> struct EnumTraits : public std::false_type {}; -/// The Bernstein hash function used by the accelerator tables. -uint32_t djbHash(StringRef Buffer); +template <> struct EnumTraits<Attribute> : public std::true_type { + static constexpr char Type[3] = "AT"; + static constexpr StringRef (*StringFn)(unsigned) = &AttributeString; +}; +template <> struct EnumTraits<Form> : public std::true_type { + static constexpr char Type[5] = "FORM"; + static constexpr StringRef (*StringFn)(unsigned) = &FormEncodingString; +}; + +template <> struct EnumTraits<Index> : public std::true_type { + static constexpr char Type[4] = "IDX"; + static constexpr StringRef (*StringFn)(unsigned) = &IndexString; +}; + +template <> struct EnumTraits<Tag> : public std::true_type { + static constexpr char Type[4] = "TAG"; + static constexpr StringRef (*StringFn)(unsigned) = &TagString; +}; } // End of namespace dwarf +/// Dwarf constants format_provider +/// +/// Specialization of the format_provider template for dwarf enums. Unlike the +/// dumping functions above, these format unknown enumerator values as +/// DW_TYPE_unknown_1234 (e.g. DW_TAG_unknown_ffff). +template <typename Enum> +struct format_provider< + Enum, typename std::enable_if<dwarf::EnumTraits<Enum>::value>::type> { + static void format(const Enum &E, raw_ostream &OS, StringRef Style) { + StringRef Str = dwarf::EnumTraits<Enum>::StringFn(E); + if (Str.empty()) { + OS << "DW_" << dwarf::EnumTraits<Enum>::Type << "_unknown_" + << llvm::format("%x", E); + } else + OS << Str; + } +}; } // End of namespace llvm #endif diff --git a/contrib/llvm/include/llvm/BinaryFormat/DynamicTags.def b/contrib/llvm/include/llvm/BinaryFormat/DynamicTags.def new file mode 100644 index 000000000000..2e15cc30fca7 --- /dev/null +++ b/contrib/llvm/include/llvm/BinaryFormat/DynamicTags.def @@ -0,0 +1,216 @@ +#ifndef DYNAMIC_TAG +#error "DYNAMIC_TAG must be defined" +#endif + +// Add separate macros for the architecture specific tags and the markers +// such as DT_HIOS, etc. to allow using this file to in other contexts. +// For example we can use it to generate a stringification switch statement. + +#ifndef HEXAGON_DYNAMIC_TAG +#define HEXAGON_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#define HEXAGON_DYNAMIC_TAG_DEFINED +#endif + +#ifndef MIPS_DYNAMIC_TAG +#define MIPS_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#define MIPS_DYNAMIC_TAG_DEFINED +#endif + +#ifndef PPC64_DYNAMIC_TAG +#define PPC64_DYNAMIC_TAG(name, value) DYNAMIC_TAG(name, value) +#define PPC64_DYNAMIC_TAG_DEFINED +#endif + +#ifndef DYNAMIC_TAG_MARKER +#define DYNAMIC_TAG_MARKER(name, value) DYNAMIC_TAG(name, value) +#define DYNAMIC_TAG_MARKER_DEFINED +#endif + +DYNAMIC_TAG(NULL, 0) // Marks end of dynamic array. +DYNAMIC_TAG(NEEDED, 1) // String table offset of needed library. +DYNAMIC_TAG(PLTRELSZ, 2) // Size of relocation entries in PLT. +DYNAMIC_TAG(PLTGOT, 3) // Address associated with linkage table. +DYNAMIC_TAG(HASH, 4) // Address of symbolic hash table. +DYNAMIC_TAG(STRTAB, 5) // Address of dynamic string table. +DYNAMIC_TAG(SYMTAB, 6) // Address of dynamic symbol table. +DYNAMIC_TAG(RELA, 7) // Address of relocation table (Rela entries). +DYNAMIC_TAG(RELASZ, 8) // Size of Rela relocation table. +DYNAMIC_TAG(RELAENT, 9) // Size of a Rela relocation entry. +DYNAMIC_TAG(STRSZ, 10) // Total size of the string table. +DYNAMIC_TAG(SYMENT, 11) // Size of a symbol table entry. +DYNAMIC_TAG(INIT, 12) // Address of initialization function. +DYNAMIC_TAG(FINI, 13) // Address of termination function. +DYNAMIC_TAG(SONAME, 14) // String table offset of a shared objects name. +DYNAMIC_TAG(RPATH, 15) // String table offset of library search path. +DYNAMIC_TAG(SYMBOLIC, 16) // Changes symbol resolution algorithm. +DYNAMIC_TAG(REL, 17) // Address of relocation table (Rel entries). +DYNAMIC_TAG(RELSZ, 18) // Size of Rel relocation table. +DYNAMIC_TAG(RELENT, 19) // Size of a Rel relocation entry. +DYNAMIC_TAG(PLTREL, 20) // Type of relocation entry used for linking. +DYNAMIC_TAG(DEBUG, 21) // Reserved for debugger. +DYNAMIC_TAG(TEXTREL, 22) // Relocations exist for non-writable segments. +DYNAMIC_TAG(JMPREL, 23) // Address of relocations associated with PLT. +DYNAMIC_TAG(BIND_NOW, 24) // Process all relocations before execution. +DYNAMIC_TAG(INIT_ARRAY, 25) // Pointer to array of initialization functions. +DYNAMIC_TAG(FINI_ARRAY, 26) // Pointer to array of termination functions. +DYNAMIC_TAG(INIT_ARRAYSZ, 27) // Size of DT_INIT_ARRAY. +DYNAMIC_TAG(FINI_ARRAYSZ, 28) // Size of DT_FINI_ARRAY. +DYNAMIC_TAG(RUNPATH, 29) // String table offset of lib search path. +DYNAMIC_TAG(FLAGS, 30) // Flags. +DYNAMIC_TAG_MARKER(ENCODING, 32) // Values from here to DT_LOOS follow the rules + // for the interpretation of the d_un union. + +DYNAMIC_TAG(PREINIT_ARRAY, 32) // Pointer to array of preinit functions. +DYNAMIC_TAG(PREINIT_ARRAYSZ, 33) // Size of the DT_PREINIT_ARRAY array. + +DYNAMIC_TAG(SYMTAB_SHNDX, 34) // Address of the SHT_SYMTAB_SHNDX section. + +// Experimental support for SHT_RELR sections. For details, see proposal +// at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg +DYNAMIC_TAG(RELRSZ, 35) // Size of Relr relocation table. +DYNAMIC_TAG(RELR, 36) // Address of relocation table (Relr entries). +DYNAMIC_TAG(RELRENT, 37) // Size of a Relr relocation entry. + +DYNAMIC_TAG_MARKER(LOOS, 0x60000000) // Start of environment specific tags. +DYNAMIC_TAG_MARKER(HIOS, 0x6FFFFFFF) // End of environment specific tags. +DYNAMIC_TAG_MARKER(LOPROC, 0x70000000) // Start of processor specific tags. +DYNAMIC_TAG_MARKER(HIPROC, 0x7FFFFFFF) // End of processor specific tags. + +// Android packed relocation section tags. +// https://android.googlesource.com/platform/bionic/+/6f12bfece5dcc01325e0abba56a46b1bcf991c69/tools/relocation_packer/src/elf_file.cc#31 +DYNAMIC_TAG(ANDROID_REL, 0x6000000F) +DYNAMIC_TAG(ANDROID_RELSZ, 0x60000010) +DYNAMIC_TAG(ANDROID_RELA, 0x60000011) +DYNAMIC_TAG(ANDROID_RELASZ, 0x60000012) + +// Android's experimental support for SHT_RELR sections. +// https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#253 +DYNAMIC_TAG(ANDROID_RELR, 0x6FFFE000) // Address of relocation table (Relr entries). +DYNAMIC_TAG(ANDROID_RELRSZ, 0x6FFFE001) // Size of Relr relocation table. +DYNAMIC_TAG(ANDROID_RELRENT, 0x6FFFE003) // Size of a Relr relocation entry. + +DYNAMIC_TAG(GNU_HASH, 0x6FFFFEF5) // Reference to the GNU hash table. +DYNAMIC_TAG(TLSDESC_PLT, 0x6FFFFEF6) // Location of PLT entry for TLS + // descriptor resolver calls. +DYNAMIC_TAG(TLSDESC_GOT, 0x6FFFFEF7) // Location of GOT entry used by TLS + // descriptor resolver PLT entry. +DYNAMIC_TAG(RELACOUNT, 0x6FFFFFF9) // ELF32_Rela count. +DYNAMIC_TAG(RELCOUNT, 0x6FFFFFFA) // ELF32_Rel count. + +DYNAMIC_TAG(FLAGS_1, 0X6FFFFFFB) // Flags_1. + +DYNAMIC_TAG(VERSYM, 0x6FFFFFF0) // The address of .gnu.version section. +DYNAMIC_TAG(VERDEF, 0X6FFFFFFC) // The address of the version definition + // table. +DYNAMIC_TAG(VERDEFNUM, 0X6FFFFFFD) // The number of entries in DT_VERDEF. +DYNAMIC_TAG(VERNEED, 0X6FFFFFFE) // The address of the version dependency + // table. +DYNAMIC_TAG(VERNEEDNUM, 0X6FFFFFFF) // The number of entries in DT_VERNEED. + +// Hexagon specific dynamic table entries +HEXAGON_DYNAMIC_TAG(HEXAGON_SYMSZ, 0x70000000) +HEXAGON_DYNAMIC_TAG(HEXAGON_VER, 0x70000001) +HEXAGON_DYNAMIC_TAG(HEXAGON_PLT, 0x70000002) + +// Mips specific dynamic table entry tags. + +MIPS_DYNAMIC_TAG(MIPS_RLD_VERSION, 0x70000001) // 32 bit version number for + // runtime linker interface. +MIPS_DYNAMIC_TAG(MIPS_TIME_STAMP, 0x70000002) // Time stamp. +MIPS_DYNAMIC_TAG(MIPS_ICHECKSUM, 0x70000003) // Checksum of external strings + // and common sizes. +MIPS_DYNAMIC_TAG(MIPS_IVERSION, 0x70000004) // Index of version string + // in string table. +MIPS_DYNAMIC_TAG(MIPS_FLAGS, 0x70000005) // 32 bits of flags. +MIPS_DYNAMIC_TAG(MIPS_BASE_ADDRESS, 0x70000006) // Base address of the segment. +MIPS_DYNAMIC_TAG(MIPS_MSYM, 0x70000007) // Address of .msym section. +MIPS_DYNAMIC_TAG(MIPS_CONFLICT, 0x70000008) // Address of .conflict section. +MIPS_DYNAMIC_TAG(MIPS_LIBLIST, 0x70000009) // Address of .liblist section. +MIPS_DYNAMIC_TAG(MIPS_LOCAL_GOTNO, 0x7000000a) // Number of local global offset + // table entries. +MIPS_DYNAMIC_TAG(MIPS_CONFLICTNO, 0x7000000b) // Number of entries + // in the .conflict section. +MIPS_DYNAMIC_TAG(MIPS_LIBLISTNO, 0x70000010) // Number of entries + // in the .liblist section. +MIPS_DYNAMIC_TAG(MIPS_SYMTABNO, 0x70000011) // Number of entries + // in the .dynsym section. +MIPS_DYNAMIC_TAG(MIPS_UNREFEXTNO, 0x70000012) // Index of first external dynamic + // symbol not referenced locally. +MIPS_DYNAMIC_TAG(MIPS_GOTSYM, 0x70000013) // Index of first dynamic symbol + // in global offset table. +MIPS_DYNAMIC_TAG(MIPS_HIPAGENO, 0x70000014) // Number of page table entries + // in global offset table. +MIPS_DYNAMIC_TAG(MIPS_RLD_MAP, 0x70000016) // Address of run time loader map + // used for debugging. +MIPS_DYNAMIC_TAG(MIPS_DELTA_CLASS, 0x70000017) // Delta C++ class definition. +MIPS_DYNAMIC_TAG(MIPS_DELTA_CLASS_NO, 0x70000018) // Number of entries + // in DT_MIPS_DELTA_CLASS. +MIPS_DYNAMIC_TAG(MIPS_DELTA_INSTANCE, 0x70000019) // Delta C++ class instances. +MIPS_DYNAMIC_TAG(MIPS_DELTA_INSTANCE_NO, 0x7000001A) // Number of entries + // in DT_MIPS_DELTA_INSTANCE. +MIPS_DYNAMIC_TAG(MIPS_DELTA_RELOC, 0x7000001B) // Delta relocations. +MIPS_DYNAMIC_TAG(MIPS_DELTA_RELOC_NO, 0x7000001C) // Number of entries + // in DT_MIPS_DELTA_RELOC. +MIPS_DYNAMIC_TAG(MIPS_DELTA_SYM, 0x7000001D) // Delta symbols that Delta + // relocations refer to. +MIPS_DYNAMIC_TAG(MIPS_DELTA_SYM_NO, 0x7000001E) // Number of entries + // in DT_MIPS_DELTA_SYM. +MIPS_DYNAMIC_TAG(MIPS_DELTA_CLASSSYM, 0x70000020) // Delta symbols that hold + // class declarations. +MIPS_DYNAMIC_TAG(MIPS_DELTA_CLASSSYM_NO, 0x70000021) // Number of entries + // in DT_MIPS_DELTA_CLASSSYM. + +MIPS_DYNAMIC_TAG(MIPS_CXX_FLAGS, 0x70000022) // Flags indicating information + // about C++ flavor. +MIPS_DYNAMIC_TAG(MIPS_PIXIE_INIT, 0x70000023) // Pixie information. +MIPS_DYNAMIC_TAG(MIPS_SYMBOL_LIB, 0x70000024) // Address of .MIPS.symlib +MIPS_DYNAMIC_TAG(MIPS_LOCALPAGE_GOTIDX, 0x70000025) // The GOT index of the first PTE + // for a segment +MIPS_DYNAMIC_TAG(MIPS_LOCAL_GOTIDX, 0x70000026) // The GOT index of the first PTE + // for a local symbol +MIPS_DYNAMIC_TAG(MIPS_HIDDEN_GOTIDX, 0x70000027) // The GOT index of the first PTE + // for a hidden symbol +MIPS_DYNAMIC_TAG(MIPS_PROTECTED_GOTIDX, 0x70000028) // The GOT index of the first PTE + // for a protected symbol +MIPS_DYNAMIC_TAG(MIPS_OPTIONS, 0x70000029) // Address of `.MIPS.options'. +MIPS_DYNAMIC_TAG(MIPS_INTERFACE, 0x7000002A) // Address of `.interface'. +MIPS_DYNAMIC_TAG(MIPS_DYNSTR_ALIGN, 0x7000002B) // Unknown. +MIPS_DYNAMIC_TAG(MIPS_INTERFACE_SIZE, 0x7000002C) // Size of the .interface section. +MIPS_DYNAMIC_TAG(MIPS_RLD_TEXT_RESOLVE_ADDR, 0x7000002D) // Size of rld_text_resolve + // function stored in the GOT. +MIPS_DYNAMIC_TAG(MIPS_PERF_SUFFIX, 0x7000002E) // Default suffix of DSO to be added + // by rld on dlopen() calls. +MIPS_DYNAMIC_TAG(MIPS_COMPACT_SIZE, 0x7000002F) // Size of compact relocation + // section (O32). +MIPS_DYNAMIC_TAG(MIPS_GP_VALUE, 0x70000030) // GP value for auxiliary GOTs. +MIPS_DYNAMIC_TAG(MIPS_AUX_DYNAMIC, 0x70000031) // Address of auxiliary .dynamic. +MIPS_DYNAMIC_TAG(MIPS_PLTGOT, 0x70000032) // Address of the base of the PLTGOT. +MIPS_DYNAMIC_TAG(MIPS_RWPLT, 0x70000034) // Points to the base + // of a writable PLT. +MIPS_DYNAMIC_TAG(MIPS_RLD_MAP_REL, 0x70000035) // Relative offset of run time loader + // map, used for debugging. + +// PPC64 specific dynamic table entries. +PPC64_DYNAMIC_TAG(PPC64_GLINK, 0x70000000) // Address of 32 bytes before the + // first glink lazy resolver stub. + +// Sun machine-independent extensions. +DYNAMIC_TAG(AUXILIARY, 0x7FFFFFFD) // Shared object to load before self +DYNAMIC_TAG(FILTER, 0x7FFFFFFF) // Shared object to get values from + + +#ifdef DYNAMIC_TAG_MARKER_DEFINED +#undef DYNAMIC_TAG_MARKER +#endif +#ifdef MIPS_DYNAMIC_TAG_DEFINED +#undef MIPS_DYNAMIC_TAG +#undef MIPS_DYNAMIC_TAG_DEFINED +#endif +#ifdef HEXAGON_DYNAMIC_TAG_DEFINED +#undef HEXAGON_DYNAMIC_TAG +#undef HEXAGON_DYNAMIC_TAG_DEFINED +#endif +#ifdef PPC64_DYNAMIC_TAG_DEFINED +#undef PPC64_DYNAMIC_TAG +#undef PPC64_DYNAMIC_TAG_DEFINED +#endif diff --git a/contrib/llvm/include/llvm/BinaryFormat/ELF.h b/contrib/llvm/include/llvm/BinaryFormat/ELF.h index c902972d93bd..0f3f1939ce68 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/ELF.h +++ b/contrib/llvm/include/llvm/BinaryFormat/ELF.h @@ -312,11 +312,6 @@ enum { EM_RISCV = 243, // RISC-V EM_LANAI = 244, // Lanai 32-bit processor EM_BPF = 247, // Linux kernel bpf virtual machine - - // A request has been made to the maintainer of the official registry for - // such numbers for an official value for WebAssembly. As soon as one is - // allocated, this enum will be updated to use it. - EM_WEBASSEMBLY = 0x4157, // WebAssembly architecture }; // Object file classes. @@ -644,18 +639,78 @@ enum { #include "ELFRelocs/Sparc.def" }; -// ELF Relocation types for WebAssembly -enum { -#include "ELFRelocs/WebAssembly.def" -}; - // AMDGPU specific e_flags. enum : unsigned { - // AMDGPU machine architectures. - EF_AMDGPU_ARCH_NONE = 0x00000000, // None/unknown. - EF_AMDGPU_ARCH_R600 = 0x00000001, // AMD HD2XXX-HD6XXX GPUs. - EF_AMDGPU_ARCH_GCN = 0x00000002, // AMD GCN GFX6+ GPUs. - EF_AMDGPU_ARCH = 0x0000000f // EF_AMDGPU_ARCH_XXX selection mask. + // Processor selection mask for EF_AMDGPU_MACH_* values. + EF_AMDGPU_MACH = 0x0ff, + + // Not specified processor. + EF_AMDGPU_MACH_NONE = 0x000, + + // R600-based processors. + + // Radeon HD 2000/3000 Series (R600). + EF_AMDGPU_MACH_R600_R600 = 0x001, + EF_AMDGPU_MACH_R600_R630 = 0x002, + EF_AMDGPU_MACH_R600_RS880 = 0x003, + EF_AMDGPU_MACH_R600_RV670 = 0x004, + // Radeon HD 4000 Series (R700). + EF_AMDGPU_MACH_R600_RV710 = 0x005, + EF_AMDGPU_MACH_R600_RV730 = 0x006, + EF_AMDGPU_MACH_R600_RV770 = 0x007, + // Radeon HD 5000 Series (Evergreen). + EF_AMDGPU_MACH_R600_CEDAR = 0x008, + EF_AMDGPU_MACH_R600_CYPRESS = 0x009, + EF_AMDGPU_MACH_R600_JUNIPER = 0x00a, + EF_AMDGPU_MACH_R600_REDWOOD = 0x00b, + EF_AMDGPU_MACH_R600_SUMO = 0x00c, + // Radeon HD 6000 Series (Northern Islands). + EF_AMDGPU_MACH_R600_BARTS = 0x00d, + EF_AMDGPU_MACH_R600_CAICOS = 0x00e, + EF_AMDGPU_MACH_R600_CAYMAN = 0x00f, + EF_AMDGPU_MACH_R600_TURKS = 0x010, + + // Reserved for R600-based processors. + EF_AMDGPU_MACH_R600_RESERVED_FIRST = 0x011, + EF_AMDGPU_MACH_R600_RESERVED_LAST = 0x01f, + + // First/last R600-based processors. + EF_AMDGPU_MACH_R600_FIRST = EF_AMDGPU_MACH_R600_R600, + EF_AMDGPU_MACH_R600_LAST = EF_AMDGPU_MACH_R600_TURKS, + + // AMDGCN-based processors. + + // AMDGCN GFX6. + EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020, + EF_AMDGPU_MACH_AMDGCN_GFX601 = 0x021, + // AMDGCN GFX7. + EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022, + EF_AMDGPU_MACH_AMDGCN_GFX701 = 0x023, + EF_AMDGPU_MACH_AMDGCN_GFX702 = 0x024, + EF_AMDGPU_MACH_AMDGCN_GFX703 = 0x025, + EF_AMDGPU_MACH_AMDGCN_GFX704 = 0x026, + // AMDGCN GFX8. + EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028, + EF_AMDGPU_MACH_AMDGCN_GFX802 = 0x029, + EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a, + EF_AMDGPU_MACH_AMDGCN_GFX810 = 0x02b, + // AMDGCN GFX9. + EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c, + EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d, + EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e, + EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f, + + // Reserved for AMDGCN-based processors. + EF_AMDGPU_MACH_AMDGCN_RESERVED0 = 0x027, + EF_AMDGPU_MACH_AMDGCN_RESERVED1 = 0x030, + + // First/last AMDGCN-based processors. + EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600, + EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX906, + + // Indicates if the xnack target feature is enabled for all code contained in + // the object. + EF_AMDGPU_XNACK = 0x100, }; // ELF Relocation types for AMDGPU @@ -714,36 +769,46 @@ enum { // Section types. enum : unsigned { - SHT_NULL = 0, // No associated section (inactive entry). - SHT_PROGBITS = 1, // Program-defined contents. - SHT_SYMTAB = 2, // Symbol table. - SHT_STRTAB = 3, // String table. - SHT_RELA = 4, // Relocation entries; explicit addends. - SHT_HASH = 5, // Symbol hash table. - SHT_DYNAMIC = 6, // Information for dynamic linking. - SHT_NOTE = 7, // Information about the file. - SHT_NOBITS = 8, // Data occupies no space in the file. - SHT_REL = 9, // Relocation entries; no explicit addends. - SHT_SHLIB = 10, // Reserved. - SHT_DYNSYM = 11, // Symbol table. - SHT_INIT_ARRAY = 14, // Pointers to initialization functions. - SHT_FINI_ARRAY = 15, // Pointers to termination functions. - SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions. - SHT_GROUP = 17, // Section group. - SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. - SHT_LOOS = 0x60000000, // Lowest operating system-specific type. + SHT_NULL = 0, // No associated section (inactive entry). + SHT_PROGBITS = 1, // Program-defined contents. + SHT_SYMTAB = 2, // Symbol table. + SHT_STRTAB = 3, // String table. + SHT_RELA = 4, // Relocation entries; explicit addends. + SHT_HASH = 5, // Symbol hash table. + SHT_DYNAMIC = 6, // Information for dynamic linking. + SHT_NOTE = 7, // Information about the file. + SHT_NOBITS = 8, // Data occupies no space in the file. + SHT_REL = 9, // Relocation entries; no explicit addends. + SHT_SHLIB = 10, // Reserved. + SHT_DYNSYM = 11, // Symbol table. + SHT_INIT_ARRAY = 14, // Pointers to initialization functions. + SHT_FINI_ARRAY = 15, // Pointers to termination functions. + SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions. + SHT_GROUP = 17, // Section group. + SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. + // Experimental support for SHT_RELR sections. For details, see proposal + // at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg + SHT_RELR = 19, // Relocation entries; only offsets. + SHT_LOOS = 0x60000000, // Lowest operating system-specific type. // Android packed relocation section types. // https://android.googlesource.com/platform/bionic/+/6f12bfece5dcc01325e0abba56a46b1bcf991c69/tools/relocation_packer/src/elf_file.cc#37 SHT_ANDROID_REL = 0x60000001, SHT_ANDROID_RELA = 0x60000002, - SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table. - SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes. - SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. - SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. - SHT_GNU_verneed = 0x6ffffffe, // GNU version references. - SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. - SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. - SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. + SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table. + SHT_LLVM_LINKER_OPTIONS = 0x6fff4c01, // LLVM Linker Options. + SHT_LLVM_CALL_GRAPH_PROFILE = 0x6fff4c02, // LLVM Call Graph Profile. + SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols + // for safe ICF. + // Android's experimental support for SHT_RELR sections. + // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512 + SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. + SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes. + SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. + SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. + SHT_GNU_verneed = 0x6ffffffe, // GNU version references. + SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. + SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. + SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. // Fixme: All this is duplicated in MCSectionELF. Why?? // Exception Index table SHT_ARM_EXIDX = 0x70000001U, @@ -753,18 +818,18 @@ enum : unsigned { SHT_ARM_ATTRIBUTES = 0x70000003U, SHT_ARM_DEBUGOVERLAY = 0x70000004U, SHT_ARM_OVERLAYSECTION = 0x70000005U, - SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in - // this section based on their sizes - SHT_X86_64_UNWIND = 0x70000001, // Unwind information + SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in + // this section based on their sizes + SHT_X86_64_UNWIND = 0x70000001, // Unwind information - SHT_MIPS_REGINFO = 0x70000006, // Register usage information - SHT_MIPS_OPTIONS = 0x7000000d, // General options - SHT_MIPS_DWARF = 0x7000001e, // DWARF debugging section. - SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. + SHT_MIPS_REGINFO = 0x70000006, // Register usage information + SHT_MIPS_OPTIONS = 0x7000000d, // General options + SHT_MIPS_DWARF = 0x7000001e, // DWARF debugging section. + SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. - SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. - SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. - SHT_HIUSER = 0xffffffff // Highest type reserved for applications. + SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. + SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. + SHT_HIUSER = 0xffffffff // Highest type reserved for applications. }; // Section flags. @@ -1000,6 +1065,9 @@ struct Elf32_Rela { } }; +// Relocation entry without explicit addend or info (relative relocations only). +typedef Elf32_Word Elf32_Relr; // offset/bitmap for relative relocations + // Relocation entry, without explicit addend. struct Elf64_Rel { Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). @@ -1033,6 +1101,9 @@ struct Elf64_Rela { } }; +// Relocation entry without explicit addend or info (relative relocations only). +typedef Elf64_Xword Elf64_Relr; // offset/bitmap for relative relocations + // Program header for ELF32. struct Elf32_Phdr { Elf32_Word p_type; // Type of segment @@ -1096,9 +1167,6 @@ enum { PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. PT_MIPS_OPTIONS = 0x70000002, // Options segment. PT_MIPS_ABIFLAGS = 0x70000003, // Abiflags segment. - - // WebAssembly program header types. - PT_WEBASSEMBLY_FUNCTIONS = PT_LOPROC + 0, // Function definitions. }; // Segment flag bits. @@ -1130,154 +1198,9 @@ struct Elf64_Dyn { // Dynamic table entry tags. enum { - DT_NULL = 0, // Marks end of dynamic array. - DT_NEEDED = 1, // String table offset of needed library. - DT_PLTRELSZ = 2, // Size of relocation entries in PLT. - DT_PLTGOT = 3, // Address associated with linkage table. - DT_HASH = 4, // Address of symbolic hash table. - DT_STRTAB = 5, // Address of dynamic string table. - DT_SYMTAB = 6, // Address of dynamic symbol table. - DT_RELA = 7, // Address of relocation table (Rela entries). - DT_RELASZ = 8, // Size of Rela relocation table. - DT_RELAENT = 9, // Size of a Rela relocation entry. - DT_STRSZ = 10, // Total size of the string table. - DT_SYMENT = 11, // Size of a symbol table entry. - DT_INIT = 12, // Address of initialization function. - DT_FINI = 13, // Address of termination function. - DT_SONAME = 14, // String table offset of a shared objects name. - DT_RPATH = 15, // String table offset of library search path. - DT_SYMBOLIC = 16, // Changes symbol resolution algorithm. - DT_REL = 17, // Address of relocation table (Rel entries). - DT_RELSZ = 18, // Size of Rel relocation table. - DT_RELENT = 19, // Size of a Rel relocation entry. - DT_PLTREL = 20, // Type of relocation entry used for linking. - DT_DEBUG = 21, // Reserved for debugger. - DT_TEXTREL = 22, // Relocations exist for non-writable segments. - DT_JMPREL = 23, // Address of relocations associated with PLT. - DT_BIND_NOW = 24, // Process all relocations before execution. - DT_INIT_ARRAY = 25, // Pointer to array of initialization functions. - DT_FINI_ARRAY = 26, // Pointer to array of termination functions. - DT_INIT_ARRAYSZ = 27, // Size of DT_INIT_ARRAY. - DT_FINI_ARRAYSZ = 28, // Size of DT_FINI_ARRAY. - DT_RUNPATH = 29, // String table offset of lib search path. - DT_FLAGS = 30, // Flags. - DT_ENCODING = 32, // Values from here to DT_LOOS follow the rules - // for the interpretation of the d_un union. - - DT_PREINIT_ARRAY = 32, // Pointer to array of preinit functions. - DT_PREINIT_ARRAYSZ = 33, // Size of the DT_PREINIT_ARRAY array. - - DT_LOOS = 0x60000000, // Start of environment specific tags. - DT_HIOS = 0x6FFFFFFF, // End of environment specific tags. - DT_LOPROC = 0x70000000, // Start of processor specific tags. - DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags. - - // Android packed relocation section tags. - // https://android.googlesource.com/platform/bionic/+/6f12bfece5dcc01325e0abba56a46b1bcf991c69/tools/relocation_packer/src/elf_file.cc#31 - DT_ANDROID_REL = 0x6000000F, - DT_ANDROID_RELSZ = 0x60000010, - DT_ANDROID_RELA = 0x60000011, - DT_ANDROID_RELASZ = 0x60000012, - - DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table. - DT_TLSDESC_PLT = - 0x6FFFFEF6, // Location of PLT entry for TLS descriptor resolver calls. - DT_TLSDESC_GOT = 0x6FFFFEF7, // Location of GOT entry used by TLS descriptor - // resolver PLT entry. - DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count. - DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. - - DT_FLAGS_1 = 0X6FFFFFFB, // Flags_1. - DT_VERSYM = 0x6FFFFFF0, // The address of .gnu.version section. - DT_VERDEF = 0X6FFFFFFC, // The address of the version definition table. - DT_VERDEFNUM = 0X6FFFFFFD, // The number of entries in DT_VERDEF. - DT_VERNEED = 0X6FFFFFFE, // The address of the version Dependency table. - DT_VERNEEDNUM = 0X6FFFFFFF, // The number of entries in DT_VERNEED. - - // Hexagon specific dynamic table entries - DT_HEXAGON_SYMSZ = 0x70000000, - DT_HEXAGON_VER = 0x70000001, - DT_HEXAGON_PLT = 0x70000002, - - // Mips specific dynamic table entry tags. - DT_MIPS_RLD_VERSION = 0x70000001, // 32 bit version number for runtime - // linker interface. - DT_MIPS_TIME_STAMP = 0x70000002, // Time stamp. - DT_MIPS_ICHECKSUM = 0x70000003, // Checksum of external strings - // and common sizes. - DT_MIPS_IVERSION = 0x70000004, // Index of version string - // in string table. - DT_MIPS_FLAGS = 0x70000005, // 32 bits of flags. - DT_MIPS_BASE_ADDRESS = 0x70000006, // Base address of the segment. - DT_MIPS_MSYM = 0x70000007, // Address of .msym section. - DT_MIPS_CONFLICT = 0x70000008, // Address of .conflict section. - DT_MIPS_LIBLIST = 0x70000009, // Address of .liblist section. - DT_MIPS_LOCAL_GOTNO = 0x7000000a, // Number of local global offset - // table entries. - DT_MIPS_CONFLICTNO = 0x7000000b, // Number of entries - // in the .conflict section. - DT_MIPS_LIBLISTNO = 0x70000010, // Number of entries - // in the .liblist section. - DT_MIPS_SYMTABNO = 0x70000011, // Number of entries - // in the .dynsym section. - DT_MIPS_UNREFEXTNO = 0x70000012, // Index of first external dynamic symbol - // not referenced locally. - DT_MIPS_GOTSYM = 0x70000013, // Index of first dynamic symbol - // in global offset table. - DT_MIPS_HIPAGENO = 0x70000014, // Number of page table entries - // in global offset table. - DT_MIPS_RLD_MAP = 0x70000016, // Address of run time loader map, - // used for debugging. - DT_MIPS_DELTA_CLASS = 0x70000017, // Delta C++ class definition. - DT_MIPS_DELTA_CLASS_NO = 0x70000018, // Number of entries - // in DT_MIPS_DELTA_CLASS. - DT_MIPS_DELTA_INSTANCE = 0x70000019, // Delta C++ class instances. - DT_MIPS_DELTA_INSTANCE_NO = 0x7000001A, // Number of entries - // in DT_MIPS_DELTA_INSTANCE. - DT_MIPS_DELTA_RELOC = 0x7000001B, // Delta relocations. - DT_MIPS_DELTA_RELOC_NO = 0x7000001C, // Number of entries - // in DT_MIPS_DELTA_RELOC. - DT_MIPS_DELTA_SYM = 0x7000001D, // Delta symbols that Delta - // relocations refer to. - DT_MIPS_DELTA_SYM_NO = 0x7000001E, // Number of entries - // in DT_MIPS_DELTA_SYM. - DT_MIPS_DELTA_CLASSSYM = 0x70000020, // Delta symbols that hold - // class declarations. - DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021, // Number of entries - // in DT_MIPS_DELTA_CLASSSYM. - DT_MIPS_CXX_FLAGS = 0x70000022, // Flags indicating information - // about C++ flavor. - DT_MIPS_PIXIE_INIT = 0x70000023, // Pixie information. - DT_MIPS_SYMBOL_LIB = 0x70000024, // Address of .MIPS.symlib - DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025, // The GOT index of the first PTE - // for a segment - DT_MIPS_LOCAL_GOTIDX = 0x70000026, // The GOT index of the first PTE - // for a local symbol - DT_MIPS_HIDDEN_GOTIDX = 0x70000027, // The GOT index of the first PTE - // for a hidden symbol - DT_MIPS_PROTECTED_GOTIDX = 0x70000028, // The GOT index of the first PTE - // for a protected symbol - DT_MIPS_OPTIONS = 0x70000029, // Address of `.MIPS.options'. - DT_MIPS_INTERFACE = 0x7000002A, // Address of `.interface'. - DT_MIPS_DYNSTR_ALIGN = 0x7000002B, // Unknown. - DT_MIPS_INTERFACE_SIZE = 0x7000002C, // Size of the .interface section. - DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002D, // Size of rld_text_resolve - // function stored in the GOT. - DT_MIPS_PERF_SUFFIX = 0x7000002E, // Default suffix of DSO to be added - // by rld on dlopen() calls. - DT_MIPS_COMPACT_SIZE = 0x7000002F, // Size of compact relocation - // section (O32). - DT_MIPS_GP_VALUE = 0x70000030, // GP value for auxiliary GOTs. - DT_MIPS_AUX_DYNAMIC = 0x70000031, // Address of auxiliary .dynamic. - DT_MIPS_PLTGOT = 0x70000032, // Address of the base of the PLTGOT. - DT_MIPS_RWPLT = 0x70000034, // Points to the base - // of a writable PLT. - DT_MIPS_RLD_MAP_REL = 0x70000035, // Relative offset of run time loader - // map, used for debugging. - - // Sun machine-independent extensions. - DT_AUXILIARY = 0x7FFFFFFD, // Shared object to load before self - DT_FILTER = 0x7FFFFFFF // Shared object to get values from +#define DYNAMIC_TAG(name, value) DT_##name = value, +#include "DynamicTags.def" +#undef DYNAMIC_TAG }; // DT_FLAGS values. @@ -1380,6 +1303,20 @@ enum { NT_GNU_HWCAP = 2, NT_GNU_BUILD_ID = 3, NT_GNU_GOLD_VERSION = 4, + NT_GNU_PROPERTY_TYPE_0 = 5, +}; + +// Property types used in GNU_PROPERTY_TYPE_0 notes. +enum : unsigned { + GNU_PROPERTY_STACK_SIZE = 1, + GNU_PROPERTY_NO_COPY_ON_PROTECTED = 2, + GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002 +}; + +// CET properties +enum { + GNU_PROPERTY_X86_FEATURE_1_IBT = 1 << 0, + GNU_PROPERTY_X86_FEATURE_1_SHSTK = 1 << 1 }; // AMDGPU specific notes. @@ -1423,6 +1360,20 @@ struct Elf64_Chdr { Elf64_Xword ch_addralign; }; +// Node header for ELF32. +struct Elf32_Nhdr { + Elf32_Word n_namesz; + Elf32_Word n_descsz; + Elf32_Word n_type; +}; + +// Node header for ELF64. +struct Elf64_Nhdr { + Elf64_Word n_namesz; + Elf64_Word n_descsz; + Elf64_Word n_type; +}; + // Legal values for ch_type field of compressed section header. enum { ELFCOMPRESS_ZLIB = 1, // ZLIB/DEFLATE algorithm. diff --git a/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def b/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def index 3a47c5a07574..8c5b482f0511 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def +++ b/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def @@ -89,6 +89,13 @@ #undef R_PPC64_DTPREL16_HIGHESTA #undef R_PPC64_TLSGD #undef R_PPC64_TLSLD +#undef R_PPC64_ADDR16_HIGH +#undef R_PPC64_ADDR16_HIGHA +#undef R_PPC64_TPREL16_HIGH +#undef R_PPC64_TPREL16_HIGHA +#undef R_PPC64_DTPREL16_HIGH +#undef R_PPC64_DTPREL16_HIGHA +#undef R_PPC64_IRELATIVE #undef R_PPC64_REL16 #undef R_PPC64_REL16_LO #undef R_PPC64_REL16_HI @@ -175,6 +182,13 @@ ELF_RELOC(R_PPC64_DTPREL16_HIGHEST, 105) ELF_RELOC(R_PPC64_DTPREL16_HIGHESTA, 106) ELF_RELOC(R_PPC64_TLSGD, 107) ELF_RELOC(R_PPC64_TLSLD, 108) +ELF_RELOC(R_PPC64_ADDR16_HIGH, 110) +ELF_RELOC(R_PPC64_ADDR16_HIGHA, 111) +ELF_RELOC(R_PPC64_TPREL16_HIGH, 112) +ELF_RELOC(R_PPC64_TPREL16_HIGHA, 113) +ELF_RELOC(R_PPC64_DTPREL16_HIGH, 114) +ELF_RELOC(R_PPC64_DTPREL16_HIGHA, 115) +ELF_RELOC(R_PPC64_IRELATIVE, 248) ELF_RELOC(R_PPC64_REL16, 249) ELF_RELOC(R_PPC64_REL16_LO, 250) ELF_RELOC(R_PPC64_REL16_HI, 251) diff --git a/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/WebAssembly.def b/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/WebAssembly.def deleted file mode 100644 index 9a34349efb96..000000000000 --- a/contrib/llvm/include/llvm/BinaryFormat/ELFRelocs/WebAssembly.def +++ /dev/null @@ -1,8 +0,0 @@ - -#ifndef ELF_RELOC -#error "ELF_RELOC must be defined" -#endif - -ELF_RELOC(R_WEBASSEMBLY_NONE, 0) -ELF_RELOC(R_WEBASSEMBLY_DATA, 1) -ELF_RELOC(R_WEBASSEMBLY_FUNCTION, 2) diff --git a/contrib/llvm/include/llvm/BinaryFormat/MachO.h b/contrib/llvm/include/llvm/BinaryFormat/MachO.h index 060fbe162ad2..c5294c76ebf7 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/MachO.h +++ b/contrib/llvm/include/llvm/BinaryFormat/MachO.h @@ -1973,9 +1973,11 @@ const uint32_t PPC_THREAD_STATE_COUNT = // Define a union of all load command structs #define LOAD_COMMAND_STRUCT(LCStruct) LCStruct LCStruct##_data; -union macho_load_command { +LLVM_PACKED_START +union alignas(4) macho_load_command { #include "llvm/BinaryFormat/MachO.def" }; +LLVM_PACKED_END } // end namespace MachO } // end namespace llvm diff --git a/contrib/llvm/include/llvm/BinaryFormat/Magic.h b/contrib/llvm/include/llvm/BinaryFormat/Magic.h index c0e23db5e1ae..04801f810be3 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/Magic.h +++ b/contrib/llvm/include/llvm/BinaryFormat/Magic.h @@ -45,7 +45,8 @@ struct file_magic { coff_import_library, ///< COFF import library pecoff_executable, ///< PECOFF executable file windows_resource, ///< Windows compiled resource file (.res) - wasm_object ///< WebAssembly Object file + wasm_object, ///< WebAssembly Object file + pdb, ///< Windows PDB debug info file }; bool is_object() const { return V != unknown; } @@ -58,10 +59,10 @@ private: Impl V = unknown; }; -/// @brief Identify the type of a binary file based on how magical it is. +/// Identify the type of a binary file based on how magical it is. file_magic identify_magic(StringRef magic); -/// @brief Get and identify \a path's type based on its content. +/// Get and identify \a path's type based on its content. /// /// @param path Input path. /// @param result Set to the type of file, or file_magic::unknown. diff --git a/contrib/llvm/include/llvm/BinaryFormat/Wasm.h b/contrib/llvm/include/llvm/BinaryFormat/Wasm.h index 57a0b441821b..fa5448dacec4 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/contrib/llvm/include/llvm/BinaryFormat/Wasm.h @@ -24,6 +24,8 @@ namespace wasm { const char WasmMagic[] = {'\0', 'a', 's', 'm'}; // Wasm binary format version const uint32_t WasmVersion = 0x1; +// Wasm linking metadata version +const uint32_t WasmMetadataVersion = 0x1; // Wasm uses a 64k page size const uint32_t WasmPageSize = 65536; @@ -33,24 +35,24 @@ struct WasmObjectHeader { }; struct WasmSignature { - std::vector<int32_t> ParamTypes; - int32_t ReturnType; + std::vector<uint8_t> ParamTypes; + uint8_t ReturnType; }; struct WasmExport { StringRef Name; - uint32_t Kind; + uint8_t Kind; uint32_t Index; }; struct WasmLimits { - uint32_t Flags; + uint8_t Flags; uint32_t Initial; uint32_t Maximum; }; struct WasmTable { - int32_t ElemType; + uint8_t ElemType; WasmLimits Limits; }; @@ -65,43 +67,55 @@ struct WasmInitExpr { } Value; }; -struct WasmGlobal { - int32_t Type; +struct WasmGlobalType { + uint8_t Type; bool Mutable; +}; + +struct WasmGlobal { + uint32_t Index; + WasmGlobalType Type; WasmInitExpr InitExpr; + StringRef SymbolName; // from the "linking" section }; struct WasmImport { StringRef Module; StringRef Field; - uint32_t Kind; + uint8_t Kind; union { uint32_t SigIndex; - WasmGlobal Global; + WasmGlobalType Global; WasmTable Table; WasmLimits Memory; }; }; struct WasmLocalDecl { - int32_t Type; + uint8_t Type; uint32_t Count; }; struct WasmFunction { + uint32_t Index; std::vector<WasmLocalDecl> Locals; ArrayRef<uint8_t> Body; uint32_t CodeSectionOffset; uint32_t Size; + uint32_t CodeOffset; // start of Locals and Body + StringRef SymbolName; // from the "linking" section + StringRef DebugName; // from the "name" section + uint32_t Comdat; // from the "comdat info" section }; struct WasmDataSegment { uint32_t MemoryIndex; WasmInitExpr Offset; ArrayRef<uint8_t> Content; - StringRef Name; + StringRef Name; // from the "segment info" section uint32_t Alignment; uint32_t Flags; + uint32_t Comdat; // from the "comdat info" section }; struct WasmElemSegment { @@ -110,21 +124,50 @@ struct WasmElemSegment { std::vector<uint32_t> Functions; }; +// Represents the location of a Wasm data symbol within a WasmDataSegment, as +// the index of the segment, and the offset and size within the segment. +struct WasmDataReference { + uint32_t Segment; + uint32_t Offset; + uint32_t Size; +}; + struct WasmRelocation { - uint32_t Type; // The type of the relocation. - uint32_t Index; // Index into function to global index space. + uint8_t Type; // The type of the relocation. + uint32_t Index; // Index into either symbol or type index space. uint64_t Offset; // Offset from the start of the section. int64_t Addend; // A value to add to the symbol. }; struct WasmInitFunc { uint32_t Priority; - uint32_t FunctionIndex; + uint32_t Symbol; +}; + +struct WasmSymbolInfo { + StringRef Name; + uint8_t Kind; + uint32_t Flags; + StringRef Module; // For undefined symbols the module name of the import + union { + // For function or global symbols, the index in function or global index + // space. + uint32_t ElementIndex; + // For a data symbols, the address of the data relative to segment. + WasmDataReference DataRef; + }; +}; + +struct WasmFunctionName { + uint32_t Index; + StringRef Name; }; struct WasmLinkingData { - uint32_t DataSize; + uint32_t Version; std::vector<WasmInitFunc> InitFunctions; + std::vector<StringRef> Comdats; + std::vector<WasmSymbolInfo> SymbolTable; }; enum : unsigned { @@ -143,14 +186,15 @@ enum : unsigned { }; // Type immediate encodings used in various contexts. -enum { - WASM_TYPE_I32 = -0x01, - WASM_TYPE_I64 = -0x02, - WASM_TYPE_F32 = -0x03, - WASM_TYPE_F64 = -0x04, - WASM_TYPE_ANYFUNC = -0x10, - WASM_TYPE_FUNC = -0x20, - WASM_TYPE_NORESULT = -0x40, // for blocks with no result values +enum : unsigned { + WASM_TYPE_I32 = 0x7F, + WASM_TYPE_I64 = 0x7E, + WASM_TYPE_F32 = 0x7D, + WASM_TYPE_F64 = 0x7C, + WASM_TYPE_ANYFUNC = 0x70, + WASM_TYPE_EXCEPT_REF = 0x68, + WASM_TYPE_FUNC = 0x60, + WASM_TYPE_NORESULT = 0x40, // for blocks with no result values }; // Kinds of externals (for imports and exports). @@ -172,11 +216,6 @@ enum : unsigned { }; enum : unsigned { - WASM_NAMES_FUNCTION = 0x1, - WASM_NAMES_LOCAL = 0x2, -}; - -enum : unsigned { WASM_LIMITS_FLAG_HAS_MAX = 0x1, }; @@ -186,24 +225,46 @@ enum class ValType { I64 = WASM_TYPE_I64, F32 = WASM_TYPE_F32, F64 = WASM_TYPE_F64, + EXCEPT_REF = WASM_TYPE_EXCEPT_REF, +}; + +// Kind codes used in the custom "name" section +enum : unsigned { + WASM_NAMES_FUNCTION = 0x1, + WASM_NAMES_LOCAL = 0x2, }; -// Linking metadata kinds. +// Kind codes used in the custom "linking" section enum : unsigned { - WASM_SYMBOL_INFO = 0x2, - WASM_DATA_SIZE = 0x3, WASM_SEGMENT_INFO = 0x5, WASM_INIT_FUNCS = 0x6, + WASM_COMDAT_INFO = 0x7, + WASM_SYMBOL_TABLE = 0x8, +}; + +// Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO +enum : unsigned { + WASM_COMDAT_DATA = 0x0, + WASM_COMDAT_FUNCTION = 0x1, +}; + +// Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE +enum WasmSymbolType : unsigned { + WASM_SYMBOL_TYPE_FUNCTION = 0x0, + WASM_SYMBOL_TYPE_DATA = 0x1, + WASM_SYMBOL_TYPE_GLOBAL = 0x2, + WASM_SYMBOL_TYPE_SECTION = 0x3, }; const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; -const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0x4; +const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc; const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0; const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1; const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; +const unsigned WASM_SYMBOL_UNDEFINED = 0x10; #define WASM_RELOC(name, value) name = value, @@ -213,18 +274,25 @@ enum : unsigned { #undef WASM_RELOC -struct Global { - ValType Type; - bool Mutable; +// Useful comparison operators +inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) { + return LHS.ReturnType == RHS.ReturnType && LHS.ParamTypes == RHS.ParamTypes; +} - // The initial value for this global is either the value of an imported - // global, in which case InitialModule and InitialName specify the global - // import, or a value, in which case InitialModule is empty and InitialValue - // holds the value. - StringRef InitialModule; - StringRef InitialName; - uint64_t InitialValue; -}; +inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) { + return !(LHS == RHS); +} + +inline bool operator==(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { + return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable; +} + +inline bool operator!=(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { + return !(LHS == RHS); +} + +std::string toString(wasm::WasmSymbolType type); +std::string relocTypetoString(uint32_t type); } // end namespace wasm } // end namespace llvm diff --git a/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def b/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def index d6f0e42b33bf..8ffd51e483f3 100644 --- a/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def +++ b/contrib/llvm/include/llvm/BinaryFormat/WasmRelocs.def @@ -11,3 +11,5 @@ WASM_RELOC(R_WEBASSEMBLY_MEMORY_ADDR_SLEB, 4) WASM_RELOC(R_WEBASSEMBLY_MEMORY_ADDR_I32, 5) WASM_RELOC(R_WEBASSEMBLY_TYPE_INDEX_LEB, 6) WASM_RELOC(R_WEBASSEMBLY_GLOBAL_INDEX_LEB, 7) +WASM_RELOC(R_WEBASSEMBLY_FUNCTION_OFFSET_I32, 8) +WASM_RELOC(R_WEBASSEMBLY_SECTION_OFFSET_I32, 9) diff --git a/contrib/llvm/include/llvm/Bitcode/BitcodeWriter.h b/contrib/llvm/include/llvm/Bitcode/BitcodeWriter.h index c78077525c8b..0010cf6c0544 100644 --- a/contrib/llvm/include/llvm/Bitcode/BitcodeWriter.h +++ b/contrib/llvm/include/llvm/Bitcode/BitcodeWriter.h @@ -86,7 +86,7 @@ class raw_ostream; /// Can be used to produce the same module hash for a minimized bitcode /// used just for the thin link as in the regular full bitcode that will /// be used in the backend. - void writeModule(const Module *M, bool ShouldPreserveUseListOrder = false, + void writeModule(const Module &M, bool ShouldPreserveUseListOrder = false, const ModuleSummaryIndex *Index = nullptr, bool GenerateHash = false, ModuleHash *ModHash = nullptr); @@ -97,7 +97,7 @@ class raw_ostream; /// /// ModHash is for use in ThinLTO incremental build, generated while the /// IR bitcode file writing. - void writeThinLinkBitcode(const Module *M, const ModuleSummaryIndex &Index, + void writeThinLinkBitcode(const Module &M, const ModuleSummaryIndex &Index, const ModuleHash &ModHash); void writeIndex( @@ -105,7 +105,7 @@ class raw_ostream; const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex); }; - /// \brief Write the specified module to the specified raw output stream. + /// Write the specified module to the specified raw output stream. /// /// For streams where it matters, the given stream should be in "binary" /// mode. @@ -126,7 +126,7 @@ class raw_ostream; /// Can be used to produce the same module hash for a minimized bitcode /// used just for the thin link as in the regular full bitcode that will /// be used in the backend. - void WriteBitcodeToFile(const Module *M, raw_ostream &Out, + void WriteBitcodeToFile(const Module &M, raw_ostream &Out, bool ShouldPreserveUseListOrder = false, const ModuleSummaryIndex *Index = nullptr, bool GenerateHash = false, @@ -139,7 +139,7 @@ class raw_ostream; /// /// ModHash is for use in ThinLTO incremental build, generated while the IR /// bitcode file writing. - void WriteThinLinkBitcodeToFile(const Module *M, raw_ostream &Out, + void WriteThinLinkBitcodeToFile(const Module &M, raw_ostream &Out, const ModuleSummaryIndex &Index, const ModuleHash &ModHash); diff --git a/contrib/llvm/include/llvm/Bitcode/BitcodeWriterPass.h b/contrib/llvm/include/llvm/Bitcode/BitcodeWriterPass.h index 9ac6fba16b96..05044c9ae11c 100644 --- a/contrib/llvm/include/llvm/Bitcode/BitcodeWriterPass.h +++ b/contrib/llvm/include/llvm/Bitcode/BitcodeWriterPass.h @@ -21,9 +21,10 @@ namespace llvm { class Module; class ModulePass; +class Pass; class raw_ostream; -/// \brief Create and return a pass that writes the module to the specified +/// 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. /// @@ -40,7 +41,10 @@ ModulePass *createBitcodeWriterPass(raw_ostream &Str, bool EmitSummaryIndex = false, bool EmitModuleHash = false); -/// \brief Pass for writing a module of IR out to a bitcode file. +/// Check whether a pass is a BitcodeWriterPass. +bool isBitcodeWriterPass(Pass *P); + +/// 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. @@ -51,7 +55,7 @@ class BitcodeWriterPass : public PassInfoMixin<BitcodeWriterPass> { bool EmitModuleHash; public: - /// \brief Construct a bitcode writer pass around a particular output stream. + /// Construct a bitcode writer pass around a particular output stream. /// /// If \c ShouldPreserveUseListOrder, encode use-list order so it can be /// reproduced when deserialized. @@ -65,7 +69,7 @@ public: : OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder), EmitSummaryIndex(EmitSummaryIndex), EmitModuleHash(EmitModuleHash) {} - /// \brief Run the bitcode writer pass, and output the module to the selected + /// Run the bitcode writer pass, and output the module to the selected /// output stream. PreservedAnalyses run(Module &M, ModuleAnalysisManager &); }; diff --git a/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h b/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h index b484fa2efbfb..72e7619d9e1c 100644 --- a/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h +++ b/contrib/llvm/include/llvm/Bitcode/BitstreamReader.h @@ -429,7 +429,7 @@ public: // don't care what code widths are used inside of it. ReadVBR(bitc::CodeLenWidth); SkipToFourByteBoundary(); - unsigned NumFourBytes = Read(bitc::BlockSizeWidth); + size_t NumFourBytes = Read(bitc::BlockSizeWidth); // Check that the block wasn't partially defined, and that the offset isn't // bogus. diff --git a/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h b/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h index e276db5f92f6..c854769e0622 100644 --- a/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h +++ b/contrib/llvm/include/llvm/Bitcode/BitstreamWriter.h @@ -90,10 +90,10 @@ public: assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); } - /// \brief Retrieve the current position in the stream, in bits. + /// Retrieve the current position in the stream, in bits. uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; } - /// \brief Retrieve the number of bits currently used to encode an abbrev ID. + /// Retrieve the number of bits currently used to encode an abbrev ID. unsigned GetAbbrevIDWidth() const { return CurCodeSize; } //===--------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 01419d7ae2bf..6723cf42dd2c 100644 --- a/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/contrib/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -256,6 +256,18 @@ enum GlobalValueSummarySymtabCodes { // strings in strtab. // [n * name] FS_CFI_FUNCTION_DECLS = 18, + // Per-module summary that also adds relative block frequency to callee info. + // PERMODULE_RELBF: [valueid, flags, instcount, numrefs, + // numrefs x valueid, + // n x (valueid, relblockfreq)] + FS_PERMODULE_RELBF = 19, + // Index-wide flags + FS_FLAGS = 20, + // Maps type identifier to summary information for that type identifier. + // TYPE_ID: [typeid, kind, bitwidth, align, size, bitmask, inlinebits, + // n x (typeid, kind, name, numrba, + // numrba x (numarg, numarg x arg, kind, info, byte, bit))] + FS_TYPE_ID = 21, }; enum MetadataCodes { @@ -272,7 +284,7 @@ enum MetadataCodes { METADATA_ATTACHMENT = 11, // [m x [value, [n x [id, mdnode]]] METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num] METADATA_SUBRANGE = 13, // [distinct, count, lo] - METADATA_ENUMERATOR = 14, // [distinct, value, name] + METADATA_ENUMERATOR = 14, // [isUnsigned|distinct, value, name] METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc] METADATA_FILE = 16, // [distinct, filename, directory, checksumkind, checksum] METADATA_DERIVED_TYPE = 17, // [distinct, ...] @@ -298,6 +310,7 @@ enum MetadataCodes { METADATA_GLOBAL_VAR_EXPR = 37, // [distinct, var, expr] METADATA_INDEX_OFFSET = 38, // [offset] METADATA_INDEX = 39, // [bitpos] + METADATA_LABEL = 40, // [distinct, scope, name, file, line] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each @@ -575,6 +588,9 @@ enum AttributeKindCodes { ATTR_KIND_SPECULATABLE = 53, ATTR_KIND_STRICT_FP = 54, ATTR_KIND_SANITIZE_HWADDRESS = 55, + ATTR_KIND_NOCF_CHECK = 56, + ATTR_KIND_OPT_FOR_FUZZING = 57, + ATTR_KIND_SHADOWCALLSTACK = 58, }; enum ComdatSelectionKindCodes { diff --git a/contrib/llvm/include/llvm/CodeGen/AccelTable.h b/contrib/llvm/include/llvm/CodeGen/AccelTable.h new file mode 100644 index 000000000000..13928582f2dd --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/AccelTable.h @@ -0,0 +1,434 @@ +//==- include/llvm/CodeGen/AccelTable.h - Accelerator Tables -----*- 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 accelerator tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_DWARFACCELTABLE_H +#define LLVM_CODEGEN_DWARFACCELTABLE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/CodeGen/DIE.h" +#include "llvm/CodeGen/DwarfStringPoolEntry.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/DJB.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include <cstddef> +#include <cstdint> +#include <vector> + +/// The DWARF and Apple accelerator tables are an indirect hash table optimized +/// for null lookup rather than access to known data. The Apple accelerator +/// tables are a precursor of the newer DWARF v5 accelerator tables. Both +/// formats share common design ideas. +/// +/// The Apple accelerator table are output into an on-disk format that looks +/// like this: +/// +/// .------------------. +/// | HEADER | +/// |------------------| +/// | BUCKETS | +/// |------------------| +/// | HASHES | +/// |------------------| +/// | OFFSETS | +/// |------------------| +/// | DATA | +/// `------------------' +/// +/// The header contains a magic number, version, type of hash function, +/// the number of buckets, total number of hashes, and room for a special struct +/// of data and the length of that struct. +/// +/// The buckets contain an index (e.g. 6) into the hashes array. The hashes +/// section contains all of the 32-bit hash values in contiguous memory, and the +/// offsets contain the offset into the data area for the particular hash. +/// +/// For a lookup example, we could hash a function name and take it modulo the +/// number of buckets giving us our bucket. From there we take the bucket value +/// as an index into the hashes table and look at each successive hash as long +/// as the hash value is still the same modulo result (bucket value) as earlier. +/// If we have a match we look at that same entry in the offsets table and grab +/// the offset in the data for our final match. +/// +/// The DWARF v5 accelerator table consists of zero or more name indices that +/// are output into an on-disk format that looks like this: +/// +/// .------------------. +/// | HEADER | +/// |------------------| +/// | CU LIST | +/// |------------------| +/// | LOCAL TU LIST | +/// |------------------| +/// | FOREIGN TU LIST | +/// |------------------| +/// | HASH TABLE | +/// |------------------| +/// | NAME TABLE | +/// |------------------| +/// | ABBREV TABLE | +/// |------------------| +/// | ENTRY POOL | +/// `------------------' +/// +/// For the full documentation please refer to the DWARF 5 standard. +/// +/// +/// This file defines the class template AccelTable, which is represents an +/// abstract view of an Accelerator table, without any notion of an on-disk +/// layout. This class is parameterized by an entry type, which should derive +/// from AccelTableData. This is the type of individual entries in the table, +/// and it should store the data necessary to emit them. AppleAccelTableData is +/// the base class for Apple Accelerator Table entries, which have a uniform +/// structure based on a sequence of Atoms. There are different sub-classes +/// derived from AppleAccelTable, which differ in the set of Atoms and how they +/// obtain their values. +/// +/// An Apple Accelerator Table can be serialized by calling emitAppleAccelTable +/// function. +/// +/// TODO: Add DWARF v5 emission code. + +namespace llvm { + +class AsmPrinter; +class DwarfCompileUnit; +class DwarfDebug; + +/// Interface which the different types of accelerator table data have to +/// conform. It serves as a base class for different values of the template +/// argument of the AccelTable class template. +class AccelTableData { +public: + virtual ~AccelTableData() = default; + + bool operator<(const AccelTableData &Other) const { + return order() < Other.order(); + } + + // Subclasses should implement: + // static uint32_t hash(StringRef Name); + +#ifndef NDEBUG + virtual void print(raw_ostream &OS) const = 0; +#endif +protected: + virtual uint64_t order() const = 0; +}; + +/// A base class holding non-template-dependant functionality of the AccelTable +/// class. Clients should not use this class directly but rather instantiate +/// AccelTable with a type derived from AccelTableData. +class AccelTableBase { +public: + using HashFn = uint32_t(StringRef); + + /// Represents a group of entries with identical name (and hence, hash value). + struct HashData { + DwarfStringPoolEntryRef Name; + uint32_t HashValue; + std::vector<AccelTableData *> Values; + MCSymbol *Sym; + + HashData(DwarfStringPoolEntryRef Name, HashFn *Hash) + : Name(Name), HashValue(Hash(Name.getString())) {} + +#ifndef NDEBUG + void print(raw_ostream &OS) const; + void dump() const { print(dbgs()); } +#endif + }; + using HashList = std::vector<HashData *>; + using BucketList = std::vector<HashList>; + +protected: + /// Allocator for HashData and Values. + BumpPtrAllocator Allocator; + + using StringEntries = StringMap<HashData, BumpPtrAllocator &>; + StringEntries Entries; + + HashFn *Hash; + uint32_t BucketCount; + uint32_t UniqueHashCount; + + HashList Hashes; + BucketList Buckets; + + void computeBucketCount(); + + AccelTableBase(HashFn *Hash) : Entries(Allocator), Hash(Hash) {} + +public: + void finalize(AsmPrinter *Asm, StringRef Prefix); + ArrayRef<HashList> getBuckets() const { return Buckets; } + uint32_t getBucketCount() const { return BucketCount; } + uint32_t getUniqueHashCount() const { return UniqueHashCount; } + uint32_t getUniqueNameCount() const { return Entries.size(); } + +#ifndef NDEBUG + void print(raw_ostream &OS) const; + void dump() const { print(dbgs()); } +#endif + + AccelTableBase(const AccelTableBase &) = delete; + void operator=(const AccelTableBase &) = delete; +}; + +/// This class holds an abstract representation of an Accelerator Table, +/// consisting of a sequence of buckets, each bucket containint a sequence of +/// HashData entries. The class is parameterized by the type of entries it +/// holds. The type template parameter also defines the hash function to use for +/// hashing names. +template <typename DataT> class AccelTable : public AccelTableBase { +public: + AccelTable() : AccelTableBase(DataT::hash) {} + + template <typename... Types> + void addName(DwarfStringPoolEntryRef Name, Types &&... Args); +}; + +template <typename AccelTableDataT> +template <typename... Types> +void AccelTable<AccelTableDataT>::addName(DwarfStringPoolEntryRef Name, + Types &&... Args) { + assert(Buckets.empty() && "Already finalized!"); + // If the string is in the list already then add this die to the list + // otherwise add a new one. + auto Iter = Entries.try_emplace(Name.getString(), Name, Hash).first; + assert(Iter->second.Name == Name); + Iter->second.Values.push_back( + new (Allocator) AccelTableDataT(std::forward<Types>(Args)...)); +} + +/// A base class for different implementations of Data classes for Apple +/// Accelerator Tables. The columns in the table are defined by the static Atoms +/// variable defined on the subclasses. +class AppleAccelTableData : public AccelTableData { +public: + /// An Atom defines the form of the data in an Apple accelerator table. + /// Conceptually it is a column in the accelerator consisting of a type and a + /// specification of the form of its data. + struct Atom { + /// Atom Type. + const uint16_t Type; + /// DWARF Form. + const uint16_t Form; + + constexpr Atom(uint16_t Type, uint16_t Form) : Type(Type), Form(Form) {} + +#ifndef NDEBUG + void print(raw_ostream &OS) const; + void dump() const { print(dbgs()); } +#endif + }; + // Subclasses should define: + // static constexpr Atom Atoms[]; + + virtual void emit(AsmPrinter *Asm) const = 0; + + static uint32_t hash(StringRef Buffer) { return djbHash(Buffer); } +}; + +/// The Data class implementation for DWARF v5 accelerator table. Unlike the +/// Apple Data classes, this class is just a DIE wrapper, and does not know to +/// serialize itself. The complete serialization logic is in the +/// emitDWARF5AccelTable function. +class DWARF5AccelTableData : public AccelTableData { +public: + static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); } + + DWARF5AccelTableData(const DIE &Die) : Die(Die) {} + +#ifndef NDEBUG + void print(raw_ostream &OS) const override; +#endif + + const DIE &getDie() const { return Die; } + uint64_t getDieOffset() const { return Die.getOffset(); } + unsigned getDieTag() const { return Die.getTag(); } + +protected: + const DIE &Die; + + uint64_t order() const override { return Die.getOffset(); } +}; + +class DWARF5AccelTableStaticData : public AccelTableData { +public: + static uint32_t hash(StringRef Name) { return caseFoldingDjbHash(Name); } + + DWARF5AccelTableStaticData(uint64_t DieOffset, unsigned DieTag, + unsigned CUIndex) + : DieOffset(DieOffset), DieTag(DieTag), CUIndex(CUIndex) {} + +#ifndef NDEBUG + void print(raw_ostream &OS) const override; +#endif + + uint64_t getDieOffset() const { return DieOffset; } + unsigned getDieTag() const { return DieTag; } + unsigned getCUIndex() const { return CUIndex; } + +protected: + uint64_t DieOffset; + unsigned DieTag; + unsigned CUIndex; + + uint64_t order() const override { return DieOffset; } +}; + +void emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents, + StringRef Prefix, const MCSymbol *SecBegin, + ArrayRef<AppleAccelTableData::Atom> Atoms); + +/// Emit an Apple Accelerator Table consisting of entries in the specified +/// AccelTable. The DataT template parameter should be derived from +/// AppleAccelTableData. +template <typename DataT> +void emitAppleAccelTable(AsmPrinter *Asm, AccelTable<DataT> &Contents, + StringRef Prefix, const MCSymbol *SecBegin) { + static_assert(std::is_convertible<DataT *, AppleAccelTableData *>::value, ""); + emitAppleAccelTableImpl(Asm, Contents, Prefix, SecBegin, DataT::Atoms); +} + +void emitDWARF5AccelTable(AsmPrinter *Asm, + AccelTable<DWARF5AccelTableData> &Contents, + const DwarfDebug &DD, + ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs); + +void emitDWARF5AccelTable( + AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents, + ArrayRef<MCSymbol *> CUs, + llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)> + getCUIndexForEntry); + +/// Accelerator table data implementation for simple Apple accelerator tables +/// with just a DIE reference. +class AppleAccelTableOffsetData : public AppleAccelTableData { +public: + AppleAccelTableOffsetData(const DIE &D) : Die(D) {} + + void emit(AsmPrinter *Asm) const override; + +#ifndef _MSC_VER + // The line below is rejected by older versions (TBD) of MSVC. + static constexpr Atom Atoms[] = { + Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; +#else + // FIXME: Erase this path once the minimum MSCV version has been bumped. + static const SmallVector<Atom, 4> Atoms; +#endif + +#ifndef NDEBUG + void print(raw_ostream &OS) const override; +#endif +protected: + uint64_t order() const override { return Die.getOffset(); } + + const DIE &Die; +}; + +/// Accelerator table data implementation for Apple type accelerator tables. +class AppleAccelTableTypeData : public AppleAccelTableOffsetData { +public: + AppleAccelTableTypeData(const DIE &D) : AppleAccelTableOffsetData(D) {} + + void emit(AsmPrinter *Asm) const override; + +#ifndef _MSC_VER + // The line below is rejected by older versions (TBD) of MSVC. + static constexpr Atom Atoms[] = { + Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), + Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), + Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; +#else + // FIXME: Erase this path once the minimum MSCV version has been bumped. + static const SmallVector<Atom, 4> Atoms; +#endif + +#ifndef NDEBUG + void print(raw_ostream &OS) const override; +#endif +}; + +/// Accelerator table data implementation for simple Apple accelerator tables +/// with a DIE offset but no actual DIE pointer. +class AppleAccelTableStaticOffsetData : public AppleAccelTableData { +public: + AppleAccelTableStaticOffsetData(uint32_t Offset) : Offset(Offset) {} + + void emit(AsmPrinter *Asm) const override; + +#ifndef _MSC_VER + // The line below is rejected by older versions (TBD) of MSVC. + static constexpr Atom Atoms[] = { + Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)}; +#else + // FIXME: Erase this path once the minimum MSCV version has been bumped. + static const SmallVector<Atom, 4> Atoms; +#endif + +#ifndef NDEBUG + void print(raw_ostream &OS) const override; +#endif +protected: + uint64_t order() const override { return Offset; } + + uint32_t Offset; +}; + +/// Accelerator table data implementation for type accelerator tables with +/// a DIE offset but no actual DIE pointer. +class AppleAccelTableStaticTypeData : public AppleAccelTableStaticOffsetData { +public: + AppleAccelTableStaticTypeData(uint32_t Offset, uint16_t Tag, + bool ObjCClassIsImplementation, + uint32_t QualifiedNameHash) + : AppleAccelTableStaticOffsetData(Offset), + QualifiedNameHash(QualifiedNameHash), Tag(Tag), + ObjCClassIsImplementation(ObjCClassIsImplementation) {} + + void emit(AsmPrinter *Asm) const override; + +#ifndef _MSC_VER + // The line below is rejected by older versions (TBD) of MSVC. + static constexpr Atom Atoms[] = { + Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), + Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), + Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)}; +#else + // FIXME: Erase this path once the minimum MSCV version has been bumped. + static const SmallVector<Atom, 4> Atoms; +#endif + +#ifndef NDEBUG + void print(raw_ostream &OS) const override; +#endif +protected: + uint64_t order() const override { return Offset; } + + uint32_t QualifiedNameHash; + uint16_t Tag; + bool ObjCClassIsImplementation; +}; + +} // end namespace llvm + +#endif // LLVM_CODEGEN_DWARFACCELTABLE_H diff --git a/contrib/llvm/include/llvm/CodeGen/Analysis.h b/contrib/llvm/include/llvm/CodeGen/Analysis.h index ba88f1f78fb8..d77aee66ed76 100644 --- a/contrib/llvm/include/llvm/CodeGen/Analysis.h +++ b/contrib/llvm/include/llvm/CodeGen/Analysis.h @@ -36,7 +36,7 @@ class SDValue; class SelectionDAG; struct EVT; -/// \brief Compute the linearized index of a member in a nested +/// Compute the linearized index of a member in a nested /// aggregate/struct/array. /// /// Given an LLVM IR aggregate type and a sequence of insertvalue or @@ -124,7 +124,7 @@ bool returnTypeIsEligibleForTailCall(const Function *F, const Instruction *I, const TargetLoweringBase &TLI); DenseMap<const MachineBasicBlock *, int> -getFuncletMembership(const MachineFunction &MF); +getEHScopeMembership(const MachineFunction &MF); } // End llvm namespace diff --git a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h index b8944a668000..b6056380916c 100644 --- a/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/contrib/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -50,6 +50,7 @@ class GlobalValue; class GlobalVariable; class MachineBasicBlock; class MachineConstantPoolValue; +class MachineDominatorTree; class MachineFunction; class MachineInstr; class MachineJumpTableInfo; @@ -92,11 +93,17 @@ public: std::unique_ptr<MCStreamer> OutStreamer; /// The current machine function. - const MachineFunction *MF = nullptr; + MachineFunction *MF = nullptr; /// This is a pointer to the current MachineModuleInfo. MachineModuleInfo *MMI = nullptr; + /// This is a pointer to the current MachineLoopInfo. + MachineDominatorTree *MDT = nullptr; + + /// This is a pointer to the current MachineLoopInfo. + MachineLoopInfo *MLI = nullptr; + /// Optimization remark emitter. MachineOptimizationRemarkEmitter *ORE; @@ -130,9 +137,6 @@ private: static char ID; - /// If VerboseAsm is set, a pointer to the loop info for this function. - MachineLoopInfo *LI = nullptr; - struct HandlerInfo { AsmPrinterHandler *Handler; const char *TimerName; @@ -161,6 +165,12 @@ public: }; private: + /// If generated on the fly this own the instance. + std::unique_ptr<MachineDominatorTree> OwnedMDT; + + /// If generated on the fly this own the instance. + std::unique_ptr<MachineLoopInfo> OwnedMLI; + /// Structure for generating diagnostics for inline assembly. Only initialised /// when necessary. mutable std::unique_ptr<SrcMgrDiagInfo> DiagInfo; @@ -191,6 +201,10 @@ public: /// Return a unique ID for the current function. unsigned getFunctionNumber() const; + /// Return symbol for the function pseudo stack if the stack frame is not a + /// register based. + virtual const MCSymbol *getFunctionFrameSymbol() const { return nullptr; } + MCSymbol *getFunctionBegin() const { return CurrentFnBegin; } MCSymbol *getFunctionEnd() const { return CurrentFnEnd; } MCSymbol *getCurExceptionSym(); @@ -228,6 +242,7 @@ public: TAIL_CALL = 2, LOG_ARGS_ENTER = 3, CUSTOM_EVENT = 4, + TYPED_EVENT = 5, }; // The table will contain these structs that point to the sled, the function @@ -327,15 +342,15 @@ public: /// global value is specified, and if that global has an explicit alignment /// requested, it will override the alignment request if required for /// correctness. - void EmitAlignment(unsigned NumBits, const GlobalObject *GO = nullptr) const; + void EmitAlignment(unsigned NumBits, const GlobalObject *GV = nullptr) const; /// Lower the specified LLVM Constant to an MCExpr. virtual const MCExpr *lowerConstant(const Constant *CV); - /// \brief Print a general LLVM constant to the .s file. + /// Print a general LLVM constant to the .s file. void EmitGlobalConstant(const DataLayout &DL, const Constant *CV); - /// \brief Unnamed constant global variables solely contaning a pointer to + /// Unnamed constant global variables solely contaning a pointer to /// another globals variable act like a global variable "proxy", or GOT /// equivalents, i.e., it's only used to hold the address of the latter. One /// optimization is to replace accesses to these proxies by using the GOT @@ -345,7 +360,7 @@ public: /// accesses to GOT entries. void computeGlobalGOTEquivs(Module &M); - /// \brief Constant expressions using GOT equivalent globals may not be + /// Constant expressions using GOT equivalent globals may not be /// eligible for PC relative GOT entry conversion, in such cases we need to /// emit the proxies we previously omitted in EmitGlobalVariable. void emitGlobalGOTEquivs(); @@ -444,13 +459,16 @@ public: void printOffset(int64_t Offset, raw_ostream &OS) const; /// Emit a byte directive and value. - void EmitInt8(int Value) const; + void emitInt8(int Value) const; /// Emit a short directive and value. - void EmitInt16(int Value) const; + void emitInt16(int Value) const; /// Emit a long directive and value. - void EmitInt32(int Value) const; + void emitInt32(int Value) const; + + /// Emit a long long directive and value. + void emitInt64(uint64_t Value) const; /// Emit something like ".long Hi-Lo" where the size in bytes of the directive /// is specified by Size and Hi/Lo specify the labels. This implicitly uses @@ -458,6 +476,10 @@ public: void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) const; + /// Emit something like ".uleb128 Hi-Lo". + void EmitLabelDifferenceAsULEB128(const MCSymbol *Hi, + const MCSymbol *Lo) const; + /// Emit something like ".long Label+Offset" where the size in bytes of the /// directive is specified by Size and Label specifies the label. This /// implicitly uses .set if it is available. @@ -471,6 +493,9 @@ public: EmitLabelPlusOffset(Label, 0, Size, IsSectionRelative); } + /// Emit something like ".long Label + Offset". + void EmitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const; + //===------------------------------------------------------------------===// // Dwarf Emission Helper Routines //===------------------------------------------------------------------===// @@ -481,11 +506,6 @@ public: /// Emit the specified unsigned leb128 value. void EmitULEB128(uint64_t Value, const char *Desc = nullptr) const; - /// Emit the specified unsigned leb128 value padded to a specific number - /// bytes - void EmitPaddedULEB128(uint64_t Value, unsigned PadTo, - const char *Desc = nullptr) const; - /// Emit a .byte 42 directive that corresponds to an encoding. If verbose /// assembly output is enabled, we output comments describing the encoding. /// Desc is a string saying what the encoding is specifying (e.g. "LSDA"). @@ -508,7 +528,12 @@ public: /// When possible, emit a DwarfStringPool section offset without any /// relocations, and without using the symbol. Otherwise, defers to \a /// emitDwarfSymbolReference(). - void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const; + void emitDwarfStringOffset(DwarfStringPoolEntry S) const; + + /// Emit the 4-byte offset of a string from the start of its section. + void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const { + emitDwarfStringOffset(S.getEntry()); + } /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. virtual unsigned getISAEncoding() { return 0; } @@ -523,10 +548,10 @@ public: // Dwarf Lowering Routines //===------------------------------------------------------------------===// - /// \brief Emit frame instruction to describe the layout of the frame. + /// Emit frame instruction to describe the layout of the frame. void emitCFIInstruction(const MCCFIInstruction &Inst) const; - /// \brief Emit Dwarf abbreviation table. + /// Emit Dwarf abbreviation table. template <typename T> void emitDwarfAbbrevs(const T &Abbrevs) const { // For each abbreviation. for (const auto &Abbrev : Abbrevs) @@ -538,7 +563,7 @@ public: void emitDwarfAbbrev(const DIEAbbrev &Abbrev) const; - /// \brief Recursively emit Dwarf DIE tree. + /// Recursively emit Dwarf DIE tree. void emitDwarfDIE(const DIE &Die) const; //===------------------------------------------------------------------===// @@ -625,10 +650,9 @@ private: void EmitXXStructorList(const DataLayout &DL, const Constant *List, bool isCtor); - GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &C); + GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &S); /// Emit GlobalAlias or GlobalIFunc. - void emitGlobalIndirectSymbol(Module &M, - const GlobalIndirectSymbol& GIS); + void emitGlobalIndirectSymbol(Module &M, const GlobalIndirectSymbol &GIS); void setupCodePaddingContext(const MachineBasicBlock &MBB, MCCodePaddingContext &Context) const; }; diff --git a/contrib/llvm/include/llvm/CodeGen/AtomicExpandUtils.h b/contrib/llvm/include/llvm/CodeGen/AtomicExpandUtils.h index 1f9c96b18e1b..b1adf66e7ff4 100644 --- a/contrib/llvm/include/llvm/CodeGen/AtomicExpandUtils.h +++ b/contrib/llvm/include/llvm/CodeGen/AtomicExpandUtils.h @@ -26,7 +26,7 @@ using CreateCmpXchgInstFun = function_ref<void(IRBuilder<> &, Value *, Value *, Value *, AtomicOrdering, Value *&, Value *&)>; -/// \brief Expand an atomic RMW instruction into a loop utilizing +/// Expand an atomic RMW instruction into a loop utilizing /// cmpxchg. You'll want to make sure your target machine likes cmpxchg /// instructions in the first place and that there isn't another, better, /// transformation available (for example AArch32/AArch64 have linked loads). @@ -58,7 +58,7 @@ using CreateCmpXchgInstFun = /// [...] /// /// Returns true if the containing function was modified. -bool expandAtomicRMWToCmpXchg(AtomicRMWInst *AI, CreateCmpXchgInstFun Factory); +bool expandAtomicRMWToCmpXchg(AtomicRMWInst *AI, CreateCmpXchgInstFun CreateCmpXchg); } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h index 526ddb1b9706..f76a2426377a 100644 --- a/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h +++ b/contrib/llvm/include/llvm/CodeGen/BasicTTIImpl.h @@ -26,7 +26,6 @@ #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TargetTransformInfoImpl.h" #include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/CodeGen/ValueTypes.h" @@ -47,6 +46,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/MathExtras.h" #include <algorithm> #include <cassert> @@ -65,7 +65,7 @@ class TargetMachine; extern cl::opt<unsigned> PartialUnrollingThreshold; -/// \brief Base class which can be used to help build a TTI implementation. +/// Base class which can be used to help build a TTI implementation. /// /// This class provides as much implementation of the TTI interface as is /// possible using the target independent parts of the code generator. @@ -101,16 +101,32 @@ private: return Cost; } - /// \brief Local query method delegates up to T which *must* implement this! + /// Local query method delegates up to T which *must* implement this! const TargetSubtargetInfo *getST() const { return static_cast<const T *>(this)->getST(); } - /// \brief Local query method delegates up to T which *must* implement this! + /// Local query method delegates up to T which *must* implement this! const TargetLoweringBase *getTLI() const { return static_cast<const T *>(this)->getTLI(); } + static ISD::MemIndexedMode getISDIndexedMode(TTI::MemIndexedMode M) { + switch (M) { + case TTI::MIM_Unindexed: + return ISD::UNINDEXED; + case TTI::MIM_PreInc: + return ISD::PRE_INC; + case TTI::MIM_PreDec: + return ISD::PRE_DEC; + case TTI::MIM_PostInc: + return ISD::POST_INC; + case TTI::MIM_PostDec: + return ISD::POST_DEC; + } + llvm_unreachable("Unexpected MemIndexedMode"); + } + protected: explicit BasicTTIImplBase(const TargetMachine *TM, const DataLayout &DL) : BaseT(DL) {} @@ -157,6 +173,18 @@ public: return getTLI()->isLegalAddressingMode(DL, AM, Ty, AddrSpace, I); } + bool isIndexedLoadLegal(TTI::MemIndexedMode M, Type *Ty, + const DataLayout &DL) const { + EVT VT = getTLI()->getValueType(DL, Ty); + return getTLI()->isIndexedLoadLegal(getISDIndexedMode(M), VT); + } + + bool isIndexedStoreLegal(TTI::MemIndexedMode M, Type *Ty, + const DataLayout &DL) const { + EVT VT = getTLI()->getValueType(DL, Ty); + return getTLI()->isIndexedStoreLegal(getISDIndexedMode(M), VT); + } + bool isLSRCostLess(TTI::LSRCost C1, TTI::LSRCost C2) { return TargetTransformInfoImplBase::isLSRCostLess(C1, C2); } @@ -179,6 +207,8 @@ public: return getTLI()->isProfitableToHoist(I); } + bool useAA() const { return getST()->useAA(); } + bool isTypeLegal(Type *Ty) { EVT VT = getTLI()->getValueType(DL, Ty); return getTLI()->isTypeLegal(VT); @@ -240,7 +270,7 @@ public: bool IsJTAllowed = TLI->areJTsAllowed(SI.getParent()->getParent()); // Early exit if both a jump table and bit test are not allowed. - if (N < 1 || (!IsJTAllowed && DL.getPointerSizeInBits() < N)) + if (N < 1 || (!IsJTAllowed && DL.getIndexSizeInBits(0u) < N)) return N; APInt MaxCaseVal = SI.case_begin()->getCaseValue()->getValue(); @@ -254,7 +284,7 @@ public: } // Check if suitable for a bit test - if (N <= DL.getPointerSizeInBits()) { + if (N <= DL.getIndexSizeInBits(0u)) { SmallPtrSet<const BasicBlock *, 4> Dests; for (auto I : SI.cases()) Dests.insert(I.getCaseSuccessor()); @@ -523,11 +553,15 @@ public: unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index, Type *SubTp) { - if (Kind == TTI::SK_Alternate || Kind == TTI::SK_PermuteTwoSrc || - Kind == TTI::SK_PermuteSingleSrc) { + switch (Kind) { + case TTI::SK_Select: + case TTI::SK_Transpose: + case TTI::SK_PermuteSingleSrc: + case TTI::SK_PermuteTwoSrc: return getPermuteShuffleOverhead(Tp); + default: + return 1; } - return 1; } unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src, @@ -614,7 +648,7 @@ public: } // If we are legalizing by splitting, query the concrete TTI for the cost - // of casting the original vector twice. We also need to factor int the + // of casting the original vector twice. We also need to factor in the // cost of the split itself. Count that as 1, to be consistent with // TLI->getTypeLegalizationCost(). if ((TLI->getTypeAction(Src->getContext(), TLI->getValueType(DL, Src)) == @@ -916,6 +950,20 @@ public: RetTy, Args[0], VarMask, Alignment); } + case Intrinsic::experimental_vector_reduce_add: + case Intrinsic::experimental_vector_reduce_mul: + case Intrinsic::experimental_vector_reduce_and: + case Intrinsic::experimental_vector_reduce_or: + case Intrinsic::experimental_vector_reduce_xor: + case Intrinsic::experimental_vector_reduce_fadd: + case Intrinsic::experimental_vector_reduce_fmul: + case Intrinsic::experimental_vector_reduce_smax: + case Intrinsic::experimental_vector_reduce_smin: + case Intrinsic::experimental_vector_reduce_fmax: + case Intrinsic::experimental_vector_reduce_fmin: + case Intrinsic::experimental_vector_reduce_umax: + case Intrinsic::experimental_vector_reduce_umin: + return getIntrinsicInstrCost(IID, RetTy, Args[0]->getType(), FMF); } } @@ -1039,6 +1087,39 @@ public: case Intrinsic::masked_load: return static_cast<T *>(this) ->getMaskedMemoryOpCost(Instruction::Load, RetTy, 0, 0); + case Intrinsic::experimental_vector_reduce_add: + return static_cast<T *>(this)->getArithmeticReductionCost( + Instruction::Add, Tys[0], /*IsPairwiseForm=*/false); + case Intrinsic::experimental_vector_reduce_mul: + return static_cast<T *>(this)->getArithmeticReductionCost( + Instruction::Mul, Tys[0], /*IsPairwiseForm=*/false); + case Intrinsic::experimental_vector_reduce_and: + return static_cast<T *>(this)->getArithmeticReductionCost( + Instruction::And, Tys[0], /*IsPairwiseForm=*/false); + case Intrinsic::experimental_vector_reduce_or: + return static_cast<T *>(this)->getArithmeticReductionCost( + Instruction::Or, Tys[0], /*IsPairwiseForm=*/false); + case Intrinsic::experimental_vector_reduce_xor: + return static_cast<T *>(this)->getArithmeticReductionCost( + Instruction::Xor, Tys[0], /*IsPairwiseForm=*/false); + case Intrinsic::experimental_vector_reduce_fadd: + return static_cast<T *>(this)->getArithmeticReductionCost( + Instruction::FAdd, Tys[0], /*IsPairwiseForm=*/false); + case Intrinsic::experimental_vector_reduce_fmul: + return static_cast<T *>(this)->getArithmeticReductionCost( + Instruction::FMul, Tys[0], /*IsPairwiseForm=*/false); + case Intrinsic::experimental_vector_reduce_smax: + case Intrinsic::experimental_vector_reduce_smin: + case Intrinsic::experimental_vector_reduce_fmax: + case Intrinsic::experimental_vector_reduce_fmin: + return static_cast<T *>(this)->getMinMaxReductionCost( + Tys[0], CmpInst::makeCmpResultType(Tys[0]), /*IsPairwiseForm=*/false, + /*IsSigned=*/true); + case Intrinsic::experimental_vector_reduce_umax: + case Intrinsic::experimental_vector_reduce_umin: + return static_cast<T *>(this)->getMinMaxReductionCost( + Tys[0], CmpInst::makeCmpResultType(Tys[0]), /*IsPairwiseForm=*/false, + /*IsSigned=*/false); case Intrinsic::ctpop: ISDs.push_back(ISD::CTPOP); // In case of legalization use TCC_Expensive. This is cheaper than a @@ -1123,7 +1204,7 @@ public: return SingleCallCost; } - /// \brief Compute a cost of the given call instruction. + /// Compute a cost of the given call instruction. /// /// Compute the cost of calling function F with return type RetTy and /// argument types Tys. F might be nullptr, in this case the cost of an @@ -1284,7 +1365,7 @@ public: /// @} }; -/// \brief Concrete BasicTTIImpl that can be used if no further customization +/// Concrete BasicTTIImpl that can be used if no further customization /// is needed. class BasicTTIImpl : public BasicTTIImplBase<BasicTTIImpl> { using BaseT = BasicTTIImplBase<BasicTTIImpl>; @@ -1298,7 +1379,7 @@ class BasicTTIImpl : public BasicTTIImplBase<BasicTTIImpl> { const TargetLoweringBase *getTLI() const { return TLI; } public: - explicit BasicTTIImpl(const TargetMachine *ST, const Function &F); + explicit BasicTTIImpl(const TargetMachine *TM, const Function &F); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h index d9e8206408a7..f85767f1fc11 100644 --- a/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h +++ b/contrib/llvm/include/llvm/CodeGen/CalcSpillWeights.h @@ -22,7 +22,7 @@ class MachineFunction; class MachineLoopInfo; class VirtRegMap; - /// \brief Normalize the spill weight of a live interval + /// Normalize the spill weight of a live interval /// /// The spill weight of a live interval is computed as: /// @@ -42,7 +42,7 @@ class VirtRegMap; return UseDefFreq / (Size + 25*SlotIndex::InstrDist); } - /// \brief Calculate auxiliary information for a virtual register such as its + /// Calculate auxiliary information for a virtual register such as its /// spill weight and allocation hint. class VirtRegAuxInfo { public: @@ -64,10 +64,10 @@ class VirtRegMap; NormalizingFn norm = normalizeSpillWeight) : MF(mf), LIS(lis), VRM(vrm), Loops(loops), MBFI(mbfi), normalize(norm) {} - /// \brief (re)compute li's spill weight and allocation hint. + /// (re)compute li's spill weight and allocation hint. void calculateSpillWeightAndHint(LiveInterval &li); - /// \brief Compute future expected spill weight of a split artifact of li + /// Compute future expected spill weight of a split artifact of li /// that will span between start and end slot indexes. /// \param li The live interval to be split. /// \param start The expected begining of the split artifact. Instructions @@ -78,7 +78,7 @@ class VirtRegMap; /// negative weight for unspillable li. float futureWeight(LiveInterval &li, SlotIndex start, SlotIndex end); - /// \brief Helper function for weight calculations. + /// Helper function for weight calculations. /// (Re)compute li's spill weight and allocation hint, or, for non null /// start and end - compute future expected spill weight of a split /// artifact of li that will span between start and end slot indexes. @@ -94,7 +94,7 @@ class VirtRegMap; SlotIndex *end = nullptr); }; - /// \brief Compute spill weights and allocation hints for all virtual register + /// Compute spill weights and allocation hints for all virtual register /// live intervals. void calculateSpillWeightsAndHints(LiveIntervals &LIS, MachineFunction &MF, VirtRegMap *VRM, diff --git a/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h b/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h index d30a27328c01..efcf80ba0b4e 100644 --- a/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h +++ b/contrib/llvm/include/llvm/CodeGen/CallingConvLower.h @@ -304,7 +304,7 @@ public: /// CheckReturn - Analyze the return values of a function, returning /// true if the return can be performed without sret-demotion, and /// false otherwise. - bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &ArgsFlags, + bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, CCAssignFn Fn); /// AnalyzeCallOperands - Analyze the outgoing arguments to a call, diff --git a/contrib/llvm/include/llvm/CodeGen/CommandFlags.def b/contrib/llvm/include/llvm/CodeGen/CommandFlags.inc index fe96033a9c61..7d2d167289e0 100644 --- a/contrib/llvm/include/llvm/CodeGen/CommandFlags.def +++ b/contrib/llvm/include/llvm/CodeGen/CommandFlags.inc @@ -17,7 +17,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" -#include "llvm/MC/MCTargetOptionsCommandFlags.def" +#include "llvm/MC/MCTargetOptionsCommandFlags.inc" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" @@ -98,7 +98,9 @@ static cl::opt<llvm::ExceptionHandling> ExceptionModel( clEnumValN(ExceptionHandling::SjLj, "sjlj", "SjLj exception handling"), clEnumValN(ExceptionHandling::ARM, "arm", "ARM EHABI exceptions"), clEnumValN(ExceptionHandling::WinEH, "wineh", - "Windows exception model"))); + "Windows exception model"), + clEnumValN(ExceptionHandling::Wasm, "wasm", + "WebAssembly exception handling"))); static cl::opt<TargetMachine::CodeGenFileType> FileType( "filetype", cl::init(TargetMachine::CGFT_AssemblyFile), @@ -259,6 +261,10 @@ static cl::opt<bool> EnableStackSizeSection( "stack-size-section", cl::desc("Emit a section containing stack size metadata"), cl::init(false)); +static cl::opt<bool> + EnableAddrsig("addrsig", cl::desc("Emit an address-significance table"), + cl::init(false)); + // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static TargetOptions InitTargetOptionsFromCodeGenFlags() { @@ -284,8 +290,10 @@ static TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.FunctionSections = FunctionSections; Options.UniqueSectionNames = UniqueSectionNames; Options.EmulatedTLS = EmulatedTLS; + Options.ExplicitEmulatedTLS = EmulatedTLS.getNumOccurrences() > 0; Options.ExceptionModel = ExceptionModel; Options.EmitStackSizeSection = EnableStackSizeSection; + Options.EmitAddrsig = EnableAddrsig; Options.MCOptions = InitMCTargetOptionsFromFlags(); @@ -326,7 +334,27 @@ LLVM_ATTRIBUTE_UNUSED static std::string getFeaturesStr() { return Features.getString(); } -/// \brief Set function attributes of functions in Module M based on CPU, +LLVM_ATTRIBUTE_UNUSED static std::vector<std::string> getFeatureList() { + SubtargetFeatures Features; + + // If user asked for the 'native' CPU, we need to autodetect features. + // This is necessary for x86 where the CPU might not support all the + // features the autodetected CPU name lists in the target. For example, + // not all Sandybridge processors support AVX. + if (MCPU == "native") { + StringMap<bool> HostFeatures; + if (sys::getHostCPUFeatures(HostFeatures)) + for (auto &F : HostFeatures) + Features.AddFeature(F.first(), F.second); + } + + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + + return Features.getFeatures(); +} + +/// Set function attributes of functions in Module M based on CPU, /// Features, and command line flags. LLVM_ATTRIBUTE_UNUSED static void setFunctionAttributes(StringRef CPU, StringRef Features, Module &M) { diff --git a/contrib/llvm/include/llvm/CodeGen/CostTable.h b/contrib/llvm/include/llvm/CodeGen/CostTable.h index 5a6368c5a0f8..48ad76971520 100644 --- a/contrib/llvm/include/llvm/CodeGen/CostTable.h +++ b/contrib/llvm/include/llvm/CodeGen/CostTable.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Cost tables and simple lookup functions +/// Cost tables and simple lookup functions /// //===----------------------------------------------------------------------===// @@ -17,7 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/CodeGen/MachineValueType.h" +#include "llvm/Support/MachineValueType.h" namespace llvm { diff --git a/contrib/llvm/include/llvm/CodeGen/DIE.h b/contrib/llvm/include/llvm/CodeGen/DIE.h index f809fc97fe59..7d486b1df56d 100644 --- a/contrib/llvm/include/llvm/CodeGen/DIE.h +++ b/contrib/llvm/include/llvm/CodeGen/DIE.h @@ -136,7 +136,7 @@ class DIEAbbrevSet { /// The bump allocator to use when creating DIEAbbrev objects in the uniqued /// storage container. BumpPtrAllocator &Alloc; - /// \brief FoldingSet that uniques the abbreviations. + /// FoldingSet that uniques the abbreviations. FoldingSet<DIEAbbrev> AbbreviationsSet; /// A list of all the unique abbreviations in use. std::vector<DIEAbbrev *> Abbreviations; @@ -190,7 +190,7 @@ public: uint64_t getValue() const { return Integer; } void setValue(uint64_t Val) { Integer = Val; } - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + void EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const; unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; void print(raw_ostream &O) const; @@ -868,7 +868,7 @@ public: return dwarf::DW_FORM_block; } - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + void EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const; unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; void print(raw_ostream &O) const; @@ -899,7 +899,7 @@ public: return dwarf::DW_FORM_block; } - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + void EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const; unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; void print(raw_ostream &O) const; diff --git a/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h b/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h index fc2b5ddd2d2c..e6c0483cfc35 100644 --- a/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h +++ b/contrib/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h @@ -41,6 +41,8 @@ public: unsigned getOffset() const { return I->second.Offset; } unsigned getIndex() const { return I->second.Index; } StringRef getString() const { return I->first(); } + /// Return the entire string pool entry for convenience. + DwarfStringPoolEntry getEntry() const { return I->getValue(); } bool operator==(const DwarfStringPoolEntryRef &X) const { return I == X.I; } bool operator!=(const DwarfStringPoolEntryRef &X) const { return I != X.I; } diff --git a/contrib/llvm/include/llvm/CodeGen/ExecutionDepsFix.h b/contrib/llvm/include/llvm/CodeGen/ExecutionDepsFix.h deleted file mode 100644 index f4db8b7322da..000000000000 --- a/contrib/llvm/include/llvm/CodeGen/ExecutionDepsFix.h +++ /dev/null @@ -1,230 +0,0 @@ -//==- llvm/CodeGen/ExecutionDepsFix.h - Execution Dependency Fix -*- C++ -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// \file Execution Dependency Fix pass. -/// -/// Some X86 SSE instructions like mov, and, or, xor are available in different -/// variants for different operand types. These variant instructions are -/// equivalent, but on Nehalem and newer cpus there is extra latency -/// transferring data between integer and floating point domains. ARM cores -/// have similar issues when they are configured with both VFP and NEON -/// pipelines. -/// -/// This pass changes the variant instructions to minimize domain crossings. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_EXECUTIONDEPSFIX_H -#define LLVM_CODEGEN_EXECUTIONDEPSFIX_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/CodeGen/LivePhysRegs.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/RegisterClassInfo.h" -#include "llvm/Pass.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/MathExtras.h" -#include <cassert> -#include <limits> -#include <utility> -#include <vector> - -namespace llvm { - -class MachineBasicBlock; -class MachineInstr; -class TargetInstrInfo; - -/// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track -/// of execution domains. -/// -/// An open DomainValue represents a set of instructions that can still switch -/// execution domain. Multiple registers may refer to the same open -/// DomainValue - they will eventually be collapsed to the same execution -/// domain. -/// -/// A collapsed DomainValue represents a single register that has been forced -/// into one of more execution domains. There is a separate collapsed -/// DomainValue for each register, but it may contain multiple execution -/// domains. A register value is initially created in a single execution -/// domain, but if we were forced to pay the penalty of a domain crossing, we -/// keep track of the fact that the register is now available in multiple -/// domains. -struct DomainValue { - // Basic reference counting. - unsigned Refs = 0; - - // Bitmask of available domains. For an open DomainValue, it is the still - // possible domains for collapsing. For a collapsed DomainValue it is the - // domains where the register is available for free. - unsigned AvailableDomains; - - // Pointer to the next DomainValue in a chain. When two DomainValues are - // merged, Victim.Next is set to point to Victor, so old DomainValue - // references can be updated by following the chain. - DomainValue *Next; - - // Twiddleable instructions using or defining these registers. - SmallVector<MachineInstr*, 8> Instrs; - - DomainValue() { clear(); } - - // A collapsed DomainValue has no instructions to twiddle - it simply keeps - // track of the domains where the registers are already available. - bool isCollapsed() const { return Instrs.empty(); } - - // Is domain available? - bool hasDomain(unsigned domain) const { - assert(domain < - static_cast<unsigned>(std::numeric_limits<unsigned>::digits) && - "undefined behavior"); - return AvailableDomains & (1u << domain); - } - - // Mark domain as available. - void addDomain(unsigned domain) { - AvailableDomains |= 1u << domain; - } - - // Restrict to a single domain available. - void setSingleDomain(unsigned domain) { - AvailableDomains = 1u << domain; - } - - // Return bitmask of domains that are available and in mask. - unsigned getCommonDomains(unsigned mask) const { - return AvailableDomains & mask; - } - - // First domain available. - unsigned getFirstDomain() const { - return countTrailingZeros(AvailableDomains); - } - - // Clear this DomainValue and point to next which has all its data. - void clear() { - AvailableDomains = 0; - Next = nullptr; - Instrs.clear(); - } -}; - -/// Information about a live register. -struct LiveReg { - /// Value currently in this register, or NULL when no value is being tracked. - /// This counts as a DomainValue reference. - DomainValue *Value; - - /// Instruction that defined this register, relative to the beginning of the - /// current basic block. When a LiveReg is used to represent a live-out - /// register, this value is relative to the end of the basic block, so it - /// will be a negative number. - int Def; -}; - -class ExecutionDepsFix : public MachineFunctionPass { - SpecificBumpPtrAllocator<DomainValue> Allocator; - SmallVector<DomainValue*,16> Avail; - - const TargetRegisterClass *const RC; - MachineFunction *MF; - const TargetInstrInfo *TII; - const TargetRegisterInfo *TRI; - RegisterClassInfo RegClassInfo; - std::vector<SmallVector<int, 1>> AliasMap; - const unsigned NumRegs; - LiveReg *LiveRegs; - struct MBBInfo { - // Keeps clearance and domain information for all registers. Note that this - // is different from the usual definition notion of liveness. The CPU - // doesn't care whether or not we consider a register killed. - LiveReg *OutRegs = nullptr; - - // Whether we have gotten to this block in primary processing yet. - bool PrimaryCompleted = false; - - // The number of predecessors for which primary processing has completed - unsigned IncomingProcessed = 0; - - // The value of `IncomingProcessed` at the start of primary processing - unsigned PrimaryIncoming = 0; - - // The number of predecessors for which all processing steps are done. - unsigned IncomingCompleted = 0; - - MBBInfo() = default; - }; - using MBBInfoMap = DenseMap<MachineBasicBlock *, MBBInfo>; - MBBInfoMap MBBInfos; - - /// List of undefined register reads in this block in forward order. - std::vector<std::pair<MachineInstr *, unsigned>> UndefReads; - - /// Storage for register unit liveness. - LivePhysRegs LiveRegSet; - - /// Current instruction number. - /// The first instruction in each basic block is 0. - int CurInstr; - -public: - ExecutionDepsFix(char &PassID, const TargetRegisterClass &RC) - : MachineFunctionPass(PassID), RC(&RC), NumRegs(RC.getNumRegs()) {} - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - MachineFunctionPass::getAnalysisUsage(AU); - } - - bool runOnMachineFunction(MachineFunction &MF) override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } - -private: - iterator_range<SmallVectorImpl<int>::const_iterator> - regIndices(unsigned Reg) const; - // DomainValue allocation. - DomainValue *alloc(int domain = -1); - DomainValue *retain(DomainValue *DV) { - if (DV) ++DV->Refs; - return DV; - } - void release(DomainValue*); - DomainValue *resolve(DomainValue*&); - - // LiveRegs manipulations. - void setLiveReg(int rx, DomainValue *DV); - void kill(int rx); - void force(int rx, unsigned domain); - void collapse(DomainValue *dv, unsigned domain); - bool merge(DomainValue *A, DomainValue *B); - - void enterBasicBlock(MachineBasicBlock*); - void leaveBasicBlock(MachineBasicBlock*); - bool isBlockDone(MachineBasicBlock *); - void processBasicBlock(MachineBasicBlock *MBB, bool PrimaryPass); - bool visitInstr(MachineInstr *); - void processDefs(MachineInstr *, bool breakDependency, bool Kill); - void visitSoftInstr(MachineInstr*, unsigned mask); - void visitHardInstr(MachineInstr*, unsigned domain); - bool pickBestRegisterForUndef(MachineInstr *MI, unsigned OpIdx, - unsigned Pref); - bool shouldBreakDependence(MachineInstr*, unsigned OpIdx, unsigned Pref); - void processUndefReads(MachineBasicBlock*); -}; - -} // end namepsace llvm - -#endif // LLVM_CODEGEN_EXECUTIONDEPSFIX_H diff --git a/contrib/llvm/include/llvm/CodeGen/ExecutionDomainFix.h b/contrib/llvm/include/llvm/CodeGen/ExecutionDomainFix.h new file mode 100644 index 000000000000..338c214dd073 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/ExecutionDomainFix.h @@ -0,0 +1,213 @@ +//==-- llvm/CodeGen/ExecutionDomainFix.h - Execution Domain Fix -*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file Execution Domain Fix pass. +/// +/// Some X86 SSE instructions like mov, and, or, xor are available in different +/// variants for different operand types. These variant instructions are +/// equivalent, but on Nehalem and newer cpus there is extra latency +/// transferring data between integer and floating point domains. ARM cores +/// have similar issues when they are configured with both VFP and NEON +/// pipelines. +/// +/// This pass changes the variant instructions to minimize domain crossings. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_EXECUTIONDOMAINFIX_H +#define LLVM_CODEGEN_EXECUTIONDOMAINFIX_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/LoopTraversal.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/ReachingDefAnalysis.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" + +namespace llvm { + +class MachineBasicBlock; +class MachineInstr; +class TargetInstrInfo; + +/// A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track +/// of execution domains. +/// +/// An open DomainValue represents a set of instructions that can still switch +/// execution domain. Multiple registers may refer to the same open +/// DomainValue - they will eventually be collapsed to the same execution +/// domain. +/// +/// A collapsed DomainValue represents a single register that has been forced +/// into one of more execution domains. There is a separate collapsed +/// DomainValue for each register, but it may contain multiple execution +/// domains. A register value is initially created in a single execution +/// domain, but if we were forced to pay the penalty of a domain crossing, we +/// keep track of the fact that the register is now available in multiple +/// domains. +struct DomainValue { + /// Basic reference counting. + unsigned Refs = 0; + + /// Bitmask of available domains. For an open DomainValue, it is the still + /// possible domains for collapsing. For a collapsed DomainValue it is the + /// domains where the register is available for free. + unsigned AvailableDomains; + + /// Pointer to the next DomainValue in a chain. When two DomainValues are + /// merged, Victim.Next is set to point to Victor, so old DomainValue + /// references can be updated by following the chain. + DomainValue *Next; + + /// Twiddleable instructions using or defining these registers. + SmallVector<MachineInstr *, 8> Instrs; + + DomainValue() { clear(); } + + /// A collapsed DomainValue has no instructions to twiddle - it simply keeps + /// track of the domains where the registers are already available. + bool isCollapsed() const { return Instrs.empty(); } + + /// Is domain available? + bool hasDomain(unsigned domain) const { + assert(domain < + static_cast<unsigned>(std::numeric_limits<unsigned>::digits) && + "undefined behavior"); + return AvailableDomains & (1u << domain); + } + + /// Mark domain as available. + void addDomain(unsigned domain) { AvailableDomains |= 1u << domain; } + + // Restrict to a single domain available. + void setSingleDomain(unsigned domain) { AvailableDomains = 1u << domain; } + + /// Return bitmask of domains that are available and in mask. + unsigned getCommonDomains(unsigned mask) const { + return AvailableDomains & mask; + } + + /// First domain available. + unsigned getFirstDomain() const { + return countTrailingZeros(AvailableDomains); + } + + /// Clear this DomainValue and point to next which has all its data. + void clear() { + AvailableDomains = 0; + Next = nullptr; + Instrs.clear(); + } +}; + +class ExecutionDomainFix : public MachineFunctionPass { + SpecificBumpPtrAllocator<DomainValue> Allocator; + SmallVector<DomainValue *, 16> Avail; + + const TargetRegisterClass *const RC; + MachineFunction *MF; + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + std::vector<SmallVector<int, 1>> AliasMap; + const unsigned NumRegs; + /// Value currently in each register, or NULL when no value is being tracked. + /// This counts as a DomainValue reference. + using LiveRegsDVInfo = std::vector<DomainValue *>; + LiveRegsDVInfo LiveRegs; + /// Keeps domain information for all registers. Note that this + /// is different from the usual definition notion of liveness. The CPU + /// doesn't care whether or not we consider a register killed. + using OutRegsInfoMap = SmallVector<LiveRegsDVInfo, 4>; + OutRegsInfoMap MBBOutRegsInfos; + + ReachingDefAnalysis *RDA; + +public: + ExecutionDomainFix(char &PassID, const TargetRegisterClass &RC) + : MachineFunctionPass(PassID), RC(&RC), NumRegs(RC.getNumRegs()) {} + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + AU.addRequired<ReachingDefAnalysis>(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoVRegs); + } + +private: + /// Translate TRI register number to a list of indices into our smaller tables + /// of interesting registers. + iterator_range<SmallVectorImpl<int>::const_iterator> + regIndices(unsigned Reg) const; + + /// DomainValue allocation. + DomainValue *alloc(int domain = -1); + + /// Add reference to DV. + DomainValue *retain(DomainValue *DV) { + if (DV) + ++DV->Refs; + return DV; + } + + /// Release a reference to DV. When the last reference is released, + /// collapse if needed. + void release(DomainValue *); + + /// Follow the chain of dead DomainValues until a live DomainValue is reached. + /// Update the referenced pointer when necessary. + DomainValue *resolve(DomainValue *&); + + /// Set LiveRegs[rx] = dv, updating reference counts. + void setLiveReg(int rx, DomainValue *DV); + + /// Kill register rx, recycle or collapse any DomainValue. + void kill(int rx); + + /// Force register rx into domain. + void force(int rx, unsigned domain); + + /// Collapse open DomainValue into given domain. If there are multiple + /// registers using dv, they each get a unique collapsed DomainValue. + void collapse(DomainValue *dv, unsigned domain); + + /// All instructions and registers in B are moved to A, and B is released. + bool merge(DomainValue *A, DomainValue *B); + + /// Set up LiveRegs by merging predecessor live-out values. + void enterBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB); + + /// Update live-out values. + void leaveBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB); + + /// Process he given basic block. + void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB); + + /// Visit given insturcion. + bool visitInstr(MachineInstr *); + + /// Update def-ages for registers defined by MI. + /// If Kill is set, also kill off DomainValues clobbered by the defs. + void processDefs(MachineInstr *, bool Kill); + + /// A soft instruction can be changed to work in other domains given by mask. + void visitSoftInstr(MachineInstr *, unsigned mask); + + /// A hard instruction only works in one domain. All input registers will be + /// forced into that domain. + void visitHardInstr(MachineInstr *, unsigned domain); +}; + +} // namespace llvm + +#endif // LLVM_CODEGEN_EXECUTIONDOMAINFIX_H diff --git a/contrib/llvm/include/llvm/CodeGen/FastISel.h b/contrib/llvm/include/llvm/CodeGen/FastISel.h index 85bb826dcb8c..865d8a88b8cc 100644 --- a/contrib/llvm/include/llvm/CodeGen/FastISel.h +++ b/contrib/llvm/include/llvm/CodeGen/FastISel.h @@ -19,7 +19,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallSite.h" @@ -28,6 +27,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/Support/MachineValueType.h" #include <algorithm> #include <cstdint> #include <utility> @@ -61,7 +61,7 @@ class Type; class User; class Value; -/// \brief This is a fast-path instruction selection class that generates poor +/// This is a fast-path instruction selection class that generates poor /// code and doesn't support illegal types or non-trivial lowering, but runs /// quickly. class FastISel { @@ -78,7 +78,7 @@ public: bool IsReturnValueUsed : 1; bool IsPatchPoint : 1; - // \brief IsTailCall Should be modified by implementations of FastLowerCall + // IsTailCall Should be modified by implementations of FastLowerCall // that perform tail call conversions. bool IsTailCall = false; @@ -215,67 +215,74 @@ protected: const TargetLibraryInfo *LibInfo; bool SkipTargetIndependentISel; - /// \brief The position of the last instruction for materializing constants + /// The position of the last instruction for materializing constants /// for use in the current block. It resets to EmitStartPt when it makes sense /// (for example, it's usually profitable to avoid function calls between the /// definition and the use) MachineInstr *LastLocalValue; - /// \brief The top most instruction in the current block that is allowed for + /// The top most instruction in the current block that is allowed for /// emitting local variables. LastLocalValue resets to EmitStartPt when it /// makes sense (for example, on function calls) MachineInstr *EmitStartPt; + /// Last local value flush point. On a subsequent flush, no local value will + /// sink past this point. + MachineBasicBlock::iterator LastFlushPoint; + public: virtual ~FastISel(); - /// \brief Return the position of the last instruction emitted for + /// Return the position of the last instruction emitted for /// materializing constants for use in the current block. MachineInstr *getLastLocalValue() { return LastLocalValue; } - /// \brief Update the position of the last instruction emitted for + /// Update the position of the last instruction emitted for /// materializing constants for use in the current block. void setLastLocalValue(MachineInstr *I) { EmitStartPt = I; LastLocalValue = I; } - /// \brief Set the current block to which generated machine instructions will - /// be appended, and clear the local CSE map. + /// Set the current block to which generated machine instructions will + /// be appended. void startNewBlock(); - /// \brief Return current debug location information. + /// Flush the local value map and sink local values if possible. + void finishBasicBlock(); + + /// Return current debug location information. DebugLoc getCurDebugLoc() const { return DbgLoc; } - /// \brief Do "fast" instruction selection for function arguments and append + /// Do "fast" instruction selection for function arguments and append /// the machine instructions to the current block. Returns true when /// successful. bool lowerArguments(); - /// \brief Do "fast" instruction selection for the given LLVM IR instruction + /// Do "fast" instruction selection for the given LLVM IR instruction /// and append the generated machine instructions to the current block. /// Returns true if selection was successful. bool selectInstruction(const Instruction *I); - /// \brief Do "fast" instruction selection for the given LLVM IR operator + /// Do "fast" instruction selection for the given LLVM IR operator /// (Instruction or ConstantExpr), and append generated machine instructions /// to the current block. Return true if selection was successful. bool selectOperator(const User *I, unsigned Opcode); - /// \brief Create a virtual register and arrange for it to be assigned the + /// Create a virtual register and arrange for it to be assigned the /// value for the given LLVM value. unsigned getRegForValue(const Value *V); - /// \brief Look up the value to see if its value is already cached in a + /// Look up the value to see if its value is already cached in a /// register. It may be defined by instructions across blocks or defined /// locally. unsigned lookUpRegForValue(const Value *V); - /// \brief This is a wrapper around getRegForValue that also takes care of + /// This is a wrapper around getRegForValue that also takes care of /// truncating or sign-extending the given getelementptr index value. - std::pair<unsigned, bool> getRegForGEPIndex(const Value *V); + std::pair<unsigned, bool> getRegForGEPIndex(const Value *Idx); - /// \brief We're checking to see if we can fold \p LI into \p FoldInst. Note + /// We're checking to see if we can fold \p LI into \p FoldInst. Note /// that we could have a sequence where multiple LLVM IR instructions are /// folded into the same machineinstr. For example we could have: /// @@ -289,7 +296,7 @@ public: /// If we succeed folding, return true. bool tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst); - /// \brief The specified machine instr operand is a vreg, and that vreg is + /// The specified machine instr operand is a vreg, and that vreg is /// being provided by the specified load instruction. If possible, try to /// fold the load as an operand to the instruction, returning true if /// possible. @@ -300,11 +307,11 @@ public: return false; } - /// \brief Reset InsertPt to prepare for inserting instructions into the + /// Reset InsertPt to prepare for inserting instructions into the /// current block. void recomputeInsertPt(); - /// \brief Remove all dead instructions between the I and E. + /// Remove all dead instructions between the I and E. void removeDeadCode(MachineBasicBlock::iterator I, MachineBasicBlock::iterator E); @@ -313,11 +320,11 @@ public: DebugLoc DL; }; - /// \brief Prepare InsertPt to begin inserting instructions into the local + /// Prepare InsertPt to begin inserting instructions into the local /// value area and return the old insert position. SavePoint enterLocalValueArea(); - /// \brief Reset InsertPt to the given old insert position. + /// Reset InsertPt to the given old insert position. void leaveLocalValueArea(SavePoint Old); protected: @@ -325,45 +332,45 @@ protected: const TargetLibraryInfo *LibInfo, bool SkipTargetIndependentISel = false); - /// \brief This method is called by target-independent code when the normal + /// This method is called by target-independent code when the normal /// FastISel process fails to select an instruction. This gives targets a /// chance to emit code for anything that doesn't fit into FastISel's /// framework. It returns true if it was successful. virtual bool fastSelectInstruction(const Instruction *I) = 0; - /// \brief This method is called by target-independent code to do target- + /// This method is called by target-independent code to do target- /// specific argument lowering. It returns true if it was successful. virtual bool fastLowerArguments(); - /// \brief This method is called by target-independent code to do target- + /// This method is called by target-independent code to do target- /// specific call lowering. It returns true if it was successful. virtual bool fastLowerCall(CallLoweringInfo &CLI); - /// \brief This method is called by target-independent code to do target- + /// This method is called by target-independent code to do target- /// specific intrinsic lowering. It returns true if it was successful. virtual bool fastLowerIntrinsicCall(const IntrinsicInst *II); - /// \brief This method is called by target-independent code to request that an + /// This method is called by target-independent code to request that an /// instruction with the given type and opcode be emitted. virtual unsigned fastEmit_(MVT VT, MVT RetVT, unsigned Opcode); - /// \brief This method is called by target-independent code to request that an + /// This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register operand be emitted. virtual unsigned fastEmit_r(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill); - /// \brief This method is called by target-independent code to request that an + /// This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register operands be emitted. virtual unsigned fastEmit_rr(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill); - /// \brief This method is called by target-independent code to request that an + /// This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register and immediate /// operands be emitted. virtual unsigned fastEmit_ri(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill, uint64_t Imm); - /// \brief This method is a wrapper of fastEmit_ri. + /// This method is a wrapper of fastEmit_ri. /// /// It first tries to emit an instruction with an immediate operand using /// fastEmit_ri. If that fails, it materializes the immediate into a register @@ -371,89 +378,89 @@ protected: unsigned fastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0, bool Op0IsKill, uint64_t Imm, MVT ImmType); - /// \brief This method is called by target-independent code to request that an + /// This method is called by target-independent code to request that an /// instruction with the given type, opcode, and immediate operand be emitted. virtual unsigned fastEmit_i(MVT VT, MVT RetVT, unsigned Opcode, uint64_t Imm); - /// \brief This method is called by target-independent code to request that an + /// This method is called by target-independent code to request that an /// instruction with the given type, opcode, and floating-point immediate /// operand be emitted. virtual unsigned fastEmit_f(MVT VT, MVT RetVT, unsigned Opcode, const ConstantFP *FPImm); - /// \brief Emit a MachineInstr with no operands and a result register in the + /// Emit a MachineInstr with no operands and a result register in the /// given register class. unsigned fastEmitInst_(unsigned MachineInstOpcode, const TargetRegisterClass *RC); - /// \brief Emit a MachineInstr with one register operand and a result register + /// Emit a MachineInstr with one register operand and a result register /// in the given register class. unsigned fastEmitInst_r(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill); - /// \brief Emit a MachineInstr with two register operands and a result + /// Emit a MachineInstr with two register operands and a result /// register in the given register class. unsigned fastEmitInst_rr(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill); - /// \brief Emit a MachineInstr with three register operands and a result + /// Emit a MachineInstr with three register operands and a result /// register in the given register class. unsigned fastEmitInst_rrr(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, unsigned Op2, bool Op2IsKill); - /// \brief Emit a MachineInstr with a register operand, an immediate, and a + /// Emit a MachineInstr with a register operand, an immediate, and a /// result register in the given register class. unsigned fastEmitInst_ri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, uint64_t Imm); - /// \brief Emit a MachineInstr with one register operand and two immediate + /// Emit a MachineInstr with one register operand and two immediate /// operands. unsigned fastEmitInst_rii(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, uint64_t Imm1, uint64_t Imm2); - /// \brief Emit a MachineInstr with a floating point immediate, and a result + /// Emit a MachineInstr with a floating point immediate, and a result /// register in the given register class. unsigned fastEmitInst_f(unsigned MachineInstOpcode, const TargetRegisterClass *RC, const ConstantFP *FPImm); - /// \brief Emit a MachineInstr with two register operands, an immediate, and a + /// Emit a MachineInstr with two register operands, an immediate, and a /// result register in the given register class. unsigned fastEmitInst_rri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm); - /// \brief Emit a MachineInstr with a single immediate operand, and a result + /// Emit a MachineInstr with a single immediate operand, and a result /// register in the given register class. - unsigned fastEmitInst_i(unsigned MachineInstrOpcode, + unsigned fastEmitInst_i(unsigned MachineInstOpcode, const TargetRegisterClass *RC, uint64_t Imm); - /// \brief Emit a MachineInstr for an extract_subreg from a specified index of + /// Emit a MachineInstr for an extract_subreg from a specified index of /// a superregister to a specified type. unsigned fastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, bool Op0IsKill, uint32_t Idx); - /// \brief Emit MachineInstrs to compute the value of Op with all but the + /// Emit MachineInstrs to compute the value of Op with all but the /// least significant bit set to zero. unsigned fastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill); - /// \brief Emit an unconditional branch to the given block, unless it is the + /// Emit an unconditional branch to the given block, unless it is the /// immediate (fall-through) successor, and update the CFG. - void fastEmitBranch(MachineBasicBlock *MBB, const DebugLoc &DL); + void fastEmitBranch(MachineBasicBlock *MSucc, const DebugLoc &DbgLoc); /// Emit an unconditional branch to \p FalseMBB, obtains the branch weight /// and adds TrueMBB and FalseMBB to the successor list. void finishCondBranch(const BasicBlock *BranchBB, MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB); - /// \brief Update the value map to include the new mapping for this + /// Update the value map to include the new mapping for this /// instruction, or insert an extra copy to get the result in a previous /// determined register. /// @@ -464,26 +471,26 @@ protected: unsigned createResultReg(const TargetRegisterClass *RC); - /// \brief Try to constrain Op so that it is usable by argument OpNum of the + /// Try to constrain Op so that it is usable by argument OpNum of the /// provided MCInstrDesc. If this fails, create a new virtual register in the /// correct class and COPY the value there. unsigned constrainOperandRegClass(const MCInstrDesc &II, unsigned Op, unsigned OpNum); - /// \brief Emit a constant in a register using target-specific logic, such as + /// Emit a constant in a register using target-specific logic, such as /// constant pool loads. virtual unsigned fastMaterializeConstant(const Constant *C) { return 0; } - /// \brief Emit an alloca address in a register using target-specific logic. + /// Emit an alloca address in a register using target-specific logic. virtual unsigned fastMaterializeAlloca(const AllocaInst *C) { return 0; } - /// \brief Emit the floating-point constant +0.0 in a register using target- + /// Emit the floating-point constant +0.0 in a register using target- /// specific logic. virtual unsigned fastMaterializeFloatZero(const ConstantFP *CF) { return 0; } - /// \brief Check if \c Add is an add that can be safely folded into \c GEP. + /// Check if \c Add is an add that can be safely folded into \c GEP. /// /// \c Add can be folded into \c GEP if: /// - \c Add is an add, @@ -492,16 +499,16 @@ protected: /// - \c Add has a constant operand. bool canFoldAddIntoGEP(const User *GEP, const Value *Add); - /// \brief Test whether the given value has exactly one use. + /// Test whether the given value has exactly one use. bool hasTrivialKill(const Value *V); - /// \brief Create a machine mem operand from the given instruction. + /// Create a machine mem operand from the given instruction. MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const; CmpInst::Predicate optimizeCmpPredicate(const CmpInst *CI) const; bool lowerCallTo(const CallInst *CI, MCSymbol *Symbol, unsigned NumArgs); - bool lowerCallTo(const CallInst *CI, const char *SymbolName, + bool lowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs); bool lowerCallTo(CallLoweringInfo &CLI); @@ -518,23 +525,24 @@ protected: } bool lowerCall(const CallInst *I); - /// \brief Select and emit code for a binary operator instruction, which has + /// Select and emit code for a binary operator instruction, which has /// an opcode which directly corresponds to the given ISD opcode. bool selectBinaryOp(const User *I, unsigned ISDOpcode); bool selectFNeg(const User *I); bool selectGetElementPtr(const User *I); bool selectStackmap(const CallInst *I); bool selectPatchpoint(const CallInst *I); - bool selectCall(const User *Call); + bool selectCall(const User *I); bool selectIntrinsicCall(const IntrinsicInst *II); bool selectBitCast(const User *I); bool selectCast(const User *I, unsigned Opcode); - bool selectExtractValue(const User *I); + bool selectExtractValue(const User *U); bool selectInsertValue(const User *I); bool selectXRayCustomEvent(const CallInst *II); + bool selectXRayTypedEvent(const CallInst *II); private: - /// \brief Handle PHI nodes in successor blocks. + /// Handle PHI nodes in successor blocks. /// /// Emit code to ensure constants are copied into registers when needed. /// Remember the virtual registers that need to be added to the Machine PHI @@ -543,27 +551,41 @@ private: /// correspond to a different MBB than the end. bool handlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); - /// \brief Helper for materializeRegForValue to materialize a constant in a + /// Helper for materializeRegForValue to materialize a constant in a /// target-independent way. unsigned materializeConstant(const Value *V, MVT VT); - /// \brief Helper for getRegForVale. This function is called when the value + /// Helper for getRegForVale. This function is called when the value /// isn't already available in a register and must be materialized with new /// instructions. unsigned materializeRegForValue(const Value *V, MVT VT); - /// \brief Clears LocalValueMap and moves the area for the new local variables + /// Clears LocalValueMap and moves the area for the new local variables /// to the beginning of the block. It helps to avoid spilling cached variables /// across heavy instructions like calls. void flushLocalValueMap(); - /// \brief Removes dead local value instructions after SavedLastLocalvalue. + /// Removes dead local value instructions after SavedLastLocalvalue. void removeDeadLocalValueCode(MachineInstr *SavedLastLocalValue); - /// \brief Insertion point before trying to select the current instruction. + struct InstOrderMap { + DenseMap<MachineInstr *, unsigned> Orders; + MachineInstr *FirstTerminator = nullptr; + unsigned FirstTerminatorOrder = std::numeric_limits<unsigned>::max(); + + void initialize(MachineBasicBlock *MBB, + MachineBasicBlock::iterator LastFlushPoint); + }; + + /// Sinks the local value materialization instruction LocalMI to its first use + /// in the basic block, or deletes it if it is not used. + void sinkLocalValueMaterialization(MachineInstr &LocalMI, unsigned DefReg, + InstOrderMap &OrderMap); + + /// Insertion point before trying to select the current instruction. MachineBasicBlock::iterator SavedInsertPt; - /// \brief Add a stackmap or patchpoint intrinsic call's live variable + /// Add a stackmap or patchpoint intrinsic call's live variable /// operands to a stackmap or patchpoint machine instruction. bool addStackMapLiveVars(SmallVectorImpl<MachineOperand> &Ops, const CallInst *CI, unsigned StartIdx); diff --git a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h index 3b39d87ffb4a..2da00b7d61ab 100644 --- a/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -118,6 +118,17 @@ public: /// cross-basic-block values. DenseMap<const Value *, unsigned> ValueMap; + /// VirtReg2Value map is needed by the Divergence Analysis driven + /// instruction selection. It is reverted ValueMap. It is computed + /// in lazy style - on demand. It is used to get the Value corresponding + /// to the live in virtual register and is called from the + /// TargetLowerinInfo::isSDNodeSourceOfDivergence. + DenseMap<unsigned, const Value*> VirtReg2Value; + + /// This method is called from TargetLowerinInfo::isSDNodeSourceOfDivergence + /// to get the Value corresponding to the live-in virtual register. + const Value * getValueFromVirtualReg(unsigned Vreg); + /// Track virtual registers created for exception pointers. DenseMap<const Value *, unsigned> CatchPadExceptionPointers; @@ -167,6 +178,8 @@ public: /// RegFixups - Registers which need to be replaced after isel is done. DenseMap<unsigned, unsigned> RegFixups; + DenseSet<unsigned> RegsWithFixups; + /// StatepointStackSlots - A list of temporary stack slots (frame indices) /// used to spill values at a statepoint. We store them here to enable /// reuse of the same stack slots across different statepoints in different diff --git a/contrib/llvm/include/llvm/CodeGen/GCStrategy.h b/contrib/llvm/include/llvm/CodeGen/GCStrategy.h index 16168e785f81..91604fd2df87 100644 --- a/contrib/llvm/include/llvm/CodeGen/GCStrategy.h +++ b/contrib/llvm/include/llvm/CodeGen/GCStrategy.h @@ -105,12 +105,12 @@ public: /// By default, write barriers are replaced with simple store /// instructions. If true, you must provide a custom pass to lower - /// calls to @llvm.gcwrite. + /// calls to \@llvm.gcwrite. bool customWriteBarrier() const { return CustomWriteBarriers; } /// By default, read barriers are replaced with simple load /// instructions. If true, you must provide a custom pass to lower - /// calls to @llvm.gcread. + /// calls to \@llvm.gcread. bool customReadBarrier() const { return CustomReadBarriers; } /// Returns true if this strategy is expecting the use of gc.statepoints, @@ -147,7 +147,7 @@ public: /// By default, roots are left for the code generator so it can generate a /// stack map. If true, you must provide a custom pass to lower - /// calls to @llvm.gcroot. + /// calls to \@llvm.gcroot. bool customRoots() const { return CustomRoots; } /// If set, gcroot intrinsics should initialize their allocas to null diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h index ba84d76de164..58eb412d8c24 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -17,11 +17,11 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/CodeGen/CallingConvLower.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/TargetCallingConv.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/CallingConv.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachineValueType.h" #include <cstdint> #include <functional> @@ -123,7 +123,7 @@ protected: } template <typename FuncInfoTy> - void setArgFlags(ArgInfo &Arg, unsigned OpNum, const DataLayout &DL, + void setArgFlags(ArgInfo &Arg, unsigned OpIdx, const DataLayout &DL, const FuncInfoTy &FuncInfo) const; /// Invoke Handler::assignArg on each of the given \p Args and then use @@ -131,7 +131,7 @@ protected: /// /// \return True if everything has succeeded, false otherwise. bool handleAssignments(MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, - ValueHandler &Callback) const; + ValueHandler &Handler) const; public: CallLowering(const TargetLowering *TLI) : TLI(TLI) {} diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h new file mode 100644 index 000000000000..36a33deb4a64 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Combiner.h @@ -0,0 +1,43 @@ +//== ----- llvm/CodeGen/GlobalISel/Combiner.h --------------------- == // +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// This contains common code to drive combines. Combiner Passes will need to +/// setup a CombinerInfo and call combineMachineFunction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_H +#define LLVM_CODEGEN_GLOBALISEL_COMBINER_H + +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { +class MachineRegisterInfo; +class CombinerInfo; +class TargetPassConfig; +class MachineFunction; + +class Combiner { +public: + Combiner(CombinerInfo &CombinerInfo, const TargetPassConfig *TPC); + + bool combineMachineInstrs(MachineFunction &MF); + +protected: + CombinerInfo &CInfo; + + MachineRegisterInfo *MRI = nullptr; + const TargetPassConfig *TPC; + MachineIRBuilder Builder; +}; + +} // End namespace llvm. + +#endif // LLVM_CODEGEN_GLOBALISEL_GICOMBINER_H diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h new file mode 100644 index 000000000000..5d5b8398452c --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -0,0 +1,44 @@ +//== llvm/CodeGen/GlobalISel/CombinerHelper.h -------------- -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--------------------------------------------------------------------===// +// +/// This contains common combine transformations that may be used in a combine +/// pass,or by the target elsewhere. +/// Targets can pick individual opcode transformations from the helper or use +/// tryCombine which invokes all transformations. All of the transformations +/// return true if the MachineInstruction changed and false otherwise. +// +//===--------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H +#define LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H + +namespace llvm { + +class MachineIRBuilder; +class MachineRegisterInfo; +class MachineInstr; + +class CombinerHelper { + MachineIRBuilder &Builder; + MachineRegisterInfo &MRI; + +public: + CombinerHelper(MachineIRBuilder &B); + + /// If \p MI is COPY, try to combine it. + /// Returns true if MI changed. + bool tryCombineCopy(MachineInstr &MI); + + /// Try to transform \p MI by using all of the above + /// combine functions. Returns true if changed. + bool tryCombine(MachineInstr &MI); +}; +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h new file mode 100644 index 000000000000..1d248547adbf --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/CombinerInfo.h @@ -0,0 +1,48 @@ +//===- llvm/CodeGen/GlobalISel/CombinerInfo.h ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// Interface for Targets to specify which operations are combined how and when. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_INFO_H +#define LLVM_CODEGEN_GLOBALISEL_COMBINER_INFO_H + +#include <cassert> +namespace llvm { + +class LegalizerInfo; +class MachineInstr; +class MachineIRBuilder; +class MachineRegisterInfo; +// Contains information relevant to enabling/disabling various combines for a +// pass. +class CombinerInfo { +public: + CombinerInfo(bool AllowIllegalOps, bool ShouldLegalizeIllegal, + LegalizerInfo *LInfo) + : IllegalOpsAllowed(AllowIllegalOps), + LegalizeIllegalOps(ShouldLegalizeIllegal), LInfo(LInfo) { + assert(((AllowIllegalOps || !LegalizeIllegalOps) || LInfo) && + "Expecting legalizerInfo when illegalops not allowed"); + } + virtual ~CombinerInfo() = default; + /// If \p IllegalOpsAllowed is false, the CombinerHelper will make use of + /// the legalizerInfo to check for legality before each transformation. + bool IllegalOpsAllowed; // TODO: Make use of this. + + /// If \p LegalizeIllegalOps is true, the Combiner will also legalize the + /// illegal ops that are created. + bool LegalizeIllegalOps; // TODO: Make use of this. + const LegalizerInfo *LInfo; + virtual bool combine(MachineInstr &MI, MachineIRBuilder &B) const = 0; +}; +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h new file mode 100644 index 000000000000..8d61f9a68279 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h @@ -0,0 +1,134 @@ +//===-- llvm/CodeGen/GlobalISel/ConstantFoldingMIRBuilder.h --*- 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 implements a version of MachineIRBuilder which does trivial +/// constant folding. +//===----------------------------------------------------------------------===// +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" + +namespace llvm { + +static Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const unsigned Op1, + const unsigned Op2, + const MachineRegisterInfo &MRI) { + auto MaybeOp1Cst = getConstantVRegVal(Op1, MRI); + auto MaybeOp2Cst = getConstantVRegVal(Op2, MRI); + if (MaybeOp1Cst && MaybeOp2Cst) { + LLT Ty = MRI.getType(Op1); + APInt C1(Ty.getSizeInBits(), *MaybeOp1Cst, true); + APInt C2(Ty.getSizeInBits(), *MaybeOp2Cst, true); + switch (Opcode) { + default: + break; + case TargetOpcode::G_ADD: + return C1 + C2; + case TargetOpcode::G_AND: + return C1 & C2; + case TargetOpcode::G_ASHR: + return C1.ashr(C2); + case TargetOpcode::G_LSHR: + return C1.lshr(C2); + case TargetOpcode::G_MUL: + return C1 * C2; + case TargetOpcode::G_OR: + return C1 | C2; + case TargetOpcode::G_SHL: + return C1 << C2; + case TargetOpcode::G_SUB: + return C1 - C2; + case TargetOpcode::G_XOR: + return C1 ^ C2; + case TargetOpcode::G_UDIV: + if (!C2.getBoolValue()) + break; + return C1.udiv(C2); + case TargetOpcode::G_SDIV: + if (!C2.getBoolValue()) + break; + return C1.sdiv(C2); + case TargetOpcode::G_UREM: + if (!C2.getBoolValue()) + break; + return C1.urem(C2); + case TargetOpcode::G_SREM: + if (!C2.getBoolValue()) + break; + return C1.srem(C2); + } + } + return None; +} + +/// An MIRBuilder which does trivial constant folding of binary ops. +/// Calls to buildInstr will also try to constant fold binary ops. +class ConstantFoldingMIRBuilder + : public FoldableInstructionsBuilder<ConstantFoldingMIRBuilder> { +public: + // Pull in base class constructors. + using FoldableInstructionsBuilder< + ConstantFoldingMIRBuilder>::FoldableInstructionsBuilder; + // Unhide buildInstr + using FoldableInstructionsBuilder<ConstantFoldingMIRBuilder>::buildInstr; + + // Implement buildBinaryOp required by FoldableInstructionsBuilder which + // tries to constant fold. + MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Dst, + unsigned Src0, unsigned Src1) { + validateBinaryOp(Dst, Src0, Src1); + auto MaybeCst = ConstantFoldBinOp(Opcode, Src0, Src1, getMF().getRegInfo()); + if (MaybeCst) + return buildConstant(Dst, MaybeCst->getSExtValue()); + return buildInstr(Opcode).addDef(Dst).addUse(Src0).addUse(Src1); + } + + template <typename DstTy, typename UseArg1Ty, typename UseArg2Ty> + MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty, UseArg1Ty &&Arg1, + UseArg2Ty &&Arg2) { + unsigned Dst = getDestFromArg(Ty); + return buildInstr(Opc, Dst, getRegFromArg(std::forward<UseArg1Ty>(Arg1)), + getRegFromArg(std::forward<UseArg2Ty>(Arg2))); + } + + // Try to provide an overload for buildInstr for binary ops in order to + // constant fold. + MachineInstrBuilder buildInstr(unsigned Opc, unsigned Dst, unsigned Src0, + unsigned Src1) { + switch (Opc) { + default: + break; + case TargetOpcode::G_ADD: + case TargetOpcode::G_AND: + case TargetOpcode::G_ASHR: + case TargetOpcode::G_LSHR: + case TargetOpcode::G_MUL: + case TargetOpcode::G_OR: + case TargetOpcode::G_SHL: + case TargetOpcode::G_SUB: + case TargetOpcode::G_XOR: + case TargetOpcode::G_UDIV: + case TargetOpcode::G_SDIV: + case TargetOpcode::G_UREM: + case TargetOpcode::G_SREM: { + return buildBinaryOp(Opc, Dst, Src0, Src1); + } + } + return buildInstr(Opc).addDef(Dst).addUse(Src0).addUse(Src1); + } + + // Fallback implementation of buildInstr. + template <typename DstTy, typename... UseArgsTy> + MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty, + UseArgsTy &&... Args) { + auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty)); + addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...); + return MIB; + } +}; +} // namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 7061c014d9b7..f3553966fcdf 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -24,6 +24,7 @@ #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" #include "llvm/CodeGen/GlobalISel/Types.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/Allocator.h" #include "llvm/IR/Intrinsics.h" #include <memory> #include <utility> @@ -63,9 +64,83 @@ private: /// Interface used to lower the everything related to calls. const CallLowering *CLI; - /// Mapping of the values of the current LLVM IR function - /// to the related virtual registers. - ValueToVReg ValToVReg; + /// This class contains the mapping between the Values to vreg related data. + class ValueToVRegInfo { + public: + ValueToVRegInfo() = default; + + using VRegListT = SmallVector<unsigned, 1>; + using OffsetListT = SmallVector<uint64_t, 1>; + + using const_vreg_iterator = + DenseMap<const Value *, VRegListT *>::const_iterator; + using const_offset_iterator = + DenseMap<const Value *, OffsetListT *>::const_iterator; + + inline const_vreg_iterator vregs_end() const { return ValToVRegs.end(); } + + VRegListT *getVRegs(const Value &V) { + auto It = ValToVRegs.find(&V); + if (It != ValToVRegs.end()) + return It->second; + + return insertVRegs(V); + } + + OffsetListT *getOffsets(const Value &V) { + auto It = TypeToOffsets.find(V.getType()); + if (It != TypeToOffsets.end()) + return It->second; + + return insertOffsets(V); + } + + const_vreg_iterator findVRegs(const Value &V) const { + return ValToVRegs.find(&V); + } + + bool contains(const Value &V) const { + return ValToVRegs.find(&V) != ValToVRegs.end(); + } + + void reset() { + ValToVRegs.clear(); + TypeToOffsets.clear(); + VRegAlloc.DestroyAll(); + OffsetAlloc.DestroyAll(); + } + + private: + VRegListT *insertVRegs(const Value &V) { + assert(ValToVRegs.find(&V) == ValToVRegs.end() && "Value already exists"); + + // We placement new using our fast allocator since we never try to free + // the vectors until translation is finished. + auto *VRegList = new (VRegAlloc.Allocate()) VRegListT(); + ValToVRegs[&V] = VRegList; + return VRegList; + } + + OffsetListT *insertOffsets(const Value &V) { + assert(TypeToOffsets.find(V.getType()) == TypeToOffsets.end() && + "Type already exists"); + + auto *OffsetList = new (OffsetAlloc.Allocate()) OffsetListT(); + TypeToOffsets[V.getType()] = OffsetList; + return OffsetList; + } + SpecificBumpPtrAllocator<VRegListT> VRegAlloc; + SpecificBumpPtrAllocator<OffsetListT> OffsetAlloc; + + // We store pointers to vectors here since references may be invalidated + // while we hold them if we stored the vectors directly. + DenseMap<const Value *, VRegListT*> ValToVRegs; + DenseMap<const Type *, OffsetListT*> TypeToOffsets; + }; + + /// Mapping of the values of the current LLVM IR function to the related + /// virtual registers and offsets. + ValueToVRegInfo VMap; // N.b. it's not completely obvious that this will be sufficient for every // LLVM IR construct (with "invoke" being the obvious candidate to mess up our @@ -82,7 +157,8 @@ private: // List of stubbed PHI instructions, for values and basic blocks to be filled // in once all MachineBasicBlocks have been created. - SmallVector<std::pair<const PHINode *, MachineInstr *>, 4> PendingPHIs; + SmallVector<std::pair<const PHINode *, SmallVector<MachineInstr *, 1>>, 4> + PendingPHIs; /// Record of what frame index has been allocated to specified allocas for /// this function. @@ -99,7 +175,7 @@ private: /// The general algorithm is: /// 1. Look for a virtual register for each operand or /// create one. - /// 2 Update the ValToVReg accordingly. + /// 2 Update the VMap accordingly. /// 2.alt. For constant arguments, if they are compile time constants, /// produce an immediate in the right operand and do not touch /// ValToReg. Actually we will go with a virtual register for each @@ -134,7 +210,7 @@ private: /// Translate an LLVM string intrinsic (memcpy, memset, ...). bool translateMemfunc(const CallInst &CI, MachineIRBuilder &MIRBuilder, - unsigned Intrinsic); + unsigned ID); void getStackGuard(unsigned DstReg, MachineIRBuilder &MIRBuilder); @@ -146,6 +222,19 @@ private: bool translateInlineAsm(const CallInst &CI, MachineIRBuilder &MIRBuilder); + // FIXME: temporary function to expose previous interface to call lowering + // until it is refactored. + /// Combines all component registers of \p V into a single scalar with size + /// "max(Offsets) + last size". + unsigned packRegs(const Value &V, MachineIRBuilder &MIRBuilder); + + void unpackRegs(const Value &V, unsigned Src, MachineIRBuilder &MIRBuilder); + + /// Returns true if the value should be split into multiple LLTs. + /// If \p Offsets is given then the split type's offsets will be stored in it. + bool valueIsSplit(const Value &V, + SmallVectorImpl<uint64_t> *Offsets = nullptr); + /// Translate call instruction. /// \pre \p U is a call instruction. bool translateCall(const User &U, MachineIRBuilder &MIRBuilder); @@ -310,6 +399,9 @@ private: bool translateShuffleVector(const User &U, MachineIRBuilder &MIRBuilder); + bool translateAtomicCmpXchg(const User &U, MachineIRBuilder &MIRBuilder); + bool translateAtomicRMW(const User &U, MachineIRBuilder &MIRBuilder); + // Stubs to keep the compiler happy while we implement the rest of the // translation. bool translateResume(const User &U, MachineIRBuilder &MIRBuilder) { @@ -327,14 +419,8 @@ private: bool translateFence(const User &U, MachineIRBuilder &MIRBuilder) { return false; } - bool translateAtomicCmpXchg(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } - bool translateAtomicRMW(const User &U, MachineIRBuilder &MIRBuilder) { - return false; - } bool translateAddrSpaceCast(const User &U, MachineIRBuilder &MIRBuilder) { - return false; + return translateCast(TargetOpcode::G_ADDRSPACE_CAST, U, MIRBuilder); } bool translateCleanupPad(const User &U, MachineIRBuilder &MIRBuilder) { return false; @@ -381,9 +467,24 @@ private: // * Clear the different maps. void finalizeFunction(); - /// Get the VReg that represents \p Val. - /// If such VReg does not exist, it is created. - unsigned getOrCreateVReg(const Value &Val); + /// Get the VRegs that represent \p Val. + /// Non-aggregate types have just one corresponding VReg and the list can be + /// used as a single "unsigned". Aggregates get flattened. If such VRegs do + /// not exist, they are created. + ArrayRef<unsigned> getOrCreateVRegs(const Value &Val); + + unsigned getOrCreateVReg(const Value &Val) { + auto Regs = getOrCreateVRegs(Val); + if (Regs.empty()) + return 0; + assert(Regs.size() == 1 && + "attempt to get single VReg for aggregate or void"); + return Regs[0]; + } + + /// Allocate some vregs and offsets in the VMap. Then populate just the + /// offsets while leaving the vregs empty. + ValueToVRegInfo::VRegListT &allocateVRegs(const Value &Val); /// Get the frame index that represents \p Val. /// If such VReg does not exist, it is created. diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h index 4264a866b6c0..471def7f45a3 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h @@ -20,6 +20,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/CodeGenCoverage.h" +#include "llvm/Support/LowLevelTypeImpl.h" #include <bitset> #include <cstddef> #include <cstdint> @@ -31,7 +32,6 @@ namespace llvm { class APInt; class APFloat; -class LLT; class MachineInstr; class MachineInstrBuilder; class MachineFunction; @@ -81,6 +81,23 @@ enum { /// failed match. GIM_Try, + /// Switch over the opcode on the specified instruction + /// - InsnID - Instruction ID + /// - LowerBound - numerically minimum opcode supported + /// - UpperBound - numerically maximum + 1 opcode supported + /// - Default - failure jump target + /// - JumpTable... - (UpperBound - LowerBound) (at least 2) jump targets + GIM_SwitchOpcode, + + /// Switch over the LLT on the specified instruction operand + /// - InsnID - Instruction ID + /// - OpIdx - Operand index + /// - LowerBound - numerically minimum Type ID supported + /// - UpperBound - numerically maximum + 1 Type ID supported + /// - Default - failure jump target + /// - JumpTable... - (UpperBound - LowerBound) (at least 2) jump targets + GIM_SwitchType, + /// Record the specified instruction /// - NewInsnID - Instruction ID to define /// - InsnID - Instruction ID @@ -117,6 +134,23 @@ enum { GIM_CheckAtomicOrdering, GIM_CheckAtomicOrderingOrStrongerThan, GIM_CheckAtomicOrderingWeakerThan, + /// Check the size of the memory access for the given machine memory operand. + /// - InsnID - Instruction ID + /// - MMOIdx - MMO index + /// - Size - The size in bytes of the memory access + GIM_CheckMemorySizeEqualTo, + /// Check the size of the memory access for the given machine memory operand + /// against the size of an operand. + /// - InsnID - Instruction ID + /// - MMOIdx - MMO index + /// - OpIdx - The operand index to compare the MMO against + GIM_CheckMemorySizeEqualToLLT, + GIM_CheckMemorySizeLessThanLLT, + GIM_CheckMemorySizeGreaterThanLLT, + /// Check a generic C++ instruction predicate + /// - InsnID - Instruction ID + /// - PredicateID - The ID of the predicate function to call + GIM_CheckCxxInsnPredicate, /// Check the type for the specified operand /// - InsnID - Instruction ID @@ -133,12 +167,14 @@ enum { /// - OpIdx - Operand index /// - Expected register bank (specified as a register class) GIM_CheckRegBankForClass, + /// Check the operand matches a complex predicate /// - InsnID - Instruction ID /// - OpIdx - Operand index /// - RendererID - The renderer to hold the result /// - Complex predicate ID GIM_CheckComplexPattern, + /// Check the operand is a specific integer /// - InsnID - Instruction ID /// - OpIdx - Operand index @@ -155,6 +191,7 @@ enum { /// - OpIdx - Operand index /// - Expected Intrinsic ID GIM_CheckIntrinsicID, + /// Check the specified operand is an MBB /// - InsnID - Instruction ID /// - OpIdx - Operand index @@ -183,6 +220,7 @@ enum { /// - OldInsnID - Instruction ID to mutate /// - NewOpcode - The new opcode to use GIR_MutateOpcode, + /// Build a new instruction /// - InsnID - Instruction ID to define /// - Opcode - The new opcode to use @@ -193,6 +231,7 @@ enum { /// - OldInsnID - Instruction ID to copy from /// - OpIdx - The operand to copy GIR_Copy, + /// Copy an operand to the specified instruction or add a zero register if the /// operand is a zero immediate. /// - NewInsnID - Instruction ID to modify @@ -206,6 +245,7 @@ enum { /// - OpIdx - The operand to copy /// - SubRegIdx - The subregister to copy GIR_CopySubReg, + /// Add an implicit register def to the specified instruction /// - InsnID - Instruction ID to modify /// - RegNum - The register to add @@ -218,10 +258,13 @@ enum { /// - InsnID - Instruction ID to modify /// - RegNum - The register to add GIR_AddRegister, - /// Add a a temporary register to the specified instruction + + /// Add a temporary register to the specified instruction /// - InsnID - Instruction ID to modify /// - TempRegID - The temporary register ID to add + /// - TempRegFlags - The register flags to set GIR_AddTempRegister, + /// Add an immediate to the specified instruction /// - InsnID - Instruction ID to modify /// - Imm - The immediate to add @@ -230,11 +273,17 @@ enum { /// - InsnID - Instruction ID to modify /// - RendererID - The renderer to call GIR_ComplexRenderer, + /// Render sub-operands of complex operands to the specified instruction /// - InsnID - Instruction ID to modify /// - RendererID - The renderer to call /// - RenderOpID - The suboperand to render. GIR_ComplexSubOperandRenderer, + /// Render operands to the specified instruction using a custom function + /// - InsnID - Instruction ID to modify + /// - OldInsnID - Instruction ID to get the matched operand from + /// - RendererFnID - Custom renderer function to call + GIR_CustomRenderer, /// Render a G_CONSTANT operator as a sign-extended immediate. /// - NewInsnID - Instruction ID to modify @@ -242,24 +291,34 @@ enum { /// The operand index is implicitly 1. GIR_CopyConstantAsSImm, + /// Render a G_FCONSTANT operator as a sign-extended immediate. + /// - NewInsnID - Instruction ID to modify + /// - OldInsnID - Instruction ID to copy from + /// The operand index is implicitly 1. + GIR_CopyFConstantAsFPImm, + /// Constrain an instruction operand to a register class. /// - InsnID - Instruction ID to modify /// - OpIdx - Operand index /// - RCEnum - Register class enumeration value GIR_ConstrainOperandRC, + /// Constrain an instructions operands according to the instruction /// description. /// - InsnID - Instruction ID to modify GIR_ConstrainSelectedInstOperands, + /// Merge all memory operands into instruction. /// - InsnID - Instruction ID to modify /// - MergeInsnID... - One or more Instruction ID to merge into the result. /// - GIU_MergeMemOperands_EndOfList - Terminates the list of instructions to /// merge. GIR_MergeMemOperands, + /// Erase from parent. /// - InsnID - Instruction ID to erase GIR_EraseFromParent, + /// Create a new temporary register that's not constrained. /// - TempRegID - The temporary register ID to initialize. /// - Expected type @@ -271,6 +330,9 @@ enum { /// Increment the rule coverage counter. /// - RuleID - The ID of the rule that was covered. GIR_Coverage, + + /// Keeping track of the number of the GI opcodes. Must be the last entry. + GIU_NumOpcodes, }; enum { @@ -311,11 +373,27 @@ protected: }; public: - template <class PredicateBitset, class ComplexMatcherMemFn> - struct MatcherInfoTy { + template <class PredicateBitset, class ComplexMatcherMemFn, + class CustomRendererFn> + struct ISelInfoTy { + ISelInfoTy(const LLT *TypeObjects, size_t NumTypeObjects, + const PredicateBitset *FeatureBitsets, + const ComplexMatcherMemFn *ComplexPredicates, + const CustomRendererFn *CustomRenderers) + : TypeObjects(TypeObjects), + FeatureBitsets(FeatureBitsets), + ComplexPredicates(ComplexPredicates), + CustomRenderers(CustomRenderers) { + + for (size_t I = 0; I < NumTypeObjects; ++I) + TypeIDMap[TypeObjects[I]] = I; + } const LLT *TypeObjects; const PredicateBitset *FeatureBitsets; const ComplexMatcherMemFn *ComplexPredicates; + const CustomRendererFn *CustomRenderers; + + SmallDenseMap<LLT, unsigned, 64> TypeIDMap; }; protected: @@ -324,23 +402,35 @@ protected: /// Execute a given matcher table and return true if the match was successful /// and false otherwise. template <class TgtInstructionSelector, class PredicateBitset, - class ComplexMatcherMemFn> + class ComplexMatcherMemFn, class CustomRendererFn> bool executeMatchTable( TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State, - const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo, + const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn> + &ISelInfo, const int64_t *MatchTable, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, CodeGenCoverage &CoverageInfo) const; + virtual const int64_t *getMatchTable() const { + llvm_unreachable("Should have been overridden by tablegen if used"); + } + virtual bool testImmPredicate_I64(unsigned, int64_t) const { - llvm_unreachable("Subclasses must override this to use tablegen"); + llvm_unreachable( + "Subclasses must override this with a tablegen-erated function"); } virtual bool testImmPredicate_APInt(unsigned, const APInt &) const { - llvm_unreachable("Subclasses must override this to use tablegen"); + llvm_unreachable( + "Subclasses must override this with a tablegen-erated function"); } virtual bool testImmPredicate_APFloat(unsigned, const APFloat &) const { - llvm_unreachable("Subclasses must override this to use tablegen"); + llvm_unreachable( + "Subclasses must override this with a tablegen-erated function"); + } + virtual bool testMIPredicate_MI(unsigned, const MachineInstr &) const { + llvm_unreachable( + "Subclasses must override this with a tablegen-erated function"); } /// Constrain a register operand of an instruction \p I to a specified @@ -353,20 +443,6 @@ protected: const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const; - /// Mutate the newly-selected instruction \p I to constrain its (possibly - /// generic) virtual register operands to the instruction's register class. - /// This could involve inserting COPYs before (for uses) or after (for defs). - /// This requires the number of operands to match the instruction description. - /// \returns whether operand regclass constraining succeeded. - /// - // FIXME: Not all instructions have the same number of operands. We should - // probably expose a constrain helper per operand and let the target selector - // constrain individual registers, like fast-isel. - bool constrainSelectedInstRegOperands(MachineInstr &I, - const TargetInstrInfo &TII, - const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI) const; - bool isOperandImmEqual(const MachineOperand &MO, int64_t Value, const MachineRegisterInfo &MRI) const; diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h index bf834cf8f5e3..2003a79f6b20 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -40,19 +41,22 @@ enum { GIPFP_I64_Invalid = 0, GIPFP_APInt_Invalid = 0, GIPFP_APFloat_Invalid = 0, + GIPFP_MI_Invalid = 0, }; template <class TgtInstructionSelector, class PredicateBitset, - class ComplexMatcherMemFn> + class ComplexMatcherMemFn, class CustomRendererFn> bool InstructionSelector::executeMatchTable( TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State, - const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo, + const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn> + &ISelInfo, const int64_t *MatchTable, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, CodeGenCoverage &CoverageInfo) const { + uint64_t CurrentIdx = 0; - SmallVector<uint64_t, 8> OnFailResumeAt; + SmallVector<uint64_t, 4> OnFailResumeAt; enum RejectAction { RejectAndGiveUp, RejectAndResume }; auto handleReject = [&]() -> RejectAction { @@ -60,8 +64,7 @@ bool InstructionSelector::executeMatchTable( dbgs() << CurrentIdx << ": Rejected\n"); if (OnFailResumeAt.empty()) return RejectAndGiveUp; - CurrentIdx = OnFailResumeAt.back(); - OnFailResumeAt.pop_back(); + CurrentIdx = OnFailResumeAt.pop_back_val(); DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), dbgs() << CurrentIdx << ": Resume at " << CurrentIdx << " (" << OnFailResumeAt.size() << " try-blocks remain)\n"); @@ -70,7 +73,8 @@ bool InstructionSelector::executeMatchTable( while (true) { assert(CurrentIdx != ~0u && "Invalid MatchTable index"); - switch (MatchTable[CurrentIdx++]) { + int64_t MatcherOpcode = MatchTable[CurrentIdx++]; + switch (MatcherOpcode) { case GIM_Try: { DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), dbgs() << CurrentIdx << ": Begin try-block\n"); @@ -124,8 +128,8 @@ bool InstructionSelector::executeMatchTable( dbgs() << CurrentIdx << ": GIM_CheckFeatures(ExpectedBitsetID=" << ExpectedBitsetID << ")\n"); - if ((AvailableFeatures & MatcherInfo.FeatureBitsets[ExpectedBitsetID]) != - MatcherInfo.FeatureBitsets[ExpectedBitsetID]) { + if ((AvailableFeatures & ISelInfo.FeatureBitsets[ExpectedBitsetID]) != + ISelInfo.FeatureBitsets[ExpectedBitsetID]) { if (handleReject() == RejectAndGiveUp) return false; } @@ -136,12 +140,13 @@ bool InstructionSelector::executeMatchTable( int64_t InsnID = MatchTable[CurrentIdx++]; int64_t Expected = MatchTable[CurrentIdx++]; + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); unsigned Opcode = State.MIs[InsnID]->getOpcode(); + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID << "], ExpectedOpcode=" << Expected << ") // Got=" << Opcode << "\n"); - assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); if (Opcode != Expected) { if (handleReject() == RejectAndGiveUp) return false; @@ -149,6 +154,77 @@ bool InstructionSelector::executeMatchTable( break; } + case GIM_SwitchOpcode: { + int64_t InsnID = MatchTable[CurrentIdx++]; + int64_t LowerBound = MatchTable[CurrentIdx++]; + int64_t UpperBound = MatchTable[CurrentIdx++]; + int64_t Default = MatchTable[CurrentIdx++]; + + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + const int64_t Opcode = State.MIs[InsnID]->getOpcode(); + + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), { + dbgs() << CurrentIdx << ": GIM_SwitchOpcode(MIs[" << InsnID << "], [" + << LowerBound << ", " << UpperBound << "), Default=" << Default + << ", JumpTable...) // Got=" << Opcode << "\n"; + }); + if (Opcode < LowerBound || UpperBound <= Opcode) { + CurrentIdx = Default; + break; + } + CurrentIdx = MatchTable[CurrentIdx + (Opcode - LowerBound)]; + if (!CurrentIdx) { + CurrentIdx = Default; + break; + } + OnFailResumeAt.push_back(Default); + break; + } + + case GIM_SwitchType: { + int64_t InsnID = MatchTable[CurrentIdx++]; + int64_t OpIdx = MatchTable[CurrentIdx++]; + int64_t LowerBound = MatchTable[CurrentIdx++]; + int64_t UpperBound = MatchTable[CurrentIdx++]; + int64_t Default = MatchTable[CurrentIdx++]; + + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); + + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), { + dbgs() << CurrentIdx << ": GIM_SwitchType(MIs[" << InsnID + << "]->getOperand(" << OpIdx << "), [" << LowerBound << ", " + << UpperBound << "), Default=" << Default + << ", JumpTable...) // Got="; + if (!MO.isReg()) + dbgs() << "Not a VReg\n"; + else + dbgs() << MRI.getType(MO.getReg()) << "\n"; + }); + if (!MO.isReg()) { + CurrentIdx = Default; + break; + } + const LLT Ty = MRI.getType(MO.getReg()); + const auto TyI = ISelInfo.TypeIDMap.find(Ty); + if (TyI == ISelInfo.TypeIDMap.end()) { + CurrentIdx = Default; + break; + } + const int64_t TypeID = TyI->second; + if (TypeID < LowerBound || UpperBound <= TypeID) { + CurrentIdx = Default; + break; + } + CurrentIdx = MatchTable[CurrentIdx + (TypeID - LowerBound)]; + if (!CurrentIdx) { + CurrentIdx = Default; + break; + } + OnFailResumeAt.push_back(Default); + break; + } + case GIM_CheckNumOperands: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t Expected = MatchTable[CurrentIdx++]; @@ -194,7 +270,8 @@ bool InstructionSelector::executeMatchTable( << CurrentIdx << ": GIM_CheckAPIntImmPredicate(MIs[" << InsnID << "], Predicate=" << Predicate << ")\n"); assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - assert(State.MIs[InsnID]->getOpcode() && "Expected G_CONSTANT"); + assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT && + "Expected G_CONSTANT"); assert(Predicate > GIPFP_APInt_Invalid && "Expected a valid predicate"); APInt Value; if (State.MIs[InsnID]->getOperand(1).isCImm()) @@ -226,6 +303,21 @@ bool InstructionSelector::executeMatchTable( return false; break; } + case GIM_CheckCxxInsnPredicate: { + int64_t InsnID = MatchTable[CurrentIdx++]; + int64_t Predicate = MatchTable[CurrentIdx++]; + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), + dbgs() + << CurrentIdx << ": GIM_CheckCxxPredicate(MIs[" + << InsnID << "], Predicate=" << Predicate << ")\n"); + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + assert(Predicate > GIPFP_MI_Invalid && "Expected a valid predicate"); + + if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID])) + if (handleReject() == RejectAndGiveUp) + return false; + break; + } case GIM_CheckAtomicOrdering: { int64_t InsnID = MatchTable[CurrentIdx++]; AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++]; @@ -233,7 +325,6 @@ bool InstructionSelector::executeMatchTable( dbgs() << CurrentIdx << ": GIM_CheckAtomicOrdering(MIs[" << InsnID << "], " << (uint64_t)Ordering << ")\n"); assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (!State.MIs[InsnID]->hasOneMemOperand()) if (handleReject() == RejectAndGiveUp) return false; @@ -252,7 +343,6 @@ bool InstructionSelector::executeMatchTable( << ": GIM_CheckAtomicOrderingOrStrongerThan(MIs[" << InsnID << "], " << (uint64_t)Ordering << ")\n"); assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (!State.MIs[InsnID]->hasOneMemOperand()) if (handleReject() == RejectAndGiveUp) return false; @@ -271,7 +361,6 @@ bool InstructionSelector::executeMatchTable( << ": GIM_CheckAtomicOrderingWeakerThan(MIs[" << InsnID << "], " << (uint64_t)Ordering << ")\n"); assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (!State.MIs[InsnID]->hasOneMemOperand()) if (handleReject() == RejectAndGiveUp) return false; @@ -282,6 +371,87 @@ bool InstructionSelector::executeMatchTable( return false; break; } + case GIM_CheckMemorySizeEqualTo: { + int64_t InsnID = MatchTable[CurrentIdx++]; + int64_t MMOIdx = MatchTable[CurrentIdx++]; + uint64_t Size = MatchTable[CurrentIdx++]; + + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), + dbgs() << CurrentIdx + << ": GIM_CheckMemorySizeEqual(MIs[" << InsnID + << "]->memoperands() + " << MMOIdx + << ", Size=" << Size << ")\n"); + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + + if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { + if (handleReject() == RejectAndGiveUp) + return false; + break; + } + + MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); + + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), + dbgs() << MMO->getSize() << " bytes vs " << Size + << " bytes\n"); + if (MMO->getSize() != Size) + if (handleReject() == RejectAndGiveUp) + return false; + + break; + } + case GIM_CheckMemorySizeEqualToLLT: + case GIM_CheckMemorySizeLessThanLLT: + case GIM_CheckMemorySizeGreaterThanLLT: { + int64_t InsnID = MatchTable[CurrentIdx++]; + int64_t MMOIdx = MatchTable[CurrentIdx++]; + int64_t OpIdx = MatchTable[CurrentIdx++]; + + DEBUG_WITH_TYPE( + TgtInstructionSelector::getName(), + dbgs() << CurrentIdx << ": GIM_CheckMemorySize" + << (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT + ? "EqualTo" + : MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT + ? "GreaterThan" + : "LessThan") + << "LLT(MIs[" << InsnID << "]->memoperands() + " << MMOIdx + << ", OpIdx=" << OpIdx << ")\n"); + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + + MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); + if (!MO.isReg()) { + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), + dbgs() << CurrentIdx << ": Not a register\n"); + if (handleReject() == RejectAndGiveUp) + return false; + break; + } + + if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { + if (handleReject() == RejectAndGiveUp) + return false; + break; + } + + MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); + + unsigned Size = MRI.getType(MO.getReg()).getSizeInBits(); + if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT && + MMO->getSize() * 8 != Size) { + if (handleReject() == RejectAndGiveUp) + return false; + } else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT && + MMO->getSize() * 8 >= Size) { + if (handleReject() == RejectAndGiveUp) + return false; + } else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT && + MMO->getSize() * 8 <= Size) + if (handleReject() == RejectAndGiveUp) + return false; + + break; + } case GIM_CheckType: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t OpIdx = MatchTable[CurrentIdx++]; @@ -291,8 +461,9 @@ bool InstructionSelector::executeMatchTable( << "]->getOperand(" << OpIdx << "), TypeID=" << TypeID << ")\n"); assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (MRI.getType(State.MIs[InsnID]->getOperand(OpIdx).getReg()) != - MatcherInfo.TypeObjects[TypeID]) { + MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); + if (!MO.isReg() || + MRI.getType(MO.getReg()) != ISelInfo.TypeObjects[TypeID]) { if (handleReject() == RejectAndGiveUp) return false; } @@ -308,7 +479,6 @@ bool InstructionSelector::executeMatchTable( << InsnID << "]->getOperand(" << OpIdx << "), SizeInBits=" << SizeInBits << ")\n"); assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - // iPTR must be looked up in the target. if (SizeInBits == 0) { MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent(); @@ -317,11 +487,15 @@ bool InstructionSelector::executeMatchTable( assert(SizeInBits != 0 && "Pointer size must be known"); - const LLT &Ty = MRI.getType(State.MIs[InsnID]->getOperand(OpIdx).getReg()); - if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits) { - if (handleReject() == RejectAndGiveUp) - return false; - } + MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); + if (MO.isReg()) { + const LLT &Ty = MRI.getType(MO.getReg()); + if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits) + if (handleReject() == RejectAndGiveUp) + return false; + } else if (handleReject() == RejectAndGiveUp) + return false; + break; } case GIM_CheckRegBankForClass: { @@ -333,9 +507,10 @@ bool InstructionSelector::executeMatchTable( << InsnID << "]->getOperand(" << OpIdx << "), RCEnum=" << RCEnum << ")\n"); assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); - if (&RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum)) != - RBI.getRegBank(State.MIs[InsnID]->getOperand(OpIdx).getReg(), MRI, - TRI)) { + MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); + if (!MO.isReg() || + &RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum)) != + RBI.getRegBank(MO.getReg(), MRI, TRI)) { if (handleReject() == RejectAndGiveUp) return false; } @@ -356,7 +531,7 @@ bool InstructionSelector::executeMatchTable( assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); // FIXME: Use std::invoke() when it's available. ComplexRendererFns Renderer = - (ISel.*MatcherInfo.ComplexPredicates[ComplexPredicateID])( + (ISel.*ISelInfo.ComplexPredicates[ComplexPredicateID])( State.MIs[InsnID]->getOperand(OpIdx)); if (Renderer.hasValue()) State.Renderers[RendererID] = Renderer.getValue(); @@ -375,16 +550,19 @@ bool InstructionSelector::executeMatchTable( << InsnID << "]->getOperand(" << OpIdx << "), Value=" << Value << ")\n"); assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); + if (MO.isReg()) { + // isOperandImmEqual() will sign-extend to 64-bits, so should we. + LLT Ty = MRI.getType(MO.getReg()); + Value = SignExtend64(Value, Ty.getSizeInBits()); - // isOperandImmEqual() will sign-extend to 64-bits, so should we. - LLT Ty = MRI.getType(State.MIs[InsnID]->getOperand(OpIdx).getReg()); - Value = SignExtend64(Value, Ty.getSizeInBits()); + if (!isOperandImmEqual(MO, Value, MRI)) { + if (handleReject() == RejectAndGiveUp) + return false; + } + } else if (handleReject() == RejectAndGiveUp) + return false; - if (!isOperandImmEqual(State.MIs[InsnID]->getOperand(OpIdx), Value, - MRI)) { - if (handleReject() == RejectAndGiveUp) - return false; - } break; } @@ -467,7 +645,7 @@ bool InstructionSelector::executeMatchTable( } case GIM_Reject: DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIM_Reject"); + dbgs() << CurrentIdx << ": GIM_Reject\n"); if (handleReject() == RejectAndGiveUp) return false; break; @@ -649,6 +827,36 @@ bool InstructionSelector::executeMatchTable( break; } + // TODO: Needs a test case once we have a pattern that uses this. + case GIR_CopyFConstantAsFPImm: { + int64_t NewInsnID = MatchTable[CurrentIdx++]; + int64_t OldInsnID = MatchTable[CurrentIdx++]; + assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); + assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT && "Expected G_FCONSTANT"); + if (State.MIs[OldInsnID]->getOperand(1).isFPImm()) + OutMIs[NewInsnID].addFPImm( + State.MIs[OldInsnID]->getOperand(1).getFPImm()); + else + llvm_unreachable("Expected FPImm operand"); + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), + dbgs() << CurrentIdx << ": GIR_CopyFPConstantAsFPImm(OutMIs[" + << NewInsnID << "], MIs[" << OldInsnID << "])\n"); + break; + } + + case GIR_CustomRenderer: { + int64_t InsnID = MatchTable[CurrentIdx++]; + int64_t OldInsnID = MatchTable[CurrentIdx++]; + int64_t RendererFnID = MatchTable[CurrentIdx++]; + assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); + DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), + dbgs() << CurrentIdx << ": GIR_CustomRenderer(OutMIs[" + << InsnID << "], MIs[" << OldInsnID << "], " + << RendererFnID << ")\n"); + (ISel.*ISelInfo.CustomRenderers[RendererFnID])(OutMIs[InsnID], + *State.MIs[OldInsnID]); + break; + } case GIR_ConstrainOperandRC: { int64_t InsnID = MatchTable[CurrentIdx++]; int64_t OpIdx = MatchTable[CurrentIdx++]; @@ -710,7 +918,7 @@ bool InstructionSelector::executeMatchTable( int64_t TypeID = MatchTable[CurrentIdx++]; State.TempRegisters[TempRegID] = - MRI.createGenericVirtualRegister(MatcherInfo.TypeObjects[TypeID]); + MRI.createGenericVirtualRegister(ISelInfo.TypeObjects[TypeID]); DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), dbgs() << CurrentIdx << ": TempRegs[" << TempRegID << "] = GIR_MakeTempReg(" << TypeID << ")\n"); @@ -729,7 +937,7 @@ bool InstructionSelector::executeMatchTable( case GIR_Done: DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), - dbgs() << CurrentIdx << ": GIR_Done"); + dbgs() << CurrentIdx << ": GIR_Done\n"); return true; default: diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h index e7945ff5bf4f..873587651efd 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -38,7 +38,7 @@ public: return false; if (MachineInstr *DefMI = getOpcodeDef(TargetOpcode::G_TRUNC, MI.getOperand(1).getReg(), MRI)) { - DEBUG(dbgs() << ".. Combine MI: " << MI;); + LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); unsigned DstReg = MI.getOperand(0).getReg(); unsigned SrcReg = DefMI->getOperand(1).getReg(); Builder.setInstr(MI); @@ -59,10 +59,10 @@ public: MI.getOperand(1).getReg(), MRI)) { unsigned DstReg = MI.getOperand(0).getReg(); LLT DstTy = MRI.getType(DstReg); - if (isInstUnsupported(TargetOpcode::G_AND, DstTy) || - isInstUnsupported(TargetOpcode::G_CONSTANT, DstTy)) + if (isInstUnsupported({TargetOpcode::G_AND, {DstTy}}) || + isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) return false; - DEBUG(dbgs() << ".. Combine MI: " << MI;); + LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); Builder.setInstr(MI); unsigned ZExtSrc = MI.getOperand(1).getReg(); LLT ZExtSrcTy = MRI.getType(ZExtSrc); @@ -87,11 +87,11 @@ public: MI.getOperand(1).getReg(), MRI)) { unsigned DstReg = MI.getOperand(0).getReg(); LLT DstTy = MRI.getType(DstReg); - if (isInstUnsupported(TargetOpcode::G_SHL, DstTy) || - isInstUnsupported(TargetOpcode::G_ASHR, DstTy) || - isInstUnsupported(TargetOpcode::G_CONSTANT, DstTy)) + if (isInstUnsupported({TargetOpcode::G_SHL, {DstTy}}) || + isInstUnsupported({TargetOpcode::G_ASHR, {DstTy}}) || + isInstUnsupported({TargetOpcode::G_CONSTANT, {DstTy}})) return false; - DEBUG(dbgs() << ".. Combine MI: " << MI;); + LLVM_DEBUG(dbgs() << ".. Combine MI: " << MI;); Builder.setInstr(MI); unsigned SExtSrc = MI.getOperand(1).getReg(); LLT SExtSrcTy = MRI.getType(SExtSrc); @@ -121,9 +121,9 @@ public: MI.getOperand(1).getReg(), MRI)) { unsigned DstReg = MI.getOperand(0).getReg(); LLT DstTy = MRI.getType(DstReg); - if (isInstUnsupported(TargetOpcode::G_IMPLICIT_DEF, DstTy)) + if (isInstUnsupported({TargetOpcode::G_IMPLICIT_DEF, {DstTy}})) return false; - DEBUG(dbgs() << ".. Combine EXT(IMPLICIT_DEF) " << MI;); + LLVM_DEBUG(dbgs() << ".. Combine EXT(IMPLICIT_DEF) " << MI;); Builder.setInstr(MI); Builder.buildInstr(TargetOpcode::G_IMPLICIT_DEF, DstReg); markInstAndDefDead(MI, *DefMI, DeadInsts); @@ -139,9 +139,9 @@ public: return false; unsigned NumDefs = MI.getNumOperands() - 1; - unsigned SrcReg = MI.getOperand(NumDefs).getReg(); - MachineInstr *MergeI = MRI.getVRegDef(SrcReg); - if (!MergeI || (MergeI->getOpcode() != TargetOpcode::G_MERGE_VALUES)) + MachineInstr *MergeI = getOpcodeDef(TargetOpcode::G_MERGE_VALUES, + MI.getOperand(NumDefs).getReg(), MRI); + if (!MergeI) return false; const unsigned NumMergeRegs = MergeI->getNumOperands() - 1; @@ -253,11 +253,8 @@ private: // and as a result, %3, %2, %1 are dead. MachineInstr *PrevMI = &MI; while (PrevMI != &DefMI) { - // If we're dealing with G_UNMERGE_VALUES, tryCombineMerges doesn't really try - // to fold copies in between and we can ignore them here. - if (PrevMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) - break; - unsigned PrevRegSrc = PrevMI->getOperand(1).getReg(); + unsigned PrevRegSrc = + PrevMI->getOperand(PrevMI->getNumOperands() - 1).getReg(); MachineInstr *TmpDef = MRI.getVRegDef(PrevRegSrc); if (MRI.hasOneUse(PrevRegSrc)) { if (TmpDef != &DefMI) { @@ -269,18 +266,16 @@ private: break; PrevMI = TmpDef; } - if ((PrevMI == &DefMI || - DefMI.getOpcode() == TargetOpcode::G_MERGE_VALUES) && - MRI.hasOneUse(DefMI.getOperand(0).getReg())) + if (PrevMI == &DefMI && MRI.hasOneUse(DefMI.getOperand(0).getReg())) DeadInsts.push_back(&DefMI); } /// Checks if the target legalizer info has specified anything about the /// instruction, or if unsupported. - bool isInstUnsupported(unsigned Opcode, const LLT &DstTy) const { - auto Action = LI.getAction({Opcode, 0, DstTy}); - return Action.first == LegalizerInfo::LegalizeAction::Unsupported || - Action.first == LegalizerInfo::LegalizeAction::NotFound; + bool isInstUnsupported(const LegalityQuery &Query) const { + using namespace LegalizeActions; + auto Step = LI.getAction(Query); + return Step.Action == Unsupported || Step.Action == NotFound; } }; diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 8bd8a9dcd0e2..d122e67b87b8 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -93,12 +93,24 @@ public: const LegalizerInfo &getLegalizerInfo() const { return LI; } private: + /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a + /// Use by extending the operand's type to \p WideTy using the specified \p + /// ExtOpcode for the extension instruction, and replacing the vreg of the + /// operand in place. + void widenScalarSrc(MachineInstr &MI, LLT WideTy, unsigned OpIdx, + unsigned ExtOpcode); + + /// Legalize a single operand \p OpIdx of the machine instruction \p MI as a + /// Def by extending the operand's type to \p WideTy and truncating it back + /// with the \p TruncOpcode, and replacing the vreg of the operand in place. + void widenScalarDst(MachineInstr &MI, LLT WideTy, unsigned OpIdx = 0, + unsigned TruncOpcode = TargetOpcode::G_TRUNC); /// Helper function to split a wide generic register into bitwise blocks with /// the given Type (which implies the number of blocks needed). The generic /// registers created are appended to Ops, starting at bit 0 of Reg. void extractParts(unsigned Reg, LLT Ty, int NumParts, - SmallVectorImpl<unsigned> &Ops); + SmallVectorImpl<unsigned> &VRegs); MachineRegisterInfo &MRI; const LegalizerInfo &LI; diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h index b6735d538b37..713d72eb4c9b 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -19,8 +19,11 @@ #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/LowLevelTypeImpl.h" #include <cassert> #include <cstdint> @@ -30,9 +33,67 @@ namespace llvm { +extern cl::opt<bool> DisableGISelLegalityCheck; + class MachineInstr; class MachineIRBuilder; class MachineRegisterInfo; +class MCInstrInfo; + +namespace LegalizeActions { +enum LegalizeAction : std::uint8_t { + /// The operation is expected to be selectable directly by the target, and + /// no transformation is necessary. + Legal, + + /// The operation should be synthesized from multiple instructions acting on + /// a narrower scalar base-type. For example a 64-bit add might be + /// implemented in terms of 32-bit add-with-carry. + NarrowScalar, + + /// The operation should be implemented in terms of a wider scalar + /// base-type. For example a <2 x s8> add could be implemented as a <2 + /// x s32> add (ignoring the high bits). + WidenScalar, + + /// The (vector) operation should be implemented by splitting it into + /// sub-vectors where the operation is legal. For example a <8 x s64> add + /// might be implemented as 4 separate <2 x s64> adds. + FewerElements, + + /// The (vector) operation should be implemented by widening the input + /// vector and ignoring the lanes added by doing so. For example <2 x i8> is + /// rarely legal, but you might perform an <8 x i8> and then only look at + /// the first two results. + MoreElements, + + /// The operation itself must be expressed in terms of simpler actions on + /// this target. E.g. a SREM replaced by an SDIV and subtraction. + Lower, + + /// The operation should be implemented as a call to some kind of runtime + /// support library. For example this usually happens on machines that don't + /// support floating-point operations natively. + Libcall, + + /// The target wants to do something special with this combination of + /// operand and type. A callback will be issued when it is needed. + Custom, + + /// This operation is completely unsupported on the target. A programming + /// error has occurred. + Unsupported, + + /// Sentinel value for when no action was found in the specified table. + NotFound, + + /// Fall back onto the old rules. + /// TODO: Remove this once we've migrated + UseLegacyRules, +}; +} // end namespace LegalizeActions + +using LegalizeActions::LegalizeAction; /// Legalization is decided based on an instruction's opcode, which type slot /// we're considering, and what the existing type is. These aspects are gathered @@ -51,64 +112,642 @@ struct InstrAspect { } }; -class LegalizerInfo { -public: - enum LegalizeAction : std::uint8_t { - /// The operation is expected to be selectable directly by the target, and - /// no transformation is necessary. - Legal, +/// The LegalityQuery object bundles together all the information that's needed +/// to decide whether a given operation is legal or not. +/// For efficiency, it doesn't make a copy of Types so care must be taken not +/// to free it before using the query. +struct LegalityQuery { + unsigned Opcode; + ArrayRef<LLT> Types; + + struct MemDesc { + uint64_t Size; + AtomicOrdering Ordering; + }; - /// The operation should be synthesized from multiple instructions acting on - /// a narrower scalar base-type. For example a 64-bit add might be - /// implemented in terms of 32-bit add-with-carry. - NarrowScalar, + /// Operations which require memory can use this to place requirements on the + /// memory type for each MMO. + ArrayRef<MemDesc> MMODescrs; - /// The operation should be implemented in terms of a wider scalar - /// base-type. For example a <2 x s8> add could be implemented as a <2 - /// x s32> add (ignoring the high bits). - WidenScalar, + constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types, + const ArrayRef<MemDesc> MMODescrs) + : Opcode(Opcode), Types(Types), MMODescrs(MMODescrs) {} + constexpr LegalityQuery(unsigned Opcode, const ArrayRef<LLT> Types) + : LegalityQuery(Opcode, Types, {}) {} - /// The (vector) operation should be implemented by splitting it into - /// sub-vectors where the operation is legal. For example a <8 x s64> add - /// might be implemented as 4 separate <2 x s64> adds. - FewerElements, + raw_ostream &print(raw_ostream &OS) const; +}; - /// The (vector) operation should be implemented by widening the input - /// vector and ignoring the lanes added by doing so. For example <2 x i8> is - /// rarely legal, but you might perform an <8 x i8> and then only look at - /// the first two results. - MoreElements, +/// The result of a query. It either indicates a final answer of Legal or +/// Unsupported or describes an action that must be taken to make an operation +/// more legal. +struct LegalizeActionStep { + /// The action to take or the final answer. + LegalizeAction Action; + /// If describing an action, the type index to change. Otherwise zero. + unsigned TypeIdx; + /// If describing an action, the new type for TypeIdx. Otherwise LLT{}. + LLT NewType; - /// The operation itself must be expressed in terms of simpler actions on - /// this target. E.g. a SREM replaced by an SDIV and subtraction. - Lower, + LegalizeActionStep(LegalizeAction Action, unsigned TypeIdx, + const LLT &NewType) + : Action(Action), TypeIdx(TypeIdx), NewType(NewType) {} - /// The operation should be implemented as a call to some kind of runtime - /// support library. For example this usually happens on machines that don't - /// support floating-point operations natively. - Libcall, + bool operator==(const LegalizeActionStep &RHS) const { + return std::tie(Action, TypeIdx, NewType) == + std::tie(RHS.Action, RHS.TypeIdx, RHS.NewType); + } +}; - /// The target wants to do something special with this combination of - /// operand and type. A callback will be issued when it is needed. - Custom, +using LegalityPredicate = std::function<bool (const LegalityQuery &)>; +using LegalizeMutation = + std::function<std::pair<unsigned, LLT>(const LegalityQuery &)>; - /// This operation is completely unsupported on the target. A programming - /// error has occurred. - Unsupported, +namespace LegalityPredicates { +struct TypePairAndMemSize { + LLT Type0; + LLT Type1; + uint64_t MemSize; + + bool operator==(const TypePairAndMemSize &Other) const { + return Type0 == Other.Type0 && Type1 == Other.Type1 && + MemSize == Other.MemSize; + } +}; - /// Sentinel value for when no action was found in the specified table. - NotFound, +/// True iff P0 and P1 are true. +template<typename Predicate> +Predicate all(Predicate P0, Predicate P1) { + return [=](const LegalityQuery &Query) { + return P0(Query) && P1(Query); }; +} +/// True iff all given predicates are true. +template<typename Predicate, typename... Args> +Predicate all(Predicate P0, Predicate P1, Args... args) { + return all(all(P0, P1), args...); +} +/// True iff the given type index is the specified types. +LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit); +/// True iff the given type index is one of the specified types. +LegalityPredicate typeInSet(unsigned TypeIdx, + std::initializer_list<LLT> TypesInit); +/// True iff the given types for the given pair of type indexes is one of the +/// specified type pairs. +LegalityPredicate +typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1, + std::initializer_list<std::pair<LLT, LLT>> TypesInit); +/// True iff the given types for the given pair of type indexes is one of the +/// specified type pairs. +LegalityPredicate typePairAndMemSizeInSet( + unsigned TypeIdx0, unsigned TypeIdx1, unsigned MMOIdx, + std::initializer_list<TypePairAndMemSize> TypesAndMemSizeInit); +/// True iff the specified type index is a scalar. +LegalityPredicate isScalar(unsigned TypeIdx); +/// True iff the specified type index is a scalar that's narrower than the given +/// size. +LegalityPredicate narrowerThan(unsigned TypeIdx, unsigned Size); +/// True iff the specified type index is a scalar that's wider than the given +/// size. +LegalityPredicate widerThan(unsigned TypeIdx, unsigned Size); +/// True iff the specified type index is a scalar whose size is not a power of +/// 2. +LegalityPredicate sizeNotPow2(unsigned TypeIdx); +/// True iff the specified MMO index has a size that is not a power of 2 +LegalityPredicate memSizeInBytesNotPow2(unsigned MMOIdx); +/// True iff the specified type index is a vector whose element count is not a +/// power of 2. +LegalityPredicate numElementsNotPow2(unsigned TypeIdx); +/// True iff the specified MMO index has at an atomic ordering of at Ordering or +/// stronger. +LegalityPredicate atomicOrderingAtLeastOrStrongerThan(unsigned MMOIdx, + AtomicOrdering Ordering); +} // end namespace LegalityPredicates + +namespace LegalizeMutations { +/// Select this specific type for the given type index. +LegalizeMutation changeTo(unsigned TypeIdx, LLT Ty); +/// Keep the same type as the given type index. +LegalizeMutation changeTo(unsigned TypeIdx, unsigned FromTypeIdx); +/// Widen the type for the given type index to the next power of 2. +LegalizeMutation widenScalarToNextPow2(unsigned TypeIdx, unsigned Min = 0); +/// Add more elements to the type for the given type index to the next power of +/// 2. +LegalizeMutation moreElementsToNextPow2(unsigned TypeIdx, unsigned Min = 0); +} // end namespace LegalizeMutations + +/// A single rule in a legalizer info ruleset. +/// The specified action is chosen when the predicate is true. Where appropriate +/// for the action (e.g. for WidenScalar) the new type is selected using the +/// given mutator. +class LegalizeRule { + LegalityPredicate Predicate; + LegalizeAction Action; + LegalizeMutation Mutation; + +public: + LegalizeRule(LegalityPredicate Predicate, LegalizeAction Action, + LegalizeMutation Mutation = nullptr) + : Predicate(Predicate), Action(Action), Mutation(Mutation) {} + + /// Test whether the LegalityQuery matches. + bool match(const LegalityQuery &Query) const { + return Predicate(Query); + } + + LegalizeAction getAction() const { return Action; } + + /// Determine the change to make. + std::pair<unsigned, LLT> determineMutation(const LegalityQuery &Query) const { + if (Mutation) + return Mutation(Query); + return std::make_pair(0, LLT{}); + } +}; + +class LegalizeRuleSet { + /// When non-zero, the opcode we are an alias of + unsigned AliasOf; + /// If true, there is another opcode that aliases this one + bool IsAliasedByAnother; + SmallVector<LegalizeRule, 2> Rules; + +#ifndef NDEBUG + /// If bit I is set, this rule set contains a rule that may handle (predicate + /// or perform an action upon (or both)) the type index I. The uncertainty + /// comes from free-form rules executing user-provided lambda functions. We + /// conservatively assume such rules do the right thing and cover all type + /// indices. The bitset is intentionally 1 bit wider than it absolutely needs + /// to be to distinguish such cases from the cases where all type indices are + /// individually handled. + SmallBitVector TypeIdxsCovered{MCOI::OPERAND_LAST_GENERIC - + MCOI::OPERAND_FIRST_GENERIC + 2}; +#endif + + unsigned typeIdx(unsigned TypeIdx) { + assert(TypeIdx <= + (MCOI::OPERAND_LAST_GENERIC - MCOI::OPERAND_FIRST_GENERIC) && + "Type Index is out of bounds"); +#ifndef NDEBUG + TypeIdxsCovered.set(TypeIdx); +#endif + return TypeIdx; + } + void markAllTypeIdxsAsCovered() { +#ifndef NDEBUG + TypeIdxsCovered.set(); +#endif + } + + void add(const LegalizeRule &Rule) { + assert(AliasOf == 0 && + "RuleSet is aliased, change the representative opcode instead"); + Rules.push_back(Rule); + } + + static bool always(const LegalityQuery &) { return true; } + + /// Use the given action when the predicate is true. + /// Action should not be an action that requires mutation. + LegalizeRuleSet &actionIf(LegalizeAction Action, + LegalityPredicate Predicate) { + add({Predicate, Action}); + return *this; + } + /// Use the given action when the predicate is true. + /// Action should be an action that requires mutation. + LegalizeRuleSet &actionIf(LegalizeAction Action, LegalityPredicate Predicate, + LegalizeMutation Mutation) { + add({Predicate, Action, Mutation}); + return *this; + } + /// Use the given action when type index 0 is any type in the given list. + /// Action should not be an action that requires mutation. + LegalizeRuleSet &actionFor(LegalizeAction Action, + std::initializer_list<LLT> Types) { + using namespace LegalityPredicates; + return actionIf(Action, typeInSet(typeIdx(0), Types)); + } + /// Use the given action when type index 0 is any type in the given list. + /// Action should be an action that requires mutation. + LegalizeRuleSet &actionFor(LegalizeAction Action, + std::initializer_list<LLT> Types, + LegalizeMutation Mutation) { + using namespace LegalityPredicates; + return actionIf(Action, typeInSet(typeIdx(0), Types), Mutation); + } + /// Use the given action when type indexes 0 and 1 is any type pair in the + /// given list. + /// Action should not be an action that requires mutation. + LegalizeRuleSet &actionFor(LegalizeAction Action, + std::initializer_list<std::pair<LLT, LLT>> Types) { + using namespace LegalityPredicates; + return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types)); + } + /// Use the given action when type indexes 0 and 1 is any type pair in the + /// given list. + /// Action should be an action that requires mutation. + LegalizeRuleSet &actionFor(LegalizeAction Action, + std::initializer_list<std::pair<LLT, LLT>> Types, + LegalizeMutation Mutation) { + using namespace LegalityPredicates; + return actionIf(Action, typePairInSet(typeIdx(0), typeIdx(1), Types), + Mutation); + } + /// Use the given action when type indexes 0 and 1 are both in the given list. + /// That is, the type pair is in the cartesian product of the list. + /// Action should not be an action that requires mutation. + LegalizeRuleSet &actionForCartesianProduct(LegalizeAction Action, + std::initializer_list<LLT> Types) { + using namespace LegalityPredicates; + return actionIf(Action, all(typeInSet(typeIdx(0), Types), + typeInSet(typeIdx(1), Types))); + } + /// Use the given action when type indexes 0 and 1 are both in their + /// respective lists. + /// That is, the type pair is in the cartesian product of the lists + /// Action should not be an action that requires mutation. + LegalizeRuleSet & + actionForCartesianProduct(LegalizeAction Action, + std::initializer_list<LLT> Types0, + std::initializer_list<LLT> Types1) { + using namespace LegalityPredicates; + return actionIf(Action, all(typeInSet(typeIdx(0), Types0), + typeInSet(typeIdx(1), Types1))); + } + /// Use the given action when type indexes 0, 1, and 2 are all in their + /// respective lists. + /// That is, the type triple is in the cartesian product of the lists + /// Action should not be an action that requires mutation. + LegalizeRuleSet &actionForCartesianProduct( + LegalizeAction Action, std::initializer_list<LLT> Types0, + std::initializer_list<LLT> Types1, std::initializer_list<LLT> Types2) { + using namespace LegalityPredicates; + return actionIf(Action, all(typeInSet(typeIdx(0), Types0), + all(typeInSet(typeIdx(1), Types1), + typeInSet(typeIdx(2), Types2)))); + } + +public: + LegalizeRuleSet() : AliasOf(0), IsAliasedByAnother(false), Rules() {} + + bool isAliasedByAnother() { return IsAliasedByAnother; } + void setIsAliasedByAnother() { IsAliasedByAnother = true; } + void aliasTo(unsigned Opcode) { + assert((AliasOf == 0 || AliasOf == Opcode) && + "Opcode is already aliased to another opcode"); + assert(Rules.empty() && "Aliasing will discard rules"); + AliasOf = Opcode; + } + unsigned getAlias() const { return AliasOf; } + + /// The instruction is legal if predicate is true. + LegalizeRuleSet &legalIf(LegalityPredicate Predicate) { + // We have no choice but conservatively assume that the free-form + // user-provided Predicate properly handles all type indices: + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::Legal, Predicate); + } + /// The instruction is legal when type index 0 is any type in the given list. + LegalizeRuleSet &legalFor(std::initializer_list<LLT> Types) { + return actionFor(LegalizeAction::Legal, Types); + } + /// The instruction is legal when type indexes 0 and 1 is any type pair in the + /// given list. + LegalizeRuleSet &legalFor(std::initializer_list<std::pair<LLT, LLT>> Types) { + return actionFor(LegalizeAction::Legal, Types); + } + /// The instruction is legal when type indexes 0 and 1 along with the memory + /// size is any type and size tuple in the given list. + LegalizeRuleSet &legalForTypesWithMemSize( + std::initializer_list<LegalityPredicates::TypePairAndMemSize> + TypesAndMemSize) { + return actionIf(LegalizeAction::Legal, + LegalityPredicates::typePairAndMemSizeInSet( + typeIdx(0), typeIdx(1), /*MMOIdx*/ 0, TypesAndMemSize)); + } + /// The instruction is legal when type indexes 0 and 1 are both in the given + /// list. That is, the type pair is in the cartesian product of the list. + LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types) { + return actionForCartesianProduct(LegalizeAction::Legal, Types); + } + /// The instruction is legal when type indexes 0 and 1 are both their + /// respective lists. + LegalizeRuleSet &legalForCartesianProduct(std::initializer_list<LLT> Types0, + std::initializer_list<LLT> Types1) { + return actionForCartesianProduct(LegalizeAction::Legal, Types0, Types1); + } + + /// The instruction is lowered. + LegalizeRuleSet &lower() { + using namespace LegalizeMutations; + // We have no choice but conservatively assume that predicate-less lowering + // properly handles all type indices by design: + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::Lower, always); + } + /// The instruction is lowered if predicate is true. Keep type index 0 as the + /// same type. + LegalizeRuleSet &lowerIf(LegalityPredicate Predicate) { + using namespace LegalizeMutations; + // We have no choice but conservatively assume that lowering with a + // free-form user provided Predicate properly handles all type indices: + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::Lower, Predicate); + } + /// The instruction is lowered if predicate is true. + LegalizeRuleSet &lowerIf(LegalityPredicate Predicate, + LegalizeMutation Mutation) { + // We have no choice but conservatively assume that lowering with a + // free-form user provided Predicate properly handles all type indices: + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::Lower, Predicate, Mutation); + } + /// The instruction is lowered when type index 0 is any type in the given + /// list. Keep type index 0 as the same type. + LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types) { + return actionFor(LegalizeAction::Lower, Types, + LegalizeMutations::changeTo(0, 0)); + } + /// The instruction is lowered when type index 0 is any type in the given + /// list. + LegalizeRuleSet &lowerFor(std::initializer_list<LLT> Types, + LegalizeMutation Mutation) { + return actionFor(LegalizeAction::Lower, Types, Mutation); + } + /// The instruction is lowered when type indexes 0 and 1 is any type pair in + /// the given list. Keep type index 0 as the same type. + LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types) { + return actionFor(LegalizeAction::Lower, Types, + LegalizeMutations::changeTo(0, 0)); + } + /// The instruction is lowered when type indexes 0 and 1 is any type pair in + /// the given list. + LegalizeRuleSet &lowerFor(std::initializer_list<std::pair<LLT, LLT>> Types, + LegalizeMutation Mutation) { + return actionFor(LegalizeAction::Lower, Types, Mutation); + } + /// The instruction is lowered when type indexes 0 and 1 are both in their + /// respective lists. + LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0, + std::initializer_list<LLT> Types1) { + using namespace LegalityPredicates; + return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1); + } + /// The instruction is lowered when when type indexes 0, 1, and 2 are all in + /// their respective lists. + LegalizeRuleSet &lowerForCartesianProduct(std::initializer_list<LLT> Types0, + std::initializer_list<LLT> Types1, + std::initializer_list<LLT> Types2) { + using namespace LegalityPredicates; + return actionForCartesianProduct(LegalizeAction::Lower, Types0, Types1, + Types2); + } + + /// Like legalIf, but for the Libcall action. + LegalizeRuleSet &libcallIf(LegalityPredicate Predicate) { + // We have no choice but conservatively assume that a libcall with a + // free-form user provided Predicate properly handles all type indices: + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::Libcall, Predicate); + } + LegalizeRuleSet &libcallFor(std::initializer_list<LLT> Types) { + return actionFor(LegalizeAction::Libcall, Types); + } + LegalizeRuleSet & + libcallFor(std::initializer_list<std::pair<LLT, LLT>> Types) { + return actionFor(LegalizeAction::Libcall, Types); + } + LegalizeRuleSet & + libcallForCartesianProduct(std::initializer_list<LLT> Types) { + return actionForCartesianProduct(LegalizeAction::Libcall, Types); + } + LegalizeRuleSet & + libcallForCartesianProduct(std::initializer_list<LLT> Types0, + std::initializer_list<LLT> Types1) { + return actionForCartesianProduct(LegalizeAction::Libcall, Types0, Types1); + } + + /// Widen the scalar to the one selected by the mutation if the predicate is + /// true. + LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate, + LegalizeMutation Mutation) { + // We have no choice but conservatively assume that an action with a + // free-form user provided Predicate properly handles all type indices: + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::WidenScalar, Predicate, Mutation); + } + /// Narrow the scalar to the one selected by the mutation if the predicate is + /// true. + LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate, + LegalizeMutation Mutation) { + // We have no choice but conservatively assume that an action with a + // free-form user provided Predicate properly handles all type indices: + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::NarrowScalar, Predicate, Mutation); + } + + /// Add more elements to reach the type selected by the mutation if the + /// predicate is true. + LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate, + LegalizeMutation Mutation) { + // We have no choice but conservatively assume that an action with a + // free-form user provided Predicate properly handles all type indices: + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::MoreElements, Predicate, Mutation); + } + /// Remove elements to reach the type selected by the mutation if the + /// predicate is true. + LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate, + LegalizeMutation Mutation) { + // We have no choice but conservatively assume that an action with a + // free-form user provided Predicate properly handles all type indices: + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::FewerElements, Predicate, Mutation); + } + + /// The instruction is unsupported. + LegalizeRuleSet &unsupported() { + return actionIf(LegalizeAction::Unsupported, always); + } + LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate) { + return actionIf(LegalizeAction::Unsupported, Predicate); + } + LegalizeRuleSet &unsupportedIfMemSizeNotPow2() { + return actionIf(LegalizeAction::Unsupported, + LegalityPredicates::memSizeInBytesNotPow2(0)); + } + + LegalizeRuleSet &customIf(LegalityPredicate Predicate) { + // We have no choice but conservatively assume that a custom action with a + // free-form user provided Predicate properly handles all type indices: + markAllTypeIdxsAsCovered(); + return actionIf(LegalizeAction::Custom, Predicate); + } + LegalizeRuleSet &customFor(std::initializer_list<LLT> Types) { + return actionFor(LegalizeAction::Custom, Types); + } + LegalizeRuleSet &customForCartesianProduct(std::initializer_list<LLT> Types) { + return actionForCartesianProduct(LegalizeAction::Custom, Types); + } + LegalizeRuleSet & + customForCartesianProduct(std::initializer_list<LLT> Types0, + std::initializer_list<LLT> Types1) { + return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1); + } + + /// Widen the scalar to the next power of two that is at least MinSize. + /// No effect if the type is not a scalar or is a power of two. + LegalizeRuleSet &widenScalarToNextPow2(unsigned TypeIdx, + unsigned MinSize = 0) { + using namespace LegalityPredicates; + return actionIf(LegalizeAction::WidenScalar, sizeNotPow2(typeIdx(TypeIdx)), + LegalizeMutations::widenScalarToNextPow2(TypeIdx, MinSize)); + } + + LegalizeRuleSet &narrowScalar(unsigned TypeIdx, LegalizeMutation Mutation) { + using namespace LegalityPredicates; + return actionIf(LegalizeAction::NarrowScalar, isScalar(typeIdx(TypeIdx)), + Mutation); + } + + /// Ensure the scalar is at least as wide as Ty. + LegalizeRuleSet &minScalar(unsigned TypeIdx, const LLT &Ty) { + using namespace LegalityPredicates; + using namespace LegalizeMutations; + return actionIf(LegalizeAction::WidenScalar, + narrowerThan(TypeIdx, Ty.getSizeInBits()), + changeTo(typeIdx(TypeIdx), Ty)); + } + + /// Ensure the scalar is at most as wide as Ty. + LegalizeRuleSet &maxScalar(unsigned TypeIdx, const LLT &Ty) { + using namespace LegalityPredicates; + using namespace LegalizeMutations; + return actionIf(LegalizeAction::NarrowScalar, + widerThan(TypeIdx, Ty.getSizeInBits()), + changeTo(typeIdx(TypeIdx), Ty)); + } + + /// Conditionally limit the maximum size of the scalar. + /// For example, when the maximum size of one type depends on the size of + /// another such as extracting N bits from an M bit container. + LegalizeRuleSet &maxScalarIf(LegalityPredicate Predicate, unsigned TypeIdx, + const LLT &Ty) { + using namespace LegalityPredicates; + using namespace LegalizeMutations; + return actionIf(LegalizeAction::NarrowScalar, + [=](const LegalityQuery &Query) { + return widerThan(TypeIdx, Ty.getSizeInBits()) && + Predicate(Query); + }, + changeTo(typeIdx(TypeIdx), Ty)); + } + + /// Limit the range of scalar sizes to MinTy and MaxTy. + LegalizeRuleSet &clampScalar(unsigned TypeIdx, const LLT &MinTy, + const LLT &MaxTy) { + assert(MinTy.isScalar() && MaxTy.isScalar() && "Expected scalar types"); + return minScalar(TypeIdx, MinTy).maxScalar(TypeIdx, MaxTy); + } + + /// Add more elements to the vector to reach the next power of two. + /// No effect if the type is not a vector or the element count is a power of + /// two. + LegalizeRuleSet &moreElementsToNextPow2(unsigned TypeIdx) { + using namespace LegalityPredicates; + return actionIf(LegalizeAction::MoreElements, + numElementsNotPow2(typeIdx(TypeIdx)), + LegalizeMutations::moreElementsToNextPow2(TypeIdx)); + } + + /// Limit the number of elements in EltTy vectors to at least MinElements. + LegalizeRuleSet &clampMinNumElements(unsigned TypeIdx, const LLT &EltTy, + unsigned MinElements) { + // Mark the type index as covered: + typeIdx(TypeIdx); + return actionIf( + LegalizeAction::MoreElements, + [=](const LegalityQuery &Query) { + LLT VecTy = Query.Types[TypeIdx]; + return VecTy.isVector() && VecTy.getElementType() == EltTy && + VecTy.getNumElements() < MinElements; + }, + [=](const LegalityQuery &Query) { + LLT VecTy = Query.Types[TypeIdx]; + return std::make_pair( + TypeIdx, LLT::vector(MinElements, VecTy.getScalarSizeInBits())); + }); + } + /// Limit the number of elements in EltTy vectors to at most MaxElements. + LegalizeRuleSet &clampMaxNumElements(unsigned TypeIdx, const LLT &EltTy, + unsigned MaxElements) { + // Mark the type index as covered: + typeIdx(TypeIdx); + return actionIf( + LegalizeAction::FewerElements, + [=](const LegalityQuery &Query) { + LLT VecTy = Query.Types[TypeIdx]; + return VecTy.isVector() && VecTy.getElementType() == EltTy && + VecTy.getNumElements() > MaxElements; + }, + [=](const LegalityQuery &Query) { + LLT VecTy = Query.Types[TypeIdx]; + return std::make_pair( + TypeIdx, LLT::vector(MaxElements, VecTy.getScalarSizeInBits())); + }); + } + /// Limit the number of elements for the given vectors to at least MinTy's + /// number of elements and at most MaxTy's number of elements. + /// + /// No effect if the type is not a vector or does not have the same element + /// type as the constraints. + /// The element type of MinTy and MaxTy must match. + LegalizeRuleSet &clampNumElements(unsigned TypeIdx, const LLT &MinTy, + const LLT &MaxTy) { + assert(MinTy.getElementType() == MaxTy.getElementType() && + "Expected element types to agree"); + + const LLT &EltTy = MinTy.getElementType(); + return clampMinNumElements(TypeIdx, EltTy, MinTy.getNumElements()) + .clampMaxNumElements(TypeIdx, EltTy, MaxTy.getNumElements()); + } + + /// Fallback on the previous implementation. This should only be used while + /// porting a rule. + LegalizeRuleSet &fallback() { + add({always, LegalizeAction::UseLegacyRules}); + return *this; + } + + /// Check if there is no type index which is obviously not handled by the + /// LegalizeRuleSet in any way at all. + /// \pre Type indices of the opcode form a dense [0, \p NumTypeIdxs) set. + bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const; + /// Apply the ruleset to the given LegalityQuery. + LegalizeActionStep apply(const LegalityQuery &Query) const; +}; + +class LegalizerInfo { +public: LegalizerInfo(); virtual ~LegalizerInfo() = default; + unsigned getOpcodeIdxForOpcode(unsigned Opcode) const; + unsigned getActionDefinitionsIdx(unsigned Opcode) const; + /// Compute any ancillary tables needed to quickly decide how an operation /// should be handled. This must be called after all "set*Action"methods but /// before any query is made or incorrect results may be returned. void computeTables(); + /// Perform simple self-diagnostic and assert if there is anything obviously + /// wrong with the actions set up. + void verify(const MCInstrInfo &MII) const; + static bool needsLegalizingToDifferentSize(const LegalizeAction Action) { + using namespace LegalizeActions; switch (Action) { case NarrowScalar: case WidenScalar: @@ -121,8 +760,8 @@ public: } } - typedef std::pair<uint16_t, LegalizeAction> SizeAndAction; - typedef std::vector<SizeAndAction> SizeAndActionsVec; + using SizeAndAction = std::pair<uint16_t, LegalizeAction>; + using SizeAndActionsVec = std::vector<SizeAndAction>; using SizeChangeStrategy = std::function<SizeAndActionsVec(const SizeAndActionsVec &v)>; @@ -186,8 +825,9 @@ public: /// and Unsupported for all other scalar types T. static SizeAndActionsVec unsupportedForDifferentSizes(const SizeAndActionsVec &v) { + using namespace LegalizeActions; return increaseToLargerTypesAndDecreaseToLargest(v, Unsupported, - Unsupported); + Unsupported); } /// A SizeChangeStrategy for the common case where legalization for a @@ -196,32 +836,36 @@ public: /// largest legal type. static SizeAndActionsVec widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v) { + using namespace LegalizeActions; assert(v.size() > 0 && "At least one size that can be legalized towards is needed" " for this SizeChangeStrategy"); return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar, - NarrowScalar); + NarrowScalar); } static SizeAndActionsVec widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v) { + using namespace LegalizeActions; return increaseToLargerTypesAndDecreaseToLargest(v, WidenScalar, - Unsupported); + Unsupported); } static SizeAndActionsVec narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v) { + using namespace LegalizeActions; return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar, - Unsupported); + Unsupported); } static SizeAndActionsVec narrowToSmallerAndWidenToSmallest(const SizeAndActionsVec &v) { + using namespace LegalizeActions; assert(v.size() > 0 && "At least one size that can be legalized towards is needed" " for this SizeChangeStrategy"); return decreaseToSmallerTypesAndIncreaseToSmallest(v, NarrowScalar, - WidenScalar); + WidenScalar); } /// A SizeChangeStrategy for the common case where legalization for a @@ -244,8 +888,9 @@ public: /// (FewerElements, vector(4,32)). static SizeAndActionsVec moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v) { + using namespace LegalizeActions; return increaseToLargerTypesAndDecreaseToLargest(v, MoreElements, - FewerElements); + FewerElements); } /// Helper function to implement many typical SizeChangeStrategy functions. @@ -259,22 +904,46 @@ public: LegalizeAction DecreaseAction, LegalizeAction IncreaseAction); - /// Determine what action should be taken to legalize the given generic - /// instruction opcode, type-index and type. Requires computeTables to have - /// been called. + /// Get the action definitions for the given opcode. Use this to run a + /// LegalityQuery through the definitions. + const LegalizeRuleSet &getActionDefinitions(unsigned Opcode) const; + + /// Get the action definition builder for the given opcode. Use this to define + /// the action definitions. /// - /// \returns a pair consisting of the kind of legalization that should be - /// performed and the destination type. - std::pair<LegalizeAction, LLT> getAction(const InstrAspect &Aspect) const; + /// It is an error to request an opcode that has already been requested by the + /// multiple-opcode variant. + LegalizeRuleSet &getActionDefinitionsBuilder(unsigned Opcode); + + /// Get the action definition builder for the given set of opcodes. Use this + /// to define the action definitions for multiple opcodes at once. The first + /// opcode given will be considered the representative opcode and will hold + /// the definitions whereas the other opcodes will be configured to refer to + /// the representative opcode. This lowers memory requirements and very + /// slightly improves performance. + /// + /// It would be very easy to introduce unexpected side-effects as a result of + /// this aliasing if it were permitted to request different but intersecting + /// sets of opcodes but that is difficult to keep track of. It is therefore an + /// error to request the same opcode twice using this API, to request an + /// opcode that already has definitions, or to use the single-opcode API on an + /// opcode that has already been requested by this API. + LegalizeRuleSet & + getActionDefinitionsBuilder(std::initializer_list<unsigned> Opcodes); + void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom); + + /// Determine what action should be taken to legalize the described + /// instruction. Requires computeTables to have been called. + /// + /// \returns a description of the next legalization step to perform. + LegalizeActionStep getAction(const LegalityQuery &Query) const; /// Determine what action should be taken to legalize the given generic /// instruction. /// - /// \returns a tuple consisting of the LegalizeAction that should be - /// performed, the type-index it should be performed on and the destination - /// type. - std::tuple<LegalizeAction, unsigned, LLT> - getAction(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; + /// \returns a description of the next legalization step to perform. + LegalizeActionStep getAction(const MachineInstr &MI, + const MachineRegisterInfo &MRI) const; bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const; @@ -283,6 +952,15 @@ public: MachineIRBuilder &MIRBuilder) const; private: + /// Determine what action should be taken to legalize the given generic + /// instruction opcode, type-index and type. Requires computeTables to have + /// been called. + /// + /// \returns a pair consisting of the kind of legalization that should be + /// performed and the destination type. + std::pair<LegalizeAction, LLT> + getAspectAction(const InstrAspect &Aspect) const; + /// The SizeAndActionsVec is a representation mapping between all natural /// numbers and an Action. The natural number represents the bit size of /// the InstrAspect. For example, for a target with native support for 32-bit @@ -350,6 +1028,7 @@ private: /// A partial SizeAndActionsVec potentially doesn't cover all bit sizes, /// i.e. it's OK if it doesn't start from size 1. static void checkPartialSizeAndActionsVector(const SizeAndActionsVec& v) { + using namespace LegalizeActions; #ifndef NDEBUG // The sizes should be in increasing order int prev_size = -1; @@ -441,7 +1120,7 @@ private: static const int LastOp = TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END; // Data structures used temporarily during construction of legality data: - typedef DenseMap<LLT, LegalizeAction> TypeMap; + using TypeMap = DenseMap<LLT, LegalizeAction>; SmallVector<TypeMap, 1> SpecifiedActions[LastOp - FirstOp + 1]; SmallVector<SizeChangeStrategy, 1> ScalarSizeChangeStrategies[LastOp - FirstOp + 1]; @@ -456,8 +1135,16 @@ private: AddrSpace2PointerActions[LastOp - FirstOp + 1]; std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>> NumElements2Actions[LastOp - FirstOp + 1]; + + LegalizeRuleSet RulesForOpcode[LastOp - FirstOp + 1]; }; +#ifndef NDEBUG +/// Checks that MIR is fully legal, returns an illegal instruction if it's not, +/// nullptr otherwise +const MachineInstr *machineFunctionIsIllegal(const MachineFunction &MF); +#endif + } // end namespace llvm. #endif // LLVM_CODEGEN_GLOBALISEL_LEGALIZERINFO_H diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h index 0a46eb9e7840..1e2d4763e5e1 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Localizer.h @@ -70,6 +70,8 @@ public: .set(MachineFunctionProperties::Property::RegBankSelected); } + void getAnalysisUsage(AnalysisUsage &AU) const override; + bool runOnMachineFunction(MachineFunction &MF) override; }; diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h new file mode 100644 index 000000000000..f77f9a8df7ee --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h @@ -0,0 +1,338 @@ +//== ----- llvm/CodeGen/GlobalISel/MIPatternMatch.h --------------------- == // +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// Contains matchers for matching SSA Machine Instructions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_GMIR_PATTERNMATCH_H +#define LLVM_GMIR_PATTERNMATCH_H + +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/APInt.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +namespace llvm { +namespace MIPatternMatch { + +template <typename Reg, typename Pattern> +bool mi_match(Reg R, MachineRegisterInfo &MRI, Pattern &&P) { + return P.match(MRI, R); +} + +// TODO: Extend for N use. +template <typename SubPatternT> struct OneUse_match { + SubPatternT SubPat; + OneUse_match(const SubPatternT &SP) : SubPat(SP) {} + + template <typename OpTy> + bool match(const MachineRegisterInfo &MRI, unsigned Reg) { + return MRI.hasOneUse(Reg) && SubPat.match(MRI, Reg); + } +}; + +template <typename SubPat> +inline OneUse_match<SubPat> m_OneUse(const SubPat &SP) { + return SP; +} + +struct ConstantMatch { + int64_t &CR; + ConstantMatch(int64_t &C) : CR(C) {} + bool match(const MachineRegisterInfo &MRI, unsigned Reg) { + if (auto MaybeCst = getConstantVRegVal(Reg, MRI)) { + CR = *MaybeCst; + return true; + } + return false; + } +}; + +inline ConstantMatch m_ICst(int64_t &Cst) { return ConstantMatch(Cst); } + +// TODO: Rework this for different kinds of MachineOperand. +// Currently assumes the Src for a match is a register. +// We might want to support taking in some MachineOperands and call getReg on +// that. + +struct operand_type_match { + bool match(const MachineRegisterInfo &MRI, unsigned Reg) { return true; } + bool match(const MachineRegisterInfo &MRI, MachineOperand *MO) { + return MO->isReg(); + } +}; + +inline operand_type_match m_Reg() { return operand_type_match(); } + +/// Matching combinators. +template <typename... Preds> struct And { + template <typename MatchSrc> + bool match(MachineRegisterInfo &MRI, MatchSrc &&src) { + return true; + } +}; + +template <typename Pred, typename... Preds> +struct And<Pred, Preds...> : And<Preds...> { + Pred P; + And(Pred &&p, Preds &&... preds) + : And<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) { + } + template <typename MatchSrc> + bool match(MachineRegisterInfo &MRI, MatchSrc &&src) { + return P.match(MRI, src) && And<Preds...>::match(MRI, src); + } +}; + +template <typename... Preds> struct Or { + template <typename MatchSrc> + bool match(MachineRegisterInfo &MRI, MatchSrc &&src) { + return false; + } +}; + +template <typename Pred, typename... Preds> +struct Or<Pred, Preds...> : Or<Preds...> { + Pred P; + Or(Pred &&p, Preds &&... preds) + : Or<Preds...>(std::forward<Preds>(preds)...), P(std::forward<Pred>(p)) {} + template <typename MatchSrc> + bool match(MachineRegisterInfo &MRI, MatchSrc &&src) { + return P.match(MRI, src) || Or<Preds...>::match(MRI, src); + } +}; + +template <typename... Preds> And<Preds...> m_all_of(Preds &&... preds) { + return And<Preds...>(std::forward<Preds>(preds)...); +} + +template <typename... Preds> Or<Preds...> m_any_of(Preds &&... preds) { + return Or<Preds...>(std::forward<Preds>(preds)...); +} + +template <typename BindTy> struct bind_helper { + static bool bind(const MachineRegisterInfo &MRI, BindTy &VR, BindTy &V) { + VR = V; + return true; + } +}; + +template <> struct bind_helper<MachineInstr *> { + static bool bind(const MachineRegisterInfo &MRI, MachineInstr *&MI, + unsigned Reg) { + MI = MRI.getVRegDef(Reg); + if (MI) + return true; + return false; + } +}; + +template <> struct bind_helper<LLT> { + static bool bind(const MachineRegisterInfo &MRI, LLT &Ty, unsigned Reg) { + Ty = MRI.getType(Reg); + if (Ty.isValid()) + return true; + return false; + } +}; + +template <> struct bind_helper<const ConstantFP *> { + static bool bind(const MachineRegisterInfo &MRI, const ConstantFP *&F, + unsigned Reg) { + F = getConstantFPVRegVal(Reg, MRI); + if (F) + return true; + return false; + } +}; + +template <typename Class> struct bind_ty { + Class &VR; + + bind_ty(Class &V) : VR(V) {} + + template <typename ITy> bool match(const MachineRegisterInfo &MRI, ITy &&V) { + return bind_helper<Class>::bind(MRI, VR, V); + } +}; + +inline bind_ty<unsigned> m_Reg(unsigned &R) { return R; } +inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; } +inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; } + +// Helper for matching G_FCONSTANT +inline bind_ty<const ConstantFP *> m_GFCst(const ConstantFP *&C) { return C; } + +// General helper for all the binary generic MI such as G_ADD/G_SUB etc +template <typename LHS_P, typename RHS_P, unsigned Opcode, + bool Commutable = false> +struct BinaryOp_match { + LHS_P L; + RHS_P R; + + BinaryOp_match(const LHS_P &LHS, const RHS_P &RHS) : L(LHS), R(RHS) {} + template <typename OpTy> bool match(MachineRegisterInfo &MRI, OpTy &&Op) { + MachineInstr *TmpMI; + if (mi_match(Op, MRI, m_MInstr(TmpMI))) { + if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 3) { + return (L.match(MRI, TmpMI->getOperand(1).getReg()) && + R.match(MRI, TmpMI->getOperand(2).getReg())) || + (Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) && + L.match(MRI, TmpMI->getOperand(2).getReg()))); + } + } + return false; + } +}; + +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true> +m_GAdd(const LHS &L, const RHS &R) { + return BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true>(L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, TargetOpcode::G_SUB> m_GSub(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, TargetOpcode::G_SUB>(L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, TargetOpcode::G_MUL, true> +m_GMul(const LHS &L, const RHS &R) { + return BinaryOp_match<LHS, RHS, TargetOpcode::G_MUL, true>(L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FADD, true> +m_GFAdd(const LHS &L, const RHS &R) { + return BinaryOp_match<LHS, RHS, TargetOpcode::G_FADD, true>(L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FMUL, true> +m_GFMul(const LHS &L, const RHS &R) { + return BinaryOp_match<LHS, RHS, TargetOpcode::G_FMUL, true>(L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, TargetOpcode::G_FSUB, false> +m_GFSub(const LHS &L, const RHS &R) { + return BinaryOp_match<LHS, RHS, TargetOpcode::G_FSUB, false>(L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, TargetOpcode::G_AND, true> +m_GAnd(const LHS &L, const RHS &R) { + return BinaryOp_match<LHS, RHS, TargetOpcode::G_AND, true>(L, R); +} + +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true> m_GOr(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, TargetOpcode::G_OR, true>(L, R); +} + +// Helper for unary instructions (G_[ZSA]EXT/G_TRUNC) etc +template <typename SrcTy, unsigned Opcode> struct UnaryOp_match { + SrcTy L; + + UnaryOp_match(const SrcTy &LHS) : L(LHS) {} + template <typename OpTy> bool match(MachineRegisterInfo &MRI, OpTy &&Op) { + MachineInstr *TmpMI; + if (mi_match(Op, MRI, m_MInstr(TmpMI))) { + if (TmpMI->getOpcode() == Opcode && TmpMI->getNumOperands() == 2) { + return L.match(MRI, TmpMI->getOperand(1).getReg()); + } + } + return false; + } +}; + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT> +m_GAnyExt(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_ANYEXT>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_SEXT> m_GSExt(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_SEXT>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_ZEXT> m_GZExt(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_ZEXT>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_FPEXT> m_GFPExt(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_FPEXT>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_TRUNC> m_GTrunc(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_TRUNC>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST> +m_GBitcast(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT> +m_GPtrToInt(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR> +m_GIntToPtr(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_INTTOPTR>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC> +m_GFPTrunc(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_FPTRUNC>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_FABS> m_GFabs(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_FABS>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::G_FNEG> m_GFNeg(const SrcTy &Src) { + return UnaryOp_match<SrcTy, TargetOpcode::G_FNEG>(Src); +} + +template <typename SrcTy> +inline UnaryOp_match<SrcTy, TargetOpcode::COPY> m_Copy(SrcTy &&Src) { + return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src)); +} + +// Helper for checking if a Reg is of specific type. +struct CheckType { + LLT Ty; + CheckType(const LLT &Ty) : Ty(Ty) {} + + bool match(MachineRegisterInfo &MRI, unsigned Reg) { + return MRI.getType(Reg) == Ty; + } +}; + +inline CheckType m_SpecificType(LLT Ty) { return Ty; } + +} // namespace GMIPatternMatch +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index aa875c11d86f..983a4e680d5c 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -23,7 +23,6 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DebugLoc.h" -#include <queue> namespace llvm { @@ -32,11 +31,10 @@ class MachineFunction; class MachineInstr; class TargetInstrInfo; -/// Helper class to build MachineInstr. -/// It keeps internally the insertion point and debug location for all -/// the new instructions we want to create. -/// This information can be modify via the related setters. -class MachineIRBuilder { +/// Class which stores all the state required in a MachineIRBuilder. +/// Since MachineIRBuilders will only store state in this object, it allows +/// to transfer BuilderState between different kinds of MachineIRBuilders. +struct MachineIRBuilderState { /// MachineFunction under construction. MachineFunction *MF; /// Information used to access the description of the opcodes. @@ -53,15 +51,23 @@ class MachineIRBuilder { /// @} std::function<void(MachineInstr *)> InsertedInstr; +}; + +/// Helper class to build MachineInstr. +/// It keeps internally the insertion point and debug location for all +/// the new instructions we want to create. +/// This information can be modify via the related setters. +class MachineIRBuilderBase { + MachineIRBuilderState State; const TargetInstrInfo &getTII() { - assert(TII && "TargetInstrInfo is not set"); - return *TII; + assert(State.TII && "TargetInstrInfo is not set"); + return *State.TII; } void validateTruncExt(unsigned Dst, unsigned Src, bool IsExtend); - MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Res, unsigned Op0, unsigned Op1); +protected: unsigned getDestFromArg(unsigned Reg) { return Reg; } unsigned getDestFromArg(LLT Ty) { return getMF().getRegInfo().createGenericVirtualRegister(Ty); @@ -89,30 +95,41 @@ class MachineIRBuilder { return MIB->getOperand(0).getReg(); } + void validateBinaryOp(unsigned Res, unsigned Op0, unsigned Op1); + public: /// Some constructors for easy use. - MachineIRBuilder() = default; - MachineIRBuilder(MachineFunction &MF) { setMF(MF); } - MachineIRBuilder(MachineInstr &MI) : MachineIRBuilder(*MI.getMF()) { + MachineIRBuilderBase() = default; + MachineIRBuilderBase(MachineFunction &MF) { setMF(MF); } + MachineIRBuilderBase(MachineInstr &MI) : MachineIRBuilderBase(*MI.getMF()) { setInstr(MI); } + MachineIRBuilderBase(const MachineIRBuilderState &BState) : State(BState) {} + /// Getter for the function we currently build. MachineFunction &getMF() { - assert(MF && "MachineFunction is not set"); - return *MF; + assert(State.MF && "MachineFunction is not set"); + return *State.MF; } + /// Getter for DebugLoc + const DebugLoc &getDL() { return State.DL; } + + /// Getter for MRI + MachineRegisterInfo *getMRI() { return State.MRI; } + + /// Getter for the State + MachineIRBuilderState &getState() { return State; } + /// Getter for the basic block we currently build. MachineBasicBlock &getMBB() { - assert(MBB && "MachineBasicBlock is not set"); - return *MBB; + assert(State.MBB && "MachineBasicBlock is not set"); + return *State.MBB; } /// Current insertion point for new instructions. - MachineBasicBlock::iterator getInsertPt() { - return II; - } + MachineBasicBlock::iterator getInsertPt() { return State.II; } /// Set the insertion point before the specified position. /// \pre MBB must be in getMF(). @@ -137,15 +154,16 @@ public: /// \name Control where instructions we create are recorded (typically for /// visiting again later during legalization). /// @{ + void recordInsertion(MachineInstr *InsertedInstr) const; void recordInsertions(std::function<void(MachineInstr *)> InsertedInstr); void stopRecordingInsertions(); /// @} /// Set the debug location to \p DL for all the next build instructions. - void setDebugLoc(const DebugLoc &DL) { this->DL = DL; } + void setDebugLoc(const DebugLoc &DL) { this->State.DL = DL; } /// Get the current instruction's debug location. - DebugLoc getDebugLoc() { return DL; } + DebugLoc getDebugLoc() { return State.DL; } /// Build and insert <empty> = \p Opcode <empty>. /// The insertion point is the one set by the last call of either @@ -156,20 +174,6 @@ public: /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildInstr(unsigned Opcode); - /// DAG like Generic method for building arbitrary instructions as above. - /// \Opc opcode for the instruction. - /// \Ty Either LLT/TargetRegisterClass/unsigned types for Dst - /// \Args Variadic list of uses of types(unsigned/MachineInstrBuilder) - /// Uses of type MachineInstrBuilder will perform - /// getOperand(0).getReg() to convert to register. - template <typename DstTy, typename... UseArgsTy> - MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty, - UseArgsTy &&... Args) { - auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty)); - addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...); - return MIB; - } - /// Build but don't insert <empty> = \p Opcode <empty>. /// /// \pre setMF, setBasicBlock or setMI must have been called. @@ -227,49 +231,6 @@ public: /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildGlobalValue(unsigned Res, const GlobalValue *GV); - /// Build and insert \p Res = G_ADD \p Op0, \p Op1 - /// - /// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1, - /// truncated to their width. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same (scalar or vector) type). - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildAdd(unsigned Res, unsigned Op0, - unsigned Op1); - template <typename DstTy, typename... UseArgsTy> - MachineInstrBuilder buildAdd(DstTy &&Ty, UseArgsTy &&... UseArgs) { - unsigned Res = getDestFromArg(Ty); - return buildAdd(Res, (getRegFromArg(UseArgs))...); - } - - /// Build and insert \p Res = G_SUB \p Op0, \p Op1 - /// - /// G_SUB sets \p Res to the sum of integer parameters \p Op0 and \p Op1, - /// truncated to their width. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same (scalar or vector) type). - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildSub(unsigned Res, unsigned Op0, - unsigned Op1); - - /// Build and insert \p Res = G_MUL \p Op0, \p Op1 - /// - /// G_MUL sets \p Res to the sum of integer parameters \p Op0 and \p Op1, - /// truncated to their width. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same (scalar or vector) type). - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildMul(unsigned Res, unsigned Op0, - unsigned Op1); /// Build and insert \p Res = G_GEP \p Op0, \p Op1 /// @@ -338,34 +299,6 @@ public: MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0, unsigned Op1, unsigned CarryIn); - /// Build and insert \p Res = G_AND \p Op0, \p Op1 - /// - /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p - /// Op1. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same (scalar or vector) type). - /// - /// \return a MachineInstrBuilder for the newly created instruction. - template <typename DstTy, typename... UseArgsTy> - MachineInstrBuilder buildAnd(DstTy &&Dst, UseArgsTy &&... UseArgs) { - return buildAnd(getDestFromArg(Dst), getRegFromArg(UseArgs)...); - } - MachineInstrBuilder buildAnd(unsigned Res, unsigned Op0, - unsigned Op1); - - /// Build and insert \p Res = G_OR \p Op0, \p Op1 - /// - /// G_OR sets \p Res to the bitwise or of integer parameters \p Op0 and \p - /// Op1. - /// - /// \pre setBasicBlock or setMI must have been called. - /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers - /// with the same (scalar or vector) type). - /// - /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildOr(unsigned Res, unsigned Op0, unsigned Op1); /// Build and insert \p Res = G_ANYEXT \p Op0 /// @@ -399,6 +332,10 @@ public: /// \pre \p Op must be smaller than \p Res /// /// \return The newly created instruction. + template <typename DstType, typename ArgType> + MachineInstrBuilder buildSExt(DstType &&Res, ArgType &&Arg) { + return buildSExt(getDestFromArg(Res), getRegFromArg(Arg)); + } MachineInstrBuilder buildSExt(unsigned Res, unsigned Op); /// Build and insert \p Res = G_ZEXT \p Op @@ -413,6 +350,10 @@ public: /// \pre \p Op must be smaller than \p Res /// /// \return The newly created instruction. + template <typename DstType, typename ArgType> + MachineInstrBuilder buildZExt(DstType &&Res, ArgType &&Arg) { + return buildZExt(getDestFromArg(Res), getRegFromArg(Arg)); + } MachineInstrBuilder buildZExt(unsigned Res, unsigned Op); /// Build and insert \p Res = G_SEXT \p Op, \p Res = G_TRUNC \p Op, or @@ -423,6 +364,10 @@ public: /// \pre \p Op must be a generic virtual register with scalar or vector type. /// /// \return The newly created instruction. + template <typename DstTy, typename UseArgTy> + MachineInstrBuilder buildSExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) { + return buildSExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use)); + } MachineInstrBuilder buildSExtOrTrunc(unsigned Res, unsigned Op); /// Build and insert \p Res = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or @@ -433,6 +378,10 @@ public: /// \pre \p Op must be a generic virtual register with scalar or vector type. /// /// \return The newly created instruction. + template <typename DstTy, typename UseArgTy> + MachineInstrBuilder buildZExtOrTrunc(DstTy &&Dst, UseArgTy &&Use) { + return buildZExtOrTrunc(getDestFromArg(Dst), getRegFromArg(Use)); + } MachineInstrBuilder buildZExtOrTrunc(unsigned Res, unsigned Op); // Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_TRUNC \p Op, or @@ -462,6 +411,10 @@ public: unsigned Op); /// Build and insert an appropriate cast between two registers of equal size. + template <typename DstType, typename ArgType> + MachineInstrBuilder buildCast(DstType &&Res, ArgType &&Arg) { + return buildCast(getDestFromArg(Res), getRegFromArg(Arg)); + } MachineInstrBuilder buildCast(unsigned Dst, unsigned Src); /// Build and insert G_BR \p Dest @@ -471,7 +424,7 @@ public: /// \pre setBasicBlock or setMI must have been called. /// /// \return a MachineInstrBuilder for the newly created instruction. - MachineInstrBuilder buildBr(MachineBasicBlock &BB); + MachineInstrBuilder buildBr(MachineBasicBlock &Dest); /// Build and insert G_BRCOND \p Tst, \p Dest /// @@ -485,7 +438,7 @@ public: /// depend on bit 0 (for now). /// /// \return The newly created instruction. - MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &BB); + MachineInstrBuilder buildBrCond(unsigned Tst, MachineBasicBlock &Dest); /// Build and insert G_BRINDIRECT \p Tgt /// @@ -532,8 +485,18 @@ public: /// \pre \p Res must be a generic virtual register with scalar type. /// /// \return The newly created instruction. + template <typename DstType> + MachineInstrBuilder buildFConstant(DstType &&Res, const ConstantFP &Val) { + return buildFConstant(getDestFromArg(Res), Val); + } MachineInstrBuilder buildFConstant(unsigned Res, const ConstantFP &Val); + template <typename DstType> + MachineInstrBuilder buildFConstant(DstType &&Res, double Val) { + return buildFConstant(getDestFromArg(Res), Val); + } + MachineInstrBuilder buildFConstant(unsigned Res, double Val); + /// Build and insert \p Res = COPY Op /// /// Register-to-register COPY sets \p Res to \p Op. @@ -559,6 +522,18 @@ public: MachineInstrBuilder buildLoad(unsigned Res, unsigned Addr, MachineMemOperand &MMO); + /// Build and insert `Res = <opcode> Addr, MMO`. + /// + /// Loads the value stored at \p Addr. Puts the result in \p Res. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildLoadInstr(unsigned Opcode, unsigned Res, + unsigned Addr, MachineMemOperand &MMO); + /// Build and insert `G_STORE Val, Addr, MMO`. /// /// Stores the value \p Val to \p Addr. @@ -580,7 +555,10 @@ public: MachineInstrBuilder buildExtract(unsigned Res, unsigned Src, uint64_t Index); /// Build and insert \p Res = IMPLICIT_DEF. - MachineInstrBuilder buildUndef(unsigned Dst); + template <typename DstType> MachineInstrBuilder buildUndef(DstType &&Res) { + return buildUndef(getDestFromArg(Res)); + } + MachineInstrBuilder buildUndef(unsigned Res); /// Build and insert instructions to put \p Ops together at the specified p /// Indices to form a larger register. @@ -649,6 +627,10 @@ public: /// \pre \p Res must be smaller than \p Op /// /// \return The newly created instruction. + template <typename DstType, typename SrcType> + MachineInstrBuilder buildFPTrunc(DstType &&Res, SrcType &&Src) { + return buildFPTrunc(getDestFromArg(Res), getRegFromArg(Src)); + } MachineInstrBuilder buildFPTrunc(unsigned Res, unsigned Op); /// Build and insert \p Res = G_TRUNC \p Op @@ -735,7 +717,28 @@ public: MachineInstrBuilder buildExtractVectorElement(unsigned Res, unsigned Val, unsigned Idx); - /// Build and insert `OldValRes = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal, + /// Build and insert `OldValRes<def>, SuccessRes<def> = + /// G_ATOMIC_CMPXCHG_WITH_SUCCESS Addr, CmpVal, NewVal, MMO`. + /// + /// Atomically replace the value at \p Addr with \p NewVal if it is currently + /// \p CmpVal otherwise leaves it unchanged. Puts the original value from \p + /// Addr in \p Res, along with an s1 indicating whether it was replaced. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register of scalar type. + /// \pre \p SuccessRes must be a generic virtual register of scalar type. It + /// will be assigned 0 on failure and 1 on success. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, \p CmpVal, and \p NewVal must be generic virtual + /// registers of the same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder + buildAtomicCmpXchgWithSuccess(unsigned OldValRes, unsigned SuccessRes, + unsigned Addr, unsigned CmpVal, unsigned NewVal, + MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal, /// MMO`. /// /// Atomically replace the value at \p Addr with \p NewVal if it is currently @@ -752,6 +755,328 @@ public: MachineInstrBuilder buildAtomicCmpXchg(unsigned OldValRes, unsigned Addr, unsigned CmpVal, unsigned NewVal, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_<Opcode> Addr, Val, MMO`. + /// + /// Atomically read-modify-update the value at \p Addr with \p Val. Puts the + /// original value from \p Addr in \p OldValRes. The modification is + /// determined by the opcode. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMW(unsigned Opcode, unsigned OldValRes, + unsigned Addr, unsigned Val, + MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_XCHG Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with \p Val. Puts the original + /// value from \p Addr in \p OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWXchg(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_ADD Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with the addition of \p Val and + /// the original value. Puts the original value from \p Addr in \p OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWAdd(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_SUB Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with the subtraction of \p Val and + /// the original value. Puts the original value from \p Addr in \p OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWSub(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_AND Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with the bitwise and of \p Val and + /// the original value. Puts the original value from \p Addr in \p OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWAnd(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_NAND Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with the bitwise nand of \p Val + /// and the original value. Puts the original value from \p Addr in \p + /// OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWNand(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_OR Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with the bitwise or of \p Val and + /// the original value. Puts the original value from \p Addr in \p OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWOr(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_XOR Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with the bitwise xor of \p Val and + /// the original value. Puts the original value from \p Addr in \p OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWXor(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_MAX Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with the signed maximum of \p + /// Val and the original value. Puts the original value from \p Addr in \p + /// OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWMax(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_MIN Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with the signed minimum of \p + /// Val and the original value. Puts the original value from \p Addr in \p + /// OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWMin(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_UMAX Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with the unsigned maximum of \p + /// Val and the original value. Puts the original value from \p Addr in \p + /// OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWUmax(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); + + /// Build and insert `OldValRes<def> = G_ATOMICRMW_UMIN Addr, Val, MMO`. + /// + /// Atomically replace the value at \p Addr with the unsigned minimum of \p + /// Val and the original value. Puts the original value from \p Addr in \p + /// OldValRes. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p OldValRes must be a generic virtual register. + /// \pre \p Addr must be a generic virtual register with pointer type. + /// \pre \p OldValRes, and \p Val must be generic virtual registers of the + /// same type. + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildAtomicRMWUmin(unsigned OldValRes, unsigned Addr, + unsigned Val, MachineMemOperand &MMO); +}; + +/// A CRTP class that contains methods for building instructions that can +/// be constant folded. MachineIRBuilders that want to inherit from this will +/// need to implement buildBinaryOp (for constant folding binary ops). +/// Alternatively, they can implement buildInstr(Opc, Dst, Uses...) to perform +/// additional folding for Opc. +template <typename Base> +class FoldableInstructionsBuilder : public MachineIRBuilderBase { + Base &base() { return static_cast<Base &>(*this); } + +public: + using MachineIRBuilderBase::MachineIRBuilderBase; + /// Build and insert \p Res = G_ADD \p Op0, \p Op1 + /// + /// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1, + /// truncated to their width. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers + /// with the same (scalar or vector) type). + /// + /// \return a MachineInstrBuilder for the newly created instruction. + + MachineInstrBuilder buildAdd(unsigned Dst, unsigned Src0, unsigned Src1) { + return base().buildBinaryOp(TargetOpcode::G_ADD, Dst, Src0, Src1); + } + template <typename DstTy, typename... UseArgsTy> + MachineInstrBuilder buildAdd(DstTy &&Ty, UseArgsTy &&... UseArgs) { + unsigned Res = base().getDestFromArg(Ty); + return base().buildAdd(Res, (base().getRegFromArg(UseArgs))...); + } + + /// Build and insert \p Res = G_SUB \p Op0, \p Op1 + /// + /// G_SUB sets \p Res to the sum of integer parameters \p Op0 and \p Op1, + /// truncated to their width. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers + /// with the same (scalar or vector) type). + /// + /// \return a MachineInstrBuilder for the newly created instruction. + + MachineInstrBuilder buildSub(unsigned Dst, unsigned Src0, unsigned Src1) { + return base().buildBinaryOp(TargetOpcode::G_SUB, Dst, Src0, Src1); + } + template <typename DstTy, typename... UseArgsTy> + MachineInstrBuilder buildSub(DstTy &&Ty, UseArgsTy &&... UseArgs) { + unsigned Res = base().getDestFromArg(Ty); + return base().buildSub(Res, (base().getRegFromArg(UseArgs))...); + } + + /// Build and insert \p Res = G_MUL \p Op0, \p Op1 + /// + /// G_MUL sets \p Res to the sum of integer parameters \p Op0 and \p Op1, + /// truncated to their width. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers + /// with the same (scalar or vector) type). + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildMul(unsigned Dst, unsigned Src0, unsigned Src1) { + return base().buildBinaryOp(TargetOpcode::G_MUL, Dst, Src0, Src1); + } + template <typename DstTy, typename... UseArgsTy> + MachineInstrBuilder buildMul(DstTy &&Ty, UseArgsTy &&... UseArgs) { + unsigned Res = base().getDestFromArg(Ty); + return base().buildMul(Res, (base().getRegFromArg(UseArgs))...); + } + + /// Build and insert \p Res = G_AND \p Op0, \p Op1 + /// + /// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p + /// Op1. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers + /// with the same (scalar or vector) type). + /// + /// \return a MachineInstrBuilder for the newly created instruction. + + MachineInstrBuilder buildAnd(unsigned Dst, unsigned Src0, unsigned Src1) { + return base().buildBinaryOp(TargetOpcode::G_AND, Dst, Src0, Src1); + } + template <typename DstTy, typename... UseArgsTy> + MachineInstrBuilder buildAnd(DstTy &&Ty, UseArgsTy &&... UseArgs) { + unsigned Res = base().getDestFromArg(Ty); + return base().buildAnd(Res, (base().getRegFromArg(UseArgs))...); + } + + /// Build and insert \p Res = G_OR \p Op0, \p Op1 + /// + /// G_OR sets \p Res to the bitwise or of integer parameters \p Op0 and \p + /// Op1. + /// + /// \pre setBasicBlock or setMI must have been called. + /// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers + /// with the same (scalar or vector) type). + /// + /// \return a MachineInstrBuilder for the newly created instruction. + MachineInstrBuilder buildOr(unsigned Dst, unsigned Src0, unsigned Src1) { + return base().buildBinaryOp(TargetOpcode::G_OR, Dst, Src0, Src1); + } + template <typename DstTy, typename... UseArgsTy> + MachineInstrBuilder buildOr(DstTy &&Ty, UseArgsTy &&... UseArgs) { + unsigned Res = base().getDestFromArg(Ty); + return base().buildOr(Res, (base().getRegFromArg(UseArgs))...); + } +}; + +class MachineIRBuilder : public FoldableInstructionsBuilder<MachineIRBuilder> { +public: + using FoldableInstructionsBuilder< + MachineIRBuilder>::FoldableInstructionsBuilder; + MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Dst, + unsigned Src0, unsigned Src1) { + validateBinaryOp(Dst, Src0, Src1); + return buildInstr(Opcode).addDef(Dst).addUse(Src0).addUse(Src1); + } + using FoldableInstructionsBuilder<MachineIRBuilder>::buildInstr; + /// DAG like Generic method for building arbitrary instructions as above. + /// \Opc opcode for the instruction. + /// \Ty Either LLT/TargetRegisterClass/unsigned types for Dst + /// \Args Variadic list of uses of types(unsigned/MachineInstrBuilder) + /// Uses of type MachineInstrBuilder will perform + /// getOperand(0).getReg() to convert to register. + template <typename DstTy, typename... UseArgsTy> + MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty, + UseArgsTy &&... Args) { + auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty)); + addUsesFromArgs(MIB, std::forward<UseArgsTy>(Args)...); + return MIB; + } }; } // End namespace llvm. diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h index 676955c33fe9..c53ae416e60b 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h @@ -22,7 +22,7 @@ /// of an instruction should live. It asks the target which banks may be /// used for each operand of the instruction and what is the cost. Then, /// it chooses the solution which minimize the cost of the instruction plus -/// the cost of any move that may be needed to to the values into the right +/// the cost of any move that may be needed to the values into the right /// register bank. /// In other words, the cost for an instruction on a register bank RegBank /// is: Cost of I on RegBank plus the sum of the cost for bringing the diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h index 5d758423f4e7..d5612e17393c 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBank.h @@ -42,7 +42,7 @@ private: public: RegisterBank(unsigned ID, const char *Name, unsigned Size, - const uint32_t *ContainedRegClasses, unsigned NumRegClasses); + const uint32_t *CoveredClasses, unsigned NumRegClasses); /// Get the identifier of this register bank. unsigned getID() const { return ID; } diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index 02868b220984..82fd7eddb68a 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -622,6 +622,8 @@ public: /// \pre \p Reg is a virtual register that either has a bank or a class. /// \returns The constrained register class, or nullptr if there is none. /// \note This is a generic variant of MachineRegisterInfo::constrainRegClass + /// \note Use MachineRegisterInfo::constrainRegAttrs instead for any non-isel + /// purpose, including non-select passes of GlobalISel static const TargetRegisterClass * constrainGenericRegister(unsigned Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI); diff --git a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h index 5864c15cc8eb..51e3a2732972 100644 --- a/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h +++ b/contrib/llvm/include/llvm/CodeGen/GlobalISel/Utils.h @@ -19,8 +19,10 @@ namespace llvm { +class AnalysisUsage; class MachineFunction; class MachineInstr; +class MachineOperand; class MachineOptimizationRemarkEmitter; class MachineOptimizationRemarkMissed; class MachineRegisterInfo; @@ -32,6 +34,7 @@ class TargetRegisterInfo; class TargetRegisterClass; class Twine; class ConstantFP; +class APFloat; /// Try to constrain Reg to the specified register class. If this fails, /// create a new virtual register in the correct class and insert a COPY before @@ -57,8 +60,21 @@ unsigned constrainOperandRegClass(const MachineFunction &MF, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const MCInstrDesc &II, - unsigned Reg, unsigned OpIdx); + const MachineOperand &RegMO, unsigned OpIdx); +/// Mutate the newly-selected instruction \p I to constrain its (possibly +/// generic) virtual register operands to the instruction's register class. +/// This could involve inserting COPYs before (for uses) or after (for defs). +/// This requires the number of operands to match the instruction description. +/// \returns whether operand regclass constraining succeeded. +/// +// FIXME: Not all instructions have the same number of operands. We should +// probably expose a constrain helper per operand and let the target selector +// constrain individual registers, like fast-isel. +bool constrainSelectedInstRegOperands(MachineInstr &I, + const TargetInstrInfo &TII, + const TargetRegisterInfo &TRI, + const RegisterBankInfo &RBI); /// Check whether an instruction \p MI is dead: it only defines dead virtual /// registers, and doesn't have other side effects. bool isTriviallyDead(const MachineInstr &MI, const MachineRegisterInfo &MRI); @@ -85,5 +101,12 @@ const ConstantFP* getConstantFPVRegVal(unsigned VReg, MachineInstr *getOpcodeDef(unsigned Opcode, unsigned Reg, const MachineRegisterInfo &MRI); +/// Returns an APFloat from Val converted to the appropriate size. +APFloat getAPFloatFromSize(double Val, unsigned Size); + +/// Modify analysis usage so it preserves passes required for the SelectionDAG +/// fallback. +void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU); + } // End namespace llvm. #endif diff --git a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h index d256849be9af..80bd796d5374 100644 --- a/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/contrib/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -377,6 +377,8 @@ namespace ISD { /// When the 1st operand is a vector, the shift amount must be in the same /// type. (TLI.getShiftAmountTy() will return the same type when the input /// type is a vector.) + /// For rotates, the shift amount is treated as an unsigned amount modulo + /// the element size of the first operand. SHL, SRA, SRL, ROTL, ROTR, /// Byte Swap and Counting operators. @@ -412,19 +414,11 @@ namespace ISD { /// then the result type must also be a vector type. SETCC, - /// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, and - /// op #2 is a *carry value*. This operator checks the result of - /// "LHS - RHS - Carry", and can be used to compare two wide integers: - /// (setcce lhshi rhshi (subc lhslo rhslo) cc). Only valid for integers. - /// FIXME: This node is deprecated in favor of SETCCCARRY. - /// It is kept around for now to provide a smooth transition path - /// toward the use of SETCCCARRY and will eventually be removed. - SETCCE, - /// Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but /// op #2 is a boolean indicating if there is an incoming carry. This /// operator checks the result of "LHS - RHS - Carry", and can be used to - /// compare two wide integers: (setcce lhshi rhshi (subc lhslo rhslo) cc). + /// compare two wide integers: + /// (setcccarry lhshi rhshi (subcarry lhslo rhslo) cc). /// Only valid for integers. SETCCCARRY, @@ -495,7 +489,8 @@ namespace ISD { ZERO_EXTEND_VECTOR_INREG, /// FP_TO_[US]INT - Convert a floating point value to a signed or unsigned - /// integer. + /// integer. These have the same semantics as fptosi and fptoui in IR. If + /// the FP value cannot fit in the integer type, the results are undefined. FP_TO_SINT, FP_TO_UINT, @@ -779,6 +774,7 @@ namespace ISD { ATOMIC_LOAD_ADD, ATOMIC_LOAD_SUB, ATOMIC_LOAD_AND, + ATOMIC_LOAD_CLR, ATOMIC_LOAD_OR, ATOMIC_LOAD_XOR, ATOMIC_LOAD_NAND, diff --git a/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h b/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h index 988e6d6cb3a3..9b8d83ce77ca 100644 --- a/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h +++ b/contrib/llvm/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -17,6 +17,7 @@ #define LLVM_CODEGEN_LATENCYPRIORITYQUEUE_H #include "llvm/CodeGen/ScheduleDAG.h" +#include "llvm/Config/llvm-config.h" namespace llvm { class LatencyPriorityQueue; @@ -26,7 +27,7 @@ namespace llvm { LatencyPriorityQueue *PQ; explicit latency_sort(LatencyPriorityQueue *pq) : PQ(pq) {} - bool operator()(const SUnit* left, const SUnit* right) const; + bool operator()(const SUnit* LHS, const SUnit* RHS) const; }; class LatencyPriorityQueue : public SchedulingPriorityQueue { @@ -83,11 +84,15 @@ namespace llvm { void remove(SUnit *SU) override; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + LLVM_DUMP_METHOD void dump(ScheduleDAG *DAG) const override; +#endif + // 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) override; + void scheduledNode(SUnit *SU) override; private: void AdjustPriorityOfUnscheduledPreds(SUnit *SU); diff --git a/contrib/llvm/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h b/contrib/llvm/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h index 848ee1dc0dc6..221f16a03f16 100644 --- a/contrib/llvm/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/LazyMachineBlockFrequencyInfo.h @@ -23,7 +23,7 @@ #include "llvm/CodeGen/MachineLoopInfo.h" namespace llvm { -/// \brief This is an alternative analysis pass to MachineBlockFrequencyInfo. +/// This is an alternative analysis pass to MachineBlockFrequencyInfo. /// The difference is that with this pass, the block frequencies are not /// computed when the analysis pass is executed but rather when the BFI result /// is explicitly requested by the analysis client. @@ -49,7 +49,7 @@ private: /// The function. MachineFunction *MF = nullptr; - /// \brief Calculate MBFI and all other analyses that's not available and + /// Calculate MBFI and all other analyses that's not available and /// required by BFI. MachineBlockFrequencyInfo &calculateIfNotAvailable() const; @@ -58,10 +58,10 @@ public: LazyMachineBlockFrequencyInfoPass(); - /// \brief Compute and return the block frequencies. + /// Compute and return the block frequencies. MachineBlockFrequencyInfo &getBFI() { return calculateIfNotAvailable(); } - /// \brief Compute and return the block frequencies. + /// Compute and return the block frequencies. const MachineBlockFrequencyInfo &getBFI() const { return calculateIfNotAvailable(); } diff --git a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h index f4fa872c7f5b..cdf9ad2588cf 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveInterval.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveInterval.h @@ -326,7 +326,7 @@ namespace llvm { /// createDeadDef - Make sure the range has a value defined at Def. /// If one already exists, return it. Otherwise allocate a new value and /// add liveness for a dead def. - VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNInfoAllocator); + VNInfo *createDeadDef(SlotIndex Def, VNInfo::Allocator &VNIAlloc); /// Create a def of value @p VNI. Return @p VNI. If there already exists /// a definition at VNI->def, the value defined there must be @p VNI. @@ -454,7 +454,7 @@ namespace llvm { /// overlapsFrom - Return true if the intersection of the two live ranges /// is not empty. The specified iterator is a hint that we can begin /// scanning the Other range starting at I. - bool overlapsFrom(const LiveRange &Other, const_iterator I) const; + bool overlapsFrom(const LiveRange &Other, const_iterator StartPos) const; /// Returns true if all segments of the @p Other live range are completely /// covered by this live range. @@ -482,7 +482,7 @@ namespace llvm { /// @p Use, return {nullptr, false}. If there is an "undef" before @p Use, /// return {nullptr, true}. std::pair<VNInfo*,bool> extendInBlock(ArrayRef<SlotIndex> Undefs, - SlotIndex StartIdx, SlotIndex Use); + SlotIndex StartIdx, SlotIndex Kill); /// Simplified version of the above "extendInBlock", which assumes that /// no register lanes are undefined by <def,read-undef> operands. @@ -609,7 +609,7 @@ namespace llvm { void print(raw_ostream &OS) const; void dump() const; - /// \brief Walk the range and assert if any invariants fail to hold. + /// Walk the range and assert if any invariants fail to hold. /// /// Note that this is a no-op when asserts are disabled. #ifdef NDEBUG @@ -791,7 +791,7 @@ namespace llvm { /// L00E0 and L0010 and the L000F lane into L0007 and L0008. The Mod /// function will be applied to the L0010 and L0008 subranges. void refineSubRanges(BumpPtrAllocator &Allocator, LaneBitmask LaneMask, - std::function<void(LiveInterval::SubRange&)> Mod); + std::function<void(LiveInterval::SubRange&)> Apply); bool operator<(const LiveInterval& other) const { const SlotIndex &thisIndex = beginIndex(); @@ -802,7 +802,7 @@ namespace llvm { void print(raw_ostream &OS) const; void dump() const; - /// \brief Walks the interval and assert if any invariants fail to hold. + /// Walks the interval and assert if any invariants fail to hold. /// /// Note that this is a no-op when asserts are disabled. #ifdef NDEBUG diff --git a/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h b/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h index b922e543c856..9e2799bd4414 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveIntervalUnion.h @@ -154,7 +154,7 @@ public: unsigned MaxInterferingRegs = std::numeric_limits<unsigned>::max()); // Was this virtual register visited during collectInterferingVRegs? - bool isSeenInterference(LiveInterval *VReg) const; + bool isSeenInterference(LiveInterval *VirtReg) const; // Did collectInterferingVRegs collect all interferences? bool seenAllInterferences() const { return SeenAllInterferences; } diff --git a/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h b/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h index 1150f3c1c47b..291a07a712cb 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveIntervals.h @@ -105,7 +105,7 @@ class VirtRegMap; /// Calculate the spill weight to assign to a single instruction. static float getSpillWeight(bool isDef, bool isUse, const MachineBlockFrequencyInfo *MBFI, - const MachineInstr &Instr); + const MachineInstr &MI); /// Calculate the spill weight to assign to a single instruction. static float getSpillWeight(bool isDef, bool isUse, @@ -462,6 +462,10 @@ class VirtRegMap; void computeRegUnitRange(LiveRange&, unsigned Unit); void computeVirtRegInterval(LiveInterval&); + using ShrinkToUsesWorkList = SmallVector<std::pair<SlotIndex, VNInfo*>, 16>; + void extendSegmentsToUses(LiveRange &Segments, + ShrinkToUsesWorkList &WorkList, unsigned Reg, + LaneBitmask LaneMask); /// Helper function for repairIntervalsInRange(), walks backwards and /// creates/modifies live segments in \p LR to match the operands found. diff --git a/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h b/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h index f9aab0d09e1f..301a45066b4c 100644 --- a/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h +++ b/contrib/llvm/include/llvm/CodeGen/LivePhysRegs.h @@ -44,7 +44,7 @@ class MachineOperand; class MachineRegisterInfo; class raw_ostream; -/// \brief A set of physical registers with utility functions to track liveness +/// A set of physical registers with utility functions to track liveness /// when walking backward/forward through a basic block. class LivePhysRegs { const TargetRegisterInfo *TRI = nullptr; @@ -84,7 +84,7 @@ public: LiveRegs.insert(*SubRegs); } - /// \brief Removes a physical register, all its sub-registers, and all its + /// 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."); @@ -98,7 +98,7 @@ public: SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> *Clobbers = nullptr); - /// \brief Returns true if register \p Reg is contained in the set. This also + /// 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 /// addReg() always adds all sub-registers to the set as well. /// Note: Returns false if just some sub registers are live, use available() @@ -155,7 +155,7 @@ public: void dump() const; private: - /// \brief Adds live-in registers from basic block \p MBB, taking associated + /// Adds live-in registers from basic block \p MBB, taking associated /// lane masks into consideration. void addBlockLiveIns(const MachineBasicBlock &MBB); @@ -169,7 +169,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const LivePhysRegs& LR) { return OS; } -/// \brief Computes registers live-in to \p MBB assuming all of its successors +/// Computes registers live-in to \p MBB assuming all of its successors /// live-in lists are up-to-date. Puts the result into the given LivePhysReg /// instance \p LiveRegs. void computeLiveIns(LivePhysRegs &LiveRegs, const MachineBasicBlock &MBB); @@ -185,6 +185,13 @@ void addLiveIns(MachineBasicBlock &MBB, const LivePhysRegs &LiveRegs); void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB); +/// Convenience function for recomputing live-in's for \p MBB. +static inline void recomputeLiveIns(MachineBasicBlock &MBB) { + LivePhysRegs LPR; + MBB.clearLiveIns(); + computeAndAddLiveIns(LPR, MBB); +} + } // end namespace llvm #endif // LLVM_CODEGEN_LIVEPHYSREGS_H diff --git a/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h b/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h index 84bccde0caa2..53830297c525 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveRangeEdit.h @@ -117,10 +117,13 @@ private: /// registers are created. void MRI_NoteNewVirtualRegister(unsigned VReg) override; - /// \brief Check if MachineOperand \p MO is a last use/kill either in the + /// Check if MachineOperand \p MO is a last use/kill either in the /// main live range of \p LI or in one of the matching subregister ranges. bool useIsKill(const LiveInterval &LI, const MachineOperand &MO) const; + /// Create a new empty interval based on OldReg. + LiveInterval &createEmptyIntervalFrom(unsigned OldReg, bool createSubRanges); + public: /// Create a LiveRangeEdit for breaking down parent into smaller pieces. /// @param parent The register being spilled or split. @@ -174,16 +177,13 @@ public: return makeArrayRef(NewRegs).slice(FirstNew); } - /// createEmptyIntervalFrom - Create a new empty interval based on OldReg. - LiveInterval &createEmptyIntervalFrom(unsigned OldReg); - /// createFrom - Create a new virtual register based on OldReg. unsigned createFrom(unsigned OldReg); /// create - Create a new register with the same class and original slot as /// parent. LiveInterval &createEmptyInterval() { - return createEmptyIntervalFrom(getReg()); + return createEmptyIntervalFrom(getReg(), true); } unsigned create() { return createFrom(getReg()); } @@ -233,12 +233,6 @@ public: return Rematted.count(ParentVNI); } - void markDeadRemat(MachineInstr *inst) { - // DeadRemats is an optional field. - if (DeadRemats) - DeadRemats->insert(inst); - } - /// eraseVirtReg - Notify the delegate that Reg is no longer in use, and try /// to erase it from LIS. void eraseVirtReg(unsigned Reg); diff --git a/contrib/llvm/include/llvm/CodeGen/LiveRegMatrix.h b/contrib/llvm/include/llvm/CodeGen/LiveRegMatrix.h index fa6827f6b1f9..f62a55c73085 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveRegMatrix.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveRegMatrix.h @@ -107,6 +107,13 @@ public: /// with the highest enum value is returned. InterferenceKind checkInterference(LiveInterval &VirtReg, unsigned PhysReg); + /// Check for interference in the segment [Start, End) that may prevent + /// assignment to PhysReg. If this function returns true, there is + /// interference in the segment [Start, End) of some other interval already + /// assigned to PhysReg. If this function returns false, PhysReg is free at + /// the segment [Start, End). + bool checkInterference(SlotIndex Start, SlotIndex End, unsigned PhysReg); + /// Assign VirtReg to PhysReg. /// This will mark VirtReg's live range as occupied in the LiveRegMatrix and /// update VirtRegMap. The live range is expected to be available in PhysReg. diff --git a/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h b/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h index dc4956da9637..249545906e01 100644 --- a/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h +++ b/contrib/llvm/include/llvm/CodeGen/LiveRegUnits.h @@ -16,6 +16,7 @@ #define LLVM_CODEGEN_LIVEREGUNITS_H #include "llvm/ADT/BitVector.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/MC/LaneBitmask.h" #include "llvm/MC/MCRegisterInfo.h" @@ -40,6 +41,36 @@ public: init(TRI); } + /// For a machine instruction \p MI, adds all register units used in + /// \p UsedRegUnits and defined or clobbered in \p ModifiedRegUnits. This is + /// useful when walking over a range of instructions to track registers + /// used or defined seperately. + static void accumulateUsedDefed(const MachineInstr &MI, + LiveRegUnits &ModifiedRegUnits, + LiveRegUnits &UsedRegUnits, + const TargetRegisterInfo *TRI) { + for (ConstMIBundleOperands O(MI); O.isValid(); ++O) { + if (O->isRegMask()) + ModifiedRegUnits.addRegsInMask(O->getRegMask()); + if (!O->isReg()) + continue; + unsigned Reg = O->getReg(); + if (!TargetRegisterInfo::isPhysicalRegister(Reg)) + continue; + if (O->isDef()) { + // Some architectures (e.g. AArch64 XZR/WZR) have registers that are + // constant and may be used as destinations to indicate the generated + // value is discarded. No need to track such case as a def. + if (!TRI->isConstantPhysReg(Reg)) + ModifiedRegUnits.addReg(Reg); + } else { + assert(O->isUse() && "Reg operand not a def and not a use"); + UsedRegUnits.addReg(Reg); + } + } + return; + } + /// Initialize and clear the set. void init(const TargetRegisterInfo &TRI) { this->TRI = &TRI; @@ -59,7 +90,7 @@ public: Units.set(*Unit); } - /// \brief Adds register units covered by physical register \p Reg that are + /// Adds register units covered by physical register \p Reg that are /// part of the lanemask \p Mask. void addRegMasked(unsigned Reg, LaneBitmask Mask) { for (MCRegUnitMaskIterator Unit(Reg, TRI); Unit.isValid(); ++Unit) { diff --git a/contrib/llvm/include/llvm/CodeGen/LoopTraversal.h b/contrib/llvm/include/llvm/CodeGen/LoopTraversal.h new file mode 100644 index 000000000000..750da0143c0d --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/LoopTraversal.h @@ -0,0 +1,116 @@ +//==------ llvm/CodeGen/LoopTraversal.h - Loop Traversal -*- C++ -*---------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file Loop Traversal logic. +/// +/// This class provides the basic blocks traversal order used by passes like +/// ReachingDefAnalysis and ExecutionDomainFix. +/// It identifies basic blocks that are part of loops and should to be visited +/// twice and returns efficient traversal order for all the blocks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LOOPTRAVERSAL_H +#define LLVM_CODEGEN_LOOPTRAVERSAL_H + +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class MachineBasicBlock; +class MachineFunction; + +/// This class provides the basic blocks traversal order used by passes like +/// ReachingDefAnalysis and ExecutionDomainFix. +/// It identifies basic blocks that are part of loops and should to be visited +/// twice and returns efficient traversal order for all the blocks. +/// +/// We want to visit every instruction in every basic block in order to update +/// it's execution domain or collect clearance information. However, for the +/// clearance calculation, we need to know clearances from all predecessors +/// (including any backedges), therfore we need to visit some blocks twice. +/// As an example, consider the following loop. +/// +/// +/// PH -> A -> B (xmm<Undef> -> xmm<Def>) -> C -> D -> EXIT +/// ^ | +/// +----------------------------------+ +/// +/// The iteration order this pass will return is as follows: +/// Optimized: PH A B C A' B' C' D +/// +/// The basic block order is constructed as follows: +/// Once we finish processing some block, we update the counters in MBBInfos +/// and re-process any successors that are now 'done'. +/// We call a block that is ready for its final round of processing `done` +/// (isBlockDone), e.g. when all predecessor information is known. +/// +/// Note that a naive traversal order would be to do two complete passes over +/// all basic blocks/instructions, the first for recording clearances, the +/// second for updating clearance based on backedges. +/// However, for functions without backedges, or functions with a lot of +/// straight-line code, and a small loop, that would be a lot of unnecessary +/// work (since only the BBs that are part of the loop require two passes). +/// +/// E.g., the naive iteration order for the above exmple is as follows: +/// Naive: PH A B C D A' B' C' D' +/// +/// In the optimized approach we avoid processing D twice, because we +/// can entirely process the predecessors before getting to D. +class LoopTraversal { +private: + struct MBBInfo { + /// Whether we have gotten to this block in primary processing yet. + bool PrimaryCompleted = false; + + /// The number of predecessors for which primary processing has completed + unsigned IncomingProcessed = 0; + + /// The value of `IncomingProcessed` at the start of primary processing + unsigned PrimaryIncoming = 0; + + /// The number of predecessors for which all processing steps are done. + unsigned IncomingCompleted = 0; + + MBBInfo() = default; + }; + using MBBInfoMap = SmallVector<MBBInfo, 4>; + /// Helps keep track if we proccessed this block and all its predecessors. + MBBInfoMap MBBInfos; + +public: + struct TraversedMBBInfo { + /// The basic block. + MachineBasicBlock *MBB = nullptr; + + /// True if this is the first time we process the basic block. + bool PrimaryPass = true; + + /// True if the block that is ready for its final round of processing. + bool IsDone = true; + + TraversedMBBInfo(MachineBasicBlock *BB = nullptr, bool Primary = true, + bool Done = true) + : MBB(BB), PrimaryPass(Primary), IsDone(Done) {} + }; + LoopTraversal() {} + + /// Identifies basic blocks that are part of loops and should to be + /// visited twice and returns efficient traversal order for all the blocks. + typedef SmallVector<TraversedMBBInfo, 4> TraversalOrder; + TraversalOrder traverse(MachineFunction &MF); + +private: + /// Returens true if the block is ready for its final round of processing. + bool isBlockDone(MachineBasicBlock *MBB); +}; + +} // namespace llvm + +#endif // LLVM_CODEGEN_LOOPTRAVERSAL_H diff --git a/contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h b/contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h index b631a8c0122a..e199a1f69ad7 100644 --- a/contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h +++ b/contrib/llvm/include/llvm/CodeGen/MIRParser/MIRParser.h @@ -45,7 +45,7 @@ public: /// \returns nullptr if a parsing error occurred. std::unique_ptr<Module> parseIRModule(); - /// \brief Parses MachineFunctions in the MIR file and add them to the given + /// Parses MachineFunctions in the MIR file and add them to the given /// MachineModuleInfo \p MMI. /// /// \returns true if an error occurred. diff --git a/contrib/llvm/include/llvm/CodeGen/MIRPrinter.h b/contrib/llvm/include/llvm/CodeGen/MIRPrinter.h index c73adc3f2b11..078c4b2f6072 100644 --- a/contrib/llvm/include/llvm/CodeGen/MIRPrinter.h +++ b/contrib/llvm/include/llvm/CodeGen/MIRPrinter.h @@ -38,7 +38,7 @@ void printMIR(raw_ostream &OS, const MachineFunction &MF); /// this funciton and the parser will use this function to construct a list if /// it is missing. void guessSuccessors(const MachineBasicBlock &MBB, - SmallVectorImpl<MachineBasicBlock*> &Successors, + SmallVectorImpl<MachineBasicBlock*> &Result, bool &IsFallthrough); } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h index ba40e522e261..7f46406c4789 100644 --- a/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h +++ b/contrib/llvm/include/llvm/CodeGen/MIRYamlMapping.h @@ -258,11 +258,11 @@ template <> struct MappingTraits<MachineStackObject> { YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored, true); YamlIO.mapOptional("local-offset", Object.LocalOffset, Optional<int64_t>()); - YamlIO.mapOptional("di-variable", Object.DebugVar, + YamlIO.mapOptional("debug-info-variable", Object.DebugVar, StringValue()); // Don't print it out when it's empty. - YamlIO.mapOptional("di-expression", Object.DebugExpr, + YamlIO.mapOptional("debug-info-expression", Object.DebugExpr, StringValue()); // Don't print it out when it's empty. - YamlIO.mapOptional("di-location", Object.DebugLoc, + YamlIO.mapOptional("debug-info-location", Object.DebugLoc, StringValue()); // Don't print it out when it's empty. } @@ -283,6 +283,9 @@ struct FixedMachineStackObject { bool IsAliased = false; StringValue CalleeSavedRegister; bool CalleeSavedRestored = true; + StringValue DebugVar; + StringValue DebugExpr; + StringValue DebugLoc; bool operator==(const FixedMachineStackObject &Other) const { return ID == Other.ID && Type == Other.Type && Offset == Other.Offset && @@ -290,7 +293,9 @@ struct FixedMachineStackObject { StackID == Other.StackID && IsImmutable == Other.IsImmutable && IsAliased == Other.IsAliased && CalleeSavedRegister == Other.CalleeSavedRegister && - CalleeSavedRestored == Other.CalleeSavedRestored; + CalleeSavedRestored == Other.CalleeSavedRestored && + DebugVar == Other.DebugVar && DebugExpr == Other.DebugExpr + && DebugLoc == Other.DebugLoc; } }; @@ -321,6 +326,12 @@ template <> struct MappingTraits<FixedMachineStackObject> { StringValue()); // Don't print it out when it's empty. YamlIO.mapOptional("callee-saved-restored", Object.CalleeSavedRestored, true); + YamlIO.mapOptional("debug-info-variable", Object.DebugVar, + StringValue()); // Don't print it out when it's empty. + YamlIO.mapOptional("debug-info-expression", Object.DebugExpr, + StringValue()); // Don't print it out when it's empty. + YamlIO.mapOptional("debug-info-location", Object.DebugLoc, + StringValue()); // Don't print it out when it's empty. } static const bool flow = true; @@ -417,6 +428,7 @@ struct MachineFrameInfo { bool HasOpaqueSPAdjustment = false; bool HasVAStart = false; bool HasMustTailInVarArgFunc = false; + unsigned LocalFrameSize = 0; StringValue SavePoint; StringValue RestorePoint; @@ -434,6 +446,7 @@ struct MachineFrameInfo { HasOpaqueSPAdjustment == Other.HasOpaqueSPAdjustment && HasVAStart == Other.HasVAStart && HasMustTailInVarArgFunc == Other.HasMustTailInVarArgFunc && + LocalFrameSize == Other.LocalFrameSize && SavePoint == Other.SavePoint && RestorePoint == Other.RestorePoint; } }; @@ -457,6 +470,7 @@ template <> struct MappingTraits<MachineFrameInfo> { YamlIO.mapOptional("hasVAStart", MFI.HasVAStart, false); YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc, false); + YamlIO.mapOptional("localFrameSize", MFI.LocalFrameSize, (unsigned)0); YamlIO.mapOptional("savePoint", MFI.SavePoint, StringValue()); // Don't print it out when it's empty. YamlIO.mapOptional("restorePoint", MFI.RestorePoint, @@ -472,6 +486,7 @@ struct MachineFunction { bool Legalized = false; bool RegBankSelected = false; bool Selected = false; + bool FailedISel = false; // Register information bool TracksRegLiveness = false; std::vector<VirtualRegisterDefinition> VirtualRegisters; @@ -495,6 +510,7 @@ template <> struct MappingTraits<MachineFunction> { YamlIO.mapOptional("legalized", MF.Legalized, false); YamlIO.mapOptional("regBankSelected", MF.RegBankSelected, false); YamlIO.mapOptional("selected", MF.Selected, false); + YamlIO.mapOptional("failedISel", MF.FailedISel, false); YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness, false); YamlIO.mapOptional("registers", MF.VirtualRegisters, std::vector<VirtualRegisterDefinition>()); diff --git a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h index 89210e16629e..ace33efd8713 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -58,7 +58,7 @@ private: public: void addNodeToList(MachineInstr *N); void removeNodeFromList(MachineInstr *N); - void transferNodesFromList(ilist_traits &OldList, instr_iterator First, + void transferNodesFromList(ilist_traits &FromList, instr_iterator First, instr_iterator Last); void deleteNode(MachineInstr *MI); }; @@ -115,13 +115,18 @@ private: /// branch. bool AddressTaken = false; + /// Indicate that this basic block is the entry block of an EH scope, i.e., + /// the block that used to have a catchpad or cleanuppad instruction in the + /// LLVM IR. + bool IsEHScopeEntry = false; + /// Indicate that this basic block is the entry block of an EH funclet. bool IsEHFuncletEntry = false; /// Indicate that this basic block is the entry block of a cleanup funclet. bool IsCleanupFuncletEntry = false; - /// \brief since getSymbol is a relatively heavy-weight operation, the symbol + /// since getSymbol is a relatively heavy-weight operation, the symbol /// is only computed once and is cached. mutable MCSymbol *CachedMCSymbol = nullptr; @@ -225,6 +230,14 @@ public: return make_range(getFirstTerminator(), end()); } + /// Returns a range that iterates over the phis in the basic block. + inline iterator_range<iterator> phis() { + return make_range(begin(), getFirstNonPHI()); + } + inline iterator_range<const_iterator> phis() const { + return const_cast<MachineBasicBlock *>(this)->phis(); + } + // Machine-CFG iterators using pred_iterator = std::vector<MachineBasicBlock *>::iterator; using const_pred_iterator = std::vector<MachineBasicBlock *>::const_iterator; @@ -367,6 +380,14 @@ public: bool hasEHPadSuccessor() const; + /// Returns true if this is the entry block of an EH scope, i.e., the block + /// that used to have a catchpad or cleanuppad instruction in the LLVM IR. + bool isEHScopeEntry() const { return IsEHScopeEntry; } + + /// Indicates if this is the entry block of an EH scope, i.e., the block that + /// that used to have a catchpad or cleanuppad instruction in the LLVM IR. + void setIsEHScopeEntry(bool V = true) { IsEHScopeEntry = V; } + /// Returns true if this is the entry block of an EH funclet. bool isEHFuncletEntry() const { return IsEHFuncletEntry; } @@ -456,6 +477,11 @@ public: /// probabilities may need to be normalized. void copySuccessor(MachineBasicBlock *Orig, succ_iterator I); + /// Split the old successor into old plus new and updates the probability + /// info. + void splitSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New, + bool NormalizeSuccProbs = false); + /// Transfers all the successors from MBB to this machine basic block (i.e., /// copies all the successors FromMBB and remove all the successors from /// FromMBB). @@ -553,7 +579,7 @@ public: /// Check if the edge between this block and the given successor \p /// Succ, can be split. If this returns true a subsequent call to /// SplitCriticalEdge is guaranteed to return a valid basic block if - /// no changes occured in the meantime. + /// no changes occurred in the meantime. bool canSplitCriticalEdge(const MachineBasicBlock *Succ) const; void pop_front() { Insts.pop_front(); } @@ -692,12 +718,19 @@ public: bool IsCond); /// Find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE - /// instructions. Return UnknownLoc if there is none. + /// and DBG_LABEL instructions. Return UnknownLoc if there is none. DebugLoc findDebugLoc(instr_iterator MBBI); DebugLoc findDebugLoc(iterator MBBI) { return findDebugLoc(MBBI.getInstrIterator()); } + /// Find the previous valid DebugLoc preceding MBBI, skipping and DBG_VALUE + /// instructions. Return UnknownLoc if there is none. + DebugLoc findPrevDebugLoc(instr_iterator MBBI); + DebugLoc findPrevDebugLoc(iterator MBBI) { + return findPrevDebugLoc(MBBI.getInstrIterator()); + } + /// Find and return the merged DebugLoc of the branch instructions of the /// block. Return UnknownLoc if there is none. DebugLoc findBranchDebugLoc(); @@ -724,9 +757,10 @@ public: // Debugging methods. void dump() const; - void print(raw_ostream &OS, const SlotIndexes* = nullptr) const; + void print(raw_ostream &OS, const SlotIndexes * = nullptr, + bool IsStandalone = true) const; void print(raw_ostream &OS, ModuleSlotTracker &MST, - const SlotIndexes* = nullptr) const; + const SlotIndexes * = nullptr, bool IsStandalone = true) const; // Printing method used by LoopInfo. void printAsOperand(raw_ostream &OS, bool PrintType = true) const; @@ -881,7 +915,7 @@ public: /// const_instr_iterator} and the respective reverse iterators. template<typename IterT> inline IterT skipDebugInstructionsForward(IterT It, IterT End) { - while (It != End && It->isDebugValue()) + while (It != End && It->isDebugInstr()) It++; return It; } @@ -892,7 +926,7 @@ inline IterT skipDebugInstructionsForward(IterT It, IterT End) { /// const_instr_iterator} and the respective reverse iterators. template<class IterT> inline IterT skipDebugInstructionsBackward(IterT It, IterT Begin) { - while (It != Begin && It->isDebugValue()) + while (It != Begin && It->isDebugInstr()) It--; return It; } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h index 1705a0f7e59b..b0b5420a884b 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineConstantPool.h @@ -63,7 +63,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, /// This class is a data container for one entry in a MachineConstantPool. /// It contains a pointer to the value and an offset from the start of /// the constant pool. -/// @brief An entry in a MachineConstantPool +/// An entry in a MachineConstantPool class MachineConstantPoolEntry { public: /// The constant itself. @@ -117,7 +117,7 @@ public: /// the use of MO_ConstantPoolIndex values. When emitting assembly or machine /// code, these virtual address references are converted to refer to the /// address of the function constant pool values. -/// @brief The machine constant pool. +/// The machine constant pool. class MachineConstantPool { unsigned PoolAlignment; ///< The alignment for the pool. std::vector<MachineConstantPoolEntry> Constants; ///< The pool of constants. @@ -128,7 +128,7 @@ class MachineConstantPool { const DataLayout &getDataLayout() const { return DL; } public: - /// @brief The only constructor. + /// The only constructor. explicit MachineConstantPool(const DataLayout &DL) : PoolAlignment(1), DL(DL) {} ~MachineConstantPool(); diff --git a/contrib/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h b/contrib/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h index ffbcc62bfa36..75d75bc3669a 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineDominanceFrontier.h @@ -37,9 +37,9 @@ public: MachineDominanceFrontier(); - DominanceFrontierBase<MachineBasicBlock, false> &getBase() { return Base; } + ForwardDominanceFrontierBase<MachineBasicBlock> &getBase() { return Base; } - const SmallVectorImpl<MachineBasicBlock *> &getRoots() const { + const SmallVectorImpl<MachineBasicBlock *> &getRoots() const { return Base.getRoots(); } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineDominators.h b/contrib/llvm/include/llvm/CodeGen/MachineDominators.h index 98fdb51aae2f..e3d3d169db97 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineDominators.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineDominators.h @@ -45,7 +45,7 @@ using MachineDomTreeNode = DomTreeNodeBase<MachineBasicBlock>; /// compute a normal dominator tree. /// class MachineDominatorTree : public MachineFunctionPass { - /// \brief Helper structure used to hold all the basic blocks + /// Helper structure used to hold all the basic blocks /// involved in the split of a critical edge. struct CriticalEdge { MachineBasicBlock *FromBB; @@ -53,12 +53,12 @@ class MachineDominatorTree : public MachineFunctionPass { MachineBasicBlock *NewBB; }; - /// \brief Pile up all the critical edges to be split. + /// Pile up all the critical edges to be split. /// The splitting of a critical edge is local and thus, it is possible /// to apply several of those changes at the same time. mutable SmallVector<CriticalEdge, 32> CriticalEdgesToSplit; - /// \brief Remember all the basic blocks that are inserted during + /// Remember all the basic blocks that are inserted during /// edge splitting. /// Invariant: NewBBs == all the basic blocks contained in the NewBB /// field of all the elements of CriticalEdgesToSplit. @@ -69,7 +69,7 @@ class MachineDominatorTree : public MachineFunctionPass { /// The DominatorTreeBase that is used to compute a normal dominator tree std::unique_ptr<DomTreeBase<MachineBasicBlock>> DT; - /// \brief Apply all the recorded critical edges to the DT. + /// Apply all the recorded critical edges to the DT. /// This updates the underlying DT information in a way that uses /// the fast query path of DT as much as possible. /// @@ -228,7 +228,7 @@ public: void print(raw_ostream &OS, const Module*) const override; - /// \brief Record that the critical edge (FromBB, ToBB) has been + /// Record that the critical edge (FromBB, ToBB) has been /// split with NewBB. /// This is best to use this method instead of directly update the /// underlying information, because this helps mitigating the @@ -249,12 +249,6 @@ public: "A basic block inserted via edge splitting cannot appear twice"); CriticalEdgesToSplit.push_back({FromBB, ToBB, NewBB}); } - - /// \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; }; //===------------------------------------- diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h index f887517217e1..2d6081f3577d 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -85,9 +85,23 @@ public: /// stack offsets of the object, eliminating all MO_FrameIndex operands from /// the program. /// -/// @brief Abstract Stack Frame Information +/// Abstract Stack Frame Information class MachineFrameInfo { +public: + /// Stack Smashing Protection (SSP) rules require that vulnerable stack + /// allocations are located close the stack protector. + enum SSPLayoutKind { + SSPLK_None, ///< Did not trigger a stack protector. No effect on data + ///< layout. + SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest + ///< to the stack protector. + SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest + ///< to the stack protector. + SSPLK_AddrOf ///< The address of this allocation is exposed and + ///< triggered protection. 3rd closest to the protector. + }; +private: // Represent a single object allocated on the stack. struct StackObject { // The offset of this object from the stack pointer on entry to @@ -123,6 +137,9 @@ class MachineFrameInfo { /// necessarily reside in the same contiguous memory block as other stack /// objects. Objects with differing stack IDs should not be merged or /// replaced substituted for each other. + // + /// It is assumed a target uses consecutive, increasing stack IDs starting + /// from 1. uint8_t StackID; /// If this stack object is originated from an Alloca instruction @@ -145,12 +162,15 @@ class MachineFrameInfo { /// If true, the object has been zero-extended. bool isSExt = false; + uint8_t SSPLayout; + StackObject(uint64_t Size, unsigned Alignment, int64_t SPOffset, bool IsImmutable, bool IsSpillSlot, const AllocaInst *Alloca, bool IsAliased, uint8_t StackID = 0) : SPOffset(SPOffset), Size(Size), Alignment(Alignment), isImmutable(IsImmutable), isSpillSlot(IsSpillSlot), - StackID(StackID), Alloca(Alloca), isAliased(IsAliased) {} + StackID(StackID), Alloca(Alloca), isAliased(IsAliased), + SSPLayout(SSPLK_None) {} }; /// The alignment of the stack. @@ -485,6 +505,20 @@ public: Objects[ObjectIdx+NumFixedObjects].SPOffset = SPOffset; } + SSPLayoutKind getObjectSSPLayout(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return (SSPLayoutKind)Objects[ObjectIdx+NumFixedObjects].SSPLayout; + } + + void setObjectSSPLayout(int ObjectIdx, SSPLayoutKind Kind) { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + assert(!isDeadObjectIndex(ObjectIdx) && + "Setting SSP layout for a dead object?"); + Objects[ObjectIdx+NumFixedObjects].SSPLayout = Kind; + } + /// Return the number of bytes that must be allocated to hold /// all of the fixed size frame objects. This is only valid after /// Prolog/Epilog code insertion has finalized the stack frame layout. diff --git a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h index 7d8b7ebe8d62..e8a4d529faac 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineFunction.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineFunction.h @@ -73,6 +73,7 @@ class SlotIndexes; class TargetMachine; class TargetRegisterClass; class TargetSubtargetInfo; +struct WasmEHFuncInfo; struct WinEHFuncInfo; template <> struct ilist_alloc_traits<MachineBasicBlock> { @@ -80,8 +81,8 @@ template <> struct ilist_alloc_traits<MachineBasicBlock> { }; template <> struct ilist_callback_traits<MachineBasicBlock> { - void addNodeToList(MachineBasicBlock* MBB); - void removeNodeFromList(MachineBasicBlock* MBB); + void addNodeToList(MachineBasicBlock* N); + void removeNodeFromList(MachineBasicBlock* N); template <class Iterator> void transferNodesFromList(ilist_callback_traits &OldList, Iterator, Iterator) { @@ -96,7 +97,7 @@ template <> struct ilist_callback_traits<MachineBasicBlock> { struct MachineFunctionInfo { virtual ~MachineFunctionInfo(); - /// \brief Factory function: default behavior is to call new using the + /// Factory function: default behavior is to call new using the /// supplied allocator. /// /// This function can be overridden in a derive class. @@ -245,6 +246,10 @@ class MachineFunction { // Keep track of jump tables for switch instructions MachineJumpTableInfo *JumpTableInfo; + // Keeps track of Wasm exception handling related data. This will be null for + // functions that aren't using a wasm EH personality. + WasmEHFuncInfo *WasmEHInfo = nullptr; + // Keeps track of Windows exception handling related data. This will be null // for functions that aren't using a funclet-based EH personality. WinEHFuncInfo *WinEHInfo = nullptr; @@ -319,6 +324,7 @@ class MachineFunction { bool CallsEHReturn = false; bool CallsUnwindInit = false; + bool HasEHScopes = false; bool HasEHFunclets = false; /// List of C++ TypeInfo used. @@ -349,17 +355,18 @@ public: struct VariableDbgInfo { const DILocalVariable *Var; const DIExpression *Expr; - unsigned Slot; + // The Slot can be negative for fixed stack objects. + int Slot; const DILocation *Loc; VariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr, - unsigned Slot, const DILocation *Loc) + int Slot, const DILocation *Loc) : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} }; using VariableDbgInfoMapTy = SmallVector<VariableDbgInfo, 4>; VariableDbgInfoMapTy VariableDbgInfos; - MachineFunction(const Function &F, const TargetMachine &TM, + MachineFunction(const Function &F, const TargetMachine &Target, const TargetSubtargetInfo &STI, unsigned FunctionNum, MachineModuleInfo &MMI); MachineFunction(const MachineFunction &) = delete; @@ -430,6 +437,12 @@ public: MachineConstantPool *getConstantPool() { return ConstantPool; } const MachineConstantPool *getConstantPool() const { return ConstantPool; } + /// getWasmEHFuncInfo - Return information about how the current function uses + /// Wasm exception handling. Returns null for functions that don't use wasm + /// exception handling. + const WasmEHFuncInfo *getWasmEHFuncInfo() const { return WasmEHInfo; } + WasmEHFuncInfo *getWasmEHFuncInfo() { return WasmEHInfo; } + /// getWinEHFuncInfo - Return information about how the current function uses /// Windows exception handling. Returns null for functions that don't use /// funclets for exception handling. @@ -609,7 +622,7 @@ public: //===--------------------------------------------------------------------===// // Internal functions used to automatically number MachineBasicBlocks - /// \brief Adds the MBB to the internal numbering. Returns the unique number + /// Adds the MBB to the internal numbering. Returns the unique number /// assigned to the MBB. unsigned addToMBBNumbering(MachineBasicBlock *MBB) { MBBNumbering.push_back(MBB); @@ -695,14 +708,8 @@ 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; - } + /// Allocate and initialize a register mask with @p NumRegister bits. + uint32_t *allocateRegMask(); /// allocateMemRefsArray - Allocate an array to hold MachineMemOperand /// pointers. This array is owned by the MachineFunction. @@ -759,6 +766,9 @@ public: bool callsUnwindInit() const { return CallsUnwindInit; } void setCallsUnwindInit(bool b) { CallsUnwindInit = b; } + bool hasEHScopes() const { return HasEHScopes; } + void setHasEHScopes(bool V) { HasEHScopes = V; } + bool hasEHFunclets() const { return HasEHFunclets; } void setHasEHFunclets(bool V) { HasEHFunclets = V; } @@ -793,7 +803,7 @@ public: void addCleanup(MachineBasicBlock *LandingPad); void addSEHCatchHandler(MachineBasicBlock *LandingPad, const Function *Filter, - const BlockAddress *RecoverLabel); + const BlockAddress *RecoverBA); void addSEHCleanupHandler(MachineBasicBlock *LandingPad, const Function *Cleanup); @@ -860,7 +870,7 @@ public: /// Collect information used to emit debugging information of a variable. void setVariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr, - unsigned Slot, const DILocation *Loc) { + int Slot, const DILocation *Loc) { VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc); } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h index 3c1c1bb14f42..88e13cdf4138 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstr.h @@ -80,7 +80,21 @@ public: FrameDestroy = 1 << 1, // Instruction is used as a part of // function frame destruction code. BundledPred = 1 << 2, // Instruction has bundled predecessors. - BundledSucc = 1 << 3 // Instruction has bundled successors. + BundledSucc = 1 << 3, // Instruction has bundled successors. + FmNoNans = 1 << 4, // Instruction does not support Fast + // math nan values. + FmNoInfs = 1 << 5, // Instruction does not support Fast + // math infinity values. + FmNsz = 1 << 6, // Instruction is not required to retain + // signed zero values. + FmArcp = 1 << 7, // Instruction supports Fast math + // reciprocal approximations. + FmContract = 1 << 8, // Instruction supports Fast math + // contraction operations like fma. + FmAfn = 1 << 9, // Instruction may map to Fast math + // instrinsic approximation. + FmReassoc = 1 << 10 // Instruction supports Fast math + // reassociation of operand order. }; private: @@ -93,7 +107,7 @@ private: using OperandCapacity = ArrayRecycler<MachineOperand>::Capacity; OperandCapacity CapOperands; // Capacity of the Operands array. - uint8_t Flags = 0; // Various bits of additional + uint16_t Flags = 0; // Various bits of additional // information about machine // instruction. @@ -127,7 +141,7 @@ private: /// This constructor create a MachineInstr and add the implicit operands. /// It reserves space for number of operands specified by /// MCInstrDesc. An explicit DebugLoc is supplied. - MachineInstr(MachineFunction &, const MCInstrDesc &MCID, DebugLoc dl, + MachineInstr(MachineFunction &, const MCInstrDesc &tid, DebugLoc dl, bool NoImp = false); // MachineInstrs are pool-allocated and owned by MachineFunction. @@ -175,7 +189,7 @@ public: } /// Return the MI flags bitvector. - uint8_t getFlags() const { + uint16_t getFlags() const { return Flags; } @@ -186,7 +200,7 @@ public: /// Set a MI flag. void setFlag(MIFlag Flag) { - Flags |= (uint8_t)Flag; + Flags |= (uint16_t)Flag; } void setFlags(unsigned flags) { @@ -197,7 +211,7 @@ public: /// clearFlag - Clear a MI flag. void clearFlag(MIFlag Flag) { - Flags &= ~((uint8_t)Flag); + Flags &= ~((uint16_t)Flag); } /// Return true if MI is in a bundle (but not the first MI in a bundle). @@ -278,6 +292,10 @@ public: /// this DBG_VALUE instruction. const DIExpression *getDebugExpression() const; + /// Return the debug label referenced by + /// this DBG_LABEL instruction. + const DILabel *getDebugLabel() const; + /// Emit an error referring to the source location of this instruction. /// This should only be used for inline assembly that is somehow /// impossible to compile. Other errors should have been handled much @@ -304,6 +322,11 @@ public: return Operands[i]; } + /// Returns the total number of definitions. + unsigned getNumDefs() const { + return getNumExplicitDefs() + MCID->getNumImplicitDefs(); + } + /// Return true if operand \p OpIdx is a subregister index. bool isOperandSubregIdx(unsigned OpIdx) const { assert(getOperand(OpIdx).getType() == MachineOperand::MO_Immediate && @@ -322,6 +345,9 @@ public: /// Returns the number of non-implicit operands. unsigned getNumExplicitOperands() const; + /// Returns the number of non-implicit definitions. + unsigned getNumExplicitDefs() const; + /// iterator/begin/end - Iterate over all operands of a machine instruction. using mop_iterator = MachineOperand *; using const_mop_iterator = const MachineOperand *; @@ -356,31 +382,29 @@ public: /// Implicit definition are not included! iterator_range<mop_iterator> defs() { return make_range(operands_begin(), - operands_begin() + getDesc().getNumDefs()); + operands_begin() + getNumExplicitDefs()); } /// \copydoc defs() iterator_range<const_mop_iterator> defs() const { return make_range(operands_begin(), - operands_begin() + getDesc().getNumDefs()); + operands_begin() + getNumExplicitDefs()); } /// Returns a range that includes all operands that are register uses. /// This may include unrelated operands which are not register uses. iterator_range<mop_iterator> uses() { - return make_range(operands_begin() + getDesc().getNumDefs(), - operands_end()); + return make_range(operands_begin() + getNumExplicitDefs(), operands_end()); } /// \copydoc uses() iterator_range<const_mop_iterator> uses() const { - return make_range(operands_begin() + getDesc().getNumDefs(), - operands_end()); + return make_range(operands_begin() + getNumExplicitDefs(), operands_end()); } iterator_range<mop_iterator> explicit_uses() { - return make_range(operands_begin() + getDesc().getNumDefs(), - operands_begin() + getNumExplicitOperands() ); + return make_range(operands_begin() + getNumExplicitDefs(), + operands_begin() + getNumExplicitOperands()); } iterator_range<const_mop_iterator> explicit_uses() const { - return make_range(operands_begin() + getDesc().getNumDefs(), - operands_begin() + getNumExplicitOperands() ); + return make_range(operands_begin() + getNumExplicitDefs(), + operands_begin() + getNumExplicitOperands()); } /// Returns the number of the operand iterator \p I points to. @@ -391,7 +415,7 @@ public: /// Access to memory operands of the instruction mmo_iterator memoperands_begin() const { return MemRefs; } mmo_iterator memoperands_end() const { return MemRefs + NumMemRefs; } - /// Return true if we don't have any memory operands which described the the + /// Return true if we don't have any memory operands which described the /// memory access done by this instruction. If this is true, calling code /// must be conservative. bool memoperands_empty() const { return NumMemRefs == 0; } @@ -529,6 +553,12 @@ public: return hasProperty(MCID::MoveImm, Type); } + /// Return true if this instruction is a register move. + /// (including moving values from subreg to reg) + bool isMoveReg(QueryType Type = IgnoreBundle) const { + return hasProperty(MCID::MoveReg, Type); + } + /// Return true if this instruction is a bitcast instruction. bool isBitcast(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Bitcast, Type); @@ -576,7 +606,7 @@ public: return hasProperty(MCID::FoldableAsLoad, Type); } - /// \brief Return true if this instruction behaves + /// Return true if this instruction behaves /// the same way as the generic REG_SEQUENCE instructions. /// E.g., on ARM, /// dX VMOVDRR rY, rZ @@ -590,7 +620,7 @@ public: return hasProperty(MCID::RegSequence, Type); } - /// \brief Return true if this instruction behaves + /// Return true if this instruction behaves /// the same way as the generic EXTRACT_SUBREG instructions. /// E.g., on ARM, /// rX, rY VMOVRRD dZ @@ -605,7 +635,7 @@ public: return hasProperty(MCID::ExtractSubreg, Type); } - /// \brief Return true if this instruction behaves + /// Return true if this instruction behaves /// the same way as the generic INSERT_SUBREG instructions. /// E.g., on ARM, /// dX = VSETLNi32 dY, rZ, Imm @@ -817,6 +847,8 @@ public: bool isPosition() const { return isLabel() || isCFIInstruction(); } bool isDebugValue() const { return getOpcode() == TargetOpcode::DBG_VALUE; } + bool isDebugLabel() const { return getOpcode() == TargetOpcode::DBG_LABEL; } + bool isDebugInstr() const { return isDebugValue() || isDebugLabel(); } /// A DBG_VALUE is indirect iff the first operand is a register and /// the second operand is an immediate. @@ -893,6 +925,9 @@ public: case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: case TargetOpcode::DBG_VALUE: + case TargetOpcode::DBG_LABEL: + case TargetOpcode::LIFETIME_START: + case TargetOpcode::LIFETIME_END: return true; } } @@ -1047,7 +1082,7 @@ public: const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const; - /// \brief Applies the constraints (def/use) implied by this MI on \p Reg to + /// 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, @@ -1064,7 +1099,7 @@ public: const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, bool ExploreBundle = false) const; - /// \brief Applies the constraints (def/use) implied by the \p OpIdx operand + /// Applies the constraints (def/use) implied by the \p OpIdx operand /// to the given \p CurRC. /// /// Returns the register class that satisfies both \p CurRC and the @@ -1233,15 +1268,20 @@ public: bool hasComplexRegisterTies() const; /// Print this MI to \p OS. + /// Don't print information that can be inferred from other instructions if + /// \p IsStandalone is false. It is usually true when only a fragment of the + /// function is printed. /// Only print the defs and the opcode if \p SkipOpers is true. /// Otherwise, also print operands if \p SkipDebugLoc is true. /// Otherwise, also print the debug loc, with a terminating newline. /// \p TII is used to print the opcode name. If it's not present, but the /// MI is in a function, the opcode will be printed using the function's TII. - void print(raw_ostream &OS, bool SkipOpers = false, bool SkipDebugLoc = false, + void print(raw_ostream &OS, bool IsStandalone = true, bool SkipOpers = false, + bool SkipDebugLoc = false, bool AddNewLine = true, const TargetInstrInfo *TII = nullptr) const; - void print(raw_ostream &OS, ModuleSlotTracker &MST, bool SkipOpers = false, - bool SkipDebugLoc = false, + void print(raw_ostream &OS, ModuleSlotTracker &MST, bool IsStandalone = true, + bool SkipOpers = false, bool SkipDebugLoc = false, + bool AddNewLine = true, const TargetInstrInfo *TII = nullptr) const; void dump() const; /// @} @@ -1281,7 +1321,7 @@ public: /// Erase an operand from an instruction, leaving it with one /// fewer operand than it started with. - void RemoveOperand(unsigned i); + void RemoveOperand(unsigned OpNo); /// Add a MachineMemOperand to the machine instruction. /// This function should be used only occasionally. The setMemRefs function @@ -1311,6 +1351,11 @@ public: /// modify the memrefs of the this MachineInstr. std::pair<mmo_iterator, unsigned> mergeMemRefsWith(const MachineInstr& Other); + /// Return the MIFlags which represent both MachineInstrs. This + /// should be used when merging two MachineInstrs into one. This routine does + /// not modify the MIFlags of this MachineInstr. + uint16_t mergeFlagsWith(const MachineInstr& Other) const; + /// Clear this MachineInstr's memory reference descriptor list. This resets /// the memrefs to their most conservative state. This should be used only /// as a last resort since it greatly pessimizes our knowledge of the memory @@ -1351,7 +1396,7 @@ private: /// 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 + /// 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( diff --git a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h index e4f3976ec950..665608755741 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -20,6 +20,7 @@ #define LLVM_CODEGEN_MACHINEINSTRBUILDER_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" @@ -219,6 +220,9 @@ public: assert((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable()) : true) && "first MDNode argument of a DBG_VALUE not a variable"); + assert((MI->isDebugLabel() ? static_cast<bool>(MI->getDebugLabel()) + : true) && + "first MDNode argument of a DBG_LABEL not a label"); return *this; } @@ -283,6 +287,12 @@ public: MI->copyImplicitOps(*MF, OtherMI); return *this; } + + bool constrainAllUses(const TargetInstrInfo &TII, + const TargetRegisterInfo &TRI, + const RegisterBankInfo &RBI) const { + return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); + } }; /// Builder interface. Specify how to create the initial instruction itself. @@ -408,6 +418,13 @@ MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MDNode *Expr); /// This version of the builder builds a DBG_VALUE intrinsic +/// for a MachineOperand. +MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, + const MCInstrDesc &MCID, bool IsIndirect, + MachineOperand &MO, const MDNode *Variable, + const MDNode *Expr); + +/// This version of the builder builds a DBG_VALUE intrinsic /// for either a value in a register or a register-indirect /// address and inserts it at position I. MachineInstrBuilder BuildMI(MachineBasicBlock &BB, @@ -416,6 +433,14 @@ MachineInstrBuilder BuildMI(MachineBasicBlock &BB, unsigned Reg, const MDNode *Variable, const MDNode *Expr); +/// This version of the builder builds a DBG_VALUE intrinsic +/// for a machine operand and inserts it at position I. +MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, const DebugLoc &DL, + const MCInstrDesc &MCID, bool IsIndirect, + MachineOperand &MO, const MDNode *Variable, + const MDNode *Expr); + /// Clone a DBG_VALUE whose value has been spilled to FrameIndex. MachineInstr *buildDbgValueForSpill(MachineBasicBlock &BB, MachineBasicBlock::iterator I, diff --git a/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h index 104655e45524..917fb90380f5 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineLoopInfo.h @@ -54,7 +54,7 @@ public: /// that contains the header. MachineBasicBlock *getBottomBlock(); - /// \brief Find the block that contains the loop control variable and the + /// Find the block that contains the loop control variable and the /// loop test. This will return the latch block if it's one of the exiting /// blocks. Otherwise, return the exiting block. Return 'null' when /// multiple exiting blocks are present. @@ -97,7 +97,7 @@ public: LoopInfoBase<MachineBasicBlock, MachineLoop>& getBase() { return LI; } - /// \brief Find the block that either is the loop preheader, or could + /// Find the block that either is the loop preheader, or could /// speculatively be used as the preheader. This is e.g. useful to place /// loop setup code. Code that cannot be speculated should not be placed /// here. SpeculativePreheader is controlling whether it also tries to diff --git a/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h b/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h index c5b204a79f04..078ef7ca510c 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineMemOperand.h @@ -184,7 +184,7 @@ public: /// atomic operations the atomic ordering requirements when store does not /// occur must also be specified. MachineMemOperand(MachinePointerInfo PtrInfo, Flags flags, uint64_t s, - unsigned base_alignment, + uint64_t a, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr, SyncScope::ID SSID = SyncScope::System, @@ -295,6 +295,9 @@ public: /// @{ void print(raw_ostream &OS) const; void print(raw_ostream &OS, ModuleSlotTracker &MST) const; + void print(raw_ostream &OS, ModuleSlotTracker &MST, + SmallVectorImpl<StringRef> &SSNs, const LLVMContext &Context, + const MachineFrameInfo *MFI, const TargetInstrInfo *TII) const; /// @} friend bool operator==(const MachineMemOperand &LHS, diff --git a/contrib/llvm/include/llvm/CodeGen/MachineOperand.h b/contrib/llvm/include/llvm/CodeGen/MachineOperand.h index 4be7942c2c64..53e8889d118a 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineOperand.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineOperand.h @@ -74,7 +74,7 @@ public: private: /// OpKind - Specify what kind of operand this is. This discriminates the /// union. - MachineOperandType OpKind : 8; + unsigned OpKind : 8; /// Subregister number for MO_Register. A value of 0 indicates the /// MO_Register has no subReg. @@ -85,17 +85,17 @@ private: /// TiedTo - Non-zero when this register operand is tied to another register /// operand. The encoding of this field is described in the block comment /// before MachineInstr::tieOperands(). - unsigned char TiedTo : 4; + unsigned TiedTo : 4; /// IsDef - True if this is a def, false if this is a use of the register. /// This is only valid on register operands. /// - bool IsDef : 1; + unsigned IsDef : 1; /// IsImp - True if this is an implicit def or use, false if it is explicit. /// This is only valid on register opderands. /// - bool IsImp : 1; + unsigned IsImp : 1; /// IsDeadOrKill /// For uses: IsKill - True if this instruction is the last use of the @@ -103,14 +103,10 @@ private: /// For defs: IsDead - True if this register is never used by a subsequent /// instruction. /// This is only valid on register operands. - bool IsDeadOrKill : 1; + unsigned IsDeadOrKill : 1; - /// IsRenamable - True if this register may be renamed, i.e. it does not - /// generate a value that is somehow read in a way that is not represented by - /// the Machine IR (e.g. to meet an ABI or ISA requirement). This is only - /// valid on physical register operands. Virtual registers are assumed to - /// always be renamable regardless of the value of this field. - bool IsRenamable : 1; + /// See isRenamable(). + unsigned IsRenamable : 1; /// IsUndef - True if this register operand reads an "undef" value, i.e. the /// read value doesn't matter. This flag can be set on both use and def @@ -129,7 +125,7 @@ private: /// Any register can be used for %2, and its value doesn't matter, but /// the two operands must be the same register. /// - bool IsUndef : 1; + unsigned IsUndef : 1; /// IsInternalRead - True if this operand reads a value that was defined /// inside the same instruction or bundle. This flag can be set on both use @@ -140,16 +136,16 @@ private: /// When this flag is set, the instruction bundle must contain at least one /// other def of the register. If multiple instructions in the bundle define /// the register, the meaning is target-defined. - bool IsInternalRead : 1; + unsigned IsInternalRead : 1; /// IsEarlyClobber - True if this MO_Register 'def' operand is written to /// by the MachineInstr before all input registers are read. This is used to /// model the GCC inline asm '&' constraint modifier. - bool IsEarlyClobber : 1; + unsigned IsEarlyClobber : 1; /// IsDebug - True if this MO_Register 'use' operand is in a debug pseudo, /// not a real instruction. Such uses should be ignored during codegen. - bool IsDebug : 1; + unsigned IsDebug : 1; /// SmallContents - This really should be part of the Contents union, but /// lives out here so we can get a better packed struct. @@ -198,7 +194,19 @@ private: } Contents; explicit MachineOperand(MachineOperandType K) - : OpKind(K), SubReg_TargetFlags(0), ParentMI(nullptr) {} + : OpKind(K), SubReg_TargetFlags(0), ParentMI(nullptr) { + // Assert that the layout is what we expect. It's easy to grow this object. + static_assert(alignof(MachineOperand) <= alignof(int64_t), + "MachineOperand shouldn't be more than 8 byte aligned"); + static_assert(sizeof(Contents) <= 2 * sizeof(void *), + "Contents should be at most two pointers"); + static_assert(sizeof(MachineOperand) <= + alignTo<alignof(int64_t)>(2 * sizeof(unsigned) + + 3 * sizeof(void *)), + "MachineOperand too big. Should be Kind, SmallContents, " + "ParentMI, and Contents"); + } + public: /// getType - Returns the MachineOperandType for this operand. /// @@ -238,7 +246,7 @@ public: /// MO_Immediate operands can also be subreg idices. If it's the case, the /// subreg index name will be printed. MachineInstr::isOperandSubregIdx can be /// called to check this. - static void printSubregIdx(raw_ostream &OS, uint64_t Index, + static void printSubRegIdx(raw_ostream &OS, uint64_t Index, const TargetRegisterInfo *TRI); /// Print operand target flags. @@ -270,6 +278,9 @@ public: /// \param PrintDef - whether we want to print `def` on an operand which /// isDef. Sometimes, if the operand is printed before '=', we don't print /// `def`. + /// \param IsStandalone - whether we want a verbose output of the MO. This + /// prints extra information that can be easily inferred when printing the + /// whole function, but not when printing only a fragment of it. /// \param ShouldPrintRegisterTies - whether we want to print register ties. /// Sometimes they are easily determined by the instruction's descriptor /// (MachineInstr::hasComplexRegiterTies can determine if it's needed). @@ -280,10 +291,16 @@ public: /// information from it's parent. /// \param IntrinsicInfo - same as \p TRI. void print(raw_ostream &os, ModuleSlotTracker &MST, LLT TypeToPrint, - bool PrintDef, bool ShouldPrintRegisterTies, + bool PrintDef, bool IsStandalone, bool ShouldPrintRegisterTies, unsigned TiedOperandIdx, const TargetRegisterInfo *TRI, const TargetIntrinsicInfo *IntrinsicInfo) const; + /// Same as print(os, TRI, IntrinsicInfo), but allows to specify the low-level + /// type to be printed the same way the full version of print(...) does it. + void print(raw_ostream &os, LLT TypeToPrint, + const TargetRegisterInfo *TRI = nullptr, + const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const; + void dump() const; //===--------------------------------------------------------------------===// @@ -369,6 +386,35 @@ public: return IsUndef; } + /// isRenamable - Returns true if this register may be renamed, i.e. it does + /// not generate a value that is somehow read in a way that is not represented + /// by the Machine IR (e.g. to meet an ABI or ISA requirement). This is only + /// valid on physical register operands. Virtual registers are assumed to + /// always be renamable regardless of the value of this field. + /// + /// Operands that are renamable can freely be changed to any other register + /// that is a member of the register class returned by + /// MI->getRegClassConstraint(). + /// + /// isRenamable can return false for several different reasons: + /// + /// - ABI constraints (since liveness is not always precisely modeled). We + /// conservatively handle these cases by setting all physical register + /// operands that didn’t start out as virtual regs to not be renamable. + /// Also any physical register operands created after register allocation or + /// whose register is changed after register allocation will not be + /// renamable. This state is tracked in the MachineOperand::IsRenamable + /// bit. + /// + /// - Opcode/target constraints: for opcodes that have complex register class + /// requirements (e.g. that depend on other operands/instructions), we set + /// hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq in the machine opcode + /// description. Operands belonging to instructions with opcodes that are + /// marked hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq return false from + /// isRenamable(). Additionally, the AllowRegisterRenaming target property + /// prevents any operands from being marked renamable for targets that don't + /// have detailed opcode hasExtraSrcRegAllocReq/hasExtraDstRegAllocReq + /// values. bool isRenamable() const; bool isInternalRead() const { @@ -458,10 +504,6 @@ public: void setIsRenamable(bool Val = true); - /// Set IsRenamable to true if there are no extra register allocation - /// requirements placed on this operand by the parent instruction's opcode. - void setIsRenamableIfNoExtraRegAllocReq(); - void setIsInternalRead(bool Val = true) { assert(isReg() && "Wrong MachineOperand mutator"); IsInternalRead = Val; @@ -574,6 +616,11 @@ public: return Contents.RegMask; } + /// Returns number of elements needed for a regmask array. + static unsigned getRegMaskSize(unsigned NumRegs) { + return (NumRegs + 31) / 32; + } + /// getRegLiveOut - Returns a bit mask of live-out registers. const uint32_t *getRegLiveOut() const { assert(isRegLiveOut() && "Wrong MachineOperand accessor"); @@ -594,6 +641,11 @@ public: Contents.ImmVal = immVal; } + void setCImm(const ConstantInt *CI) { + assert(isCImm() && "Wrong MachineOperand mutator"); + Contents.CI = CI; + } + void setFPImm(const ConstantFP *CFP) { assert(isFPImm() && "Wrong MachineOperand mutator"); Contents.CFP = CFP; @@ -641,7 +693,7 @@ public: /// should stay in sync with the hash_value overload below. bool isIdenticalTo(const MachineOperand &Other) const; - /// \brief MachineOperand hash_value overload. + /// MachineOperand hash_value overload. /// /// Note that this includes the same information in the hash that /// isIdenticalTo uses for comparison. It is thus suited for use in hash diff --git a/contrib/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h b/contrib/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h index 2fdefbed37ce..a7ce870400c2 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h @@ -24,7 +24,7 @@ class MachineBasicBlock; class MachineBlockFrequencyInfo; class MachineInstr; -/// \brief Common features for diagnostics dealing with optimization remarks +/// Common features for diagnostics dealing with optimization remarks /// that are used by machine passes. class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase { public: @@ -151,7 +151,7 @@ public: /// Emit an optimization remark. void emit(DiagnosticInfoOptimizationBase &OptDiag); - /// \brief Whether we allow for extra compile-time budget to perform more + /// Whether we allow for extra compile-time budget to perform more /// analysis to be more informative. /// /// This is useful to enable additional missed optimizations to be reported @@ -164,7 +164,7 @@ public: .getDiagHandlerPtr()->isAnyRemarkEnabled(PassName)); } - /// \brief Take a lambda that returns a remark which will be emitted. Second + /// Take a lambda that returns a remark which will be emitted. Second /// argument is only used to restrict this to functions. template <typename T> void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { @@ -192,7 +192,7 @@ private: /// Similar but use value from \p OptDiag and update hotness there. void computeHotness(DiagnosticInfoMIROptimization &Remark); - /// \brief Only allow verbose messages if we know we're filtering by hotness + /// Only allow verbose messages if we know we're filtering by hotness /// (BFI is only set in this case). bool shouldEmitVerbose() { return MBFI != nullptr; } }; diff --git a/contrib/llvm/include/llvm/CodeGen/MachineOutliner.h b/contrib/llvm/include/llvm/CodeGen/MachineOutliner.h new file mode 100644 index 000000000000..4249a99a891b --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/MachineOutliner.h @@ -0,0 +1,226 @@ +//===---- MachineOutliner.h - Outliner data structures ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Contains all data structures shared between the outliner implemented in +/// MachineOutliner.cpp and target implementations of the outliner. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MACHINEOUTLINER_H +#define LLVM_MACHINEOUTLINER_H + +#include "llvm/CodeGen/LiveRegUnits.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" + +namespace llvm { +namespace outliner { + +/// Represents how an instruction should be mapped by the outliner. +/// \p Legal instructions are those which are safe to outline. +/// \p LegalTerminator instructions are safe to outline, but only as the +/// last instruction in a sequence. +/// \p Illegal instructions are those which cannot be outlined. +/// \p Invisible instructions are instructions which can be outlined, but +/// shouldn't actually impact the outlining result. +enum InstrType { Legal, LegalTerminator, Illegal, Invisible }; + +/// An individual sequence of instructions to be replaced with a call to +/// an outlined function. +struct Candidate { +private: + /// The start index of this \p Candidate in the instruction list. + unsigned StartIdx; + + /// The number of instructions in this \p Candidate. + unsigned Len; + + // The first instruction in this \p Candidate. + MachineBasicBlock::iterator FirstInst; + + // The last instruction in this \p Candidate. + MachineBasicBlock::iterator LastInst; + + // The basic block that contains this Candidate. + MachineBasicBlock *MBB; + + /// Cost of calling an outlined function from this point as defined by the + /// target. + unsigned CallOverhead; + +public: + /// The index of this \p Candidate's \p OutlinedFunction in the list of + /// \p OutlinedFunctions. + unsigned FunctionIdx; + + /// Set to false if the candidate overlapped with another candidate. + bool InCandidateList = true; + + /// Identifier denoting the instructions to emit to call an outlined function + /// from this point. Defined by the target. + unsigned CallConstructionID; + + /// Contains physical register liveness information for the MBB containing + /// this \p Candidate. + /// + /// This is optionally used by the target to calculate more fine-grained + /// cost model information. + LiveRegUnits LRU; + + /// Return the number of instructions in this Candidate. + unsigned getLength() const { return Len; } + + /// Return the start index of this candidate. + unsigned getStartIdx() const { return StartIdx; } + + /// Return the end index of this candidate. + unsigned getEndIdx() const { return StartIdx + Len - 1; } + + /// Set the CallConstructionID and CallOverhead of this candidate to CID and + /// CO respectively. + void setCallInfo(unsigned CID, unsigned CO) { + CallConstructionID = CID; + CallOverhead = CO; + } + + /// Returns the call overhead of this candidate if it is in the list. + unsigned getCallOverhead() const { + return InCandidateList ? CallOverhead : 0; + } + + MachineBasicBlock::iterator &front() { return FirstInst; } + MachineBasicBlock::iterator &back() { return LastInst; } + MachineFunction *getMF() const { return MBB->getParent(); } + MachineBasicBlock *getMBB() const { return MBB; } + + /// The number of instructions that would be saved by outlining every + /// candidate of this type. + /// + /// This is a fixed value which is not updated during the candidate pruning + /// process. It is only used for deciding which candidate to keep if two + /// candidates overlap. The true benefit is stored in the OutlinedFunction + /// for some given candidate. + unsigned Benefit = 0; + + Candidate(unsigned StartIdx, unsigned Len, + MachineBasicBlock::iterator &FirstInst, + MachineBasicBlock::iterator &LastInst, MachineBasicBlock *MBB, + unsigned FunctionIdx) + : StartIdx(StartIdx), Len(Len), FirstInst(FirstInst), LastInst(LastInst), + MBB(MBB), FunctionIdx(FunctionIdx) {} + Candidate() {} + + /// Used to ensure that \p Candidates are outlined in an order that + /// preserves the start and end indices of other \p Candidates. + bool operator<(const Candidate &RHS) const { + return getStartIdx() > RHS.getStartIdx(); + } + + /// Compute the registers that are live across this Candidate. + /// Used by targets that need this information for cost model calculation. + /// If a target does not need this information, then this should not be + /// called. + void initLRU(const TargetRegisterInfo &TRI) { + assert(MBB->getParent()->getRegInfo().tracksLiveness() && + "Candidate's Machine Function must track liveness"); + LRU.init(TRI); + LRU.addLiveOuts(*MBB); + + // Compute liveness from the end of the block up to the beginning of the + // outlining candidate. + std::for_each(MBB->rbegin(), (MachineBasicBlock::reverse_iterator)front(), + [this](MachineInstr &MI) { LRU.stepBackward(MI); }); + } +}; + +/// The information necessary to create an outlined function for some +/// class of candidate. +struct OutlinedFunction { + +private: + /// The number of candidates for this \p OutlinedFunction. + unsigned OccurrenceCount = 0; + +public: + std::vector<std::shared_ptr<Candidate>> Candidates; + + /// The actual outlined function created. + /// This is initialized after we go through and create the actual function. + MachineFunction *MF = nullptr; + + /// A number assigned to this function which appears at the end of its name. + unsigned Name; + + /// The sequence of integers corresponding to the instructions in this + /// function. + std::vector<unsigned> Sequence; + + /// Represents the size of a sequence in bytes. (Some instructions vary + /// widely in size, so just counting the instructions isn't very useful.) + unsigned SequenceSize; + + /// Target-defined overhead of constructing a frame for this function. + unsigned FrameOverhead; + + /// Target-defined identifier for constructing a frame for this function. + unsigned FrameConstructionID; + + /// Return the number of candidates for this \p OutlinedFunction. + unsigned getOccurrenceCount() { return OccurrenceCount; } + + /// Decrement the occurrence count of this OutlinedFunction and return the + /// new count. + unsigned decrement() { + assert(OccurrenceCount > 0 && "Can't decrement an empty function!"); + OccurrenceCount--; + return getOccurrenceCount(); + } + + /// Return the number of bytes it would take to outline this + /// function. + unsigned getOutliningCost() { + unsigned CallOverhead = 0; + for (std::shared_ptr<Candidate> &C : Candidates) + CallOverhead += C->getCallOverhead(); + return CallOverhead + SequenceSize + FrameOverhead; + } + + /// Return the size in bytes of the unoutlined sequences. + unsigned getNotOutlinedCost() { return OccurrenceCount * SequenceSize; } + + /// Return the number of instructions that would be saved by outlining + /// this function. + unsigned getBenefit() { + unsigned NotOutlinedCost = getNotOutlinedCost(); + unsigned OutlinedCost = getOutliningCost(); + return (NotOutlinedCost < OutlinedCost) ? 0 + : NotOutlinedCost - OutlinedCost; + } + + OutlinedFunction(std::vector<Candidate> &Cands, + unsigned SequenceSize, unsigned FrameOverhead, + unsigned FrameConstructionID) + : SequenceSize(SequenceSize), FrameOverhead(FrameOverhead), + FrameConstructionID(FrameConstructionID) { + OccurrenceCount = Cands.size(); + for (Candidate &C : Cands) + Candidates.push_back(std::make_shared<outliner::Candidate>(C)); + + unsigned B = getBenefit(); + for (std::shared_ptr<Candidate> &C : Candidates) + C->Benefit = B; + } + + OutlinedFunction() {} +}; +} // namespace outliner +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 3be94f802170..5bf4a49c8b3b 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -20,6 +20,7 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/LowLevelType.h" @@ -75,6 +76,13 @@ private: VirtReg2IndexFunctor> VRegInfo; + /// Map for recovering vreg name from vreg number. + /// This map is used by the MIR Printer. + IndexedMap<std::string, VirtReg2IndexFunctor> VReg2Name; + + /// StringSet that is used to unique vreg names. + StringSet<> VRegNames; + /// The flag is true upon \p UpdatedCSRs initialization /// and false otherwise. bool IsUpdatedCSRsInitialized; @@ -128,9 +136,9 @@ private: /// started. BitVector ReservedRegs; - using VRegToTypeMap = DenseMap<unsigned, LLT>; - /// Map generic virtual registers to their actual size. - mutable std::unique_ptr<VRegToTypeMap> VRegToType; + using VRegToTypeMap = IndexedMap<LLT, VirtReg2IndexFunctor>; + /// Map generic virtual registers to their low-level type. + VRegToTypeMap VRegToType; /// Keep track of the physical registers that are live in to the function. /// Live in values are typically arguments in registers. LiveIn values are @@ -418,6 +426,20 @@ public: /// specified register (it may be live-in). bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); } + StringRef getVRegName(unsigned Reg) const { + return VReg2Name.inBounds(Reg) ? StringRef(VReg2Name[Reg]) : ""; + } + + void insertVRegByName(StringRef Name, unsigned Reg) { + assert((Name.empty() || VRegNames.find(Name) == VRegNames.end()) && + "Named VRegs Must be Unique."); + if (!Name.empty()) { + VRegNames.insert(Name); + VReg2Name.grow(Reg); + VReg2Name[Reg] = Name.str(); + } + } + /// Return true if there is exactly one operand defining the specified /// register. bool hasOneDef(unsigned RegNo) const { @@ -548,12 +570,16 @@ public: /// except that it also changes any definitions of the register as well. /// /// Note that it is usually necessary to first constrain ToReg's register - /// class to match the FromReg constraints using: + /// class and register bank to match the FromReg constraints using one of the + /// methods: /// /// constrainRegClass(ToReg, getRegClass(FromReg)) + /// constrainRegAttrs(ToReg, FromReg) + /// RegisterBankInfo::constrainGenericRegister(ToReg, + /// *MRI.getRegClass(FromReg), MRI) /// - /// That function will return NULL if the virtual registers have incompatible - /// constraints. + /// These functions will return a falsy result if the virtual registers have + /// incompatible constraints. /// /// Note that if ToReg is a physical register the function will replace and /// apply sub registers to ToReg in order to obtain a final/proper physical @@ -653,10 +679,30 @@ public: /// new register class, or NULL if no such class exists. /// This should only be used when the constraint is known to be trivial, like /// GR32 -> GR32_NOSP. Beware of increasing register pressure. + /// + /// \note Assumes that the register has a register class assigned. + /// Use RegisterBankInfo::constrainGenericRegister in GlobalISel's + /// InstructionSelect pass and constrainRegAttrs in every other pass, + /// including non-select passes of GlobalISel, instead. const TargetRegisterClass *constrainRegClass(unsigned Reg, const TargetRegisterClass *RC, unsigned MinNumRegs = 0); + /// Constrain the register class or the register bank of the virtual register + /// \p Reg to be a common subclass and a common bank of both registers + /// provided respectively. Do nothing if any of the attributes (classes, + /// banks, or low-level types) of the registers are deemed incompatible, or if + /// the resulting register will have a class smaller than before and of size + /// less than \p MinNumRegs. Return true if such register attributes exist, + /// false otherwise. + /// + /// \note Assumes that each register has either a low-level type or a class + /// assigned, but not both. Use this method instead of constrainRegClass and + /// RegisterBankInfo::constrainGenericRegister everywhere but SelectionDAG + /// ISel / FastISel and GlobalISel's InstructionSelect pass respectively. + bool constrainRegAttrs(unsigned Reg, unsigned ConstrainingReg, + unsigned MinNumRegs = 0); + /// recomputeRegClass - Try to find a legal super-class of Reg's register /// class that still satisfies the constraints from the instructions using /// Reg. Returns true if Reg was upgraded. @@ -668,26 +714,23 @@ public: /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. - unsigned createVirtualRegister(const TargetRegisterClass *RegClass); + unsigned createVirtualRegister(const TargetRegisterClass *RegClass, + StringRef Name = ""); - /// Accessor for VRegToType. This accessor should only be used - /// by global-isel related work. - VRegToTypeMap &getVRegToType() const { - if (!VRegToType) - VRegToType.reset(new VRegToTypeMap); - return *VRegToType.get(); - } - - /// Get the low-level type of \p VReg or LLT{} if VReg is not a generic + /// Get the low-level type of \p Reg or LLT{} if Reg is not a generic /// (target independent) virtual register. - LLT getType(unsigned VReg) const; + LLT getType(unsigned Reg) const { + if (TargetRegisterInfo::isVirtualRegister(Reg) && VRegToType.inBounds(Reg)) + return VRegToType[Reg]; + return LLT{}; + } /// Set the low-level type of \p VReg to \p Ty. void setType(unsigned VReg, LLT Ty); /// Create and return a new generic virtual register with low-level /// type \p Ty. - unsigned createGenericVirtualRegister(LLT Ty); + unsigned createGenericVirtualRegister(LLT Ty, StringRef Name = ""); /// Remove all types associated to virtual registers (after instruction /// selection and constraining of all generic virtual registers). @@ -698,7 +741,7 @@ public: /// temporarily while constructing machine instructions. Most operations are /// undefined on an incomplete register until one of setRegClass(), /// setRegBank() or setSize() has been called on it. - unsigned createIncompleteVirtualRegister(); + unsigned createIncompleteVirtualRegister(StringRef Name = ""); /// getNumVirtRegs - Return the number of virtual registers created. unsigned getNumVirtRegs() const { return VRegInfo.size(); } diff --git a/contrib/llvm/include/llvm/CodeGen/MachineSSAUpdater.h b/contrib/llvm/include/llvm/CodeGen/MachineSSAUpdater.h index b5ea2080444d..5e91246b402c 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineSSAUpdater.h @@ -56,7 +56,7 @@ public: /// MachineSSAUpdater constructor. If InsertedPHIs is specified, it will be /// filled in with all PHI Nodes created by rewriting. explicit MachineSSAUpdater(MachineFunction &MF, - SmallVectorImpl<MachineInstr*> *InsertedPHIs = nullptr); + SmallVectorImpl<MachineInstr*> *NewPHI = nullptr); MachineSSAUpdater(const MachineSSAUpdater &) = delete; MachineSSAUpdater &operator=(const MachineSSAUpdater &) = delete; ~MachineSSAUpdater(); diff --git a/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h b/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h index e327881de13a..85ffa4eda2b8 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h +++ b/contrib/llvm/include/llvm/CodeGen/MachineScheduler.h @@ -237,7 +237,7 @@ public: /// be scheduled at the bottom. virtual SUnit *pickNode(bool &IsTopNode) = 0; - /// \brief Scheduler callback to notify that a new subtree is scheduled. + /// Scheduler callback to notify that a new subtree is scheduled. virtual void scheduleTree(unsigned SubtreeID) {} /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an @@ -318,11 +318,11 @@ public: Mutations.push_back(std::move(Mutation)); } - /// \brief True if an edge can be added from PredSU to SuccSU without creating + /// True if an edge can be added from PredSU to SuccSU without creating /// a cycle. bool canAddEdge(SUnit *SuccSU, SUnit *PredSU); - /// \brief Add a DAG edge to the given SU with the given predecessor + /// Add a DAG edge to the given SU with the given predecessor /// dependence data. /// /// \returns true if the edge may be added without creating a cycle OR if an @@ -374,7 +374,7 @@ protected: /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues. void placeDebugValues(); - /// \brief dump the scheduled Sequence. + /// dump the scheduled Sequence. void dumpSchedule() const; // Lesser helpers... @@ -445,7 +445,7 @@ public: /// 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. + /// Return true if register pressure tracking is enabled. bool isTrackingPressure() const { return ShouldTrackPressure; } /// Get current register pressure for the top scheduled instructions. @@ -897,6 +897,28 @@ protected: #endif }; +// Utility functions used by heuristics in tryCandidate(). +bool tryLess(int TryVal, int CandVal, + GenericSchedulerBase::SchedCandidate &TryCand, + GenericSchedulerBase::SchedCandidate &Cand, + GenericSchedulerBase::CandReason Reason); +bool tryGreater(int TryVal, int CandVal, + GenericSchedulerBase::SchedCandidate &TryCand, + GenericSchedulerBase::SchedCandidate &Cand, + GenericSchedulerBase::CandReason Reason); +bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand, + GenericSchedulerBase::SchedCandidate &Cand, + SchedBoundary &Zone); +bool tryPressure(const PressureChange &TryP, + const PressureChange &CandP, + GenericSchedulerBase::SchedCandidate &TryCand, + GenericSchedulerBase::SchedCandidate &Cand, + GenericSchedulerBase::CandReason Reason, + const TargetRegisterInfo *TRI, + const MachineFunction &MF); +unsigned getWeakLeft(const SUnit *SU, bool isTop); +int biasPhysRegCopy(const SUnit *SU, bool isTop); + /// GenericScheduler shrinks the unscheduled zone using heuristics to balance /// the schedule. class GenericScheduler : public GenericSchedulerBase { @@ -963,9 +985,8 @@ protected: const RegPressureTracker &RPTracker, RegPressureTracker &TempTracker); - void tryCandidate(SchedCandidate &Cand, - SchedCandidate &TryCand, - SchedBoundary *Zone); + virtual void tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand, + SchedBoundary *Zone) const; SUnit *pickNodeBidirectional(bool &IsTopNode); diff --git a/contrib/llvm/include/llvm/CodeGen/MacroFusion.h b/contrib/llvm/include/llvm/CodeGen/MacroFusion.h index dc105fdc68fd..a77226ddaf33 100644 --- a/contrib/llvm/include/llvm/CodeGen/MacroFusion.h +++ b/contrib/llvm/include/llvm/CodeGen/MacroFusion.h @@ -25,7 +25,7 @@ class ScheduleDAGMutation; class TargetInstrInfo; class TargetSubtargetInfo; -/// \brief Check if the instr pair, FirstMI and SecondMI, should be fused +/// Check if the instr pair, FirstMI and SecondMI, should be fused /// together. Given SecondMI, when FirstMI is unspecified, then check if /// SecondMI may be part of a fused pair at all. using ShouldSchedulePredTy = std::function<bool(const TargetInstrInfo &TII, @@ -33,13 +33,13 @@ using ShouldSchedulePredTy = std::function<bool(const TargetInstrInfo &TII, const MachineInstr *FirstMI, const MachineInstr &SecondMI)>; -/// \brief Create a DAG scheduling mutation to pair instructions back to back +/// Create a DAG scheduling mutation to pair instructions back to back /// for instructions that benefit according to the target-specific /// shouldScheduleAdjacent predicate function. std::unique_ptr<ScheduleDAGMutation> createMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent); -/// \brief Create a DAG scheduling mutation to pair branch instructions with one +/// Create a DAG scheduling mutation to pair branch instructions with one /// of their predecessors back to back for instructions that benefit according /// to the target-specific shouldScheduleAdjacent predicate function. std::unique_ptr<ScheduleDAGMutation> diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h index e94878ced10d..a6d88b057dcb 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Graph.h @@ -29,12 +29,12 @@ namespace PBQP { using NodeId = unsigned; using EdgeId = unsigned; - /// @brief Returns a value representing an invalid (non-existent) node. + /// Returns a value representing an invalid (non-existent) node. static NodeId invalidNodeId() { return std::numeric_limits<NodeId>::max(); } - /// @brief Returns a value representing an invalid (non-existent) edge. + /// Returns a value representing an invalid (non-existent) edge. static EdgeId invalidEdgeId() { return std::numeric_limits<EdgeId>::max(); } @@ -338,19 +338,19 @@ namespace PBQP { const NodeEntry &NE; }; - /// @brief Construct an empty PBQP graph. + /// Construct an empty PBQP graph. Graph() = default; - /// @brief Construct an empty PBQP graph with the given graph metadata. + /// Construct an empty PBQP graph with the given graph metadata. Graph(GraphMetadata Metadata) : Metadata(std::move(Metadata)) {} - /// @brief Get a reference to the graph metadata. + /// Get a reference to the graph metadata. GraphMetadata& getMetadata() { return Metadata; } - /// @brief Get a const-reference to the graph metadata. + /// Get a const-reference to the graph metadata. const GraphMetadata& getMetadata() const { return Metadata; } - /// @brief Lock this graph to the given solver instance in preparation + /// 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. @@ -363,13 +363,13 @@ namespace PBQP { Solver->handleAddEdge(EId); } - /// @brief Release from solver instance. + /// Release from solver instance. void unsetSolver() { assert(Solver && "Solver not set."); Solver = nullptr; } - /// @brief Add a node with the given costs. + /// Add a node with the given costs. /// @param Costs Cost vector for the new node. /// @return Node iterator for the added node. template <typename OtherVectorT> @@ -382,7 +382,7 @@ namespace PBQP { return NId; } - /// @brief Add a node bypassing the cost allocator. + /// Add a node bypassing the cost allocator. /// @param Costs Cost vector ptr for the new node (must be convertible to /// VectorPtr). /// @return Node iterator for the added node. @@ -401,7 +401,7 @@ namespace PBQP { return NId; } - /// @brief Add an edge between the given nodes with the given costs. + /// Add an edge between the given nodes with the given costs. /// @param N1Id First node. /// @param N2Id Second node. /// @param Costs Cost matrix for new edge. @@ -419,7 +419,7 @@ namespace PBQP { return EId; } - /// @brief Add an edge bypassing the cost allocator. + /// Add an edge bypassing the cost allocator. /// @param N1Id First node. /// @param N2Id Second node. /// @param Costs Cost matrix for new edge. @@ -444,7 +444,7 @@ namespace PBQP { return EId; } - /// @brief Returns true if the graph is empty. + /// Returns true if the graph is empty. bool empty() const { return NodeIdSet(*this).empty(); } NodeIdSet nodeIds() const { return NodeIdSet(*this); } @@ -452,15 +452,15 @@ namespace PBQP { AdjEdgeIdSet adjEdgeIds(NodeId NId) { return AdjEdgeIdSet(getNode(NId)); } - /// @brief Get the number of nodes in the graph. + /// Get the number of nodes in the graph. /// @return Number of nodes in the graph. unsigned getNumNodes() const { return NodeIdSet(*this).size(); } - /// @brief Get the number of edges in the graph. + /// Get the number of edges in the graph. /// @return Number of edges in the graph. unsigned getNumEdges() const { return EdgeIdSet(*this).size(); } - /// @brief Set a node's cost vector. + /// Set a node's cost vector. /// @param NId Node to update. /// @param Costs New costs to set. template <typename OtherVectorT> @@ -471,7 +471,7 @@ namespace PBQP { getNode(NId).Costs = AllocatedCosts; } - /// @brief Get a VectorPtr to a node's cost vector. Rarely useful - use + /// Get a VectorPtr to a node's cost vector. Rarely useful - use /// getNodeCosts where possible. /// @param NId Node id. /// @return VectorPtr to node cost vector. @@ -483,7 +483,7 @@ namespace PBQP { return getNode(NId).Costs; } - /// @brief Get a node's cost vector. + /// Get a node's cost vector. /// @param NId Node id. /// @return Node cost vector. const Vector& getNodeCosts(NodeId NId) const { @@ -502,7 +502,7 @@ namespace PBQP { return getNode(NId).getAdjEdgeIds().size(); } - /// @brief Update an edge's cost matrix. + /// Update an edge's cost matrix. /// @param EId Edge id. /// @param Costs New cost matrix. template <typename OtherMatrixT> @@ -513,7 +513,7 @@ namespace PBQP { getEdge(EId).Costs = AllocatedCosts; } - /// @brief Get a MatrixPtr to a node's cost matrix. Rarely useful - use + /// Get a MatrixPtr to a node's cost matrix. Rarely useful - use /// getEdgeCosts where possible. /// @param EId Edge id. /// @return MatrixPtr to edge cost matrix. @@ -525,7 +525,7 @@ namespace PBQP { return getEdge(EId).Costs; } - /// @brief Get an edge's cost matrix. + /// Get an edge's cost matrix. /// @param EId Edge id. /// @return Edge cost matrix. const Matrix& getEdgeCosts(EdgeId EId) const { @@ -540,21 +540,21 @@ namespace PBQP { return getEdge(EId).Metadata; } - /// @brief Get the first node connected to this edge. + /// Get the first node connected to this edge. /// @param EId Edge id. /// @return The first node connected to the given edge. NodeId getEdgeNode1Id(EdgeId EId) const { return getEdge(EId).getN1Id(); } - /// @brief Get the second node connected to this edge. + /// Get the second node connected to this edge. /// @param EId Edge id. /// @return The second node connected to the given edge. NodeId getEdgeNode2Id(EdgeId EId) const { return getEdge(EId).getN2Id(); } - /// @brief Get the "other" node connected to this edge. + /// Get the "other" node connected to this edge. /// @param EId Edge id. /// @param NId Node id for the "given" node. /// @return The iterator for the "other" node connected to this edge. @@ -566,7 +566,7 @@ namespace PBQP { return E.getN1Id(); } - /// @brief Get the edge connecting two nodes. + /// 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, @@ -581,7 +581,7 @@ namespace PBQP { return invalidEdgeId(); } - /// @brief Remove a node from the graph. + /// Remove a node from the graph. /// @param NId Node id. void removeNode(NodeId NId) { if (Solver) @@ -598,7 +598,7 @@ namespace PBQP { FreeNodeIds.push_back(NId); } - /// @brief Disconnect an edge from the given node. + /// 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 @@ -631,14 +631,14 @@ namespace PBQP { E.disconnectFrom(*this, NId); } - /// @brief Convenience method to disconnect all neighbours from the given + /// 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. + /// 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. @@ -649,7 +649,7 @@ namespace PBQP { Solver->handleReconnectEdge(EId, NId); } - /// @brief Remove an edge from the graph. + /// Remove an edge from the graph. /// @param EId Edge id. void removeEdge(EdgeId EId) { if (Solver) @@ -660,7 +660,7 @@ namespace PBQP { Edges[EId].invalidate(); } - /// @brief Remove all nodes and edges from the graph. + /// Remove all nodes and edges from the graph. void clear() { Nodes.clear(); FreeNodeIds.clear(); diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h index ba405e816d10..d1432a3053c4 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Math.h @@ -22,34 +22,34 @@ namespace PBQP { using PBQPNum = float; -/// \brief PBQP Vector class. +/// PBQP Vector class. class Vector { friend hash_code hash_value(const Vector &); public: - /// \brief Construct a PBQP vector of the given size. + /// Construct a PBQP vector of the given size. explicit Vector(unsigned Length) : Length(Length), Data(llvm::make_unique<PBQPNum []>(Length)) {} - /// \brief Construct a PBQP vector with initializer. + /// Construct a PBQP vector with initializer. Vector(unsigned Length, PBQPNum InitVal) : Length(Length), Data(llvm::make_unique<PBQPNum []>(Length)) { std::fill(Data.get(), Data.get() + Length, InitVal); } - /// \brief Copy construct a PBQP vector. + /// Copy construct a PBQP vector. Vector(const Vector &V) : Length(V.Length), Data(llvm::make_unique<PBQPNum []>(Length)) { std::copy(V.Data.get(), V.Data.get() + Length, Data.get()); } - /// \brief Move construct a PBQP vector. + /// Move construct a PBQP vector. Vector(Vector &&V) : Length(V.Length), Data(std::move(V.Data)) { V.Length = 0; } - /// \brief Comparison operator. + /// Comparison operator. bool operator==(const Vector &V) const { assert(Length != 0 && Data && "Invalid vector"); if (Length != V.Length) @@ -57,27 +57,27 @@ public: return std::equal(Data.get(), Data.get() + Length, V.Data.get()); } - /// \brief Return the length of the vector + /// Return the length of the vector unsigned getLength() const { assert(Length != 0 && Data && "Invalid vector"); return Length; } - /// \brief Element access. + /// Element access. PBQPNum& operator[](unsigned Index) { assert(Length != 0 && Data && "Invalid vector"); assert(Index < Length && "Vector element access out of bounds."); return Data[Index]; } - /// \brief Const element access. + /// Const element access. const PBQPNum& operator[](unsigned Index) const { assert(Length != 0 && Data && "Invalid vector"); assert(Index < Length && "Vector element access out of bounds."); return Data[Index]; } - /// \brief Add another vector to this one. + /// Add another vector to this one. Vector& operator+=(const Vector &V) { assert(Length != 0 && Data && "Invalid vector"); assert(Length == V.Length && "Vector length mismatch."); @@ -86,7 +86,7 @@ public: return *this; } - /// \brief Returns the index of the minimum value in this vector + /// Returns the index of the minimum value in this vector unsigned minIndex() const { assert(Length != 0 && Data && "Invalid vector"); return std::min_element(Data.get(), Data.get() + Length) - Data.get(); @@ -97,14 +97,14 @@ private: std::unique_ptr<PBQPNum []> Data; }; -/// \brief Return a hash_value for the given vector. +/// Return a hash_value for the given vector. inline hash_code hash_value(const Vector &V) { unsigned *VBegin = reinterpret_cast<unsigned*>(V.Data.get()); unsigned *VEnd = reinterpret_cast<unsigned*>(V.Data.get() + V.Length); return hash_combine(V.Length, hash_combine_range(VBegin, VEnd)); } -/// \brief Output a textual representation of the given vector on the given +/// Output a textual representation of the given vector on the given /// output stream. template <typename OStream> OStream& operator<<(OStream &OS, const Vector &V) { @@ -118,18 +118,18 @@ OStream& operator<<(OStream &OS, const Vector &V) { return OS; } -/// \brief PBQP Matrix class +/// PBQP Matrix class class Matrix { private: friend hash_code hash_value(const Matrix &); public: - /// \brief Construct a PBQP Matrix with the given dimensions. + /// Construct a PBQP Matrix with the given dimensions. Matrix(unsigned Rows, unsigned Cols) : Rows(Rows), Cols(Cols), Data(llvm::make_unique<PBQPNum []>(Rows * Cols)) { } - /// \brief Construct a PBQP Matrix with the given dimensions and initial + /// Construct a PBQP Matrix with the given dimensions and initial /// value. Matrix(unsigned Rows, unsigned Cols, PBQPNum InitVal) : Rows(Rows), Cols(Cols), @@ -137,20 +137,20 @@ public: std::fill(Data.get(), Data.get() + (Rows * Cols), InitVal); } - /// \brief Copy construct a PBQP matrix. + /// Copy construct a PBQP matrix. Matrix(const Matrix &M) : Rows(M.Rows), Cols(M.Cols), Data(llvm::make_unique<PBQPNum []>(Rows * Cols)) { std::copy(M.Data.get(), M.Data.get() + (Rows * Cols), Data.get()); } - /// \brief Move construct a PBQP matrix. + /// Move construct a PBQP matrix. Matrix(Matrix &&M) : Rows(M.Rows), Cols(M.Cols), Data(std::move(M.Data)) { M.Rows = M.Cols = 0; } - /// \brief Comparison operator. + /// Comparison operator. bool operator==(const Matrix &M) const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); if (Rows != M.Rows || Cols != M.Cols) @@ -158,33 +158,33 @@ public: return std::equal(Data.get(), Data.get() + (Rows * Cols), M.Data.get()); } - /// \brief Return the number of rows in this matrix. + /// Return the number of rows in this matrix. unsigned getRows() const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); return Rows; } - /// \brief Return the number of cols in this matrix. + /// Return the number of cols in this matrix. unsigned getCols() const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); return Cols; } - /// \brief Matrix element access. + /// Matrix element access. PBQPNum* operator[](unsigned R) { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); assert(R < Rows && "Row out of bounds."); return Data.get() + (R * Cols); } - /// \brief Matrix element access. + /// Matrix element access. const PBQPNum* operator[](unsigned R) const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); assert(R < Rows && "Row out of bounds."); return Data.get() + (R * Cols); } - /// \brief Returns the given row as a vector. + /// Returns the given row as a vector. Vector getRowAsVector(unsigned R) const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); Vector V(Cols); @@ -193,7 +193,7 @@ public: return V; } - /// \brief Returns the given column as a vector. + /// Returns the given column as a vector. Vector getColAsVector(unsigned C) const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); Vector V(Rows); @@ -202,7 +202,7 @@ public: return V; } - /// \brief Matrix transpose. + /// Matrix transpose. Matrix transpose() const { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); Matrix M(Cols, Rows); @@ -212,7 +212,7 @@ public: return M; } - /// \brief Add the given matrix to this one. + /// Add the given matrix to this one. Matrix& operator+=(const Matrix &M) { assert(Rows != 0 && Cols != 0 && Data && "Invalid matrix"); assert(Rows == M.Rows && Cols == M.Cols && @@ -234,7 +234,7 @@ private: std::unique_ptr<PBQPNum []> Data; }; -/// \brief Return a hash_code for the given matrix. +/// Return a hash_code for the given matrix. inline hash_code hash_value(const Matrix &M) { unsigned *MBegin = reinterpret_cast<unsigned*>(M.Data.get()); unsigned *MEnd = @@ -242,7 +242,7 @@ inline hash_code hash_value(const Matrix &M) { return hash_combine(M.Rows, M.Cols, hash_combine_range(MBegin, MEnd)); } -/// \brief Output a textual representation of the given matrix on the given +/// Output a textual representation of the given matrix on the given /// output stream. template <typename OStream> OStream& operator<<(OStream &OS, const Matrix &M) { diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h b/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h index 8aeb51936760..21b99027970d 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -23,7 +23,7 @@ namespace llvm { namespace PBQP { - /// \brief Reduce a node of degree one. + /// 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. @@ -166,7 +166,7 @@ namespace PBQP { } #endif - // \brief Find a solution to a fully reduced graph by backpropagation. + // 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 diff --git a/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h b/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h index 6a247277fdfa..4d4379fbc2c2 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQP/Solution.h @@ -21,7 +21,7 @@ namespace llvm { namespace PBQP { - /// \brief Represents a solution to a PBQP problem. + /// Represents a solution to a PBQP problem. /// /// To get the selection for each node in the problem use the getSelection method. class Solution { @@ -30,17 +30,17 @@ namespace PBQP { SelectionsMap selections; public: - /// \brief Initialise an empty solution. + /// Initialise an empty solution. Solution() = default; - /// \brief Set the selection for a given node. + /// Set the selection for a given node. /// @param nodeId Node id. /// @param selection Selection for nodeId. void setSelection(GraphBase::NodeId nodeId, unsigned selection) { selections[nodeId] = selection; } - /// \brief Get a node's selection. + /// Get a node's selection. /// @param nodeId Node id. /// @return The selection for nodeId; unsigned getSelection(GraphBase::NodeId nodeId) const { diff --git a/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h b/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h index 269b7a7b3a35..995467dc56d8 100644 --- a/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h +++ b/contrib/llvm/include/llvm/CodeGen/PBQPRAConstraint.h @@ -33,7 +33,7 @@ class PBQPRAGraph; using PBQPRAGraph = PBQP::RegAlloc::PBQPRAGraph; -/// @brief Abstract base for classes implementing PBQP register allocation +/// Abstract base for classes implementing PBQP register allocation /// constraints (e.g. Spill-costs, interference, coalescing). class PBQPRAConstraint { public: @@ -44,7 +44,7 @@ private: virtual void anchor(); }; -/// @brief PBQP register allocation constraint composer. +/// PBQP register allocation constraint composer. /// /// Constraints added to this list will be applied, in the order that they are /// added, to the PBQP graph. diff --git a/contrib/llvm/include/llvm/CodeGen/ParallelCG.h b/contrib/llvm/include/llvm/CodeGen/ParallelCG.h index 14ef0ec408ba..dbf09ea31e20 100644 --- a/contrib/llvm/include/llvm/CodeGen/ParallelCG.h +++ b/contrib/llvm/include/llvm/CodeGen/ParallelCG.h @@ -40,7 +40,7 @@ std::unique_ptr<Module> splitCodeGen(std::unique_ptr<Module> M, ArrayRef<raw_pwrite_stream *> OSs, ArrayRef<llvm::raw_pwrite_stream *> BCOSs, const std::function<std::unique_ptr<TargetMachine>()> &TMFactory, - TargetMachine::CodeGenFileType FT = TargetMachine::CGFT_ObjectFile, + TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_ObjectFile, bool PreserveLocals = false); } // namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/Passes.h b/contrib/llvm/include/llvm/CodeGen/Passes.h index 064526b1efa7..cb12b14f4435 100644 --- a/contrib/llvm/include/llvm/CodeGen/Passes.h +++ b/contrib/llvm/include/llvm/CodeGen/Passes.h @@ -154,6 +154,9 @@ namespace llvm { /// This pass adds dead/undef flags after analyzing subregister lanes. extern char &DetectDeadLanesID; + /// This pass perform post-ra machine sink for COPY instructions. + extern char &PostRAMachineSinkingID; + /// FastRegisterAllocation Pass - This pass register allocates as fast as /// possible. It is best suited for debug code where live ranges are short. /// @@ -212,6 +215,10 @@ namespace llvm { /// into tails of their predecessors. extern char &TailDuplicateID; + /// Duplicate blocks with unconditional branches into tails of their + /// predecessors. Variant that works before register allocation. + extern char &EarlyTailDuplicateID; + /// MachineTraceMetrics - This pass computes critical path and CPU resource /// usage in an ensemble of traces. extern char &MachineTraceMetricsID; @@ -269,9 +276,13 @@ namespace llvm { /// memory operations. extern char &ImplicitNullChecksID; - /// MachineLICM - This pass performs LICM on machine instructions. + /// This pass performs loop invariant code motion on machine instructions. extern char &MachineLICMID; + /// This pass performs loop invariant code motion on machine instructions. + /// This variant works before register allocation. \see MachineLICMID. + extern char &EarlyMachineLICMID; + /// MachineSinking - This pass performs sinking on machine instructions. extern char &MachineSinkingID; @@ -290,7 +301,7 @@ namespace llvm { /// StackSlotColoring - This pass performs stack slot coloring. extern char &StackSlotColoringID; - /// \brief This pass lays out funclets contiguously. + /// This pass lays out funclets contiguously. extern char &FuncletLayoutID; /// This pass inserts the XRay instrumentation sleds if they are supported by @@ -300,7 +311,7 @@ namespace llvm { /// This pass inserts FEntry calls extern char &FEntryInserterID; - /// \brief This pass implements the "patchable-function" attribute. + /// This pass implements the "patchable-function" attribute. extern char &PatchableFunctionID; /// createStackProtectorPass - This pass adds stack protectors to functions. @@ -318,13 +329,17 @@ namespace llvm { /// createWinEHPass - Prepares personality functions used by MSVC on Windows, /// in addition to the Itanium LSDA based personalities. - FunctionPass *createWinEHPass(); + FunctionPass *createWinEHPass(bool DemoteCatchSwitchPHIOnly = false); /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// FunctionPass *createSjLjEHPreparePass(); + /// createWasmEHPass - This pass adapts exception handling code to use + /// WebAssembly's exception handling scheme. + FunctionPass *createWasmEHPass(); + /// LocalStackSlotAllocation - This pass assigns local frame indices to stack /// slots relative to one another and allocates base registers to access them /// when it is estimated by the target to be out of range of normal frame @@ -369,7 +384,7 @@ namespace llvm { /// ModulePass *createLowerEmuTLSPass(); - /// This pass lowers the @llvm.load.relative intrinsic to instructions. + /// This pass lowers the \@llvm.load.relative intrinsic to instructions. /// This is unsafe to do earlier because a pass may combine the constant /// initializer into the load, which may result in an overflowing evaluation. ModulePass *createPreISelIntrinsicLoweringPass(); @@ -408,7 +423,7 @@ namespace llvm { /// This pass performs outlining on machine instructions directly before /// printing assembly. - ModulePass *createMachineOutlinerPass(bool OutlineFromLinkOnceODRs = false); + ModulePass *createMachineOutlinerPass(bool RunOnAllFunctions = true); /// This pass expands the experimental reduction intrinsics into sequences of /// shuffles. @@ -417,9 +432,15 @@ namespace llvm { // This pass expands memcmp() to load/stores. FunctionPass *createExpandMemCmpPass(); + /// Creates Break False Dependencies pass. \see BreakFalseDeps.cpp + FunctionPass *createBreakFalseDeps(); + // This pass expands indirectbr instructions. FunctionPass *createIndirectBrExpandPass(); + /// Creates CFI Instruction Inserter pass. \see CFIInstrInserter.cpp + FunctionPass *createCFIInstrInserter(); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h b/contrib/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h new file mode 100644 index 000000000000..b21b745c8fd1 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/ReachingDefAnalysis.h @@ -0,0 +1,118 @@ +//==--- llvm/CodeGen/ReachingDefAnalysis.h - Reaching Def Analysis -*- C++ -*---==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file Reaching Defs Analysis pass. +/// +/// This pass tracks for each instruction what is the “closest” reaching def of +/// a given register. It is used by BreakFalseDeps (for clearance calculation) +/// and ExecutionDomainFix (for arbitrating conflicting domains). +/// +/// Note that this is different from the usual definition notion of liveness. +/// The CPU doesn't care whether or not we consider a register killed. +/// +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REACHINGDEFSANALYSIS_H +#define LLVM_CODEGEN_REACHINGDEFSANALYSIS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/LoopTraversal.h" +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + +class MachineBasicBlock; +class MachineInstr; + +/// This class provides the reaching def analysis. +class ReachingDefAnalysis : public MachineFunctionPass { +private: + MachineFunction *MF; + const TargetRegisterInfo *TRI; + unsigned NumRegUnits; + /// Instruction that defined each register, relative to the beginning of the + /// current basic block. When a LiveRegsDefInfo is used to represent a + /// live-out register, this value is relative to the end of the basic block, + /// so it will be a negative number. + using LiveRegsDefInfo = std::vector<int>; + LiveRegsDefInfo LiveRegs; + + /// Keeps clearance information for all registers. Note that this + /// is different from the usual definition notion of liveness. The CPU + /// doesn't care whether or not we consider a register killed. + using OutRegsInfoMap = SmallVector<LiveRegsDefInfo, 4>; + OutRegsInfoMap MBBOutRegsInfos; + + /// Current instruction number. + /// The first instruction in each basic block is 0. + int CurInstr; + + /// Maps instructions to their instruction Ids, relative to the begining of + /// their basic blocks. + DenseMap<MachineInstr *, int> InstIds; + + /// All reaching defs of a given RegUnit for a given MBB. + using MBBRegUnitDefs = SmallVector<int, 1>; + /// All reaching defs of all reg units for a given MBB + using MBBDefsInfo = std::vector<MBBRegUnitDefs>; + /// All reaching defs of all reg units for a all MBBs + using MBBReachingDefsInfo = SmallVector<MBBDefsInfo, 4>; + MBBReachingDefsInfo MBBReachingDefs; + + /// Default values are 'nothing happened a long time ago'. + const int ReachingDefDefaultVal = -(1 << 20); + +public: + static char ID; // Pass identification, replacement for typeid + + ReachingDefAnalysis() : MachineFunctionPass(ID) { + initializeReachingDefAnalysisPass(*PassRegistry::getPassRegistry()); + } + void releaseMemory() override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoVRegs); + } + + /// Provides the instruction id of the closest reaching def instruction of + /// PhysReg that reaches MI, relative to the begining of MI's basic block. + int getReachingDef(MachineInstr *MI, int PhysReg); + + /// Provides the clearance - the number of instructions since the closest + /// reaching def instuction of PhysReg that reaches MI. + int getClearance(MachineInstr *MI, MCPhysReg PhysReg); + +private: + /// Set up LiveRegs by merging predecessor live-out values. + void enterBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB); + + /// Update live-out values. + void leaveBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB); + + /// Process he given basic block. + void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB); + + /// Update def-ages for registers defined by MI. + /// Also break dependencies on partial defs and undef uses. + void processDefs(MachineInstr *); +}; + +} // namespace llvm + +#endif // LLVM_CODEGEN_REACHINGDEFSANALYSIS_H diff --git a/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h b/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h index 5b342863eb50..ba9763077d09 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h +++ b/contrib/llvm/include/llvm/CodeGen/RegAllocPBQP.h @@ -43,10 +43,10 @@ class raw_ostream; namespace PBQP { namespace RegAlloc { -/// @brief Spill option index. +/// Spill option index. inline unsigned getSpillOptionIdx() { return 0; } -/// \brief Metadata to speed allocatability test. +/// Metadata to speed allocatability test. /// /// Keeps track of the number of infinities in each row and column. class MatrixMetadata { @@ -89,7 +89,7 @@ private: std::unique_ptr<bool[]> UnsafeCols; }; -/// \brief Holds a vector of the allowed physical regs for a vreg. +/// Holds a vector of the allowed physical regs for a vreg. class AllowedRegVector { friend hash_code hash_value(const AllowedRegVector &); @@ -127,7 +127,7 @@ inline hash_code hash_value(const AllowedRegVector &OptRegs) { hash_combine_range(OStart, OEnd)); } -/// \brief Holds graph-level metadata relevant to PBQP RA problems. +/// Holds graph-level metadata relevant to PBQP RA problems. class GraphMetadata { private: using AllowedRegVecPool = ValuePool<AllowedRegVector>; @@ -164,7 +164,7 @@ private: AllowedRegVecPool AllowedRegVecs; }; -/// \brief Holds solver state and other metadata relevant to each PBQP RA node. +/// Holds solver state and other metadata relevant to each PBQP RA node. class NodeMetadata { public: using AllowedRegVector = RegAlloc::AllowedRegVector; @@ -505,14 +505,14 @@ private: public: PBQPRAGraph(GraphMetadata Metadata) : BaseT(std::move(Metadata)) {} - /// @brief Dump this graph to dbgs(). + /// Dump this graph to dbgs(). void dump() const; - /// @brief Dump this graph to an output stream. + /// Dump this graph to an output stream. /// @param OS Output stream to print on. void dump(raw_ostream &OS) const; - /// @brief Print a representation of this graph in DOT format. + /// Print a representation of this graph in DOT format. /// @param OS Output stream to print on. void printDot(raw_ostream &OS) const; }; @@ -527,7 +527,7 @@ inline Solution solve(PBQPRAGraph& G) { } // end namespace RegAlloc } // end namespace PBQP -/// @brief Create a PBQP register allocator instance. +/// Create a PBQP register allocator instance. FunctionPass * createPBQPRegisterAllocator(char *customPassID = nullptr); diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h b/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h index 2b14b78d621d..79054b9e33b7 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h +++ b/contrib/llvm/include/llvm/CodeGen/RegisterPressure.h @@ -171,10 +171,10 @@ class RegisterOperands { public: /// List of virtual registers and register units read by the instruction. SmallVector<RegisterMaskPair, 8> Uses; - /// \brief List of virtual registers and register units defined by the + /// List of virtual registers and register units defined by the /// instruction which are not dead. SmallVector<RegisterMaskPair, 8> Defs; - /// \brief List of virtual registers and register units defined by the + /// List of virtual registers and register units defined by the /// instruction but dead. SmallVector<RegisterMaskPair, 8> DeadDefs; @@ -219,7 +219,7 @@ public: return const_cast<PressureDiffs*>(this)->operator[](Idx); } - /// \brief Record pressure difference induced by the given operand list to + /// Record pressure difference induced by the given operand list to /// node with index \p Idx. void addInstruction(unsigned Idx, const RegisterOperands &RegOpers, const MachineRegisterInfo &MRI); @@ -546,7 +546,7 @@ protected: /// Add Reg to the live in set and increase max pressure. void discoverLiveIn(RegisterMaskPair Pair); - /// \brief Get the SlotIndex for the first nondebug instruction including or + /// Get the SlotIndex for the first nondebug instruction including or /// after the current position. SlotIndex getCurrSlot() const; diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h b/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h index 489c72b81a98..b6bd028a8cac 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h +++ b/contrib/llvm/include/llvm/CodeGen/RegisterScavenging.h @@ -127,7 +127,7 @@ public: /// Find an unused register of the specified register class. /// Return 0 if none is found. - unsigned FindUnusedReg(const TargetRegisterClass *RegClass) const; + unsigned FindUnusedReg(const TargetRegisterClass *RC) const; /// Add a scavenging frame index. void addScavengingFrameIndex(int FI) { @@ -158,7 +158,7 @@ public: /// Returns the scavenged register. /// This is deprecated as it depends on the quality of the kill flags being /// present; Use scavengeRegisterBackwards() instead! - unsigned scavengeRegister(const TargetRegisterClass *RegClass, + unsigned scavengeRegister(const TargetRegisterClass *RC, MachineBasicBlock::iterator I, int SPAdj); unsigned scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj) { return scavengeRegister(RegClass, MBBI, SPAdj); @@ -218,7 +218,7 @@ private: /// Spill a register after position \p After and reload it before position /// \p UseMI. ScavengedInfo &spill(unsigned Reg, const TargetRegisterClass &RC, int SPAdj, - MachineBasicBlock::iterator After, + MachineBasicBlock::iterator Before, MachineBasicBlock::iterator &UseMI); }; diff --git a/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h b/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h index eabadd8d784a..efd175eeed30 100644 --- a/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/RegisterUsageInfo.h @@ -19,6 +19,7 @@ #ifndef LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H #define LLVM_CODEGEN_PHYSICALREGISTERUSAGEINFO_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/IR/Instructions.h" #include "llvm/Pass.h" @@ -31,8 +32,6 @@ class Function; class TargetMachine; class PhysicalRegisterUsageInfo : public ImmutablePass { - virtual void anchor(); - public: static char ID; @@ -41,25 +40,20 @@ public: initializePhysicalRegisterUsageInfoPass(Registry); } - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - - /// To set TargetMachine *, which is used to print - /// analysis when command line option -print-regusage is used. - void setTargetMachine(const TargetMachine *TM_) { TM = TM_; } + /// Set TargetMachine which is used to print analysis. + void setTargetMachine(const TargetMachine &TM); bool doInitialization(Module &M) override; bool doFinalization(Module &M) override; /// To store RegMask for given Function *. - void storeUpdateRegUsageInfo(const Function *FP, - std::vector<uint32_t> RegMask); + void storeUpdateRegUsageInfo(const Function &FP, + ArrayRef<uint32_t> RegMask); - /// To query stored RegMask for given Function *, it will return nullptr if - /// function is not known. - const std::vector<uint32_t> *getRegUsageInfo(const Function *FP); + /// To query stored RegMask for given Function *, it will returns ane empty + /// array if function is not known. + ArrayRef<uint32_t> getRegUsageInfo(const Function &FP); void print(raw_ostream &OS, const Module *M = nullptr) const override; diff --git a/contrib/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h b/contrib/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h index 03166ccdfe38..8d582ee298b6 100644 --- a/contrib/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h +++ b/contrib/llvm/include/llvm/CodeGen/ResourcePriorityQueue.h @@ -32,7 +32,7 @@ namespace llvm { ResourcePriorityQueue *PQ; explicit resource_sort(ResourcePriorityQueue *pq) : PQ(pq) {} - bool operator()(const SUnit* left, const SUnit* right) const; + bool operator()(const SUnit* LHS, const SUnit* RHS) const; }; class ResourcePriorityQueue : public SchedulingPriorityQueue { @@ -121,7 +121,7 @@ namespace llvm { void remove(SUnit *SU) override; /// scheduledNode - Main resource tracking point. - void scheduledNode(SUnit *Node) override; + void scheduledNode(SUnit *SU) override; bool isResourceAvailable(SUnit *SU); void reserveResources(SUnit *SU); diff --git a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h b/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h index 016bef1702c4..28567a1ce437 100644 --- a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.h @@ -29,7 +29,7 @@ namespace RTLIB { /// enum Libcall { #define HANDLE_LIBCALL(code, name) code, - #include "RuntimeLibcalls.def" + #include "llvm/IR/RuntimeLibcalls.def" #undef HANDLE_LIBCALL }; diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h index f3f2f05b877d..5e7837834ec8 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAG.h @@ -76,7 +76,7 @@ class TargetRegisterInfo; }; private: - /// \brief A pointer to the depending/depended-on SUnit, and an enum + /// A pointer to the depending/depended-on SUnit, and an enum /// indicating the kind of the dependency. PointerIntPair<SUnit *, 2, Kind> Dep; @@ -137,7 +137,7 @@ class TargetRegisterInfo; return !operator==(Other); } - /// \brief Returns the latency value for this edge, which roughly means the + /// Returns the latency value for this edge, which roughly means the /// minimum number of cycles that must elapse between the predecessor and /// the successor, given that they have this edge between them. unsigned getLatency() const { @@ -163,7 +163,7 @@ class TargetRegisterInfo; return getKind() != Data; } - /// \brief Tests if this is an Order dependence between two memory accesses + /// Tests if this is an Order dependence between two memory accesses /// where both sides of the dependence access memory in non-volatile and /// fully modeled ways. bool isNormalMemory() const { @@ -181,7 +181,7 @@ class TargetRegisterInfo; return (isNormalMemory() || isBarrier()); } - /// \brief Tests if this is an Order dependence that is marked as + /// Tests 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. bool isMustAlias() const { @@ -196,13 +196,13 @@ class TargetRegisterInfo; return getKind() == Order && Contents.OrdKind >= Weak; } - /// \brief Tests if this is an Order dependence that is marked as + /// Tests if this is an Order dependence that is marked as /// "artificial", meaning it isn't necessary for correctness. bool isArtificial() const { return getKind() == Order && Contents.OrdKind == Artificial; } - /// \brief Tests if this is an Order dependence that is marked as "cluster", + /// Tests if this is an Order dependence that is marked as "cluster", /// meaning it is artificial and wants to be adjacent. bool isCluster() const { return getKind() == Order && Contents.OrdKind == Cluster; @@ -308,7 +308,7 @@ class TargetRegisterInfo; nullptr; ///< Is a special copy node if != nullptr. const TargetRegisterClass *CopySrcRC = nullptr; - /// \brief Constructs an SUnit for pre-regalloc scheduling to represent an + /// Constructs an SUnit for pre-regalloc scheduling to represent an /// SDNode and any nodes flagged to it. SUnit(SDNode *node, unsigned nodenum) : Node(node), NodeNum(nodenum), isVRegCycle(false), isCall(false), @@ -319,7 +319,7 @@ class TargetRegisterInfo; isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false), isHeightCurrent(false) {} - /// \brief Constructs an SUnit for post-regalloc scheduling to represent a + /// Constructs an SUnit for post-regalloc scheduling to represent a /// MachineInstr. SUnit(MachineInstr *instr, unsigned nodenum) : Instr(instr), NodeNum(nodenum), isVRegCycle(false), isCall(false), @@ -330,7 +330,7 @@ class TargetRegisterInfo; isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false), isHeightCurrent(false) {} - /// \brief Constructs a placeholder SUnit. + /// Constructs a placeholder SUnit. SUnit() : isVRegCycle(false), isCall(false), isCallOp(false), isTwoAddress(false), isCommutable(false), hasPhysRegUses(false), hasPhysRegDefs(false), @@ -339,7 +339,7 @@ class TargetRegisterInfo; isCloned(false), isUnbuffered(false), hasReservedResource(false), isDepthCurrent(false), isHeightCurrent(false) {} - /// \brief Boundary nodes are placeholders for the boundary of the + /// Boundary nodes are placeholders for the boundary of the /// scheduling region. /// /// BoundaryNodes can have DAG edges, including Data edges, but they do not @@ -362,7 +362,7 @@ class TargetRegisterInfo; return Node; } - /// \brief Returns true if this SUnit refers to a machine instruction as + /// Returns true if this SUnit refers to a machine instruction as /// opposed to an SDNode. bool isInstr() const { return Instr; } @@ -384,7 +384,7 @@ class TargetRegisterInfo; /// It also adds the current node as a successor of the specified node. bool addPred(const SDep &D, bool Required = true); - /// \brief Adds a barrier edge to SU by calling addPred(), with latency 0 + /// Adds a barrier edge to SU by calling addPred(), with latency 0 /// generally or latency 1 for a store followed by a load. bool addPredBarrier(SUnit *SU) { SDep Dep(SU, SDep::Barrier); @@ -406,7 +406,7 @@ class TargetRegisterInfo; return Depth; } - /// \brief Returns the height of this node, which is the length of the + /// Returns the height of this node, which is the length of the /// maximum path down to any node which has no successors. unsigned getHeight() const { if (!isHeightCurrent) @@ -414,21 +414,21 @@ class TargetRegisterInfo; return Height; } - /// \brief If NewDepth is greater than this node's depth value, sets it to + /// If NewDepth is greater than this node's depth value, sets it to /// be the new depth value. This also recursively marks successor nodes /// dirty. void setDepthToAtLeast(unsigned NewDepth); - /// \brief If NewDepth is greater than this node's depth value, set it to be + /// If NewDepth is greater than this node's depth value, set it to be /// the new height value. This also recursively marks predecessor nodes /// dirty. void setHeightToAtLeast(unsigned NewHeight); - /// \brief Sets a flag in this node to indicate that its stored Depth value + /// Sets a flag in this node to indicate that its stored Depth value /// will require recomputation the next time getDepth() is called. void setDepthDirty(); - /// \brief Sets a flag in this node to indicate that its stored Height value + /// Sets a flag in this node to indicate that its stored Height value /// will require recomputation the next time getHeight() is called. void setHeightDirty(); @@ -455,15 +455,15 @@ class TargetRegisterInfo; return NumSuccsLeft == 0; } - /// \brief Orders this node's predecessor edges such that the critical path + /// Orders this node's predecessor edges such that the critical path /// edge occurs first. void biasCriticalPath(); void dump(const ScheduleDAG *G) const; void dumpAll(const ScheduleDAG *G) const; raw_ostream &print(raw_ostream &O, - const SUnit *N = nullptr, - const SUnit *X = nullptr) const; + const SUnit *Entry = nullptr, + const SUnit *Exit = nullptr) const; raw_ostream &print(raw_ostream &O, const ScheduleDAG *G) const; private: @@ -497,7 +497,7 @@ class TargetRegisterInfo; //===--------------------------------------------------------------------===// - /// \brief This interface is used to plug different priorities computation + /// This interface is used to plug different priorities computation /// algorithms into the list scheduler. It implements the interface of a /// standard priority queue, where nodes are inserted in arbitrary order and /// returned in priority order. The computation of the priority and the @@ -609,7 +609,7 @@ class TargetRegisterInfo; virtual void addCustomGraphFeatures(GraphWriter<ScheduleDAG*> &) const {} #ifndef NDEBUG - /// \brief Verifies that all SUnits were scheduled and that their state is + /// Verifies that all SUnits were scheduled and that their state is /// consistent. Returns the number of scheduled SUnits. unsigned VerifyScheduledDAG(bool isBottomUp); #endif @@ -708,7 +708,7 @@ class TargetRegisterInfo; /// method. void DFS(const SUnit *SU, int UpperBound, bool& HasLoop); - /// \brief Reassigns topological indexes for the nodes in the DAG to + /// Reassigns topological indexes for the nodes in the DAG to /// preserve the topological ordering. void Shift(BitVector& Visited, int LowerBound, int UpperBound); @@ -735,11 +735,11 @@ class TargetRegisterInfo; /// Returns true if addPred(TargetSU, SU) creates a cycle. bool WillCreateCycle(SUnit *TargetSU, SUnit *SU); - /// \brief Updates the topological ordering to accommodate an edge to be + /// Updates the topological ordering to accommodate an edge to be /// added from SUnit \p X to SUnit \p Y. void AddPred(SUnit *Y, SUnit *X); - /// \brief Updates the topological ordering to accommodate an an edge to be + /// Updates the topological ordering to accommodate an an edge to be /// removed from the specified node \p N from the predecessors of the /// current node \p M. void RemovePred(SUnit *M, SUnit *N); diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h index 14882205584e..520a23846f6e 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -190,7 +190,7 @@ namespace llvm { using SUList = std::list<SUnit *>; protected: - /// \brief A map from ValueType to SUList, used during DAG construction, as + /// A map from ValueType to SUList, used during DAG construction, as /// a means of remembering which SUs depend on which memory locations. class Value2SUsMap; @@ -201,7 +201,7 @@ namespace llvm { void reduceHugeMemNodeMaps(Value2SUsMap &stores, Value2SUsMap &loads, unsigned N); - /// \brief Adds a chain edge between SUa and SUb, but only if both + /// Adds a chain edge between SUa and SUb, but only if both /// AliasAnalysis and Target fail to deny the dependency. void addChainDependency(SUnit *SUa, SUnit *SUb, unsigned Latency = 0); @@ -286,7 +286,7 @@ namespace llvm { /// Cleans up after scheduling in the given block. virtual void finishBlock(); - /// \brief Initialize the DAG and common scheduler state for a new + /// Initialize the DAG and common scheduler state for a new /// scheduling region. This does not actually create the DAG, only clears /// it. The scheduling driver may call BuildSchedGraph multiple times per /// scheduling region. @@ -308,7 +308,7 @@ namespace llvm { LiveIntervals *LIS = nullptr, bool TrackLaneMasks = false); - /// \brief Adds dependencies from instructions in the current list of + /// Adds dependencies from instructions in the current list of /// instructions being scheduled to scheduling barrier. We want to make sure /// instructions which define registers that are either used by the /// terminator or are live-out are properly scheduled. This is especially diff --git a/contrib/llvm/include/llvm/CodeGen/ScheduleDFS.h b/contrib/llvm/include/llvm/CodeGen/ScheduleDFS.h index d6a8c791392c..3ecc033ac35a 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScheduleDFS.h +++ b/contrib/llvm/include/llvm/CodeGen/ScheduleDFS.h @@ -25,7 +25,7 @@ namespace llvm { class raw_ostream; -/// \brief Represent the ILP of the subDAG rooted at a DAG node. +/// Represent the ILP of the subDAG rooted at a DAG node. /// /// ILPValues summarize the DAG subtree rooted at each node. ILPValues are /// valid for all nodes regardless of their subtree membership. @@ -62,13 +62,13 @@ struct ILPValue { void dump() const; }; -/// \brief Compute the values of each DAG node for various metrics during DFS. +/// Compute the values of each DAG node for various metrics during DFS. class SchedDFSResult { friend class SchedDFSImpl; static const unsigned InvalidSubtreeID = ~0u; - /// \brief Per-SUnit data computed during DFS for various metrics. + /// Per-SUnit data computed during DFS for various metrics. /// /// A node's SubtreeID is set to itself when it is visited to indicate that it /// is the root of a subtree. Later it is set to its parent to indicate an @@ -81,7 +81,7 @@ class SchedDFSResult { NodeData() = default; }; - /// \brief Per-Subtree data computed during DFS. + /// Per-Subtree data computed during DFS. struct TreeData { unsigned ParentTreeID = InvalidSubtreeID; unsigned SubInstrCount = 0; @@ -89,7 +89,7 @@ class SchedDFSResult { TreeData() = default; }; - /// \brief Record a connection between subtrees and the connection level. + /// Record a connection between subtrees and the connection level. struct Connection { unsigned TreeID; unsigned Level; @@ -117,15 +117,15 @@ public: SchedDFSResult(bool IsBU, unsigned lim) : IsBottomUp(IsBU), SubtreeLimit(lim) {} - /// \brief Get the node cutoff before subtrees are considered significant. + /// Get the node cutoff before subtrees are considered significant. unsigned getSubtreeLimit() const { return SubtreeLimit; } - /// \brief Return true if this DFSResult is uninitialized. + /// Return true if this DFSResult is uninitialized. /// /// resize() initializes DFSResult, while compute() populates it. bool empty() const { return DFSNodeData.empty(); } - /// \brief Clear the results. + /// Clear the results. void clear() { DFSNodeData.clear(); DFSTreeData.clear(); @@ -133,37 +133,37 @@ public: SubtreeConnectLevels.clear(); } - /// \brief Initialize the result data with the size of the DAG. + /// Initialize the result data with the size of the DAG. void resize(unsigned NumSUnits) { DFSNodeData.resize(NumSUnits); } - /// \brief Compute various metrics for the DAG with given roots. + /// Compute various metrics for the DAG with given roots. void compute(ArrayRef<SUnit> SUnits); - /// \brief Get the number of instructions in the given subtree and its + /// Get the number of instructions in the given subtree and its /// children. unsigned getNumInstrs(const SUnit *SU) const { return DFSNodeData[SU->NodeNum].InstrCount; } - /// \brief Get the number of instructions in the given subtree not including + /// Get the number of instructions in the given subtree not including /// children. unsigned getNumSubInstrs(unsigned SubtreeID) const { return DFSTreeData[SubtreeID].SubInstrCount; } - /// \brief Get the ILP value for a DAG node. + /// Get the ILP value for a DAG node. /// /// A leaf node has an ILP of 1/1. ILPValue getILP(const SUnit *SU) const { return ILPValue(DFSNodeData[SU->NodeNum].InstrCount, 1 + SU->getDepth()); } - /// \brief The number of subtrees detected in this DAG. + /// The number of subtrees detected in this DAG. unsigned getNumSubtrees() const { return SubtreeConnectLevels.size(); } - /// \brief Get the ID of the subtree the given DAG node belongs to. + /// Get the ID of the subtree the given DAG node belongs to. /// /// For convenience, if DFSResults have not been computed yet, give everything /// tree ID 0. @@ -174,7 +174,7 @@ public: return DFSNodeData[SU->NodeNum].SubtreeID; } - /// \brief Get the connection level of a subtree. + /// Get the connection level of a subtree. /// /// For bottom-up trees, the connection level is the latency depth (in cycles) /// of the deepest connection to another subtree. @@ -182,7 +182,7 @@ public: return SubtreeConnectLevels[SubtreeID]; } - /// \brief Scheduler callback to update SubtreeConnectLevels when a tree is + /// Scheduler callback to update SubtreeConnectLevels when a tree is /// initially scheduled. void scheduleTree(unsigned SubtreeID); }; diff --git a/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h b/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h index 466ab532030c..3f75d108f282 100644 --- a/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h +++ b/contrib/llvm/include/llvm/CodeGen/ScoreboardHazardRecognizer.h @@ -106,7 +106,7 @@ class ScoreboardHazardRecognizer : public ScheduleHazardRecognizer { Scoreboard RequiredScoreboard; public: - ScoreboardHazardRecognizer(const InstrItineraryData *ItinData, + ScoreboardHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG, const char *ParentDebugType = ""); diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h index 6a5c2db34bb1..888f9425ff90 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -28,11 +28,12 @@ #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/DivergenceAnalysis.h" #include "llvm/CodeGen/DAGCombine.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/DebugLoc.h" @@ -44,6 +45,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/RecyclingAllocator.h" #include <algorithm> #include <cassert> @@ -71,8 +73,10 @@ class MachineConstantPoolValue; class MCSymbol; class OptimizationRemarkEmitter; class SDDbgValue; +class SDDbgLabel; class SelectionDAG; class SelectionDAGTargetInfo; +class TargetLibraryInfo; class TargetLowering; class TargetMachine; class TargetSubtargetInfo; @@ -145,6 +149,7 @@ class SDDbgInfo { BumpPtrAllocator Alloc; SmallVector<SDDbgValue*, 32> DbgValues; SmallVector<SDDbgValue*, 32> ByvalParmDbgValues; + SmallVector<SDDbgLabel*, 4> DbgLabels; using DbgValMapType = DenseMap<const SDNode *, SmallVector<SDDbgValue *, 2>>; DbgValMapType DbgValMap; @@ -161,7 +166,11 @@ public: DbgValMap[Node].push_back(V); } - /// \brief Invalidate all DbgValues attached to the node and remove + void add(SDDbgLabel *L) { + DbgLabels.push_back(L); + } + + /// Invalidate all DbgValues attached to the node and remove /// it from the Node-to-DbgValues map. void erase(const SDNode *Node); @@ -169,13 +178,14 @@ public: DbgValMap.clear(); DbgValues.clear(); ByvalParmDbgValues.clear(); + DbgLabels.clear(); Alloc.Reset(); } BumpPtrAllocator &getAlloc() { return Alloc; } bool empty() const { - return DbgValues.empty() && ByvalParmDbgValues.empty(); + return DbgValues.empty() && ByvalParmDbgValues.empty() && DbgLabels.empty(); } ArrayRef<SDDbgValue*> getSDDbgValues(const SDNode *Node) { @@ -186,11 +196,14 @@ public: } using DbgIterator = SmallVectorImpl<SDDbgValue*>::iterator; + using DbgLabelIterator = SmallVectorImpl<SDDbgLabel*>::iterator; DbgIterator DbgBegin() { return DbgValues.begin(); } DbgIterator DbgEnd() { return DbgValues.end(); } DbgIterator ByvalParmDbgBegin() { return ByvalParmDbgValues.begin(); } DbgIterator ByvalParmDbgEnd() { return ByvalParmDbgValues.end(); } + DbgLabelIterator DbgLabelBegin() { return DbgLabels.begin(); } + DbgLabelIterator DbgLabelEnd() { return DbgLabels.end(); } }; void checkForCycles(const SelectionDAG *DAG, bool force = false); @@ -210,11 +223,15 @@ class SelectionDAG { const TargetMachine &TM; const SelectionDAGTargetInfo *TSI = nullptr; const TargetLowering *TLI = nullptr; + const TargetLibraryInfo *LibInfo = nullptr; MachineFunction *MF; Pass *SDAGISelPass = nullptr; LLVMContext *Context; CodeGenOpt::Level OptLevel; + DivergenceAnalysis * DA = nullptr; + FunctionLoweringInfo * FLI = nullptr; + /// The function-level optimization remark emitter. Used to emit remarks /// whenever manipulating the DAG. OptimizationRemarkEmitter *ORE; @@ -248,7 +265,7 @@ class SelectionDAG { /// Pool allocation for misc. objects that are created once per SelectionDAG. BumpPtrAllocator Allocator; - /// Tracks dbg_value information through SDISel. + /// Tracks dbg_value and dbg_label information through SDISel. SDDbgInfo *DbgInfo; uint16_t NextPersistentId = 0; @@ -344,19 +361,7 @@ private: .getRawSubclassData(); } - void createOperands(SDNode *Node, ArrayRef<SDValue> Vals) { - assert(!Node->OperandList && "Node already has operands"); - SDUse *Ops = OperandRecycler.allocate( - ArrayRecycler<SDUse>::Capacity::get(Vals.size()), OperandAllocator); - - for (unsigned I = 0; I != Vals.size(); ++I) { - Ops[I].setUser(Node); - Ops[I].setInitial(Vals[I]); - } - Node->NumOperands = Vals.size(); - Node->OperandList = Ops; - checkForCycles(Node); - } + void createOperands(SDNode *Node, ArrayRef<SDValue> Vals); void removeOperands(SDNode *Node) { if (!Node->OperandList) @@ -367,7 +372,7 @@ private: Node->NumOperands = 0; Node->OperandList = nullptr; } - + void CreateTopologicalOrder(std::vector<SDNode*>& Order); public: explicit SelectionDAG(const TargetMachine &TM, CodeGenOpt::Level); SelectionDAG(const SelectionDAG &) = delete; @@ -376,7 +381,12 @@ public: /// Prepare this SelectionDAG to process code in the given MachineFunction. void init(MachineFunction &NewMF, OptimizationRemarkEmitter &NewORE, - Pass *PassPtr); + Pass *PassPtr, const TargetLibraryInfo *LibraryInfo, + DivergenceAnalysis * Divergence); + + void setFunctionLoweringInfo(FunctionLoweringInfo * FuncInfo) { + FLI = FuncInfo; + } /// Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -389,6 +399,7 @@ public: const TargetMachine &getTarget() const { return TM; } const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); } const TargetLowering &getTargetLoweringInfo() const { return *TLI; } + const TargetLibraryInfo &getLibInfo() const { return *LibInfo; } const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; } LLVMContext *getContext() const {return Context; } OptimizationRemarkEmitter &getORE() const { return *ORE; } @@ -460,6 +471,8 @@ public: return Root; } + void VerifyDAGDiverence(); + /// This iterates over the nodes in the SelectionDAG, folding /// certain types of nodes together, or eliminating superfluous nodes. The /// Level argument controls whether Combine is allowed to produce nodes and @@ -483,7 +496,7 @@ public: /// the graph. void Legalize(); - /// \brief Transforms a SelectionDAG node and any operands to it into a node + /// Transforms a SelectionDAG node and any operands to it into a node /// that is compatible with the target instruction selector, as indicated by /// the TargetLowering object. /// @@ -534,7 +547,7 @@ public: //===--------------------------------------------------------------------===// // Node creation methods. - /// \brief Create a ConstantSDNode wrapping a constant value. + /// Create a ConstantSDNode wrapping a constant value. /// If VT is a vector type, the constant is splatted into a BUILD_VECTOR. /// /// If only legal types can be produced, this does the necessary @@ -567,9 +580,13 @@ public: bool isOpaque = false) { return getConstant(Val, DL, VT, true, isOpaque); } + + /// Create a true or false constant of type \p VT using the target's + /// BooleanContent for type \p OpVT. + SDValue getBoolConstant(bool V, const SDLoc &DL, EVT VT, EVT OpVT); /// @} - /// \brief Create a ConstantFPSDNode wrapping a constant value. + /// Create a ConstantFPSDNode wrapping a constant value. /// If VT is a vector type, the constant is splatted into a BUILD_VECTOR. /// /// If only legal types can be produced, this does the necessary @@ -581,7 +598,7 @@ public: bool isTarget = false); SDValue getConstantFP(const APFloat &Val, const SDLoc &DL, EVT VT, bool isTarget = false); - SDValue getConstantFP(const ConstantFP &CF, const SDLoc &DL, EVT VT, + SDValue getConstantFP(const ConstantFP &V, const SDLoc &DL, EVT VT, bool isTarget = false); SDValue getTargetConstantFP(double Val, const SDLoc &DL, EVT VT) { return getConstantFP(Val, DL, VT, true); @@ -741,7 +758,7 @@ public: return getNode(ISD::BUILD_VECTOR, DL, VT, Ops); } - /// \brief Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to + /// Returns an ISD::VECTOR_SHUFFLE node semantically equivalent to /// the shuffle node in input but with swapped operands. /// /// Example: shuffle A, B, <0,5,2,7> -> shuffle B, A, <4,1,6,3> @@ -765,7 +782,7 @@ public: /// Return the expression required to zero extend the Op /// value assuming it was the smaller SrcTy value. - SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT SrcTy); + SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT); /// Return an operation which will any-extend the low lanes of the operand /// into the specified vector type. For example, @@ -793,10 +810,10 @@ public: /// Create a bitwise NOT operation as (XOR Val, -1). SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT); - /// \brief Create a logical NOT operation as (XOR Val, BooleanOne). + /// Create a logical NOT operation as (XOR Val, BooleanOne). SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT); - /// \brief Create an add instruction with appropriate flags when used for + /// Create an add instruction with appropriate flags when used for /// addressing some offset of an object. i.e. if a load is split into multiple /// components, create an add nuw from the base pointer to the offset. SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Op, int64_t Offset) { @@ -862,17 +879,18 @@ public: ArrayRef<SDValue> Ops, const SDNodeFlags Flags = SDNodeFlags()); SDValue getNode(unsigned Opcode, const SDLoc &DL, ArrayRef<EVT> ResultTys, ArrayRef<SDValue> Ops); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, + SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, ArrayRef<SDValue> Ops); // Specialize based on number of operands. SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT); - SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N, + SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue Operand, const SDNodeFlags Flags = SDNodeFlags()); SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, SDValue N2, const SDNodeFlags Flags = SDNodeFlags()); SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, - SDValue N2, SDValue N3); + SDValue N2, SDValue N3, + const SDNodeFlags Flags = SDNodeFlags()); SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4); SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, @@ -880,15 +898,15 @@ public: // Specialize again based on number of operands for nodes with a VTList // rather than a single VT. - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1, + SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList); + SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N); + SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1, SDValue N2); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1, + SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1, SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1, + SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1, SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTs, SDValue N1, + SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5); /// Compute a TokenFactor to force all the incoming stack arguments to be @@ -910,6 +928,23 @@ public: SDValue Size, unsigned Align, bool isVol, bool isTailCall, MachinePointerInfo DstPtrInfo); + SDValue getAtomicMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, + unsigned DstAlign, SDValue Src, unsigned SrcAlign, + SDValue Size, Type *SizeTy, unsigned ElemSz, + bool isTailCall, MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo); + + SDValue getAtomicMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst, + unsigned DstAlign, SDValue Src, unsigned SrcAlign, + SDValue Size, Type *SizeTy, unsigned ElemSz, + bool isTailCall, MachinePointerInfo DstPtrInfo, + MachinePointerInfo SrcPtrInfo); + + SDValue getAtomicMemset(SDValue Chain, const SDLoc &dl, SDValue Dst, + unsigned DstAlign, SDValue Value, SDValue Size, + Type *SizeTy, unsigned ElemSz, bool isTailCall, + MachinePointerInfo DstPtrInfo); + /// Helper function to make it easier to build SetCC's if you just /// have an ISD::CondCode instead of an SDValue. /// @@ -1050,12 +1085,12 @@ public: MachineMemOperand *MMO); SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, - MachinePointerInfo PtrInfo, EVT TVT, unsigned Alignment = 0, + MachinePointerInfo PtrInfo, EVT SVT, unsigned Alignment = 0, MachineMemOperand::Flags MMOFlags = MachineMemOperand::MONone, const AAMDNodes &AAInfo = AAMDNodes()); SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, - SDValue Ptr, EVT TVT, MachineMemOperand *MMO); - SDValue getIndexedStore(SDValue OrigStoe, const SDLoc &dl, SDValue Base, + SDValue Ptr, EVT SVT, MachineMemOperand *MMO); + SDValue getIndexedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); /// Returns sum of the base pointer and offset. @@ -1121,28 +1156,31 @@ public: SDValue Op3, SDValue Op4, SDValue Op5); SDNode *UpdateNodeOperands(SDNode *N, ArrayRef<SDValue> Ops); + // Propagates the change in divergence to users + void updateDivergence(SDNode * N); + /// These are used for target selectors to *mutate* the /// specified node to have the specified return type, Target opcode, and /// operands. Note that target opcodes are stored as /// ~TargetOpcode in the node opcode field. The resultant node is returned. - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, SDValue Op1); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT); + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT, SDValue Op1); + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT, SDValue Op1, SDValue Op2); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT, SDValue Op1, SDValue Op2, SDValue Op3); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT, + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT, ArrayRef<SDValue> Ops); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, EVT VT2); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, EVT VT2); + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, EVT VT2, ArrayRef<SDValue> Ops); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, EVT VT2, EVT VT3, ArrayRef<SDValue> Ops); SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, EVT VT2, SDValue Op1); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, EVT VT1, + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, EVT VT1, EVT VT2, SDValue Op1, SDValue Op2); - SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, SDVTList VTs, + SDNode *SelectNodeTo(SDNode *N, unsigned MachineOpc, SDVTList VTs, ArrayRef<SDValue> Ops); /// This *mutates* the specified node to have the specified @@ -1197,7 +1235,7 @@ public: SDValue Operand, SDValue Subreg); /// Get the specified node if it's already available, or else return NULL. - SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, ArrayRef<SDValue> Ops, + SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTList, ArrayRef<SDValue> Ops, const SDNodeFlags Flags = SDNodeFlags()); /// Creates a SDDbgValue node. @@ -1212,8 +1250,16 @@ public: /// Creates a FrameIndex SDDbgValue node. SDDbgValue *getFrameIndexDbgValue(DIVariable *Var, DIExpression *Expr, - unsigned FI, const DebugLoc &DL, - unsigned O); + unsigned FI, bool IsIndirect, + const DebugLoc &DL, unsigned O); + + /// Creates a VReg SDDbgValue node. + SDDbgValue *getVRegDbgValue(DIVariable *Var, DIExpression *Expr, + unsigned VReg, bool IsIndirect, + const DebugLoc &DL, unsigned O); + + /// Creates a SDDbgLabel node. + SDDbgLabel *getDbgLabel(DILabel *Label, const DebugLoc &DL, unsigned O); /// Transfer debug values from one node to another, while optionally /// generating fragment expressions for split-up values. If \p InvalidateDbg @@ -1245,7 +1291,7 @@ public: /// to be given new uses. These new uses of From are left in place, and /// not automatically transferred to To. /// - void ReplaceAllUsesWith(SDValue From, SDValue Op); + void ReplaceAllUsesWith(SDValue From, SDValue To); void ReplaceAllUsesWith(SDNode *From, SDNode *To); void ReplaceAllUsesWith(SDNode *From, const SDValue *To); @@ -1296,6 +1342,9 @@ public: /// value is produced by SD. void AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter); + /// Add a dbg_label SDNode. + void AddDbgLabel(SDDbgLabel *DB); + /// Get the debug values which reference the given SDNode. ArrayRef<SDDbgValue*> GetDbgValues(const SDNode* SD) { return DbgInfo->getSDDbgValues(SD); @@ -1317,6 +1366,13 @@ public: return DbgInfo->ByvalParmDbgEnd(); } + SDDbgInfo::DbgLabelIterator DbgLabelBegin() { + return DbgInfo->DbgLabelBegin(); + } + SDDbgInfo::DbgLabelIterator DbgLabelEnd() { + return DbgInfo->DbgLabelEnd(); + } + /// To be invoked on an SDNode that is slated to be erased. This /// function mirrors \c llvm::salvageDebugInfo. void salvageDebugInfo(SDNode &N); @@ -1431,8 +1487,11 @@ public: /// Test whether the given SDValue is known to never be NaN. bool isKnownNeverNaN(SDValue Op) const; - /// Test whether the given SDValue is known to never be positive or negative - /// zero. + /// Test whether the given floating point SDValue is known to never be + /// positive or negative zero. + bool isKnownNeverZeroFloat(SDValue Op) const; + + /// Test whether the given SDValue is known to contain non-zero value(s). bool isKnownNeverZero(SDValue Op) const; /// Test whether two SDValues are known to compare equal. This diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h index de6849a1eae1..86df0af7303f 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -110,6 +110,11 @@ public: CodeGenOpt::Level OptLevel, bool IgnoreChains = false); + static void InvalidateNodeId(SDNode *N); + static int getUninvalidatedNodeId(SDNode *N); + + static void EnforceNodeIdInvariant(SDNode *N); + // Opcodes used by the DAG state machine: enum BuiltinOpcodes { OPC_Scope, @@ -199,23 +204,28 @@ protected: /// of the new node T. void ReplaceUses(SDValue F, SDValue T) { CurDAG->ReplaceAllUsesOfValueWith(F, T); + EnforceNodeIdInvariant(T.getNode()); } /// ReplaceUses - replace all uses of the old nodes F with the use /// of the new nodes T. void ReplaceUses(const SDValue *F, const SDValue *T, unsigned Num) { CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num); + for (unsigned i = 0; i < Num; ++i) + EnforceNodeIdInvariant(T[i].getNode()); } /// ReplaceUses - replace all uses of the old node F with the use /// of the new node T. void ReplaceUses(SDNode *F, SDNode *T) { CurDAG->ReplaceAllUsesWith(F, T); + EnforceNodeIdInvariant(T); } /// Replace all uses of \c F with \c T, then remove \c F from the DAG. void ReplaceNode(SDNode *F, SDNode *T) { CurDAG->ReplaceAllUsesWith(F, T); + EnforceNodeIdInvariant(T); CurDAG->RemoveDeadNode(F); } @@ -270,7 +280,7 @@ public: void SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, unsigned TableSize); - /// \brief Return true if complex patterns for this target can mutate the + /// Return true if complex patterns for this target can mutate the /// DAG. virtual bool ComplexPatternFuncMutatesDAG() const { return false; @@ -282,14 +292,14 @@ private: // Calls to these functions are generated by tblgen. void Select_INLINEASM(SDNode *N); - void Select_READ_REGISTER(SDNode *N); - void Select_WRITE_REGISTER(SDNode *N); + void Select_READ_REGISTER(SDNode *Op); + void Select_WRITE_REGISTER(SDNode *Op); void Select_UNDEF(SDNode *N); void CannotYetSelect(SDNode *N); private: void DoInstructionSelection(); - SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs, + SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTList, ArrayRef<SDValue> Ops, unsigned EmitNodeInfo); SDNode *MutateStrictFPToFP(SDNode *Node, unsigned NewOpc); @@ -299,10 +309,10 @@ private: /// instruction selected, false if no code should be emitted for it. bool PrepareEHLandingPad(); - /// \brief Perform instruction selection on all basic blocks in the function. + /// Perform instruction selection on all basic blocks in the function. void SelectAllBasicBlocks(const Function &Fn); - /// \brief Perform instruction selection on a single basic block, for + /// Perform instruction selection on a single basic block, for /// instructions between \p Begin and \p End. \p HadTailCall will be set /// to true if a call in the block was translated as a tail call. void SelectBasicBlock(BasicBlock::const_iterator Begin, @@ -312,7 +322,7 @@ private: void CodeGenAndEmitDAG(); - /// \brief Generate instructions for lowering the incoming arguments of the + /// Generate instructions for lowering the incoming arguments of the /// given function. void LowerArguments(const Function &F); diff --git a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h index 522c2f1b2cb2..1af22185d366 100644 --- a/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/contrib/llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -31,17 +31,18 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/Operator.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachineValueType.h" #include <algorithm> #include <cassert> #include <climits> @@ -189,8 +190,10 @@ public: inline bool isUndef() const; inline unsigned getMachineOpcode() const; inline const DebugLoc &getDebugLoc() const; - inline void dump(const SelectionDAG *G = nullptr) const; - inline void dumpr(const SelectionDAG *G = nullptr) const; + inline void dump() const; + inline void dump(const SelectionDAG *G) const; + inline void dumpr() const; + inline void dumpr(const SelectionDAG *G) const; /// Return true if this operand (which must be a chain) reaches the /// specified operand without crossing any side-effecting instructions. @@ -357,21 +360,34 @@ private: bool NoUnsignedWrap : 1; bool NoSignedWrap : 1; bool Exact : 1; - bool UnsafeAlgebra : 1; bool NoNaNs : 1; bool NoInfs : 1; bool NoSignedZeros : 1; bool AllowReciprocal : 1; bool VectorReduction : 1; bool AllowContract : 1; + bool ApproximateFuncs : 1; + bool AllowReassociation : 1; public: /// Default constructor turns off all optimization flags. SDNodeFlags() : AnyDefined(false), NoUnsignedWrap(false), NoSignedWrap(false), - Exact(false), UnsafeAlgebra(false), NoNaNs(false), NoInfs(false), + Exact(false), NoNaNs(false), NoInfs(false), NoSignedZeros(false), AllowReciprocal(false), VectorReduction(false), - AllowContract(false) {} + AllowContract(false), ApproximateFuncs(false), + AllowReassociation(false) {} + + /// Propagate the fast-math-flags from an IR FPMathOperator. + void copyFMF(const FPMathOperator &FPMO) { + setNoNaNs(FPMO.hasNoNaNs()); + setNoInfs(FPMO.hasNoInfs()); + setNoSignedZeros(FPMO.hasNoSignedZeros()); + setAllowReciprocal(FPMO.hasAllowReciprocal()); + setAllowContract(FPMO.hasAllowContract()); + setApproximateFuncs(FPMO.hasApproxFunc()); + setAllowReassociation(FPMO.hasAllowReassoc()); + } /// Sets the state of the flags to the defined state. void setDefined() { AnyDefined = true; } @@ -391,10 +407,6 @@ public: setDefined(); Exact = b; } - void setUnsafeAlgebra(bool b) { - setDefined(); - UnsafeAlgebra = b; - } void setNoNaNs(bool b) { setDefined(); NoNaNs = b; @@ -419,18 +431,32 @@ public: setDefined(); AllowContract = b; } + void setApproximateFuncs(bool b) { + setDefined(); + ApproximateFuncs = b; + } + void setAllowReassociation(bool b) { + setDefined(); + AllowReassociation = b; + } // These are accessors for each flag. bool hasNoUnsignedWrap() const { return NoUnsignedWrap; } bool hasNoSignedWrap() const { return NoSignedWrap; } bool hasExact() const { return Exact; } - bool hasUnsafeAlgebra() const { return UnsafeAlgebra; } bool hasNoNaNs() const { return NoNaNs; } bool hasNoInfs() const { return NoInfs; } bool hasNoSignedZeros() const { return NoSignedZeros; } bool hasAllowReciprocal() const { return AllowReciprocal; } bool hasVectorReduction() const { return VectorReduction; } bool hasAllowContract() const { return AllowContract; } + bool hasApproximateFuncs() const { return ApproximateFuncs; } + bool hasAllowReassociation() const { return AllowReassociation; } + + bool isFast() const { + return NoSignedZeros && AllowReciprocal && NoNaNs && NoInfs && + AllowContract && ApproximateFuncs && AllowReassociation; + } /// Clear any flags in this flag set that aren't also set in Flags. /// If the given Flags are undefined then don't do anything. @@ -440,13 +466,14 @@ public: NoUnsignedWrap &= Flags.NoUnsignedWrap; NoSignedWrap &= Flags.NoSignedWrap; Exact &= Flags.Exact; - UnsafeAlgebra &= Flags.UnsafeAlgebra; NoNaNs &= Flags.NoNaNs; NoInfs &= Flags.NoInfs; NoSignedZeros &= Flags.NoSignedZeros; AllowReciprocal &= Flags.AllowReciprocal; VectorReduction &= Flags.VectorReduction; AllowContract &= Flags.AllowContract; + ApproximateFuncs &= Flags.ApproximateFuncs; + AllowReassociation &= Flags.AllowReassociation; } }; @@ -466,11 +493,13 @@ protected: friend class SDNode; friend class MemIntrinsicSDNode; friend class MemSDNode; + friend class SelectionDAG; uint16_t HasDebugValue : 1; uint16_t IsMemIntrinsic : 1; + uint16_t IsDivergent : 1; }; - enum { NumSDNodeBits = 2 }; + enum { NumSDNodeBits = 3 }; class ConstantSDNodeBitfields { friend class ConstantSDNode; @@ -540,7 +569,7 @@ protected: static_assert(sizeof(ConstantSDNodeBitfields) <= 2, "field too wide"); static_assert(sizeof(MemSDNodeBitfields) <= 2, "field too wide"); static_assert(sizeof(LSBaseSDNodeBitfields) <= 2, "field too wide"); - static_assert(sizeof(LoadSDNodeBitfields) <= 4, "field too wide"); + static_assert(sizeof(LoadSDNodeBitfields) <= 2, "field too wide"); static_assert(sizeof(StoreSDNodeBitfields) <= 2, "field too wide"); private: @@ -662,6 +691,8 @@ public: bool getHasDebugValue() const { return SDNodeBits.HasDebugValue; } void setHasDebugValue(bool b) { SDNodeBits.HasDebugValue = b; } + bool isDivergent() const { return SDNodeBits.IsDivergent; } + /// Return true if there are no uses of this node. bool use_empty() const { return UseList == nullptr; } @@ -796,16 +827,44 @@ public: /// searches to be performed in parallel, caching of results across /// queries and incremental addition to Worklist. Stops early if N is /// found but will resume. Remember to clear Visited and Worklists - /// if DAG changes. + /// if DAG changes. MaxSteps gives a maximum number of nodes to visit before + /// giving up. The TopologicalPrune flag signals that positive NodeIds are + /// topologically ordered (Operands have strictly smaller node id) and search + /// can be pruned leveraging this. static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl<const SDNode *> &Visited, SmallVectorImpl<const SDNode *> &Worklist, - unsigned int MaxSteps = 0) { + unsigned int MaxSteps = 0, + bool TopologicalPrune = false) { + SmallVector<const SDNode *, 8> DeferredNodes; if (Visited.count(N)) return true; + + // Node Id's are assigned in three places: As a topological + // ordering (> 0), during legalization (results in values set to + // 0), new nodes (set to -1). If N has a topolgical id then we + // know that all nodes with ids smaller than it cannot be + // successors and we need not check them. Filter out all node + // that can't be matches. We add them to the worklist before exit + // in case of multiple calls. Note that during selection the topological id + // may be violated if a node's predecessor is selected before it. We mark + // this at selection negating the id of unselected successors and + // restricting topological pruning to positive ids. + + int NId = N->getNodeId(); + // If we Invalidated the Id, reconstruct original NId. + if (NId < -1) + NId = -(NId + 1); + + bool Found = false; while (!Worklist.empty()) { const SDNode *M = Worklist.pop_back_val(); - bool Found = false; + int MId = M->getNodeId(); + if (TopologicalPrune && M->getOpcode() != ISD::TokenFactor && (NId > 0) && + (MId > 0) && (MId < NId)) { + DeferredNodes.push_back(M); + continue; + } for (const SDValue &OpV : M->op_values()) { SDNode *Op = OpV.getNode(); if (Visited.insert(Op).second) @@ -814,11 +873,16 @@ public: Found = true; } if (Found) - return true; + break; if (MaxSteps != 0 && Visited.size() >= MaxSteps) - return false; + break; } - return false; + // Push deferred nodes back on worklist. + Worklist.append(DeferredNodes.begin(), DeferredNodes.end()); + // If we bailed early, conservatively return found. + if (MaxSteps != 0 && Visited.size() >= MaxSteps) + return true; + return Found; } /// Return true if all the users of N are contained in Nodes. @@ -884,6 +948,7 @@ public: const SDNodeFlags getFlags() const { return Flags; } void setFlags(SDNodeFlags NewFlags) { Flags = NewFlags; } + bool isFast() { return Flags.isFast(); } /// Clear any flags in this node that aren't also set in Flags. /// If Flags is not in a defined state then this has no effect. @@ -1089,10 +1154,18 @@ inline const DebugLoc &SDValue::getDebugLoc() const { return Node->getDebugLoc(); } +inline void SDValue::dump() const { + return Node->dump(); +} + inline void SDValue::dump(const SelectionDAG *G) const { return Node->dump(G); } +inline void SDValue::dumpr() const { + return Node->dumpr(); +} + inline void SDValue::dumpr(const SelectionDAG *G) const { return Node->dumpr(G); } @@ -1173,7 +1246,7 @@ protected: public: MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl, SDVTList VTs, - EVT MemoryVT, MachineMemOperand *MMO); + EVT memvt, MachineMemOperand *MMO); bool readMem() const { return MMO->isLoad(); } bool writeMem() const { return MMO->isStore(); } @@ -1190,7 +1263,8 @@ public: /// encoding of the volatile flag, as well as bits used by subclasses. This /// function should only be used to compute a FoldingSetNodeID value. /// The HasDebugValue bit is masked out because CSE map needs to match - /// nodes with debug info with nodes without debug info. + /// nodes with debug info with nodes without debug info. Same is about + /// isDivergent bit. unsigned getRawSubclassData() const { uint16_t Data; union { @@ -1199,6 +1273,7 @@ public: }; memcpy(&RawSDNodeBits, &this->RawSDNodeBits, sizeof(this->RawSDNodeBits)); SDNodeBits.HasDebugValue = 0; + SDNodeBits.IsDivergent = false; memcpy(&Data, &RawSDNodeBits, sizeof(RawSDNodeBits)); return Data; } @@ -1267,6 +1342,7 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_ADD || N->getOpcode() == ISD::ATOMIC_LOAD_SUB || N->getOpcode() == ISD::ATOMIC_LOAD_AND || + N->getOpcode() == ISD::ATOMIC_LOAD_CLR || N->getOpcode() == ISD::ATOMIC_LOAD_OR || N->getOpcode() == ISD::ATOMIC_LOAD_XOR || N->getOpcode() == ISD::ATOMIC_LOAD_NAND || @@ -1318,6 +1394,7 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_ADD || N->getOpcode() == ISD::ATOMIC_LOAD_SUB || N->getOpcode() == ISD::ATOMIC_LOAD_AND || + N->getOpcode() == ISD::ATOMIC_LOAD_CLR || N->getOpcode() == ISD::ATOMIC_LOAD_OR || N->getOpcode() == ISD::ATOMIC_LOAD_XOR || N->getOpcode() == ISD::ATOMIC_LOAD_NAND || @@ -1421,9 +1498,8 @@ class ConstantSDNode : public SDNode { const ConstantInt *Value; - ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, - const DebugLoc &DL, EVT VT) - : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DL, + ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, EVT VT) + : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, 0, DebugLoc(), getSDVTList(VT)), Value(val) { ConstantSDNodeBits.IsOpaque = isOpaque; @@ -1459,10 +1535,9 @@ class ConstantFPSDNode : public SDNode { const ConstantFP *Value; - ConstantFPSDNode(bool isTarget, const ConstantFP *val, const DebugLoc &DL, - EVT VT) - : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, DL, - getSDVTList(VT)), + ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) + : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, 0, + DebugLoc(), getSDVTList(VT)), Value(val) {} public: @@ -1519,10 +1594,10 @@ bool isOneConstant(SDValue V); bool isBitwiseNot(SDValue V); /// Returns the SDNode if it is a constant splat BuildVector or constant int. -ConstantSDNode *isConstOrConstSplat(SDValue V); +ConstantSDNode *isConstOrConstSplat(SDValue N); /// Returns the SDNode if it is a constant splat BuildVector or constant float. -ConstantFPSDNode *isConstOrConstSplatFP(SDValue V); +ConstantFPSDNode *isConstOrConstSplatFP(SDValue N); class GlobalAddressSDNode : public SDNode { friend class SelectionDAG; @@ -1533,7 +1608,7 @@ class GlobalAddressSDNode : public SDNode { GlobalAddressSDNode(unsigned Opc, unsigned Order, const DebugLoc &DL, const GlobalValue *GA, EVT VT, int64_t o, - unsigned char TargetFlags); + unsigned char TF); public: const GlobalValue *getGlobal() const { return TheGlobal; } @@ -1714,13 +1789,13 @@ public: unsigned MinSplatBits = 0, bool isBigEndian = false) const; - /// \brief Returns the splatted value or a null value if this is not a splat. + /// Returns the splatted value or a null value if this is not a splat. /// /// If passed a non-null UndefElements bitvector, it will resize it to match /// the vector width and set the bits where elements are undef. SDValue getSplatValue(BitVector *UndefElements = nullptr) const; - /// \brief Returns the splatted constant or null if this is not a constant + /// Returns the splatted constant or null if this is not a constant /// splat. /// /// If passed a non-null UndefElements bitvector, it will resize it to match @@ -1728,7 +1803,7 @@ public: ConstantSDNode * getConstantSplatNode(BitVector *UndefElements = nullptr) const; - /// \brief Returns the splatted constant FP or null if this is not a constant + /// Returns the splatted constant FP or null if this is not a constant /// FP splat. /// /// If passed a non-null UndefElements bitvector, it will resize it to match @@ -1736,7 +1811,7 @@ public: ConstantFPSDNode * getConstantFPSplatNode(BitVector *UndefElements = nullptr) const; - /// \brief If this is a constant FP splat and the splatted constant FP is an + /// If this is a constant FP splat and the splatted constant FP is an /// exact power or 2, return the log base 2 integer value. Otherwise, /// return -1. /// @@ -2120,13 +2195,14 @@ public: : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {} // In the both nodes address is Op1, mask is Op2: - // MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a passthru value - // MaskedScatterSDNode (Chain, value, mask, base, index) + // MaskedGatherSDNode (Chain, passthru, mask, base, index, scale) + // MaskedScatterSDNode (Chain, value, mask, base, index, scale) // Mask is a vector of i1 elements const SDValue &getBasePtr() const { return getOperand(3); } const SDValue &getIndex() const { return getOperand(4); } const SDValue &getMask() const { return getOperand(2); } const SDValue &getValue() const { return getOperand(1); } + const SDValue &getScale() const { return getOperand(5); } static bool classof(const SDNode *N) { return N->getOpcode() == ISD::MGATHER || @@ -2329,6 +2405,17 @@ namespace ISD { cast<StoreSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; } + /// Attempt to match a unary predicate against a scalar/splat constant or + /// every element of a constant BUILD_VECTOR. + bool matchUnaryPredicate(SDValue Op, + std::function<bool(ConstantSDNode *)> Match); + + /// Attempt to match a binary predicate against a pair of scalar/splat + /// constants or every element of a pair of constant BUILD_VECTORs. + bool matchBinaryPredicate( + SDValue LHS, SDValue RHS, + std::function<bool(ConstantSDNode *, ConstantSDNode *)> Match); + } // end namespace ISD } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h index 3a91e363f923..334267d9828b 100644 --- a/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h +++ b/contrib/llvm/include/llvm/CodeGen/SlotIndexes.h @@ -578,9 +578,9 @@ class raw_ostream; assert(!MI.isInsideBundle() && "Instructions inside bundles should use bundle start's slot."); assert(mi2iMap.find(&MI) == mi2iMap.end() && "Instr already indexed."); - // Numbering DBG_VALUE instructions could cause code generation to be + // Numbering debug instructions could cause code generation to be // affected by debug information. - assert(!MI.isDebugValue() && "Cannot number DBG_VALUE instructions."); + assert(!MI.isDebugInstr() && "Cannot number debug instructions."); assert(MI.getParent() != nullptr && "Instr must be added to function."); @@ -674,10 +674,10 @@ class raw_ostream; idx2MBBMap.push_back(IdxMBBPair(startIdx, mbb)); renumberIndexes(newItr); - std::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare()); + llvm::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare()); } - /// \brief Free the resources that were required to maintain a SlotIndex. + /// Free the resources that were required to maintain a SlotIndex. /// /// Once an index is no longer needed (for instance because the instruction /// at that index has been moved), the resources required to maintain the diff --git a/contrib/llvm/include/llvm/CodeGen/StackMaps.h b/contrib/llvm/include/llvm/CodeGen/StackMaps.h index 4407114d2741..3c9850265737 100644 --- a/contrib/llvm/include/llvm/CodeGen/StackMaps.h +++ b/contrib/llvm/include/llvm/CodeGen/StackMaps.h @@ -29,7 +29,7 @@ class MCStreamer; class raw_ostream; class TargetRegisterInfo; -/// \brief MI-level stackmap operands. +/// MI-level stackmap operands. /// /// MI stackmap operations take the form: /// <id>, <numBytes>, live args... @@ -60,7 +60,7 @@ public: } }; -/// \brief MI-level patchpoint operands. +/// MI-level patchpoint operands. /// /// MI patchpoint operations take the form: /// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ... @@ -137,7 +137,7 @@ public: return getVarIdx(); } - /// \brief Get the next scratch register operand index. + /// Get the next scratch register operand index. unsigned getNextScratchIdx(unsigned StartIdx = 0) const; }; @@ -236,15 +236,15 @@ public: FnInfos.clear(); } - /// \brief Generate a stackmap record for a stackmap instruction. + /// Generate a stackmap record for a stackmap instruction. /// /// MI must be a raw STACKMAP, not a PATCHPOINT. void recordStackMap(const MachineInstr &MI); - /// \brief Generate a stackmap record for a patchpoint instruction. + /// Generate a stackmap record for a patchpoint instruction. void recordPatchPoint(const MachineInstr &MI); - /// \brief Generate a stackmap record for a statepoint instruction. + /// Generate a stackmap record for a statepoint instruction. void recordStatepoint(const MachineInstr &MI); /// If there is any stack map data, create a stack map section and serialize @@ -293,11 +293,11 @@ private: MachineInstr::const_mop_iterator MOE, LocationVec &Locs, LiveOutVec &LiveOuts) const; - /// \brief Create a live-out register record for the given register @p Reg. + /// 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 + /// 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; @@ -311,16 +311,16 @@ private: MachineInstr::const_mop_iterator MOE, bool recordResult = false); - /// \brief Emit the stackmap header. + /// Emit the stackmap header. void emitStackmapHeader(MCStreamer &OS); - /// \brief Emit the function frame record for each function. + /// Emit the function frame record for each function. void emitFunctionFrameRecords(MCStreamer &OS); - /// \brief Emit the constant pool. + /// Emit the constant pool. void emitConstantPoolEntries(MCStreamer &OS); - /// \brief Emit the callsite info for each stackmap/patchpoint intrinsic call. + /// Emit the callsite info for each stackmap/patchpoint intrinsic call. void emitCallsiteEntries(MCStreamer &OS); void print(raw_ostream &OS); diff --git a/contrib/llvm/include/llvm/CodeGen/StackProtector.h b/contrib/llvm/include/llvm/CodeGen/StackProtector.h index 72de212d0df9..a506ac636a17 100644 --- a/contrib/llvm/include/llvm/CodeGen/StackProtector.h +++ b/contrib/llvm/include/llvm/CodeGen/StackProtector.h @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Triple.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/ValueMap.h" #include "llvm/Pass.h" @@ -35,24 +36,11 @@ class TargetMachine; class Type; class StackProtector : public FunctionPass { -public: - /// SSPLayoutKind. Stack Smashing Protection (SSP) rules require that - /// vulnerable stack allocations are located close the stack protector. - enum SSPLayoutKind { - SSPLK_None, ///< Did not trigger a stack protector. No effect on data - ///< layout. - SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest - ///< to the stack protector. - SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest - ///< to the stack protector. - SSPLK_AddrOf ///< The address of this allocation is exposed and - ///< triggered protection. 3rd closest to the protector. - }; - +private: /// A mapping of AllocaInsts to their required SSP layout. - using SSPLayoutMap = ValueMap<const AllocaInst *, SSPLayoutKind>; + using SSPLayoutMap = DenseMap<const AllocaInst *, + MachineFrameInfo::SSPLayoutKind>; -private: const TargetMachine *TM = nullptr; /// TLI - Keep a pointer of a TargetLowering to consult for determining @@ -70,7 +58,7 @@ private: /// AllocaInst triggers a stack protector. SSPLayoutMap Layout; - /// \brief The minimum size of buffers that will receive stack smashing + /// The minimum size of buffers that will receive stack smashing /// protection when -fstack-protection is used. unsigned SSPBufferSize = 0; @@ -107,7 +95,7 @@ private: bool ContainsProtectableArray(Type *Ty, bool &IsLarge, bool Strong = false, bool InStruct = false) const; - /// \brief Check whether a stack allocation has its address taken. + /// Check whether a stack allocation has its address taken. bool HasAddressTaken(const Instruction *AI); /// RequiresStackProtector - Check whether or not this function needs a @@ -123,14 +111,12 @@ public: void getAnalysisUsage(AnalysisUsage &AU) const override; - SSPLayoutKind getSSPLayout(const AllocaInst *AI) const; - // Return true if StackProtector is supposed to be handled by SelectionDAG. bool shouldEmitSDCheck(const BasicBlock &BB) const; - void adjustForColoring(const AllocaInst *From, const AllocaInst *To); - bool runOnFunction(Function &Fn) override; + + void copyToMachineFrameInfo(MachineFrameInfo &MFI) const; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/TargetCallingConv.h b/contrib/llvm/include/llvm/CodeGen/TargetCallingConv.h index 8646a15599cb..7d138f585171 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetCallingConv.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetCallingConv.h @@ -14,8 +14,8 @@ #ifndef LLVM_CODEGEN_TARGETCALLINGCONV_H #define LLVM_CODEGEN_TARGETCALLINGCONV_H -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/MathExtras.h" #include <cassert> #include <climits> diff --git a/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h index 61f1cf07bcf2..f8effee998e3 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetFrameLowering.h @@ -158,6 +158,10 @@ public: return false; } + /// Returns true if the target can safely skip saving callee-saved registers + /// for noreturn nounwind functions. + virtual bool enableCalleeSaveSkip(const MachineFunction &MF) const; + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. virtual void emitPrologue(MachineFunction &MF, @@ -341,6 +345,14 @@ public: return false; return true; } + + /// Return initial CFA offset value i.e. the one valid at the beginning of the + /// function (before any stack operations). + virtual int getInitialCFAOffset(const MachineFunction &MF) const; + + /// Return initial CFA register value i.e. the one valid at the beginning of + /// the function (before any stack operations). + virtual unsigned getInitialCFARegister(const MachineFunction &MF) const; }; } // End llvm namespace diff --git a/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h index 57dee3bb44b3..b5bc561d834c 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -18,12 +18,14 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/None.h" +#include "llvm/CodeGen/LiveRegUnits.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineCombinerPattern.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineOutliner.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/Support/BranchProbability.h" @@ -79,7 +81,7 @@ public: /// Given a machine instruction descriptor, returns the register /// class constraint for OpNum, or NULL. - const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, unsigned OpNum, + const TargetRegisterClass *getRegClass(const MCInstrDesc &MCID, unsigned OpNum, const TargetRegisterInfo *TRI, const MachineFunction &MF) const; @@ -225,6 +227,17 @@ public: return 0; } + /// Optional extension of isLoadFromStackSlot that returns the number of + /// bytes loaded from the stack. This must be implemented if a backend + /// supports partial stack slot spills/loads to further disambiguate + /// what the load does. + virtual unsigned isLoadFromStackSlot(const MachineInstr &MI, + int &FrameIndex, + unsigned &MemBytes) const { + MemBytes = 0; + return isLoadFromStackSlot(MI, FrameIndex); + } + /// Check for post-frame ptr elimination stack locations as well. /// This uses a heuristic so it isn't reliable for correctness. virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr &MI, @@ -252,6 +265,17 @@ public: return 0; } + /// Optional extension of isStoreToStackSlot that returns the number of + /// bytes stored to the stack. This must be implemented if a backend + /// supports partial stack slot spills/loads to further disambiguate + /// what the store does. + virtual unsigned isStoreToStackSlot(const MachineInstr &MI, + int &FrameIndex, + unsigned &MemBytes) const { + MemBytes = 0; + return isStoreToStackSlot(MI, FrameIndex); + } + /// Check for post-frame ptr elimination stack locations as well. /// This uses a heuristic, so it isn't reliable for correctness. virtual unsigned isStoreToStackSlotPostFE(const MachineInstr &MI, @@ -325,7 +349,7 @@ public: unsigned SubIdx, const MachineInstr &Orig, const TargetRegisterInfo &TRI) const; - /// \brief Clones instruction or the whole instruction bundle \p Orig and + /// Clones instruction or the whole instruction bundle \p Orig and /// insert into \p MBB before \p InsertBefore. The target may update operands /// that are required to be unique. /// @@ -635,8 +659,8 @@ public: return true; } - /// Generate code to reduce the loop iteration by one and check if the loop is - /// finished. Return the value/register of the the new loop count. We need + /// Generate code to reduce the loop iteration by one and check if the loop + /// is finished. Return the value/register of the new loop count. We need /// this function when peeling off one or more iterations of a loop. This /// function assumes the nth iteration is peeled first. virtual unsigned reduceLoopCount(MachineBasicBlock &MBB, MachineInstr *IndVar, @@ -822,6 +846,15 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::copyPhysReg!"); } + /// If the specific machine instruction is a instruction that moves/copies + /// value from one register to another register return true along with + /// @Source machine operand and @Destination machine operand. + virtual bool isCopyInstr(const MachineInstr &MI, + const MachineOperand *&SourceOpNum, + const MachineOperand *&Destination) const { + return false; + } + /// Store the specified register of the given register class to the specified /// stack frame index. The store instruction is to be added to the given /// machine basic block before the specified machine instruction. If isKill @@ -876,7 +909,7 @@ public: /// The new instruction is inserted before MI, and the client is responsible /// for removing the old instruction. MachineInstr *foldMemoryOperand(MachineInstr &MI, ArrayRef<unsigned> Ops, - int FrameIndex, + int FI, LiveIntervals *LIS = nullptr) const; /// Same as the previous version except it allows folding of any load and @@ -928,13 +961,13 @@ public: /// \param InsInstrs - Vector of new instructions that implement P /// \param DelInstrs - Old instructions, including Root, that could be /// replaced by InsInstr - /// \param InstrIdxForVirtReg - map of virtual register to instruction in + /// \param InstIdxForVirtReg - map of virtual register to instruction in /// InsInstr that defines it virtual void genAlternativeCodeSequence( MachineInstr &Root, MachineCombinerPattern Pattern, SmallVectorImpl<MachineInstr *> &InsInstrs, SmallVectorImpl<MachineInstr *> &DelInstrs, - DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const; + DenseMap<unsigned, unsigned> &InstIdxForVirtReg) const; /// Attempt to reassociate \P Root and \P Prev according to \P Pattern to /// reduce critical path length. @@ -983,7 +1016,7 @@ protected: return nullptr; } - /// \brief Target-dependent implementation of getRegSequenceInputs. + /// Target-dependent implementation of getRegSequenceInputs. /// /// \returns true if it is possible to build the equivalent /// REG_SEQUENCE inputs with the pair \p MI, \p DefIdx. False otherwise. @@ -997,7 +1030,7 @@ protected: return false; } - /// \brief Target-dependent implementation of getExtractSubregInputs. + /// Target-dependent implementation of getExtractSubregInputs. /// /// \returns true if it is possible to build the equivalent /// EXTRACT_SUBREG inputs with the pair \p MI, \p DefIdx. False otherwise. @@ -1011,7 +1044,7 @@ protected: return false; } - /// \brief Target-dependent implementation of getInsertSubregInputs. + /// Target-dependent implementation of getInsertSubregInputs. /// /// \returns true if it is possible to build the equivalent /// INSERT_SUBREG inputs with the pair \p MI, \p DefIdx. False otherwise. @@ -1433,7 +1466,7 @@ public: return 0; } - /// \brief Return the minimum clearance before an instruction that reads an + /// Return the minimum clearance before an instruction that reads an /// unused register. /// /// For example, AVX instructions may copy part of a register operand into @@ -1500,7 +1533,7 @@ public: return false; } - /// \brief Return the value to use for the MachineCSE's LookAheadLimit, + /// Return the value to use for the MachineCSE's LookAheadLimit, /// which is a heuristic used for CSE'ing phys reg defs. virtual unsigned getMachineCSELookAheadLimit() const { // The default lookahead is small to prevent unprofitable quadratic @@ -1569,64 +1602,32 @@ public: return false; } - /// \brief Describes the number of instructions that it will take to call and - /// construct a frame for a given outlining candidate. - struct MachineOutlinerInfo { - /// Number of instructions to call an outlined function for this candidate. - unsigned CallOverhead; - - /// \brief Number of instructions to construct an outlined function frame - /// for this candidate. - unsigned FrameOverhead; - - /// \brief Represents the specific instructions that must be emitted to - /// construct a call to this candidate. - unsigned CallConstructionID; - - /// \brief Represents the specific instructions that must be emitted to - /// construct a frame for this candidate's outlined function. - unsigned FrameConstructionID; - - MachineOutlinerInfo() {} - MachineOutlinerInfo(unsigned CallOverhead, unsigned FrameOverhead, - unsigned CallConstructionID, - unsigned FrameConstructionID) - : CallOverhead(CallOverhead), FrameOverhead(FrameOverhead), - CallConstructionID(CallConstructionID), - FrameConstructionID(FrameConstructionID) {} - }; - - /// \brief Returns a \p MachineOutlinerInfo struct containing target-specific + /// Returns a \p outliner::OutlinedFunction struct containing target-specific /// information for a set of outlining candidates. - virtual MachineOutlinerInfo getOutlininingCandidateInfo( - std::vector< - std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>> - &RepeatedSequenceLocs) const { + virtual outliner::OutlinedFunction getOutliningCandidateInfo( + std::vector<outliner::Candidate> &RepeatedSequenceLocs) const { llvm_unreachable( - "Target didn't implement TargetInstrInfo::getOutliningOverhead!"); + "Target didn't implement TargetInstrInfo::getOutliningCandidateInfo!"); } - /// Represents how an instruction should be mapped by the outliner. - /// \p Legal instructions are those which are safe to outline. - /// \p Illegal instructions are those which cannot be outlined. - /// \p Invisible instructions are instructions which can be outlined, but - /// shouldn't actually impact the outlining result. - enum MachineOutlinerInstrType { Legal, Illegal, Invisible }; - /// Returns how or if \p MI should be outlined. - virtual MachineOutlinerInstrType getOutliningType(MachineInstr &MI) const { + virtual outliner::InstrType + getOutliningType(MachineBasicBlock::iterator &MIT, unsigned Flags) const { llvm_unreachable( "Target didn't implement TargetInstrInfo::getOutliningType!"); } - /// Insert a custom epilogue for outlined functions. - /// This may be empty, in which case no epilogue or return statement will be - /// emitted. - virtual void insertOutlinerEpilogue(MachineBasicBlock &MBB, - MachineFunction &MF, - const MachineOutlinerInfo &MInfo) const { + /// Returns target-defined flags defining properties of the MBB for + /// the outliner. + virtual unsigned getMachineOutlinerMBBFlags(MachineBasicBlock &MBB) const { + return 0x0; + } + + /// Insert a custom frame for outlined functions. + virtual void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, + const outliner::OutlinedFunction &OF) const { llvm_unreachable( - "Target didn't implement TargetInstrInfo::insertOutlinerEpilogue!"); + "Target didn't implement TargetInstrInfo::buildOutlinedFrame!"); } /// Insert a call to an outlined function into the program. @@ -1635,20 +1636,11 @@ public: virtual MachineBasicBlock::iterator insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, - const MachineOutlinerInfo &MInfo) const { + const outliner::Candidate &C) const { llvm_unreachable( "Target didn't implement TargetInstrInfo::insertOutlinedCall!"); } - /// Insert a custom prologue for outlined functions. - /// This may be empty, in which case no prologue will be emitted. - virtual void insertOutlinerPrologue(MachineBasicBlock &MBB, - MachineFunction &MF, - const MachineOutlinerInfo &MInfo) const { - llvm_unreachable( - "Target didn't implement TargetInstrInfo::insertOutlinerPrologue!"); - } - /// Return true if the function can safely be outlined from. /// A function \p MF is considered safe for outlining if an outlined function /// produced from instructions in F will produce a program which produces the @@ -1659,13 +1651,18 @@ public: "TargetInstrInfo::isFunctionSafeToOutlineFrom!"); } + /// Return true if the function should be outlined from by default. + virtual bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const { + return false; + } + private: unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode; unsigned CatchRetOpcode; unsigned ReturnOpcode; }; -/// \brief Provide DenseMapInfo for TargetInstrInfo::RegSubRegPair. +/// Provide DenseMapInfo for TargetInstrInfo::RegSubRegPair. template <> struct DenseMapInfo<TargetInstrInfo::RegSubRegPair> { using RegInfo = DenseMapInfo<unsigned>; @@ -1679,7 +1676,7 @@ template <> struct DenseMapInfo<TargetInstrInfo::RegSubRegPair> { RegInfo::getTombstoneKey()); } - /// \brief Reuse getHashValue implementation from + /// Reuse getHashValue implementation from /// std::pair<unsigned, unsigned>. static unsigned getHashValue(const TargetInstrInfo::RegSubRegPair &Val) { std::pair<unsigned, unsigned> PairVal = std::make_pair(Val.Reg, Val.SubReg); diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLowering.h b/contrib/llvm/include/llvm/CodeGen/TargetLowering.h index cea8472caa35..d5ff71cf9ac2 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetLowering.h @@ -29,9 +29,9 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/DivergenceAnalysis.h" #include "llvm/CodeGen/DAGCombine.h" #include "llvm/CodeGen/ISDOpcodes.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" @@ -52,6 +52,7 @@ #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Target/TargetMachine.h" #include <algorithm> #include <cassert> @@ -222,7 +223,7 @@ public: virtual ~TargetLoweringBase() = default; protected: - /// \brief Initialize all of the actions to default values. + /// Initialize all of the actions to default values. void initActions(); public: @@ -253,7 +254,8 @@ public: /// A documentation for this function would be nice... virtual MVT getScalarShiftAmountTy(const DataLayout &, EVT) const; - EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL) const; + EVT getShiftAmountTy(EVT LHSTy, const DataLayout &DL, + bool LegalTypes = true) const; /// Returns the type to be used for the index operand of: /// ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT, @@ -421,17 +423,17 @@ public: return true; } - /// \brief Return true if it is cheap to speculate a call to intrinsic cttz. + /// Return true if it is cheap to speculate a call to intrinsic cttz. virtual bool isCheapToSpeculateCttz() const { return false; } - /// \brief Return true if it is cheap to speculate a call to intrinsic ctlz. + /// Return true if it is cheap to speculate a call to intrinsic ctlz. virtual bool isCheapToSpeculateCtlz() const { return false; } - /// \brief Return true if ctlz instruction is fast. + /// Return true if ctlz instruction is fast. virtual bool isCtlzFast() const { return false; } @@ -444,13 +446,13 @@ public: return false; } - /// \brief Return true if it is cheaper to split the store of a merged int val + /// Return true if it is cheaper to split the store of a merged int val /// from a pair of smaller values into multiple stores. virtual bool isMultiStoresCheaperThanBitsMerge(EVT LTy, EVT HTy) const { return false; } - /// \brief Return if the target supports combining a + /// Return if the target supports combining a /// chain like: /// \code /// %andResult = and %val1, #mask @@ -507,7 +509,30 @@ public: return hasAndNotCompare(X); } - /// \brief Return true if the target wants to use the optimization that + /// There are two ways to clear extreme bits (either low or high): + /// Mask: x & (-1 << y) (the instcombine canonical form) + /// Shifts: x >> y << y + /// Return true if the variant with 2 shifts is preferred. + /// Return false if there is no preference. + virtual bool preferShiftsToClearExtremeBits(SDValue X) const { + // By default, let's assume that no one prefers shifts. + return false; + } + + /// Should we tranform the IR-optimal check for whether given truncation + /// down into KeptBits would be truncating or not: + /// (add %x, (1 << (KeptBits-1))) srccond (1 << KeptBits) + /// Into it's more traditional form: + /// ((%x << C) a>> C) dstcond %x + /// Return true if we should transform. + /// Return false if there is no preference. + virtual bool shouldTransformSignedTruncationCheck(EVT XVT, + unsigned KeptBits) const { + // By default, let's assume that no one prefers shifts. + return false; + } + + /// Return true if the target wants to use the optimization that /// turns ext(promotableInst1(...(promotableInstN(load)))) into /// promotedInst1(...(promotedInstN(ext(load)))). bool enableExtLdPromotion() const { return EnableExtLdPromotion; } @@ -746,10 +771,10 @@ public: /// operations don't trap except for integer divide and remainder. virtual bool canOpTrap(unsigned Op, EVT VT) const; - /// Similar to isShuffleMaskLegal. This is used by Targets can use this to - /// indicate if there is a suitable VECTOR_SHUFFLE that can be used to replace - /// a VAND with a constant pool entry. - virtual bool isVectorClearMaskLegal(const SmallVectorImpl<int> &/*Mask*/, + /// Similar to isShuffleMaskLegal. Targets can use this to indicate if there + /// is a suitable VECTOR_SHUFFLE that can be used to replace a VAND with a + /// constant pool entry. + virtual bool isVectorClearMaskLegal(ArrayRef<int> /*Mask*/, EVT /*VT*/) const { return false; } @@ -765,6 +790,39 @@ public: return OpActions[(unsigned)VT.getSimpleVT().SimpleTy][Op]; } + LegalizeAction getStrictFPOperationAction(unsigned Op, EVT VT) const { + unsigned EqOpc; + switch (Op) { + default: llvm_unreachable("Unexpected FP pseudo-opcode"); + case ISD::STRICT_FADD: EqOpc = ISD::FADD; break; + case ISD::STRICT_FSUB: EqOpc = ISD::FSUB; break; + case ISD::STRICT_FMUL: EqOpc = ISD::FMUL; break; + case ISD::STRICT_FDIV: EqOpc = ISD::FDIV; break; + case ISD::STRICT_FSQRT: EqOpc = ISD::FSQRT; break; + case ISD::STRICT_FPOW: EqOpc = ISD::FPOW; break; + case ISD::STRICT_FPOWI: EqOpc = ISD::FPOWI; break; + case ISD::STRICT_FMA: EqOpc = ISD::FMA; break; + case ISD::STRICT_FSIN: EqOpc = ISD::FSIN; break; + case ISD::STRICT_FCOS: EqOpc = ISD::FCOS; break; + case ISD::STRICT_FEXP: EqOpc = ISD::FEXP; break; + case ISD::STRICT_FEXP2: EqOpc = ISD::FEXP2; break; + case ISD::STRICT_FLOG: EqOpc = ISD::FLOG; break; + case ISD::STRICT_FLOG10: EqOpc = ISD::FLOG10; break; + case ISD::STRICT_FLOG2: EqOpc = ISD::FLOG2; break; + case ISD::STRICT_FRINT: EqOpc = ISD::FRINT; break; + case ISD::STRICT_FNEARBYINT: EqOpc = ISD::FNEARBYINT; break; + } + + auto Action = getOperationAction(EqOpc, VT); + + // We don't currently handle Custom or Promote for strict FP pseudo-ops. + // For now, we just expand for those cases. + if (Action != Legal) + Action = Expand; + + return Action; + } + /// Return true if the specified operation is legal on this target or can be /// made legal with custom lowering. This is used to help guide high-level /// lowering decisions. @@ -812,7 +870,7 @@ public: bool rangeFitsInWord(const APInt &Low, const APInt &High, const DataLayout &DL) const { // FIXME: Using the pointer type doesn't seem ideal. - uint64_t BW = DL.getPointerSizeInBits(); + uint64_t BW = DL.getIndexSizeInBits(0u); uint64_t Range = (High - Low).getLimitedValue(UINT64_MAX - 1) + 1; return Range <= BW; } @@ -820,7 +878,7 @@ public: /// Return true if lowering to a jump table is suitable for a set of case /// clusters which may contain \p NumCases cases, \p Range range of values. /// FIXME: This function check the maximum table size and density, but the - /// minimum size is not checked. It would be nice if the the minimum size is + /// minimum size is not checked. It would be nice if the minimum size is /// also combined within this function. Currently, the minimum size check is /// performed in findJumpTable() in SelectionDAGBuiler and /// getEstimatedNumberOfCaseClusters() in BasicTTIImpl. @@ -986,9 +1044,14 @@ public: /// Return true if the specified condition code is legal on this target. bool isCondCodeLegal(ISD::CondCode CC, MVT VT) const { - return - getCondCodeAction(CC, VT) == Legal || - getCondCodeAction(CC, VT) == Custom; + return getCondCodeAction(CC, VT) == Legal; + } + + /// Return true if the specified condition code is legal or custom on this + /// target. + bool isCondCodeLegalOrCustom(ISD::CondCode CC, MVT VT) const { + return getCondCodeAction(CC, VT) == Legal || + getCondCodeAction(CC, VT) == Custom; } /// If the action for this operation is to promote, this method returns the @@ -1110,10 +1173,6 @@ public: /// Certain combinations of ABIs, Targets and features require that types /// are legal for some operations and not for other operations. /// For MIPS all vector types must be passed through the integer register set. - virtual MVT getRegisterTypeForCallingConv(MVT VT) const { - return getRegisterType(VT); - } - virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, EVT VT) const { return getRegisterType(Context, VT); @@ -1172,7 +1231,7 @@ public: return getPointerTy(DL).getSizeInBits(); } - /// \brief Get maximum # of store operations permitted for llvm.memset + /// Get maximum # of store operations permitted for llvm.memset /// /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memset. The value is set by the target at the @@ -1182,7 +1241,7 @@ public: return OptSize ? MaxStoresPerMemsetOptSize : MaxStoresPerMemset; } - /// \brief Get maximum # of store operations permitted for llvm.memcpy + /// Get maximum # of store operations permitted for llvm.memcpy /// /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memcpy. The value is set by the target at the @@ -1192,6 +1251,15 @@ public: return OptSize ? MaxStoresPerMemcpyOptSize : MaxStoresPerMemcpy; } + /// \brief Get maximum # of store operations to be glued together + /// + /// This function returns the maximum number of store operations permitted + /// to glue together during lowering of llvm.memcpy. The value is set by + // the target at the performance threshold for such a replacement. + virtual unsigned getMaxGluedStoresPerMemcpy() const { + return MaxGluedStoresPerMemcpy; + } + /// Get maximum # of load operations permitted for memcmp /// /// This function returns the maximum number of load operations permitted @@ -1202,7 +1270,19 @@ public: return OptSize ? MaxLoadsPerMemcmpOptSize : MaxLoadsPerMemcmp; } - /// \brief Get maximum # of store operations permitted for llvm.memmove + /// For memcmp expansion when the memcmp result is only compared equal or + /// not-equal to 0, allow up to this number of load pairs per block. As an + /// example, this may allow 'memcmp(a, b, 3) == 0' in a single block: + /// a0 = load2bytes &a[0] + /// b0 = load2bytes &b[0] + /// a2 = load1byte &a[2] + /// b2 = load1byte &b[2] + /// r = cmp eq (a0 ^ b0 | a2 ^ b2), 0 + virtual unsigned getMemcmpEqZeroLoadsPerBlock() const { + return 1; + } + + /// Get maximum # of store operations permitted for llvm.memmove /// /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memmove. The value is set by the target at the @@ -1212,7 +1292,7 @@ public: return OptSize ? MaxStoresPerMemmoveOptSize : MaxStoresPerMemmove; } - /// \brief Determine if the target supports unaligned memory accesses. + /// Determine if the target supports unaligned memory accesses. /// /// 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 @@ -1350,7 +1430,7 @@ public: /// If the target has a standard location for the stack protector guard, /// returns the address of that location. Otherwise, returns nullptr. /// DEPRECATED: please override useLoadStackGuardNode and customize - /// LOAD_STACK_GUARD, or customize @llvm.stackguard(). + /// LOAD_STACK_GUARD, or customize \@llvm.stackguard(). virtual Value *getIRStackGuard(IRBuilder<> &IRB) const; /// Inserts necessary declarations for SSP (stack protection) purpose. @@ -1905,7 +1985,7 @@ public: Type *Ty, unsigned AddrSpace, Instruction *I = nullptr) const; - /// \brief Return the cost of the scaling factor used in the addressing mode + /// Return the cost of the scaling factor used in the addressing mode /// represented by AM for this target, for a load/store of the specified type. /// /// If the AM is supported, the return value must be >= 0. @@ -2098,11 +2178,14 @@ public: return false; } - /// \brief Get the maximum supported factor for interleaved memory accesses. + /// Return true if the target has a vector blend instruction. + virtual bool hasVectorBlend() const { return false; } + + /// Get the maximum supported factor for interleaved memory accesses. /// Default to be the minimum interleave factor: 2. virtual unsigned getMaxSupportedInterleaveFactor() const { return 2; } - /// \brief Lower an interleaved load to target specific intrinsics. Return + /// Lower an interleaved load to target specific intrinsics. Return /// true on success. /// /// \p LI is the vector load instruction. @@ -2116,7 +2199,7 @@ public: return false; } - /// \brief Lower an interleaved store to target specific intrinsics. Return + /// Lower an interleaved store to target specific intrinsics. Return /// true on success. /// /// \p SI is the vector store instruction. @@ -2189,7 +2272,7 @@ public: return false; } - /// \brief Return true if it is beneficial to convert a load of a constant to + /// 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 @@ -2214,6 +2297,11 @@ public: return false; } + // Return true if CodeGenPrepare should consider splitting large offset of a + // GEP to make the GEP fit into the addressing mode and can be sunk into the + // same blocks of its users. + virtual bool shouldConsiderGEPOffsetSplit() const { return false; } + //===--------------------------------------------------------------------===// // Runtime Library hooks // @@ -2453,7 +2541,7 @@ protected: /// expected to be merged. unsigned GatherAllAliasesMaxDepth; - /// \brief Specify maximum number of store instructions per memset call. + /// Specify maximum number of store instructions per memset call. /// /// When lowering \@llvm.memset this field specifies the maximum number of /// store operations that may be substituted for the call to memset. Targets @@ -2469,7 +2557,7 @@ protected: /// to memset, used for functions with OptSize attribute. unsigned MaxStoresPerMemsetOptSize; - /// \brief Specify maximum bytes of store instructions per memcpy call. + /// Specify maximum bytes of store instructions per memcpy call. /// /// When lowering \@llvm.memcpy this field specifies the maximum number of /// store operations that may be substituted for a call to memcpy. Targets @@ -2482,13 +2570,21 @@ protected: /// constant size. unsigned MaxStoresPerMemcpy; + + /// \brief Specify max number of store instructions to glue in inlined memcpy. + /// + /// When memcpy is inlined based on MaxStoresPerMemcpy, specify maximum number + /// of store instructions to keep together. This helps in pairing and + // vectorization later on. + unsigned MaxGluedStoresPerMemcpy = 0; + /// Maximum number of store operations that may be substituted for a call to /// memcpy, used for functions with OptSize attribute. unsigned MaxStoresPerMemcpyOptSize; unsigned MaxLoadsPerMemcmp; unsigned MaxLoadsPerMemcmpOptSize; - /// \brief Specify maximum bytes of store instructions per memmove call. + /// Specify maximum bytes of store instructions per memmove call. /// /// When lowering \@llvm.memmove this field specifies the maximum number of /// store instructions that may be substituted for a call to memmove. Targets @@ -2520,6 +2616,16 @@ protected: /// sequence of memory operands that is recognized by PrologEpilogInserter. MachineBasicBlock *emitPatchPoint(MachineInstr &MI, MachineBasicBlock *MBB) const; + + /// Replace/modify the XRay custom event operands with target-dependent + /// details. + MachineBasicBlock *emitXRayCustomEvent(MachineInstr &MI, + MachineBasicBlock *MBB) const; + + /// Replace/modify the XRay typed event operands with target-dependent + /// details. + MachineBasicBlock *emitXRayTypedEvent(MachineInstr &MI, + MachineBasicBlock *MBB) const; }; /// This class defines information used to lower LLVM code to legal SelectionDAG @@ -2539,6 +2645,16 @@ public: bool isPositionIndependent() const; + virtual bool isSDNodeSourceOfDivergence(const SDNode *N, + FunctionLoweringInfo *FLI, + DivergenceAnalysis *DA) const { + return false; + } + + virtual bool isSDNodeAlwaysUniform(const SDNode * N) const { + return false; + } + /// Returns true by value, base pointer and offset pointer and addressing mode /// by reference if the node's address can be legally represented as /// pre-indexed load / store address. @@ -2690,6 +2806,30 @@ public: bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask, DAGCombinerInfo &DCI) const; + /// Look at Vector Op. At this point, we know that only the DemandedElts + /// elements of the result of Op are ever used downstream. If we can use + /// this information to simplify Op, create a new simplified DAG node and + /// return true, storing the original and new nodes in TLO. + /// Otherwise, analyze the expression and return a mask of KnownUndef and + /// KnownZero elements for the expression (used to simplify the caller). + /// The KnownUndef/Zero elements may only be accurate for those bits + /// in the DemandedMask. + /// \p AssumeSingleUse When this parameter is true, this function will + /// attempt to simplify \p Op even if there are multiple uses. + /// Callers are responsible for correctly updating the DAG based on the + /// results of this function, because simply replacing replacing TLO.Old + /// with TLO.New will be incorrect when this parameter is true and TLO.Old + /// has multiple uses. + bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedEltMask, + APInt &KnownUndef, APInt &KnownZero, + TargetLoweringOpt &TLO, unsigned Depth = 0, + bool AssumeSingleUse = false) const; + + /// Helper wrapper around SimplifyDemandedVectorElts + bool SimplifyDemandedVectorElts(SDValue Op, const APInt &DemandedElts, + APInt &KnownUndef, APInt &KnownZero, + DAGCombinerInfo &DCI) const; + /// Determine which of the bits specified in Mask are known to be either zero /// or one and return them in the KnownZero/KnownOne bitsets. The DemandedElts /// argument allows us to only collect the known bits that are shared by the @@ -2718,6 +2858,15 @@ public: const SelectionDAG &DAG, unsigned Depth = 0) const; + /// Attempt to simplify any target nodes based on the demanded vector + /// elements, returning true on success. Otherwise, analyze the expression and + /// return a mask of KnownUndef and KnownZero elements for the expression + /// (used to simplify the caller). The KnownUndef/Zero elements may only be + /// accurate for those bits in the DemandedMask + virtual bool SimplifyDemandedVectorEltsForTargetNode( + SDValue Op, const APInt &DemandedElts, APInt &KnownUndef, + APInt &KnownZero, TargetLoweringOpt &TLO, unsigned Depth = 0) const; + struct DAGCombinerInfo { void *DC; // The DAG Combiner object. CombineLevel Level; @@ -2731,7 +2880,7 @@ public: bool isBeforeLegalize() const { return Level == BeforeLegalizeTypes; } bool isBeforeLegalizeOps() const { return Level < AfterLegalizeVectorOps; } - bool isAfterLegalizeVectorOps() const { + bool isAfterLegalizeDAG() const { return Level == AfterLegalizeDAG; } CombineLevel getDAGCombineLevel() { return Level; } @@ -2753,12 +2902,8 @@ public: /// from getBooleanContents(). bool isConstFalseVal(const SDNode *N) const; - /// Return a constant of type VT that contains a true value that respects - /// getBooleanContents() - SDValue getConstTrueVal(SelectionDAG &DAG, EVT VT, const SDLoc &DL) const; - /// Return if \p N is a True value when extended to \p VT. - bool isExtendedTrueVal(const ConstantSDNode *N, EVT VT, bool Signed) const; + bool isExtendedTrueVal(const ConstantSDNode *N, EVT VT, bool SExt) const; /// Try to simplify a setcc built with the specified operands and cc. If it is /// unable to simplify it, return a null SDValue. @@ -3479,7 +3624,7 @@ public: /// bounds the returned pointer is unspecified, but will be within the vector /// bounds. SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, - SDValue Idx) const; + SDValue Index) const; //===--------------------------------------------------------------------===// // Instruction Emitting Hooks @@ -3518,6 +3663,13 @@ public: virtual SDValue LowerToTLSEmulatedModel(const GlobalAddressSDNode *GA, SelectionDAG &DAG) const; + /// Expands target specific indirect branch for the case of JumpTable + /// expanasion. + virtual SDValue expandIndirectJTBranch(const SDLoc& dl, SDValue Value, SDValue Addr, + SelectionDAG &DAG) const { + return DAG.getNode(ISD::BRIND, dl, MVT::Other, Value, Addr); + } + // seteq(x, 0) -> truncate(srl(ctlz(zext(x)), log2(#bits))) // If we're comparing for equality to zero and isCtlzFast is true, expose the // fact that this can be implemented as a ctlz/srl pair, so that the dag @@ -3528,6 +3680,11 @@ private: SDValue simplifySetCCWithAnd(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, DAGCombinerInfo &DCI, const SDLoc &DL) const; + + SDValue optimizeSetCCOfSignedTruncationCheck(EVT SCCVT, SDValue N0, + SDValue N1, ISD::CondCode Cond, + DAGCombinerInfo &DCI, + const SDLoc &DL) const; }; /// Given an LLVM IR type and return type attributes, compute the return value diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 69de9f8cb35d..f5c7fc824ab4 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -15,9 +15,9 @@ #ifndef LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H #define LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H -#include "llvm/CodeGen/TargetLoweringObjectFile.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCExpr.h" +#include "llvm/Target/TargetLoweringObjectFile.h" namespace llvm { @@ -36,16 +36,18 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { protected: MCSymbolRefExpr::VariantKind PLTRelativeVariantKind = MCSymbolRefExpr::VK_None; + const TargetMachine *TM; public: TargetLoweringObjectFileELF() = default; ~TargetLoweringObjectFileELF() override = default; + void Initialize(MCContext &Ctx, const TargetMachine &TM) override; + /// Emit Obj-C garbage collection and linker options. - void emitModuleMetadata(MCStreamer &Streamer, Module &M, - const TargetMachine &TM) const override; + void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override; - void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM, + void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &DL, const MCSymbol *Sym) const override; /// Given a constant with the SectionKind, return a section that it should be @@ -98,8 +100,7 @@ public: void Initialize(MCContext &Ctx, const TargetMachine &TM) override; /// Emit the module flags that specify the garbage collection information. - void emitModuleMetadata(MCStreamer &Streamer, Module &M, - const TargetMachine &TM) const override; + void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override; MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const override; @@ -153,8 +154,7 @@ public: const TargetMachine &TM) const override; /// Emit Obj-C garbage collection and linker options. - void emitModuleMetadata(MCStreamer &Streamer, Module &M, - const TargetMachine &TM) const override; + void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override; MCSection *getStaticCtorSection(unsigned Priority, const MCSymbol *KeySym) const override; @@ -163,6 +163,19 @@ public: void emitLinkerFlagsForGlobal(raw_ostream &OS, const GlobalValue *GV) const override; + + void emitLinkerFlagsForUsed(raw_ostream &OS, + const GlobalValue *GV) const override; + + const MCExpr *lowerRelativeReference(const GlobalValue *LHS, + const GlobalValue *RHS, + const TargetMachine &TM) const override; + + /// Given a mergeable constant with the specified size and relocation + /// information, return a section that it should be placed in. + MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, + const Constant *C, + unsigned &Align) const override; }; class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile { diff --git a/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.h b/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.h index 3ca31a970944..d0d959c4ae11 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.h @@ -22,7 +22,7 @@ namespace TargetOpcode { enum { #define HANDLE_TARGET_OPCODE(OPC) OPC, #define HANDLE_TARGET_OPCODE_MARKER(IDENT, OPC) IDENT = OPC, -#include "llvm/CodeGen/TargetOpcodes.def" +#include "llvm/Support/TargetOpcodes.def" }; } // end namespace TargetOpcode diff --git a/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h b/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h index da9841a0586e..5918c524d11c 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetPassConfig.h @@ -84,20 +84,6 @@ template <> struct isPodLike<IdentifyingPassPtr> { /// This is an ImmutablePass solely for the purpose of exposing CodeGen options /// to the internals of other CodeGen passes. class TargetPassConfig : public ImmutablePass { -public: - /// Pseudo Pass IDs. These are defined within TargetPassConfig because they - /// are unregistered pass IDs. They are only useful for use with - /// TargetPassConfig APIs to identify multiple occurrences of the same pass. - /// - - /// EarlyTailDuplicate - A clone of the TailDuplicate pass that runs early - /// during codegen, on SSA form. - static char EarlyTailDuplicateID; - - /// PostRAMachineLICM - A clone of the LICM pass that runs during late machine - /// optimization after regalloc. - static char PostRAMachineLICMID; - private: PassManagerBase *PM = nullptr; AnalysisID StartBefore = nullptr; @@ -218,9 +204,6 @@ public: /// Return true if the optimized regalloc pipeline is enabled. bool getOptimizeRegAlloc() const; - /// Return true if shrink wrapping is enabled. - bool getEnableShrinkWrap() const; - /// Return true if the default global register allocator is in use and /// has not be overriden on the command line with '-regalloc=...' bool usingDefaultRegAlloc() const; @@ -229,7 +212,7 @@ public: /// representation to the MI representation. /// Adds IR based lowering and target specific optimization passes and finally /// the core instruction selection passes. - /// \returns true if an error occured, false otherwise. + /// \returns true if an error occurred, false otherwise. bool addISelPasses(); /// Add common target configurable passes that perform LLVM IR to IR @@ -320,10 +303,6 @@ public: /// verification is enabled. void addVerifyPass(const std::string &Banner); - /// Check whether or not GlobalISel should be enabled by default. - /// Fallback/abort behavior is controlled via other methods. - virtual bool isGlobalISelEnabled() const; - /// Check whether or not GlobalISel should abort on error. /// When this is disabled, GlobalISel will fall back on SDISel instead of /// erroring out. diff --git a/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h index 81907538fb0b..538a5845466c 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetRegisterInfo.h @@ -21,11 +21,11 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/IR/CallingConv.h" #include "llvm/MC/LaneBitmask.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Printable.h" #include <cassert> @@ -238,12 +238,12 @@ private: protected: TargetRegisterInfo(const TargetRegisterInfoDesc *ID, - regclass_iterator RegClassBegin, - regclass_iterator RegClassEnd, + regclass_iterator RCB, + regclass_iterator RCE, const char *const *SRINames, const LaneBitmask *SRILaneMasks, LaneBitmask CoveringLanes, - const RegClassInfo *const RSI, + const RegClassInfo *const RCIs, unsigned Mode = 0); virtual ~TargetRegisterInfo(); @@ -444,6 +444,13 @@ public: return false; } + /// Returns the original SrcReg unless it is the target of a copy-like + /// operation, in which case we chain backwards through all such operations + /// to the ultimate source register. If a physical register is encountered, + /// we stop the search. + virtual unsigned lookThruCopyLike(unsigned SrcReg, + const MachineRegisterInfo *MRI) const; + /// Return a null-terminated list of all of the callee-saved registers on /// this target. The register should be in the order of desired callee-save /// stack frame offset. The first register is closest to the incoming stack @@ -752,6 +759,9 @@ public: virtual const RegClassWeight &getRegClassWeight( const TargetRegisterClass *RC) const = 0; + /// Returns size in bits of a phys/virtual/generic register. + unsigned getRegSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI) const; + /// Get the weight in units of pressure for this register unit. virtual unsigned getRegUnitWeight(unsigned RegUnit) const = 0; @@ -961,7 +971,7 @@ public: //===--------------------------------------------------------------------===// /// Subtarget Hooks - /// \brief SrcRC and DstRC will be morphed into NewRC if this returns true. + /// SrcRC and DstRC will be morphed into NewRC if this returns true. virtual bool shouldCoalesce(MachineInstr *MI, const TargetRegisterClass *SrcRC, unsigned SubReg, @@ -985,6 +995,12 @@ public: /// of the set as well. bool checkAllSuperRegsMarked(const BitVector &RegisterSet, ArrayRef<MCPhysReg> Exceptions = ArrayRef<MCPhysReg>()) const; + + virtual const TargetRegisterClass * + getConstrainedRegClassForOperand(const MachineOperand &MO, + const MachineRegisterInfo &MRI) const { + return nullptr; + } }; //===----------------------------------------------------------------------===// @@ -1151,7 +1167,8 @@ struct VirtReg2IndexFunctor { /// /// Usage: OS << printReg(Reg, TRI, SubRegIdx) << '\n'; Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI = nullptr, - unsigned SubRegIdx = 0); + unsigned SubIdx = 0, + const MachineRegisterInfo *MRI = nullptr); /// Create Printable object to print register units on a \ref raw_ostream. /// @@ -1163,11 +1180,11 @@ Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI = nullptr, /// Usage: OS << printRegUnit(Unit, TRI) << '\n'; Printable printRegUnit(unsigned Unit, const TargetRegisterInfo *TRI); -/// \brief Create Printable object to print virtual registers and physical +/// Create Printable object to print virtual registers and physical /// registers on a \ref raw_ostream. Printable printVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *TRI); -/// \brief Create Printable object to print register classes or register banks +/// Create Printable object to print register classes or register banks /// on a \ref raw_ostream. Printable printRegClassOrBank(unsigned Reg, const MachineRegisterInfo &RegInfo, const TargetRegisterInfo *TRI); diff --git a/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h b/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h index 1044f0bd27e6..6173925e23a1 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetSchedule.h @@ -19,6 +19,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/Config/llvm-config.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/MC/MCSchedule.h" @@ -45,24 +46,23 @@ class TargetSchedModel { public: TargetSchedModel() : SchedModel(MCSchedModel::GetDefaultSchedModel()) {} - /// \brief Initialize the machine model for instruction scheduling. + /// Initialize the machine model for instruction scheduling. /// /// The machine model API keeps a copy of the top-level MCSchedModel table /// indices and may query TargetSubtargetInfo and TargetInstrInfo to resolve /// dynamic properties. - void init(const MCSchedModel &sm, const TargetSubtargetInfo *sti, - const TargetInstrInfo *tii); + void init(const TargetSubtargetInfo *TSInfo); /// Return the MCSchedClassDesc for this instruction. const MCSchedClassDesc *resolveSchedClass(const MachineInstr *MI) const; - /// \brief TargetSubtargetInfo getter. + /// TargetSubtargetInfo getter. const TargetSubtargetInfo *getSubtargetInfo() const { return STI; } - /// \brief TargetInstrInfo getter. + /// TargetInstrInfo getter. const TargetInstrInfo *getInstrInfo() const { return TII; } - /// \brief Return true if this machine model includes an instruction-level + /// Return true if this machine model includes an instruction-level /// scheduling model. /// /// This is more detailed than the course grain IssueWidth and default @@ -71,7 +71,7 @@ public: const MCSchedModel *getMCSchedModel() const { return &SchedModel; } - /// \brief Return true if this machine model includes cycle-to-cycle itinerary + /// Return true if this machine model includes cycle-to-cycle itinerary /// data. /// /// This models scheduling at each stage in the processor pipeline. @@ -83,35 +83,35 @@ public: return nullptr; } - /// \brief Return true if this machine model includes an instruction-level + /// Return true if this machine model includes an instruction-level /// scheduling model or cycle-to-cycle itinerary data. bool hasInstrSchedModelOrItineraries() const { return hasInstrSchedModel() || hasInstrItineraries(); } - /// \brief Identify the processor corresponding to the current subtarget. + /// Identify the processor corresponding to the current subtarget. unsigned getProcessorID() const { return SchedModel.getProcessorID(); } - /// \brief Maximum number of micro-ops that may be scheduled per cycle. + /// Maximum number of micro-ops that may be scheduled per cycle. unsigned getIssueWidth() const { return SchedModel.IssueWidth; } - /// \brief Return true if new group must begin. + /// Return true if new group must begin. bool mustBeginGroup(const MachineInstr *MI, const MCSchedClassDesc *SC = nullptr) const; - /// \brief Return true if current group must end. + /// Return true if current group must end. bool mustEndGroup(const MachineInstr *MI, const MCSchedClassDesc *SC = nullptr) const; - /// \brief Return the number of issue slots required for this MI. + /// Return the number of issue slots required for this MI. unsigned getNumMicroOps(const MachineInstr *MI, const MCSchedClassDesc *SC = nullptr) const; - /// \brief Get the number of kinds of resources for this target. + /// Get the number of kinds of resources for this target. unsigned getNumProcResourceKinds() const { return SchedModel.getNumProcResourceKinds(); } - /// \brief Get a processor resource by ID for convenience. + /// Get a processor resource by ID for convenience. const MCProcResourceDesc *getProcResource(unsigned PIdx) const { return SchedModel.getProcResource(PIdx); } @@ -126,7 +126,7 @@ public: using ProcResIter = const MCWriteProcResEntry *; - // \brief Get an iterator into the processor resources consumed by this + // Get an iterator into the processor resources consumed by this // scheduling class. ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const { // The subtarget holds a single resource table for all processors. @@ -136,34 +136,34 @@ public: return STI->getWriteProcResEnd(SC); } - /// \brief Multiply the number of units consumed for a resource by this factor + /// Multiply the number of units consumed for a resource by this factor /// to normalize it relative to other resources. unsigned getResourceFactor(unsigned ResIdx) const { return ResourceFactors[ResIdx]; } - /// \brief Multiply number of micro-ops by this factor to normalize it + /// Multiply number of micro-ops by this factor to normalize it /// relative to other resources. unsigned getMicroOpFactor() const { return MicroOpFactor; } - /// \brief Multiply cycle count by this factor to normalize it relative to + /// Multiply cycle count by this factor to normalize it relative to /// other resources. This is the number of resource units per cycle. unsigned getLatencyFactor() const { return ResourceLCM; } - /// \brief Number of micro-ops that may be buffered for OOO execution. + /// Number of micro-ops that may be buffered for OOO execution. unsigned getMicroOpBufferSize() const { return SchedModel.MicroOpBufferSize; } - /// \brief Number of resource units that may be buffered for OOO execution. + /// Number of resource units that may be buffered for OOO execution. /// \return The buffer size in resource units or -1 for unlimited. int getResourceBufferSize(unsigned PIdx) const { return SchedModel.getProcResource(PIdx)->BufferSize; } - /// \brief Compute operand latency based on the available machine model. + /// Compute operand latency based on the available machine model. /// /// Compute and return the latency of the given data dependent def and use /// when the operand indices are already known. UseMI may be NULL for an @@ -172,7 +172,7 @@ public: const MachineInstr *UseMI, unsigned UseOperIdx) const; - /// \brief Compute the instruction latency based on the available machine + /// Compute the instruction latency based on the available machine /// model. /// /// Compute and return the expected latency of this instruction independent of @@ -185,18 +185,20 @@ public: /// if converter after moving it to TargetSchedModel). unsigned computeInstrLatency(const MachineInstr *MI, bool UseDefaultDefLatency = true) const; + unsigned computeInstrLatency(const MCInst &Inst) const; unsigned computeInstrLatency(unsigned Opcode) const; - /// \brief Output dependency latency of a pair of defs of the same register. + /// Output dependency latency of a pair of defs of the same register. /// /// This is typically one cycle. - unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx, + unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx, const MachineInstr *DepMI) const; - /// \brief Compute the reciprocal throughput of the given instruction. - Optional<double> computeInstrRThroughput(const MachineInstr *MI) const; - Optional<double> computeInstrRThroughput(unsigned Opcode) const; + /// Compute the reciprocal throughput of the given instruction. + double computeReciprocalThroughput(const MachineInstr *MI) const; + double computeReciprocalThroughput(const MCInst &MI) const; + double computeReciprocalThroughput(unsigned Opcode) const; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h index 9d99cba347ce..227e591f5a7d 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h +++ b/contrib/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h @@ -144,7 +144,7 @@ public: return 0; } - /// \brief True if the subtarget should run MachineScheduler after aggressive + /// True if the subtarget should run MachineScheduler after aggressive /// coalescing. /// /// This currently replaces the SelectionDAG scheduler with the "source" order @@ -152,14 +152,14 @@ public: /// TargetLowering preference). It does not yet disable the postRA scheduler. virtual bool enableMachineScheduler() const; - /// \brief Support printing of [latency:throughput] comment in output .S file. + /// Support printing of [latency:throughput] comment in output .S file. virtual bool supportPrintSchedInfo() const { return false; } - /// \brief True if the machine scheduler should disable the TLI preference + /// True if the machine scheduler should disable the TLI preference /// for preRA scheduling with the source level scheduler. virtual bool enableMachineSchedDefaultSched() const { return true; } - /// \brief True if the subtarget should enable joining global copies. + /// True if the subtarget should enable joining global copies. /// /// By default this is enabled if the machine scheduler is enabled, but /// can be overridden. @@ -171,13 +171,13 @@ public: /// which is the preferred way to influence this. virtual bool enablePostRAScheduler() const; - /// \brief True if the subtarget should run the atomic expansion pass. + /// True if the subtarget should run the atomic expansion pass. virtual bool enableAtomicExpand() const; /// True if the subtarget should run the indirectbr expansion pass. virtual bool enableIndirectBrExpand() const; - /// \brief Override generic scheduling policy within a region. + /// Override generic scheduling policy within a region. /// /// This is a convenient way for targets that don't provide any custom /// scheduling heuristics (no custom MachineSchedStrategy) to make @@ -185,7 +185,7 @@ public: virtual void overrideSchedPolicy(MachineSchedPolicy &Policy, unsigned NumRegionInstrs) const {} - // \brief Perform target specific adjustments to the latency of a schedule + // Perform target specific adjustments to the latency of a schedule // dependency. virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep &dep) const {} @@ -200,13 +200,13 @@ public: return CriticalPathRCs.clear(); } - // \brief Provide an ordered list of schedule DAG mutations for the post-RA + // Provide an ordered list of schedule DAG mutations for the post-RA // scheduler. virtual void getPostRAMutations( std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const { } - // \brief Provide an ordered list of schedule DAG mutations for the machine + // Provide an ordered list of schedule DAG mutations for the machine // pipeliner. virtual void getSMSMutations( std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const { @@ -218,25 +218,25 @@ public: return CodeGenOpt::Default; } - /// \brief True if the subtarget should run the local reassignment + /// True if the subtarget should run the local reassignment /// heuristic of the register allocator. /// This heuristic may be compile time intensive, \p OptLevel provides /// a finer grain to tune the register allocator. virtual bool enableRALocalReassignment(CodeGenOpt::Level OptLevel) const; - /// \brief True if the subtarget should consider the cost of local intervals + /// True if the subtarget should consider the cost of local intervals /// created by a split candidate when choosing the best split candidate. This /// heuristic may be compile time intensive. virtual bool enableAdvancedRASplitCost() const; - /// \brief Enable use of alias analysis during code generation (during MI + /// Enable use of alias analysis during code generation (during MI /// scheduling, DAGCombine, etc.). virtual bool useAA() const; - /// \brief Enable the use of the early if conversion pass. + /// Enable the use of the early if conversion pass. virtual bool enableEarlyIfConversion() const { return false; } - /// \brief Return PBQPConstraint(s) for the target. + /// Return PBQPConstraint(s) for the target. /// /// Override to provide custom PBQP constraints. virtual std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const { @@ -249,8 +249,11 @@ public: virtual bool enableSubRegLiveness() const { return false; } /// Returns string representation of scheduler comment - std::string getSchedInfoStr(const MachineInstr &MI) const override; + std::string getSchedInfoStr(const MachineInstr &MI) const; std::string getSchedInfoStr(MCInst const &MCI) const override; + + /// This is called after a .mir file was loaded. + virtual void mirFileLoaded(MachineFunction &MF) const; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/CodeGen/ValueTypes.h b/contrib/llvm/include/llvm/CodeGen/ValueTypes.h index 40d501edde10..d2ef4a94f8e2 100644 --- a/contrib/llvm/include/llvm/CodeGen/ValueTypes.h +++ b/contrib/llvm/include/llvm/CodeGen/ValueTypes.h @@ -16,8 +16,8 @@ #ifndef LLVM_CODEGEN_VALUETYPES_H #define LLVM_CODEGEN_VALUETYPES_H -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/MathExtras.h" #include <cassert> #include <cstdint> diff --git a/contrib/llvm/include/llvm/CodeGen/ValueTypes.td b/contrib/llvm/include/llvm/CodeGen/ValueTypes.td index 73c7fb4ce4b3..0abb4ece1d14 100644 --- a/contrib/llvm/include/llvm/CodeGen/ValueTypes.td +++ b/contrib/llvm/include/llvm/CodeGen/ValueTypes.td @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// // // Value types - These values correspond to the register types defined in the -// ValueTypes.h file. If you update anything here, you must update it there as -// well! +// MachineValueTypes.h file. If you update anything here, you must update it +// there as well! // //===----------------------------------------------------------------------===// @@ -69,7 +69,7 @@ def v4i32 : ValueType<128, 43>; // 4 x i32 vector value def v8i32 : ValueType<256, 44>; // 8 x i32 vector value def v16i32 : ValueType<512, 45>; // 16 x i32 vector value def v32i32 : ValueType<1024,46>; // 32 x i32 vector value -def v64i32 : ValueType<2048,47>; // 32 x i32 vector value +def v64i32 : ValueType<2048,47>; // 64 x i32 vector value def v1i64 : ValueType<64 , 48>; // 1 x i64 vector value def v2i64 : ValueType<128, 49>; // 2 x i64 vector value @@ -145,6 +145,7 @@ def x86mmx : ValueType<64 , 109>; // X86 MMX value def FlagVT : ValueType<0 , 110>; // Pre-RA sched glue def isVoid : ValueType<0 , 111>; // Produces no value def untyped: ValueType<8 , 112>; // Produces an untyped value +def ExceptRef: ValueType<0, 113>; // WebAssembly's except_ref type def token : ValueType<0 , 248>; // TokenTy def MetadataVT: ValueType<0, 249>; // Metadata diff --git a/contrib/llvm/include/llvm/CodeGen/VirtRegMap.h b/contrib/llvm/include/llvm/CodeGen/VirtRegMap.h index 3b06f0393114..6a8e50a7e5f5 100644 --- a/contrib/llvm/include/llvm/CodeGen/VirtRegMap.h +++ b/contrib/llvm/include/llvm/CodeGen/VirtRegMap.h @@ -90,24 +90,24 @@ class TargetInstrInfo; void grow(); - /// @brief returns true if the specified virtual register is + /// returns true if the specified virtual register is /// mapped to a physical register bool hasPhys(unsigned virtReg) const { return getPhys(virtReg) != NO_PHYS_REG; } - /// @brief returns the physical register mapped to the specified + /// returns the physical register mapped to the specified /// virtual register unsigned getPhys(unsigned virtReg) const { assert(TargetRegisterInfo::isVirtualRegister(virtReg)); return Virt2PhysMap[virtReg]; } - /// @brief creates a mapping for the specified virtual register to + /// creates a mapping for the specified virtual register to /// the specified physical register void assignVirt2Phys(unsigned virtReg, MCPhysReg physReg); - /// @brief clears the specified virtual register's, physical + /// clears the specified virtual register's, physical /// register mapping void clearVirt(unsigned virtReg) { assert(TargetRegisterInfo::isVirtualRegister(virtReg)); @@ -116,26 +116,26 @@ class TargetInstrInfo; Virt2PhysMap[virtReg] = NO_PHYS_REG; } - /// @brief clears all virtual to physical register mappings + /// clears all virtual to physical register mappings void clearAllVirt() { Virt2PhysMap.clear(); grow(); } - /// @brief returns true if VirtReg is assigned to its preferred physreg. + /// returns true if VirtReg is assigned to its preferred physreg. bool hasPreferredPhys(unsigned VirtReg); - /// @brief returns true if VirtReg has a known preferred register. + /// returns true if VirtReg has a known preferred register. /// This returns false if VirtReg has a preference that is a virtual /// register that hasn't been assigned yet. bool hasKnownPreference(unsigned VirtReg); - /// @brief records virtReg is a split live interval from SReg. + /// records virtReg is a split live interval from SReg. void setIsSplitFromReg(unsigned virtReg, unsigned SReg) { Virt2SplitMap[virtReg] = SReg; } - /// @brief returns the live interval virtReg is split from. + /// returns the live interval virtReg is split from. unsigned getPreSplitReg(unsigned virtReg) const { return Virt2SplitMap[virtReg]; } @@ -149,7 +149,7 @@ class TargetInstrInfo; return Orig ? Orig : VirtReg; } - /// @brief returns true if the specified virtual register is not + /// returns true if the specified virtual register is not /// mapped to a stack slot or rematerialized. bool isAssignedReg(unsigned virtReg) const { if (getStackSlot(virtReg) == NO_STACK_SLOT) @@ -159,20 +159,20 @@ class TargetInstrInfo; return (Virt2SplitMap[virtReg] && Virt2PhysMap[virtReg] != NO_PHYS_REG); } - /// @brief returns the stack slot mapped to the specified virtual + /// returns the stack slot mapped to the specified virtual /// register int getStackSlot(unsigned virtReg) const { assert(TargetRegisterInfo::isVirtualRegister(virtReg)); return Virt2StackSlotMap[virtReg]; } - /// @brief create a mapping for the specifed virtual register to + /// create a mapping for the specifed virtual register to /// the next available stack slot int assignVirt2StackSlot(unsigned virtReg); - /// @brief create a mapping for the specified virtual register to + /// create a mapping for the specified virtual register to /// the specified stack slot - void assignVirt2StackSlot(unsigned virtReg, int frameIndex); + void assignVirt2StackSlot(unsigned virtReg, int SS); void print(raw_ostream &OS, const Module* M = nullptr) const override; void dump() const; diff --git a/contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h b/contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h new file mode 100644 index 000000000000..3ad6760d8813 --- /dev/null +++ b/contrib/llvm/include/llvm/CodeGen/WasmEHFuncInfo.h @@ -0,0 +1,80 @@ +//===--- llvm/CodeGen/WasmEHFuncInfo.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures for Wasm exception handling schemes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_WASMEHFUNCINFO_H +#define LLVM_CODEGEN_WASMEHFUNCINFO_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/IR/BasicBlock.h" + +namespace llvm { + +using BBOrMBB = PointerUnion<const BasicBlock *, MachineBasicBlock *>; + +struct WasmEHFuncInfo { + // When there is an entry <A, B>, if an exception is not caught by A, it + // should next unwind to the EH pad B. + DenseMap<BBOrMBB, BBOrMBB> EHPadUnwindMap; + // For entry <A, B>, A is a BB with an instruction that may throw + // (invoke/cleanupret in LLVM IR, call/rethrow in the backend) and B is an EH + // pad that A unwinds to. + DenseMap<BBOrMBB, BBOrMBB> ThrowUnwindMap; + + // Helper functions + const BasicBlock *getEHPadUnwindDest(const BasicBlock *BB) const { + return EHPadUnwindMap.lookup(BB).get<const BasicBlock *>(); + } + void setEHPadUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) { + EHPadUnwindMap[BB] = Dest; + } + const BasicBlock *getThrowUnwindDest(BasicBlock *BB) const { + return ThrowUnwindMap.lookup(BB).get<const BasicBlock *>(); + } + void setThrowUnwindDest(const BasicBlock *BB, const BasicBlock *Dest) { + ThrowUnwindMap[BB] = Dest; + } + bool hasEHPadUnwindDest(const BasicBlock *BB) const { + return EHPadUnwindMap.count(BB); + } + bool hasThrowUnwindDest(const BasicBlock *BB) const { + return ThrowUnwindMap.count(BB); + } + + MachineBasicBlock *getEHPadUnwindDest(MachineBasicBlock *MBB) const { + return EHPadUnwindMap.lookup(MBB).get<MachineBasicBlock *>(); + } + void setEHPadUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) { + EHPadUnwindMap[MBB] = Dest; + } + MachineBasicBlock *getThrowUnwindDest(MachineBasicBlock *MBB) const { + return ThrowUnwindMap.lookup(MBB).get<MachineBasicBlock *>(); + } + void setThrowUnwindDest(MachineBasicBlock *MBB, MachineBasicBlock *Dest) { + ThrowUnwindMap[MBB] = Dest; + } + bool hasEHPadUnwindDest(MachineBasicBlock *MBB) const { + return EHPadUnwindMap.count(MBB); + } + bool hasThrowUnwindDest(MachineBasicBlock *MBB) const { + return ThrowUnwindMap.count(MBB); + } +}; + +// Analyze the IR in the given function to build WasmEHFuncInfo. +void calculateWasmEHInfo(const Function *F, WasmEHFuncInfo &EHInfo); + +} // namespace llvm + +#endif // LLVM_CODEGEN_WASMEHFUNCINFO_H diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h index 9f3a753ad1ae..9dbeb438f4ae 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -61,6 +61,30 @@ template <typename Kind> struct RemappedRecord { SmallVector<std::pair<uint32_t, TypeIndex>, 8> Mappings; }; +template <typename Record, typename Func> +Error forEachCodeViewRecord(ArrayRef<uint8_t> StreamBuffer, Func F) { + while (!StreamBuffer.empty()) { + if (StreamBuffer.size() < sizeof(RecordPrefix)) + return make_error<CodeViewError>(cv_error_code::corrupt_record); + + const RecordPrefix *Prefix = + reinterpret_cast<const RecordPrefix *>(StreamBuffer.data()); + + size_t RealLen = Prefix->RecordLen + 2; + if (StreamBuffer.size() < RealLen) + return make_error<CodeViewError>(cv_error_code::corrupt_record); + + ArrayRef<uint8_t> Data = StreamBuffer.take_front(RealLen); + StreamBuffer = StreamBuffer.drop_front(RealLen); + + Record R(static_cast<decltype(Record::Type)>((uint16_t)Prefix->RecordKind), + Data); + if (auto EC = F(R)) + return EC; + } + return Error::success(); +} + /// Read a complete record from a stream at a random offset. template <typename Kind> inline Expected<CVRecord<Kind>> readCVRecordFromStream(BinaryStreamRef Stream, diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h index df55e181364c..b765ba1abb4d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -20,7 +20,7 @@ class TypeCollection; class TypeVisitorCallbacks; enum VisitorDataSource { - VDS_BytesPresent, // The record bytes are passed into the the visitation + VDS_BytesPresent, // The record bytes are passed into the visitation // function. The algorithm should first deserialize them // before passing them on through the pipeline. VDS_BytesExternal // The record bytes are not present, and it is the diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h index 1a4f510c24ab..4ce9f68cffd9 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -22,8 +22,8 @@ namespace llvm { namespace codeview { -/// Distinguishes individual records in .debug$T section or PDB type stream. The -/// documentation and headers talk about this as the "leaf" type. +/// Distinguishes individual records in .debug$T or .debug$P section or PDB type +/// stream. The documentation and headers talk about this as the "leaf" type. enum class TypeRecordKind : uint16_t { #define TYPE_RECORD(lf_ename, value, name) name = value, #include "CodeViewTypes.def" @@ -531,7 +531,7 @@ enum LineFlags : uint16_t { LF_HaveColumns = 1, // CV_LINES_HAVE_COLUMNS }; -/// Data in the the SUBSEC_FRAMEDATA subection. +/// Data in the SUBSEC_FRAMEDATA subection. struct FrameData { support::ulittle32_t RvaStart; support::ulittle32_t CodeSize; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def index 3f0660294866..6da8893bd61a 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def @@ -15,254 +15,254 @@ #define CV_REGISTER(name, value) #endif -// This currently only contains the "register subset shraed by all processor +// This currently only contains the "register subset shared by all processor // types" (ERR etc.) and the x86 registers. -CV_REGISTER(ERR, 30000) -CV_REGISTER(TEB, 30001) -CV_REGISTER(TIMER, 30002) -CV_REGISTER(EFAD1, 30003) -CV_REGISTER(EFAD2, 30004) -CV_REGISTER(EFAD3, 30005) -CV_REGISTER(VFRAME, 30006) -CV_REGISTER(HANDLE, 30007) -CV_REGISTER(PARAMS, 30008) -CV_REGISTER(LOCALS, 30009) -CV_REGISTER(TID, 30010) -CV_REGISTER(ENV, 30011) -CV_REGISTER(CMDLN, 30012) +CV_REGISTER(CVRegERR, 30000) +CV_REGISTER(CVRegTEB, 30001) +CV_REGISTER(CVRegTIMER, 30002) +CV_REGISTER(CVRegEFAD1, 30003) +CV_REGISTER(CVRegEFAD2, 30004) +CV_REGISTER(CVRegEFAD3, 30005) +CV_REGISTER(CVRegVFRAME, 30006) +CV_REGISTER(CVRegHANDLE, 30007) +CV_REGISTER(CVRegPARAMS, 30008) +CV_REGISTER(CVRegLOCALS, 30009) +CV_REGISTER(CVRegTID, 30010) +CV_REGISTER(CVRegENV, 30011) +CV_REGISTER(CVRegCMDLN, 30012) -CV_REGISTER(NONE, 0) -CV_REGISTER(AL, 1) -CV_REGISTER(CL, 2) -CV_REGISTER(DL, 3) -CV_REGISTER(BL, 4) -CV_REGISTER(AH, 5) -CV_REGISTER(CH, 6) -CV_REGISTER(DH, 7) -CV_REGISTER(BH, 8) -CV_REGISTER(AX, 9) -CV_REGISTER(CX, 10) -CV_REGISTER(DX, 11) -CV_REGISTER(BX, 12) -CV_REGISTER(SP, 13) -CV_REGISTER(BP, 14) -CV_REGISTER(SI, 15) -CV_REGISTER(DI, 16) -CV_REGISTER(EAX, 17) -CV_REGISTER(ECX, 18) -CV_REGISTER(EDX, 19) -CV_REGISTER(EBX, 20) -CV_REGISTER(ESP, 21) -CV_REGISTER(EBP, 22) -CV_REGISTER(ESI, 23) -CV_REGISTER(EDI, 24) -CV_REGISTER(ES, 25) -CV_REGISTER(CS, 26) -CV_REGISTER(SS, 27) -CV_REGISTER(DS, 28) -CV_REGISTER(FS, 29) -CV_REGISTER(GS, 30) -CV_REGISTER(IP, 31) -CV_REGISTER(FLAGS, 32) -CV_REGISTER(EIP, 33) -CV_REGISTER(EFLAGS, 34) -CV_REGISTER(TEMP, 40) -CV_REGISTER(TEMPH, 41) -CV_REGISTER(QUOTE, 42) -CV_REGISTER(PCDR3, 43) -CV_REGISTER(PCDR4, 44) -CV_REGISTER(PCDR5, 45) -CV_REGISTER(PCDR6, 46) -CV_REGISTER(PCDR7, 47) -CV_REGISTER(CR0, 80) -CV_REGISTER(CR1, 81) -CV_REGISTER(CR2, 82) -CV_REGISTER(CR3, 83) -CV_REGISTER(CR4, 84) -CV_REGISTER(DR0, 90) -CV_REGISTER(DR1, 91) -CV_REGISTER(DR2, 92) -CV_REGISTER(DR3, 93) -CV_REGISTER(DR4, 94) -CV_REGISTER(DR5, 95) -CV_REGISTER(DR6, 96) -CV_REGISTER(DR7, 97) -CV_REGISTER(GDTR, 110) -CV_REGISTER(GDTL, 111) -CV_REGISTER(IDTR, 112) -CV_REGISTER(IDTL, 113) -CV_REGISTER(LDTR, 114) -CV_REGISTER(TR, 115) +CV_REGISTER(CVRegNONE, 0) +CV_REGISTER(CVRegAL, 1) +CV_REGISTER(CVRegCL, 2) +CV_REGISTER(CVRegDL, 3) +CV_REGISTER(CVRegBL, 4) +CV_REGISTER(CVRegAH, 5) +CV_REGISTER(CVRegCH, 6) +CV_REGISTER(CVRegDH, 7) +CV_REGISTER(CVRegBH, 8) +CV_REGISTER(CVRegAX, 9) +CV_REGISTER(CVRegCX, 10) +CV_REGISTER(CVRegDX, 11) +CV_REGISTER(CVRegBX, 12) +CV_REGISTER(CVRegSP, 13) +CV_REGISTER(CVRegBP, 14) +CV_REGISTER(CVRegSI, 15) +CV_REGISTER(CVRegDI, 16) +CV_REGISTER(CVRegEAX, 17) +CV_REGISTER(CVRegECX, 18) +CV_REGISTER(CVRegEDX, 19) +CV_REGISTER(CVRegEBX, 20) +CV_REGISTER(CVRegESP, 21) +CV_REGISTER(CVRegEBP, 22) +CV_REGISTER(CVRegESI, 23) +CV_REGISTER(CVRegEDI, 24) +CV_REGISTER(CVRegES, 25) +CV_REGISTER(CVRegCS, 26) +CV_REGISTER(CVRegSS, 27) +CV_REGISTER(CVRegDS, 28) +CV_REGISTER(CVRegFS, 29) +CV_REGISTER(CVRegGS, 30) +CV_REGISTER(CVRegIP, 31) +CV_REGISTER(CVRegFLAGS, 32) +CV_REGISTER(CVRegEIP, 33) +CV_REGISTER(CVRegEFLAGS, 34) +CV_REGISTER(CVRegTEMP, 40) +CV_REGISTER(CVRegTEMPH, 41) +CV_REGISTER(CVRegQUOTE, 42) +CV_REGISTER(CVRegPCDR3, 43) +CV_REGISTER(CVRegPCDR4, 44) +CV_REGISTER(CVRegPCDR5, 45) +CV_REGISTER(CVRegPCDR6, 46) +CV_REGISTER(CVRegPCDR7, 47) +CV_REGISTER(CVRegCR0, 80) +CV_REGISTER(CVRegCR1, 81) +CV_REGISTER(CVRegCR2, 82) +CV_REGISTER(CVRegCR3, 83) +CV_REGISTER(CVRegCR4, 84) +CV_REGISTER(CVRegDR0, 90) +CV_REGISTER(CVRegDR1, 91) +CV_REGISTER(CVRegDR2, 92) +CV_REGISTER(CVRegDR3, 93) +CV_REGISTER(CVRegDR4, 94) +CV_REGISTER(CVRegDR5, 95) +CV_REGISTER(CVRegDR6, 96) +CV_REGISTER(CVRegDR7, 97) +CV_REGISTER(CVRegGDTR, 110) +CV_REGISTER(CVRegGDTL, 111) +CV_REGISTER(CVRegIDTR, 112) +CV_REGISTER(CVRegIDTL, 113) +CV_REGISTER(CVRegLDTR, 114) +CV_REGISTER(CVRegTR, 115) -CV_REGISTER(PSEUDO1, 116) -CV_REGISTER(PSEUDO2, 117) -CV_REGISTER(PSEUDO3, 118) -CV_REGISTER(PSEUDO4, 119) -CV_REGISTER(PSEUDO5, 120) -CV_REGISTER(PSEUDO6, 121) -CV_REGISTER(PSEUDO7, 122) -CV_REGISTER(PSEUDO8, 123) -CV_REGISTER(PSEUDO9, 124) +CV_REGISTER(CVRegPSEUDO1, 116) +CV_REGISTER(CVRegPSEUDO2, 117) +CV_REGISTER(CVRegPSEUDO3, 118) +CV_REGISTER(CVRegPSEUDO4, 119) +CV_REGISTER(CVRegPSEUDO5, 120) +CV_REGISTER(CVRegPSEUDO6, 121) +CV_REGISTER(CVRegPSEUDO7, 122) +CV_REGISTER(CVRegPSEUDO8, 123) +CV_REGISTER(CVRegPSEUDO9, 124) -CV_REGISTER(ST0, 128) -CV_REGISTER(ST1, 129) -CV_REGISTER(ST2, 130) -CV_REGISTER(ST3, 131) -CV_REGISTER(ST4, 132) -CV_REGISTER(ST5, 133) -CV_REGISTER(ST6, 134) -CV_REGISTER(ST7, 135) -CV_REGISTER(CTRL, 136) -CV_REGISTER(STAT, 137) -CV_REGISTER(TAG, 138) -CV_REGISTER(FPIP, 139) -CV_REGISTER(FPCS, 140) -CV_REGISTER(FPDO, 141) -CV_REGISTER(FPDS, 142) -CV_REGISTER(ISEM, 143) -CV_REGISTER(FPEIP, 144) -CV_REGISTER(FPEDO, 145) +CV_REGISTER(CVRegST0, 128) +CV_REGISTER(CVRegST1, 129) +CV_REGISTER(CVRegST2, 130) +CV_REGISTER(CVRegST3, 131) +CV_REGISTER(CVRegST4, 132) +CV_REGISTER(CVRegST5, 133) +CV_REGISTER(CVRegST6, 134) +CV_REGISTER(CVRegST7, 135) +CV_REGISTER(CVRegCTRL, 136) +CV_REGISTER(CVRegSTAT, 137) +CV_REGISTER(CVRegTAG, 138) +CV_REGISTER(CVRegFPIP, 139) +CV_REGISTER(CVRegFPCS, 140) +CV_REGISTER(CVRegFPDO, 141) +CV_REGISTER(CVRegFPDS, 142) +CV_REGISTER(CVRegISEM, 143) +CV_REGISTER(CVRegFPEIP, 144) +CV_REGISTER(CVRegFPEDO, 145) -CV_REGISTER(MM0, 146) -CV_REGISTER(MM1, 147) -CV_REGISTER(MM2, 148) -CV_REGISTER(MM3, 149) -CV_REGISTER(MM4, 150) -CV_REGISTER(MM5, 151) -CV_REGISTER(MM6, 152) -CV_REGISTER(MM7, 153) +CV_REGISTER(CVRegMM0, 146) +CV_REGISTER(CVRegMM1, 147) +CV_REGISTER(CVRegMM2, 148) +CV_REGISTER(CVRegMM3, 149) +CV_REGISTER(CVRegMM4, 150) +CV_REGISTER(CVRegMM5, 151) +CV_REGISTER(CVRegMM6, 152) +CV_REGISTER(CVRegMM7, 153) -CV_REGISTER(XMM0, 154) -CV_REGISTER(XMM1, 155) -CV_REGISTER(XMM2, 156) -CV_REGISTER(XMM3, 157) -CV_REGISTER(XMM4, 158) -CV_REGISTER(XMM5, 159) -CV_REGISTER(XMM6, 160) -CV_REGISTER(XMM7, 161) +CV_REGISTER(CVRegXMM0, 154) +CV_REGISTER(CVRegXMM1, 155) +CV_REGISTER(CVRegXMM2, 156) +CV_REGISTER(CVRegXMM3, 157) +CV_REGISTER(CVRegXMM4, 158) +CV_REGISTER(CVRegXMM5, 159) +CV_REGISTER(CVRegXMM6, 160) +CV_REGISTER(CVRegXMM7, 161) -CV_REGISTER(MXCSR, 211) +CV_REGISTER(CVRegMXCSR, 211) -CV_REGISTER(EDXEAX, 212) +CV_REGISTER(CVRegEDXEAX, 212) -CV_REGISTER(EMM0L, 220) -CV_REGISTER(EMM1L, 221) -CV_REGISTER(EMM2L, 222) -CV_REGISTER(EMM3L, 223) -CV_REGISTER(EMM4L, 224) -CV_REGISTER(EMM5L, 225) -CV_REGISTER(EMM6L, 226) -CV_REGISTER(EMM7L, 227) +CV_REGISTER(CVRegEMM0L, 220) +CV_REGISTER(CVRegEMM1L, 221) +CV_REGISTER(CVRegEMM2L, 222) +CV_REGISTER(CVRegEMM3L, 223) +CV_REGISTER(CVRegEMM4L, 224) +CV_REGISTER(CVRegEMM5L, 225) +CV_REGISTER(CVRegEMM6L, 226) +CV_REGISTER(CVRegEMM7L, 227) -CV_REGISTER(EMM0H, 228) -CV_REGISTER(EMM1H, 229) -CV_REGISTER(EMM2H, 230) -CV_REGISTER(EMM3H, 231) -CV_REGISTER(EMM4H, 232) -CV_REGISTER(EMM5H, 233) -CV_REGISTER(EMM6H, 234) -CV_REGISTER(EMM7H, 235) +CV_REGISTER(CVRegEMM0H, 228) +CV_REGISTER(CVRegEMM1H, 229) +CV_REGISTER(CVRegEMM2H, 230) +CV_REGISTER(CVRegEMM3H, 231) +CV_REGISTER(CVRegEMM4H, 232) +CV_REGISTER(CVRegEMM5H, 233) +CV_REGISTER(CVRegEMM6H, 234) +CV_REGISTER(CVRegEMM7H, 235) -CV_REGISTER(MM00, 236) -CV_REGISTER(MM01, 237) -CV_REGISTER(MM10, 238) -CV_REGISTER(MM11, 239) -CV_REGISTER(MM20, 240) -CV_REGISTER(MM21, 241) -CV_REGISTER(MM30, 242) -CV_REGISTER(MM31, 243) -CV_REGISTER(MM40, 244) -CV_REGISTER(MM41, 245) -CV_REGISTER(MM50, 246) -CV_REGISTER(MM51, 247) -CV_REGISTER(MM60, 248) -CV_REGISTER(MM61, 249) -CV_REGISTER(MM70, 250) -CV_REGISTER(MM71, 251) +CV_REGISTER(CVRegMM00, 236) +CV_REGISTER(CVRegMM01, 237) +CV_REGISTER(CVRegMM10, 238) +CV_REGISTER(CVRegMM11, 239) +CV_REGISTER(CVRegMM20, 240) +CV_REGISTER(CVRegMM21, 241) +CV_REGISTER(CVRegMM30, 242) +CV_REGISTER(CVRegMM31, 243) +CV_REGISTER(CVRegMM40, 244) +CV_REGISTER(CVRegMM41, 245) +CV_REGISTER(CVRegMM50, 246) +CV_REGISTER(CVRegMM51, 247) +CV_REGISTER(CVRegMM60, 248) +CV_REGISTER(CVRegMM61, 249) +CV_REGISTER(CVRegMM70, 250) +CV_REGISTER(CVRegMM71, 251) -CV_REGISTER(BND0, 396) -CV_REGISTER(BND1, 397) -CV_REGISTER(BND2, 398) +CV_REGISTER(CVRegBND0, 396) +CV_REGISTER(CVRegBND1, 397) +CV_REGISTER(CVRegBND2, 398) -CV_REGISTER(XMM8, 252) -CV_REGISTER(XMM9, 253) -CV_REGISTER(XMM10, 254) -CV_REGISTER(XMM11, 255) -CV_REGISTER(XMM12, 256) -CV_REGISTER(XMM13, 257) -CV_REGISTER(XMM14, 258) -CV_REGISTER(XMM15, 259) +CV_REGISTER(CVRegXMM8, 252) +CV_REGISTER(CVRegXMM9, 253) +CV_REGISTER(CVRegXMM10, 254) +CV_REGISTER(CVRegXMM11, 255) +CV_REGISTER(CVRegXMM12, 256) +CV_REGISTER(CVRegXMM13, 257) +CV_REGISTER(CVRegXMM14, 258) +CV_REGISTER(CVRegXMM15, 259) -CV_REGISTER(SIL, 324) -CV_REGISTER(DIL, 325) -CV_REGISTER(BPL, 326) -CV_REGISTER(SPL, 327) +CV_REGISTER(CVRegSIL, 324) +CV_REGISTER(CVRegDIL, 325) +CV_REGISTER(CVRegBPL, 326) +CV_REGISTER(CVRegSPL, 327) -CV_REGISTER(RAX, 328) -CV_REGISTER(RBX, 329) -CV_REGISTER(RCX, 330) -CV_REGISTER(RDX, 331) -CV_REGISTER(RSI, 332) -CV_REGISTER(RDI, 333) -CV_REGISTER(RBP, 334) -CV_REGISTER(RSP, 335) +CV_REGISTER(CVRegRAX, 328) +CV_REGISTER(CVRegRBX, 329) +CV_REGISTER(CVRegRCX, 330) +CV_REGISTER(CVRegRDX, 331) +CV_REGISTER(CVRegRSI, 332) +CV_REGISTER(CVRegRDI, 333) +CV_REGISTER(CVRegRBP, 334) +CV_REGISTER(CVRegRSP, 335) -CV_REGISTER(R8, 336) -CV_REGISTER(R9, 337) -CV_REGISTER(R10, 338) -CV_REGISTER(R11, 339) -CV_REGISTER(R12, 340) -CV_REGISTER(R13, 341) -CV_REGISTER(R14, 342) -CV_REGISTER(R15, 343) +CV_REGISTER(CVRegR8, 336) +CV_REGISTER(CVRegR9, 337) +CV_REGISTER(CVRegR10, 338) +CV_REGISTER(CVRegR11, 339) +CV_REGISTER(CVRegR12, 340) +CV_REGISTER(CVRegR13, 341) +CV_REGISTER(CVRegR14, 342) +CV_REGISTER(CVRegR15, 343) -CV_REGISTER(R8B, 344) -CV_REGISTER(R9B, 345) -CV_REGISTER(R10B, 346) -CV_REGISTER(R11B, 347) -CV_REGISTER(R12B, 348) -CV_REGISTER(R13B, 349) -CV_REGISTER(R14B, 350) -CV_REGISTER(R15B, 351) +CV_REGISTER(CVRegR8B, 344) +CV_REGISTER(CVRegR9B, 345) +CV_REGISTER(CVRegR10B, 346) +CV_REGISTER(CVRegR11B, 347) +CV_REGISTER(CVRegR12B, 348) +CV_REGISTER(CVRegR13B, 349) +CV_REGISTER(CVRegR14B, 350) +CV_REGISTER(CVRegR15B, 351) -CV_REGISTER(R8W, 352) -CV_REGISTER(R9W, 353) -CV_REGISTER(R10W, 354) -CV_REGISTER(R11W, 355) -CV_REGISTER(R12W, 356) -CV_REGISTER(R13W, 357) -CV_REGISTER(R14W, 358) -CV_REGISTER(R15W, 359) +CV_REGISTER(CVRegR8W, 352) +CV_REGISTER(CVRegR9W, 353) +CV_REGISTER(CVRegR10W, 354) +CV_REGISTER(CVRegR11W, 355) +CV_REGISTER(CVRegR12W, 356) +CV_REGISTER(CVRegR13W, 357) +CV_REGISTER(CVRegR14W, 358) +CV_REGISTER(CVRegR15W, 359) -CV_REGISTER(R8D, 360) -CV_REGISTER(R9D, 361) -CV_REGISTER(R10D, 362) -CV_REGISTER(R11D, 363) -CV_REGISTER(R12D, 364) -CV_REGISTER(R13D, 365) -CV_REGISTER(R14D, 366) -CV_REGISTER(R15D, 367) +CV_REGISTER(CVRegR8D, 360) +CV_REGISTER(CVRegR9D, 361) +CV_REGISTER(CVRegR10D, 362) +CV_REGISTER(CVRegR11D, 363) +CV_REGISTER(CVRegR12D, 364) +CV_REGISTER(CVRegR13D, 365) +CV_REGISTER(CVRegR14D, 366) +CV_REGISTER(CVRegR15D, 367) // cvconst.h defines both CV_REG_YMM0 (252) and CV_AMD64_YMM0 (368). Keep the // original prefix to distinguish them. -CV_REGISTER(AMD64_YMM0, 368) -CV_REGISTER(AMD64_YMM1, 369) -CV_REGISTER(AMD64_YMM2, 370) -CV_REGISTER(AMD64_YMM3, 371) -CV_REGISTER(AMD64_YMM4, 372) -CV_REGISTER(AMD64_YMM5, 373) -CV_REGISTER(AMD64_YMM6, 374) -CV_REGISTER(AMD64_YMM7, 375) -CV_REGISTER(AMD64_YMM8, 376) -CV_REGISTER(AMD64_YMM9, 377) -CV_REGISTER(AMD64_YMM10, 378) -CV_REGISTER(AMD64_YMM11, 379) -CV_REGISTER(AMD64_YMM12, 380) -CV_REGISTER(AMD64_YMM13, 381) -CV_REGISTER(AMD64_YMM14, 382) -CV_REGISTER(AMD64_YMM15, 383) +CV_REGISTER(CVRegAMD64_YMM0, 368) +CV_REGISTER(CVRegAMD64_YMM1, 369) +CV_REGISTER(CVRegAMD64_YMM2, 370) +CV_REGISTER(CVRegAMD64_YMM3, 371) +CV_REGISTER(CVRegAMD64_YMM4, 372) +CV_REGISTER(CVRegAMD64_YMM5, 373) +CV_REGISTER(CVRegAMD64_YMM6, 374) +CV_REGISTER(CVRegAMD64_YMM7, 375) +CV_REGISTER(CVRegAMD64_YMM8, 376) +CV_REGISTER(CVRegAMD64_YMM9, 377) +CV_REGISTER(CVRegAMD64_YMM10, 378) +CV_REGISTER(CVRegAMD64_YMM11, 379) +CV_REGISTER(CVRegAMD64_YMM12, 380) +CV_REGISTER(CVRegAMD64_YMM13, 381) +CV_REGISTER(CVRegAMD64_YMM14, 382) +CV_REGISTER(CVRegAMD64_YMM15, 383) diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def index 69ce9606a670..e9a479dba496 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/CodeViewTypes.def @@ -87,6 +87,8 @@ TYPE_RECORD(LF_UDT_MOD_SRC_LINE, 0x1607, UdtModSourceLine) TYPE_RECORD(LF_METHODLIST, 0x1206, MethodOverloadList) +TYPE_RECORD(LF_PRECOMP, 0x1509, Precomp) +TYPE_RECORD(LF_ENDPRECOMP, 0x0014, EndPrecomp) // 16 bit type records. CV_TYPE(LF_MODIFIER_16t, 0x0001) @@ -106,7 +108,6 @@ CV_TYPE(LF_NOTTRAN, 0x0010) CV_TYPE(LF_DIMARRAY_16t, 0x0011) CV_TYPE(LF_VFTPATH_16t, 0x0012) CV_TYPE(LF_PRECOMP_16t, 0x0013) -CV_TYPE(LF_ENDPRECOMP, 0x0014) CV_TYPE(LF_OEM_16t, 0x0015) CV_TYPE(LF_TYPESERVER_ST, 0x0016) @@ -181,7 +182,6 @@ CV_TYPE(LF_MANAGED_ST, 0x140f) CV_TYPE(LF_ST_MAX, 0x1500) CV_TYPE(LF_TYPESERVER, 0x1501) CV_TYPE(LF_DIMARRAY, 0x1508) -CV_TYPE(LF_PRECOMP, 0x1509) CV_TYPE(LF_ALIAS, 0x150a) CV_TYPE(LF_DEFARG, 0x150b) CV_TYPE(LF_FRIENDFCN, 0x150c) diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h index 7f0f10e4fbfa..bebc960223cc 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H #define LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CodeView.h" @@ -66,19 +67,26 @@ public: uint32_t insert(StringRef S); // Return the ID for string S. Assumes S exists in the table. - uint32_t getStringId(StringRef S) const; + uint32_t getIdForString(StringRef S) const; + + StringRef getStringForId(uint32_t Id) const; uint32_t calculateSerializedSize() const override; Error commit(BinaryStreamWriter &Writer) const override; uint32_t size() const; - StringMap<uint32_t>::const_iterator begin() const { return Strings.begin(); } + StringMap<uint32_t>::const_iterator begin() const { + return StringToId.begin(); + } + + StringMap<uint32_t>::const_iterator end() const { return StringToId.end(); } - StringMap<uint32_t>::const_iterator end() const { return Strings.end(); } + std::vector<uint32_t> sortedIds() const; private: - StringMap<uint32_t> Strings; + DenseMap<uint32_t, StringRef> IdToString; + StringMap<uint32_t> StringToId; uint32_t StringSize = 1; }; diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h index d8ac3343c15f..c4704168ed34 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h @@ -69,9 +69,22 @@ public: ArrayRef<ArrayRef<uint8_t>> records() const; ArrayRef<GloballyHashedType> hashes() const; - using CreateRecord = llvm::function_ref<ArrayRef<uint8_t>()>; + template <typename CreateFunc> + TypeIndex insertRecordAs(GloballyHashedType Hash, size_t RecordSize, + CreateFunc Create) { + auto Result = HashedRecords.try_emplace(Hash, nextTypeIndex()); + + if (LLVM_UNLIKELY(Result.second)) { + uint8_t *Stable = RecordStorage.Allocate<uint8_t>(RecordSize); + MutableArrayRef<uint8_t> Data(Stable, RecordSize); + SeenRecords.push_back(Create(Data)); + SeenHashes.push_back(Hash); + } + + // Update the caller's copy of Record to point a stable copy. + return Result.first->second; + } - TypeIndex insertRecordAs(GloballyHashedType Hash, CreateRecord Create); TypeIndex insertRecordBytes(ArrayRef<uint8_t> Data); TypeIndex insertRecord(ContinuationRecordBuilder &Builder); diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h index 16d78692c839..383f7dd9fb6a 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h @@ -26,7 +26,7 @@ namespace llvm { namespace codeview { -/// \brief Provides amortized O(1) random access to a CodeView type stream. +/// Provides amortized O(1) random access to a CodeView type stream. /// Normally to access a type from a type stream, you must know its byte /// offset into the type stream, because type records are variable-lengthed. /// However, this is not the way we prefer to access them. For example, given diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h index 741337533701..1f732d29a538 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeHashing.h @@ -58,7 +58,10 @@ struct LocallyHashedType { } }; -enum class GlobalTypeHashAlg : uint16_t { SHA1 = 0 }; +enum class GlobalTypeHashAlg : uint16_t { + SHA1 = 0, // standard 20-byte SHA1 hash + SHA1_8 // last 8-bytes of standard SHA1 hash +}; /// A globally hashed type represents a hash value that is sufficient to /// uniquely identify a record across multiple type streams or type sequences. @@ -77,10 +80,10 @@ struct GloballyHashedType { GloballyHashedType(StringRef H) : GloballyHashedType(ArrayRef<uint8_t>(H.bytes_begin(), H.bytes_end())) {} GloballyHashedType(ArrayRef<uint8_t> H) { - assert(H.size() == 20); - ::memcpy(Hash.data(), H.data(), 20); + assert(H.size() == 8); + ::memcpy(Hash.data(), H.data(), 8); } - std::array<uint8_t, 20> Hash; + std::array<uint8_t, 8> Hash; /// Given a sequence of bytes representing a record, compute a global hash for /// this record. Due to the nature of global hashes incorporating the hashes diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h index 508bdd395f74..61ebdf878ce7 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -330,6 +330,10 @@ public: return !!(Attrs & uint32_t(PointerOptions::Unaligned)); } + bool isRestrict() const { + return !!(Attrs & uint32_t(PointerOptions::Restrict)); + } + TypeIndex ReferentType; uint32_t Attrs; Optional<MemberPointerInfo> MemberInfo; @@ -892,6 +896,33 @@ public: TypeIndex ContinuationIndex; }; +// LF_PRECOMP +class PrecompRecord : public TypeRecord { +public: + PrecompRecord() = default; + explicit PrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + uint32_t getStartTypeIndex() const { return StartTypeIndex; } + uint32_t getTypesCount() const { return TypesCount; } + uint32_t getSignature() const { return Signature; } + StringRef getPrecompFilePath() const { return PrecompFilePath; } + + uint32_t StartTypeIndex; + uint32_t TypesCount; + uint32_t Signature; + StringRef PrecompFilePath; +}; + +// LF_ENDPRECOMP +class EndPrecompRecord : public TypeRecord { +public: + EndPrecompRecord() = default; + explicit EndPrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} + + uint32_t getSignature() const { return Signature; } + + uint32_t Signature; +}; } // end namespace codeview } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h index 59e216abcb11..583740d2eb4b 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h +++ b/contrib/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h @@ -23,7 +23,7 @@ struct GloballyHashedType; class GlobalTypeTableBuilder; class MergingTypeTableBuilder; -/// \brief Merge one set of type records into another. This method assumes +/// Merge one set of type records into another. This method assumes /// that all records are type records, and there are no Id records present. /// /// \param Dest The table to store the re-written type records into. @@ -40,7 +40,7 @@ Error mergeTypeRecords(MergingTypeTableBuilder &Dest, SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &Types); -/// \brief Merge one set of id records into another. This method assumes +/// Merge one set of id records into another. This method assumes /// that all records are id records, and there are no Type records present. /// However, since Id records can refer back to Type records, this method /// assumes that the referenced type records have also been merged into @@ -65,7 +65,7 @@ Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types, SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &Ids); -/// \brief Merge a unified set of type and id records, splitting them into +/// Merge a unified set of type and id records, splitting them into /// separate output streams. /// /// \param DestIds The table to store the re-written id records into. diff --git a/contrib/llvm/include/llvm/DebugInfo/DIContext.h b/contrib/llvm/include/llvm/DebugInfo/DIContext.h index abace9378607..f89eb34fdd77 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DIContext.h +++ b/contrib/llvm/include/llvm/DebugInfo/DIContext.h @@ -31,6 +31,7 @@ namespace llvm { struct DILineInfo { std::string FileName; std::string FunctionName; + Optional<StringRef> Source; uint32_t Line = 0; uint32_t Column = 0; uint32_t StartLine = 0; @@ -159,6 +160,7 @@ struct DIDumpOptions { bool ShowForm = false; bool SummarizeTypes = false; bool Verbose = false; + bool DisplayRawContents = false; /// Return default option set for printing a single DIE without children. static DIDumpOptions getForSingleDIE() { diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h index 0bade10f6201..1d448728338f 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H #define LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" @@ -20,18 +21,76 @@ namespace llvm { class raw_ostream; +class ScopedPrinter; + +/// The accelerator tables are designed to allow efficient random access +/// (using a symbol name as a key) into debug info by providing an index of the +/// debug info DIEs. This class implements the common functionality of Apple and +/// DWARF 5 accelerator tables. +/// TODO: Generalize the rest of the AppleAcceleratorTable interface and move it +/// to this class. +class DWARFAcceleratorTable { +protected: + DWARFDataExtractor AccelSection; + DataExtractor StringSection; + +public: + /// An abstract class representing a single entry in the accelerator tables. + class Entry { + protected: + SmallVector<DWARFFormValue, 3> Values; + + Entry() = default; + + // Make these protected so only (final) subclasses can be copied around. + Entry(const Entry &) = default; + Entry(Entry &&) = default; + Entry &operator=(const Entry &) = default; + Entry &operator=(Entry &&) = default; + ~Entry() = default; + + + public: + /// Returns the Offset of the Compilation Unit associated with this + /// Accelerator Entry or None if the Compilation Unit offset is not recorded + /// in this Accelerator Entry. + virtual Optional<uint64_t> getCUOffset() const = 0; + + /// Returns the Tag of the Debug Info Entry associated with this + /// Accelerator Entry or None if the Tag is not recorded in this + /// Accelerator Entry. + virtual Optional<dwarf::Tag> getTag() const = 0; + + /// Returns the raw values of fields in the Accelerator Entry. In general, + /// these can only be interpreted with the help of the metadata in the + /// owning Accelerator Table. + ArrayRef<DWARFFormValue> getValues() const { return Values; } + }; + + DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection, + DataExtractor StringSection) + : AccelSection(AccelSection), StringSection(StringSection) {} + virtual ~DWARFAcceleratorTable(); + + virtual llvm::Error extract() = 0; + virtual void dump(raw_ostream &OS) const = 0; + + DWARFAcceleratorTable(const DWARFAcceleratorTable &) = delete; + void operator=(const DWARFAcceleratorTable &) = delete; +}; /// This implements the Apple accelerator table format, a precursor of the /// DWARF 5 accelerator table format. -/// TODO: Factor out a common base class for both formats. -class DWARFAcceleratorTable { +class AppleAcceleratorTable : public DWARFAcceleratorTable { struct Header { uint32_t Magic; uint16_t Version; uint16_t HashFunction; - uint32_t NumBuckets; - uint32_t NumHashes; + uint32_t BucketCount; + uint32_t HashCount; uint32_t HeaderDataLength; + + void dump(ScopedPrinter &W) const; }; struct HeaderData { @@ -40,22 +99,51 @@ class DWARFAcceleratorTable { uint32_t DIEOffsetBase; SmallVector<std::pair<AtomType, Form>, 3> Atoms; + + Optional<uint64_t> extractOffset(Optional<DWARFFormValue> Value) const; }; struct Header Hdr; struct HeaderData HdrData; - DWARFDataExtractor AccelSection; - DataExtractor StringSection; bool IsValid = false; + /// Returns true if we should continue scanning for entries or false if we've + /// reached the last (sentinel) entry of encountered a parsing error. + bool dumpName(ScopedPrinter &W, SmallVectorImpl<DWARFFormValue> &AtomForms, + uint32_t *DataOffset) const; + public: - /// An iterator for the entries associated with one key. Each entry can have - /// multiple DWARFFormValues. - class ValueIterator : public std::iterator<std::input_iterator_tag, - ArrayRef<DWARFFormValue>> { - const DWARFAcceleratorTable *AccelTable = nullptr; - SmallVector<DWARFFormValue, 3> AtomForms; ///< The decoded data entry. + /// Apple-specific implementation of an Accelerator Entry. + class Entry final : public DWARFAcceleratorTable::Entry { + const HeaderData *HdrData = nullptr; + + Entry(const HeaderData &Data); + Entry() = default; + + void extract(const AppleAcceleratorTable &AccelTable, uint32_t *Offset); + + public: + Optional<uint64_t> getCUOffset() const override; + + /// Returns the Section Offset of the Debug Info Entry associated with this + /// Accelerator Entry or None if the DIE offset is not recorded in this + /// Accelerator Entry. The returned offset is relative to the start of the + /// Section containing the DIE. + Optional<uint64_t> getDIESectionOffset() const; + Optional<dwarf::Tag> getTag() const override; + + /// Returns the value of the Atom in this Accelerator Entry, if the Entry + /// contains such Atom. + Optional<DWARFFormValue> lookup(HeaderData::AtomType Atom) const; + + friend class AppleAcceleratorTable; + friend class ValueIterator; + }; + + class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> { + const AppleAcceleratorTable *AccelTable = nullptr; + Entry Current; ///< The current entry. unsigned DataOffset = 0; ///< Offset into the section. unsigned Data = 0; ///< Current data entry. unsigned NumData = 0; ///< Number of data entries. @@ -64,13 +152,11 @@ public: void Next(); public: /// Construct a new iterator for the entries at \p DataOffset. - ValueIterator(const DWARFAcceleratorTable &AccelTable, unsigned DataOffset); + ValueIterator(const AppleAcceleratorTable &AccelTable, unsigned DataOffset); /// End marker. ValueIterator() = default; - const ArrayRef<DWARFFormValue> operator*() const { - return AtomForms; - } + const Entry &operator*() const { return Current; } ValueIterator &operator++() { Next(); return *this; } ValueIterator operator++(int) { ValueIterator I = *this; @@ -85,16 +171,18 @@ public: } }; - - DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection, + AppleAcceleratorTable(const DWARFDataExtractor &AccelSection, DataExtractor StringSection) - : AccelSection(AccelSection), StringSection(StringSection) {} + : DWARFAcceleratorTable(AccelSection, StringSection) {} - llvm::Error extract(); + llvm::Error extract() override; uint32_t getNumBuckets(); uint32_t getNumHashes(); uint32_t getSizeHdr(); uint32_t getHeaderDataLength(); + + /// Return the Atom description, which can be used to interpret the raw values + /// of the Accelerator Entries in this table. ArrayRef<std::pair<HeaderData::AtomType, HeaderData::Form>> getAtomsDesc(); bool validateForms(); @@ -107,10 +195,404 @@ public: /// related to the input hash data offset. /// DieTag is the tag of the DIE std::pair<uint32_t, dwarf::Tag> readAtoms(uint32_t &HashDataOffset); - void dump(raw_ostream &OS) const; + void dump(raw_ostream &OS) const override; + + /// Look up all entries in the accelerator table matching \c Key. + iterator_range<ValueIterator> equal_range(StringRef Key) const; +}; + +/// .debug_names section consists of one or more units. Each unit starts with a +/// header, which is followed by a list of compilation units, local and foreign +/// type units. +/// +/// These may be followed by an (optional) hash lookup table, which consists of +/// an array of buckets and hashes similar to the apple tables above. The only +/// difference is that the hashes array is 1-based, and consequently an empty +/// bucket is denoted by 0 and not UINT32_MAX. +/// +/// Next is the name table, which consists of an array of names and array of +/// entry offsets. This is different from the apple tables, which store names +/// next to the actual entries. +/// +/// The structure of the entries is described by an abbreviations table, which +/// comes after the name table. Unlike the apple tables, which have a uniform +/// entry structure described in the header, each .debug_names entry may have +/// different index attributes (DW_IDX_???) attached to it. +/// +/// The last segment consists of a list of entries, which is a 0-terminated list +/// referenced by the name table and interpreted with the help of the +/// abbreviation table. +class DWARFDebugNames : public DWARFAcceleratorTable { + /// The fixed-size part of a Dwarf 5 Name Index header + struct HeaderPOD { + uint32_t UnitLength; + uint16_t Version; + uint16_t Padding; + uint32_t CompUnitCount; + uint32_t LocalTypeUnitCount; + uint32_t ForeignTypeUnitCount; + uint32_t BucketCount; + uint32_t NameCount; + uint32_t AbbrevTableSize; + uint32_t AugmentationStringSize; + }; + +public: + class NameIndex; + class NameIterator; + class ValueIterator; + + /// Dwarf 5 Name Index header. + struct Header : public HeaderPOD { + SmallString<8> AugmentationString; + + Error extract(const DWARFDataExtractor &AS, uint32_t *Offset); + void dump(ScopedPrinter &W) const; + }; + + /// Index attribute and its encoding. + struct AttributeEncoding { + dwarf::Index Index; + dwarf::Form Form; + + constexpr AttributeEncoding(dwarf::Index Index, dwarf::Form Form) + : Index(Index), Form(Form) {} + + friend bool operator==(const AttributeEncoding &LHS, + const AttributeEncoding &RHS) { + return LHS.Index == RHS.Index && LHS.Form == RHS.Form; + } + }; + + /// Abbreviation describing the encoding of Name Index entries. + struct Abbrev { + uint32_t Code; ///< Abbreviation code + dwarf::Tag Tag; ///< Dwarf Tag of the described entity. + std::vector<AttributeEncoding> Attributes; ///< List of index attributes. + + Abbrev(uint32_t Code, dwarf::Tag Tag, + std::vector<AttributeEncoding> Attributes) + : Code(Code), Tag(Tag), Attributes(std::move(Attributes)) {} + + void dump(ScopedPrinter &W) const; + }; + + /// DWARF v5-specific implementation of an Accelerator Entry. + class Entry final : public DWARFAcceleratorTable::Entry { + const NameIndex *NameIdx; + const Abbrev *Abbr; + + Entry(const NameIndex &NameIdx, const Abbrev &Abbr); + + public: + Optional<uint64_t> getCUOffset() const override; + Optional<dwarf::Tag> getTag() const override { return tag(); } + + /// Returns the Index into the Compilation Unit list of the owning Name + /// Index or None if this Accelerator Entry does not have an associated + /// Compilation Unit. It is up to the user to verify that the returned Index + /// is valid in the owning NameIndex (or use getCUOffset(), which will + /// handle that check itself). Note that entries in NameIndexes which index + /// just a single Compilation Unit are implicitly associated with that unit, + /// so this function will return 0 even without an explicit + /// DW_IDX_compile_unit attribute. + Optional<uint64_t> getCUIndex() const; + + /// .debug_names-specific getter, which always succeeds (DWARF v5 index + /// entries always have a tag). + dwarf::Tag tag() const { return Abbr->Tag; } + + /// Returns the Offset of the DIE within the containing CU or TU. + Optional<uint64_t> getDIEUnitOffset() const; + + /// Return the Abbreviation that can be used to interpret the raw values of + /// this Accelerator Entry. + const Abbrev &getAbbrev() const { return *Abbr; } + + /// Returns the value of the Index Attribute in this Accelerator Entry, if + /// the Entry contains such Attribute. + Optional<DWARFFormValue> lookup(dwarf::Index Index) const; + + void dump(ScopedPrinter &W) const; + + friend class NameIndex; + friend class ValueIterator; + }; + + /// Error returned by NameIndex::getEntry to report it has reached the end of + /// the entry list. + class SentinelError : public ErrorInfo<SentinelError> { + public: + static char ID; + + void log(raw_ostream &OS) const override { OS << "Sentinel"; } + std::error_code convertToErrorCode() const override; + }; + +private: + /// DenseMapInfo for struct Abbrev. + struct AbbrevMapInfo { + static Abbrev getEmptyKey(); + static Abbrev getTombstoneKey(); + static unsigned getHashValue(uint32_t Code) { + return DenseMapInfo<uint32_t>::getHashValue(Code); + } + static unsigned getHashValue(const Abbrev &Abbr) { + return getHashValue(Abbr.Code); + } + static bool isEqual(uint32_t LHS, const Abbrev &RHS) { + return LHS == RHS.Code; + } + static bool isEqual(const Abbrev &LHS, const Abbrev &RHS) { + return LHS.Code == RHS.Code; + } + }; + +public: + /// A single entry in the Name Table (Dwarf 5 sect. 6.1.1.4.6) of the Name + /// Index. + class NameTableEntry { + DataExtractor StrData; + + uint32_t Index; + uint32_t StringOffset; + uint32_t EntryOffset; + + public: + NameTableEntry(const DataExtractor &StrData, uint32_t Index, + uint32_t StringOffset, uint32_t EntryOffset) + : StrData(StrData), Index(Index), StringOffset(StringOffset), + EntryOffset(EntryOffset) {} + + /// Return the index of this name in the parent Name Index. + uint32_t getIndex() const { return Index; } + + /// Returns the offset of the name of the described entities. + uint32_t getStringOffset() const { return StringOffset; } + + /// Return the string referenced by this name table entry or nullptr if the + /// string offset is not valid. + const char *getString() const { + uint32_t Off = StringOffset; + return StrData.getCStr(&Off); + } + + /// Returns the offset of the first Entry in the list. + uint32_t getEntryOffset() const { return EntryOffset; } + }; + + /// Represents a single accelerator table within the Dwarf 5 .debug_names + /// section. + class NameIndex { + DenseSet<Abbrev, AbbrevMapInfo> Abbrevs; + struct Header Hdr; + const DWARFDebugNames &Section; + + // Base of the whole unit and of various important tables, as offsets from + // the start of the section. + uint32_t Base; + uint32_t CUsBase; + uint32_t BucketsBase; + uint32_t HashesBase; + uint32_t StringOffsetsBase; + uint32_t EntryOffsetsBase; + uint32_t EntriesBase; + + void dumpCUs(ScopedPrinter &W) const; + void dumpLocalTUs(ScopedPrinter &W) const; + void dumpForeignTUs(ScopedPrinter &W) const; + void dumpAbbreviations(ScopedPrinter &W) const; + bool dumpEntry(ScopedPrinter &W, uint32_t *Offset) const; + void dumpName(ScopedPrinter &W, const NameTableEntry &NTE, + Optional<uint32_t> Hash) const; + void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const; + + Expected<AttributeEncoding> extractAttributeEncoding(uint32_t *Offset); + + Expected<std::vector<AttributeEncoding>> + extractAttributeEncodings(uint32_t *Offset); + + Expected<Abbrev> extractAbbrev(uint32_t *Offset); + + public: + NameIndex(const DWARFDebugNames &Section, uint32_t Base) + : Section(Section), Base(Base) {} + + /// Reads offset of compilation unit CU. CU is 0-based. + uint32_t getCUOffset(uint32_t CU) const; + uint32_t getCUCount() const { return Hdr.CompUnitCount; } + + /// Reads offset of local type unit TU, TU is 0-based. + uint32_t getLocalTUOffset(uint32_t TU) const; + uint32_t getLocalTUCount() const { return Hdr.LocalTypeUnitCount; } + + /// Reads signature of foreign type unit TU. TU is 0-based. + uint64_t getForeignTUSignature(uint32_t TU) const; + uint32_t getForeignTUCount() const { return Hdr.ForeignTypeUnitCount; } + + /// Reads an entry in the Bucket Array for the given Bucket. The returned + /// value is a (1-based) index into the Names, StringOffsets and + /// EntryOffsets arrays. The input Bucket index is 0-based. + uint32_t getBucketArrayEntry(uint32_t Bucket) const; + uint32_t getBucketCount() const { return Hdr.BucketCount; } + + /// Reads an entry in the Hash Array for the given Index. The input Index + /// is 1-based. + uint32_t getHashArrayEntry(uint32_t Index) const; + + /// Reads an entry in the Name Table for the given Index. The Name Table + /// consists of two arrays -- String Offsets and Entry Offsets. The returned + /// offsets are relative to the starts of respective sections. Input Index + /// is 1-based. + NameTableEntry getNameTableEntry(uint32_t Index) const; + + uint32_t getNameCount() const { return Hdr.NameCount; } + + const DenseSet<Abbrev, AbbrevMapInfo> &getAbbrevs() const { + return Abbrevs; + } + + Expected<Entry> getEntry(uint32_t *Offset) const; + + /// Look up all entries in this Name Index matching \c Key. + iterator_range<ValueIterator> equal_range(StringRef Key) const; + + NameIterator begin() const { return NameIterator(this, 1); } + NameIterator end() const { return NameIterator(this, getNameCount() + 1); } + + llvm::Error extract(); + uint32_t getUnitOffset() const { return Base; } + uint32_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; } + void dump(ScopedPrinter &W) const; + + friend class DWARFDebugNames; + }; + + class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> { + + /// The Name Index we are currently iterating through. The implementation + /// relies on the fact that this can also be used as an iterator into the + /// "NameIndices" vector in the Accelerator section. + const NameIndex *CurrentIndex = nullptr; + + /// Whether this is a local iterator (searches in CurrentIndex only) or not + /// (searches all name indices). + bool IsLocal; + + Optional<Entry> CurrentEntry; + unsigned DataOffset = 0; ///< Offset into the section. + std::string Key; ///< The Key we are searching for. + Optional<uint32_t> Hash; ///< Hash of Key, if it has been computed. + + bool getEntryAtCurrentOffset(); + Optional<uint32_t> findEntryOffsetInCurrentIndex(); + bool findInCurrentIndex(); + void searchFromStartOfCurrentIndex(); + void next(); + + /// Set the iterator to the "end" state. + void setEnd() { *this = ValueIterator(); } + + public: + /// Create a "begin" iterator for looping over all entries in the + /// accelerator table matching Key. The iterator will run through all Name + /// Indexes in the section in sequence. + ValueIterator(const DWARFDebugNames &AccelTable, StringRef Key); + + /// Create a "begin" iterator for looping over all entries in a specific + /// Name Index. Other indices in the section will not be visited. + ValueIterator(const NameIndex &NI, StringRef Key); + + /// End marker. + ValueIterator() = default; + + const Entry &operator*() const { return *CurrentEntry; } + ValueIterator &operator++() { + next(); + return *this; + } + ValueIterator operator++(int) { + ValueIterator I = *this; + next(); + return I; + } + + friend bool operator==(const ValueIterator &A, const ValueIterator &B) { + return A.CurrentIndex == B.CurrentIndex && A.DataOffset == B.DataOffset; + } + friend bool operator!=(const ValueIterator &A, const ValueIterator &B) { + return !(A == B); + } + }; + + class NameIterator { + + /// The Name Index we are iterating through. + const NameIndex *CurrentIndex; + + /// The current name in the Name Index. + uint32_t CurrentName; + + void next() { + assert(CurrentName <= CurrentIndex->getNameCount()); + ++CurrentName; + } + + public: + using iterator_category = std::input_iterator_tag; + using value_type = NameTableEntry; + using difference_type = uint32_t; + using pointer = NameTableEntry *; + using reference = NameTableEntry; // We return entries by value. + + /// Creates an iterator whose initial position is name CurrentName in + /// CurrentIndex. + NameIterator(const NameIndex *CurrentIndex, uint32_t CurrentName) + : CurrentIndex(CurrentIndex), CurrentName(CurrentName) {} + + NameTableEntry operator*() const { + return CurrentIndex->getNameTableEntry(CurrentName); + } + NameIterator &operator++() { + next(); + return *this; + } + NameIterator operator++(int) { + NameIterator I = *this; + next(); + return I; + } + + friend bool operator==(const NameIterator &A, const NameIterator &B) { + return A.CurrentIndex == B.CurrentIndex && A.CurrentName == B.CurrentName; + } + friend bool operator!=(const NameIterator &A, const NameIterator &B) { + return !(A == B); + } + }; + +private: + SmallVector<NameIndex, 0> NameIndices; + DenseMap<uint32_t, const NameIndex *> CUToNameIndex; + +public: + DWARFDebugNames(const DWARFDataExtractor &AccelSection, + DataExtractor StringSection) + : DWARFAcceleratorTable(AccelSection, StringSection) {} + + llvm::Error extract() override; + void dump(raw_ostream &OS) const override; /// Look up all entries in the accelerator table matching \c Key. iterator_range<ValueIterator> equal_range(StringRef Key) const; + + using const_iterator = SmallVector<NameIndex, 0>::const_iterator; + const_iterator begin() const { return NameIndices.begin(); } + const_iterator end() const { return NameIndices.end(); } + + /// Return the Name Index covering the compile unit at CUOffset, or nullptr if + /// there is no Name Index covering that unit. + const NameIndex *getCUNameIndex(uint32_t CUOffset); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h new file mode 100644 index 000000000000..5a7df5c353e8 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h @@ -0,0 +1,68 @@ +//===- DWARFAddressRange.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARF_DWARFADDRESSRANGE_H +#define LLVM_DEBUGINFO_DWARF_DWARFADDRESSRANGE_H + +#include "llvm/DebugInfo/DIContext.h" +#include <cstdint> +#include <tuple> +#include <vector> + +namespace llvm { + +class raw_ostream; + +struct DWARFAddressRange { + uint64_t LowPC; + uint64_t HighPC; + uint64_t SectionIndex; + + DWARFAddressRange() = default; + + /// Used for unit testing. + DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0) + : LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {} + + /// Returns true if LowPC is smaller or equal to HighPC. This accounts for + /// dead-stripped ranges. + bool valid() const { return LowPC <= HighPC; } + + /// Returns true if [LowPC, HighPC) intersects with [RHS.LowPC, RHS.HighPC). + bool intersects(const DWARFAddressRange &RHS) const { + assert(valid() && RHS.valid()); + // Empty ranges can't intersect. + if (LowPC == HighPC || RHS.LowPC == RHS.HighPC) + return false; + return LowPC < RHS.HighPC && RHS.LowPC < HighPC; + } + + /// Returns true if [LowPC, HighPC) fully contains [RHS.LowPC, RHS.HighPC). + bool contains(const DWARFAddressRange &RHS) const { + assert(valid() && RHS.valid()); + return LowPC <= RHS.LowPC && RHS.HighPC <= HighPC; + } + + void dump(raw_ostream &OS, uint32_t AddressSize, + DIDumpOptions DumpOpts = {}) const; +}; + +static inline bool operator<(const DWARFAddressRange &LHS, + const DWARFAddressRange &RHS) { + return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC); +} + +raw_ostream &operator<<(raw_ostream &OS, const DWARFAddressRange &R); + +/// DWARFAddressRangesVector - represents a set of absolute address ranges. +using DWARFAddressRangesVector = std::vector<DWARFAddressRange>; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFADDRESSRANGE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h index a18adf87bf8e..c219ca75e640 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFCompileUnit.h @@ -18,13 +18,13 @@ namespace llvm { class DWARFCompileUnit : public DWARFUnit { public: DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, - bool IsDWO, const DWARFUnitSectionBase &UnitSection, - const DWARFUnitIndex::Entry *Entry) - : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, - UnitSection, Entry) {} + bool IsDWO, const DWARFUnitSectionBase &UnitSection) + : DWARFUnit(Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, + UnitSection) {} // VTable anchor. ~DWARFCompileUnit() override; diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h index 2ddbc4b91ba2..fe7430c9f04c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -34,6 +34,7 @@ #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/Error.h" #include "llvm/Support/Host.h" #include <cstdint> @@ -43,7 +44,6 @@ namespace llvm { -class DataExtractor; class MCRegisterInfo; class MemoryBuffer; class raw_ostream; @@ -69,10 +69,11 @@ class DWARFContext : public DIContext { std::unique_ptr<DWARFDebugFrame> DebugFrame; std::unique_ptr<DWARFDebugFrame> EHFrame; std::unique_ptr<DWARFDebugMacro> Macro; - std::unique_ptr<DWARFAcceleratorTable> AppleNames; - std::unique_ptr<DWARFAcceleratorTable> AppleTypes; - std::unique_ptr<DWARFAcceleratorTable> AppleNamespaces; - std::unique_ptr<DWARFAcceleratorTable> AppleObjC; + std::unique_ptr<DWARFDebugNames> Names; + std::unique_ptr<AppleAcceleratorTable> AppleNames; + std::unique_ptr<AppleAcceleratorTable> AppleTypes; + std::unique_ptr<AppleAcceleratorTable> AppleNamespaces; + std::unique_ptr<AppleAcceleratorTable> AppleObjC; DWARFUnitSection<DWARFCompileUnit> DWOCUs; std::deque<DWARFUnitSection<DWARFTypeUnit>> DWOTUs; @@ -204,6 +205,9 @@ public: DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash); + /// Return the compile unit that includes an offset (relative to .debug_info). + DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); + /// Get a DIE given an exact offset. DWARFDie getDIEForOffset(uint32_t Offset); @@ -243,19 +247,36 @@ public: const DWARFDebugMacro *getDebugMacro(); /// Get a reference to the parsed accelerator table object. - const DWARFAcceleratorTable &getAppleNames(); + const DWARFDebugNames &getDebugNames(); /// Get a reference to the parsed accelerator table object. - const DWARFAcceleratorTable &getAppleTypes(); + const AppleAcceleratorTable &getAppleNames(); /// Get a reference to the parsed accelerator table object. - const DWARFAcceleratorTable &getAppleNamespaces(); + const AppleAcceleratorTable &getAppleTypes(); /// Get a reference to the parsed accelerator table object. - const DWARFAcceleratorTable &getAppleObjC(); + const AppleAcceleratorTable &getAppleNamespaces(); + + /// Get a reference to the parsed accelerator table object. + const AppleAcceleratorTable &getAppleObjC(); + + /// Get a pointer to a parsed line table corresponding to a compile unit. + /// Report any parsing issues as warnings on stderr. + const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U); /// Get a pointer to a parsed line table corresponding to a compile unit. - const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu); + /// Report any recoverable parsing problems using the callback. + Expected<const DWARFDebugLine::LineTable *> + getLineTableForUnit(DWARFUnit *U, + std::function<void(Error)> RecoverableErrorCallback); + + DataExtractor getStringExtractor() const { + return DataExtractor(DObj->getStringSection(), false, 0); + } + DataExtractor getLineStringExtractor() const { + return DataExtractor(DObj->getLineStringSection(), false, 0); + } /// Wraps the returned DIEs for a given address. struct DIEsForAddress { @@ -303,9 +324,6 @@ public: Error loadRegisterInfo(const object::ObjectFile &Obj); private: - /// Return the compile unit that includes an offset (relative to .debug_info). - DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); - /// Return the compile unit which contains instruction with provided /// address. DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h index a379d9c85b38..10e146b70ec7 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -44,6 +44,13 @@ public: uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr) const { return getRelocatedValue(getAddressSize(), Off, SecIx); } + + /// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding. + /// There is a DWARF encoding that uses a PC-relative adjustment. + /// For these values, \p AbsPosOffset is used to fix them, which should + /// reflect the absolute address of this pointer. + Optional<uint64_t> getEncodedPointer(uint32_t *Offset, uint8_t Encoding, + uint64_t AbsPosOffset = 0) const; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h index dfbbb95076e8..ab46fac39f7c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h @@ -43,6 +43,7 @@ public: uint64_t Length; uint64_t getEndAddress() const { return Address + Length; } + void dump(raw_ostream &OS, uint32_t AddressSize) const; }; private: diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h index a711fb295444..ff1c7fb38389 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -10,40 +10,290 @@ #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H -#include "llvm/Support/DataExtractor.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/Support/Error.h" #include <memory> #include <vector> namespace llvm { -class FrameEntry; class raw_ostream; -/// \brief A parsed .debug_frame or .eh_frame section -/// +namespace dwarf { + +/// Represent a sequence of Call Frame Information instructions that, when read +/// in order, construct a table mapping PC to frame state. This can also be +/// referred to as "CFI rules" in DWARF literature to avoid confusion with +/// computer programs in the broader sense, and in this context each instruction +/// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5 +/// manual, "6.4.1 Structure of Call Frame Information". +class CFIProgram { +public: + typedef SmallVector<uint64_t, 2> Operands; + + /// An instruction consists of a DWARF CFI opcode and an optional sequence of + /// operands. If it refers to an expression, then this expression has its own + /// sequence of operations and operands handled separately by DWARFExpression. + struct Instruction { + Instruction(uint8_t Opcode) : Opcode(Opcode) {} + + uint8_t Opcode; + Operands Ops; + // Associated DWARF expression in case this instruction refers to one + Optional<DWARFExpression> Expression; + }; + + using InstrList = std::vector<Instruction>; + using iterator = InstrList::iterator; + using const_iterator = InstrList::const_iterator; + + iterator begin() { return Instructions.begin(); } + const_iterator begin() const { return Instructions.begin(); } + iterator end() { return Instructions.end(); } + const_iterator end() const { return Instructions.end(); } + + unsigned size() const { return (unsigned)Instructions.size(); } + bool empty() const { return Instructions.empty(); } + + CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor) + : CodeAlignmentFactor(CodeAlignmentFactor), + DataAlignmentFactor(DataAlignmentFactor) {} + + /// Parse and store a sequence of CFI instructions from Data, + /// starting at *Offset and ending at EndOffset. *Offset is updated + /// to EndOffset upon successful parsing, or indicates the offset + /// where a problem occurred in case an error is returned. + Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset); + + void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, + unsigned IndentLevel = 1) const; + +private: + std::vector<Instruction> Instructions; + const uint64_t CodeAlignmentFactor; + const int64_t DataAlignmentFactor; + + /// Convenience method to add a new instruction with the given opcode. + void addInstruction(uint8_t Opcode) { + Instructions.push_back(Instruction(Opcode)); + } + + /// Add a new single-operand instruction. + void addInstruction(uint8_t Opcode, uint64_t Operand1) { + Instructions.push_back(Instruction(Opcode)); + Instructions.back().Ops.push_back(Operand1); + } + + /// Add a new instruction that has two operands. + void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { + Instructions.push_back(Instruction(Opcode)); + Instructions.back().Ops.push_back(Operand1); + Instructions.back().Ops.push_back(Operand2); + } + + /// Types of operands to CFI instructions + /// In DWARF, this type is implicitly tied to a CFI instruction opcode and + /// thus this type doesn't need to be explictly written to the file (this is + /// not a DWARF encoding). The relationship of instrs to operand types can + /// be obtained from getOperandTypes() and is only used to simplify + /// instruction printing. + enum OperandType { + OT_Unset, + OT_None, + OT_Address, + OT_Offset, + OT_FactoredCodeOffset, + OT_SignedFactDataOffset, + OT_UnsignedFactDataOffset, + OT_Register, + OT_Expression + }; + + /// Retrieve the array describing the types of operands according to the enum + /// above. This is indexed by opcode. + static ArrayRef<OperandType[2]> getOperandTypes(); + + /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. + void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, + const Instruction &Instr, unsigned OperandIdx, + uint64_t Operand) const; +}; + +/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an +/// FDE. +class FrameEntry { +public: + enum FrameKind { FK_CIE, FK_FDE }; + + FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign, + int64_t DataAlign) + : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign, DataAlign) {} + + virtual ~FrameEntry() {} + + FrameKind getKind() const { return Kind; } + uint64_t getOffset() const { return Offset; } + uint64_t getLength() const { return Length; } + const CFIProgram &cfis() const { return CFIs; } + CFIProgram &cfis() { return CFIs; } + + /// Dump the instructions in this CFI fragment + virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + bool IsEH) const = 0; + +protected: + const FrameKind Kind; + + /// Offset of this entry in the section. + const uint64_t Offset; + + /// Entry length as specified in DWARF. + const uint64_t Length; + + CFIProgram CFIs; +}; + +/// DWARF Common Information Entry (CIE) +class CIE : public FrameEntry { +public: + // CIEs (and FDEs) are simply container classes, so the only sensible way to + // create them is by providing the full parsed contents in the constructor. + CIE(uint64_t Offset, uint64_t Length, uint8_t Version, + SmallString<8> Augmentation, uint8_t AddressSize, + uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, + int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, + SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, + uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality, + Optional<uint32_t> PersonalityEnc) + : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor, + DataAlignmentFactor), + Version(Version), Augmentation(std::move(Augmentation)), + AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize), + CodeAlignmentFactor(CodeAlignmentFactor), + DataAlignmentFactor(DataAlignmentFactor), + ReturnAddressRegister(ReturnAddressRegister), + AugmentationData(std::move(AugmentationData)), + FDEPointerEncoding(FDEPointerEncoding), + LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality), + PersonalityEnc(PersonalityEnc) {} + + static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; } + + StringRef getAugmentationString() const { return Augmentation; } + uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } + int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } + uint8_t getVersion() const { return Version; } + uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; } + Optional<uint64_t> getPersonalityAddress() const { return Personality; } + Optional<uint32_t> getPersonalityEncoding() const { return PersonalityEnc; } + + uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; } + + uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } + + void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + bool IsEH) const override; + +private: + /// The following fields are defined in section 6.4.1 of the DWARF standard v4 + const uint8_t Version; + const SmallString<8> Augmentation; + const uint8_t AddressSize; + const uint8_t SegmentDescriptorSize; + const uint64_t CodeAlignmentFactor; + const int64_t DataAlignmentFactor; + const uint64_t ReturnAddressRegister; + + // The following are used when the CIE represents an EH frame entry. + const SmallString<8> AugmentationData; + const uint32_t FDEPointerEncoding; + const uint32_t LSDAPointerEncoding; + const Optional<uint64_t> Personality; + const Optional<uint32_t> PersonalityEnc; +}; + +/// DWARF Frame Description Entry (FDE) +class FDE : public FrameEntry { +public: + // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with + // an offset to the CIE (provided by parsing the FDE header). The CIE itself + // is obtained lazily once it's actually required. + FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, + uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie, + Optional<uint64_t> LSDAAddress) + : FrameEntry(FK_FDE, Offset, Length, + Cie ? Cie->getCodeAlignmentFactor() : 0, + Cie ? Cie->getDataAlignmentFactor() : 0), + LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation), + AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {} + + ~FDE() override = default; + + const CIE *getLinkedCIE() const { return LinkedCIE; } + uint64_t getInitialLocation() const { return InitialLocation; } + uint64_t getAddressRange() const { return AddressRange; } + Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; } + + void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + bool IsEH) const override; + + static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; } + +private: + /// The following fields are defined in section 6.4.1 of the DWARF standard v3 + const uint64_t LinkedCIEOffset; + const uint64_t InitialLocation; + const uint64_t AddressRange; + const CIE *LinkedCIE; + const Optional<uint64_t> LSDAAddress; +}; + +} // end namespace dwarf + +/// A parsed .debug_frame or .eh_frame section class DWARFDebugFrame { // True if this is parsing an eh_frame section. - bool IsEH; + const bool IsEH; + // Not zero for sane pointer values coming out of eh_frame + const uint64_t EHFrameAddress; + + std::vector<std::unique_ptr<dwarf::FrameEntry>> Entries; + using iterator = pointee_iterator<decltype(Entries)::const_iterator>; + + /// Return the entry at the given offset or nullptr. + dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const; public: - DWARFDebugFrame(bool IsEH); + // If IsEH is true, assume it is a .eh_frame section. Otherwise, + // it is a .debug_frame section. EHFrameAddress should be different + // than zero for correct parsing of .eh_frame addresses when they + // use a PC-relative encoding. + DWARFDebugFrame(bool IsEH = false, uint64_t EHFrameAddress = 0); ~DWARFDebugFrame(); /// Dump the section data into the given stream. - void dump(raw_ostream &OS, Optional<uint64_t> Offset) const; + void dump(raw_ostream &OS, const MCRegisterInfo *MRI, + Optional<uint64_t> Offset) const; - /// \brief Parse the section from raw data. - /// data is assumed to be pointing to the beginning of the section. - void parse(DataExtractor Data); + /// Parse the section from raw data. \p Data is assumed to contain the whole + /// frame section contents to be parsed. + void parse(DWARFDataExtractor Data); /// Return whether the section has any entries. bool empty() const { return Entries.empty(); } - /// Return the entry at the given offset or nullptr. - FrameEntry *getEntryAtOffset(uint64_t Offset) const; + /// DWARF Frame entries accessors + iterator begin() const { return Entries.begin(); } + iterator end() const { return Entries.end(); } + iterator_range<iterator> entries() const { + return iterator_range<iterator>(Entries.begin(), Entries.end()); + } -private: - std::vector<std::unique_ptr<FrameEntry>> Entries; + uint64_t getEHFrameAddress() const { return EHFrameAddress; } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index de8ad4e5ef3c..5b2af34bbcf5 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -10,11 +10,14 @@ #ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H #define LLVM_DEBUGINFO_DWARFDEBUGLINE_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/Support/MD5.h" #include <cstdint> #include <map> @@ -31,11 +34,30 @@ public: struct FileNameEntry { FileNameEntry() = default; - StringRef Name; + DWARFFormValue Name; uint64_t DirIdx = 0; uint64_t ModTime = 0; uint64_t Length = 0; MD5::MD5Result Checksum; + DWARFFormValue Source; + }; + + /// Tracks which optional content types are present in a DWARF file name + /// entry format. + struct ContentTypeTracker { + ContentTypeTracker() = default; + + /// Whether filename entries provide a modification timestamp. + bool HasModTime = false; + /// Whether filename entries provide a file size. + bool HasLength = false; + /// For v5, whether filename entries provide an MD5 checksum. + bool HasMD5 = false; + /// For v5, whether filename entries provide source text. + bool HasSource = false; + + /// Update tracked content types with \p ContentType. + void trackContentType(dwarf::LineNumberEntryFormat ContentType); }; struct Prologue { @@ -47,7 +69,7 @@ public: /// Version, address size (starting in v5), and DWARF32/64 format; these /// parameters affect interpretation of forms (used in the directory and /// file tables starting with v5). - DWARFFormParams FormParams; + dwarf::FormParams FormParams; /// The number of bytes following the prologue_length field to the beginning /// of the first byte of the statement program itself. uint64_t PrologueLength; @@ -68,13 +90,13 @@ public: uint8_t LineRange; /// The number assigned to the first special opcode. uint8_t OpcodeBase; - /// For v5, whether filename entries provide an MD5 checksum. - bool HasMD5; + /// This tracks which optional file format content types are present. + ContentTypeTracker ContentTypes; std::vector<uint8_t> StandardOpcodeLengths; - std::vector<StringRef> IncludeDirectories; + std::vector<DWARFFormValue> IncludeDirectories; std::vector<FileNameEntry> FileNames; - const DWARFFormParams getFormParams() const { return FormParams; } + const dwarf::FormParams getFormParams() const { return FormParams; } uint16_t getVersion() const { return FormParams.Version; } uint8_t getAddressSize() const { return FormParams.AddrSize; } bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; } @@ -83,6 +105,8 @@ public: uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; } + bool totalLengthIsValid() const; + /// Length of the prologue in bytes. uint32_t getLength() const { return PrologueLength + sizeofTotalLength() + sizeof(getVersion()) + @@ -99,9 +123,9 @@ public: } void clear(); - void dump(raw_ostream &OS) const; - bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, - const DWARFUnit *U = nullptr); + void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; + Error parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, + const DWARFContext &Ctx, const DWARFUnit *U = nullptr); }; /// Standard .debug_line state machine structure. @@ -219,12 +243,14 @@ public: DILineInfoSpecifier::FileLineInfoKind Kind, DILineInfo &Result) const; - void dump(raw_ostream &OS) const; + void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const; void clear(); /// Parse prologue and all rows. - bool parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, - const DWARFUnit *U, raw_ostream *OS = nullptr); + Error parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, + const DWARFContext &Ctx, const DWARFUnit *U, + std::function<void(Error)> RecoverableErrorCallback = warn, + raw_ostream *OS = nullptr); using RowVector = std::vector<Row>; using RowIter = RowVector::const_iterator; @@ -238,11 +264,75 @@ public: private: uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq, uint64_t Address) const; + Optional<StringRef> + getSourceByIndex(uint64_t FileIndex, + DILineInfoSpecifier::FileLineInfoKind Kind) const; }; const LineTable *getLineTable(uint32_t Offset) const; - const LineTable *getOrParseLineTable(DWARFDataExtractor &DebugLineData, - uint32_t Offset, const DWARFUnit *U); + Expected<const LineTable *> getOrParseLineTable( + DWARFDataExtractor &DebugLineData, uint32_t Offset, + const DWARFContext &Ctx, const DWARFUnit *U, + std::function<void(Error)> RecoverableErrorCallback = warn); + + /// Helper to allow for parsing of an entire .debug_line section in sequence. + class SectionParser { + public: + using cu_range = DWARFUnitSection<DWARFCompileUnit>::iterator_range; + using tu_range = + iterator_range<std::deque<DWARFUnitSection<DWARFTypeUnit>>::iterator>; + using LineToUnitMap = std::map<uint64_t, DWARFUnit *>; + + SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, cu_range CUs, + tu_range TUs); + + /// Get the next line table from the section. Report any issues via the + /// callbacks. + /// + /// \param RecoverableErrorCallback - any issues that don't prevent further + /// parsing of the table will be reported through this callback. + /// \param UnrecoverableErrorCallback - any issues that prevent further + /// parsing of the table will be reported through this callback. + /// \param OS - if not null, the parser will print information about the + /// table as it parses it. + LineTable + parseNext(function_ref<void(Error)> RecoverableErrorCallback = warn, + function_ref<void(Error)> UnrecoverableErrorCallback = warn, + raw_ostream *OS = nullptr); + + /// Skip the current line table and go to the following line table (if + /// present) immediately. + /// + /// \param ErrorCallback - report any prologue parsing issues via this + /// callback. + void skip(function_ref<void(Error)> ErrorCallback = warn); + + /// Indicates if the parser has parsed as much as possible. + /// + /// \note Certain problems with the line table structure might mean that + /// parsing stops before the end of the section is reached. + bool done() const { return Done; } + + /// Get the offset the parser has reached. + uint32_t getOffset() const { return Offset; } + + private: + DWARFUnit *prepareToParse(uint32_t Offset); + void moveToNextTable(uint32_t OldOffset, const Prologue &P); + + LineToUnitMap LineToUnit; + + DWARFDataExtractor &DebugLineData; + const DWARFContext &Context; + uint32_t Offset = 0; + bool Done = false; + }; + + /// Helper function for DWARFDebugLine parse functions, to report issues + /// identified during parsing. + /// + /// \param Err The Error to report. + static void warn(Error Err); private: struct ParsingState { diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h index a6d319a90457..9a73745fb6b4 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h @@ -42,7 +42,8 @@ public: SmallVector<Entry, 2> Entries; /// Dump this list on OS. void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize, - const MCRegisterInfo *MRI, unsigned Indent) const; + const MCRegisterInfo *MRI, uint64_t BaseAddress, + unsigned Indent) const; }; private: diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h index 761871dc6255..cae4804e61d3 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h @@ -32,7 +32,7 @@ public: /// The name of the object as given by the DW_AT_name attribute of the /// referenced DIE. - const char *Name; + StringRef Name; }; /// Each table consists of sets of variable length entries. Each set describes diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h index f9ec96366a53..ce7436d9faa3 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h @@ -10,8 +10,8 @@ #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGRANGELIST_H +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" -#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include <cassert> #include <cstdint> #include <vector> @@ -21,47 +21,6 @@ namespace llvm { struct BaseAddress; class raw_ostream; -struct DWARFAddressRange { - uint64_t LowPC; - uint64_t HighPC; - uint64_t SectionIndex; - - DWARFAddressRange() = default; - - /// Used for unit testing. - DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0) - : LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {} - - /// Returns true if LowPC is smaller or equal to HighPC. This accounts for - /// dead-stripped ranges. - bool valid() const { return LowPC <= HighPC; } - - /// Returns true if [LowPC, HighPC) intersects with [RHS.LowPC, RHS.HighPC). - bool intersects(const DWARFAddressRange &RHS) const { - // Empty ranges can't intersect. - if (LowPC == HighPC || RHS.LowPC == RHS.HighPC) - return false; - return (LowPC < RHS.HighPC) && (HighPC > RHS.LowPC); - } - - /// Returns true if [LowPC, HighPC) fully contains [RHS.LowPC, RHS.HighPC). - bool contains(const DWARFAddressRange &RHS) const { - if (LowPC <= RHS.LowPC && RHS.LowPC <= HighPC) - return LowPC <= RHS.HighPC && RHS.HighPC <= HighPC; - return false; - } -}; - -static inline bool operator<(const DWARFAddressRange &LHS, - const DWARFAddressRange &RHS) { - return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC); -} - -raw_ostream &operator<<(raw_ostream &OS, const DWARFAddressRange &R); - -/// DWARFAddressRangesVector - represents a set of absolute address ranges. -using DWARFAddressRangesVector = std::vector<DWARFAddressRange>; - class DWARFDebugRangeList { public: struct RangeListEntry { @@ -112,7 +71,7 @@ public: void clear(); void dump(raw_ostream &OS) const; - bool extract(const DWARFDataExtractor &data, uint32_t *offset_ptr); + Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr); const std::vector<RangeListEntry> &getEntries() { return Entries; } /// getAbsoluteRanges - Returns absolute address ranges defined by this range diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h new file mode 100644 index 000000000000..e2e8ab5ed219 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h @@ -0,0 +1,60 @@ +//===- DWARFDebugRnglists.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H +#define LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H + +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFListTable.h" +#include <cstdint> +#include <map> +#include <vector> + +namespace llvm { + +class Error; +class raw_ostream; + +/// A class representing a single range list entry. +struct RangeListEntry : public DWARFListEntryBase { + /// The values making up the range list entry. Most represent a range with + /// a start and end address or a start address and a length. Others are + /// single value base addresses or end-of-list with no values. The unneeded + /// values are semantically undefined, but initialized to 0. + uint64_t Value0; + uint64_t Value1; + + Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr); + void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, + uint64_t &CurrentBase, DIDumpOptions DumpOpts) const; + bool isSentinel() const { return EntryKind == dwarf::DW_RLE_end_of_list; } +}; + +/// A class representing a single rangelist. +class DWARFDebugRnglist : public DWARFListType<RangeListEntry> { +public: + /// Build a DWARFAddressRangesVector from a rangelist. + DWARFAddressRangesVector + getAbsoluteRanges(llvm::Optional<BaseAddress> BaseAddr) const; +}; + +class DWARFDebugRnglistTable : public DWARFListTableBase<DWARFDebugRnglist> { +public: + DWARFDebugRnglistTable() + : DWARFListTableBase(/* SectionName = */ ".debug_rnglists", + /* HeaderString = */ "ranges:", + /* ListTypeString = */ "range") {} +}; + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGRNGLISTS_H diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h index 75fc5995c5b2..6e6b57cbcbd4 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -16,9 +16,9 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFAttribute.h" #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include <cassert> #include <cstdint> #include <iterator> @@ -104,12 +104,24 @@ public: /// invalid DWARFDie instance if it doesn't. DWARFDie getSibling() const; + /// Get the previous sibling of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has a sibling or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getPreviousSibling() const; + /// Get the first child of this DIE object. /// /// \returns a valid DWARFDie instance if this object has children or an /// invalid DWARFDie instance if it doesn't. DWARFDie getFirstChild() const; + /// Get the last child of this DIE object. + /// + /// \returns a valid null DWARFDie instance if this object has children or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getLastChild() const; + /// Dump the DIE and all of its attributes to the supplied stream. /// /// \param OS the stream to use for output. @@ -207,7 +219,7 @@ public: /// /// \returns a address range vector that might be empty if no address range /// information is available. - DWARFAddressRangesVector getAddressRanges() const; + Expected<DWARFAddressRangesVector> getAddressRanges() const; /// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any /// of its children. @@ -288,6 +300,7 @@ public: explicit attribute_iterator(DWARFDie D, bool End); attribute_iterator &operator++(); + attribute_iterator &operator--(); explicit operator bool() const { return AttrValue.isValid(); } const DWARFAttribute &operator*() const { return AttrValue; } bool operator==(const attribute_iterator &X) const { return Index == X.Index; } @@ -306,26 +319,23 @@ inline bool operator<(const DWARFDie &LHS, const DWARFDie &RHS) { return LHS.getOffset() < RHS.getOffset(); } -class DWARFDie::iterator : public iterator_facade_base<iterator, - std::forward_iterator_tag, - const DWARFDie> { +class DWARFDie::iterator + : public iterator_facade_base<iterator, std::bidirectional_iterator_tag, + const DWARFDie> { DWARFDie Die; - void skipNull() { - if (Die && Die.isNULL()) - Die = DWARFDie(); - } public: iterator() = default; explicit iterator(DWARFDie D) : Die(D) { - // If we start out with only a Null DIE then invalidate. - skipNull(); } iterator &operator++() { Die = Die.getSibling(); - // Don't include the NULL die when iterating. - skipNull(); + return *this; + } + + iterator &operator--() { + Die = Die.getPreviousSibling(); return *this; } @@ -341,7 +351,7 @@ inline DWARFDie::iterator DWARFDie::begin() const { } inline DWARFDie::iterator DWARFDie::end() const { - return iterator(); + return iterator(getLastChild()); } inline iterator_range<DWARFDie::iterator> DWARFDie::children() const { diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h index dcd486f3fb13..3fad68a9b48b 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -93,12 +93,13 @@ public: /// An iterator to go through the expression operations. class iterator - : public iterator_facade_base<iterator, std::forward_iterator_tag, Operation> { + : public iterator_facade_base<iterator, std::forward_iterator_tag, + Operation> { friend class DWARFExpression; - DWARFExpression *Expr; + const DWARFExpression *Expr; uint32_t Offset; Operation Op; - iterator(DWARFExpression *Expr, uint32_t Offset) + iterator(const DWARFExpression *Expr, uint32_t Offset) : Expr(Expr), Offset(Offset) { Op.Error = Offset >= Expr->Data.getData().size() || @@ -127,10 +128,11 @@ public: assert(AddressSize == 8 || AddressSize == 4); } - iterator begin() { return iterator(this, 0); } - iterator end() { return iterator(this, Data.getData().size()); } + iterator begin() const { return iterator(this, 0); } + iterator end() const { return iterator(this, Data.getData().size()); } - void print(raw_ostream &OS, const MCRegisterInfo *RegInfo); + void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, + bool IsEH = false) const; private: DataExtractor Data; diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index d32053519ec4..1b5f71c946f9 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -20,38 +20,10 @@ namespace llvm { +class DWARFContext; class DWARFUnit; class raw_ostream; -/// A helper struct for DWARFFormValue methods, providing information that -/// allows it to know the byte size of DW_FORM values that vary in size -/// depending on the DWARF version, address byte size, or DWARF32/DWARF64. -struct DWARFFormParams { - uint16_t Version; - uint8_t AddrSize; - dwarf::DwarfFormat Format; - - /// The definition of the size of form DW_FORM_ref_addr depends on the - /// version. In DWARF v2 it's the size of an address; after that, it's the - /// size of a reference. - uint8_t getRefAddrByteSize() const { - if (Version == 2) - return AddrSize; - return getDwarfOffsetByteSize(); - } - - /// The size of a reference is determined by the DWARF 32/64-bit format. - uint8_t getDwarfOffsetByteSize() const { - switch (Format) { - case dwarf::DwarfFormat::DWARF32: - return 4; - case dwarf::DwarfFormat::DWARF64: - return 8; - } - llvm_unreachable("Invalid Format value"); - } -}; - class DWARFFormValue { public: enum FormClass { @@ -83,7 +55,7 @@ private: dwarf::Form Form; /// Form for this value. ValueType Value; /// Contains all data for the form. const DWARFUnit *U = nullptr; /// Remember the DWARFUnit at extract time. - + const DWARFContext *C = nullptr; /// Context for extract time. public: DWARFFormValue(dwarf::Form F = dwarf::Form(0)) : Form(F) {} @@ -106,10 +78,17 @@ public: /// Extracts a value in \p Data at offset \p *OffsetPtr. The information /// in \p FormParams is needed to interpret some forms. The optional - /// \p Unit allows extracting information if the form refers to other - /// sections (e.g., .debug_str). + /// \p Context and \p Unit allows extracting information if the form refers + /// to other sections (e.g., .debug_str). bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, - DWARFFormParams FormParams, const DWARFUnit *U = nullptr); + dwarf::FormParams FormParams, + const DWARFContext *Context = nullptr, + const DWARFUnit *Unit = nullptr); + + bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr, + dwarf::FormParams FormParams, const DWARFUnit *U) { + return extractValue(Data, OffsetPtr, FormParams, nullptr, U); + } bool isInlinedCStr() const { return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr; @@ -127,19 +106,6 @@ public: Optional<uint64_t> getAsCStringOffset() const; Optional<uint64_t> getAsReferenceUVal() const; - /// Get the fixed byte size for a given form. - /// - /// If the form has a fixed byte size, then an Optional with a value will be - /// returned. If the form is always encoded using a variable length storage - /// format (ULEB or SLEB numbers or blocks) then None will be returned. - /// - /// \param Form DWARF form to get the fixed byte size for. - /// \param FormParams DWARF parameters to help interpret forms. - /// \returns Optional<uint8_t> value with the fixed byte size or None if - /// \p Form doesn't have a fixed byte size. - static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, - const DWARFFormParams FormParams); - /// Skip a form's value in \p DebugInfoData at the offset specified by /// \p OffsetPtr. /// @@ -150,7 +116,7 @@ public: /// \param Params DWARF parameters to help interpret forms. /// \returns true on success, false if the form was not skipped. bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr, - const DWARFFormParams Params) const { + const dwarf::FormParams Params) const { return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params); } @@ -165,7 +131,8 @@ public: /// \param FormParams DWARF parameters to help interpret forms. /// \returns true on success, false if the form was not skipped. static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData, - uint32_t *OffsetPtr, const DWARFFormParams FormParams); + uint32_t *OffsetPtr, + const dwarf::FormParams FormParams); private: void dumpString(raw_ostream &OS) const; diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h new file mode 100644 index 000000000000..ab12f3bc08b0 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFListTable.h @@ -0,0 +1,278 @@ +//===- DWARFListTable.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFLISTTABLE_H +#define LLVM_DEBUGINFO_DWARFLISTTABLE_H + +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdint> +#include <map> +#include <vector> + +namespace llvm { + +/// A base class for DWARF list entries, such as range or location list +/// entries. +struct DWARFListEntryBase { + /// The offset at which the entry is located in the section. + uint32_t Offset; + /// The DWARF encoding (DW_RLE_* or DW_LLE_*). + uint8_t EntryKind; + /// The index of the section this entry belongs to. + uint64_t SectionIndex; +}; + +/// A base class for lists of entries that are extracted from a particular +/// section, such as range lists or location lists. +template <typename ListEntryType> class DWARFListType { + using EntryType = ListEntryType; + using ListEntries = std::vector<EntryType>; + +protected: + ListEntries Entries; + +public: + // FIXME: We need to consolidate the various verions of "createError" + // that are used in the DWARF consumer. Until then, this is a workaround. + Error createError(const char *, const char *, uint32_t); + + const ListEntries &getEntries() const { return Entries; } + bool empty() const { return Entries.empty(); } + void clear() { Entries.clear(); } + Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End, + uint32_t *OffsetPtr, StringRef SectionName, + StringRef ListStringName); +}; + +/// A class representing the header of a list table such as the range list +/// table in the .debug_rnglists section. +class DWARFListTableHeader { + struct Header { + /// The total length of the entries for this table, not including the length + /// field itself. + uint32_t Length = 0; + /// The DWARF version number. + uint16_t Version; + /// The size in bytes of an address on the target architecture. For + /// segmented addressing, this is the size of the offset portion of the + /// address. + uint8_t AddrSize; + /// The size in bytes of a segment selector on the target architecture. + /// If the target system uses a flat address space, this value is 0. + uint8_t SegSize; + /// The number of offsets that follow the header before the range lists. + uint32_t OffsetEntryCount; + }; + + Header HeaderData; + /// The offset table, which contains offsets to the individual list entries. + /// It is used by forms such as DW_FORM_rnglistx. + /// FIXME: Generate the table and use the appropriate forms. + std::vector<uint32_t> Offsets; + /// The table's format, either DWARF32 or DWARF64. + dwarf::DwarfFormat Format; + /// The offset at which the header (and hence the table) is located within + /// its section. + uint32_t HeaderOffset; + /// The name of the section the list is located in. + StringRef SectionName; + /// A characterization of the list for dumping purposes, e.g. "range" or + /// "location". + StringRef ListTypeString; + +public: + DWARFListTableHeader(StringRef SectionName, StringRef ListTypeString) + : SectionName(SectionName), ListTypeString(ListTypeString) {} + + void clear() { + HeaderData = {}; + Offsets.clear(); + } + uint32_t getHeaderOffset() const { return HeaderOffset; } + uint8_t getAddrSize() const { return HeaderData.AddrSize; } + uint32_t getLength() const { return HeaderData.Length; } + StringRef getSectionName() const { return SectionName; } + StringRef getListTypeString() const { return ListTypeString; } + dwarf::DwarfFormat getFormat() const { return Format; } + + void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; + Optional<uint32_t> getOffsetEntry(uint32_t Index) const { + if (Index < Offsets.size()) + return Offsets[Index]; + return None; + } + + /// Extract the table header and the array of offsets. + Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr); + + /// Returns the length of the table, including the length field, or 0 if the + /// length has not been determined (e.g. because the table has not yet been + /// parsed, or there was a problem in parsing). + uint32_t length() const; +}; + +/// A class representing a table of lists as specified in the DWARF v5 +/// standard for location lists and range lists. The table consists of a header +/// followed by an array of offsets into a DWARF section, followed by zero or +/// more list entries. The list entries are kept in a map where the keys are +/// the lists' section offsets. +template <typename DWARFListType> class DWARFListTableBase { + DWARFListTableHeader Header; + /// A mapping between file offsets and lists. It is used to find a particular + /// list based on an offset (obtained from DW_AT_ranges, for example). + std::map<uint32_t, DWARFListType> ListMap; + /// This string is displayed as a heading before the list is dumped + /// (e.g. "ranges:"). + StringRef HeaderString; + +protected: + DWARFListTableBase(StringRef SectionName, StringRef HeaderString, + StringRef ListTypeString) + : Header(SectionName, ListTypeString), HeaderString(HeaderString) {} + +public: + void clear() { + Header.clear(); + ListMap.clear(); + } + /// Extract the table header and the array of offsets. + Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) { + return Header.extract(Data, OffsetPtr); + } + /// Extract an entire table, including all list entries. + Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr); + /// Look up a list based on a given offset. Extract it and enter it into the + /// list map if necessary. + Expected<DWARFListType> findList(DWARFDataExtractor Data, uint32_t Offset); + + uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); } + uint8_t getAddrSize() const { return Header.getAddrSize(); } + + void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const; + + /// Return the contents of the offset entry designated by a given index. + Optional<uint32_t> getOffsetEntry(uint32_t Index) const { + return Header.getOffsetEntry(Index); + } + /// Return the size of the table header including the length but not including + /// the offsets. This is dependent on the table format, which is unambiguously + /// derived from parsing the table. + uint8_t getHeaderSize() const { + switch (Header.getFormat()) { + case dwarf::DwarfFormat::DWARF32: + return 12; + case dwarf::DwarfFormat::DWARF64: + return 20; + } + llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64"); + } + + uint32_t length() { return Header.length(); } +}; + +template <typename DWARFListType> +Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data, + uint32_t *OffsetPtr) { + clear(); + if (Error E = extractHeaderAndOffsets(Data, OffsetPtr)) + return E; + + Data.setAddressSize(Header.getAddrSize()); + uint32_t End = getHeaderOffset() + Header.length(); + while (*OffsetPtr < End) { + DWARFListType CurrentList; + uint32_t Off = *OffsetPtr; + if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr, + Header.getSectionName(), + Header.getListTypeString())) + return E; + ListMap[Off] = CurrentList; + } + + assert(*OffsetPtr == End && + "mismatch between expected length of table and length " + "of extracted data"); + return Error::success(); +} + +template <typename ListEntryType> +Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data, + uint32_t HeaderOffset, uint32_t End, + uint32_t *OffsetPtr, + StringRef SectionName, + StringRef ListTypeString) { + if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End) + return createError("invalid %s list offset 0x%" PRIx32, + ListTypeString.data(), *OffsetPtr); + Entries.clear(); + while (*OffsetPtr < End) { + ListEntryType Entry; + if (Error E = Entry.extract(Data, End, OffsetPtr)) + return E; + Entries.push_back(Entry); + if (Entry.isSentinel()) + return Error::success(); + } + return createError("no end of list marker detected at end of %s table " + "starting at offset 0x%" PRIx32, + SectionName.data(), HeaderOffset); +} + +template <typename DWARFListType> +void DWARFListTableBase<DWARFListType>::dump(raw_ostream &OS, + DIDumpOptions DumpOpts) const { + Header.dump(OS, DumpOpts); + OS << HeaderString << "\n"; + + // Determine the length of the longest encoding string we have in the table, + // so we can align the output properly. We only need this in verbose mode. + size_t MaxEncodingStringLength = 0; + if (DumpOpts.Verbose) { + for (const auto &List : ListMap) + for (const auto &Entry : List.second.getEntries()) + MaxEncodingStringLength = + std::max(MaxEncodingStringLength, + dwarf::RangeListEncodingString(Entry.EntryKind).size()); + } + + uint64_t CurrentBase = 0; + for (const auto &List : ListMap) + for (const auto &Entry : List.second.getEntries()) + Entry.dump(OS, getAddrSize(), MaxEncodingStringLength, CurrentBase, + DumpOpts); +} + +template <typename DWARFListType> +Expected<DWARFListType> +DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data, + uint32_t Offset) { + auto Entry = ListMap.find(Offset); + if (Entry != ListMap.end()) + return Entry->second; + + // Extract the list from the section and enter it into the list map. + DWARFListType List; + uint32_t End = getHeaderOffset() + Header.length(); + uint32_t StartingOffset = Offset; + if (Error E = + List.extract(Data, getHeaderOffset(), End, &Offset, + Header.getSectionName(), Header.getListTypeString())) + return std::move(E); + ListMap[StartingOffset] = List; + return List; +} + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFLISTTABLE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h index 167eb2da5ba0..6e8f370f4aea 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFObject.h @@ -42,8 +42,10 @@ public: virtual StringRef getDebugFrameSection() const { return ""; } virtual StringRef getEHFrameSection() const { return ""; } virtual const DWARFSection &getLineSection() const { return Dummy; } + virtual StringRef getLineStringSection() const { return ""; } virtual StringRef getStringSection() const { return ""; } virtual const DWARFSection &getRangeSection() const { return Dummy; } + virtual const DWARFSection &getRnglistsSection() const { return Dummy; } virtual StringRef getMacinfoSection() const { return ""; } virtual StringRef getPubNamesSection() const { return ""; } virtual StringRef getPubTypesSection() const { return ""; } @@ -61,12 +63,14 @@ public: return Dummy; } virtual const DWARFSection &getRangeDWOSection() const { return Dummy; } + virtual const DWARFSection &getRnglistsDWOSection() const { return Dummy; } virtual const DWARFSection &getAddrSection() const { return Dummy; } virtual const DWARFSection &getAppleNamesSection() const { return Dummy; } virtual const DWARFSection &getAppleTypesSection() const { return Dummy; } virtual const DWARFSection &getAppleNamespacesSection() const { return Dummy; } + virtual const DWARFSection &getDebugNamesSection() const { return Dummy; } virtual const DWARFSection &getAppleObjCSection() const { return Dummy; } virtual StringRef getCUIndexSection() const { return ""; } virtual StringRef getGdbIndexSection() const { return ""; } diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h index a7842454f435..cb5a78ee3dbf 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h @@ -24,29 +24,21 @@ struct DWARFSection; class raw_ostream; class DWARFTypeUnit : public DWARFUnit { -private: - uint64_t TypeHash; - uint32_t TypeOffset; - public: DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, - const DWARFUnitSectionBase &UnitSection, - const DWARFUnitIndex::Entry *Entry) - : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, - UnitSection, Entry) {} + const DWARFUnitSectionBase &UnitSection) + : DWARFUnit(Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, + UnitSection) {} - uint32_t getHeaderSize() const override { - return DWARFUnit::getHeaderSize() + 12; - } + uint64_t getTypeHash() const { return getHeader().getTypeHash(); } + uint32_t getTypeOffset() const { return getHeader().getTypeOffset(); } void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}); static const DWARFSectionKind Section = DW_SECT_TYPES; - -protected: - bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 3cec58383f87..988a7958184c 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -18,6 +18,7 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" @@ -40,6 +41,66 @@ class DWARFContext; class DWARFDebugAbbrev; class DWARFUnit; +/// Base class describing the header of any kind of "unit." Some information +/// is specific to certain unit types. We separate this class out so we can +/// parse the header before deciding what specific kind of unit to construct. +class DWARFUnitHeader { + // Offset within section. + uint32_t Offset = 0; + // Version, address size, and DWARF format. + dwarf::FormParams FormParams; + uint32_t Length = 0; + uint64_t AbbrOffset = 0; + + // For DWO units only. + const DWARFUnitIndex::Entry *IndexEntry = nullptr; + + // For type units only. + uint64_t TypeHash = 0; + uint32_t TypeOffset = 0; + + // For v5 split or skeleton compile units only. + Optional<uint64_t> DWOId; + + // Unit type as parsed, or derived from the section kind. + uint8_t UnitType = 0; + + // Size as parsed. uint8_t for compactness. + uint8_t Size = 0; + +public: + /// Parse a unit header from \p debug_info starting at \p offset_ptr. + bool extract(DWARFContext &Context, const DWARFDataExtractor &debug_info, + uint32_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO, + const DWARFUnitIndex *Index = nullptr); + uint32_t getOffset() const { return Offset; } + const dwarf::FormParams &getFormParams() const { return FormParams; } + uint16_t getVersion() const { return FormParams.Version; } + dwarf::DwarfFormat getFormat() const { return FormParams.Format; } + uint8_t getAddressByteSize() const { return FormParams.AddrSize; } + uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); } + uint8_t getDwarfOffsetByteSize() const { + return FormParams.getDwarfOffsetByteSize(); + } + uint32_t getLength() const { return Length; } + uint64_t getAbbrOffset() const { return AbbrOffset; } + Optional<uint64_t> getDWOId() const { return DWOId; } + void setDWOId(uint64_t Id) { + assert((!DWOId || *DWOId == Id) && "setting DWOId to a different value"); + DWOId = Id; + } + const DWARFUnitIndex::Entry *getIndexEntry() const { return IndexEntry; } + uint64_t getTypeHash() const { return TypeHash; } + uint32_t getTypeOffset() const { return TypeOffset; } + uint8_t getUnitType() const { return UnitType; } + bool isTypeUnit() const { + return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type; + } + uint8_t getSize() const { return Size; } + // FIXME: Support DWARF64. + uint32_t getNextUnitOffset() const { return Offset + Length + 4; } +}; + /// Base class for all DWARFUnitSection classes. This provides the /// functionality common to all unit types. class DWARFUnitSectionBase { @@ -56,7 +117,8 @@ public: protected: ~DWARFUnitSectionBase() = default; - virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section, + virtual void parseImpl(DWARFContext &Context, const DWARFObject &Obj, + const DWARFSection &Section, const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, @@ -116,14 +178,14 @@ public: } private: - void parseImpl(DWARFContext &Context, const DWARFSection &Section, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, - StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, - const DWARFSection &LS, bool LE, bool IsDWO, - bool Lazy) override { + void parseImpl(DWARFContext &Context, const DWARFObject &Obj, + const DWARFSection &Section, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, StringRef SS, const DWARFSection &SOS, + const DWARFSection *AOS, const DWARFSection &LS, bool LE, + bool IsDWO, bool Lazy) override { if (Parsed) return; - DataExtractor Data(Section.Data, LE, 0); + DWARFDataExtractor Data(Obj, Section, LE, 0); if (!Parser) { const DWARFUnitIndex *Index = nullptr; if (IsDWO) @@ -132,11 +194,12 @@ private: &LS](uint32_t Offset) -> std::unique_ptr<UnitType> { if (!Data.isValidOffset(Offset)) return nullptr; - auto U = llvm::make_unique<UnitType>( - Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, *this, - Index ? Index->getFromOffset(Offset) : nullptr); - if (!U->extract(Data, &Offset)) + DWARFUnitHeader Header; + if (!Header.extract(Context, Data, &Offset, UnitType::Section, Index)) return nullptr; + auto U = llvm::make_unique<UnitType>( + Context, Section, Header, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, + *this); return U; }; } @@ -168,9 +231,10 @@ struct BaseAddress { /// Represents a unit's contribution to the string offsets table. struct StrOffsetsContributionDescriptor { uint64_t Base = 0; + /// The contribution size not including the header. uint64_t Size = 0; /// Format and version. - DWARFFormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32}; + dwarf::FormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32}; StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size, uint8_t Version, dwarf::DwarfFormat Format) @@ -193,6 +257,7 @@ class DWARFUnit { /// Section containing this DWARFUnit. const DWARFSection &InfoSection; + DWARFUnitHeader Header; const DWARFDebugAbbrev *Abbrev; const DWARFSection *RangeSection; uint32_t RangeSectionBase; @@ -205,63 +270,28 @@ class DWARFUnit { bool isDWO; const DWARFUnitSectionBase &UnitSection; - // Version, address size, and DWARF format. - DWARFFormParams FormParams; /// Start, length, and DWARF format of the unit's contribution to the string /// offsets table (DWARF v5). Optional<StrOffsetsContributionDescriptor> StringOffsetsTableContribution; - uint32_t Offset; - uint32_t Length; + /// A table of range lists (DWARF v5 and later). + Optional<DWARFDebugRnglistTable> RngListTable; + mutable const DWARFAbbreviationDeclarationSet *Abbrevs; - uint64_t AbbrOffset; - uint8_t UnitType; llvm::Optional<BaseAddress> BaseAddr; /// The compile unit debug information entry items. std::vector<DWARFDebugInfoEntry> DieArray; - /// The vector of inlined subroutine DIEs that we can map directly to from - /// their subprogram below. - std::vector<DWARFDie> InlinedSubroutineDIEs; - - /// A type representing a subprogram DIE and a map (built using a sorted - /// vector) into that subprogram's inlined subroutine DIEs. - struct SubprogramDIEAddrInfo { - DWARFDie SubprogramDIE; - - uint64_t SubprogramBasePC; - - /// A vector sorted to allow mapping from a relative PC to the inlined - /// subroutine DIE with the most specific address range covering that PC. - /// - /// The PCs are relative to the `SubprogramBasePC`. - /// - /// The vector is sorted in ascending order of the first int which - /// represents the relative PC for an interval in the map. The second int - /// represents the index into the `InlinedSubroutineDIEs` vector of the DIE - /// that interval maps to. An index of '-1` indicates an empty mapping. The - /// interval covered is from the `.first` relative PC to the next entry's - /// `.first` relative PC. - std::vector<std::pair<uint32_t, int32_t>> InlinedSubroutineDIEAddrMap; - }; - - /// Vector of the subprogram DIEs and their subroutine address maps. - std::vector<SubprogramDIEAddrInfo> SubprogramDIEAddrInfos; - - /// A vector sorted to allow mapping from a PC to the subprogram DIE (and - /// associated addr map) index. Subprograms with overlapping PC ranges aren't - /// supported here. Nothing will crash, but the mapping may be inaccurate. - /// This vector may also contain "empty" ranges marked by an address with - /// a DIE index of '-1'. - std::vector<std::pair<uint64_t, int64_t>> SubprogramDIEAddrMap; + /// Map from range's start address to end address and corresponding DIE. + /// IntervalMap does not support range removal, as a result, we use the + /// std::map::upper_bound for address range lookup. + std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap; using die_iterator_range = iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>; std::shared_ptr<DWARFUnit> DWO; - const DWARFUnitIndex::Entry *IndexEntry; - uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) { auto First = DieArray.data(); assert(Die >= First && Die < First + DieArray.size()); @@ -269,10 +299,10 @@ class DWARFUnit { } protected: - virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); + const DWARFUnitHeader &getHeader() const { return Header; } - /// Size in bytes of the unit header. - virtual uint32_t getHeaderSize() const { return getVersion() <= 4 ? 11 : 12; } + /// Size in bytes of the parsed unit header. + uint32_t getHeaderSize() const { return Header.getSize(); } /// Find the unit's contribution to the string offsets table and determine its /// length and form. The given offset is expected to be derived from the unit @@ -291,16 +321,28 @@ protected: public: DWARFUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, - const DWARFUnitSectionBase &UnitSection, - const DWARFUnitIndex::Entry *IndexEntry = nullptr); + const DWARFUnitSectionBase &UnitSection); virtual ~DWARFUnit(); DWARFContext& getContext() const { return Context; } - + uint32_t getOffset() const { return Header.getOffset(); } + const dwarf::FormParams &getFormParams() const { + return Header.getFormParams(); + } + uint16_t getVersion() const { return Header.getVersion(); } + uint8_t getAddressByteSize() const { return Header.getAddressByteSize(); } + uint8_t getRefAddrByteSize() const { return Header.getRefAddrByteSize(); } + uint8_t getDwarfOffsetByteSize() const { + return Header.getDwarfOffsetByteSize(); + } + uint32_t getLength() const { return Header.getLength(); } + uint8_t getUnitType() const { return Header.getUnitType(); } + uint32_t getNextUnitOffset() const { return Header.getNextUnitOffset(); } const DWARFSection &getLineSection() const { return LineSection; } StringRef getStringSection() const { return StringSection; } const DWARFSection &getStringOffsetSection() const { @@ -312,6 +354,9 @@ public: AddrOffsetSectionBase = Base; } + /// Recursively update address to Die map. + void updateAddressDieMap(DWARFDie Die); + void setRangesSection(const DWARFSection *RS, uint32_t Base) { RangeSection = RS; RangeSectionBase = Base; @@ -326,31 +371,18 @@ public: return DataExtractor(StringSection, false, 0); } - - bool extract(DataExtractor debug_info, uint32_t* offset_ptr); - - /// extractRangeList - extracts the range list referenced by this compile - /// unit from .debug_ranges section. Returns true on success. - /// Requires that compile unit is already extracted. - bool extractRangeList(uint32_t RangeListOffset, - DWARFDebugRangeList &RangeList) const; + /// Extract the range list referenced by this compile unit from the + /// .debug_ranges section. If the extraction is unsuccessful, an error + /// is returned. Successful extraction requires that the compile unit + /// has already been extracted. + Error extractRangeList(uint32_t RangeListOffset, + DWARFDebugRangeList &RangeList) const; void clear(); - uint32_t getOffset() const { return Offset; } - uint32_t getNextUnitOffset() const { return Offset + Length + 4; } - uint32_t getLength() const { return Length; } const Optional<StrOffsetsContributionDescriptor> & getStringOffsetsTableContribution() const { return StringOffsetsTableContribution; } - const DWARFFormParams &getFormParams() const { return FormParams; } - uint16_t getVersion() const { return FormParams.Version; } - dwarf::DwarfFormat getFormat() const { return FormParams.Format; } - uint8_t getAddressByteSize() const { return FormParams.AddrSize; } - uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); } - uint8_t getDwarfOffsetByteSize() const { - return FormParams.getDwarfOffsetByteSize(); - } uint8_t getDwarfStringOffsetsByteSize() const { assert(StringOffsetsTableContribution); @@ -364,8 +396,6 @@ public: const DWARFAbbreviationDeclarationSet *getAbbreviations() const; - uint8_t getUnitType() const { return UnitType; } - static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) { switch (UnitType) { case dwarf::DW_UT_compile: @@ -383,7 +413,7 @@ public: return false; } - /// \brief Return the number of bytes for the header of a unit of + /// Return the number of bytes for the header of a unit of /// UnitType type. /// /// This function must be called with a valid unit type which in @@ -403,9 +433,7 @@ public: llvm_unreachable("Invalid UnitType."); } - llvm::Optional<BaseAddress> getBaseAddress() const { return BaseAddr; } - - void setBaseAddress(BaseAddress BaseAddr) { this->BaseAddr = BaseAddr; } + llvm::Optional<BaseAddress> getBaseAddress(); DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { extractDIEsIfNeeded(ExtractUnitDIEOnly); @@ -415,7 +443,29 @@ public: } const char *getCompilationDir(); - Optional<uint64_t> getDWOId(); + Optional<uint64_t> getDWOId() { + extractDIEsIfNeeded(/*CUDieOnly*/ true); + return getHeader().getDWOId(); + } + void setDWOId(uint64_t NewID) { Header.setDWOId(NewID); } + + /// Return a vector of address ranges resulting from a (possibly encoded) + /// range list starting at a given offset in the appropriate ranges section. + Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint32_t Offset); + + /// Return a vector of address ranges retrieved from an encoded range + /// list whose offset is found via a table lookup given an index (DWARF v5 + /// and later). + Expected<DWARFAddressRangesVector> findRnglistFromIndex(uint32_t Index); + + /// Return a rangelist's offset based on an index. The index designates + /// an entry in the rangelist table's offset array and is supplied by + /// DW_FORM_rnglistx. + Optional<uint32_t> getRnglistOffset(uint32_t Index) { + if (RngListTable) + return RngListTable->getOffsetEntry(Index); + return None; + } void collectAddressRanges(DWARFAddressRangesVector &CURanges); @@ -433,14 +483,14 @@ public: /// getUnitSection - Return the DWARFUnitSection containing this unit. const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } - /// \brief Returns the number of DIEs in the unit. Parses the unit + /// Returns the number of DIEs in the unit. Parses the unit /// if necessary. unsigned getNumDIEs() { extractDIEsIfNeeded(false); return DieArray.size(); } - /// \brief Return the index of a DIE inside the unit's DIE vector. + /// Return the index of a DIE inside the unit's DIE vector. /// /// It is illegal to call this method with a DIE that hasn't be /// created by this unit. In other word, it's illegal to call this @@ -450,7 +500,7 @@ public: return getDIEIndex(D.getDebugInfoEntry()); } - /// \brief Return the DIE object at the given index. + /// Return the DIE object at the given index. DWARFDie getDIEAtIndex(unsigned Index) { assert(Index < DieArray.size()); return DWARFDie(this, &DieArray[Index]); @@ -458,9 +508,11 @@ public: DWARFDie getParent(const DWARFDebugInfoEntry *Die); DWARFDie getSibling(const DWARFDebugInfoEntry *Die); + DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die); DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die); + DWARFDie getLastChild(const DWARFDebugInfoEntry *Die); - /// \brief Return the DIE object for a given offset inside the + /// Return the DIE object for a given offset inside the /// unit's DIE vector. /// /// The unit needs to have its DIEs extracted for this method to work. @@ -478,7 +530,7 @@ public: } uint32_t getLineTableOffset() const { - if (IndexEntry) + if (auto IndexEntry = Header.getIndexEntry()) if (const auto *Contrib = IndexEntry->getOffset(DW_SECT_LINE)) return Contrib->Offset; return 0; @@ -491,7 +543,9 @@ public: private: /// Size in bytes of the .debug_info data associated with this compile unit. - size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } + size_t getDebugInfoSize() const { + return Header.getLength() + 4 - getHeaderSize(); + } /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it /// hasn't already been done. Returns the number of DIEs parsed at this call. @@ -507,9 +561,6 @@ private: /// parseDWO - Parses .dwo file for current compile unit. Returns true if /// it was actually constructed. bool parseDWO(); - - void buildSubprogramDIEAddrMap(); - void buildInlinedSubroutineDIEAddrMap(SubprogramDIEAddrInfo &SPInfo); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index 0d920abe3231..a829510a219d 100644 --- a/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/contrib/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -11,7 +11,8 @@ #define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include <cstdint> @@ -24,7 +25,7 @@ struct DWARFAttribute; class DWARFContext; class DWARFDie; class DWARFUnit; -class DWARFAcceleratorTable; +class DWARFCompileUnit; class DWARFDataExtractor; class DWARFDebugAbbrev; class DataExtractor; @@ -109,7 +110,7 @@ private: /// \param Abbrev Pointer to the abbreviations section we are verifying /// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo. /// - /// \returns The number of errors that occured during verification. + /// \returns The number of errors that occurred during verification. unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev); /// Verifies the header of a unit in the .debug_info section. @@ -151,14 +152,14 @@ private: /// type of the unit DIE. /// /// \returns true if the content is verified successfully, false otherwise. - bool verifyUnitContents(DWARFUnit Unit, uint8_t UnitType = 0); + bool verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType = 0); /// Verify that all Die ranges are valid. /// /// This function currently checks for: /// - cases in which lowPC >= highPC /// - /// \returns Number of errors that occured during verification. + /// \returns Number of errors that occurred during verification. unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI); /// Verifies the attribute's DWARF attribute and its value. @@ -170,7 +171,7 @@ private: /// \param Die The DWARF DIE that owns the attribute value /// \param AttrValue The DWARF attribute value to check /// - /// \returns NumErrors The number of errors occured during verification of + /// \returns NumErrors The number of errors occurred during verification of /// attributes' values in a .debug_info section unit unsigned verifyDebugInfoAttribute(const DWARFDie &Die, DWARFAttribute &AttrValue); @@ -185,7 +186,7 @@ private: /// \param Die The DWARF DIE that owns the attribute value /// \param AttrValue The DWARF attribute value to check /// - /// \returns NumErrors The number of errors occured during verification of + /// \returns NumErrors The number of errors occurred during verification of /// attributes' forms in a .debug_info section unit unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue); @@ -197,11 +198,11 @@ private: /// around, that it doesn't create invalid references by failing to relocate /// CU relative and absolute references. /// - /// \returns NumErrors The number of errors occured during verification of + /// \returns NumErrors The number of errors occurred during verification of /// references for the .debug_info section unsigned verifyDebugInfoReferences(); - /// Verify the the DW_AT_stmt_list encoding and value and ensure that no + /// Verify the DW_AT_stmt_list encoding and value and ensure that no /// compile units that have the same DW_AT_stmt_list value. void verifyDebugLineStmtOffsets(); @@ -228,9 +229,42 @@ private: /// \param StrData pointer to the string section /// \param SectionName the name of the table we're verifying /// - /// \returns The number of errors occured during verification - unsigned verifyAccelTable(const DWARFSection *AccelSection, - DataExtractor *StrData, const char *SectionName); + /// \returns The number of errors occurred during verification + unsigned verifyAppleAccelTable(const DWARFSection *AccelSection, + DataExtractor *StrData, + const char *SectionName); + + unsigned verifyDebugNamesCULists(const DWARFDebugNames &AccelTable); + unsigned verifyNameIndexBuckets(const DWARFDebugNames::NameIndex &NI, + const DataExtractor &StrData); + unsigned verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI); + unsigned verifyNameIndexAttribute(const DWARFDebugNames::NameIndex &NI, + const DWARFDebugNames::Abbrev &Abbr, + DWARFDebugNames::AttributeEncoding AttrEnc); + unsigned verifyNameIndexEntries(const DWARFDebugNames::NameIndex &NI, + const DWARFDebugNames::NameTableEntry &NTE); + unsigned verifyNameIndexCompleteness(const DWARFDie &Die, + const DWARFDebugNames::NameIndex &NI); + + /// Verify that the DWARF v5 accelerator table is valid. + /// + /// This function currently checks that: + /// - Headers individual Name Indices fit into the section and can be parsed. + /// - Abbreviation tables can be parsed and contain valid index attributes + /// with correct form encodings. + /// - The CU lists reference existing compile units. + /// - The buckets have a valid index, or they are empty. + /// - All names are reachable via the hash table (they have the correct hash, + /// and the hash is in the correct bucket). + /// - Information in the index entries is complete (all required entries are + /// present) and consistent with the debug_info section DIEs. + /// + /// \param AccelSection section containing the acceleration table + /// \param StrData string section + /// + /// \returns The number of errors occurred during verification + unsigned verifyDebugNames(const DWARFSection &AccelSection, + const DataExtractor &StrData); public: DWARFVerifier(raw_ostream &S, DWARFContext &D, diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h index 19e5c31b3076..3de98c4ecba8 100644 --- a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h @@ -20,11 +20,13 @@ #include <vector> namespace llvm { +class FileBufferByteStream; +class WritableBinaryStream; namespace msf { class MSFBuilder { public: - /// \brief Create a new `MSFBuilder`. + /// Create a new `MSFBuilder`. /// /// \param BlockSize The internal block size used by the PDB file. See /// isValidBlockSize() for a list of valid block sizes. @@ -109,7 +111,10 @@ public: /// Finalize the layout and build the headers and structures that describe the /// MSF layout and can be written directly to the MSF file. - Expected<MSFLayout> build(); + Expected<MSFLayout> generateLayout(); + + /// Write the MSF layout to the underlying file. + Expected<FileBufferByteStream> commit(StringRef Path, MSFLayout &Layout); BumpPtrAllocator &getAllocator() { return Allocator; } diff --git a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h index f28415d4e603..2db2b71df4a7 100644 --- a/contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h +++ b/contrib/llvm/include/llvm/DebugInfo/MSF/MSFCommon.h @@ -52,6 +52,16 @@ struct SuperBlock { struct MSFLayout { MSFLayout() = default; + uint32_t mainFpmBlock() const { + assert(SB->FreeBlockMapBlock == 1 || SB->FreeBlockMapBlock == 2); + return SB->FreeBlockMapBlock; + } + + uint32_t alternateFpmBlock() const { + // If mainFpmBlock is 1, this is 2. If mainFpmBlock is 2, this is 1. + return 3U - mainFpmBlock(); + } + const SuperBlock *SB = nullptr; BitVector FreePageMap; ArrayRef<support::ulittle32_t> DirectoryBlocks; @@ -59,7 +69,7 @@ struct MSFLayout { std::vector<ArrayRef<support::ulittle32_t>> StreamMap; }; -/// \brief Describes the layout of a stream in an MSF layout. A "stream" here +/// Describes the layout of a stream in an MSF layout. A "stream" here /// is defined as any logical unit of data which may be arranged inside the MSF /// file as a sequence of (possibly discontiguous) blocks. When we want to read /// from a particular MSF Stream, we fill out a stream layout structure and the @@ -71,7 +81,7 @@ public: std::vector<support::ulittle32_t> Blocks; }; -/// \brief Determine the layout of the FPM stream, given the MSF layout. An FPM +/// Determine the layout of the FPM stream, given the MSF layout. An FPM /// stream spans 1 or more blocks, each at equally spaced intervals throughout /// the file. MSFStreamLayout getFpmStreamLayout(const MSFLayout &Msf, @@ -108,14 +118,40 @@ inline uint32_t getFpmIntervalLength(const MSFLayout &L) { return L.SB->BlockSize; } -inline uint32_t getNumFpmIntervals(const MSFLayout &L, - bool IncludeUnusedFpmData = false) { - if (IncludeUnusedFpmData) - return divideCeil(L.SB->NumBlocks, L.SB->BlockSize); +/// Given an MSF with the specified block size and number of blocks, determine +/// how many pieces the specified Fpm is split into. +/// \p BlockSize - the block size of the MSF +/// \p NumBlocks - the total number of blocks in the MSF +/// \p IncludeUnusedFpmData - When true, this will count every block that is +/// both in the file and matches the form of an FPM block, even if some of +/// those FPM blocks are unused (a single FPM block can describe the +/// allocation status of up to 32,767 blocks, although one appears only +/// every 4,096 blocks). So there are 8x as many blocks that match the +/// form as there are blocks that are necessary to describe the allocation +/// status of the file. When this parameter is false, these extraneous +/// trailing blocks are not counted. +inline uint32_t getNumFpmIntervals(uint32_t BlockSize, uint32_t NumBlocks, + bool IncludeUnusedFpmData, int FpmNumber) { + assert(FpmNumber == 1 || FpmNumber == 2); + if (IncludeUnusedFpmData) { + // This calculation determines how many times a number of the form + // BlockSize * k + N appears in the range [0, NumBlocks). We only need to + // do this when unused data is included, since the number of blocks dwarfs + // the number of fpm blocks. + return divideCeil(NumBlocks - FpmNumber, BlockSize); + } // We want the minimum number of intervals required, where each interval can // represent BlockSize * 8 blocks. - return divideCeil(L.SB->NumBlocks, 8 * L.SB->BlockSize); + return divideCeil(NumBlocks, 8 * BlockSize); +} + +inline uint32_t getNumFpmIntervals(const MSFLayout &L, + bool IncludeUnusedFpmData = false, + bool AltFpm = false) { + return getNumFpmIntervals(L.SB->BlockSize, L.SB->NumBlocks, + IncludeUnusedFpmData, + AltFpm ? L.alternateFpmBlock() : L.mainFpmBlock()); } Error validateSuperBlock(const SuperBlock &SB); diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h new file mode 100644 index 000000000000..39490a4b2209 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h @@ -0,0 +1,40 @@ +//==- DIAEnumInjectedSources.h - DIA Injected Sources Enumerator -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMINJECTEDSOURCES_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMINJECTEDSOURCES_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIAEnumInjectedSources : public IPDBEnumChildren<IPDBInjectedSource> { +public: + explicit DIAEnumInjectedSources( + const DIASession &PDBSession, + CComPtr<IDiaEnumInjectedSources> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumInjectedSources *clone() const override; + +private: + const DIASession &Session; + CComPtr<IDiaEnumInjectedSources> Enumerator; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAENUMINJECTEDSOURCES_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h new file mode 100644 index 000000000000..52c9563b5d5f --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h @@ -0,0 +1,40 @@ +//==- DIAEnumSectionContribs.h --------------------------------- -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMSECTIONCONTRIBS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMSECTIONCONTRIBS_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIAEnumSectionContribs : public IPDBEnumChildren<IPDBSectionContrib> { +public: + explicit DIAEnumSectionContribs( + const DIASession &PDBSession, + CComPtr<IDiaEnumSectionContribs> DiaEnumerator); + + uint32_t getChildCount() const override; + ChildTypePtr getChildAtIndex(uint32_t Index) const override; + ChildTypePtr getNext() override; + void reset() override; + DIAEnumSectionContribs *clone() const override; + +private: + const DIASession &Session; + CComPtr<IDiaEnumSectionContribs> Enumerator; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAENUMSECTIONCONTRIBS_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h new file mode 100644 index 000000000000..635508da84ea --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h @@ -0,0 +1,38 @@ +//===- DIAInjectedSource.h - DIA impl for IPDBInjectedSource ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAINJECTEDSOURCE_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAINJECTEDSOURCE_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIAInjectedSource : public IPDBInjectedSource { +public: + explicit DIAInjectedSource(CComPtr<IDiaInjectedSource> DiaSourceFile); + + uint32_t getCrc32() const override; + uint64_t getCodeByteSize() const override; + std::string getFileName() const override; + std::string getObjectFileName() const override; + std::string getVirtualFileName() const override; + PDB_SourceCompression getCompression() const override; + std::string getCode() const override; + +private: + CComPtr<IDiaInjectedSource> SourceFile; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAINJECTEDSOURCE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h index 2d6c44905ce0..dfb35647055a 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h @@ -30,10 +30,31 @@ public: findChildren(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags) const override; std::unique_ptr<IPDBEnumSymbols> + findChildrenByAddr(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags, + uint32_t Section, uint32_t Offset) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint64_t VA) const override; + std::unique_ptr<IPDBEnumSymbols> findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t RVA) const override; + + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const override; std::unique_ptr<IPDBEnumSymbols> findInlineFramesByRVA(uint32_t RVA) const override; + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByVA(uint64_t VA) const override; + + std::unique_ptr<IPDBEnumLineNumbers> findInlineeLines() const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, + uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override; void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const override; void getFrontEndVersion(VersionInfo &Version) const override; @@ -82,6 +103,7 @@ public: uint32_t getSizeInUdt() const override; uint32_t getSlot() const override; std::string getSourceFileName() const override; + std::unique_ptr<IPDBLineNumber> getSrcLineOnTypeDefn() const override; uint32_t getStride() const override; uint32_t getSubTypeId() const override; std::string getSymbolsFileName() const override; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h new file mode 100644 index 000000000000..4688f1f91a89 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASectionContrib.h @@ -0,0 +1,55 @@ +//===- DIASectionContrib.h - DIA Impl. of IPDBSectionContrib ------ C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIASECTIONCONTRIB_H +#define LLVM_DEBUGINFO_PDB_DIA_DIASECTIONCONTRIB_H + +#include "DIASupport.h" +#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h" + +namespace llvm { +namespace pdb { +class DIASession; + +class DIASectionContrib : public IPDBSectionContrib { +public: + explicit DIASectionContrib(const DIASession &PDBSession, + CComPtr<IDiaSectionContrib> DiaSection); + + std::unique_ptr<PDBSymbolCompiland> getCompiland() const override; + uint32_t getAddressSection() const override; + uint32_t getAddressOffset() const override; + uint32_t getRelativeVirtualAddress() const override; + uint64_t getVirtualAddress() const override; + uint32_t getLength() const override; + bool isNotPaged() const override; + bool hasCode() const override; + bool hasCode16Bit() const override; + bool hasInitializedData() const override; + bool hasUninitializedData() const override; + bool isRemoved() const override; + bool hasComdat() const override; + bool isDiscardable() const override; + bool isNotCached() const override; + bool isShared() const override; + bool isExecutable() const override; + bool isReadable() const override; + bool isWritable() const override; + uint32_t getDataCrc32() const override; + uint32_t getRelocationsCrc32() const override; + uint32_t getCompilandId() const override; + +private: + const DIASession &Session; + CComPtr<IDiaSectionContrib> Section; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIASECTIONCONTRIB_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h index 66bd7a7e9c4e..a63659439389 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -30,18 +30,33 @@ public: std::unique_ptr<IPDBSession> &Session); uint64_t getLoadAddress() const override; - void setLoadAddress(uint64_t Address) override; + bool setLoadAddress(uint64_t Address) override; std::unique_ptr<PDBSymbolExe> getGlobalScope() override; std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override; + bool addressForVA(uint64_t VA, uint32_t &Section, + uint32_t &Offset) const override; + bool addressForRVA(uint32_t RVA, uint32_t &Section, + uint32_t &Offset) const override; + std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override; + std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA, + PDB_SymType Type) const override; + std::unique_ptr<PDBSymbol> + findSymbolBySectOffset(uint32_t Section, uint32_t Offset, + PDB_SymType Type) const override; std::unique_ptr<IPDBEnumLineNumbers> findLineNumbers(const PDBSymbolCompiland &Compiland, const IPDBSourceFile &File) const override; std::unique_ptr<IPDBEnumLineNumbers> findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, + uint32_t Length) const override; std::unique_ptr<IPDBEnumSourceFiles> findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern, @@ -65,9 +80,14 @@ public: std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override; std::unique_ptr<IPDBEnumTables> getEnumTables() const override; + + std::unique_ptr<IPDBEnumInjectedSources> getInjectedSources() const override; + + std::unique_ptr<IPDBEnumSectionContribs> getSectionContribs() const override; + private: CComPtr<IDiaSession> Session; }; -} -} +} // namespace pdb +} // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASupport.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASupport.h index 3b4a348289df..92ebc04ae5a4 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASupport.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIASupport.h @@ -22,14 +22,6 @@ #define NOMINMAX #endif -// llvm/Support/Debug.h unconditionally #defines DEBUG as a macro. -// DIA headers #define it if it is not already defined, so we have -// an order of includes problem. The real fix is to make LLVM use -// something less generic than DEBUG, such as LLVM_DEBUG(), but it's -// fairly prevalent. So for now, we save the definition state and -// restore it. -#pragma push_macro("DEBUG") - // atlbase.h has to come before windows.h #include <atlbase.h> #include <windows.h> @@ -39,6 +31,4 @@ #include <dia2.h> #include <diacreate.h> -#pragma pop_macro("DEBUG") - #endif // LLVM_DEBUGINFO_PDB_DIA_DIASUPPORT_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h new file mode 100644 index 000000000000..aa843e05de70 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/DIA/DIAUtils.h @@ -0,0 +1,31 @@ +//===- DIAUtils.h - Utility functions for working with DIA ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAUTILS_H +#define LLVM_DEBUGINFO_PDB_DIA_DIAUTILS_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/ConvertUTF.h" + +template <typename Obj> +std::string invokeBstrMethod(Obj &Object, + HRESULT (__stdcall Obj::*Func)(BSTR *)) { + CComBSTR Str16; + HRESULT Result = (Object.*Func)(&Str16); + if (S_OK != Result) + return std::string(); + + std::string Str8; + llvm::ArrayRef<char> StrBytes(reinterpret_cast<char *>(Str16.m_str), + Str16.ByteLength()); + llvm::convertUTF16ToUTF8String(StrBytes, Str8); + return Str8; +} + +#endif // LLVM_DEBUGINFO_PDB_DIA_DIAUTILS_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h new file mode 100644 index 000000000000..e75d64af92bb --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h @@ -0,0 +1,42 @@ +//===- IPDBInjectedSource.h - base class for PDB injected file --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H +#define LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H + +#include "PDBTypes.h" +#include "llvm/Support/raw_ostream.h" +#include <memory> +#include <string> + +namespace llvm { +class raw_ostream; + +namespace pdb { + +/// IPDBInjectedSource defines an interface used to represent source files +/// which were injected directly into the PDB file during the compilation +/// process. This is used, for example, to add natvis files to a PDB, but +/// in theory could be used to add arbitrary source code. +class IPDBInjectedSource { +public: + virtual ~IPDBInjectedSource(); + + virtual uint32_t getCrc32() const = 0; + virtual uint64_t getCodeByteSize() const = 0; + virtual std::string getFileName() const = 0; + virtual std::string getObjectFileName() const = 0; + virtual std::string getVirtualFileName() const = 0; + virtual PDB_SourceCompression getCompression() const = 0; + virtual std::string getCode() const = 0; +}; +} // namespace pdb +} // namespace llvm + +#endif // LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h index 18b9423378a0..bcb2eaa35630 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h @@ -42,10 +42,31 @@ public: findChildren(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags) const = 0; virtual std::unique_ptr<IPDBEnumSymbols> + findChildrenByAddr(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags, + uint32_t Section, uint32_t Offset) const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> + findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint64_t VA) const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t RVA) const = 0; + + virtual std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const = 0; virtual std::unique_ptr<IPDBEnumSymbols> findInlineFramesByRVA(uint32_t RVA) const = 0; + virtual std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByVA(uint64_t VA) const = 0; + + virtual std::unique_ptr<IPDBEnumLineNumbers> findInlineeLines() const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, + uint32_t Length) const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByVA(uint64_t VA, uint32_t Length) const = 0; virtual void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const = 0; virtual void getBackEndVersion(VersionInfo &Version) const = 0; @@ -94,6 +115,8 @@ public: virtual uint32_t getSizeInUdt() const = 0; virtual uint32_t getSlot() const = 0; virtual std::string getSourceFileName() const = 0; + virtual std::unique_ptr<IPDBLineNumber> + getSrcLineOnTypeDefn() const = 0; virtual uint32_t getStride() const = 0; virtual uint32_t getSubTypeId() const = 0; virtual std::string getSymbolsFileName() const = 0; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h new file mode 100644 index 000000000000..4fda62404672 --- /dev/null +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSectionContrib.h @@ -0,0 +1,50 @@ +//==- IPDBSectionContrib.h - Interfaces for PDB SectionContribs --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_IPDBSECTIONCONTRIB_H +#define LLVM_DEBUGINFO_PDB_IPDBSECTIONCONTRIB_H + +#include "PDBTypes.h" + +namespace llvm { +namespace pdb { + +/// IPDBSectionContrib defines an interface used to represent section +/// contributions whose information are stored in the PDB. +class IPDBSectionContrib { +public: + virtual ~IPDBSectionContrib(); + + virtual std::unique_ptr<PDBSymbolCompiland> getCompiland() const = 0; + virtual uint32_t getAddressSection() const = 0; + virtual uint32_t getAddressOffset() const = 0; + virtual uint32_t getRelativeVirtualAddress() const = 0; + virtual uint64_t getVirtualAddress() const = 0; + virtual uint32_t getLength() const = 0; + virtual bool isNotPaged() const = 0; + virtual bool hasCode() const = 0; + virtual bool hasCode16Bit() const = 0; + virtual bool hasInitializedData() const = 0; + virtual bool hasUninitializedData() const = 0; + virtual bool isRemoved() const = 0; + virtual bool hasComdat() const = 0; + virtual bool isDiscardable() const = 0; + virtual bool isNotCached() const = 0; + virtual bool isShared() const = 0; + virtual bool isExecutable() const = 0; + virtual bool isReadable() const = 0; + virtual bool isWritable() const = 0; + virtual uint32_t getDataCrc32() const = 0; + virtual uint32_t getRelocationsCrc32() const = 0; + virtual uint32_t getCompilandId() const = 0; +}; +} +} + +#endif // LLVM_DEBUGINFO_PDB_IPDBSECTIONCONTRIB_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h index 6291289de5bf..88ec517bc4a5 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -28,10 +28,15 @@ public: virtual ~IPDBSession(); virtual uint64_t getLoadAddress() const = 0; - virtual void setLoadAddress(uint64_t Address) = 0; + virtual bool setLoadAddress(uint64_t Address) = 0; virtual std::unique_ptr<PDBSymbolExe> getGlobalScope() = 0; virtual std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const = 0; + virtual bool addressForVA(uint64_t VA, uint32_t &Section, + uint32_t &Offset) const = 0; + virtual bool addressForRVA(uint32_t RVA, uint32_t &Section, + uint32_t &Offset) const = 0; + template <typename T> std::unique_ptr<T> getConcreteSymbolById(uint32_t SymbolId) const { return unique_dyn_cast_or_null<T>(getSymbolById(SymbolId)); @@ -39,12 +44,22 @@ public: virtual std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0; + virtual std::unique_ptr<PDBSymbol> + findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const = 0; + virtual std::unique_ptr<PDBSymbol> + findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, + PDB_SymType Type) const = 0; virtual std::unique_ptr<IPDBEnumLineNumbers> findLineNumbers(const PDBSymbolCompiland &Compiland, const IPDBSourceFile &File) const = 0; virtual std::unique_ptr<IPDBEnumLineNumbers> findLineNumbersByAddress(uint64_t Address, uint32_t Length) const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const = 0; + virtual std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, + uint32_t Length) const = 0; virtual std::unique_ptr<IPDBEnumSourceFiles> findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern, @@ -69,8 +84,14 @@ public: virtual std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const = 0; virtual std::unique_ptr<IPDBEnumTables> getEnumTables() const = 0; + + virtual std::unique_ptr<IPDBEnumInjectedSources> + getInjectedSources() const = 0; + + virtual std::unique_ptr<IPDBEnumSectionContribs> + getSectionContribs() const = 0; }; -} -} +} // namespace pdb +} // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h index 8200f51e3da9..9eef4041d0a1 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h @@ -47,6 +47,8 @@ public: uint32_t getRecordLength() const; + const SectionContrib &getSectionContrib() const; + private: StringRef ModuleName; StringRef ObjFileName; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h index c918a5d5e976..ce4d07917755 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -49,6 +49,7 @@ public: void setPdbFilePathNI(uint32_t NI); void setObjFileName(StringRef Name); + void setFirstSectionContrib(const SectionContrib &SC); void addSymbol(codeview::CVSymbol Symbol); void diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h index 4be113f28d6f..280615bdb507 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStream.h @@ -38,9 +38,9 @@ class DbiStream { friend class DbiStreamBuilder; public: - DbiStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream); + explicit DbiStream(std::unique_ptr<BinaryStream> Stream); ~DbiStream(); - Error reload(); + Error reload(PDBFile *Pdb); PdbRaw_DbiVer getDbiVersion() const; uint32_t getAge() const; @@ -63,6 +63,8 @@ public: PDB_Machine getMachineType() const; + const DbiStreamHeader *getHeader() const { return Header; } + BinarySubstreamRef getSectionContributionData() const; BinarySubstreamRef getSecMapSubstreamData() const; BinarySubstreamRef getModiSubstreamData() const; @@ -87,12 +89,11 @@ public: private: Error initializeSectionContributionData(); - Error initializeSectionHeadersData(); + Error initializeSectionHeadersData(PDBFile *Pdb); Error initializeSectionMapData(); - Error initializeFpoRecords(); + Error initializeFpoRecords(PDBFile *Pdb); - PDBFile &Pdb; - std::unique_ptr<msf::MappedBlockStream> Stream; + std::unique_ptr<BinaryStream> Stream; PDBStringTable ECNames; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h index ad4a0d1bcb6b..51befcdac775 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h @@ -12,6 +12,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSet.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/Support/Error.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" @@ -46,10 +47,12 @@ public: void setVersionHeader(PdbRaw_DbiVer V); void setAge(uint32_t A); void setBuildNumber(uint16_t B); + void setBuildNumber(uint8_t Major, uint8_t Minor); void setPdbDllVersion(uint16_t V); void setPdbDllRbld(uint16_t R); void setFlags(uint16_t F); void setMachineType(PDB_Machine M); + void setMachineType(COFF::MachineTypes M); void setSectionMap(ArrayRef<SecMapEntry> SecMap); // Add given bytes as a new stream. @@ -121,7 +124,7 @@ private: MutableBinaryByteStream FileInfoBuffer; std::vector<SectionContrib> SectionContribs; ArrayRef<SecMapEntry> SectionMap; - llvm::SmallVector<DebugStream, (int)DbgHeaderType::Max> DbgStreams; + std::array<Optional<DebugStream>, (int)DbgHeaderType::Max> DbgStreams; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h index 05c70c4f2175..34cc6179688b 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h @@ -12,6 +12,9 @@ #include "llvm/ADT/SparseBitVector.h" #include "llvm/ADT/iterator.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include <cstdint> @@ -26,80 +29,303 @@ class BinaryStreamWriter; namespace pdb { -class HashTableIterator; +Error readSparseBitVector(BinaryStreamReader &Stream, SparseBitVector<> &V); +Error writeSparseBitVector(BinaryStreamWriter &Writer, SparseBitVector<> &Vec); +template <typename ValueT, typename TraitsT> class HashTable; + +template <typename ValueT, typename TraitsT> +class HashTableIterator + : public iterator_facade_base<HashTableIterator<ValueT, TraitsT>, + std::forward_iterator_tag, + std::pair<uint32_t, ValueT>> { + friend HashTable<ValueT, TraitsT>; + + HashTableIterator(const HashTable<ValueT, TraitsT> &Map, uint32_t Index, + bool IsEnd) + : Map(&Map), Index(Index), IsEnd(IsEnd) {} + +public: + HashTableIterator(const HashTable<ValueT, TraitsT> &Map) : Map(&Map) { + int I = Map.Present.find_first(); + if (I == -1) { + Index = 0; + IsEnd = true; + } else { + Index = static_cast<uint32_t>(I); + IsEnd = false; + } + } + + HashTableIterator &operator=(const HashTableIterator &R) { + Map = R.Map; + return *this; + } + bool operator==(const HashTableIterator &R) const { + if (IsEnd && R.IsEnd) + return true; + if (IsEnd != R.IsEnd) + return false; + + return (Map == R.Map) && (Index == R.Index); + } + const std::pair<uint32_t, ValueT> &operator*() const { + assert(Map->Present.test(Index)); + return Map->Buckets[Index]; + } + HashTableIterator &operator++() { + while (Index < Map->Buckets.size()) { + ++Index; + if (Map->Present.test(Index)) + return *this; + } + + IsEnd = true; + return *this; + } + +private: + bool isEnd() const { return IsEnd; } + uint32_t index() const { return Index; } + + const HashTable<ValueT, TraitsT> *Map; + uint32_t Index; + bool IsEnd; +}; + +template <typename T> struct PdbHashTraits {}; + +template <> struct PdbHashTraits<uint32_t> { + uint32_t hashLookupKey(uint32_t N) const { return N; } + uint32_t storageKeyToLookupKey(uint32_t N) const { return N; } + uint32_t lookupKeyToStorageKey(uint32_t N) { return N; } +}; + +template <typename ValueT, typename TraitsT = PdbHashTraits<ValueT>> class HashTable { - friend class HashTableIterator; + using iterator = HashTableIterator<ValueT, TraitsT>; + friend iterator; struct Header { support::ulittle32_t Size; support::ulittle32_t Capacity; }; - using BucketList = std::vector<std::pair<uint32_t, uint32_t>>; + using BucketList = std::vector<std::pair<uint32_t, ValueT>>; public: - HashTable(); - explicit HashTable(uint32_t Capacity); + HashTable() { Buckets.resize(8); } + + explicit HashTable(TraitsT Traits) : HashTable(8, std::move(Traits)) {} + HashTable(uint32_t Capacity, TraitsT Traits) : Traits(Traits) { + Buckets.resize(Capacity); + } + + Error load(BinaryStreamReader &Stream) { + const Header *H; + if (auto EC = Stream.readObject(H)) + return EC; + if (H->Capacity == 0) + return make_error<RawError>(raw_error_code::corrupt_file, + "Invalid Hash Table Capacity"); + if (H->Size > maxLoad(H->Capacity)) + return make_error<RawError>(raw_error_code::corrupt_file, + "Invalid Hash Table Size"); + + Buckets.resize(H->Capacity); + + if (auto EC = readSparseBitVector(Stream, Present)) + return EC; + if (Present.count() != H->Size) + return make_error<RawError>(raw_error_code::corrupt_file, + "Present bit vector does not match size!"); + + if (auto EC = readSparseBitVector(Stream, Deleted)) + return EC; + if (Present.intersects(Deleted)) + return make_error<RawError>(raw_error_code::corrupt_file, + "Present bit vector interesects deleted!"); - Error load(BinaryStreamReader &Stream); + for (uint32_t P : Present) { + if (auto EC = Stream.readInteger(Buckets[P].first)) + return EC; + const ValueT *Value; + if (auto EC = Stream.readObject(Value)) + return EC; + Buckets[P].second = *Value; + } - uint32_t calculateSerializedLength() const; - Error commit(BinaryStreamWriter &Writer) const; + return Error::success(); + } - void clear(); + uint32_t calculateSerializedLength() const { + uint32_t Size = sizeof(Header); - uint32_t capacity() const; - uint32_t size() const; + constexpr int BitsPerWord = 8 * sizeof(uint32_t); - HashTableIterator begin() const; - HashTableIterator end() const; - HashTableIterator find(uint32_t K); + int NumBitsP = Present.find_last() + 1; + int NumBitsD = Deleted.find_last() + 1; - void set(uint32_t K, uint32_t V); - void remove(uint32_t K); - uint32_t get(uint32_t K); + uint32_t NumWordsP = alignTo(NumBitsP, BitsPerWord) / BitsPerWord; + uint32_t NumWordsD = alignTo(NumBitsD, BitsPerWord) / BitsPerWord; + + // Present bit set number of words (4 bytes), followed by that many actual + // words (4 bytes each). + Size += sizeof(uint32_t); + Size += NumWordsP * sizeof(uint32_t); + + // Deleted bit set number of words (4 bytes), followed by that many actual + // words (4 bytes each). + Size += sizeof(uint32_t); + Size += NumWordsD * sizeof(uint32_t); + + // One (Key, ValueT) pair for each entry Present. + Size += (sizeof(uint32_t) + sizeof(ValueT)) * size(); + + return Size; + } + + Error commit(BinaryStreamWriter &Writer) const { + Header H; + H.Size = size(); + H.Capacity = capacity(); + if (auto EC = Writer.writeObject(H)) + return EC; + + if (auto EC = writeSparseBitVector(Writer, Present)) + return EC; + + if (auto EC = writeSparseBitVector(Writer, Deleted)) + return EC; + + for (const auto &Entry : *this) { + if (auto EC = Writer.writeInteger(Entry.first)) + return EC; + if (auto EC = Writer.writeObject(Entry.second)) + return EC; + } + return Error::success(); + } + + void clear() { + Buckets.resize(8); + Present.clear(); + Deleted.clear(); + } + + bool empty() const { return size() == 0; } + uint32_t capacity() const { return Buckets.size(); } + uint32_t size() const { return Present.count(); } + + iterator begin() const { return iterator(*this); } + iterator end() const { return iterator(*this, 0, true); } + + /// Find the entry whose key has the specified hash value, using the specified + /// traits defining hash function and equality. + template <typename Key> iterator find_as(const Key &K) const { + uint32_t H = Traits.hashLookupKey(K) % capacity(); + uint32_t I = H; + Optional<uint32_t> FirstUnused; + do { + if (isPresent(I)) { + if (Traits.storageKeyToLookupKey(Buckets[I].first) == K) + return iterator(*this, I, false); + } else { + if (!FirstUnused) + FirstUnused = I; + // Insertion occurs via linear probing from the slot hint, and will be + // inserted at the first empty / deleted location. Therefore, if we are + // probing and find a location that is neither present nor deleted, then + // nothing must have EVER been inserted at this location, and thus it is + // not possible for a matching value to occur later. + if (!isDeleted(I)) + break; + } + I = (I + 1) % capacity(); + } while (I != H); + + // The only way FirstUnused would not be set is if every single entry in the + // table were Present. But this would violate the load factor constraints + // that we impose, so it should never happen. + assert(FirstUnused); + return iterator(*this, *FirstUnused, true); + } + + /// Set the entry using a key type that the specified Traits can convert + /// from a real key to an internal key. + template <typename Key> bool set_as(const Key &K, ValueT V) { + return set_as_internal(K, std::move(V), None); + } + + template <typename Key> ValueT get(const Key &K) const { + auto Iter = find_as(K); + assert(Iter != end()); + return (*Iter).second; + } protected: bool isPresent(uint32_t K) const { return Present.test(K); } bool isDeleted(uint32_t K) const { return Deleted.test(K); } + TraitsT Traits; BucketList Buckets; mutable SparseBitVector<> Present; mutable SparseBitVector<> Deleted; private: - static uint32_t maxLoad(uint32_t capacity); - void grow(); + /// Set the entry using a key type that the specified Traits can convert + /// from a real key to an internal key. + template <typename Key> + bool set_as_internal(const Key &K, ValueT V, Optional<uint32_t> InternalKey) { + auto Entry = find_as(K); + if (Entry != end()) { + assert(isPresent(Entry.index())); + assert(Traits.storageKeyToLookupKey(Buckets[Entry.index()].first) == K); + // We're updating, no need to do anything special. + Buckets[Entry.index()].second = V; + return false; + } - static Error readSparseBitVector(BinaryStreamReader &Stream, - SparseBitVector<> &V); - static Error writeSparseBitVector(BinaryStreamWriter &Writer, - SparseBitVector<> &Vec); -}; + auto &B = Buckets[Entry.index()]; + assert(!isPresent(Entry.index())); + assert(Entry.isEnd()); + B.first = InternalKey ? *InternalKey : Traits.lookupKeyToStorageKey(K); + B.second = V; + Present.set(Entry.index()); + Deleted.reset(Entry.index()); -class HashTableIterator - : public iterator_facade_base<HashTableIterator, std::forward_iterator_tag, - std::pair<uint32_t, uint32_t>> { - friend class HashTable; + grow(); - HashTableIterator(const HashTable &Map, uint32_t Index, bool IsEnd); + assert((find_as(K)) != end()); + return true; + } -public: - HashTableIterator(const HashTable &Map); + static uint32_t maxLoad(uint32_t capacity) { return capacity * 2 / 3 + 1; } - HashTableIterator &operator=(const HashTableIterator &R); - bool operator==(const HashTableIterator &R) const; - const std::pair<uint32_t, uint32_t> &operator*() const; - HashTableIterator &operator++(); + void grow() { + uint32_t S = size(); + uint32_t MaxLoad = maxLoad(capacity()); + if (S < maxLoad(capacity())) + return; + assert(capacity() != UINT32_MAX && "Can't grow Hash table!"); -private: - bool isEnd() const { return IsEnd; } - uint32_t index() const { return Index; } + uint32_t NewCapacity = (capacity() <= INT32_MAX) ? MaxLoad * 2 : UINT32_MAX; - const HashTable *Map; - uint32_t Index; - bool IsEnd; + // Growing requires rebuilding the table and re-hashing every item. Make a + // copy with a larger capacity, insert everything into the copy, then swap + // it in. + HashTable NewMap(NewCapacity, Traits); + for (auto I : Present) { + auto LookupKey = Traits.storageKeyToLookupKey(Buckets[I].first); + NewMap.set_as_internal(LookupKey, Buckets[I].second, Buckets[I].first); + } + + Buckets.swap(NewMap.Buckets); + std::swap(Present, NewMap.Present); + std::swap(Deleted, NewMap.Deleted); + assert(capacity() == NewCapacity); + assert(size() == S); + } }; } // end namespace pdb diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStream.h index fb8271cb5ebc..8c52b042f289 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStream.h @@ -30,12 +30,14 @@ class InfoStream { friend class InfoStreamBuilder; public: - InfoStream(std::unique_ptr<msf::MappedBlockStream> Stream); + InfoStream(std::unique_ptr<BinaryStream> Stream); Error reload(); uint32_t getStreamSize() const; + const InfoStreamHeader *getHeader() const { return Header; } + bool containsIdStream() const; PdbRaw_ImplVer getVersion() const; uint32_t getSignature() const; @@ -50,29 +52,13 @@ public: BinarySubstreamRef getNamedStreamsBuffer() const; - uint32_t getNamedStreamIndex(llvm::StringRef Name) const; - iterator_range<StringMapConstIterator<uint32_t>> named_streams() const; + Expected<uint32_t> getNamedStreamIndex(llvm::StringRef Name) const; + StringMap<uint32_t> named_streams() const; private: - std::unique_ptr<msf::MappedBlockStream> Stream; - - // PDB file format version. We only support VC70. See the enumeration - // `PdbRaw_ImplVer` for the other possible values. - uint32_t Version; - - // A 32-bit signature unique across all PDBs. This is generated with - // a call to time() when the PDB is written, but obviously this is not - // universally unique. - uint32_t Signature; - - // The number of times the PDB has been written. Might also be used to - // ensure that the PDB matches the executable. - uint32_t Age; + std::unique_ptr<BinaryStream> Stream; - // Due to the aforementioned limitations with `Signature`, this is a new - // signature present on VC70 and higher PDBs which is guaranteed to be - // universally unique. - codeview::GUID Guid; + const InfoStreamHeader *Header; BinarySubstreamRef SubNamedStreams; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h index c6cb0e221e70..419e8ada06f7 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h @@ -40,6 +40,10 @@ public: void setGuid(codeview::GUID G); void addFeature(PdbRaw_FeatureSig Sig); + uint32_t getAge() const { return Age; } + codeview::GUID getGuid() const { return Guid; } + Optional<uint32_t> getSignature() const { return Signature; } + uint32_t finalize(); Error finalizeMsfLayout(); @@ -52,8 +56,8 @@ private: std::vector<PdbRaw_FeatureSig> Features; PdbRaw_ImplVer Ver; - uint32_t Sig; uint32_t Age; + Optional<uint32_t> Signature; codeview::GUID Guid; NamedStreamMap &NamedStreams; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h index 17a82b7ce12d..01b8f1b5da56 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h @@ -25,32 +25,45 @@ class BinaryStreamWriter; namespace pdb { +class NamedStreamMap; + +struct NamedStreamMapTraits { + NamedStreamMap *NS; + + explicit NamedStreamMapTraits(NamedStreamMap &NS); + uint16_t hashLookupKey(StringRef S) const; + StringRef storageKeyToLookupKey(uint32_t Offset) const; + uint32_t lookupKeyToStorageKey(StringRef S); +}; + class NamedStreamMap { friend class NamedStreamMapBuilder; - struct FinalizationInfo { - uint32_t StringDataBytes = 0; - uint32_t SerializedLength = 0; - }; - public: NamedStreamMap(); Error load(BinaryStreamReader &Stream); Error commit(BinaryStreamWriter &Writer) const; - uint32_t finalize(); + uint32_t calculateSerializedLength() const; uint32_t size() const; bool get(StringRef Stream, uint32_t &StreamNo) const; void set(StringRef Stream, uint32_t StreamNo); - void remove(StringRef Stream); - const StringMap<uint32_t> &getStringMap() const { return Mapping; } - iterator_range<StringMapConstIterator<uint32_t>> entries() const; + + uint32_t appendStringData(StringRef S); + StringRef getString(uint32_t Offset) const; + uint32_t hashString(uint32_t Offset) const; + + StringMap<uint32_t> entries() const; private: - Optional<FinalizationInfo> FinalizedInfo; - HashTable FinalizedHashTable; - StringMap<uint32_t> Mapping; + NamedStreamMapTraits HashTraits; + /// Closed hash table from Offset -> StreamNumber, where Offset is the offset + /// of the stream name in NamesBuffer. + HashTable<support::ulittle32_t, NamedStreamMapTraits> OffsetIndexMap; + + /// Buffer of string data. + std::vector<char> NamesBuffer; }; } // end namespace pdb diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h index 931b93fb7266..5b70ecfa2056 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h @@ -35,10 +35,31 @@ public: findChildren(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags) const override; std::unique_ptr<IPDBEnumSymbols> + findChildrenByAddr(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags, + uint32_t Section, uint32_t Offset) const override; + std::unique_ptr<IPDBEnumSymbols> + findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint64_t VA) const override; + std::unique_ptr<IPDBEnumSymbols> findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t RVA) const override; + + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const override; std::unique_ptr<IPDBEnumSymbols> findInlineFramesByRVA(uint32_t RVA) const override; + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByVA(uint64_t VA) const override; + + std::unique_ptr<IPDBEnumLineNumbers> findInlineeLines() const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, + uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override; void getDataBytes(SmallVector<uint8_t, 32> &Bytes) const override; void getFrontEndVersion(VersionInfo &Version) const override; @@ -87,6 +108,7 @@ public: uint32_t getSizeInUdt() const override; uint32_t getSlot() const override; std::string getSourceFileName() const override; + std::unique_ptr<IPDBLineNumber> getSrcLineOnTypeDefn() const override; uint32_t getStride() const override; uint32_t getSubTypeId() const override; std::string getSymbolsFileName() const override; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h index 2e68ced46bfe..aff7ef2f8f21 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h @@ -49,18 +49,33 @@ public: SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI); uint64_t getLoadAddress() const override; - void setLoadAddress(uint64_t Address) override; + bool setLoadAddress(uint64_t Address) override; std::unique_ptr<PDBSymbolExe> getGlobalScope() override; std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override; + bool addressForVA(uint64_t VA, uint32_t &Section, + uint32_t &Offset) const override; + bool addressForRVA(uint32_t RVA, uint32_t &Section, + uint32_t &Offset) const override; + std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override; + std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA, + PDB_SymType Type) const override; + std::unique_ptr<PDBSymbol> + findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, + PDB_SymType Type) const override; std::unique_ptr<IPDBEnumLineNumbers> findLineNumbers(const PDBSymbolCompiland &Compiland, const IPDBSourceFile &File) const override; std::unique_ptr<IPDBEnumLineNumbers> findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const override; + std::unique_ptr<IPDBEnumLineNumbers> + findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, + uint32_t Length) const override; std::unique_ptr<IPDBEnumSourceFiles> findSourceFiles(const PDBSymbolCompiland *Compiland, llvm::StringRef Pattern, @@ -85,6 +100,10 @@ public: std::unique_ptr<IPDBEnumTables> getEnumTables() const override; + std::unique_ptr<IPDBEnumInjectedSources> getInjectedSources() const override; + + std::unique_ptr<IPDBEnumSectionContribs> getSectionContribs() const override; + PDBFile &getPDBFile() { return *Pdb; } const PDBFile &getPDBFile() const { return *Pdb; } @@ -94,7 +113,7 @@ private: std::vector<std::unique_ptr<NativeRawSymbol>> SymbolCache; DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId; }; -} -} +} // namespace pdb +} // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h index 7ed164bee9ee..7f9c4cf9fa83 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h @@ -17,9 +17,11 @@ #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" #include <memory> #include <vector> @@ -54,12 +56,34 @@ public: Error commit(StringRef Filename); Expected<uint32_t> getNamedStreamIndex(StringRef Name) const; - Error addNamedStream(StringRef Name, uint32_t Size); + Error addNamedStream(StringRef Name, StringRef Data); + void addInjectedSource(StringRef Name, std::unique_ptr<MemoryBuffer> Buffer); private: - Expected<msf::MSFLayout> finalizeMsfLayout(); + struct InjectedSourceDescriptor { + // The full name of the stream that contains the contents of this injected + // source. This is built as a concatenation of the literal "/src/files" + // plus the "vname". + std::string StreamName; + + // The exact name of the file name as specified by the user. + uint32_t NameIndex; + + // The string table index of the "vname" of the file. As far as we + // understand, this is the same as the name, except it is lowercased and + // forward slashes are converted to backslashes. + uint32_t VNameIndex; + std::unique_ptr<MemoryBuffer> Content; + }; + + Error finalizeMsfLayout(); + Expected<uint32_t> allocateNamedStream(StringRef Name, uint32_t Size); void commitFpm(WritableBinaryStream &MsfBuffer, const msf::MSFLayout &Layout); + void commitInjectedSources(WritableBinaryStream &MsfBuffer, + const msf::MSFLayout &Layout); + void commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer, + const msf::MSFLayout &Layout); BumpPtrAllocator &Allocator; @@ -71,7 +95,13 @@ private: std::unique_ptr<TpiStreamBuilder> Ipi; PDBStringTableBuilder Strings; + StringTableHashTraits InjectedSourceHashTraits; + HashTable<SrcHeaderBlockEntry, StringTableHashTraits> InjectedSourceTable; + + SmallVector<InjectedSourceDescriptor, 2> InjectedSources; + NamedStreamMap NamedStreams; + DenseMap<uint32_t, std::string> NamedStreamData; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h index b57707ee7923..0f81c18eafe6 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h @@ -31,6 +31,16 @@ struct MSFLayout; namespace pdb { class PDBFileBuilder; +class PDBStringTableBuilder; + +struct StringTableHashTraits { + PDBStringTableBuilder *Table; + + explicit StringTableHashTraits(PDBStringTableBuilder &Table); + uint32_t hashLookupKey(StringRef S) const; + StringRef storageKeyToLookupKey(uint32_t Offset) const; + uint32_t lookupKeyToStorageKey(StringRef S); +}; class PDBStringTableBuilder { public: @@ -38,6 +48,9 @@ public: // Returns the ID for S. uint32_t insert(StringRef S); + uint32_t getIdForString(StringRef S) const; + StringRef getStringForId(uint32_t Id) const; + uint32_t calculateSerializedSize() const; Error commit(BinaryStreamWriter &Writer) const; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawConstants.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawConstants.h index bb1d097b5123..fbbd3318d958 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawConstants.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawConstants.h @@ -32,6 +32,8 @@ enum PdbRaw_ImplVer : uint32_t { PdbImplVC140 = 20140508, }; +enum class PdbRaw_SrcHeaderBlockVer : uint32_t { SrcVerOne = 19980827 }; + enum class PdbRaw_FeatureSig : uint32_t { VC110 = PdbImplVC110, VC140 = PdbImplVC140, diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h index 8cc083685265..19f592d562e4 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -112,6 +112,8 @@ struct DbiBuildNo { static const uint16_t BuildMajorMask = 0x7F00; static const uint16_t BuildMajorShift = 8; + + static const uint16_t NewVersionFormatMask = 0x8000; }; /// The fixed size header that appears at the beginning of the DBI Stream. @@ -175,18 +177,6 @@ struct DbiStreamHeader { }; static_assert(sizeof(DbiStreamHeader) == 64, "Invalid DbiStreamHeader size!"); -struct SectionContribEntry { - support::ulittle16_t Section; - char Padding1[2]; - support::little32_t Offset; - support::little32_t Size; - support::ulittle32_t Characteristics; - support::ulittle16_t ModuleIndex; - char Padding2[2]; - support::ulittle32_t DataCrc; - support::ulittle32_t RelocCrc; -}; - /// The header preceeding the File Info Substream of the DBI stream. struct FileInfoSubstreamHeader { /// Total # of modules, should match number of records in the ModuleInfo @@ -228,7 +218,7 @@ struct ModuleInfoHeader { support::ulittle32_t Mod; /// First section contribution of this module. - SectionContribEntry SC; + SectionContrib SC; /// See ModInfoFlags definition. support::ulittle16_t Flags; @@ -328,6 +318,34 @@ struct PDBStringTableHeader { const uint32_t PDBStringTableSignature = 0xEFFEEFFE; +/// The header preceding the /src/headerblock stream. +struct SrcHeaderBlockHeader { + support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration. + support::ulittle32_t Size; // Size of entire stream. + uint64_t FileTime; // Time stamp (Windows FILETIME format). + support::ulittle32_t Age; // Age + uint8_t Padding[44]; // Pad to 64 bytes. +}; +static_assert(sizeof(SrcHeaderBlockHeader) == 64, "Incorrect struct size!"); + +/// A single file record entry within the /src/headerblock stream. +struct SrcHeaderBlockEntry { + support::ulittle32_t Size; // Record Length. + support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration. + support::ulittle32_t CRC; // CRC of the original file contents. + support::ulittle32_t FileSize; // Size of original source file. + support::ulittle32_t FileNI; // String table index of file name. + support::ulittle32_t ObjNI; // String table index of object name. + support::ulittle32_t VFileNI; // String table index of virtual file name. + uint8_t Compression; // PDB_SourceCompression enumeration. + uint8_t IsVirtual; // Is this a virtual file (injected)? + short Padding; // Pad to 4 bytes. + char Reserved[8]; +}; + +constexpr int I = sizeof(SrcHeaderBlockEntry); +static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!"); + } // namespace pdb } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h index d3475205a6c2..b77939929ecf 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/Native/TpiStream.h @@ -51,7 +51,7 @@ public: uint32_t getNumHashBuckets() const; FixedStreamArray<support::ulittle32_t> getHashValues() const; FixedStreamArray<codeview::TypeIndexOffset> getTypeIndexOffsets() const; - HashTable &getHashAdjusters(); + HashTable<support::ulittle32_t> &getHashAdjusters(); codeview::CVTypeRange types(bool *HadError) const; const codeview::CVTypeArray &typeArray() const { return TypeRecords; } @@ -75,7 +75,7 @@ private: std::unique_ptr<BinaryStream> HashStream; FixedStreamArray<support::ulittle32_t> HashValues; FixedStreamArray<codeview::TypeIndexOffset> TypeIndexOffsets; - HashTable HashAdjusters; + HashTable<support::ulittle32_t> HashAdjusters; const TpiStreamHeader *Header; }; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h index 778121c8eb79..3c9a19801f89 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -34,6 +34,8 @@ raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag); raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access); raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type); raw_ostream &operator<<(raw_ostream &OS, const PDB_Machine &Machine); +raw_ostream &operator<<(raw_ostream &OS, + const PDB_SourceCompression &Compression); raw_ostream &operator<<(raw_ostream &OS, const Variant &Value); raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version); diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h index 26788017cf32..9549089c7eb4 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolCompiland.h @@ -34,6 +34,7 @@ public: FORWARD_SYMBOL_METHOD(getName) std::string getSourceFileName() const; + std::string getSourceFileFullPath() const; }; } } diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h index ad4285df4d44..76b14bf17784 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolData.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H #define LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H +#include "IPDBLineNumber.h" #include "PDBSymbol.h" #include "PDBTypes.h" @@ -53,9 +54,11 @@ public: FORWARD_SYMBOL_METHOD(getValue) FORWARD_SYMBOL_METHOD(getVirtualAddress) FORWARD_SYMBOL_METHOD(isVolatileType) -}; + std::unique_ptr<IPDBEnumLineNumbers> getLineNumbers() const; + uint32_t getCompilandId() const; +}; +} // namespace pdb } // namespace llvm -} #endif // LLVM_DEBUGINFO_PDB_PDBSYMBOLDATA_H diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h index c2f02ea6f126..05d585d25763 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H #define LLVM_DEBUGINFO_PDB_PDBSYMBOLFUNC_H +#include "IPDBLineNumber.h" #include "PDBSymbol.h" #include "PDBSymbolTypeFunctionSig.h" #include "PDBTypes.h" @@ -38,7 +39,9 @@ public: FORWARD_SYMBOL_METHOD(getAddressSection) FORWARD_SYMBOL_ID_METHOD(getClassParent) FORWARD_SYMBOL_METHOD(isCompilerGenerated) + FORWARD_SYMBOL_METHOD(isConstructorVirtualBase) FORWARD_SYMBOL_METHOD(isConstType) + FORWARD_SYMBOL_METHOD(isCxxReturnUdt) FORWARD_SYMBOL_METHOD(hasCustomCallingConvention) FORWARD_SYMBOL_METHOD(hasFarReturn) FORWARD_SYMBOL_METHOD(hasAlloca) @@ -76,6 +79,9 @@ public: FORWARD_SYMBOL_METHOD(getVirtualAddress) FORWARD_SYMBOL_METHOD(getVirtualBaseOffset) FORWARD_SYMBOL_METHOD(isVolatileType) + + std::unique_ptr<IPDBEnumLineNumbers> getLineNumbers() const; + uint32_t getCompilandId() const; }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h index c5ae3c51162c..ddbe7e58f183 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H #define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEENUM_H +#include "IPDBLineNumber.h" #include "PDBSymbol.h" #include "PDBSymbolTypeBuiltin.h" #include "PDBTypes.h" @@ -38,6 +39,7 @@ public: FORWARD_SYMBOL_METHOD(getLength) FORWARD_SYMBOL_ID_METHOD(getLexicalParent) FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSrcLineOnTypeDefn) FORWARD_SYMBOL_METHOD(isNested) FORWARD_SYMBOL_METHOD(hasOverloadedOperator) FORWARD_SYMBOL_METHOD(isPacked) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h index 8de54e70701d..abd4cf5effa2 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -31,6 +31,8 @@ public: void dumpRight(PDBSymDumper &Dumper) const override; void dumpArgList(raw_ostream &OS) const; + bool isCVarArgs() const; + FORWARD_SYMBOL_METHOD(getCallingConvention) FORWARD_SYMBOL_ID_METHOD(getClassParent) FORWARD_SYMBOL_ID_METHOD(getUnmodifiedType) diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h index c502d4e77afe..7612ebac31dd 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypePointer.h @@ -32,7 +32,11 @@ public: FORWARD_SYMBOL_METHOD(getLength) FORWARD_SYMBOL_ID_METHOD(getLexicalParent) FORWARD_SYMBOL_METHOD(isReference) + FORWARD_SYMBOL_METHOD(isRValueReference) + FORWARD_SYMBOL_METHOD(isPointerToDataMember) + FORWARD_SYMBOL_METHOD(isPointerToMemberFunction) FORWARD_SYMBOL_ID_METHOD_WITH_NAME(getType, getPointeeType) + FORWARD_SYMBOL_METHOD(isRestrictedType) FORWARD_SYMBOL_METHOD(isUnalignedType) FORWARD_SYMBOL_METHOD(isVolatileType) }; diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h index e9e7fe8c9865..e259b6dca3d5 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H #define LLVM_DEBUGINFO_PDB_PDBSYMBOLTYPEUDT_H +#include "IPDBLineNumber.h" #include "IPDBSession.h" #include "PDBSymbol.h" #include "PDBSymbolTypeBaseClass.h" @@ -45,6 +46,7 @@ public: FORWARD_SYMBOL_METHOD(getLength) FORWARD_SYMBOL_ID_METHOD(getLexicalParent) FORWARD_SYMBOL_METHOD(getName) + FORWARD_SYMBOL_METHOD(getSrcLineOnTypeDefn) FORWARD_SYMBOL_METHOD(isNested) FORWARD_SYMBOL_METHOD(hasOverloadedOperator) FORWARD_SYMBOL_METHOD(isPacked) @@ -53,6 +55,7 @@ public: FORWARD_SYMBOL_METHOD(isUnalignedType) FORWARD_SYMBOL_ID_METHOD(getVirtualTableShape) FORWARD_SYMBOL_METHOD(isVolatileType) + FORWARD_SYMBOL_METHOD(getAccess) }; } } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h index a6c6da37d1cc..da6cb1d26771 100644 --- a/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h +++ b/contrib/llvm/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -23,7 +23,9 @@ namespace llvm { namespace pdb { class IPDBDataStream; +class IPDBInjectedSource; class IPDBLineNumber; +class IPDBSectionContrib; class IPDBSourceFile; class IPDBTable; class PDBSymDumper; @@ -65,6 +67,8 @@ using IPDBEnumSourceFiles = IPDBEnumChildren<IPDBSourceFile>; using IPDBEnumDataStreams = IPDBEnumChildren<IPDBDataStream>; using IPDBEnumLineNumbers = IPDBEnumChildren<IPDBLineNumber>; using IPDBEnumTables = IPDBEnumChildren<IPDBTable>; +using IPDBEnumInjectedSources = IPDBEnumChildren<IPDBInjectedSource>; +using IPDBEnumSectionContribs = IPDBEnumChildren<IPDBSectionContrib>; /// Specifies which PDB reader implementation is to be used. Only a value /// of PDB_ReaderType::DIA is currently supported, but Native is in the works. @@ -96,13 +100,18 @@ enum PDB_NameSearchFlags { NS_CaseInsensitive = 0x2, NS_FileNameExtMatch = 0x4, NS_Regex = 0x8, - NS_UndecoratedName = 0x10 + NS_UndecoratedName = 0x10, + + // For backward compatibility. + NS_CaseInFileNameExt = NS_CaseInsensitive | NS_FileNameExtMatch, + NS_CaseRegex = NS_Regex | NS_CaseSensitive, + NS_CaseInRex = NS_Regex | NS_CaseInsensitive }; /// Specifies the hash algorithm that a source file from a PDB was hashed with. /// This corresponds to the CV_SourceChksum_t enumeration and are documented /// here: https://msdn.microsoft.com/en-us/library/e96az21x.aspx -enum class PDB_Checksum { None = 0, MD5 = 1, SHA1 = 2 }; +enum class PDB_Checksum { None = 0, MD5 = 1, SHA1 = 2, SHA256 = 3 }; /// These values correspond to the CV_CPU_TYPE_e enumeration, and are documented /// here: https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx @@ -133,6 +142,13 @@ enum class PDB_Machine { WceMipsV2 = 0x169 }; +enum class PDB_SourceCompression { + None, + RunLengthEncoded, + Huffman, + LZ, +}; + /// These values correspond to the CV_call_e enumeration, and are documented /// at the following locations: /// https://msdn.microsoft.com/en-us/library/b2fc64ek.aspx @@ -209,6 +225,7 @@ enum class PDB_LocType { IlRel, MetaData, Constant, + RegRelAliasIndir, Max }; @@ -218,11 +235,24 @@ enum class PDB_UdtType { Struct, Class, Union, Interface }; /// These values correspond to the StackFrameTypeEnum enumeration, and are /// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx. -enum class PDB_StackFrameType { FPO, KernelTrap, KernelTSS, EBP, FrameData }; +enum class PDB_StackFrameType : uint16_t { + FPO, + KernelTrap, + KernelTSS, + EBP, + FrameData, + Unknown = 0xffff +}; -/// These values correspond to the StackFrameTypeEnum enumeration, and are -/// documented here: https://msdn.microsoft.com/en-us/library/bc5207xw.aspx. -enum class PDB_MemoryType { Code, Data, Stack, HeapCode }; +/// These values correspond to the MemoryTypeEnum enumeration, and are +/// documented here: https://msdn.microsoft.com/en-us/library/ms165609.aspx. +enum class PDB_MemoryType : uint16_t { + Code, + Data, + Stack, + HeapCode, + Any = 0xffff +}; /// These values correspond to the Basictype enumeration, and are documented /// here: https://msdn.microsoft.com/en-us/library/4szdtzc3.aspx @@ -244,13 +274,15 @@ enum class PDB_BuiltinType { Complex = 28, Bitfield = 29, BSTR = 30, - HResult = 31 + HResult = 31, + Char16 = 32, + Char32 = 33 }; /// These values correspond to the flags that can be combined to control the /// return of an undecorated name for a C++ decorated name, and are documented /// here: https://msdn.microsoft.com/en-us/library/kszfk0fs.aspx -enum PDB_UndnameFlags: uint32_t { +enum PDB_UndnameFlags : uint32_t { Undname_Complete = 0x0, Undname_NoLeadingUnderscores = 0x1, Undname_NoMsKeywords = 0x2, diff --git a/contrib/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/contrib/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h index 6480aef109c6..289148f569db 100644 --- a/contrib/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h +++ b/contrib/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h @@ -90,11 +90,11 @@ private: const ObjectFile *Obj, const std::string &ArchName); - /// \brief Returns pair of pointers to object and debug object. + /// Returns pair of pointers to object and debug object. Expected<ObjectPair> getOrCreateObjectPair(const std::string &Path, const std::string &ArchName); - /// \brief Return a pointer to object file at specified path, for a specified + /// Return a pointer to object file at specified path, for a specified /// architecture (e.g. if path refers to a Mach-O universal binary, only one /// object file from it will be returned). Expected<ObjectFile *> getOrCreateObject(const std::string &Path, @@ -102,14 +102,14 @@ private: std::map<std::string, std::unique_ptr<SymbolizableModule>> Modules; - /// \brief Contains cached results of getOrCreateObjectPair(). + /// Contains cached results of getOrCreateObjectPair(). std::map<std::pair<std::string, std::string>, ObjectPair> ObjectPairForPathArch; - /// \brief Contains parsed binary for each path, or parsing error. + /// Contains parsed binary for each path, or parsing error. std::map<std::string, OwningBinary<Binary>> BinaryForPath; - /// \brief Parsed object file for path/architecture pair, where "path" refers + /// Parsed object file for path/architecture pair, where "path" refers /// to Mach-O universal binary. std::map<std::pair<std::string, std::string>, std::unique_ptr<ObjectFile>> ObjectForUBPathAndArch; diff --git a/contrib/llvm/include/llvm/Demangle/Demangle.h b/contrib/llvm/include/llvm/Demangle/Demangle.h index d2eb56b39f9b..df7753f23b87 100644 --- a/contrib/llvm/include/llvm/Demangle/Demangle.h +++ b/contrib/llvm/include/llvm/Demangle/Demangle.h @@ -16,13 +16,73 @@ namespace llvm { /// The mangled_name is demangled into buf and returned. If the buffer is not /// large enough, realloc is used to expand it. /// -/// The *status will be set to -/// unknown_error: -4 -/// invalid_args: -3 -/// invalid_mangled_name: -2 -/// memory_alloc_failure: -1 -/// success: 0 +/// The *status will be set to a value from the following enumeration +enum : int { + demangle_unknown_error = -4, + demangle_invalid_args = -3, + demangle_invalid_mangled_name = -2, + demangle_memory_alloc_failure = -1, + demangle_success = 0, +}; char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n, int *status); -} +char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n, + int *status); + +/// "Partial" demangler. This supports demangling a string into an AST +/// (typically an intermediate stage in itaniumDemangle) and querying certain +/// properties or partially printing the demangled name. +struct ItaniumPartialDemangler { + ItaniumPartialDemangler(); + + ItaniumPartialDemangler(ItaniumPartialDemangler &&Other); + ItaniumPartialDemangler &operator=(ItaniumPartialDemangler &&Other); + + /// Demangle into an AST. Subsequent calls to the rest of the member functions + /// implicitly operate on the AST this produces. + /// \return true on error, false otherwise + bool partialDemangle(const char *MangledName); + + /// Just print the entire mangled name into Buf. Buf and N behave like the + /// second and third parameters to itaniumDemangle. + char *finishDemangle(char *Buf, size_t *N) const; + + /// Get the base name of a function. This doesn't include trailing template + /// arguments, ie for "a::b<int>" this function returns "b". + char *getFunctionBaseName(char *Buf, size_t *N) const; + + /// Get the context name for a function. For "a::b::c", this function returns + /// "a::b". + char *getFunctionDeclContextName(char *Buf, size_t *N) const; + + /// Get the entire name of this function. + char *getFunctionName(char *Buf, size_t *N) const; + + /// Get the parameters for this function. + char *getFunctionParameters(char *Buf, size_t *N) const; + char *getFunctionReturnType(char *Buf, size_t *N) const; + + /// If this function has any any cv or reference qualifiers. These imply that + /// the function is a non-static member function. + bool hasFunctionQualifiers() const; + + /// If this symbol describes a constructor or destructor. + bool isCtorOrDtor() const; + + /// If this symbol describes a function. + bool isFunction() const; + + /// If this symbol describes a variable. + bool isData() const; + + /// If this symbol is a <special-name>. These are generally implicitly + /// generated by the implementation, such as vtables and typeinfo names. + bool isSpecialName() const; + + ~ItaniumPartialDemangler(); +private: + void *RootNode; + void *Context; +}; +} // namespace llvm diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h index 77c23b46d320..b61cb24fa5fb 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -60,7 +60,7 @@ class ObjectFile; } // end namespace object -/// \brief Helper class for helping synchronize access to the global address map +/// Helper class for helping synchronize access to the global address map /// table. Access to this class should be serialized under a mutex. class ExecutionEngineState { public: @@ -86,7 +86,7 @@ public: return GlobalAddressReverseMap; } - /// \brief Erase an entry from the mapping table. + /// Erase an entry from the mapping table. /// /// \returns The address that \p ToUnmap was happed to. uint64_t RemoveMapping(StringRef Name); @@ -94,7 +94,7 @@ public: using FunctionCreator = std::function<void *(const std::string &)>; -/// \brief Abstract interface for implementation execution of LLVM modules, +/// Abstract interface for implementation execution of LLVM modules, /// designed to support both interpreter and just-in-time (JIT) compiler /// implementations. class ExecutionEngine { @@ -137,17 +137,15 @@ protected: virtual char *getMemoryForGV(const GlobalVariable *GV); static ExecutionEngine *(*MCJITCtor)( - std::unique_ptr<Module> M, - std::string *ErrorStr, - std::shared_ptr<MCJITMemoryManager> MM, - std::shared_ptr<JITSymbolResolver> SR, - std::unique_ptr<TargetMachine> TM); + std::unique_ptr<Module> M, std::string *ErrorStr, + std::shared_ptr<MCJITMemoryManager> MM, + std::shared_ptr<LegacyJITSymbolResolver> SR, + std::unique_ptr<TargetMachine> TM); static ExecutionEngine *(*OrcMCJITReplacementCtor)( - std::string *ErrorStr, - std::shared_ptr<MCJITMemoryManager> MM, - std::shared_ptr<JITSymbolResolver> SR, - std::unique_ptr<TargetMachine> TM); + std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MM, + std::shared_ptr<LegacyJITSymbolResolver> SR, + std::unique_ptr<TargetMachine> TM); static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M, std::string *ErrorStr); @@ -532,7 +530,7 @@ private: std::string *ErrorStr; CodeGenOpt::Level OptLevel; std::shared_ptr<MCJITMemoryManager> MemMgr; - std::shared_ptr<JITSymbolResolver> Resolver; + std::shared_ptr<LegacyJITSymbolResolver> Resolver; TargetOptions Options; Optional<Reloc::Model> RelocModel; Optional<CodeModel::Model> CMModel; @@ -571,8 +569,7 @@ public: EngineBuilder& setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM); - EngineBuilder& - setSymbolResolver(std::unique_ptr<JITSymbolResolver> SR); + EngineBuilder &setSymbolResolver(std::unique_ptr<LegacyJITSymbolResolver> SR); /// setErrorStr - Set the error string to write to on error. This option /// defaults to NULL. @@ -637,7 +634,7 @@ public: return *this; } - // \brief Use OrcMCJITReplacement instead of MCJIT. Off by default. + // Use OrcMCJITReplacement instead of MCJIT. Off by default. void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) { this->UseOrcMCJITReplacement = UseOrcMCJITReplacement; } @@ -645,7 +642,7 @@ public: void setEmulatedTLS(bool EmulatedTLS) { this->EmulatedTLS = EmulatedTLS; } - + TargetMachine *selectTarget(); /// selectTarget - Pick a target either via -march or by guessing the native diff --git a/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h b/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h index ff7840f00a44..1ce772ccde95 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/JITEventListener.h @@ -15,9 +15,11 @@ #ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H #define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H +#include "llvm-c/ExecutionEngine.h" #include "llvm/Config/llvm-config.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/Support/CBindingWrapping.h" #include <cstdint> #include <vector> @@ -115,10 +117,21 @@ public: } #endif // USE_OPROFILE +#if LLVM_USE_PERF + static JITEventListener *createPerfJITEventListener(); +#else + static JITEventListener *createPerfJITEventListener() + { + return nullptr; + } +#endif // USE_PERF + private: virtual void anchor(); }; +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITEventListener, LLVMJITEventListenerRef) + } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H diff --git a/contrib/llvm/include/llvm/ExecutionEngine/JITSymbol.h b/contrib/llvm/include/llvm/ExecutionEngine/JITSymbol.h index 933b3ea8e13d..53037c3dbc72 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/JITSymbol.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/JITSymbol.h @@ -19,8 +19,11 @@ #include <cstddef> #include <cstdint> #include <functional> +#include <map> +#include <set> #include <string> +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" namespace llvm { @@ -33,10 +36,10 @@ class BasicSymbolRef; } // end namespace object -/// @brief Represents an address in the target process's address space. +/// Represents an address in the target process's address space. using JITTargetAddress = uint64_t; -/// @brief Flags for symbols in the JIT. +/// Flags for symbols in the JIT. class JITSymbolFlags { public: using UnderlyingType = uint8_t; @@ -48,55 +51,74 @@ public: Weak = 1U << 1, Common = 1U << 2, Absolute = 1U << 3, - Exported = 1U << 4 + Exported = 1U << 4, + Lazy = 1U << 5, + Materializing = 1U << 6 }; - /// @brief Default-construct a JITSymbolFlags instance. + static JITSymbolFlags stripTransientFlags(JITSymbolFlags Orig) { + return static_cast<FlagNames>(Orig.Flags & ~Lazy & ~Materializing); + } + + /// Default-construct a JITSymbolFlags instance. JITSymbolFlags() = default; - /// @brief Construct a JITSymbolFlags instance from the given flags. + /// Construct a JITSymbolFlags instance from the given flags. JITSymbolFlags(FlagNames Flags) : Flags(Flags) {} - /// @brief Construct a JITSymbolFlags instance from the given flags and target + /// Construct a JITSymbolFlags instance from the given flags and target /// flags. JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags) : Flags(Flags), TargetFlags(TargetFlags) {} - /// @brief Return true if there was an error retrieving this symbol. + /// Return true if there was an error retrieving this symbol. bool hasError() const { return (Flags & HasError) == HasError; } - /// @brief Returns true if the Weak flag is set. + /// Returns true if this is a lazy symbol. + /// This flag is used internally by the JIT APIs to track + /// materialization states. + bool isLazy() const { return Flags & Lazy; } + + /// Returns true if this symbol is in the process of being + /// materialized. + bool isMaterializing() const { return Flags & Materializing; } + + /// Returns true if this symbol is fully materialized. + /// (i.e. neither lazy, nor materializing). + bool isMaterialized() const { return !(Flags & (Lazy | Materializing)); } + + /// Returns true if the Weak flag is set. bool isWeak() const { return (Flags & Weak) == Weak; } - /// @brief Returns true if the Common flag is set. + /// Returns true if the Common flag is set. bool isCommon() const { return (Flags & Common) == Common; } - /// @brief Returns true if the symbol isn't weak or common. - bool isStrongDefinition() const { + /// Returns true if the symbol isn't weak or common. + bool isStrong() const { return !isWeak() && !isCommon(); } - /// @brief Returns true if the Exported flag is set. + /// Returns true if the Exported flag is set. bool isExported() const { return (Flags & Exported) == Exported; } - /// @brief Implicitly convert to the underlying flags type. + /// Implicitly convert to the underlying flags type. operator UnderlyingType&() { return Flags; } - /// @brief Implicitly convert to the underlying flags type. + /// Implicitly convert to the underlying flags type. operator const UnderlyingType&() const { return Flags; } - /// @brief Return a reference to the target-specific flags. + /// Return a reference to the target-specific flags. TargetFlagsType& getTargetFlags() { return TargetFlags; } - /// @brief Return a reference to the target-specific flags. + /// Return a reference to the target-specific flags. const TargetFlagsType& getTargetFlags() const { return TargetFlags; } /// Construct a JITSymbolFlags value based on the flags of the given global @@ -112,7 +134,7 @@ private: TargetFlagsType TargetFlags = 0; }; -/// @brief ARM-specific JIT symbol flags. +/// ARM-specific JIT symbol flags. /// FIXME: This should be moved into a target-specific header. class ARMJITSymbolFlags { public: @@ -131,54 +153,59 @@ private: JITSymbolFlags::TargetFlagsType Flags = 0; }; -/// @brief Represents a symbol that has been evaluated to an address already. +/// Represents a symbol that has been evaluated to an address already. class JITEvaluatedSymbol { public: - /// @brief Create a 'null' symbol. + JITEvaluatedSymbol() = default; + + /// Create a 'null' symbol. JITEvaluatedSymbol(std::nullptr_t) {} - /// @brief Create a symbol for the given address and flags. + /// Create a symbol for the given address and flags. JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags) : Address(Address), Flags(Flags) {} - /// @brief An evaluated symbol converts to 'true' if its address is non-zero. + /// An evaluated symbol converts to 'true' if its address is non-zero. explicit operator bool() const { return Address != 0; } - /// @brief Return the address of this symbol. + /// Return the address of this symbol. JITTargetAddress getAddress() const { return Address; } - /// @brief Return the flags for this symbol. + /// Return the flags for this symbol. JITSymbolFlags getFlags() const { return Flags; } + /// Set the flags for this symbol. + void setFlags(JITSymbolFlags Flags) { this->Flags = std::move(Flags); } + private: JITTargetAddress Address = 0; JITSymbolFlags Flags; }; -/// @brief Represents a symbol in the JIT. +/// Represents a symbol in the JIT. class JITSymbol { public: using GetAddressFtor = std::function<Expected<JITTargetAddress>()>; - /// @brief Create a 'null' symbol, used to represent a "symbol not found" + /// Create a 'null' symbol, used to represent a "symbol not found" /// result from a successful (non-erroneous) lookup. JITSymbol(std::nullptr_t) : CachedAddr(0) {} - /// @brief Create a JITSymbol representing an error in the symbol lookup + /// Create a JITSymbol representing an error in the symbol lookup /// process (e.g. a network failure during a remote lookup). JITSymbol(Error Err) : Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {} - /// @brief Create a symbol for a definition with a known address. + /// Create a symbol for a definition with a known address. JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags) : CachedAddr(Addr), Flags(Flags) {} - /// @brief Construct a JITSymbol from a JITEvaluatedSymbol. + /// Construct a JITSymbol from a JITEvaluatedSymbol. JITSymbol(JITEvaluatedSymbol Sym) : CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {} - /// @brief Create a symbol for a definition that doesn't have a known address + /// Create a symbol for a definition that doesn't have a known address /// yet. /// @param GetAddress A functor to materialize a definition (fixing the /// address) on demand. @@ -218,19 +245,19 @@ public: CachedAddr.~JITTargetAddress(); } - /// @brief Returns true if the symbol exists, false otherwise. + /// Returns true if the symbol exists, false otherwise. explicit operator bool() const { return !Flags.hasError() && (CachedAddr || GetAddress); } - /// @brief Move the error field value out of this JITSymbol. + /// Move the error field value out of this JITSymbol. Error takeError() { if (Flags.hasError()) return std::move(Err); return Error::success(); } - /// @brief Get the address of the symbol in the target address space. Returns + /// Get the address of the symbol in the target address space. Returns /// '0' if the symbol does not exist. Expected<JITTargetAddress> getAddress() { assert(!Flags.hasError() && "getAddress called on error value"); @@ -256,11 +283,49 @@ private: JITSymbolFlags Flags; }; -/// \brief Symbol resolution. +/// Symbol resolution interface. +/// +/// Allows symbol flags and addresses to be looked up by name. +/// Symbol queries are done in bulk (i.e. you request resolution of a set of +/// symbols, rather than a single one) to reduce IPC overhead in the case of +/// remote JITing, and expose opportunities for parallel compilation. class JITSymbolResolver { public: + using LookupSet = std::set<StringRef>; + using LookupResult = std::map<StringRef, JITEvaluatedSymbol>; + using LookupFlagsResult = std::map<StringRef, JITSymbolFlags>; + virtual ~JITSymbolResolver() = default; + /// Returns the fully resolved address and flags for each of the given + /// symbols. + /// + /// This method will return an error if any of the given symbols can not be + /// resolved, or if the resolution process itself triggers an error. + virtual Expected<LookupResult> lookup(const LookupSet &Symbols) = 0; + + /// Returns the symbol flags for each of the given symbols. + /// + /// This method does NOT return an error if any of the given symbols is + /// missing. Instead, that symbol will be left out of the result map. + virtual Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) = 0; + +private: + virtual void anchor(); +}; + +/// Legacy symbol resolution interface. +class LegacyJITSymbolResolver : public JITSymbolResolver { +public: + /// Performs lookup by, for each symbol, first calling + /// findSymbolInLogicalDylib and if that fails calling + /// findSymbol. + Expected<LookupResult> lookup(const LookupSet &Symbols) final; + + /// Performs flags lookup by calling findSymbolInLogicalDylib and + /// returning the flags value for that symbol. + Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) final; + /// This method returns the address of the specified symbol if it exists /// within the logical dynamic library represented by this JITSymbolResolver. /// Unlike findSymbol, queries through this interface should return addresses diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index a961992c2147..8bd21a0e3dd6 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -22,6 +22,8 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/Layer.h" +#include "llvm/ExecutionEngine/Orc/Legacy.h" #include "llvm/ExecutionEngine/Orc/OrcError.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/Attributes.h" @@ -56,7 +58,47 @@ class Value; namespace orc { -/// @brief Compile-on-demand layer. +class ExtractingIRMaterializationUnit; + +class CompileOnDemandLayer2 : public IRLayer { + friend class ExtractingIRMaterializationUnit; + +public: + /// Builder for IndirectStubsManagers. + using IndirectStubsManagerBuilder = + std::function<std::unique_ptr<IndirectStubsManager>()>; + + using GetAvailableContextFunction = std::function<LLVMContext &()>; + + CompileOnDemandLayer2(ExecutionSession &ES, IRLayer &BaseLayer, + JITCompileCallbackManager &CCMgr, + IndirectStubsManagerBuilder BuildIndirectStubsManager, + GetAvailableContextFunction GetAvailableContext); + + Error add(VSO &V, VModuleKey K, std::unique_ptr<Module> M) override; + + void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr<Module> M) override; + +private: + using StubManagersMap = + std::map<const VSO *, std::unique_ptr<IndirectStubsManager>>; + + IndirectStubsManager &getStubsManager(const VSO &V); + + void emitExtractedFunctionsModule(MaterializationResponsibility R, + std::unique_ptr<Module> M); + + mutable std::mutex CODLayerMutex; + + IRLayer &BaseLayer; + JITCompileCallbackManager &CCMgr; + IndirectStubsManagerBuilder BuildIndirectStubsManager; + StubManagersMap StubsMgrs; + GetAvailableContextFunction GetAvailableContext; +}; + +/// Compile-on-demand layer. /// /// When a module is added to this layer a stub is created for each of its /// function definitions. The stubs and other global values are immediately @@ -85,8 +127,6 @@ private: return LambdaMaterializer<MaterializerFtor>(std::move(M)); } - using BaseLayerModuleHandleT = typename BaseLayerT::ModuleHandleT; - // Provide type-erasure for the Modules and MemoryManagers. template <typename ResourceT> class ResourceOwner { @@ -138,18 +178,22 @@ private: }; struct LogicalDylib { - using SymbolResolverFtor = std::function<JITSymbol(const std::string&)>; - struct SourceModuleEntry { - std::shared_ptr<Module> SourceMod; + std::unique_ptr<Module> SourceMod; std::set<Function*> StubsToClone; }; using SourceModulesList = std::vector<SourceModuleEntry>; using SourceModuleHandle = typename SourceModulesList::size_type; - SourceModuleHandle - addSourceModule(std::shared_ptr<Module> M) { + LogicalDylib() = default; + + LogicalDylib(VModuleKey K, std::shared_ptr<SymbolResolver> BackingResolver, + std::unique_ptr<IndirectStubsMgrT> StubsMgr) + : K(std::move(K)), BackingResolver(std::move(BackingResolver)), + StubsMgr(std::move(StubsMgr)) {} + + SourceModuleHandle addSourceModule(std::unique_ptr<Module> M) { SourceModuleHandle H = SourceModules.size(); SourceModules.push_back(SourceModuleEntry()); SourceModules.back().SourceMod = std::move(M); @@ -168,8 +212,8 @@ private: bool ExportedSymbolsOnly) { if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly)) return Sym; - for (auto BLH : BaseLayerHandles) - if (auto Sym = BaseLayer.findSymbolIn(BLH, Name, ExportedSymbolsOnly)) + for (auto BLK : BaseLayerVModuleKeys) + if (auto Sym = BaseLayer.findSymbolIn(BLK, Name, ExportedSymbolsOnly)) return Sym; else if (auto Err = Sym.takeError()) return std::move(Err); @@ -177,91 +221,94 @@ private: } Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) { - for (auto &BLH : BaseLayerHandles) - if (auto Err = BaseLayer.removeModule(BLH)) + for (auto &BLK : BaseLayerVModuleKeys) + if (auto Err = BaseLayer.removeModule(BLK)) return Err; return Error::success(); } - std::shared_ptr<JITSymbolResolver> ExternalSymbolResolver; + VModuleKey K; + std::shared_ptr<SymbolResolver> BackingResolver; std::unique_ptr<IndirectStubsMgrT> StubsMgr; StaticGlobalRenamer StaticRenamer; SourceModulesList SourceModules; - std::vector<BaseLayerModuleHandleT> BaseLayerHandles; + std::vector<VModuleKey> BaseLayerVModuleKeys; }; - using LogicalDylibList = std::list<LogicalDylib>; - public: - /// @brief Handle to loaded module. - using ModuleHandleT = typename LogicalDylibList::iterator; - - /// @brief Module partitioning functor. + /// Module partitioning functor. using PartitioningFtor = std::function<std::set<Function*>(Function&)>; - /// @brief Builder for IndirectStubsManagers. + /// Builder for IndirectStubsManagers. using IndirectStubsManagerBuilderT = std::function<std::unique_ptr<IndirectStubsMgrT>()>; - /// @brief Construct a compile-on-demand layer instance. - CompileOnDemandLayer(BaseLayerT &BaseLayer, PartitioningFtor Partition, + using SymbolResolverGetter = + std::function<std::shared_ptr<SymbolResolver>(VModuleKey K)>; + + using SymbolResolverSetter = + std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>; + + /// Construct a compile-on-demand layer instance. + CompileOnDemandLayer(ExecutionSession &ES, BaseLayerT &BaseLayer, + SymbolResolverGetter GetSymbolResolver, + SymbolResolverSetter SetSymbolResolver, + PartitioningFtor Partition, CompileCallbackMgrT &CallbackMgr, IndirectStubsManagerBuilderT CreateIndirectStubsManager, bool CloneStubsIntoPartitions = true) - : BaseLayer(BaseLayer), Partition(std::move(Partition)), - CompileCallbackMgr(CallbackMgr), + : ES(ES), BaseLayer(BaseLayer), + GetSymbolResolver(std::move(GetSymbolResolver)), + SetSymbolResolver(std::move(SetSymbolResolver)), + Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr), CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)), CloneStubsIntoPartitions(CloneStubsIntoPartitions) {} ~CompileOnDemandLayer() { // FIXME: Report error on log. while (!LogicalDylibs.empty()) - consumeError(removeModule(LogicalDylibs.begin())); + consumeError(removeModule(LogicalDylibs.begin()->first)); } - /// @brief Add a module to the compile-on-demand layer. - Expected<ModuleHandleT> - addModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) { - - LogicalDylibs.push_back(LogicalDylib()); - auto &LD = LogicalDylibs.back(); - LD.ExternalSymbolResolver = std::move(Resolver); - LD.StubsMgr = CreateIndirectStubsManager(); + /// Add a module to the compile-on-demand layer. + Error addModule(VModuleKey K, std::unique_ptr<Module> M) { - // Process each of the modules in this module set. - if (auto Err = addLogicalModule(LD, std::move(M))) - return std::move(Err); + assert(!LogicalDylibs.count(K) && "VModuleKey K already in use"); + auto I = LogicalDylibs.insert( + LogicalDylibs.end(), + std::make_pair(K, LogicalDylib(K, GetSymbolResolver(K), + CreateIndirectStubsManager()))); - return std::prev(LogicalDylibs.end()); + return addLogicalModule(I->second, std::move(M)); } - /// @brief Add extra modules to an existing logical module. - Error addExtraModule(ModuleHandleT H, std::shared_ptr<Module> M) { - return addLogicalModule(*H, std::move(M)); + /// Add extra modules to an existing logical module. + Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) { + return addLogicalModule(LogicalDylibs[K], std::move(M)); } - /// @brief Remove the module represented by the given handle. + /// Remove the module represented by the given key. /// /// This will remove all modules in the layers below that were derived from - /// the module represented by H. - Error removeModule(ModuleHandleT H) { - auto Err = H->removeModulesFromBaseLayer(BaseLayer); - LogicalDylibs.erase(H); + /// the module represented by K. + Error removeModule(VModuleKey K) { + auto I = LogicalDylibs.find(K); + assert(I != LogicalDylibs.end() && "VModuleKey K not valid here"); + auto Err = I->second.removeModulesFromBaseLayer(BaseLayer); + LogicalDylibs.erase(I); return Err; } - /// @brief Search for the given named symbol. + /// Search for the given named symbol. /// @param Name The name of the symbol to search for. /// @param ExportedSymbolsOnly If true, search only for exported symbols. /// @return A handle for the given named symbol, if it exists. JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { - for (auto LDI = LogicalDylibs.begin(), LDE = LogicalDylibs.end(); - LDI != LDE; ++LDI) { - if (auto Sym = LDI->StubsMgr->findStub(Name, ExportedSymbolsOnly)) + for (auto &KV : LogicalDylibs) { + if (auto Sym = KV.second.StubsMgr->findStub(Name, ExportedSymbolsOnly)) return Sym; - if (auto Sym = findSymbolIn(LDI, Name, ExportedSymbolsOnly)) + if (auto Sym = findSymbolIn(KV.first, Name, ExportedSymbolsOnly)) return Sym; else if (auto Err = Sym.takeError()) return std::move(Err); @@ -269,14 +316,15 @@ public: return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); } - /// @brief Get the address of a symbol provided by this layer, or some layer + /// Get the address of a symbol provided by this layer, or some layer /// below this one. - JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name, + JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, bool ExportedSymbolsOnly) { - return H->findSymbol(BaseLayer, Name, ExportedSymbolsOnly); + assert(LogicalDylibs.count(K) && "VModuleKey K is not valid here"); + return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly); } - /// @brief Update the stub for the given function to point at FnBodyAddr. + /// Update the stub for the given function to point at FnBodyAddr. /// This can be used to support re-optimization. /// @return true if the function exists and the stub is updated, false /// otherwise. @@ -302,15 +350,14 @@ public: } private: - - Error addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcMPtr) { + Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) { // Rename all static functions / globals to $static.X : // This will unique the names across all modules in the logical dylib, // simplifying symbol lookup. LD.StaticRenamer.rename(*SrcMPtr); - // Bump the linkage and rename any anonymous/privote members in SrcM to + // Bump the linkage and rename any anonymous/private members in SrcM to // ensure that everything will resolve properly after we partition SrcM. makeAllSymbolsExternallyAccessible(*SrcMPtr); @@ -343,22 +390,21 @@ private: // Create a callback, associate it with the stub for the function, // and set the compile action to compile the partition containing the // function. - if (auto CCInfoOrErr = CompileCallbackMgr.getCompileCallback()) { - auto &CCInfo = *CCInfoOrErr; + auto CompileAction = [this, &LD, LMId, &F]() -> JITTargetAddress { + if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F)) + return *FnImplAddrOrErr; + else { + // FIXME: Report error, return to 'abort' or something similar. + consumeError(FnImplAddrOrErr.takeError()); + return 0; + } + }; + if (auto CCAddr = + CompileCallbackMgr.getCompileCallback(std::move(CompileAction))) StubInits[MangledName] = - std::make_pair(CCInfo.getAddress(), - JITSymbolFlags::fromGlobalValue(F)); - CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress { - if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F)) - return *FnImplAddrOrErr; - else { - // FIXME: Report error, return to 'abort' or something similar. - consumeError(FnImplAddrOrErr.takeError()); - return 0; - } - }); - } else - return CCInfoOrErr.takeError(); + std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F)); + else + return CCAddr.takeError(); } if (auto Err = LD.StubsMgr->createStubs(StubInits)) @@ -396,9 +442,8 @@ private: // Initializers may refer to functions declared (but not defined) in this // module. Build a materializer to clone decls on demand. - Error MaterializerErrors = Error::success(); auto Materializer = createLambdaMaterializer( - [&LD, &GVsM, &MaterializerErrors](Value *V) -> Value* { + [&LD, &GVsM](Value *V) -> Value* { if (auto *F = dyn_cast<Function>(V)) { // Decls in the original module just get cloned. if (F->isDeclaration()) @@ -410,18 +455,8 @@ private: const DataLayout &DL = GVsM->getDataLayout(); std::string FName = mangle(F->getName(), DL); unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType()); - JITTargetAddress StubAddr = 0; - - // Get the address for the stub. If we encounter an error while - // doing so, stash it in the MaterializerErrors variable and use a - // null address as a placeholder. - if (auto StubSym = LD.StubsMgr->findStub(FName, false)) { - if (auto StubAddrOrErr = StubSym.getAddress()) - StubAddr = *StubAddrOrErr; - else - MaterializerErrors = joinErrors(std::move(MaterializerErrors), - StubAddrOrErr.takeError()); - } + JITTargetAddress StubAddr = + LD.StubsMgr->findStub(FName, false).getAddress(); ConstantInt *StubAddrCI = ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr)); @@ -450,29 +485,58 @@ private: NewA->setAliasee(cast<Constant>(Init)); } - if (MaterializerErrors) - return MaterializerErrors; - // Build a resolver for the globals module and add it to the base layer. - auto GVsResolver = createLambdaResolver( - [this, &LD](const std::string &Name) -> JITSymbol { - if (auto Sym = LD.StubsMgr->findStub(Name, false)) - return Sym; - if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name); + auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol { + if (auto Sym = LD.StubsMgr->findStub(Name, false)) + return Sym; + + if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); + + return nullptr; + }; + + auto GVsResolver = createSymbolResolver( + [&LD, LegacyLookup](const SymbolNameSet &Symbols) { + auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup); + + if (!SymbolFlags) { + logAllUnhandledErrors(SymbolFlags.takeError(), errs(), + "CODLayer/GVsResolver flags lookup failed: "); + return SymbolFlagsMap(); + } + + if (SymbolFlags->size() == Symbols.size()) + return *SymbolFlags; + + SymbolNameSet NotFoundViaLegacyLookup; + for (auto &S : Symbols) + if (!SymbolFlags->count(S)) + NotFoundViaLegacyLookup.insert(S); + auto SymbolFlags2 = + LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup); + + for (auto &KV : SymbolFlags2) + (*SymbolFlags)[KV.first] = std::move(KV.second); + + return *SymbolFlags; }, - [&LD](const std::string &Name) { - return LD.ExternalSymbolResolver->findSymbol(Name); + [this, &LD, + LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query, + SymbolNameSet Symbols) { + auto NotFoundViaLegacyLookup = + lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup); + return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup); }); - if (auto GVsHOrErr = - BaseLayer.addModule(std::move(GVsM), std::move(GVsResolver))) - LD.BaseLayerHandles.push_back(*GVsHOrErr); - else - return GVsHOrErr.takeError(); + SetSymbolResolver(LD.K, std::move(GVsResolver)); + + if (auto Err = BaseLayer.addModule(LD.K, std::move(GVsM))) + return Err; + + LD.BaseLayerVModuleKeys.push_back(LD.K); return Error::success(); } @@ -501,11 +565,11 @@ private: JITTargetAddress CalledAddr = 0; auto Part = Partition(F); - if (auto PartHOrErr = emitPartition(LD, LMId, Part)) { - auto &PartH = *PartHOrErr; + if (auto PartKeyOrErr = emitPartition(LD, LMId, Part)) { + auto &PartKey = *PartKeyOrErr; for (auto *SubF : Part) { std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout()); - if (auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false)) { + if (auto FnBodySym = BaseLayer.findSymbolIn(PartKey, FnName, false)) { if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) { JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr; @@ -526,15 +590,15 @@ private: llvm_unreachable("Function not emitted for partition"); } - LD.BaseLayerHandles.push_back(PartH); + LD.BaseLayerVModuleKeys.push_back(PartKey); } else - return PartHOrErr.takeError(); + return PartKeyOrErr.takeError(); return CalledAddr; } template <typename PartitionT> - Expected<BaseLayerModuleHandleT> + Expected<VModuleKey> emitPartition(LogicalDylib &LD, typename LogicalDylib::SourceModuleHandle LMId, const PartitionT &Part) { @@ -596,28 +660,62 @@ private: for (auto *F : Part) moveFunctionBody(*F, VMap, &Materializer); + auto K = ES.allocateVModule(); + + auto LegacyLookup = [this, &LD](const std::string &Name) -> JITSymbol { + return LD.findSymbol(BaseLayer, Name, false); + }; + // Create memory manager and symbol resolver. - auto Resolver = createLambdaResolver( - [this, &LD](const std::string &Name) -> JITSymbol { - if (auto Sym = LD.findSymbol(BaseLayer, Name, false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name); + auto Resolver = createSymbolResolver( + [&LD, LegacyLookup](const SymbolNameSet &Symbols) { + auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup); + if (!SymbolFlags) { + logAllUnhandledErrors(SymbolFlags.takeError(), errs(), + "CODLayer/SubResolver flags lookup failed: "); + return SymbolFlagsMap(); + } + + if (SymbolFlags->size() == Symbols.size()) + return *SymbolFlags; + + SymbolNameSet NotFoundViaLegacyLookup; + for (auto &S : Symbols) + if (!SymbolFlags->count(S)) + NotFoundViaLegacyLookup.insert(S); + + auto SymbolFlags2 = + LD.BackingResolver->lookupFlags(NotFoundViaLegacyLookup); + + for (auto &KV : SymbolFlags2) + (*SymbolFlags)[KV.first] = std::move(KV.second); + + return *SymbolFlags; }, - [&LD](const std::string &Name) { - return LD.ExternalSymbolResolver->findSymbol(Name); + [this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q, + SymbolNameSet Symbols) { + auto NotFoundViaLegacyLookup = + lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup); + return LD.BackingResolver->lookup(Q, + std::move(NotFoundViaLegacyLookup)); }); + SetSymbolResolver(K, std::move(Resolver)); + + if (auto Err = BaseLayer.addModule(std::move(K), std::move(M))) + return std::move(Err); - return BaseLayer.addModule(std::move(M), std::move(Resolver)); + return K; } + ExecutionSession &ES; BaseLayerT &BaseLayer; + SymbolResolverGetter GetSymbolResolver; + SymbolResolverSetter SetSymbolResolver; PartitioningFtor Partition; CompileCallbackMgrT &CompileCallbackMgr; IndirectStubsManagerBuilderT CreateIndirectStubsManager; - LogicalDylibList LogicalDylibs; + std::map<VModuleKey, LogicalDylib> LogicalDylibs; bool CloneStubsIntoPartitions; }; diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h index b9f7d6accc30..213a59124c85 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/CompileUtils.h @@ -16,13 +16,14 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ExecutionEngine/ObjectCache.h" -#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h" +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SmallVectorMemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include <algorithm> @@ -35,45 +36,51 @@ class Module; namespace orc { -/// @brief Simple compile functor: Takes a single IR module and returns an -/// ObjectFile. +/// Simple compile functor: Takes a single IR module and returns an ObjectFile. +/// This compiler supports a single compilation thread and LLVMContext only. +/// For multithreaded compilation, use MultiThreadedSimpleCompiler below. class SimpleCompiler { public: + using CompileResult = std::unique_ptr<MemoryBuffer>; - using CompileResult = object::OwningBinary<object::ObjectFile>; - - /// @brief Construct a simple compile functor with the given target. + /// Construct a simple compile functor with the given target. SimpleCompiler(TargetMachine &TM, ObjectCache *ObjCache = nullptr) : TM(TM), ObjCache(ObjCache) {} - /// @brief Set an ObjectCache to query before compiling. + /// Set an ObjectCache to query before compiling. void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; } - /// @brief Compile a Module to an ObjectFile. + /// Compile a Module to an ObjectFile. CompileResult operator()(Module &M) { CompileResult CachedObject = tryToLoadFromObjectCache(M); - if (CachedObject.getBinary()) + if (CachedObject) return CachedObject; SmallVector<char, 0> ObjBufferSV; - raw_svector_ostream ObjStream(ObjBufferSV); - legacy::PassManager PM; - MCContext *Ctx; - if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) - llvm_unreachable("Target does not support MC emission."); - PM.run(M); - std::unique_ptr<MemoryBuffer> ObjBuffer( - new ObjectMemoryBuffer(std::move(ObjBufferSV))); - Expected<std::unique_ptr<object::ObjectFile>> Obj = + { + raw_svector_ostream ObjStream(ObjBufferSV); + + legacy::PassManager PM; + MCContext *Ctx; + if (TM.addPassesToEmitMC(PM, Ctx, ObjStream)) + llvm_unreachable("Target does not support MC emission."); + PM.run(M); + } + + auto ObjBuffer = + llvm::make_unique<SmallVectorMemoryBuffer>(std::move(ObjBufferSV)); + auto Obj = object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); + if (Obj) { notifyObjectCompiled(M, *ObjBuffer); - return CompileResult(std::move(*Obj), std::move(ObjBuffer)); + return std::move(ObjBuffer); } + // TODO: Actually report errors helpfully. consumeError(Obj.takeError()); - return CompileResult(nullptr, nullptr); + return nullptr; } private: @@ -82,19 +89,7 @@ private: if (!ObjCache) return CompileResult(); - std::unique_ptr<MemoryBuffer> ObjBuffer = ObjCache->getObject(&M); - if (!ObjBuffer) - return CompileResult(); - - Expected<std::unique_ptr<object::ObjectFile>> Obj = - object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); - if (!Obj) { - // TODO: Actually report errors helpfully. - consumeError(Obj.takeError()); - return CompileResult(); - } - - return CompileResult(std::move(*Obj), std::move(ObjBuffer)); + return ObjCache->getObject(&M); } void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer) { @@ -106,6 +101,29 @@ private: ObjectCache *ObjCache = nullptr; }; +/// A thread-safe version of SimpleCompiler. +/// +/// This class creates a new TargetMachine and SimpleCompiler instance for each +/// compile. +class MultiThreadedSimpleCompiler { +public: + MultiThreadedSimpleCompiler(JITTargetMachineBuilder JTMB, + ObjectCache *ObjCache = nullptr) + : JTMB(std::move(JTMB)), ObjCache(ObjCache) {} + + void setObjectCache(ObjectCache *ObjCache) { this->ObjCache = ObjCache; } + + std::unique_ptr<MemoryBuffer> operator()(Module &M) { + auto TM = cantFail(JTMB.createTargetMachine()); + SimpleCompiler C(*TM, ObjCache); + return C(M); + } + +private: + JITTargetMachineBuilder JTMB; + ObjectCache *ObjCache = nullptr; +}; + } // end namespace orc } // end namespace llvm diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Core.h new file mode 100644 index 000000000000..fd03687cfc21 --- /dev/null +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Core.h @@ -0,0 +1,779 @@ +//===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains core ORC APIs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H +#define LLVM_EXECUTIONENGINE_ORC_CORE_H + +#include "llvm/ADT/BitmaskEnum.h" +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h" +#include "llvm/IR/Module.h" + +#include <list> +#include <map> +#include <memory> +#include <set> +#include <vector> + +namespace llvm { +namespace orc { + +// Forward declare some classes. +class AsynchronousSymbolQuery; +class ExecutionSession; +class MaterializationUnit; +class MaterializationResponsibility; +class VSO; + +/// VModuleKey provides a unique identifier (allocated and managed by +/// ExecutionSessions) for a module added to the JIT. +using VModuleKey = uint64_t; + +/// A set of symbol names (represented by SymbolStringPtrs for +// efficiency). +using SymbolNameSet = std::set<SymbolStringPtr>; + +/// Render a SymbolNameSet to an ostream. +raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols); + +/// A map from symbol names (as SymbolStringPtrs) to JITSymbols +/// (address/flags pairs). +using SymbolMap = std::map<SymbolStringPtr, JITEvaluatedSymbol>; + +/// Render a SymbolMap to an ostream. +raw_ostream &operator<<(raw_ostream &OS, const SymbolMap &Symbols); + +/// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags. +using SymbolFlagsMap = std::map<SymbolStringPtr, JITSymbolFlags>; + +/// Render a SymbolMap to an ostream. +raw_ostream &operator<<(raw_ostream &OS, const SymbolFlagsMap &Symbols); + +/// A base class for materialization failures that allows the failing +/// symbols to be obtained for logging. +using SymbolDependenceMap = std::map<VSO *, SymbolNameSet>; + +/// Render a SymbolDependendeMap. +raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps); + +/// A list of VSO pointers. +using VSOList = std::vector<VSO *>; + +/// Render a VSOList. +raw_ostream &operator<<(raw_ostream &OS, const VSOList &VSOs); + +/// Callback to notify client that symbols have been resolved. +using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>; + +/// Callback to notify client that symbols are ready for execution. +using SymbolsReadyCallback = std::function<void(Error)>; + +/// Callback to register the dependencies for a given query. +using RegisterDependenciesFunction = + std::function<void(const SymbolDependenceMap &)>; + +/// This can be used as the value for a RegisterDependenciesFunction if there +/// are no dependants to register with. +extern RegisterDependenciesFunction NoDependenciesToRegister; + +/// Used to notify a VSO that the given set of symbols failed to materialize. +class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> { +public: + static char ID; + + FailedToMaterialize(SymbolNameSet Symbols); + std::error_code convertToErrorCode() const override; + void log(raw_ostream &OS) const override; + const SymbolNameSet &getSymbols() const { return Symbols; } + +private: + SymbolNameSet Symbols; +}; + +/// Used to notify clients when symbols can not be found during a lookup. +class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> { +public: + static char ID; + + SymbolsNotFound(SymbolNameSet Symbols); + std::error_code convertToErrorCode() const override; + void log(raw_ostream &OS) const override; + const SymbolNameSet &getSymbols() const { return Symbols; } + +private: + SymbolNameSet Symbols; +}; + +/// Tracks responsibility for materialization, and mediates interactions between +/// MaterializationUnits and VSOs. +/// +/// An instance of this class is passed to MaterializationUnits when their +/// materialize method is called. It allows MaterializationUnits to resolve and +/// finalize symbols, or abandon materialization by notifying any unmaterialized +/// symbols of an error. +class MaterializationResponsibility { + friend class MaterializationUnit; +public: + MaterializationResponsibility(MaterializationResponsibility &&) = default; + MaterializationResponsibility & + operator=(MaterializationResponsibility &&) = default; + + /// Destruct a MaterializationResponsibility instance. In debug mode + /// this asserts that all symbols being tracked have been either + /// finalized or notified of an error. + ~MaterializationResponsibility(); + + /// Returns the target VSO that these symbols are being materialized + /// into. + VSO &getTargetVSO() const { return V; } + + /// Returns the symbol flags map for this responsibility instance. + SymbolFlagsMap getSymbols() { return SymbolFlags; } + + /// Returns the names of any symbols covered by this + /// MaterializationResponsibility object that have queries pending. This + /// information can be used to return responsibility for unrequested symbols + /// back to the VSO via the delegate method. + SymbolNameSet getRequestedSymbols(); + + /// Resolves the given symbols. Individual calls to this method may + /// resolve a subset of the symbols, but all symbols must have been + /// resolved prior to calling finalize. + void resolve(const SymbolMap &Symbols); + + /// Finalizes all symbols tracked by this instance. + void finalize(); + + /// Adds new symbols to the VSO and this responsibility instance. + /// VSO entries start out in the materializing state. + /// + /// This method can be used by materialization units that want to add + /// additional symbols at materialization time (e.g. stubs, compile + /// callbacks, metadata). + Error defineMaterializing(const SymbolFlagsMap &SymbolFlags); + + /// Notify all unfinalized symbols that an error has occurred. + /// This will remove all symbols covered by this MaterializationResponsibilty + /// from V, and send an error to any queries waiting on these symbols. + void failMaterialization(); + + /// Transfers responsibility to the given MaterializationUnit for all + /// symbols defined by that MaterializationUnit. This allows + /// materializers to break up work based on run-time information (e.g. + /// by introspecting which symbols have actually been looked up and + /// materializing only those). + void replace(std::unique_ptr<MaterializationUnit> MU); + + /// Delegates responsibility for the given symbols to the returned + /// materialization responsibility. Useful for breaking up work between + /// threads, or different kinds of materialization processes. + MaterializationResponsibility delegate(const SymbolNameSet &Symbols); + + void addDependencies(const SymbolStringPtr &Name, + const SymbolDependenceMap &Dependencies); + + /// Add dependencies that apply to all symbols covered by this instance. + void addDependenciesForAll(const SymbolDependenceMap &Dependencies); + +private: + /// Create a MaterializationResponsibility for the given VSO and + /// initial symbols. + MaterializationResponsibility(VSO &V, SymbolFlagsMap SymbolFlags); + + VSO &V; + SymbolFlagsMap SymbolFlags; +}; + +/// A MaterializationUnit represents a set of symbol definitions that can +/// be materialized as a group, or individually discarded (when +/// overriding definitions are encountered). +/// +/// MaterializationUnits are used when providing lazy definitions of symbols to +/// VSOs. The VSO will call materialize when the address of a symbol is +/// requested via the lookup method. The VSO will call discard if a stronger +/// definition is added or already present. +class MaterializationUnit { +public: + MaterializationUnit(SymbolFlagsMap InitalSymbolFlags) + : SymbolFlags(std::move(InitalSymbolFlags)) {} + + virtual ~MaterializationUnit() {} + + /// Return the set of symbols that this source provides. + const SymbolFlagsMap &getSymbols() const { return SymbolFlags; } + + /// Called by materialization dispatchers (see + /// ExecutionSession::DispatchMaterializationFunction) to trigger + /// materialization of this MaterializationUnit. + void doMaterialize(VSO &V) { + materialize(MaterializationResponsibility(V, std::move(SymbolFlags))); + } + + /// Called by VSOs to notify MaterializationUnits that the given symbol has + /// been overridden. + void doDiscard(const VSO &V, SymbolStringPtr Name) { + SymbolFlags.erase(Name); + discard(V, std::move(Name)); + } + +protected: + SymbolFlagsMap SymbolFlags; + +private: + virtual void anchor(); + + /// Implementations of this method should materialize all symbols + /// in the materialzation unit, except for those that have been + /// previously discarded. + virtual void materialize(MaterializationResponsibility R) = 0; + + /// Implementations of this method should discard the given symbol + /// from the source (e.g. if the source is an LLVM IR Module and the + /// symbol is a function, delete the function body or mark it available + /// externally). + virtual void discard(const VSO &V, SymbolStringPtr Name) = 0; +}; + +using MaterializationUnitList = + std::vector<std::unique_ptr<MaterializationUnit>>; + +/// A MaterializationUnit implementation for pre-existing absolute symbols. +/// +/// All symbols will be resolved and marked ready as soon as the unit is +/// materialized. +class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit { +public: + AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols); + +private: + void materialize(MaterializationResponsibility R) override; + void discard(const VSO &V, SymbolStringPtr Name) override; + static SymbolFlagsMap extractFlags(const SymbolMap &Symbols); + + SymbolMap Symbols; +}; + +/// Create an AbsoluteSymbolsMaterializationUnit with the given symbols. +/// Useful for inserting absolute symbols into a VSO. E.g.: +/// \code{.cpp} +/// VSO &V = ...; +/// SymbolStringPtr Foo = ...; +/// JITEvaluatedSymbol FooSym = ...; +/// if (auto Err = V.define(absoluteSymbols({{Foo, FooSym}}))) +/// return Err; +/// \endcode +/// +inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit> +absoluteSymbols(SymbolMap Symbols) { + return llvm::make_unique<AbsoluteSymbolsMaterializationUnit>( + std::move(Symbols)); +} + +struct SymbolAliasMapEntry { + SymbolAliasMapEntry() = default; + SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags) + : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {} + + SymbolStringPtr Aliasee; + JITSymbolFlags AliasFlags; +}; + +/// A map of Symbols to (Symbol, Flags) pairs. +using SymbolAliasMap = std::map<SymbolStringPtr, SymbolAliasMapEntry>; + +/// A materialization unit for symbol aliases. Allows existing symbols to be +/// aliased with alternate flags. +class ReExportsMaterializationUnit : public MaterializationUnit { +public: + /// SourceVSO is allowed to be nullptr, in which case the source VSO is + /// taken to be whatever VSO these definitions are materialized in. This + /// is useful for defining aliases within a VSO. + /// + /// Note: Care must be taken that no sets of aliases form a cycle, as such + /// a cycle will result in a deadlock when any symbol in the cycle is + /// resolved. + ReExportsMaterializationUnit(VSO *SourceVSO, SymbolAliasMap Aliases); + +private: + void materialize(MaterializationResponsibility R) override; + void discard(const VSO &V, SymbolStringPtr Name) override; + static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases); + + VSO *SourceVSO = nullptr; + SymbolAliasMap Aliases; +}; + +/// Create a ReExportsMaterializationUnit with the given aliases. +/// Useful for defining symbol aliases.: E.g., given a VSO V containing symbols +/// "foo" and "bar", we can define aliases "baz" (for "foo") and "qux" (for +/// "bar") with: +/// \code{.cpp} +/// SymbolStringPtr Baz = ...; +/// SymbolStringPtr Qux = ...; +/// if (auto Err = V.define(symbolAliases({ +/// {Baz, { Foo, JITSymbolFlags::Exported }}, +/// {Qux, { Bar, JITSymbolFlags::Weak }}})) +/// return Err; +/// \endcode +inline std::unique_ptr<ReExportsMaterializationUnit> +symbolAliases(SymbolAliasMap Aliases) { + return llvm::make_unique<ReExportsMaterializationUnit>(nullptr, + std::move(Aliases)); +} + +/// Create a materialization unit for re-exporting symbols from another VSO +/// with alternative names/flags. +inline std::unique_ptr<ReExportsMaterializationUnit> +reexports(VSO &SourceV, SymbolAliasMap Aliases) { + return llvm::make_unique<ReExportsMaterializationUnit>(&SourceV, + std::move(Aliases)); +} + +/// Build a SymbolAliasMap for the common case where you want to re-export +/// symbols from another VSO with the same linkage/flags. +Expected<SymbolAliasMap> +buildSimpleReexportsAliasMap(VSO &SourceV, const SymbolNameSet &Symbols); + +/// Base utilities for ExecutionSession. +class ExecutionSessionBase { + // FIXME: Remove this when we remove the old ORC layers. + friend class VSO; + +public: + /// For reporting errors. + using ErrorReporter = std::function<void(Error)>; + + /// For dispatching MaterializationUnit::materialize calls. + using DispatchMaterializationFunction = + std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>; + + /// Construct an ExecutionSessionBase. + /// + /// SymbolStringPools may be shared between ExecutionSessions. + ExecutionSessionBase(std::shared_ptr<SymbolStringPool> SSP = nullptr) + : SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {} + + /// Returns the SymbolStringPool for this ExecutionSession. + SymbolStringPool &getSymbolStringPool() const { return *SSP; } + + /// Run the given lambda with the session mutex locked. + template <typename Func> auto runSessionLocked(Func &&F) -> decltype(F()) { + std::lock_guard<std::recursive_mutex> Lock(SessionMutex); + return F(); + } + + /// Set the error reporter function. + ExecutionSessionBase &setErrorReporter(ErrorReporter ReportError) { + this->ReportError = std::move(ReportError); + return *this; + } + + /// Set the materialization dispatch function. + ExecutionSessionBase &setDispatchMaterialization( + DispatchMaterializationFunction DispatchMaterialization) { + this->DispatchMaterialization = std::move(DispatchMaterialization); + return *this; + } + + /// Report a error for this execution session. + /// + /// Unhandled errors can be sent here to log them. + void reportError(Error Err) { ReportError(std::move(Err)); } + + /// Allocate a module key for a new module to add to the JIT. + VModuleKey allocateVModule() { return ++LastKey; } + + /// Return a module key to the ExecutionSession so that it can be + /// re-used. This should only be done once all resources associated + /// with the original key have been released. + void releaseVModule(VModuleKey Key) { /* FIXME: Recycle keys */ + } + + void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err); + + using LegacyAsyncLookupFunction = std::function<SymbolNameSet( + std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>; + + /// A legacy lookup function for JITSymbolResolverAdapter. + /// Do not use -- this will be removed soon. + Expected<SymbolMap> + legacyLookup(ExecutionSessionBase &ES, LegacyAsyncLookupFunction AsyncLookup, + SymbolNameSet Names, bool WaiUntilReady, + RegisterDependenciesFunction RegisterDependencies); + + /// Search the given VSO list for the given symbols. + /// + /// + /// The OnResolve callback will be called once all requested symbols are + /// resolved, or if an error occurs prior to resolution. + /// + /// The OnReady callback will be called once all requested symbols are ready, + /// or if an error occurs after resolution but before all symbols are ready. + /// + /// If all symbols are found, the RegisterDependencies function will be called + /// while the session lock is held. This gives clients a chance to register + /// dependencies for on the queried symbols for any symbols they are + /// materializing (if a MaterializationResponsibility instance is present, + /// this can be implemented by calling + /// MaterializationResponsibility::addDependencies). If there are no + /// dependenant symbols for this query (e.g. it is being made by a top level + /// client to get an address to call) then the value NoDependenciesToRegister + /// can be used. + void lookup(const VSOList &VSOs, const SymbolNameSet &Symbols, + SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady, + RegisterDependenciesFunction RegisterDependencies); + + /// Blocking version of lookup above. Returns the resolved symbol map. + /// If WaitUntilReady is true (the default), will not return until all + /// requested symbols are ready (or an error occurs). If WaitUntilReady is + /// false, will return as soon as all requested symbols are resolved, + /// or an error occurs. If WaitUntilReady is false and an error occurs + /// after resolution, the function will return a success value, but the + /// error will be reported via reportErrors. + Expected<SymbolMap> lookup(const VSOList &VSOs, const SymbolNameSet &Symbols, + RegisterDependenciesFunction RegisterDependencies, + bool WaitUntilReady = true); + + /// Materialize the given unit. + void dispatchMaterialization(VSO &V, + std::unique_ptr<MaterializationUnit> MU) { + DispatchMaterialization(V, std::move(MU)); + } + +private: + static void logErrorsToStdErr(Error Err) { + logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: "); + } + + static void + materializeOnCurrentThread(VSO &V, std::unique_ptr<MaterializationUnit> MU) { + MU->doMaterialize(V); + } + + void runOutstandingMUs(); + + mutable std::recursive_mutex SessionMutex; + std::shared_ptr<SymbolStringPool> SSP; + VModuleKey LastKey = 0; + ErrorReporter ReportError = logErrorsToStdErr; + DispatchMaterializationFunction DispatchMaterialization = + materializeOnCurrentThread; + + // FIXME: Remove this (and runOutstandingMUs) once the linking layer works + // with callbacks from asynchronous queries. + mutable std::recursive_mutex OutstandingMUsMutex; + std::vector<std::pair<VSO *, std::unique_ptr<MaterializationUnit>>> + OutstandingMUs; +}; + +/// A symbol query that returns results via a callback when results are +/// ready. +/// +/// makes a callback when all symbols are available. +class AsynchronousSymbolQuery { + friend class ExecutionSessionBase; + friend class VSO; + +public: + + /// Create a query for the given symbols, notify-resolved and + /// notify-ready callbacks. + AsynchronousSymbolQuery(const SymbolNameSet &Symbols, + SymbolsResolvedCallback NotifySymbolsResolved, + SymbolsReadyCallback NotifySymbolsReady); + + /// Set the resolved symbol information for the given symbol name. + void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym); + + /// Returns true if all symbols covered by this query have been + /// resolved. + bool isFullyResolved() const { return NotYetResolvedCount == 0; } + + /// Call the NotifySymbolsResolved callback. + /// + /// This should only be called if all symbols covered by the query have been + /// resolved. + void handleFullyResolved(); + + /// Notify the query that a requested symbol is ready for execution. + void notifySymbolReady(); + + /// Returns true if all symbols covered by this query are ready. + bool isFullyReady() const { return NotYetReadyCount == 0; } + + /// Calls the NotifySymbolsReady callback. + /// + /// This should only be called if all symbols covered by this query are ready. + void handleFullyReady(); + +private: + void addQueryDependence(VSO &V, SymbolStringPtr Name); + + void removeQueryDependence(VSO &V, const SymbolStringPtr &Name); + + bool canStillFail(); + + void handleFailed(Error Err); + + void detach(); + + SymbolsResolvedCallback NotifySymbolsResolved; + SymbolsReadyCallback NotifySymbolsReady; + SymbolDependenceMap QueryRegistrations; + SymbolMap ResolvedSymbols; + size_t NotYetResolvedCount; + size_t NotYetReadyCount; +}; + +/// A symbol table that supports asynchoronous symbol queries. +/// +/// Represents a virtual shared object. Instances can not be copied or moved, so +/// their addresses may be used as keys for resource management. +/// VSO state changes must be made via an ExecutionSession to guarantee that +/// they are synchronized with respect to other VSO operations. +class VSO { + friend class AsynchronousSymbolQuery; + friend class ExecutionSession; + friend class ExecutionSessionBase; + friend class MaterializationResponsibility; +public: + using FallbackDefinitionGeneratorFunction = + std::function<SymbolNameSet(VSO &Parent, const SymbolNameSet &Names)>; + + using AsynchronousSymbolQuerySet = + std::set<std::shared_ptr<AsynchronousSymbolQuery>>; + + VSO(const VSO &) = delete; + VSO &operator=(const VSO &) = delete; + VSO(VSO &&) = delete; + VSO &operator=(VSO &&) = delete; + + /// Get the name for this VSO. + const std::string &getName() const { return VSOName; } + + /// Get a reference to the ExecutionSession for this VSO. + ExecutionSessionBase &getExecutionSession() const { return ES; } + + /// Set a fallback defenition generator. If set, lookup and lookupFlags will + /// pass the unresolved symbols set to the fallback definition generator, + /// allowing it to add a new definition to the VSO. + void setFallbackDefinitionGenerator( + FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator) { + this->FallbackDefinitionGenerator = std::move(FallbackDefinitionGenerator); + } + + /// Set the search order to be used when fixing up definitions in VSO. + /// This will replace the previous search order, and apply to any symbol + /// resolutions made for definitions in this VSO after the call to + /// setSearchOrder (even if the definition itself was added before the + /// call). + /// + /// If SearchThisVSOFirst is set, which by default it is, then this VSO will + /// add itself to the beginning of the SearchOrder (Clients should *not* + /// put this VSO in the list in this case, to avoid redundant lookups). + /// + /// If SearchThisVSOFirst is false then the search order will be used as + /// given. The main motivation for this feature is to support deliberate + /// shadowing of symbols in this VSO by a facade VSO. For example, the + /// facade may resolve function names to stubs, and the stubs may compile + /// lazily by looking up symbols in this dylib. Adding the facade dylib + /// as the first in the search order (instead of this dylib) ensures that + /// definitions within this dylib resolve to the lazy-compiling stubs, + /// rather than immediately materializing the definitions in this dylib. + void setSearchOrder(VSOList NewSearchOrder, bool SearchThisVSOFirst = true); + + /// Add the given VSO to the search order for definitions in this VSO. + void addToSearchOrder(VSO &V); + + /// Replace OldV with NewV in the search order if OldV is present. Otherwise + /// this operation is a no-op. + void replaceInSearchOrder(VSO &OldV, VSO &NewV); + + /// Remove the given VSO from the search order for this VSO if it is + /// present. Otherwise this operation is a no-op. + void removeFromSearchOrder(VSO &V); + + /// Do something with the search order (run under the session lock). + template <typename Func> + auto withSearchOrderDo(Func &&F) + -> decltype(F(std::declval<const VSOList &>())) { + return ES.runSessionLocked([&]() { return F(SearchOrder); }); + } + + /// Define all symbols provided by the materialization unit to be part + /// of the given VSO. + template <typename UniquePtrToMaterializationUnit> + typename std::enable_if< + std::is_convertible< + typename std::decay<UniquePtrToMaterializationUnit>::type, + std::unique_ptr<MaterializationUnit>>::value, + Error>::type + define(UniquePtrToMaterializationUnit &&MU) { + return ES.runSessionLocked([&, this]() -> Error { + assert(MU && "Can't define with a null MU"); + + if (auto Err = defineImpl(*MU)) + return Err; + + /// defineImpl succeeded. + auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU)); + for (auto &KV : UMI->MU->getSymbols()) + UnmaterializedInfos[KV.first] = UMI; + + return Error::success(); + }); + } + + /// Search the given VSO for the symbols in Symbols. If found, store + /// the flags for each symbol in Flags. Returns any unresolved symbols. + SymbolFlagsMap lookupFlags(const SymbolNameSet &Names); + + /// Dump current VSO state to OS. + void dump(raw_ostream &OS); + + /// FIXME: Remove this when we remove the old ORC layers. + /// Search the given VSOs in order for the symbols in Symbols. Results + /// (once they become available) will be returned via the given Query. + /// + /// If any symbol is not found then the unresolved symbols will be returned, + /// and the query will not be applied. The Query is not failed and can be + /// re-used in a subsequent lookup once the symbols have been added, or + /// manually failed. + SymbolNameSet legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, + SymbolNameSet Names); + +private: + using AsynchronousSymbolQueryList = + std::vector<std::shared_ptr<AsynchronousSymbolQuery>>; + + struct UnmaterializedInfo { + UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU) + : MU(std::move(MU)) {} + + std::unique_ptr<MaterializationUnit> MU; + }; + + using UnmaterializedInfosMap = + std::map<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>; + + struct MaterializingInfo { + AsynchronousSymbolQueryList PendingQueries; + SymbolDependenceMap Dependants; + SymbolDependenceMap UnfinalizedDependencies; + bool IsFinalized = false; + }; + + using MaterializingInfosMap = std::map<SymbolStringPtr, MaterializingInfo>; + + using LookupImplActionFlags = enum { + None = 0, + NotifyFullyResolved = 1 << 0U, + NotifyFullyReady = 1 << 1U, + LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady) + }; + + VSO(ExecutionSessionBase &ES, std::string Name); + + Error defineImpl(MaterializationUnit &MU); + + SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags, + const SymbolNameSet &Names); + + void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q, + SymbolNameSet &Unresolved, MaterializationUnitList &MUs); + + void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, + SymbolNameSet &Unresolved, MaterializationUnitList &MUs); + + LookupImplActionFlags + lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q, + std::vector<std::unique_ptr<MaterializationUnit>> &MUs, + SymbolNameSet &Unresolved); + + void detachQueryHelper(AsynchronousSymbolQuery &Q, + const SymbolNameSet &QuerySymbols); + + void transferFinalizedNodeDependencies(MaterializingInfo &DependantMI, + const SymbolStringPtr &DependantName, + MaterializingInfo &FinalizedMI); + + Error defineMaterializing(const SymbolFlagsMap &SymbolFlags); + + void replace(std::unique_ptr<MaterializationUnit> MU); + + SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags); + + void addDependencies(const SymbolStringPtr &Name, + const SymbolDependenceMap &Dependants); + + void resolve(const SymbolMap &Resolved); + + void finalize(const SymbolFlagsMap &Finalized); + + void notifyFailed(const SymbolNameSet &FailedSymbols); + + ExecutionSessionBase &ES; + std::string VSOName; + SymbolMap Symbols; + UnmaterializedInfosMap UnmaterializedInfos; + MaterializingInfosMap MaterializingInfos; + FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator; + VSOList SearchOrder; +}; + +/// An ExecutionSession represents a running JIT program. +class ExecutionSession : public ExecutionSessionBase { +public: + using ErrorReporter = std::function<void(Error)>; + + using DispatchMaterializationFunction = + std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> MU)>; + + /// Construct an ExecutionEngine. + /// + /// SymbolStringPools may be shared between ExecutionSessions. + ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr) + : ExecutionSessionBase(std::move(SSP)) {} + + /// Add a new VSO to this ExecutionSession. + VSO &createVSO(std::string Name); + +private: + std::vector<std::unique_ptr<VSO>> VSOs; +}; + +/// Look up the given names in the given VSOs. +/// VSOs will be searched in order and no VSO pointer may be null. +/// All symbols must be found within the given VSOs or an error +/// will be returned. +Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names); + +/// Look up a symbol by searching a list of VSOs. +Expected<JITEvaluatedSymbol> lookup(const VSOList &VSOs, SymbolStringPtr Name); + +/// Mangles symbol names then uniques them in the context of an +/// ExecutionSession. +class MangleAndInterner { +public: + MangleAndInterner(ExecutionSessionBase &ES, const DataLayout &DL); + SymbolStringPtr operator()(StringRef Name); + +private: + ExecutionSessionBase &ES; + const DataLayout &DL; +}; + +} // End namespace orc +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_CORE_H diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h index d9b45c6a1e29..e27f6e1e2cd6 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -17,13 +17,16 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/iterator_range.h" #include "llvm/ExecutionEngine/JITSymbol.h" -#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/ExecutionEngine/Orc/OrcError.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Target/TargetOptions.h" #include <algorithm> #include <cstdint> #include <string> -#include <vector> #include <utility> +#include <vector> namespace llvm { @@ -31,18 +34,58 @@ class ConstantArray; class GlobalVariable; class Function; class Module; +class TargetMachine; class Value; namespace orc { -/// @brief This iterator provides a convenient way to iterate over the elements +/// A utility class for building TargetMachines for JITs. +class JITTargetMachineBuilder { +public: + JITTargetMachineBuilder(Triple TT); + static Expected<JITTargetMachineBuilder> detectHost(); + Expected<std::unique_ptr<TargetMachine>> createTargetMachine(); + + JITTargetMachineBuilder &setArch(std::string Arch) { + this->Arch = std::move(Arch); + return *this; + } + JITTargetMachineBuilder &setCPU(std::string CPU) { + this->CPU = std::move(CPU); + return *this; + } + JITTargetMachineBuilder &setRelocationModel(Optional<Reloc::Model> RM) { + this->RM = std::move(RM); + return *this; + } + JITTargetMachineBuilder &setCodeModel(Optional<CodeModel::Model> CM) { + this->CM = std::move(CM); + return *this; + } + JITTargetMachineBuilder & + addFeatures(const std::vector<std::string> &FeatureVec); + SubtargetFeatures &getFeatures() { return Features; } + TargetOptions &getOptions() { return Options; } + +private: + Triple TT; + std::string Arch; + std::string CPU; + SubtargetFeatures Features; + TargetOptions Options; + Optional<Reloc::Model> RM; + Optional<CodeModel::Model> CM; + CodeGenOpt::Level OptLevel = CodeGenOpt::Default; +}; + +/// This iterator provides a convenient way to iterate over the elements /// of an llvm.global_ctors/llvm.global_dtors instance. /// /// The easiest way to get hold of instances of this class is to use the /// getConstructors/getDestructors functions. class CtorDtorIterator { public: - /// @brief Accessor for an element of the global_ctors/global_dtors array. + /// Accessor for an element of the global_ctors/global_dtors array. /// /// This class provides a read-only view of the element with any casts on /// the function stripped away. @@ -55,23 +98,23 @@ public: Value *Data; }; - /// @brief Construct an iterator instance. If End is true then this iterator + /// Construct an iterator instance. If End is true then this iterator /// acts as the end of the range, otherwise it is the beginning. CtorDtorIterator(const GlobalVariable *GV, bool End); - /// @brief Test iterators for equality. + /// Test iterators for equality. bool operator==(const CtorDtorIterator &Other) const; - /// @brief Test iterators for inequality. + /// Test iterators for inequality. bool operator!=(const CtorDtorIterator &Other) const; - /// @brief Pre-increment iterator. + /// Pre-increment iterator. CtorDtorIterator& operator++(); - /// @brief Post-increment iterator. + /// Post-increment iterator. CtorDtorIterator operator++(int); - /// @brief Dereference iterator. The resulting value provides a read-only view + /// Dereference iterator. The resulting value provides a read-only view /// of this element of the global_ctors/global_dtors list. Element operator*() const; @@ -80,32 +123,31 @@ private: unsigned I; }; -/// @brief Create an iterator range over the entries of the llvm.global_ctors +/// Create an iterator range over the entries of the llvm.global_ctors /// array. iterator_range<CtorDtorIterator> getConstructors(const Module &M); -/// @brief Create an iterator range over the entries of the llvm.global_ctors +/// Create an iterator range over the entries of the llvm.global_ctors /// array. iterator_range<CtorDtorIterator> getDestructors(const Module &M); -/// @brief Convenience class for recording constructor/destructor names for +/// Convenience class for recording constructor/destructor names for /// later execution. template <typename JITLayerT> class CtorDtorRunner { public: - /// @brief Construct a CtorDtorRunner for the given range using the given + /// Construct a CtorDtorRunner for the given range using the given /// name mangling function. - CtorDtorRunner(std::vector<std::string> CtorDtorNames, - typename JITLayerT::ModuleHandleT H) - : CtorDtorNames(std::move(CtorDtorNames)), H(H) {} + CtorDtorRunner(std::vector<std::string> CtorDtorNames, VModuleKey K) + : CtorDtorNames(std::move(CtorDtorNames)), K(K) {} - /// @brief Run the recorded constructors/destructors through the given JIT + /// Run the recorded constructors/destructors through the given JIT /// layer. Error runViaLayer(JITLayerT &JITLayer) const { using CtorDtorTy = void (*)(); - for (const auto &CtorDtorName : CtorDtorNames) - if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) { + for (const auto &CtorDtorName : CtorDtorNames) { + if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) { if (auto AddrOrErr = CtorDtorSym.getAddress()) { CtorDtorTy CtorDtor = reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr)); @@ -118,15 +160,30 @@ public: else return make_error<JITSymbolNotFound>(CtorDtorName); } + } return Error::success(); } private: std::vector<std::string> CtorDtorNames; - typename JITLayerT::ModuleHandleT H; + orc::VModuleKey K; }; -/// @brief Support class for static dtor execution. For hosted (in-process) JITs +class CtorDtorRunner2 { +public: + CtorDtorRunner2(VSO &V) : V(V) {} + void add(iterator_range<CtorDtorIterator> CtorDtors); + Error run(); + +private: + using CtorDtorList = std::vector<SymbolStringPtr>; + using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>; + + VSO &V; + CtorDtorPriorityMap CtorDtorsByPriority; +}; + +/// Support class for static dtor execution. For hosted (in-process) JITs /// only! /// /// If a __cxa_atexit function isn't found C++ programs that use static @@ -141,7 +198,26 @@ private: /// the client determines that destructors should be run (generally at JIT /// teardown or after a return from main), the runDestructors method should be /// called. -class LocalCXXRuntimeOverrides { +class LocalCXXRuntimeOverridesBase { +public: + /// Run any destructors recorded by the overriden __cxa_atexit function + /// (CXAAtExitOverride). + void runDestructors(); + +protected: + template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) { + return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P)); + } + + using DestructorPtr = void (*)(void *); + using CXXDestructorDataPair = std::pair<DestructorPtr, void *>; + using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>; + CXXDestructorDataPairList DSOHandleOverride; + static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, + void *DSOHandle); +}; + +class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { public: /// Create a runtime-overrides class. template <typename MangleFtorT> @@ -158,32 +234,38 @@ public: return nullptr; } - /// Run any destructors recorded by the overriden __cxa_atexit function - /// (CXAAtExitOverride). - void runDestructors(); - private: - template <typename PtrTy> - JITTargetAddress toTargetAddress(PtrTy* P) { - return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P)); - } - void addOverride(const std::string &Name, JITTargetAddress Addr) { CXXRuntimeOverrides.insert(std::make_pair(Name, Addr)); } StringMap<JITTargetAddress> CXXRuntimeOverrides; +}; - using DestructorPtr = void (*)(void *); - using CXXDestructorDataPair = std::pair<DestructorPtr, void *>; - using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>; - CXXDestructorDataPairList DSOHandleOverride; - static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, - void *DSOHandle); +class LocalCXXRuntimeOverrides2 : public LocalCXXRuntimeOverridesBase { +public: + Error enable(VSO &V, MangleAndInterner &Mangler); }; -} // end namespace orc +/// A utility class to expose symbols found via dlsym to the JIT. +/// +/// If an instance of this class is attached to a VSO as a fallback definition +/// generator, then any symbol found in the given DynamicLibrary that passes +/// the 'Allow' predicate will be added to the VSO. +class DynamicLibraryFallbackGenerator { +public: + using SymbolPredicate = std::function<bool(SymbolStringPtr)>; + DynamicLibraryFallbackGenerator(sys::DynamicLibrary Dylib, + const DataLayout &DL, SymbolPredicate Allow); + SymbolNameSet operator()(VSO &V, const SymbolNameSet &Names); +private: + sys::DynamicLibrary Dylib; + SymbolPredicate Allow; + char GlobalPrefix; +}; + +} // end namespace orc } // end namespace llvm #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h index 8a48c36f4141..a8a88d7cb2d2 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/GlobalMappingLayer.h @@ -27,7 +27,7 @@ class JITSymbolResolver; namespace orc { -/// @brief Global mapping layer. +/// Global mapping layer. /// /// This layer overrides the findSymbol method to first search a local symbol /// table that the client can define. It can be used to inject new symbol @@ -38,13 +38,13 @@ template <typename BaseLayerT> class GlobalMappingLayer { public: - /// @brief Handle to an added module. + /// Handle to an added module. using ModuleHandleT = typename BaseLayerT::ModuleHandleT; - /// @brief Construct an GlobalMappingLayer with the given BaseLayer + /// Construct an GlobalMappingLayer with the given BaseLayer GlobalMappingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} - /// @brief Add the given module to the JIT. + /// Add the given module to the JIT. /// @return A handle for the added modules. Expected<ModuleHandleT> addModule(std::shared_ptr<Module> M, @@ -52,20 +52,20 @@ public: return BaseLayer.addModule(std::move(M), std::move(Resolver)); } - /// @brief Remove the module set associated with the handle H. + /// Remove the module set associated with the handle H. Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); } - /// @brief Manually set the address to return for the given symbol. + /// Manually set the address to return for the given symbol. void setGlobalMapping(const std::string &Name, JITTargetAddress Addr) { SymbolTable[Name] = Addr; } - /// @brief Remove the given symbol from the global mapping. + /// Remove the given symbol from the global mapping. void eraseGlobalMapping(const std::string &Name) { SymbolTable.erase(Name); } - /// @brief Search for the given named symbol. + /// Search for the given named symbol. /// /// This method will first search the local symbol table, returning /// any symbol found there. If the symbol is not found in the local @@ -81,7 +81,7 @@ public: return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); } - /// @brief Get the address of the given symbol in the context of the of the + /// Get the address of the given symbol in the context of the of the /// module represented by the handle H. This call is forwarded to the /// base layer's implementation. /// @param H The handle for the module to search in. @@ -94,7 +94,7 @@ public: return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); } - /// @brief Immediately emit and finalize the module set represented by the + /// Immediately emit and finalize the module set represented by the /// given handle. /// @param H Handle for module set to emit/finalize. Error emitAndFinalize(ModuleHandleT H) { diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h index fadd334bed0f..ad6481548d59 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -16,7 +16,9 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Layer.h" #include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" #include <memory> #include <string> @@ -26,7 +28,30 @@ class Module; namespace orc { -/// @brief Eager IR compiling layer. +class IRCompileLayer2 : public IRLayer { +public: + using CompileFunction = + std::function<Expected<std::unique_ptr<MemoryBuffer>>(Module &)>; + + using NotifyCompiledFunction = + std::function<void(VModuleKey K, std::unique_ptr<Module>)>; + + IRCompileLayer2(ExecutionSession &ES, ObjectLayer &BaseLayer, + CompileFunction Compile); + + void setNotifyCompiled(NotifyCompiledFunction NotifyCompiled); + + void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr<Module> M) override; + +private: + mutable std::mutex IRLayerMutex; + ObjectLayer &BaseLayer; + CompileFunction Compile; + NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction(); +}; + +/// Eager IR compiling layer. /// /// This layer immediately compiles each IR module added via addModule to an /// object file and adds this module file to the layer below, which must @@ -34,36 +59,40 @@ namespace orc { template <typename BaseLayerT, typename CompileFtor> class IRCompileLayer { public: + /// Callback type for notifications when modules are compiled. + using NotifyCompiledCallback = + std::function<void(VModuleKey K, std::unique_ptr<Module>)>; - /// @brief Handle to a compiled module. - using ModuleHandleT = typename BaseLayerT::ObjHandleT; - - /// @brief Construct an IRCompileLayer with the given BaseLayer, which must + /// Construct an IRCompileLayer with the given BaseLayer, which must /// implement the ObjectLayer concept. - IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile) - : BaseLayer(BaseLayer), Compile(std::move(Compile)) {} + IRCompileLayer( + BaseLayerT &BaseLayer, CompileFtor Compile, + NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback()) + : BaseLayer(BaseLayer), Compile(std::move(Compile)), + NotifyCompiled(std::move(NotifyCompiled)) {} - /// @brief Get a reference to the compiler functor. + /// Get a reference to the compiler functor. CompileFtor& getCompiler() { return Compile; } - /// @brief Compile the module, and add the resulting object to the base layer - /// along with the given memory manager and symbol resolver. - /// - /// @return A handle for the added module. - Expected<ModuleHandleT> - addModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) { - using CompileResult = decltype(Compile(*M)); - auto Obj = std::make_shared<CompileResult>(Compile(*M)); - return BaseLayer.addObject(std::move(Obj), std::move(Resolver)); + /// (Re)set the NotifyCompiled callback. + void setNotifyCompiled(NotifyCompiledCallback NotifyCompiled) { + this->NotifyCompiled = std::move(NotifyCompiled); } - /// @brief Remove the module associated with the handle H. - Error removeModule(ModuleHandleT H) { - return BaseLayer.removeObject(H); + /// Compile the module, and add the resulting object to the base layer + /// along with the given memory manager and symbol resolver. + Error addModule(VModuleKey K, std::unique_ptr<Module> M) { + if (auto Err = BaseLayer.addObject(std::move(K), Compile(*M))) + return Err; + if (NotifyCompiled) + NotifyCompiled(std::move(K), std::move(M)); + return Error::success(); } - /// @brief Search for the given named symbol. + /// Remove the module associated with the VModuleKey K. + Error removeModule(VModuleKey K) { return BaseLayer.removeObject(K); } + + /// Search for the given named symbol. /// @param Name The name of the symbol to search for. /// @param ExportedSymbolsOnly If true, search only for exported symbols. /// @return A handle for the given named symbol, if it exists. @@ -71,29 +100,28 @@ public: return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); } - /// @brief Get the address of the given symbol in compiled module represented + /// Get the address of the given symbol in compiled module represented /// by the handle H. This call is forwarded to the base layer's /// implementation. - /// @param H The handle for the module to search in. + /// @param K The VModuleKey for the module to search in. /// @param Name The name of the symbol to search for. /// @param ExportedSymbolsOnly If true, search only for exported symbols. /// @return A handle for the given named symbol, if it is found in the /// given module. - JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name, + JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); + return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly); } - /// @brief Immediately emit and finalize the module represented by the given + /// Immediately emit and finalize the module represented by the given /// handle. - /// @param H Handle for module to emit/finalize. - Error emitAndFinalize(ModuleHandleT H) { - return BaseLayer.emitAndFinalize(H); - } + /// @param K The VModuleKey for the module to emit/finalize. + Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); } private: BaseLayerT &BaseLayer; CompileFtor Compile; + NotifyCompiledCallback NotifyCompiled; }; } // end namespace orc diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h index 476061afda59..266a0f45b3e4 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h @@ -15,6 +15,7 @@ #define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Layer.h" #include <memory> #include <string> @@ -22,7 +23,32 @@ namespace llvm { class Module; namespace orc { -/// @brief IR mutating layer. +class IRTransformLayer2 : public IRLayer { +public: + + using TransformFunction = + std::function<Expected<std::unique_ptr<Module>>(std::unique_ptr<Module>)>; + + IRTransformLayer2(ExecutionSession &ES, IRLayer &BaseLayer, + TransformFunction Transform = identityTransform); + + void setTransform(TransformFunction Transform) { + this->Transform = std::move(Transform); + } + + void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr<Module> M) override; + + static std::unique_ptr<Module> identityTransform(std::unique_ptr<Module> M) { + return M; + } + +private: + IRLayer &BaseLayer; + TransformFunction Transform; +}; + +/// IR mutating layer. /// /// This layer applies a user supplied transform to each module that is added, /// then adds the transformed module to the layer below. @@ -30,28 +56,23 @@ template <typename BaseLayerT, typename TransformFtor> class IRTransformLayer { public: - /// @brief Handle to a set of added modules. - using ModuleHandleT = typename BaseLayerT::ModuleHandleT; - - /// @brief Construct an IRTransformLayer with the given BaseLayer + /// Construct an IRTransformLayer with the given BaseLayer IRTransformLayer(BaseLayerT &BaseLayer, TransformFtor Transform = TransformFtor()) : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} - /// @brief Apply the transform functor to the module, then add the module to + /// Apply the transform functor to the module, then add the module to /// the layer below, along with the memory manager and symbol resolver. /// /// @return A handle for the added modules. - Expected<ModuleHandleT> - addModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) { - return BaseLayer.addModule(Transform(std::move(M)), std::move(Resolver)); + Error addModule(VModuleKey K, std::unique_ptr<Module> M) { + return BaseLayer.addModule(std::move(K), Transform(std::move(M))); } - /// @brief Remove the module associated with the handle H. - Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); } + /// Remove the module associated with the VModuleKey K. + Error removeModule(VModuleKey K) { return BaseLayer.removeModule(K); } - /// @brief Search for the given named symbol. + /// Search for the given named symbol. /// @param Name The name of the symbol to search for. /// @param ExportedSymbolsOnly If true, search only for exported symbols. /// @return A handle for the given named symbol, if it exists. @@ -59,30 +80,28 @@ public: return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); } - /// @brief Get the address of the given symbol in the context of the module - /// represented by the handle H. This call is forwarded to the base + /// Get the address of the given symbol in the context of the module + /// represented by the VModuleKey K. This call is forwarded to the base /// layer's implementation. - /// @param H The handle for the module to search in. + /// @param K The VModuleKey for the module to search in. /// @param Name The name of the symbol to search for. /// @param ExportedSymbolsOnly If true, search only for exported symbols. /// @return A handle for the given named symbol, if it is found in the /// given module. - JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name, + JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); + return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly); } - /// @brief Immediately emit and finalize the module represented by the given - /// handle. - /// @param H Handle for module to emit/finalize. - Error emitAndFinalize(ModuleHandleT H) { - return BaseLayer.emitAndFinalize(H); - } + /// Immediately emit and finalize the module represented by the given + /// VModuleKey. + /// @param K The VModuleKey for the module to emit/finalize. + Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); } - /// @brief Access the transform functor directly. + /// Access the transform functor directly. TransformFtor& getTransform() { return Transform; } - /// @brief Access the mumate functor directly. + /// Access the mumate functor directly. const TransformFtor& getTransform() const { return Transform; } private: diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index 029b86a6d2ca..8b0b3fdb7df4 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/Support/Error.h" #include "llvm/Support/Memory.h" #include "llvm/Support/Process.h" @@ -46,98 +47,29 @@ class Value; namespace orc { -/// @brief Target-independent base class for compile callback management. +/// Target-independent base class for compile callback management. class JITCompileCallbackManager { public: - using CompileFtor = std::function<JITTargetAddress()>; + using CompileFunction = std::function<JITTargetAddress()>; - /// @brief Handle to a newly created compile callback. Can be used to get an - /// IR constant representing the address of the trampoline, and to set - /// the compile action for the callback. - class CompileCallbackInfo { - public: - CompileCallbackInfo(JITTargetAddress Addr, CompileFtor &Compile) - : Addr(Addr), Compile(Compile) {} - - JITTargetAddress getAddress() const { return Addr; } - void setCompileAction(CompileFtor Compile) { - this->Compile = std::move(Compile); - } - - private: - JITTargetAddress Addr; - CompileFtor &Compile; - }; - - /// @brief Construct a JITCompileCallbackManager. + /// Construct a JITCompileCallbackManager. /// @param ErrorHandlerAddress The address of an error handler in the target /// process to be used if a compile callback fails. - JITCompileCallbackManager(JITTargetAddress ErrorHandlerAddress) - : ErrorHandlerAddress(ErrorHandlerAddress) {} + JITCompileCallbackManager(ExecutionSession &ES, + JITTargetAddress ErrorHandlerAddress) + : ES(ES), CallbacksVSO(ES.createVSO("<Callbacks>")), + ErrorHandlerAddress(ErrorHandlerAddress) {} virtual ~JITCompileCallbackManager() = default; - /// @brief Execute the callback for the given trampoline id. Called by the JIT - /// to compile functions on demand. - JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr) { - auto I = ActiveTrampolines.find(TrampolineAddr); - // FIXME: Also raise an error in the Orc error-handler when we finally have - // one. - if (I == ActiveTrampolines.end()) - return ErrorHandlerAddress; - - // Found a callback handler. Yank this trampoline out of the active list and - // put it back in the available trampolines list, then try to run the - // handler's compile and update actions. - // Moving the trampoline ID back to the available list first means there's - // at - // least one available trampoline if the compile action triggers a request - // for - // a new one. - auto Compile = std::move(I->second); - ActiveTrampolines.erase(I); - AvailableTrampolines.push_back(TrampolineAddr); - - if (auto Addr = Compile()) - return Addr; - - return ErrorHandlerAddress; - } - - /// @brief Reserve a compile callback. - Expected<CompileCallbackInfo> getCompileCallback() { - if (auto TrampolineAddrOrErr = getAvailableTrampolineAddr()) { - const auto &TrampolineAddr = *TrampolineAddrOrErr; - auto &Compile = this->ActiveTrampolines[TrampolineAddr]; - return CompileCallbackInfo(TrampolineAddr, Compile); - } else - return TrampolineAddrOrErr.takeError(); - } - - /// @brief Get a CompileCallbackInfo for an existing callback. - CompileCallbackInfo getCompileCallbackInfo(JITTargetAddress TrampolineAddr) { - auto I = ActiveTrampolines.find(TrampolineAddr); - assert(I != ActiveTrampolines.end() && "Not an active trampoline."); - return CompileCallbackInfo(I->first, I->second); - } + /// Reserve a compile callback. + Expected<JITTargetAddress> getCompileCallback(CompileFunction Compile); - /// @brief Release a compile callback. - /// - /// Note: Callbacks are auto-released after they execute. This method should - /// only be called to manually release a callback that is not going to - /// execute. - void releaseCompileCallback(JITTargetAddress TrampolineAddr) { - auto I = ActiveTrampolines.find(TrampolineAddr); - assert(I != ActiveTrampolines.end() && "Not an active trampoline."); - ActiveTrampolines.erase(I); - AvailableTrampolines.push_back(TrampolineAddr); - } + /// Execute the callback for the given trampoline id. Called by the JIT + /// to compile functions on demand. + JITTargetAddress executeCompileCallback(JITTargetAddress TrampolineAddr); protected: - JITTargetAddress ErrorHandlerAddress; - - using TrampolineMapT = std::map<JITTargetAddress, CompileFtor>; - TrampolineMapT ActiveTrampolines; std::vector<JITTargetAddress> AvailableTrampolines; private: @@ -156,17 +88,25 @@ private: virtual Error grow() = 0; virtual void anchor(); + + std::mutex CCMgrMutex; + ExecutionSession &ES; + VSO &CallbacksVSO; + JITTargetAddress ErrorHandlerAddress; + std::map<JITTargetAddress, SymbolStringPtr> AddrToSymbol; + size_t NextCallbackId = 0; }; -/// @brief Manage compile callbacks for in-process JITs. +/// Manage compile callbacks for in-process JITs. template <typename TargetT> class LocalJITCompileCallbackManager : public JITCompileCallbackManager { public: - /// @brief Construct a InProcessJITCompileCallbackManager. + /// Construct a InProcessJITCompileCallbackManager. /// @param ErrorHandlerAddress The address of an error handler in the target /// process to be used if a compile callback fails. - LocalJITCompileCallbackManager(JITTargetAddress ErrorHandlerAddress) - : JITCompileCallbackManager(ErrorHandlerAddress) { + LocalJITCompileCallbackManager(ExecutionSession &ES, + JITTargetAddress ErrorHandlerAddress) + : JITCompileCallbackManager(ES, ErrorHandlerAddress) { /// Set up the resolver block. std::error_code EC; ResolverBlock = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( @@ -229,38 +169,38 @@ private: std::vector<sys::OwningMemoryBlock> TrampolineBlocks; }; -/// @brief Base class for managing collections of named indirect stubs. +/// Base class for managing collections of named indirect stubs. class IndirectStubsManager { public: - /// @brief Map type for initializing the manager. See init. + /// Map type for initializing the manager. See init. using StubInitsMap = StringMap<std::pair<JITTargetAddress, JITSymbolFlags>>; virtual ~IndirectStubsManager() = default; - /// @brief Create a single stub with the given name, target address and flags. + /// Create a single stub with the given name, target address and flags. virtual Error createStub(StringRef StubName, JITTargetAddress StubAddr, JITSymbolFlags StubFlags) = 0; - /// @brief Create StubInits.size() stubs with the given names, target + /// Create StubInits.size() stubs with the given names, target /// addresses, and flags. virtual Error createStubs(const StubInitsMap &StubInits) = 0; - /// @brief Find the stub with the given name. If ExportedStubsOnly is true, + /// Find the stub with the given name. If ExportedStubsOnly is true, /// this will only return a result if the stub's flags indicate that it /// is exported. - virtual JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0; + virtual JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) = 0; - /// @brief Find the implementation-pointer for the stub. - virtual JITSymbol findPointer(StringRef Name) = 0; + /// Find the implementation-pointer for the stub. + virtual JITEvaluatedSymbol findPointer(StringRef Name) = 0; - /// @brief Change the value of the implementation pointer for the stub. + /// Change the value of the implementation pointer for the stub. virtual Error updatePointer(StringRef Name, JITTargetAddress NewAddr) = 0; private: virtual void anchor(); }; -/// @brief IndirectStubsManager implementation for the host architecture, e.g. +/// IndirectStubsManager implementation for the host architecture, e.g. /// OrcX86_64. (See OrcArchitectureSupport.h). template <typename TargetT> class LocalIndirectStubsManager : public IndirectStubsManager { @@ -286,7 +226,7 @@ public: return Error::success(); } - JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override { + JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override { auto I = StubIndexes.find(Name); if (I == StubIndexes.end()) return nullptr; @@ -295,13 +235,13 @@ public: assert(StubAddr && "Missing stub address"); auto StubTargetAddr = static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(StubAddr)); - auto StubSymbol = JITSymbol(StubTargetAddr, I->second.second); + auto StubSymbol = JITEvaluatedSymbol(StubTargetAddr, I->second.second); if (ExportedStubsOnly && !StubSymbol.getFlags().isExported()) return nullptr; return StubSymbol; } - JITSymbol findPointer(StringRef Name) override { + JITEvaluatedSymbol findPointer(StringRef Name) override { auto I = StubIndexes.find(Name); if (I == StubIndexes.end()) return nullptr; @@ -310,7 +250,7 @@ public: assert(PtrAddr && "Missing pointer address"); auto PtrTargetAddr = static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(PtrAddr)); - return JITSymbol(PtrTargetAddr, I->second.second); + return JITEvaluatedSymbol(PtrTargetAddr, I->second.second); } Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override { @@ -354,45 +294,45 @@ private: StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes; }; -/// @brief Create a local compile callback manager. +/// Create a local compile callback manager. /// /// The given target triple will determine the ABI, and the given /// ErrorHandlerAddress will be used by the resulting compile callback /// manager if a compile callback fails. std::unique_ptr<JITCompileCallbackManager> -createLocalCompileCallbackManager(const Triple &T, +createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES, JITTargetAddress ErrorHandlerAddress); -/// @brief Create a local indriect stubs manager builder. +/// Create a local indriect stubs manager builder. /// /// The given target triple will determine the ABI. std::function<std::unique_ptr<IndirectStubsManager>()> createLocalIndirectStubsManagerBuilder(const Triple &T); -/// @brief Build a function pointer of FunctionType with the given constant +/// Build a function pointer of FunctionType with the given constant /// address. /// /// Usage example: Turn a trampoline address into a function pointer constant /// for use in a stub. Constant *createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr); -/// @brief Create a function pointer with the given type, name, and initializer +/// Create a function pointer with the given type, name, and initializer /// in the given Module. GlobalVariable *createImplPointer(PointerType &PT, Module &M, const Twine &Name, Constant *Initializer); -/// @brief Turn a function declaration into a stub function that makes an +/// Turn a function declaration into a stub function that makes an /// indirect call using the given function pointer. void makeStub(Function &F, Value &ImplPointer); -/// @brief Raise linkage types and rename as necessary to ensure that all +/// Raise linkage types and rename as necessary to ensure that all /// symbols are accessible for other modules. /// /// This should be called before partitioning a module to ensure that the /// partitions retain access to each other's symbols. void makeAllSymbolsExternallyAccessible(Module &M); -/// @brief Clone a function declaration into a new module. +/// Clone a function declaration into a new module. /// /// This function can be used as the first step towards creating a callback /// stub (see makeStub), or moving a function body (see moveFunctionBody). @@ -407,7 +347,7 @@ void makeAllSymbolsExternallyAccessible(Module &M); Function *cloneFunctionDecl(Module &Dst, const Function &F, ValueToValueMapTy *VMap = nullptr); -/// @brief Move the body of function 'F' to a cloned function declaration in a +/// Move the body of function 'F' to a cloned function declaration in a /// different module (See related cloneFunctionDecl). /// /// If the target function declaration is not supplied via the NewF parameter @@ -419,11 +359,11 @@ void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap, ValueMaterializer *Materializer = nullptr, Function *NewF = nullptr); -/// @brief Clone a global variable declaration into a new module. +/// Clone a global variable declaration into a new module. GlobalVariable *cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, ValueToValueMapTy *VMap = nullptr); -/// @brief Move global variable GV from its parent module to cloned global +/// Move global variable GV from its parent module to cloned global /// declaration in a different module. /// /// If the target global declaration is not supplied via the NewGV parameter @@ -436,11 +376,11 @@ void moveGlobalVariableInitializer(GlobalVariable &OrigGV, ValueMaterializer *Materializer = nullptr, GlobalVariable *NewGV = nullptr); -/// @brief Clone a global alias declaration into a new module. +/// Clone a global alias declaration into a new module. GlobalAlias *cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA, ValueToValueMapTy &VMap); -/// @brief Clone module flags metadata into the destination module. +/// Clone module flags metadata into the destination module. void cloneModuleFlagsMetadata(Module &Dst, const Module &Src, ValueToValueMapTy &VMap); diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h new file mode 100644 index 000000000000..df655bd82006 --- /dev/null +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h @@ -0,0 +1,143 @@ +//===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for 3Bdetails. +// +//===----------------------------------------------------------------------===// +// +// An ORC-based JIT for compiling LLVM IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H +#define LLVM_EXECUTIONENGINE_ORC_LLJIT_H + +#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h" +#include "llvm/ExecutionEngine/Orc/CompileUtils.h" +#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" +#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" +#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h" +#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h" +#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +namespace orc { + +/// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT. +class LLJIT { +public: + /// Create an LLJIT instance. + static Expected<std::unique_ptr<LLJIT>> + Create(std::unique_ptr<ExecutionSession> ES, + std::unique_ptr<TargetMachine> TM, DataLayout DL); + + /// Returns a reference to the ExecutionSession for this JIT instance. + ExecutionSession &getExecutionSession() { return *ES; } + + /// Returns a reference to the VSO representing the JIT'd main program. + VSO &getMainVSO() { return Main; } + + /// Convenience method for defining an absolute symbol. + Error defineAbsolute(StringRef Name, JITEvaluatedSymbol Address); + + /// Adds an IR module to the given VSO. + Error addIRModule(VSO &V, std::unique_ptr<Module> M); + + /// Adds an IR module to the Main VSO. + Error addIRModule(std::unique_ptr<Module> M) { + return addIRModule(Main, std::move(M)); + } + + /// Look up a symbol in VSO V by the symbol's linker-mangled name (to look up + /// symbols based on their IR name use the lookup function instead). + Expected<JITEvaluatedSymbol> lookupLinkerMangled(VSO &V, StringRef Name); + + /// Look up a symbol in the main VSO by the symbol's linker-mangled name (to + /// look up symbols based on their IR name use the lookup function instead). + Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) { + return lookupLinkerMangled(Main, Name); + } + + /// Look up a symbol in VSO V based on its IR symbol name. + Expected<JITEvaluatedSymbol> lookup(VSO &V, StringRef UnmangledName) { + return lookupLinkerMangled(V, mangle(UnmangledName)); + } + + /// Look up a symbol in the main VSO based on its IR symbol name. + Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) { + return lookup(Main, UnmangledName); + } + + /// Runs all not-yet-run static constructors. + Error runConstructors() { return CtorRunner.run(); } + + /// Runs all not-yet-run static destructors. + Error runDestructors() { return DtorRunner.run(); } + +protected: + LLJIT(std::unique_ptr<ExecutionSession> ES, std::unique_ptr<TargetMachine> TM, + DataLayout DL); + + std::shared_ptr<RuntimeDyld::MemoryManager> getMemoryManager(VModuleKey K); + + std::string mangle(StringRef UnmangledName); + + Error applyDataLayout(Module &M); + + void recordCtorDtors(Module &M); + + std::unique_ptr<ExecutionSession> ES; + VSO &Main; + + std::unique_ptr<TargetMachine> TM; + DataLayout DL; + + RTDyldObjectLinkingLayer2 ObjLinkingLayer; + IRCompileLayer2 CompileLayer; + + CtorDtorRunner2 CtorRunner, DtorRunner; +}; + +/// An extended version of LLJIT that supports lazy function-at-a-time +/// compilation of LLVM IR. +class LLLazyJIT : public LLJIT { +public: + /// Create an LLLazyJIT instance. + static Expected<std::unique_ptr<LLLazyJIT>> + Create(std::unique_ptr<ExecutionSession> ES, + std::unique_ptr<TargetMachine> TM, DataLayout DL, LLVMContext &Ctx); + + /// Set an IR transform (e.g. pass manager pipeline) to run on each function + /// when it is compiled. + void setLazyCompileTransform(IRTransformLayer2::TransformFunction Transform) { + TransformLayer.setTransform(std::move(Transform)); + } + + /// Add a module to be lazily compiled to VSO V. + Error addLazyIRModule(VSO &V, std::unique_ptr<Module> M); + + /// Add a module to be lazily compiled to the main VSO. + Error addLazyIRModule(std::unique_ptr<Module> M) { + return addLazyIRModule(Main, std::move(M)); + } + +private: + LLLazyJIT(std::unique_ptr<ExecutionSession> ES, + std::unique_ptr<TargetMachine> TM, DataLayout DL, LLVMContext &Ctx, + std::unique_ptr<JITCompileCallbackManager> CCMgr, + std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder); + + std::unique_ptr<JITCompileCallbackManager> CCMgr; + std::function<std::unique_ptr<IndirectStubsManager>()> ISMBuilder; + + IRTransformLayer2 TransformLayer; + CompileOnDemandLayer2 CODLayer; +}; + +} // End namespace orc +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h index 228392ae0d4a..7b6f3d2f92ab 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h @@ -23,7 +23,7 @@ namespace llvm { namespace orc { template <typename DylibLookupFtorT, typename ExternalLookupFtorT> -class LambdaResolver : public JITSymbolResolver { +class LambdaResolver : public LegacyJITSymbolResolver { public: LambdaResolver(DylibLookupFtorT DylibLookupFtor, ExternalLookupFtorT ExternalLookupFtor) diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/Layer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Layer.h new file mode 100644 index 000000000000..91bd4fb83e6f --- /dev/null +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Layer.h @@ -0,0 +1,129 @@ +//===---------------- Layer.h -- Layer interfaces --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Layer interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LAYER_H +#define LLVM_EXECUTIONENGINE_ORC_LAYER_H + +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/IR/Module.h" + +namespace llvm { +namespace orc { + +/// Interface for layers that accept LLVM IR. +class IRLayer { +public: + IRLayer(ExecutionSession &ES); + virtual ~IRLayer(); + + /// Returns the ExecutionSession for this layer. + ExecutionSession &getExecutionSession() { return ES; } + + /// Adds a MaterializationUnit representing the given IR to the given VSO. + virtual Error add(VSO &V, VModuleKey K, std::unique_ptr<Module> M); + + /// Emit should materialize the given IR. + virtual void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr<Module> M) = 0; + +private: + ExecutionSession &ES; +}; + +/// IRMaterializationUnit is a convenient base class for MaterializationUnits +/// wrapping LLVM IR. Represents materialization responsibility for all symbols +/// in the given module. If symbols are overridden by other definitions, then +/// their linkage is changed to available-externally. +class IRMaterializationUnit : public MaterializationUnit { +public: + using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>; + + /// Create an IRMaterializationLayer. Scans the module to build the + /// SymbolFlags and SymbolToDefinition maps. + IRMaterializationUnit(ExecutionSession &ES, std::unique_ptr<Module> M); + + /// Create an IRMaterializationLayer from a module, and pre-existing + /// SymbolFlags and SymbolToDefinition maps. The maps must provide + /// entries for each definition in M. + /// This constructor is useful for delegating work from one + /// IRMaterializationUnit to another. + IRMaterializationUnit(std::unique_ptr<Module> M, SymbolFlagsMap SymbolFlags, + SymbolNameToDefinitionMap SymbolToDefinition); + +protected: + std::unique_ptr<Module> M; + SymbolNameToDefinitionMap SymbolToDefinition; + +private: + void discard(const VSO &V, SymbolStringPtr Name) override; +}; + +/// MaterializationUnit that materializes modules by calling the 'emit' method +/// on the given IRLayer. +class BasicIRLayerMaterializationUnit : public IRMaterializationUnit { +public: + BasicIRLayerMaterializationUnit(IRLayer &L, VModuleKey K, + std::unique_ptr<Module> M); +private: + + void materialize(MaterializationResponsibility R) override; + + IRLayer &L; + VModuleKey K; +}; + +/// Interface for Layers that accept object files. +class ObjectLayer { +public: + ObjectLayer(ExecutionSession &ES); + virtual ~ObjectLayer(); + + /// Returns the execution session for this layer. + ExecutionSession &getExecutionSession() { return ES; } + + /// Adds a MaterializationUnit representing the given IR to the given VSO. + virtual Error add(VSO &V, VModuleKey K, std::unique_ptr<MemoryBuffer> O); + + /// Emit should materialize the given IR. + virtual void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr<MemoryBuffer> O) = 0; + +private: + ExecutionSession &ES; +}; + +/// Materializes the given object file (represented by a MemoryBuffer +/// instance) by calling 'emit' on the given ObjectLayer. +class BasicObjectLayerMaterializationUnit : public MaterializationUnit { +public: + + + /// The MemoryBuffer should represent a valid object file. + /// If there is any chance that the file is invalid it should be validated + /// prior to constructing a BasicObjectLayerMaterializationUnit. + BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K, + std::unique_ptr<MemoryBuffer> O); + +private: + void materialize(MaterializationResponsibility R) override; + void discard(const VSO &V, SymbolStringPtr Name) override; + + ObjectLayer &L; + VModuleKey K; + std::unique_ptr<MemoryBuffer> O; +}; + +} // End namespace orc +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_LAYER_H diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h index b7e462e85d9d..46761b0ca7e1 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h @@ -18,6 +18,7 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" @@ -32,23 +33,18 @@ namespace llvm { namespace orc { -/// @brief Lazy-emitting IR layer. +/// Lazy-emitting IR layer. /// /// This layer accepts LLVM IR Modules (via addModule), but does not /// immediately emit them the layer below. Instead, emissing to the base layer /// is deferred until the first time the client requests the address (via /// JITSymbol::getAddress) for a symbol contained in this layer. template <typename BaseLayerT> class LazyEmittingLayer { -public: - - using BaseLayerHandleT = typename BaseLayerT::ModuleHandleT; - private: class EmissionDeferredModule { public: - EmissionDeferredModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) - : M(std::move(M)), Resolver(std::move(Resolver)) {} + EmissionDeferredModule(VModuleKey K, std::unique_ptr<Module> M) + : K(std::move(K)), M(std::move(M)) {} JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) { switch (EmitState) { @@ -65,13 +61,11 @@ private: return 0; else if (this->EmitState == NotEmitted) { this->EmitState = Emitting; - if (auto HandleOrErr = this->emitToBaseLayer(B)) - Handle = std::move(*HandleOrErr); - else - return HandleOrErr.takeError(); + if (auto Err = this->emitToBaseLayer(B)) + return std::move(Err); this->EmitState = Emitted; } - if (auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly)) + if (auto Sym = B.findSymbolIn(K, PName, ExportedSymbolsOnly)) return Sym.getAddress(); else if (auto Err = Sym.takeError()) return std::move(Err); @@ -89,13 +83,13 @@ private: // RuntimeDyld that did the lookup), so just return a nullptr here. return nullptr; case Emitted: - return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly); + return B.findSymbolIn(K, Name, ExportedSymbolsOnly); } llvm_unreachable("Invalid emit-state."); } Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) { - return EmitState != NotEmitted ? BaseLayer.removeModule(Handle) + return EmitState != NotEmitted ? BaseLayer.removeModule(K) : Error::success(); } @@ -104,10 +98,10 @@ private: "Cannot emitAndFinalize while already emitting"); if (EmitState == NotEmitted) { EmitState = Emitting; - Handle = emitToBaseLayer(BaseLayer); + emitToBaseLayer(BaseLayer); EmitState = Emitted; } - BaseLayer.emitAndFinalize(Handle); + BaseLayer.emitAndFinalize(K); } private: @@ -135,11 +129,11 @@ private: return buildMangledSymbols(Name, ExportedSymbolsOnly); } - Expected<BaseLayerHandleT> emitToBaseLayer(BaseLayerT &BaseLayer) { + Error emitToBaseLayer(BaseLayerT &BaseLayer) { // We don't need the mangled names set any more: Once we've emitted this // to the base layer we'll just look for symbols there. MangledSymbols.reset(); - return BaseLayer.addModule(std::move(M), std::move(Resolver)); + return BaseLayer.addModule(std::move(K), std::move(M)); } // If the mangled name of the given GlobalValue matches the given search @@ -192,46 +186,40 @@ private: } enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted; - BaseLayerHandleT Handle; - std::shared_ptr<Module> M; - std::shared_ptr<JITSymbolResolver> Resolver; + VModuleKey K; + std::unique_ptr<Module> M; mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols; }; - using ModuleListT = std::list<std::unique_ptr<EmissionDeferredModule>>; - BaseLayerT &BaseLayer; - ModuleListT ModuleList; + std::map<VModuleKey, std::unique_ptr<EmissionDeferredModule>> ModuleMap; public: - /// @brief Handle to a loaded module. - using ModuleHandleT = typename ModuleListT::iterator; - - /// @brief Construct a lazy emitting layer. + /// Construct a lazy emitting layer. LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} - /// @brief Add the given module to the lazy emitting layer. - Expected<ModuleHandleT> - addModule(std::shared_ptr<Module> M, - std::shared_ptr<JITSymbolResolver> Resolver) { - return ModuleList.insert( - ModuleList.end(), - llvm::make_unique<EmissionDeferredModule>(std::move(M), - std::move(Resolver))); + /// Add the given module to the lazy emitting layer. + Error addModule(VModuleKey K, std::unique_ptr<Module> M) { + assert(!ModuleMap.count(K) && "VModuleKey K already in use"); + ModuleMap[K] = + llvm::make_unique<EmissionDeferredModule>(std::move(K), std::move(M)); + return Error::success(); } - /// @brief Remove the module represented by the given handle. + /// Remove the module represented by the given handle. /// /// This method will free the memory associated with the given module, both /// in this layer, and the base layer. - Error removeModule(ModuleHandleT H) { - Error Err = (*H)->removeModuleFromBaseLayer(BaseLayer); - ModuleList.erase(H); - return Err; + Error removeModule(VModuleKey K) { + auto I = ModuleMap.find(K); + assert(I != ModuleMap.end() && "VModuleKey K not valid here"); + auto EDM = std::move(I.second); + ModuleMap.erase(I); + return EDM->removeModuleFromBaseLayer(BaseLayer); } - /// @brief Search for the given named symbol. + /// Search for the given named symbol. /// @param Name The name of the symbol to search for. /// @param ExportedSymbolsOnly If true, search only for exported symbols. /// @return A handle for the given named symbol, if it exists. @@ -243,26 +231,27 @@ public: // If not found then search the deferred modules. If any of these contain a // definition of 'Name' then they will return a JITSymbol that will emit // the corresponding module when the symbol address is requested. - for (auto &DeferredMod : ModuleList) - if (auto Symbol = DeferredMod->find(Name, ExportedSymbolsOnly, BaseLayer)) + for (auto &KV : ModuleMap) + if (auto Symbol = KV.second->find(Name, ExportedSymbolsOnly, BaseLayer)) return Symbol; // If no definition found anywhere return a null symbol. return nullptr; } - /// @brief Get the address of the given symbol in the context of the of - /// compiled modules represented by the handle H. - JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name, + /// Get the address of the given symbol in the context of the of + /// compiled modules represented by the key K. + JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, bool ExportedSymbolsOnly) { - return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer); + assert(ModuleMap.count(K) && "VModuleKey K not valid here"); + return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer); } - /// @brief Immediately emit and finalize the module represented by the given - /// handle. - /// @param H Handle for module to emit/finalize. - Error emitAndFinalize(ModuleHandleT H) { - return (*H)->emitAndFinalize(BaseLayer); + /// Immediately emit and finalize the module represented by the given + /// key. + Error emitAndFinalize(VModuleKey K) { + assert(ModuleMap.count(K) && "VModuleKey K not valid here"); + return ModuleMap[K]->emitAndFinalize(BaseLayer); } }; diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h new file mode 100644 index 000000000000..52c8c162ff0b --- /dev/null +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/Legacy.h @@ -0,0 +1,211 @@ +//===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains core ORC APIs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LEGACY_H +#define LLVM_EXECUTIONENGINE_ORC_LEGACY_H + +#include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" + +namespace llvm { +namespace orc { + +/// SymbolResolver is a composable interface for looking up symbol flags +/// and addresses using the AsynchronousSymbolQuery type. It will +/// eventually replace the LegacyJITSymbolResolver interface as the +/// stardard ORC symbol resolver type. +/// +/// FIXME: SymbolResolvers should go away and be replaced with VSOs with +/// defenition generators. +class SymbolResolver { +public: + virtual ~SymbolResolver() = default; + + /// Returns the flags for each symbol in Symbols that can be found, + /// along with the set of symbol that could not be found. + virtual SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) = 0; + + /// For each symbol in Symbols that can be found, assigns that symbols + /// value in Query. Returns the set of symbols that could not be found. + virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, + SymbolNameSet Symbols) = 0; + +private: + virtual void anchor(); +}; + +/// Implements SymbolResolver with a pair of supplied function objects +/// for convenience. See createSymbolResolver. +template <typename LookupFlagsFn, typename LookupFn> +class LambdaSymbolResolver final : public SymbolResolver { +public: + template <typename LookupFlagsFnRef, typename LookupFnRef> + LambdaSymbolResolver(LookupFlagsFnRef &&LookupFlags, LookupFnRef &&Lookup) + : LookupFlags(std::forward<LookupFlagsFnRef>(LookupFlags)), + Lookup(std::forward<LookupFnRef>(Lookup)) {} + + SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final { + return LookupFlags(Symbols); + } + + SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, + SymbolNameSet Symbols) final { + return Lookup(std::move(Query), std::move(Symbols)); + } + +private: + LookupFlagsFn LookupFlags; + LookupFn Lookup; +}; + +/// Creates a SymbolResolver implementation from the pair of supplied +/// function objects. +template <typename LookupFlagsFn, typename LookupFn> +std::unique_ptr<LambdaSymbolResolver< + typename std::remove_cv< + typename std::remove_reference<LookupFlagsFn>::type>::type, + typename std::remove_cv< + typename std::remove_reference<LookupFn>::type>::type>> +createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) { + using LambdaSymbolResolverImpl = LambdaSymbolResolver< + typename std::remove_cv< + typename std::remove_reference<LookupFlagsFn>::type>::type, + typename std::remove_cv< + typename std::remove_reference<LookupFn>::type>::type>; + return llvm::make_unique<LambdaSymbolResolverImpl>( + std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup)); +} + +class JITSymbolResolverAdapter : public JITSymbolResolver { +public: + JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R, + MaterializationResponsibility *MR); + Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) override; + Expected<LookupResult> lookup(const LookupSet &Symbols) override; + +private: + ExecutionSession &ES; + std::set<SymbolStringPtr> ResolvedStrings; + SymbolResolver &R; + MaterializationResponsibility *MR; +}; + +/// Use the given legacy-style FindSymbol function (i.e. a function that +/// takes a const std::string& or StringRef and returns a JITSymbol) to +/// find the flags for each symbol in Symbols and store their flags in +/// SymbolFlags. If any JITSymbol returned by FindSymbol is in an error +/// state the function returns immediately with that error, otherwise it +/// returns the set of symbols not found. +/// +/// Useful for implementing lookupFlags bodies that query legacy resolvers. +template <typename FindSymbolFn> +Expected<SymbolFlagsMap> lookupFlagsWithLegacyFn(const SymbolNameSet &Symbols, + FindSymbolFn FindSymbol) { + SymbolFlagsMap SymbolFlags; + + for (auto &S : Symbols) { + if (JITSymbol Sym = FindSymbol(*S)) + SymbolFlags[S] = Sym.getFlags(); + else if (auto Err = Sym.takeError()) + return std::move(Err); + } + + return SymbolFlags; +} + +/// Use the given legacy-style FindSymbol function (i.e. a function that +/// takes a const std::string& or StringRef and returns a JITSymbol) to +/// find the address and flags for each symbol in Symbols and store the +/// result in Query. If any JITSymbol returned by FindSymbol is in an +/// error then Query.notifyFailed(...) is called with that error and the +/// function returns immediately. On success, returns the set of symbols +/// not found. +/// +/// Useful for implementing lookup bodies that query legacy resolvers. +template <typename FindSymbolFn> +SymbolNameSet +lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query, + const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) { + SymbolNameSet SymbolsNotFound; + bool NewSymbolsResolved = false; + + for (auto &S : Symbols) { + if (JITSymbol Sym = FindSymbol(*S)) { + if (auto Addr = Sym.getAddress()) { + Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); + Query.notifySymbolReady(); + NewSymbolsResolved = true; + } else { + ES.legacyFailQuery(Query, Addr.takeError()); + return SymbolNameSet(); + } + } else if (auto Err = Sym.takeError()) { + ES.legacyFailQuery(Query, std::move(Err)); + return SymbolNameSet(); + } else + SymbolsNotFound.insert(S); + } + + if (NewSymbolsResolved && Query.isFullyResolved()) + Query.handleFullyResolved(); + + if (NewSymbolsResolved && Query.isFullyReady()) + Query.handleFullyReady(); + + return SymbolsNotFound; +} + +/// An ORC SymbolResolver implementation that uses a legacy +/// findSymbol-like function to perform lookup; +template <typename LegacyLookupFn> +class LegacyLookupFnResolver final : public SymbolResolver { +public: + using ErrorReporter = std::function<void(Error)>; + + LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup, + ErrorReporter ReportError) + : ES(ES), LegacyLookup(std::move(LegacyLookup)), + ReportError(std::move(ReportError)) {} + + SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) final { + if (auto SymbolFlags = lookupFlagsWithLegacyFn(Symbols, LegacyLookup)) + return std::move(*SymbolFlags); + else { + ReportError(SymbolFlags.takeError()); + return SymbolFlagsMap(); + } + } + + SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, + SymbolNameSet Symbols) final { + return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup); + } + +private: + ExecutionSession &ES; + LegacyLookupFn LegacyLookup; + ErrorReporter ReportError; +}; + +template <typename LegacyLookupFn> +std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>> +createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup, + std::function<void(Error)> ErrorReporter) { + return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>( + ES, std::move(LegacyLookup), std::move(ErrorReporter)); +} + +} // End namespace orc +} // End namespace llvm + +#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h index 957b94912b3f..3dd3cfe05b8d 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/NullResolver.h @@ -15,14 +15,23 @@ #ifndef LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H #define LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H +#include "llvm/ExecutionEngine/Orc/Legacy.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" namespace llvm { namespace orc { +class NullResolver : public SymbolResolver { +public: + SymbolFlagsMap lookupFlags(const SymbolNameSet &Symbols) override; + + SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, + SymbolNameSet Symbols) override; +}; + /// SymbolResolver impliementation that rejects all resolution requests. /// Useful for clients that have no cross-object fixups. -class NullResolver : public JITSymbolResolver { +class NullLegacyResolver : public LegacyJITSymbolResolver { public: JITSymbol findSymbol(const std::string &Name) final; diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h index cb47e7520b1a..c6b43a9c8ed6 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h @@ -15,6 +15,7 @@ #define LLVM_EXECUTIONENGINE_ORC_OBJECTTRANSFORMLAYER_H #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Layer.h" #include <algorithm> #include <memory> #include <string> @@ -22,7 +23,24 @@ namespace llvm { namespace orc { -/// @brief Object mutating layer. +class ObjectTransformLayer2 : public ObjectLayer { +public: + using TransformFunction = + std::function<Expected<std::unique_ptr<MemoryBuffer>>( + std::unique_ptr<MemoryBuffer>)>; + + ObjectTransformLayer2(ExecutionSession &ES, ObjectLayer &BaseLayer, + TransformFunction Transform); + + void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr<MemoryBuffer> O) override; + +private: + ObjectLayer &BaseLayer; + TransformFunction Transform; +}; + +/// Object mutating layer. /// /// This layer accepts sets of ObjectFiles (via addObject). It /// immediately applies the user supplied functor to each object, then adds @@ -30,29 +48,24 @@ namespace orc { template <typename BaseLayerT, typename TransformFtor> class ObjectTransformLayer { public: - /// @brief Handle to a set of added objects. - using ObjHandleT = typename BaseLayerT::ObjHandleT; - - /// @brief Construct an ObjectTransformLayer with the given BaseLayer + /// Construct an ObjectTransformLayer with the given BaseLayer ObjectTransformLayer(BaseLayerT &BaseLayer, TransformFtor Transform = TransformFtor()) : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} - /// @brief Apply the transform functor to each object in the object set, then + /// Apply the transform functor to each object in the object set, then /// add the resulting set of objects to the base layer, along with the /// memory manager and symbol resolver. /// /// @return A handle for the added objects. - template <typename ObjectPtr> - Expected<ObjHandleT> addObject(ObjectPtr Obj, - std::shared_ptr<JITSymbolResolver> Resolver) { - return BaseLayer.addObject(Transform(std::move(Obj)), std::move(Resolver)); + template <typename ObjectPtr> Error addObject(VModuleKey K, ObjectPtr Obj) { + return BaseLayer.addObject(std::move(K), Transform(std::move(Obj))); } - /// @brief Remove the object set associated with the handle H. - Error removeObject(ObjHandleT H) { return BaseLayer.removeObject(H); } + /// Remove the object set associated with the VModuleKey K. + Error removeObject(VModuleKey K) { return BaseLayer.removeObject(K); } - /// @brief Search for the given named symbol. + /// Search for the given named symbol. /// @param Name The name of the symbol to search for. /// @param ExportedSymbolsOnly If true, search only for exported symbols. /// @return A handle for the given named symbol, if it exists. @@ -60,36 +73,34 @@ public: return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); } - /// @brief Get the address of the given symbol in the context of the set of - /// objects represented by the handle H. This call is forwarded to the - /// base layer's implementation. - /// @param H The handle for the object set to search in. + /// Get the address of the given symbol in the context of the set of + /// objects represented by the VModuleKey K. This call is forwarded to + /// the base layer's implementation. + /// @param K The VModuleKey associated with the object set to search in. /// @param Name The name of the symbol to search for. /// @param ExportedSymbolsOnly If true, search only for exported symbols. /// @return A handle for the given named symbol, if it is found in the /// given object set. - JITSymbol findSymbolIn(ObjHandleT H, const std::string &Name, + JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, bool ExportedSymbolsOnly) { - return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); + return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly); } - /// @brief Immediately emit and finalize the object set represented by the - /// given handle. - /// @param H Handle for object set to emit/finalize. - Error emitAndFinalize(ObjHandleT H) { - return BaseLayer.emitAndFinalize(H); - } + /// Immediately emit and finalize the object set represented by the + /// given VModuleKey K. + Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); } - /// @brief Map section addresses for the objects associated with the handle H. - void mapSectionAddress(ObjHandleT H, const void *LocalAddress, + /// Map section addresses for the objects associated with the + /// VModuleKey K. + void mapSectionAddress(VModuleKey K, const void *LocalAddress, JITTargetAddress TargetAddr) { - BaseLayer.mapSectionAddress(H, LocalAddress, TargetAddr); + BaseLayer.mapSectionAddress(K, LocalAddress, TargetAddr); } - /// @brief Access the transform functor directly. + /// Access the transform functor directly. TransformFtor &getTransform() { return Transform; } - /// @brief Access the mumate functor directly. + /// Access the mumate functor directly. const TransformFtor &getTransform() const { return Transform; } private: diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h index e1b55649b9f2..581c598aff62 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h @@ -71,7 +71,7 @@ public: } }; -/// @brief Provide information about stub blocks generated by the +/// Provide information about stub blocks generated by the /// makeIndirectStubsBlock function. template <unsigned StubSizeVal> class GenericIndirectStubsInfo { public: @@ -92,16 +92,16 @@ public: return *this; } - /// @brief Number of stubs in this block. + /// Number of stubs in this block. unsigned getNumStubs() const { return NumStubs; } - /// @brief Get a pointer to the stub at the given index, which must be in + /// Get a pointer to the stub at the given index, which must be in /// the range 0 .. getNumStubs() - 1. void *getStub(unsigned Idx) const { return static_cast<char *>(StubsMem.base()) + Idx * StubSize; } - /// @brief Get a pointer to the implementation-pointer at the given index, + /// Get a pointer to the implementation-pointer at the given index, /// which must be in the range 0 .. getNumStubs() - 1. void **getPtr(unsigned Idx) const { char *PtrsBase = static_cast<char *>(StubsMem.base()) + NumStubs * StubSize; @@ -124,18 +124,18 @@ public: using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, void *TrampolineId); - /// @brief Write the resolver code into the given memory. The user is be + /// Write the resolver code into the given memory. The user is be /// responsible for allocating the memory and setting permissions. static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, void *CallbackMgr); - /// @brief Write the requsted number of trampolines into the given memory, + /// Write the requsted number of trampolines into the given memory, /// which must be big enough to hold 1 pointer, plus NumTrampolines /// trampolines. static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, unsigned NumTrampolines); - /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to + /// Emit at least MinStubs worth of indirect call stubs, rounded out to /// the nearest page size. /// /// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k @@ -145,7 +145,7 @@ public: unsigned MinStubs, void *InitialPtrVal); }; -/// @brief X86_64 code that's common to all ABIs. +/// X86_64 code that's common to all ABIs. /// /// X86_64 supports lazy JITing. class OrcX86_64_Base { @@ -155,13 +155,13 @@ public: using IndirectStubsInfo = GenericIndirectStubsInfo<8>; - /// @brief Write the requsted number of trampolines into the given memory, + /// Write the requsted number of trampolines into the given memory, /// which must be big enough to hold 1 pointer, plus NumTrampolines /// trampolines. static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, unsigned NumTrampolines); - /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to + /// Emit at least MinStubs worth of indirect call stubs, rounded out to /// the nearest page size. /// /// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k @@ -171,7 +171,7 @@ public: unsigned MinStubs, void *InitialPtrVal); }; -/// @brief X86_64 support for SysV ABI (Linux, MacOSX). +/// X86_64 support for SysV ABI (Linux, MacOSX). /// /// X86_64_SysV supports lazy JITing. class OrcX86_64_SysV : public OrcX86_64_Base { @@ -181,13 +181,13 @@ public: using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, void *TrampolineId); - /// @brief Write the resolver code into the given memory. The user is be + /// Write the resolver code into the given memory. The user is be /// responsible for allocating the memory and setting permissions. static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, void *CallbackMgr); }; -/// @brief X86_64 support for Win32. +/// X86_64 support for Win32. /// /// X86_64_Win32 supports lazy JITing. class OrcX86_64_Win32 : public OrcX86_64_Base { @@ -197,13 +197,13 @@ public: using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, void *TrampolineId); - /// @brief Write the resolver code into the given memory. The user is be + /// Write the resolver code into the given memory. The user is be /// responsible for allocating the memory and setting permissions. static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, void *CallbackMgr); }; -/// @brief I386 support. +/// I386 support. /// /// I386 supports lazy JITing. class OrcI386 { @@ -217,18 +217,18 @@ public: using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, void *TrampolineId); - /// @brief Write the resolver code into the given memory. The user is be + /// Write the resolver code into the given memory. The user is be /// responsible for allocating the memory and setting permissions. static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, void *CallbackMgr); - /// @brief Write the requsted number of trampolines into the given memory, + /// Write the requsted number of trampolines into the given memory, /// which must be big enough to hold 1 pointer, plus NumTrampolines /// trampolines. static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, unsigned NumTrampolines); - /// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to + /// Emit at least MinStubs worth of indirect call stubs, rounded out to /// the nearest page size. /// /// E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h index e1ac87075ac0..dc60e8d74e97 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcError.h @@ -22,7 +22,9 @@ namespace orc { enum class OrcErrorCode : int { // RPC Errors - JITSymbolNotFound = 1, + UnknownORCError = 1, + DuplicateDefinition, + JITSymbolNotFound, RemoteAllocatorDoesNotExist, RemoteAllocatorIdAlreadyInUse, RemoteMProtectAddrUnrecognized, @@ -39,6 +41,18 @@ enum class OrcErrorCode : int { std::error_code orcError(OrcErrorCode ErrCode); +class DuplicateDefinition : public ErrorInfo<DuplicateDefinition> { +public: + static char ID; + + DuplicateDefinition(std::string SymbolName); + std::error_code convertToErrorCode() const override; + void log(raw_ostream &OS) const override; + const std::string &getSymbolName() const; +private: + std::string SymbolName; +}; + class JITSymbolNotFound : public ErrorInfo<JITSymbolNotFound> { public: static char ID; diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h index 7179e5ff66fd..739e5ba47c12 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetClient.h @@ -63,7 +63,7 @@ public: public: ~RemoteRTDyldMemoryManager() { Client.destroyRemoteAllocator(Id); - DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n"); + LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << Id << "\n"); } RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &) = delete; @@ -79,9 +79,9 @@ public: Unmapped.back().CodeAllocs.emplace_back(Size, Alignment); uint8_t *Alloc = reinterpret_cast<uint8_t *>( Unmapped.back().CodeAllocs.back().getLocalAddress()); - DEBUG(dbgs() << "Allocator " << Id << " allocated code for " - << SectionName << ": " << Alloc << " (" << Size - << " bytes, alignment " << Alignment << ")\n"); + LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated code for " + << SectionName << ": " << Alloc << " (" << Size + << " bytes, alignment " << Alignment << ")\n"); return Alloc; } @@ -92,18 +92,18 @@ public: Unmapped.back().RODataAllocs.emplace_back(Size, Alignment); uint8_t *Alloc = reinterpret_cast<uint8_t *>( Unmapped.back().RODataAllocs.back().getLocalAddress()); - DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for " - << SectionName << ": " << Alloc << " (" << Size - << " bytes, alignment " << Alignment << ")\n"); + LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated ro-data for " + << SectionName << ": " << Alloc << " (" << Size + << " bytes, alignment " << Alignment << ")\n"); return Alloc; } // else... Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment); uint8_t *Alloc = reinterpret_cast<uint8_t *>( Unmapped.back().RWDataAllocs.back().getLocalAddress()); - DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for " - << SectionName << ": " << Alloc << " (" << Size - << " bytes, alignment " << Alignment << ")\n"); + LLVM_DEBUG(dbgs() << "Allocator " << Id << " allocated rw-data for " + << SectionName << ": " << Alloc << " (" << Size + << " bytes, alignment " << Alignment << ")\n"); return Alloc; } @@ -113,36 +113,36 @@ public: uint32_t RWDataAlign) override { Unmapped.push_back(ObjectAllocs()); - DEBUG(dbgs() << "Allocator " << Id << " reserved:\n"); + LLVM_DEBUG(dbgs() << "Allocator " << Id << " reserved:\n"); if (CodeSize != 0) { Unmapped.back().RemoteCodeAddr = Client.reserveMem(Id, CodeSize, CodeAlign); - DEBUG(dbgs() << " code: " - << format("0x%016x", Unmapped.back().RemoteCodeAddr) - << " (" << CodeSize << " bytes, alignment " << CodeAlign - << ")\n"); + LLVM_DEBUG(dbgs() << " code: " + << format("0x%016x", Unmapped.back().RemoteCodeAddr) + << " (" << CodeSize << " bytes, alignment " + << CodeAlign << ")\n"); } if (RODataSize != 0) { Unmapped.back().RemoteRODataAddr = Client.reserveMem(Id, RODataSize, RODataAlign); - DEBUG(dbgs() << " ro-data: " - << format("0x%016x", Unmapped.back().RemoteRODataAddr) - << " (" << RODataSize << " bytes, alignment " - << RODataAlign << ")\n"); + LLVM_DEBUG(dbgs() << " ro-data: " + << format("0x%016x", Unmapped.back().RemoteRODataAddr) + << " (" << RODataSize << " bytes, alignment " + << RODataAlign << ")\n"); } if (RWDataSize != 0) { Unmapped.back().RemoteRWDataAddr = Client.reserveMem(Id, RWDataSize, RWDataAlign); - DEBUG(dbgs() << " rw-data: " - << format("0x%016x", Unmapped.back().RemoteRWDataAddr) - << " (" << RWDataSize << " bytes, alignment " - << RWDataAlign << ")\n"); + LLVM_DEBUG(dbgs() << " rw-data: " + << format("0x%016x", Unmapped.back().RemoteRWDataAddr) + << " (" << RWDataSize << " bytes, alignment " + << RWDataAlign << ")\n"); } } @@ -162,7 +162,7 @@ public: void notifyObjectLoaded(RuntimeDyld &Dyld, const object::ObjectFile &Obj) override { - DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n"); + LLVM_DEBUG(dbgs() << "Allocator " << Id << " applied mappings:\n"); for (auto &ObjAllocs : Unmapped) { mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr); @@ -176,7 +176,7 @@ public: } bool finalizeMemory(std::string *ErrMsg = nullptr) override { - DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n"); + LLVM_DEBUG(dbgs() << "Allocator " << Id << " finalizing:\n"); for (auto &ObjAllocs : Unfinalized) { if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr, @@ -261,7 +261,7 @@ public: RemoteRTDyldMemoryManager(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id) : Client(Client), Id(Id) { - DEBUG(dbgs() << "Created remote allocator " << Id << "\n"); + LLVM_DEBUG(dbgs() << "Created remote allocator " << Id << "\n"); } // Maps all allocations in Allocs to aligned blocks @@ -270,8 +270,9 @@ public: for (auto &Alloc : Allocs) { NextAddr = alignTo(NextAddr, Alloc.getAlign()); Dyld.mapSectionAddress(Alloc.getLocalAddress(), NextAddr); - DEBUG(dbgs() << " " << static_cast<void *>(Alloc.getLocalAddress()) - << " -> " << format("0x%016x", NextAddr) << "\n"); + LLVM_DEBUG(dbgs() << " " + << static_cast<void *>(Alloc.getLocalAddress()) + << " -> " << format("0x%016x", NextAddr) << "\n"); Alloc.setRemoteAddress(NextAddr); // Only advance NextAddr if it was non-null to begin with, @@ -290,22 +291,23 @@ public: assert(!Allocs.empty() && "No sections in allocated segment"); for (auto &Alloc : Allocs) { - DEBUG(dbgs() << " copying section: " - << static_cast<void *>(Alloc.getLocalAddress()) << " -> " - << format("0x%016x", Alloc.getRemoteAddress()) << " (" - << Alloc.getSize() << " bytes)\n";); + LLVM_DEBUG(dbgs() << " copying section: " + << static_cast<void *>(Alloc.getLocalAddress()) + << " -> " + << format("0x%016x", Alloc.getRemoteAddress()) + << " (" << Alloc.getSize() << " bytes)\n";); if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(), Alloc.getSize())) return true; } - DEBUG(dbgs() << " setting " - << (Permissions & sys::Memory::MF_READ ? 'R' : '-') - << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-') - << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-') - << " permissions on block: " - << format("0x%016x", RemoteSegmentAddr) << "\n"); + LLVM_DEBUG(dbgs() << " setting " + << (Permissions & sys::Memory::MF_READ ? 'R' : '-') + << (Permissions & sys::Memory::MF_WRITE ? 'W' : '-') + << (Permissions & sys::Memory::MF_EXEC ? 'X' : '-') + << " permissions on block: " + << format("0x%016x", RemoteSegmentAddr) << "\n"); if (Client.setProtections(Id, RemoteSegmentAddr, Permissions)) return true; } @@ -356,25 +358,25 @@ public: return Error::success(); } - JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override { + JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override { auto I = StubIndexes.find(Name); if (I == StubIndexes.end()) return nullptr; auto Key = I->second.first; auto Flags = I->second.second; - auto StubSymbol = JITSymbol(getStubAddr(Key), Flags); + auto StubSymbol = JITEvaluatedSymbol(getStubAddr(Key), Flags); if (ExportedStubsOnly && !StubSymbol.getFlags().isExported()) return nullptr; return StubSymbol; } - JITSymbol findPointer(StringRef Name) override { + JITEvaluatedSymbol findPointer(StringRef Name) override { auto I = StubIndexes.find(Name); if (I == StubIndexes.end()) return nullptr; auto Key = I->second.first; auto Flags = I->second.second; - return JITSymbol(getPtrAddr(Key), Flags); + return JITEvaluatedSymbol(getPtrAddr(Key), Flags); } Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override { @@ -449,8 +451,9 @@ public: class RemoteCompileCallbackManager : public JITCompileCallbackManager { public: RemoteCompileCallbackManager(OrcRemoteTargetClient &Client, + ExecutionSession &ES, JITTargetAddress ErrorHandlerAddress) - : JITCompileCallbackManager(ErrorHandlerAddress), Client(Client) {} + : JITCompileCallbackManager(ES, ErrorHandlerAddress), Client(Client) {} private: Error grow() override { @@ -475,10 +478,10 @@ public: /// Channel is the ChannelT instance to communicate on. It is assumed that /// the channel is ready to be read from and written to. static Expected<std::unique_ptr<OrcRemoteTargetClient>> - Create(rpc::RawByteChannel &Channel, std::function<void(Error)> ReportError) { + Create(rpc::RawByteChannel &Channel, ExecutionSession &ES) { Error Err = Error::success(); auto Client = std::unique_ptr<OrcRemoteTargetClient>( - new OrcRemoteTargetClient(Channel, std::move(ReportError), Err)); + new OrcRemoteTargetClient(Channel, ES, Err)); if (Err) return std::move(Err); return std::move(Client); @@ -487,7 +490,8 @@ public: /// Call the int(void) function at the given address in the target and return /// its result. Expected<int> callIntVoid(JITTargetAddress Addr) { - DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) << "\n"); + LLVM_DEBUG(dbgs() << "Calling int(*)(void) " << format("0x%016x", Addr) + << "\n"); return callB<exec::CallIntVoid>(Addr); } @@ -495,16 +499,16 @@ public: /// return its result. Expected<int> callMain(JITTargetAddress Addr, const std::vector<std::string> &Args) { - DEBUG(dbgs() << "Calling int(*)(int, char*[]) " << format("0x%016x", Addr) - << "\n"); + LLVM_DEBUG(dbgs() << "Calling int(*)(int, char*[]) " + << format("0x%016x", Addr) << "\n"); return callB<exec::CallMain>(Addr, Args); } /// Call the void() function at the given address in the target and wait for /// it to finish. Error callVoidVoid(JITTargetAddress Addr) { - DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr) - << "\n"); + LLVM_DEBUG(dbgs() << "Calling void(*)(void) " << format("0x%016x", Addr) + << "\n"); return callB<exec::CallVoidVoid>(Addr); } @@ -531,12 +535,14 @@ public: Expected<RemoteCompileCallbackManager &> enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress) { + assert(!CallbackManager && "CallbackManager already obtained"); + // Emit the resolver block on the JIT server. if (auto Err = callB<stubs::EmitResolverBlock>()) return std::move(Err); // Create the callback manager. - CallbackManager.emplace(*this, ErrorHandlerAddress); + CallbackManager.emplace(*this, ES, ErrorHandlerAddress); RemoteCompileCallbackManager &Mgr = *CallbackManager; return Mgr; } @@ -554,10 +560,10 @@ public: Error terminateSession() { return callB<utils::TerminateSession>(); } private: - OrcRemoteTargetClient(rpc::RawByteChannel &Channel, - std::function<void(Error)> ReportError, Error &Err) + OrcRemoteTargetClient(rpc::RawByteChannel &Channel, ExecutionSession &ES, + Error &Err) : rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>(Channel, true), - ReportError(std::move(ReportError)) { + ES(ES) { ErrorAsOutParameter EAO(&Err); addHandler<utils::RequestCompile>( @@ -577,7 +583,7 @@ private: void deregisterEHFrames(JITTargetAddress Addr, uint32_t Size) { if (auto Err = callB<eh::RegisterEHFrames>(Addr, Size)) - ReportError(std::move(Err)); + ES.reportError(std::move(Err)); } void destroyRemoteAllocator(ResourceIdMgr::ResourceId Id) { @@ -592,7 +598,7 @@ private: void destroyIndirectStubsManager(ResourceIdMgr::ResourceId Id) { IndirectStubOwnerIds.release(Id); if (auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id)) - ReportError(std::move(Err)); + ES.reportError(std::move(Err)); } Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>> @@ -625,7 +631,7 @@ private: if (auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align)) return *AddrOrErr; else { - ReportError(AddrOrErr.takeError()); + ES.reportError(AddrOrErr.takeError()); return 0; } } @@ -633,7 +639,7 @@ private: bool setProtections(ResourceIdMgr::ResourceId Id, JITTargetAddress RemoteSegAddr, unsigned ProtFlags) { if (auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) { - ReportError(std::move(Err)); + ES.reportError(std::move(Err)); return true; } else return false; @@ -641,7 +647,7 @@ private: bool writeMem(JITTargetAddress Addr, const char *Src, uint64_t Size) { if (auto Err = callB<mem::WriteMem>(DirectBufferWriter(Src, Addr, Size))) { - ReportError(std::move(Err)); + ES.reportError(std::move(Err)); return true; } else return false; @@ -653,6 +659,7 @@ private: static Error doNothing() { return Error::success(); } + ExecutionSession &ES; std::function<void(Error)> ReportError; std::string RemoteTargetTriple; uint32_t RemotePointerSize = 0; diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h index cf419d33004c..acbc1682fa5d 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h @@ -161,9 +161,9 @@ private: IntVoidFnTy Fn = reinterpret_cast<IntVoidFnTy>(static_cast<uintptr_t>(Addr)); - DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n"); + LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n"); int Result = Fn(); - DEBUG(dbgs() << " Result = " << Result << "\n"); + LLVM_DEBUG(dbgs() << " Result = " << Result << "\n"); return Result; } @@ -180,15 +180,13 @@ private: for (auto &Arg : Args) ArgV[Idx++] = Arg.c_str(); ArgV[ArgC] = 0; - DEBUG( - for (int Idx = 0; Idx < ArgC; ++Idx) { - llvm::dbgs() << "Arg " << Idx << ": " << ArgV[Idx] << "\n"; - } - ); + LLVM_DEBUG(for (int Idx = 0; Idx < ArgC; ++Idx) { + llvm::dbgs() << "Arg " << Idx << ": " << ArgV[Idx] << "\n"; + }); - DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n"); + LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n"); int Result = Fn(ArgC, ArgV.get()); - DEBUG(dbgs() << " Result = " << Result << "\n"); + LLVM_DEBUG(dbgs() << " Result = " << Result << "\n"); return Result; } @@ -199,9 +197,9 @@ private: VoidVoidFnTy Fn = reinterpret_cast<VoidVoidFnTy>(static_cast<uintptr_t>(Addr)); - DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n"); + LLVM_DEBUG(dbgs() << " Calling " << format("0x%016x", Addr) << "\n"); Fn(); - DEBUG(dbgs() << " Complete.\n"); + LLVM_DEBUG(dbgs() << " Complete.\n"); return Error::success(); } @@ -211,7 +209,7 @@ private: if (I != Allocators.end()) return errorCodeToError( orcError(OrcErrorCode::RemoteAllocatorIdAlreadyInUse)); - DEBUG(dbgs() << " Created allocator " << Id << "\n"); + LLVM_DEBUG(dbgs() << " Created allocator " << Id << "\n"); Allocators[Id] = Allocator(); return Error::success(); } @@ -221,15 +219,16 @@ private: if (I != IndirectStubsOwners.end()) return errorCodeToError( orcError(OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse)); - DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n"); + LLVM_DEBUG(dbgs() << " Create indirect stubs owner " << Id << "\n"); IndirectStubsOwners[Id] = ISBlockOwnerList(); return Error::success(); } Error handleDeregisterEHFrames(JITTargetAddress TAddr, uint32_t Size) { uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr)); - DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr) - << ", Size = " << Size << " bytes\n"); + LLVM_DEBUG(dbgs() << " Registering EH frames at " + << format("0x%016x", TAddr) << ", Size = " << Size + << " bytes\n"); EHFramesDeregister(Addr, Size); return Error::success(); } @@ -240,7 +239,7 @@ private: return errorCodeToError( orcError(OrcErrorCode::RemoteAllocatorDoesNotExist)); Allocators.erase(I); - DEBUG(dbgs() << " Destroyed allocator " << Id << "\n"); + LLVM_DEBUG(dbgs() << " Destroyed allocator " << Id << "\n"); return Error::success(); } @@ -256,8 +255,8 @@ private: Expected<std::tuple<JITTargetAddress, JITTargetAddress, uint32_t>> handleEmitIndirectStubs(ResourceIdMgr::ResourceId Id, uint32_t NumStubsRequired) { - DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired - << " stubs.\n"); + LLVM_DEBUG(dbgs() << " ISMgr " << Id << " request " << NumStubsRequired + << " stubs.\n"); auto StubOwnerItr = IndirectStubsOwners.find(Id); if (StubOwnerItr == IndirectStubsOwners.end()) @@ -328,8 +327,8 @@ private: Expected<JITTargetAddress> handleGetSymbolAddress(const std::string &Name) { JITTargetAddress Addr = SymbolLookup(Name); - DEBUG(dbgs() << " Symbol '" << Name << "' = " << format("0x%016x", Addr) - << "\n"); + LLVM_DEBUG(dbgs() << " Symbol '" << Name + << "' = " << format("0x%016x", Addr) << "\n"); return Addr; } @@ -340,12 +339,13 @@ private: uint32_t PageSize = sys::Process::getPageSize(); uint32_t TrampolineSize = TargetT::TrampolineSize; uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize; - DEBUG(dbgs() << " Remote info:\n" - << " triple = '" << ProcessTriple << "'\n" - << " pointer size = " << PointerSize << "\n" - << " page size = " << PageSize << "\n" - << " trampoline size = " << TrampolineSize << "\n" - << " indirect stub size = " << IndirectStubSize << "\n"); + LLVM_DEBUG(dbgs() << " Remote info:\n" + << " triple = '" << ProcessTriple << "'\n" + << " pointer size = " << PointerSize << "\n" + << " page size = " << PageSize << "\n" + << " trampoline size = " << TrampolineSize << "\n" + << " indirect stub size = " << IndirectStubSize + << "\n"); return std::make_tuple(ProcessTriple, PointerSize, PageSize, TrampolineSize, IndirectStubSize); } @@ -354,8 +354,8 @@ private: uint64_t Size) { uint8_t *Src = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(RSrc)); - DEBUG(dbgs() << " Reading " << Size << " bytes from " - << format("0x%016x", RSrc) << "\n"); + LLVM_DEBUG(dbgs() << " Reading " << Size << " bytes from " + << format("0x%016x", RSrc) << "\n"); std::vector<uint8_t> Buffer; Buffer.resize(Size); @@ -367,8 +367,9 @@ private: Error handleRegisterEHFrames(JITTargetAddress TAddr, uint32_t Size) { uint8_t *Addr = reinterpret_cast<uint8_t *>(static_cast<uintptr_t>(TAddr)); - DEBUG(dbgs() << " Registering EH frames at " << format("0x%016x", TAddr) - << ", Size = " << Size << " bytes\n"); + LLVM_DEBUG(dbgs() << " Registering EH frames at " + << format("0x%016x", TAddr) << ", Size = " << Size + << " bytes\n"); EHFramesRegister(Addr, Size); return Error::success(); } @@ -384,8 +385,9 @@ private: if (auto Err = Allocator.allocate(LocalAllocAddr, Size, Align)) return std::move(Err); - DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr - << " (" << Size << " bytes, alignment " << Align << ")\n"); + LLVM_DEBUG(dbgs() << " Allocator " << Id << " reserved " << LocalAllocAddr + << " (" << Size << " bytes, alignment " << Align + << ")\n"); JITTargetAddress AllocAddr = static_cast<JITTargetAddress>( reinterpret_cast<uintptr_t>(LocalAllocAddr)); @@ -401,10 +403,11 @@ private: orcError(OrcErrorCode::RemoteAllocatorDoesNotExist)); auto &Allocator = I->second; void *LocalAddr = reinterpret_cast<void *>(static_cast<uintptr_t>(Addr)); - DEBUG(dbgs() << " Allocator " << Id << " set permissions on " << LocalAddr - << " to " << (Flags & sys::Memory::MF_READ ? 'R' : '-') - << (Flags & sys::Memory::MF_WRITE ? 'W' : '-') - << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n"); + LLVM_DEBUG(dbgs() << " Allocator " << Id << " set permissions on " + << LocalAddr << " to " + << (Flags & sys::Memory::MF_READ ? 'R' : '-') + << (Flags & sys::Memory::MF_WRITE ? 'W' : '-') + << (Flags & sys::Memory::MF_EXEC ? 'X' : '-') << "\n"); return Allocator.setProtections(LocalAddr, Flags); } @@ -414,14 +417,14 @@ private: } Error handleWriteMem(DirectBufferWriter DBW) { - DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to " - << format("0x%016x", DBW.getDst()) << "\n"); + LLVM_DEBUG(dbgs() << " Writing " << DBW.getSize() << " bytes to " + << format("0x%016x", DBW.getDst()) << "\n"); return Error::success(); } Error handleWritePtr(JITTargetAddress Addr, JITTargetAddress PtrVal) { - DEBUG(dbgs() << " Writing pointer *" << format("0x%016x", Addr) << " = " - << format("0x%016x", PtrVal) << "\n"); + LLVM_DEBUG(dbgs() << " Writing pointer *" << format("0x%016x", Addr) + << " = " << format("0x%016x", PtrVal) << "\n"); uintptr_t *Ptr = reinterpret_cast<uintptr_t *>(static_cast<uintptr_t>(Addr)); *Ptr = static_cast<uintptr_t>(PtrVal); diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h index c278cb176853..47bd90bb1bad 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RPCUtils.h @@ -1631,7 +1631,7 @@ RPCAsyncDispatch<RPCEndpointT, Func> rpcAsyncDispatch(RPCEndpointT &Endpoint) { return RPCAsyncDispatch<RPCEndpointT, Func>(Endpoint); } -/// \brief Allows a set of asynchrounous calls to be dispatched, and then +/// Allows a set of asynchrounous calls to be dispatched, and then /// waited on as a group. class ParallelCallGroup { public: @@ -1640,7 +1640,7 @@ public: ParallelCallGroup(const ParallelCallGroup &) = delete; ParallelCallGroup &operator=(const ParallelCallGroup &) = delete; - /// \brief Make as asynchronous call. + /// Make as asynchronous call. template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs> Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler, const ArgTs &... Args) { @@ -1669,7 +1669,7 @@ public: return AsyncDispatch(std::move(WrappedHandler), Args...); } - /// \brief Blocks until all calls have been completed and their return value + /// Blocks until all calls have been completed and their return value /// handlers run. void wait() { std::unique_lock<std::mutex> Lock(M); @@ -1683,21 +1683,21 @@ private: uint32_t NumOutstandingCalls = 0; }; -/// @brief Convenience class for grouping RPC Functions into APIs that can be +/// Convenience class for grouping RPC Functions into APIs that can be /// negotiated as a block. /// template <typename... Funcs> class APICalls { public: - /// @brief Test whether this API contains Function F. + /// Test whether this API contains Function F. template <typename F> class Contains { public: static const bool value = false; }; - /// @brief Negotiate all functions in this API. + /// Negotiate all functions in this API. template <typename RPCEndpoint> static Error negotiate(RPCEndpoint &R) { return Error::success(); diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h index 246c57341f35..48b3f7a58ed7 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -18,6 +18,9 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/Layer.h" +#include "llvm/ExecutionEngine/Orc/Legacy.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" @@ -33,15 +36,62 @@ namespace llvm { namespace orc { -class RTDyldObjectLinkingLayerBase { +class RTDyldObjectLinkingLayer2 : public ObjectLayer { public: + /// Functor for receiving object-loaded notifications. + using NotifyLoadedFunction = + std::function<void(VModuleKey, const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &)>; + + /// Functor for receiving finalization notifications. + using NotifyFinalizedFunction = std::function<void(VModuleKey)>; - using ObjectPtr = - std::shared_ptr<object::OwningBinary<object::ObjectFile>>; + using GetMemoryManagerFunction = + std::function<std::shared_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>; + + /// Construct an ObjectLinkingLayer with the given NotifyLoaded, + /// and NotifyFinalized functors. + RTDyldObjectLinkingLayer2( + ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager, + NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(), + NotifyFinalizedFunction NotifyFinalized = NotifyFinalizedFunction()); + + /// Emit the object. + void emit(MaterializationResponsibility R, VModuleKey K, + std::unique_ptr<MemoryBuffer> O) override; + + /// Map section addresses for the object associated with the + /// VModuleKey K. + void mapSectionAddress(VModuleKey K, const void *LocalAddress, + JITTargetAddress TargetAddr) const; + + /// Set the 'ProcessAllSections' flag. + /// + /// If set to true, all sections in each object file will be allocated using + /// the memory manager, rather than just the sections required for execution. + /// + /// This is kludgy, and may be removed in the future. + void setProcessAllSections(bool ProcessAllSections) { + this->ProcessAllSections = ProcessAllSections; + } + +private: + mutable std::mutex RTDyldLayerMutex; + GetMemoryManagerFunction GetMemoryManager; + NotifyLoadedFunction NotifyLoaded; + NotifyFinalizedFunction NotifyFinalized; + bool ProcessAllSections; + std::map<VModuleKey, RuntimeDyld *> ActiveRTDylds; + std::map<VModuleKey, std::shared_ptr<RuntimeDyld::MemoryManager>> MemMgrs; +}; + +class RTDyldObjectLinkingLayerBase { +public: + using ObjectPtr = std::unique_ptr<MemoryBuffer>; protected: - /// @brief Holds an object to be allocated/linked as a unit in the JIT. + /// Holds an object to be allocated/linked as a unit in the JIT. /// /// An instance of this class will be created for each object added /// via JITObjectLayer::addObject. Deleting the instance (via @@ -55,7 +105,7 @@ protected: void operator=(const LinkedObject&) = delete; virtual ~LinkedObject() = default; - virtual void finalize() = 0; + virtual Error finalize() = 0; virtual JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) = 0; @@ -79,15 +129,9 @@ protected: StringMap<JITEvaluatedSymbol> SymbolTable; bool Finalized = false; }; - - using LinkedObjectListT = std::list<std::unique_ptr<LinkedObject>>; - -public: - /// @brief Handle to a loaded object. - using ObjHandleT = LinkedObjectListT::iterator; }; -/// @brief Bare bones object linking layer. +/// Bare bones object linking layer. /// /// This class is intended to be used as the base layer for a JIT. It allows /// object files to be loaded into memory, linked, and the addresses of their @@ -98,67 +142,93 @@ public: using RTDyldObjectLinkingLayerBase::ObjectPtr; - /// @brief Functor for receiving object-loaded notifications. + /// Functor for receiving object-loaded notifications. using NotifyLoadedFtor = - std::function<void(ObjHandleT, const ObjectPtr &Obj, - const RuntimeDyld::LoadedObjectInfo &)>; + std::function<void(VModuleKey, const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &)>; - /// @brief Functor for receiving finalization notifications. - using NotifyFinalizedFtor = std::function<void(ObjHandleT)>; + /// Functor for receiving finalization notifications. + using NotifyFinalizedFtor = + std::function<void(VModuleKey, const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &)>; -private: + /// Functor for receiving deallocation notifications. + using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>; +private: + using OwnedObject = object::OwningBinary<object::ObjectFile>; - template <typename MemoryManagerPtrT, typename SymbolResolverPtrT, - typename FinalizerFtor> + template <typename MemoryManagerPtrT> class ConcreteLinkedObject : public LinkedObject { public: - ConcreteLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr, - SymbolResolverPtrT Resolver, - FinalizerFtor Finalizer, + ConcreteLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K, + OwnedObject Obj, MemoryManagerPtrT MemMgr, + std::shared_ptr<SymbolResolver> Resolver, bool ProcessAllSections) - : MemMgr(std::move(MemMgr)), - PFC(llvm::make_unique<PreFinalizeContents>(std::move(Obj), - std::move(Resolver), - std::move(Finalizer), - ProcessAllSections)) { + : K(std::move(K)), + Parent(Parent), + MemMgr(std::move(MemMgr)), + PFC(llvm::make_unique<PreFinalizeContents>( + std::move(Obj), std::move(Resolver), + ProcessAllSections)) { buildInitialSymbolTable(PFC->Obj); } ~ConcreteLinkedObject() override { - MemMgr->deregisterEHFrames(); - } + if (this->Parent.NotifyFreed) + this->Parent.NotifyFreed(K, *ObjForNotify.getBinary()); - void setHandle(ObjHandleT H) { - PFC->Handle = H; + MemMgr->deregisterEHFrames(); } - void finalize() override { + Error finalize() override { assert(PFC && "mapSectionAddress called on finalized LinkedObject"); - RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver); - RTDyld.setProcessAllSections(PFC->ProcessAllSections); - PFC->RTDyld = &RTDyld; + JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver, + nullptr); + PFC->RTDyld = llvm::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter); + PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections); + + Finalized = true; + + std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info = + PFC->RTDyld->loadObject(*PFC->Obj.getBinary()); + + // Copy the symbol table out of the RuntimeDyld instance. + { + auto SymTab = PFC->RTDyld->getSymbolTable(); + for (auto &KV : SymTab) + SymbolTable[KV.first] = KV.second; + } + + if (Parent.NotifyLoaded) + Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info); + + PFC->RTDyld->finalizeWithMemoryManagerLocking(); + + if (PFC->RTDyld->hasError()) + return make_error<StringError>(PFC->RTDyld->getErrorString(), + inconvertibleErrorCode()); - this->Finalized = true; - PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Obj), - [&]() { - this->updateSymbolTable(RTDyld); - }); + if (Parent.NotifyFinalized) + Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info); // Release resources. + if (this->Parent.NotifyFreed) + ObjForNotify = std::move(PFC->Obj); // needed for callback PFC = nullptr; + return Error::success(); } JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override { - return - [this, Name]() { - // The symbol may be materialized between the creation of this lambda - // and its execution, so we need to double check. - if (!this->Finalized) - this->finalize(); - return this->getSymbol(Name, false).getAddress(); - }; + return [this, Name]() -> Expected<JITTargetAddress> { + // The symbol may be materialized between the creation of this lambda + // and its execution, so we need to double check. + if (!this->Finalized) + if (auto Err = this->finalize()) + return std::move(Err); + return this->getSymbol(Name, false).getAddress(); + }; } void mapSectionAddress(const void *LocalAddress, @@ -169,9 +239,8 @@ private: } private: - - void buildInitialSymbolTable(const ObjectPtr &Obj) { - for (auto &Symbol : Obj->getBinary()->symbols()) { + void buildInitialSymbolTable(const OwnedObject &Obj) { + for (auto &Symbol : Obj.getBinary()->symbols()) { if (Symbol.getFlags() & object::SymbolRef::SF_Undefined) continue; Expected<StringRef> SymbolName = Symbol.getName(); @@ -186,65 +255,64 @@ private: } } - void updateSymbolTable(const RuntimeDyld &RTDyld) { - for (auto &SymEntry : SymbolTable) - SymEntry.second = RTDyld.getSymbol(SymEntry.first()); - } - // Contains the information needed prior to finalization: the object files, // memory manager, resolver, and flags needed for RuntimeDyld. struct PreFinalizeContents { - PreFinalizeContents(ObjectPtr Obj, SymbolResolverPtrT Resolver, - FinalizerFtor Finalizer, bool ProcessAllSections) - : Obj(std::move(Obj)), Resolver(std::move(Resolver)), - Finalizer(std::move(Finalizer)), - ProcessAllSections(ProcessAllSections) {} + PreFinalizeContents(OwnedObject Obj, + std::shared_ptr<SymbolResolver> Resolver, + bool ProcessAllSections) + : Obj(std::move(Obj)), + Resolver(std::move(Resolver)), + ProcessAllSections(ProcessAllSections) {} - ObjectPtr Obj; - SymbolResolverPtrT Resolver; - FinalizerFtor Finalizer; + OwnedObject Obj; + std::shared_ptr<SymbolResolver> Resolver; bool ProcessAllSections; - ObjHandleT Handle; - RuntimeDyld *RTDyld; + std::unique_ptr<RuntimeDyld> RTDyld; }; + VModuleKey K; + RTDyldObjectLinkingLayer &Parent; MemoryManagerPtrT MemMgr; + OwnedObject ObjForNotify; std::unique_ptr<PreFinalizeContents> PFC; }; - template <typename MemoryManagerPtrT, typename SymbolResolverPtrT, - typename FinalizerFtor> - std::unique_ptr< - ConcreteLinkedObject<MemoryManagerPtrT, SymbolResolverPtrT, FinalizerFtor>> - createLinkedObject(ObjectPtr Obj, MemoryManagerPtrT MemMgr, - SymbolResolverPtrT Resolver, - FinalizerFtor Finalizer, + template <typename MemoryManagerPtrT> + std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>> + createLinkedObject(RTDyldObjectLinkingLayer &Parent, VModuleKey K, + OwnedObject Obj, MemoryManagerPtrT MemMgr, + std::shared_ptr<SymbolResolver> Resolver, bool ProcessAllSections) { - using LOS = ConcreteLinkedObject<MemoryManagerPtrT, SymbolResolverPtrT, - FinalizerFtor>; - return llvm::make_unique<LOS>(std::move(Obj), std::move(MemMgr), - std::move(Resolver), std::move(Finalizer), + using LOS = ConcreteLinkedObject<MemoryManagerPtrT>; + return llvm::make_unique<LOS>(Parent, std::move(K), std::move(Obj), + std::move(MemMgr), std::move(Resolver), ProcessAllSections); } public: + struct Resources { + std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr; + std::shared_ptr<SymbolResolver> Resolver; + }; - /// @brief Functor for creating memory managers. - using MemoryManagerGetter = - std::function<std::shared_ptr<RuntimeDyld::MemoryManager>()>; + using ResourcesGetter = std::function<Resources(VModuleKey)>; - /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded, + /// Construct an ObjectLinkingLayer with the given NotifyLoaded, /// and NotifyFinalized functors. RTDyldObjectLinkingLayer( - MemoryManagerGetter GetMemMgr, + ExecutionSession &ES, ResourcesGetter GetResources, NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), - NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()) - : GetMemMgr(GetMemMgr), + NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(), + NotifyFreedFtor NotifyFreed = NotifyFreedFtor()) + : ES(ES), GetResources(std::move(GetResources)), NotifyLoaded(std::move(NotifyLoaded)), NotifyFinalized(std::move(NotifyFinalized)), - ProcessAllSections(false) {} + NotifyFreed(std::move(NotifyFreed)), + ProcessAllSections(false) { + } - /// @brief Set the 'ProcessAllSections' flag. + /// Set the 'ProcessAllSections' flag. /// /// If set to true, all sections in each object file will be allocated using /// the memory manager, rather than just the sections required for execution. @@ -254,44 +322,26 @@ public: this->ProcessAllSections = ProcessAllSections; } - /// @brief Add an object to the JIT. - /// - /// @return A handle that can be used to refer to the loaded object (for - /// symbol searching, finalization, freeing memory, etc.). - Expected<ObjHandleT> addObject(ObjectPtr Obj, - std::shared_ptr<JITSymbolResolver> Resolver) { - auto Finalizer = [&](ObjHandleT H, RuntimeDyld &RTDyld, - const ObjectPtr &ObjToLoad, - std::function<void()> LOSHandleLoad) { - std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info = - RTDyld.loadObject(*ObjToLoad->getBinary()); - - LOSHandleLoad(); - - if (this->NotifyLoaded) - this->NotifyLoaded(H, ObjToLoad, *Info); + /// Add an object to the JIT. + Error addObject(VModuleKey K, ObjectPtr ObjBuffer) { - RTDyld.finalizeWithMemoryManagerLocking(); + auto Obj = + object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()); + if (!Obj) + return Obj.takeError(); - if (this->NotifyFinalized) - this->NotifyFinalized(H); - }; + assert(!LinkedObjects.count(K) && "VModuleKey already in use"); - auto LO = - createLinkedObject(std::move(Obj), GetMemMgr(), - std::move(Resolver), std::move(Finalizer), - ProcessAllSections); - // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle - // below. - auto *LOPtr = LO.get(); + auto R = GetResources(K); - ObjHandleT Handle = LinkedObjList.insert(LinkedObjList.end(), std::move(LO)); - LOPtr->setHandle(Handle); + LinkedObjects[K] = createLinkedObject( + *this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)), + std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections); - return Handle; + return Error::success(); } - /// @brief Remove the object associated with handle H. + /// Remove the object associated with VModuleKey K. /// /// All memory allocated for the object will be freed, and the sections and /// symbols it provided will no longer be available. No attempt is made to @@ -299,57 +349,64 @@ public: /// indirectly) will result in undefined behavior. If dependence tracking is /// required to detect or resolve such issues it should be added at a higher /// layer. - Error removeObject(ObjHandleT H) { + Error removeObject(VModuleKey K) { + assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); // How do we invalidate the symbols in H? - LinkedObjList.erase(H); + LinkedObjects.erase(K); return Error::success(); } - /// @brief Search for the given named symbol. + /// Search for the given named symbol. /// @param Name The name of the symbol to search for. /// @param ExportedSymbolsOnly If true, search only for exported symbols. /// @return A handle for the given named symbol, if it exists. JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { - for (auto I = LinkedObjList.begin(), E = LinkedObjList.end(); I != E; - ++I) - if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly)) - return Symbol; + for (auto &KV : LinkedObjects) + if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly)) + return Sym; + else if (auto Err = Sym.takeError()) + return std::move(Err); return nullptr; } - /// @brief Search for the given named symbol in the context of the loaded - /// object represented by the handle H. - /// @param H The handle for the object to search in. + /// Search for the given named symbol in the context of the loaded + /// object represented by the VModuleKey K. + /// @param K The VModuleKey for the object to search in. /// @param Name The name of the symbol to search for. /// @param ExportedSymbolsOnly If true, search only for exported symbols. /// @return A handle for the given named symbol, if it is found in the /// given object. - JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, + JITSymbol findSymbolIn(VModuleKey K, StringRef Name, bool ExportedSymbolsOnly) { - return (*H)->getSymbol(Name, ExportedSymbolsOnly); + assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); + return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly); } - /// @brief Map section addresses for the object associated with the handle H. - void mapSectionAddress(ObjHandleT H, const void *LocalAddress, + /// Map section addresses for the object associated with the + /// VModuleKey K. + void mapSectionAddress(VModuleKey K, const void *LocalAddress, JITTargetAddress TargetAddr) { - (*H)->mapSectionAddress(LocalAddress, TargetAddr); + assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); + LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr); } - /// @brief Immediately emit and finalize the object represented by the given - /// handle. - /// @param H Handle for object to emit/finalize. - Error emitAndFinalize(ObjHandleT H) { - (*H)->finalize(); - return Error::success(); + /// Immediately emit and finalize the object represented by the given + /// VModuleKey. + /// @param K VModuleKey for object to emit/finalize. + Error emitAndFinalize(VModuleKey K) { + assert(LinkedObjects.count(K) && "VModuleKey not associated with object"); + return LinkedObjects[K]->finalize(); } private: + ExecutionSession &ES; - LinkedObjectListT LinkedObjList; - MemoryManagerGetter GetMemMgr; + std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects; + ResourcesGetter GetResources; NotifyLoadedFtor NotifyLoaded; NotifyFinalizedFtor NotifyFinalized; + NotifyFreedFtor NotifyFreed; bool ProcessAllSections = false; }; diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h index 17255954a99f..955e77607a18 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/RemoteObjectLayer.h @@ -306,8 +306,7 @@ public: using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT; using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol; - using ObjectPtr = - std::shared_ptr<object::OwningBinary<object::ObjectFile>>; + using ObjectPtr = std::unique_ptr<MemoryBuffer>; /// Create a RemoteObjectClientLayer that communicates with a /// RemoteObjectServerLayer instance via the given RPCEndpoint. @@ -323,15 +322,15 @@ public: *this, &ThisT::lookupInLogicalDylib); } - /// @brief Add an object to the JIT. + /// Add an object to the JIT. /// /// @return A handle that can be used to refer to the loaded object (for /// symbol searching, finalization, freeing memory, etc.). Expected<ObjHandleT> - addObject(ObjectPtr Object, std::shared_ptr<JITSymbolResolver> Resolver) { - StringRef ObjBuffer = Object->getBinary()->getData(); + addObject(ObjectPtr ObjBuffer, + std::shared_ptr<LegacyJITSymbolResolver> Resolver) { if (auto HandleOrErr = - this->Remote.template callB<AddObject>(ObjBuffer)) { + this->Remote.template callB<AddObject>(ObjBuffer->getBuffer())) { auto &Handle = *HandleOrErr; // FIXME: Return an error for this: assert(!Resolvers.count(Handle) && "Handle already in use?"); @@ -341,26 +340,26 @@ public: return HandleOrErr.takeError(); } - /// @brief Remove the given object from the JIT. + /// Remove the given object from the JIT. Error removeObject(ObjHandleT H) { return this->Remote.template callB<RemoveObject>(H); } - /// @brief Search for the given named symbol. + /// Search for the given named symbol. JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) { return remoteToJITSymbol( this->Remote.template callB<FindSymbol>(Name, ExportedSymbolsOnly)); } - /// @brief Search for the given named symbol within the given context. + /// Search for the given named symbol within the given context. JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) { return remoteToJITSymbol( this->Remote.template callB<FindSymbolIn>(H, Name, ExportedSymbolsOnly)); } - /// @brief Immediately emit and finalize the object with the given handle. + /// Immediately emit and finalize the object with the given handle. Error emitAndFinalize(ObjHandleT H) { return this->Remote.template callB<EmitAndFinalize>(H); } @@ -386,7 +385,8 @@ private: } std::map<remote::ResourceIdMgr::ResourceId, - std::shared_ptr<JITSymbolResolver>> Resolvers; + std::shared_ptr<LegacyJITSymbolResolver>> + Resolvers; }; /// RemoteObjectServerLayer acts as a server and handling RPC calls for the @@ -459,30 +459,21 @@ private: Expected<ObjHandleT> addObject(std::string ObjBuffer) { auto Buffer = llvm::make_unique<StringMemoryBuffer>(std::move(ObjBuffer)); - if (auto ObjectOrErr = - object::ObjectFile::createObjectFile(Buffer->getMemBufferRef())) { - auto Object = - std::make_shared<object::OwningBinary<object::ObjectFile>>( - std::move(*ObjectOrErr), std::move(Buffer)); + auto Id = HandleIdMgr.getNext(); + assert(!BaseLayerHandles.count(Id) && "Id already in use?"); - auto Id = HandleIdMgr.getNext(); - assert(!BaseLayerHandles.count(Id) && "Id already in use?"); + auto Resolver = createLambdaResolver( + [this, Id](const std::string &Name) { return lookup(Id, Name); }, + [this, Id](const std::string &Name) { + return lookupInLogicalDylib(Id, Name); + }); - auto Resolver = - createLambdaResolver( - [this, Id](const std::string &Name) { return lookup(Id, Name); }, - [this, Id](const std::string &Name) { - return lookupInLogicalDylib(Id, Name); - }); - - if (auto HandleOrErr = - BaseLayer.addObject(std::move(Object), std::move(Resolver))) { - BaseLayerHandles[Id] = std::move(*HandleOrErr); - return Id; - } else - return teeLog(HandleOrErr.takeError()); + if (auto HandleOrErr = + BaseLayer.addObject(std::move(Buffer), std::move(Resolver))) { + BaseLayerHandles[Id] = std::move(*HandleOrErr); + return Id; } else - return teeLog(ObjectOrErr.takeError()); + return teeLog(HandleOrErr.takeError()); } Error removeObject(ObjHandleT H) { diff --git a/contrib/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h b/contrib/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h index b01fbd44bacd..4c45cfd199dd 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h @@ -23,29 +23,36 @@ namespace orc { class SymbolStringPtr; -/// @brief String pool for symbol names used by the JIT. +/// String pool for symbol names used by the JIT. class SymbolStringPool { friend class SymbolStringPtr; public: - /// @brief Create a symbol string pointer from the given string. + /// Destroy a SymbolStringPool. + ~SymbolStringPool(); + + /// Create a symbol string pointer from the given string. SymbolStringPtr intern(StringRef S); - /// @brief Remove from the pool any entries that are no longer referenced. + /// Remove from the pool any entries that are no longer referenced. void clearDeadEntries(); - /// @brief Returns true if the pool is empty. + /// Returns true if the pool is empty. bool empty() const; private: - using RefCountType = std::atomic<uint64_t>; + using RefCountType = std::atomic<size_t>; using PoolMap = StringMap<RefCountType>; using PoolMapEntry = StringMapEntry<RefCountType>; mutable std::mutex PoolMutex; PoolMap Pool; }; -/// @brief Pointer to a pooled string representing a symbol name. +/// Pointer to a pooled string representing a symbol name. class SymbolStringPtr { friend class SymbolStringPool; + friend bool operator==(const SymbolStringPtr &LHS, + const SymbolStringPtr &RHS); + friend bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS); + public: SymbolStringPtr() = default; SymbolStringPtr(const SymbolStringPtr &Other) @@ -80,17 +87,7 @@ public: --S->getValue(); } - bool operator==(const SymbolStringPtr &Other) const { - return S == Other.S; - } - - bool operator!=(const SymbolStringPtr &Other) const { - return !(*this == Other); - } - - bool operator<(const SymbolStringPtr &Other) const { - return S->getValue() < Other.S->getValue(); - } + StringRef operator*() const { return S->first(); } private: @@ -103,25 +100,39 @@ private: SymbolStringPool::PoolMapEntry *S = nullptr; }; +inline bool operator==(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) { + return LHS.S == RHS.S; +} + +inline bool operator!=(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) { + return !(LHS == RHS); +} + +inline bool operator<(const SymbolStringPtr &LHS, const SymbolStringPtr &RHS) { + return LHS.S < RHS.S; +} + +inline SymbolStringPool::~SymbolStringPool() { +#ifndef NDEBUG + clearDeadEntries(); + assert(Pool.empty() && "Dangling references at pool destruction time"); +#endif // NDEBUG +} + inline SymbolStringPtr SymbolStringPool::intern(StringRef S) { std::lock_guard<std::mutex> Lock(PoolMutex); - auto I = Pool.find(S); - if (I != Pool.end()) - return SymbolStringPtr(&*I); - + PoolMap::iterator I; bool Added; std::tie(I, Added) = Pool.try_emplace(S, 0); - assert(Added && "Insert should always succeed here"); return SymbolStringPtr(&*I); } inline void SymbolStringPool::clearDeadEntries() { std::lock_guard<std::mutex> Lock(PoolMutex); for (auto I = Pool.begin(), E = Pool.end(); I != E;) { - auto Tmp = std::next(I); - if (I->second == 0) - Pool.erase(I); - I = Tmp; + auto Tmp = I++; + if (Tmp->second == 0) + Pool.erase(Tmp); } } diff --git a/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index 0c1862c5c3ea..23d651f6d1b6 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -47,6 +47,9 @@ public: /// newly loaded object. virtual void notifyObjectLoaded(ExecutionEngine *EE, const object::ObjectFile &) {} + +private: + void anchor() override; }; // RuntimeDyld clients often want to handle the memory management of @@ -56,7 +59,7 @@ public: // FIXME: As the RuntimeDyld fills out, additional routines will be needed // for the varying types of objects to be allocated. class RTDyldMemoryManager : public MCJITMemoryManager, - public JITSymbolResolver { + public LegacyJITSymbolResolver { public: RTDyldMemoryManager() = default; RTDyldMemoryManager(const RTDyldMemoryManager&) = delete; @@ -142,6 +145,9 @@ protected: }; typedef std::vector<EHFrame> EHFrameInfos; EHFrameInfos EHFrames; + +private: + void anchor() override; }; // Create wrappers for C Binding types (see CBindingWrapping.h). diff --git a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h index 56aa04ce694a..5dd5add1bb39 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -65,7 +65,7 @@ protected: void reassignSectionAddress(unsigned SectionID, uint64_t Addr); public: - /// \brief Information about the loaded object. + /// Information about the loaded object. class LoadedObjectInfo : public llvm::LoadedObjectInfo { friend class RuntimeDyldImpl; @@ -88,7 +88,7 @@ public: ObjSectionToIDMap ObjSecToIDMap; }; - /// \brief Memory Management. + /// Memory Management. class MemoryManager { friend class RuntimeDyld; @@ -170,7 +170,7 @@ public: bool FinalizationLocked = false; }; - /// \brief Construct a RuntimeDyld instance. + /// Construct a RuntimeDyld instance. RuntimeDyld(MemoryManager &MemMgr, JITSymbolResolver &Resolver); RuntimeDyld(const RuntimeDyld &) = delete; RuntimeDyld &operator=(const RuntimeDyld &) = delete; @@ -189,6 +189,13 @@ public: /// This address is the one used for relocation. JITEvaluatedSymbol getSymbol(StringRef Name) const; + /// Returns a copy of the symbol table. This can be used by on-finalized + /// callbacks to extract the symbol table before throwing away the + /// RuntimeDyld instance. Because the map keys (StringRefs) are backed by + /// strings inside the RuntimeDyld instance, the map should be processed + /// before the RuntimeDyld instance is discarded. + std::map<StringRef, JITEvaluatedSymbol> getSymbolTable() const; + /// Resolve the relocations for all symbols we currently know about. void resolveRelocations(); diff --git a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h index de89f405af4c..13fc5fd5a3e7 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h @@ -27,7 +27,7 @@ class RuntimeDyld; class RuntimeDyldCheckerImpl; class raw_ostream; -/// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has +/// RuntimeDyld invariant checker for verifying that RuntimeDyld has /// correctly applied relocations. /// /// The RuntimeDyldChecker class evaluates expressions against an attached @@ -74,22 +74,22 @@ public: MCInstPrinter *InstPrinter, raw_ostream &ErrStream); ~RuntimeDyldChecker(); - // \brief Get the associated RTDyld instance. + // Get the associated RTDyld instance. RuntimeDyld& getRTDyld(); - // \brief Get the associated RTDyld instance. + // Get the associated RTDyld instance. const RuntimeDyld& getRTDyld() const; - /// \brief Check a single expression against the attached RuntimeDyld + /// Check a single expression against the attached RuntimeDyld /// instance. bool check(StringRef CheckExpr) const; - /// \brief Scan the given memory buffer for lines beginning with the string + /// Scan the given memory buffer for lines beginning with the string /// in RulePrefix. The remainder of the line is passed to the check /// method to be evaluated as an expression. bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const; - /// \brief Returns the address of the requested section (or an error message + /// Returns the address of the requested section (or an error message /// in the second element of the pair if the address cannot be found). /// /// if 'LocalAddress' is true, this returns the address of the section @@ -99,7 +99,7 @@ public: StringRef SectionName, bool LocalAddress); - /// \brief If there is a section at the given local address, return its load + /// If there is a section at the given local address, return its load /// address, otherwise return none. Optional<uint64_t> getSectionLoadAddress(void *LocalAddress) const; diff --git a/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h b/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h index d76e37113c66..3cf131c27778 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/contrib/llvm/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -111,7 +111,7 @@ public: void operator=(const SectionMemoryManager &) = delete; ~SectionMemoryManager() override; - /// \brief Allocates a memory block of (at least) the given size suitable for + /// 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 @@ -120,7 +120,7 @@ public: unsigned SectionID, StringRef SectionName) override; - /// \brief Allocates a memory block of (at least) the given size suitable for + /// 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 @@ -129,7 +129,7 @@ public: unsigned SectionID, StringRef SectionName, bool isReadOnly) override; - /// \brief Update section-specific memory permissions and other attributes. + /// Update section-specific memory permissions and other attributes. /// /// This method is called when object loading is complete and section page /// permissions can be applied. It is up to the memory manager implementation @@ -142,7 +142,7 @@ public: /// \returns true if an error occurred, false otherwise. bool finalizeMemory(std::string *ErrMsg = nullptr) override; - /// \brief Invalidate instruction cache for code sections. + /// Invalidate instruction cache for code sections. /// /// Some platforms with separate data cache and instruction cache require /// explicit cache flush, otherwise JIT code manipulations (like resolved @@ -182,6 +182,8 @@ private: std::error_code applyMemoryGroupPermissions(MemoryGroup &MemGroup, unsigned Permissions); + void anchor() override; + MemoryGroup CodeMem; MemoryGroup RWDataMem; MemoryGroup RODataMem; diff --git a/contrib/llvm/include/llvm/FuzzMutate/FuzzerCLI.h b/contrib/llvm/include/llvm/FuzzMutate/FuzzerCLI.h index a775fdfb603e..3333e96db166 100644 --- a/contrib/llvm/include/llvm/FuzzMutate/FuzzerCLI.h +++ b/contrib/llvm/include/llvm/FuzzMutate/FuzzerCLI.h @@ -68,6 +68,12 @@ std::unique_ptr<Module> parseModule(const uint8_t *Data, size_t Size, /// returns 0 and leaves Dest unchanged. size_t writeModule(const Module &M, uint8_t *Dest, size_t MaxSize); +/// Try to parse module and verify it. May output verification errors to the +/// errs(). +/// \return New module or nullptr in case of error. +std::unique_ptr<Module> parseAndVerify(const uint8_t *Data, size_t Size, + LLVMContext &Context); + } // end llvm namespace #endif // LLVM_FUZZMUTATE_FUZZER_CLI_H diff --git a/contrib/llvm/include/llvm/FuzzMutate/OpDescriptor.h b/contrib/llvm/include/llvm/FuzzMutate/OpDescriptor.h index e9f8bf09a79b..dd30fda99bea 100644 --- a/contrib/llvm/include/llvm/FuzzMutate/OpDescriptor.h +++ b/contrib/llvm/include/llvm/FuzzMutate/OpDescriptor.h @@ -20,6 +20,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" #include <functional> @@ -128,7 +129,7 @@ static inline SourcePred anyFloatType() { static inline SourcePred anyPtrType() { auto Pred = [](ArrayRef<Value *>, const Value *V) { - return V->getType()->isPointerTy(); + return V->getType()->isPointerTy() && !V->isSwiftError(); }; auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) { std::vector<Constant *> Result; @@ -142,6 +143,9 @@ static inline SourcePred anyPtrType() { static inline SourcePred sizedPtrType() { auto Pred = [](ArrayRef<Value *>, const Value *V) { + if (V->isSwiftError()) + return false; + if (const auto *PtrT = dyn_cast<PointerType>(V->getType())) return PtrT->getElementType()->isSized(); return false; diff --git a/contrib/llvm/include/llvm/IR/Attributes.h b/contrib/llvm/include/llvm/IR/Attributes.h index a05a01073049..5aaaaf3c396b 100644 --- a/contrib/llvm/include/llvm/IR/Attributes.h +++ b/contrib/llvm/include/llvm/IR/Attributes.h @@ -6,11 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief This file contains the simple types necessary to represent the +/// This file contains the simple types necessary to represent the /// attributes associated with functions and their calls. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_IR_ATTRIBUTES_H @@ -22,6 +22,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include <bitset> #include <cassert> @@ -35,7 +36,6 @@ namespace llvm { class AttrBuilder; class AttributeImpl; class AttributeListImpl; -class AttributeList; class AttributeSetNode; template<typename T> struct DenseMapInfo; class Function; @@ -44,7 +44,7 @@ class Type; //===----------------------------------------------------------------------===// /// \class -/// \brief Functions, function parameters, and return types can have attributes +/// Functions, function parameters, and return types can have attributes /// to indicate how they should be treated by optimizations and code /// generation. This class represents one of those attributes. It's light-weight /// and should be passed around by-value. @@ -71,7 +71,7 @@ public: // IR-Level Attributes None, ///< No attributes have been set #define GET_ATTR_ENUM - #include "llvm/IR/Attributes.gen" + #include "llvm/IR/Attributes.inc" EndAttrKinds ///< Sentinal value useful for loops }; @@ -87,12 +87,12 @@ public: // Attribute Construction //===--------------------------------------------------------------------===// - /// \brief Return a uniquified Attribute object. + /// Return a uniquified Attribute object. static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val = 0); static Attribute get(LLVMContext &Context, StringRef Kind, StringRef Val = StringRef()); - /// \brief Return a uniquified Attribute object that has the specific + /// Return a uniquified Attribute object that has the specific /// alignment set. static Attribute getWithAlignment(LLVMContext &Context, uint64_t Align); static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align); @@ -108,51 +108,51 @@ public: // Attribute Accessors //===--------------------------------------------------------------------===// - /// \brief Return true if the attribute is an Attribute::AttrKind type. + /// Return true if the attribute is an Attribute::AttrKind type. bool isEnumAttribute() const; - /// \brief Return true if the attribute is an integer attribute. + /// Return true if the attribute is an integer attribute. bool isIntAttribute() const; - /// \brief Return true if the attribute is a string (target-dependent) + /// Return true if the attribute is a string (target-dependent) /// attribute. bool isStringAttribute() const; - /// \brief Return true if the attribute is present. + /// Return true if the attribute is present. bool hasAttribute(AttrKind Val) const; - /// \brief Return true if the target-dependent attribute is present. + /// Return true if the target-dependent attribute is present. bool hasAttribute(StringRef Val) const; - /// \brief Return the attribute's kind as an enum (Attribute::AttrKind). This + /// Return the attribute's kind as an enum (Attribute::AttrKind). This /// requires the attribute to be an enum or integer attribute. Attribute::AttrKind getKindAsEnum() const; - /// \brief Return the attribute's value as an integer. This requires that the + /// Return the attribute's value as an integer. This requires that the /// attribute be an integer attribute. uint64_t getValueAsInt() const; - /// \brief Return the attribute's kind as a string. This requires the + /// Return the attribute's kind as a string. This requires the /// attribute to be a string attribute. StringRef getKindAsString() const; - /// \brief Return the attribute's value as a string. This requires the + /// Return the attribute's value as a string. This requires the /// attribute to be a string attribute. StringRef getValueAsString() const; - /// \brief Returns the alignment field of an attribute as a byte alignment + /// Returns the alignment field of an attribute as a byte alignment /// value. unsigned getAlignment() const; - /// \brief Returns the stack alignment field of an attribute as a byte + /// Returns the stack alignment field of an attribute as a byte /// alignment value. unsigned getStackAlignment() const; - /// \brief Returns the number of dereferenceable bytes from the + /// Returns the number of dereferenceable bytes from the /// dereferenceable attribute. uint64_t getDereferenceableBytes() const; - /// \brief Returns the number of dereferenceable_or_null bytes from the + /// Returns the number of dereferenceable_or_null bytes from the /// dereferenceable_or_null attribute. uint64_t getDereferenceableOrNullBytes() const; @@ -160,27 +160,27 @@ public: /// if not known). std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const; - /// \brief The Attribute is converted to a string of equivalent mnemonic. This + /// The Attribute is converted to a string of equivalent mnemonic. This /// is, presumably, for writing out the mnemonics for the assembly writer. std::string getAsString(bool InAttrGrp = false) const; - /// \brief Equality and non-equality operators. + /// Equality and non-equality operators. bool operator==(Attribute A) const { return pImpl == A.pImpl; } bool operator!=(Attribute A) const { return pImpl != A.pImpl; } - /// \brief Less-than operator. Useful for sorting the attributes list. + /// Less-than operator. Useful for sorting the attributes list. bool operator<(Attribute A) const; void Profile(FoldingSetNodeID &ID) const { ID.AddPointer(pImpl); } - /// \brief Return a raw pointer that uniquely identifies this attribute. + /// Return a raw pointer that uniquely identifies this attribute. void *getRawPointer() const { return pImpl; } - /// \brief Get an attribute from a raw pointer created by getRawPointer. + /// Get an attribute from a raw pointer created by getRawPointer. static Attribute fromRawPointer(void *RawPtr) { return Attribute(reinterpret_cast<AttributeImpl*>(RawPtr)); } @@ -203,6 +203,9 @@ inline Attribute unwrap(LLVMAttributeRef Attr) { /// copy. Adding and removing enum attributes is intended to be fast, but adding /// and removing string or integer attributes involves a FoldingSet lookup. class AttributeSet { + friend AttributeListImpl; + template <typename Ty> friend struct DenseMapInfo; + // TODO: Extract AvailableAttrs from AttributeSetNode and store them here. // This will allow an efficient implementation of addAttribute and // removeAttribute for enum attrs. @@ -210,9 +213,6 @@ class AttributeSet { /// Private implementation pointer. AttributeSetNode *SetNode = nullptr; - friend AttributeListImpl; - template <typename Ty> friend struct DenseMapInfo; - private: explicit AttributeSet(AttributeSetNode *ASN) : SetNode(ASN) {} @@ -290,16 +290,16 @@ public: //===----------------------------------------------------------------------===// /// \class -/// \brief Provide DenseMapInfo for AttributeSet. +/// Provide DenseMapInfo for AttributeSet. template <> struct DenseMapInfo<AttributeSet> { - static inline AttributeSet getEmptyKey() { - uintptr_t Val = static_cast<uintptr_t>(-1); + static AttributeSet getEmptyKey() { + auto Val = static_cast<uintptr_t>(-1); Val <<= PointerLikeTypeTraits<void *>::NumLowBitsAvailable; return AttributeSet(reinterpret_cast<AttributeSetNode *>(Val)); } - static inline AttributeSet getTombstoneKey() { - uintptr_t Val = static_cast<uintptr_t>(-2); + static AttributeSet getTombstoneKey() { + auto Val = static_cast<uintptr_t>(-2); Val <<= PointerLikeTypeTraits<void *>::NumLowBitsAvailable; return AttributeSet(reinterpret_cast<AttributeSetNode *>(Val)); } @@ -314,7 +314,7 @@ template <> struct DenseMapInfo<AttributeSet> { //===----------------------------------------------------------------------===// /// \class -/// \brief This class holds the attributes for a function, its return value, and +/// This class holds the attributes for a function, its return value, and /// its parameters. You access the attributes for each of them via an index into /// the AttributeList object. The function attributes are at index /// `AttributeList::FunctionIndex', the return value is at index @@ -333,21 +333,20 @@ private: friend class AttributeListImpl; friend class AttributeSet; friend class AttributeSetNode; - template <typename Ty> friend struct DenseMapInfo; - /// \brief The attributes that we are managing. This can be null to represent + /// The attributes that we are managing. This can be null to represent /// the empty attributes list. AttributeListImpl *pImpl = nullptr; public: - /// \brief Create an AttributeList with the specified parameters in it. + /// Create an AttributeList with the specified parameters in it. static AttributeList get(LLVMContext &C, ArrayRef<std::pair<unsigned, Attribute>> Attrs); static AttributeList get(LLVMContext &C, ArrayRef<std::pair<unsigned, AttributeSet>> Attrs); - /// \brief Create an AttributeList from attribute sets for a function, its + /// Create an AttributeList from attribute sets for a function, its /// return value, and all of its arguments. static AttributeList get(LLVMContext &C, AttributeSet FnAttrs, AttributeSet RetAttrs, @@ -365,7 +364,7 @@ public: // AttributeList Construction and Mutation //===--------------------------------------------------------------------===// - /// \brief Return an AttributeList with the specified parameters in it. + /// Return an AttributeList with the specified parameters in it. static AttributeList get(LLVMContext &C, ArrayRef<AttributeList> Attrs); static AttributeList get(LLVMContext &C, unsigned Index, ArrayRef<Attribute::AttrKind> Kinds); @@ -374,12 +373,12 @@ public: static AttributeList get(LLVMContext &C, unsigned Index, const AttrBuilder &B); - /// \brief Add an attribute to the attribute set at the given index. + /// Add an attribute to the attribute set at the given index. /// Returns a new list because attribute lists are immutable. AttributeList addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const; - /// \brief Add an attribute to the attribute set at the given index. + /// Add an attribute to the attribute set at the given index. /// Returns a new list because attribute lists are immutable. AttributeList addAttribute(LLVMContext &C, unsigned Index, StringRef Kind, StringRef Value = StringRef()) const; @@ -388,7 +387,7 @@ public: /// Returns a new list because attribute lists are immutable. AttributeList addAttribute(LLVMContext &C, unsigned Index, Attribute A) const; - /// \brief Add attributes to the attribute set at the given index. + /// Add attributes to the attribute set at the given index. /// Returns a new list because attribute lists are immutable. AttributeList addAttributes(LLVMContext &C, unsigned Index, const AttrBuilder &B) const; @@ -420,70 +419,70 @@ public: return addAttributes(C, ArgNo + FirstArgIndex, B); } - /// \brief Remove the specified attribute at the specified index from this + /// Remove the specified attribute at the specified index from this /// attribute list. Returns a new list because attribute lists are immutable. AttributeList removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const; - /// \brief Remove the specified attribute at the specified index from this + /// Remove the specified attribute at the specified index from this /// attribute list. Returns a new list because attribute lists are immutable. AttributeList removeAttribute(LLVMContext &C, unsigned Index, StringRef Kind) const; - /// \brief Remove the specified attributes at the specified index from this + /// Remove the specified attributes at the specified index from this /// attribute list. Returns a new list because attribute lists are immutable. AttributeList removeAttributes(LLVMContext &C, unsigned Index, const AttrBuilder &AttrsToRemove) const; - /// \brief Remove all attributes at the specified index from this + /// Remove all attributes at the specified index from this /// attribute list. Returns a new list because attribute lists are immutable. AttributeList removeAttributes(LLVMContext &C, unsigned Index) const; - /// \brief Remove the specified attribute at the specified arg index from this + /// Remove the specified attribute at the specified arg index from this /// attribute list. Returns a new list because attribute lists are immutable. AttributeList removeParamAttribute(LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind) const { return removeAttribute(C, ArgNo + FirstArgIndex, Kind); } - /// \brief Remove the specified attribute at the specified arg index from this + /// Remove the specified attribute at the specified arg index from this /// attribute list. Returns a new list because attribute lists are immutable. AttributeList removeParamAttribute(LLVMContext &C, unsigned ArgNo, StringRef Kind) const { return removeAttribute(C, ArgNo + FirstArgIndex, Kind); } - /// \brief Remove the specified attribute at the specified arg index from this + /// Remove the specified attribute at the specified arg index from this /// attribute list. Returns a new list because attribute lists are immutable. AttributeList removeParamAttributes(LLVMContext &C, unsigned ArgNo, const AttrBuilder &AttrsToRemove) const { return removeAttributes(C, ArgNo + FirstArgIndex, AttrsToRemove); } - /// \brief Remove all attributes at the specified arg index from this + /// Remove all attributes at the specified arg index from this /// attribute list. Returns a new list because attribute lists are immutable. AttributeList removeParamAttributes(LLVMContext &C, unsigned ArgNo) const { return removeAttributes(C, ArgNo + FirstArgIndex); } - /// \Brief Add the dereferenceable attribute to the attribute set at the given + /// \brief Add the dereferenceable attribute to the attribute set at the given /// index. Returns a new list because attribute lists are immutable. AttributeList addDereferenceableAttr(LLVMContext &C, unsigned Index, uint64_t Bytes) const; - /// \Brief Add the dereferenceable attribute to the attribute set at the given + /// \brief Add the dereferenceable attribute to the attribute set at the given /// arg index. Returns a new list because attribute lists are immutable. AttributeList addDereferenceableParamAttr(LLVMContext &C, unsigned ArgNo, uint64_t Bytes) const { return addDereferenceableAttr(C, ArgNo + FirstArgIndex, Bytes); } - /// \brief Add the dereferenceable_or_null attribute to the attribute set at + /// Add the dereferenceable_or_null attribute to the attribute set at /// the given index. Returns a new list because attribute lists are immutable. AttributeList addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index, uint64_t Bytes) const; - /// \brief Add the dereferenceable_or_null attribute to the attribute set at + /// Add the dereferenceable_or_null attribute to the attribute set at /// the given arg index. Returns a new list because attribute lists are /// immutable. AttributeList addDereferenceableOrNullParamAttr(LLVMContext &C, @@ -510,102 +509,102 @@ public: // AttributeList Accessors //===--------------------------------------------------------------------===// - /// \brief Retrieve the LLVM context. + /// Retrieve the LLVM context. LLVMContext &getContext() const; - /// \brief The attributes for the specified index are returned. + /// The attributes for the specified index are returned. AttributeSet getAttributes(unsigned Index) const; - /// \brief The attributes for the argument or parameter at the given index are + /// The attributes for the argument or parameter at the given index are /// returned. AttributeSet getParamAttributes(unsigned ArgNo) const; - /// \brief The attributes for the ret value are returned. + /// The attributes for the ret value are returned. AttributeSet getRetAttributes() const; - /// \brief The function attributes are returned. + /// The function attributes are returned. AttributeSet getFnAttributes() const; - /// \brief Return true if the attribute exists at the given index. + /// Return true if the attribute exists at the given index. bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const; - /// \brief Return true if the attribute exists at the given index. + /// Return true if the attribute exists at the given index. bool hasAttribute(unsigned Index, StringRef Kind) const; - /// \brief Return true if attribute exists at the given index. + /// Return true if attribute exists at the given index. bool hasAttributes(unsigned Index) const; - /// \brief Return true if the attribute exists for the given argument + /// Return true if the attribute exists for the given argument bool hasParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { return hasAttribute(ArgNo + FirstArgIndex, Kind); } - /// \brief Return true if the attribute exists for the given argument + /// Return true if the attribute exists for the given argument bool hasParamAttr(unsigned ArgNo, StringRef Kind) const { return hasAttribute(ArgNo + FirstArgIndex, Kind); } - /// \brief Return true if attributes exists for the given argument + /// Return true if attributes exists for the given argument bool hasParamAttrs(unsigned ArgNo) const { return hasAttributes(ArgNo + FirstArgIndex); } - /// \brief Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but + /// Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but /// may be faster. bool hasFnAttribute(Attribute::AttrKind Kind) const; - /// \brief Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but + /// Equivalent to hasAttribute(AttributeList::FunctionIndex, Kind) but /// may be faster. bool hasFnAttribute(StringRef Kind) const; - /// \brief Equivalent to hasAttribute(ArgNo + FirstArgIndex, Kind). + /// Equivalent to hasAttribute(ArgNo + FirstArgIndex, Kind). bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const; - /// \brief Return true if the specified attribute is set for at least one + /// Return true if the specified attribute is set for at least one /// parameter or for the return value. If Index is not nullptr, the index /// of a parameter with the specified attribute is provided. bool hasAttrSomewhere(Attribute::AttrKind Kind, unsigned *Index = nullptr) const; - /// \brief Return the attribute object that exists at the given index. + /// Return the attribute object that exists at the given index. Attribute getAttribute(unsigned Index, Attribute::AttrKind Kind) const; - /// \brief Return the attribute object that exists at the given index. + /// Return the attribute object that exists at the given index. Attribute getAttribute(unsigned Index, StringRef Kind) const; - /// \brief Return the attribute object that exists at the arg index. + /// Return the attribute object that exists at the arg index. Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { return getAttribute(ArgNo + FirstArgIndex, Kind); } - /// \brief Return the attribute object that exists at the given index. + /// Return the attribute object that exists at the given index. Attribute getParamAttr(unsigned ArgNo, StringRef Kind) const { return getAttribute(ArgNo + FirstArgIndex, Kind); } - /// \brief Return the alignment of the return value. + /// Return the alignment of the return value. unsigned getRetAlignment() const; - /// \brief Return the alignment for the specified function parameter. + /// Return the alignment for the specified function parameter. unsigned getParamAlignment(unsigned ArgNo) const; - /// \brief Get the stack alignment. + /// Get the stack alignment. unsigned getStackAlignment(unsigned Index) const; - /// \brief Get the number of dereferenceable bytes (or zero if unknown). + /// Get the number of dereferenceable bytes (or zero if unknown). uint64_t getDereferenceableBytes(unsigned Index) const; - /// \brief Get the number of dereferenceable bytes (or zero if unknown) of an + /// Get the number of dereferenceable bytes (or zero if unknown) of an /// arg. uint64_t getParamDereferenceableBytes(unsigned ArgNo) const { return getDereferenceableBytes(ArgNo + FirstArgIndex); } - /// \brief Get the number of dereferenceable_or_null bytes (or zero if + /// Get the number of dereferenceable_or_null bytes (or zero if /// unknown). uint64_t getDereferenceableOrNullBytes(unsigned Index) const; - /// \brief Get the number of dereferenceable_or_null bytes (or zero if + /// Get the number of dereferenceable_or_null bytes (or zero if /// unknown) of an arg. uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const { return getDereferenceableOrNullBytes(ArgNo + FirstArgIndex); @@ -615,7 +614,7 @@ public: std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs(unsigned Index) const; - /// \brief Return the attributes at the index as a string. + /// Return the attributes at the index as a string. std::string getAsString(unsigned Index, bool InAttrGrp = false) const; //===--------------------------------------------------------------------===// @@ -637,12 +636,12 @@ public: bool operator==(const AttributeList &RHS) const { return pImpl == RHS.pImpl; } bool operator!=(const AttributeList &RHS) const { return pImpl != RHS.pImpl; } - /// \brief Return a raw pointer that uniquely identifies this attribute list. + /// Return a raw pointer that uniquely identifies this attribute list. void *getRawPointer() const { return pImpl; } - /// \brief Return true if there are no attributes. + /// Return true if there are no attributes. bool isEmpty() const { return pImpl == nullptr; } void dump() const; @@ -650,16 +649,16 @@ public: //===----------------------------------------------------------------------===// /// \class -/// \brief Provide DenseMapInfo for AttributeList. +/// Provide DenseMapInfo for AttributeList. template <> struct DenseMapInfo<AttributeList> { - static inline AttributeList getEmptyKey() { - uintptr_t Val = static_cast<uintptr_t>(-1); + static AttributeList getEmptyKey() { + auto Val = static_cast<uintptr_t>(-1); Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable; return AttributeList(reinterpret_cast<AttributeListImpl *>(Val)); } - static inline AttributeList getTombstoneKey() { - uintptr_t Val = static_cast<uintptr_t>(-2); + static AttributeList getTombstoneKey() { + auto Val = static_cast<uintptr_t>(-2); Val <<= PointerLikeTypeTraits<void*>::NumLowBitsAvailable; return AttributeList(reinterpret_cast<AttributeListImpl *>(Val)); } @@ -676,7 +675,7 @@ template <> struct DenseMapInfo<AttributeList> { //===----------------------------------------------------------------------===// /// \class -/// \brief This class is used in conjunction with the Attribute::get method to +/// This class is used in conjunction with the Attribute::get method to /// create an Attribute object. The object itself is uniquified. The Builder's /// value, however, is not. So this can be used as a quick way to test for /// equality, presence of attributes, etc. @@ -691,73 +690,75 @@ class AttrBuilder { public: AttrBuilder() = default; + AttrBuilder(const Attribute &A) { addAttribute(A); } + AttrBuilder(AttributeList AS, unsigned Idx); AttrBuilder(AttributeSet AS); void clear(); - /// \brief Add an attribute to the builder. + /// Add an attribute to the builder. AttrBuilder &addAttribute(Attribute::AttrKind Val); - /// \brief Add the Attribute object to the builder. + /// Add the Attribute object to the builder. AttrBuilder &addAttribute(Attribute A); - /// \brief Add the target-dependent attribute to the builder. + /// Add the target-dependent attribute to the builder. AttrBuilder &addAttribute(StringRef A, StringRef V = StringRef()); - /// \brief Remove an attribute from the builder. + /// Remove an attribute from the builder. AttrBuilder &removeAttribute(Attribute::AttrKind Val); - /// \brief Remove the attributes from the builder. + /// Remove the attributes from the builder. AttrBuilder &removeAttributes(AttributeList A, uint64_t WithoutIndex); - /// \brief Remove the target-dependent attribute to the builder. + /// Remove the target-dependent attribute to the builder. AttrBuilder &removeAttribute(StringRef A); - /// \brief Add the attributes from the builder. + /// Add the attributes from the builder. AttrBuilder &merge(const AttrBuilder &B); - /// \brief Remove the attributes from the builder. + /// Remove the attributes from the builder. AttrBuilder &remove(const AttrBuilder &B); - /// \brief Return true if the builder has any attribute that's in the + /// Return true if the builder has any attribute that's in the /// specified builder. bool overlaps(const AttrBuilder &B) const; - /// \brief Return true if the builder has the specified attribute. + /// Return true if the builder has the specified attribute. bool contains(Attribute::AttrKind A) const { assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!"); return Attrs[A]; } - /// \brief Return true if the builder has the specified target-dependent + /// Return true if the builder has the specified target-dependent /// attribute. bool contains(StringRef A) const; - /// \brief Return true if the builder has IR-level attributes. + /// Return true if the builder has IR-level attributes. bool hasAttributes() const; - /// \brief Return true if the builder has any attribute that's in the + /// Return true if the builder has any attribute that's in the /// specified attribute. bool hasAttributes(AttributeList A, uint64_t Index) const; - /// \brief Return true if the builder has an alignment attribute. + /// Return true if the builder has an alignment attribute. bool hasAlignmentAttr() const; - /// \brief Retrieve the alignment attribute, if it exists. + /// Retrieve the alignment attribute, if it exists. uint64_t getAlignment() const { return Alignment; } - /// \brief Retrieve the stack alignment attribute, if it exists. + /// Retrieve the stack alignment attribute, if it exists. uint64_t getStackAlignment() const { return StackAlignment; } - /// \brief Retrieve the number of dereferenceable bytes, if the + /// Retrieve the number of dereferenceable bytes, if the /// dereferenceable attribute exists (zero is returned otherwise). uint64_t getDereferenceableBytes() const { return DerefBytes; } - /// \brief Retrieve the number of dereferenceable_or_null bytes, if the + /// Retrieve the number of dereferenceable_or_null bytes, if the /// dereferenceable_or_null attribute exists (zero is returned otherwise). uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; } @@ -765,19 +766,19 @@ public: /// doesn't exist, pair(0, 0) is returned. std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const; - /// \brief This turns an int alignment (which must be a power of 2) into the + /// This turns an int alignment (which must be a power of 2) into the /// form used internally in Attribute. AttrBuilder &addAlignmentAttr(unsigned Align); - /// \brief This turns an int stack alignment (which must be a power of 2) into + /// This turns an int stack alignment (which must be a power of 2) into /// the form used internally in Attribute. AttrBuilder &addStackAlignmentAttr(unsigned Align); - /// \brief This turns the number of dereferenceable bytes into the form used + /// This turns the number of dereferenceable bytes into the form used /// internally in Attribute. AttrBuilder &addDereferenceableAttr(uint64_t Bytes); - /// \brief This turns the number of dereferenceable_or_null bytes into the + /// This turns the number of dereferenceable_or_null bytes into the /// form used internally in Attribute. AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes); @@ -789,7 +790,7 @@ public: /// Attribute.getIntValue(). AttrBuilder &addAllocSizeAttrFromRawRepr(uint64_t RawAllocSizeRepr); - /// \brief Return true if the builder contains no target-independent + /// Return true if the builder contains no target-independent /// attributes. bool empty() const { return Attrs.none(); } @@ -800,18 +801,19 @@ public: using td_range = iterator_range<td_iterator>; using td_const_range = iterator_range<td_const_iterator>; - td_iterator td_begin() { return TargetDepAttrs.begin(); } - td_iterator td_end() { return TargetDepAttrs.end(); } + td_iterator td_begin() { return TargetDepAttrs.begin(); } + td_iterator td_end() { return TargetDepAttrs.end(); } td_const_iterator td_begin() const { return TargetDepAttrs.begin(); } - td_const_iterator td_end() const { return TargetDepAttrs.end(); } + td_const_iterator td_end() const { return TargetDepAttrs.end(); } td_range td_attrs() { return td_range(td_begin(), td_end()); } + td_const_range td_attrs() const { return td_const_range(td_begin(), td_end()); } - bool td_empty() const { return TargetDepAttrs.empty(); } + bool td_empty() const { return TargetDepAttrs.empty(); } bool operator==(const AttrBuilder &B); bool operator!=(const AttrBuilder &B) { @@ -821,14 +823,14 @@ public: namespace AttributeFuncs { -/// \brief Which attributes cannot be applied to a type. +/// Which attributes cannot be applied to a type. AttrBuilder typeIncompatible(Type *Ty); /// \returns Return true if the two functions have compatible target-independent /// attributes for inlining purposes. bool areInlineCompatible(const Function &Caller, const Function &Callee); -/// \brief Merge caller's and callee's attributes. +/// Merge caller's and callee's attributes. void mergeAttributesForInlining(Function &Caller, const Function &Callee); } // end namespace AttributeFuncs diff --git a/contrib/llvm/include/llvm/IR/Attributes.td b/contrib/llvm/include/llvm/IR/Attributes.td index ebe5c1985875..1019f867aab0 100644 --- a/contrib/llvm/include/llvm/IR/Attributes.td +++ b/contrib/llvm/include/llvm/IR/Attributes.td @@ -106,9 +106,15 @@ def NoRedZone : EnumAttr<"noredzone">; /// Mark the function as not returning. def NoReturn : EnumAttr<"noreturn">; +/// Disable Indirect Branch Tracking. +def NoCfCheck : EnumAttr<"nocf_check">; + /// Function doesn't unwind stack. def NoUnwind : EnumAttr<"nounwind">; +/// Select optimizations for best fuzzing signal. +def OptForFuzzing : EnumAttr<"optforfuzzing">; + /// opt_size. def OptimizeForSize : EnumAttr<"optsize">; @@ -130,6 +136,9 @@ def ReturnsTwice : EnumAttr<"returns_twice">; /// Safe Stack protection. def SafeStack : EnumAttr<"safestack">; +/// Shadow Call Stack protection. +def ShadowCallStack : EnumAttr<"shadowcallstack">; + /// Sign extended before/after call. def SExt : EnumAttr<"signext">; @@ -205,6 +214,7 @@ def : CompatRule<"isEqual<SanitizeThreadAttr>">; def : CompatRule<"isEqual<SanitizeMemoryAttr>">; def : CompatRule<"isEqual<SanitizeHWAddressAttr>">; def : CompatRule<"isEqual<SafeStackAttr>">; +def : CompatRule<"isEqual<ShadowCallStackAttr>">; class MergeRule<string F> { // The name of the function called to merge the attributes of the caller and @@ -225,3 +235,4 @@ def : MergeRule<"setOR<ProfileSampleAccurateAttr>">; def : MergeRule<"adjustCallerSSPLevel">; def : MergeRule<"adjustCallerStackProbes">; def : MergeRule<"adjustCallerStackProbeSize">; +def : MergeRule<"adjustMinLegalVectorWidth">; diff --git a/contrib/llvm/include/llvm/IR/AutoUpgrade.h b/contrib/llvm/include/llvm/IR/AutoUpgrade.h index 3f406f0cf196..8cf574c6a138 100644 --- a/contrib/llvm/include/llvm/IR/AutoUpgrade.h +++ b/contrib/llvm/include/llvm/IR/AutoUpgrade.h @@ -37,6 +37,10 @@ namespace llvm { /// intrinsic function with a call to the specified new function. void UpgradeIntrinsicCall(CallInst *CI, Function *NewFn); + // This upgrades the comment for objc retain release markers in inline asm + // calls + void UpgradeInlineAsmString(std::string *AsmStr); + /// This is an auto-upgrade hook for any old intrinsic function syntaxes /// which need to have both the function updated as well as all calls updated /// to the new function. This should only be run in a post-processing fashion @@ -51,6 +55,10 @@ namespace llvm { /// module is modified. bool UpgradeModuleFlags(Module &M); + /// This checks for objc retain release marker which should be upgraded. It + /// returns true if module is modified. + bool UpgradeRetainReleaseMarker(Module &M); + void UpgradeSectionAttributes(Module &M); /// If the given TBAA tag uses the scalar TBAA format, create a new node diff --git a/contrib/llvm/include/llvm/IR/BasicBlock.h b/contrib/llvm/include/llvm/IR/BasicBlock.h index 77cfc9776df0..1ee19975af75 100644 --- a/contrib/llvm/include/llvm/IR/BasicBlock.h +++ b/contrib/llvm/include/llvm/IR/BasicBlock.h @@ -41,7 +41,7 @@ class PHINode; class TerminatorInst; class ValueSymbolTable; -/// \brief LLVM Basic Block Representation +/// LLVM Basic Block Representation /// /// This represents a single basic block in LLVM. A basic block is simply a /// container of instructions that execute sequentially. Basic blocks are Values @@ -70,7 +70,7 @@ private: void setParent(Function *parent); - /// \brief Constructor. + /// Constructor. /// /// If the function parameter is specified, the basic block is automatically /// inserted at either the end of the function (if InsertBefore is null), or @@ -84,7 +84,7 @@ public: BasicBlock &operator=(const BasicBlock &) = delete; ~BasicBlock(); - /// \brief Get the context in which this basic block lives. + /// Get the context in which this basic block lives. LLVMContext &getContext() const; /// Instruction iterators... @@ -93,7 +93,7 @@ public: using reverse_iterator = InstListType::reverse_iterator; using const_reverse_iterator = InstListType::const_reverse_iterator; - /// \brief Creates a new BasicBlock. + /// Creates a new BasicBlock. /// /// If the Parent parameter is specified, the basic block is automatically /// inserted at either the end of the function (if InsertBefore is 0), or @@ -104,12 +104,12 @@ public: return new BasicBlock(Context, Name, Parent, InsertBefore); } - /// \brief Return the enclosing method, or null if none. + /// Return the enclosing method, or null if none. const Function *getParent() const { return Parent; } Function *getParent() { return Parent; } - /// \brief Return the module owning the function this basic block belongs to, - /// or nullptr it the function does not have a module. + /// Return the module owning the function this basic block belongs to, or + /// nullptr if the function does not have a module. /// /// Note: this is undefined behavior if the block does not have a parent. const Module *getModule() const; @@ -118,34 +118,34 @@ public: static_cast<const BasicBlock *>(this)->getModule()); } - /// \brief Returns the terminator instruction if the block is well formed or - /// null if the block is not well formed. + /// Returns the terminator instruction if the block is well formed or null + /// if the block is not well formed. const TerminatorInst *getTerminator() const LLVM_READONLY; TerminatorInst *getTerminator() { return const_cast<TerminatorInst *>( static_cast<const BasicBlock *>(this)->getTerminator()); } - /// \brief Returns the call instruction calling @llvm.experimental.deoptimize - /// prior to the terminating return instruction of this basic block, if such a - /// call is present. Otherwise, returns null. + /// Returns the call instruction calling \@llvm.experimental.deoptimize + /// prior to the terminating return instruction of this basic block, if such + /// a call is present. Otherwise, returns null. const CallInst *getTerminatingDeoptimizeCall() const; CallInst *getTerminatingDeoptimizeCall() { return const_cast<CallInst *>( static_cast<const BasicBlock *>(this)->getTerminatingDeoptimizeCall()); } - /// \brief Returns the call instruction marked 'musttail' prior to the - /// terminating return instruction of this basic block, if such a call is - /// present. Otherwise, returns null. + /// Returns the call instruction marked 'musttail' prior to the terminating + /// return instruction of this basic block, if such a call is present. + /// Otherwise, returns null. const CallInst *getTerminatingMustTailCall() const; CallInst *getTerminatingMustTailCall() { return const_cast<CallInst *>( static_cast<const BasicBlock *>(this)->getTerminatingMustTailCall()); } - /// \brief Returns a pointer to the first instruction in this block that is - /// not a PHINode instruction. + /// Returns a pointer to the first instruction in this block that is not a + /// PHINode instruction. /// /// When adding instructions to the beginning of the basic block, they should /// be added before the returned value, not before the first instruction, @@ -156,23 +156,23 @@ public: static_cast<const BasicBlock *>(this)->getFirstNonPHI()); } - /// \brief Returns a pointer to the first instruction in this block that is not - /// a PHINode or a debug intrinsic. + /// Returns a pointer to the first instruction in this block that is not a + /// PHINode or a debug intrinsic. const Instruction* getFirstNonPHIOrDbg() const; Instruction* getFirstNonPHIOrDbg() { return const_cast<Instruction *>( static_cast<const BasicBlock *>(this)->getFirstNonPHIOrDbg()); } - /// \brief Returns a pointer to the first instruction in this block that is not - /// a PHINode, a debug intrinsic, or a lifetime intrinsic. + /// Returns a pointer to the first instruction in this block that is not a + /// PHINode, a debug intrinsic, or a lifetime intrinsic. const Instruction* getFirstNonPHIOrDbgOrLifetime() const; Instruction* getFirstNonPHIOrDbgOrLifetime() { return const_cast<Instruction *>( static_cast<const BasicBlock *>(this)->getFirstNonPHIOrDbgOrLifetime()); } - /// \brief Returns an iterator to the first instruction in this block that is + /// Returns an iterator to the first instruction in this block that is /// suitable for inserting a non-PHI instruction. /// /// In particular, it skips all PHIs and LandingPad instructions. @@ -182,23 +182,35 @@ public: ->getFirstInsertionPt().getNonConst(); } - /// \brief Unlink 'this' from the containing function, but do not delete it. + /// Return a const iterator range over the instructions in the block, skipping + /// any debug instructions. + iterator_range<filter_iterator<BasicBlock::const_iterator, + std::function<bool(const Instruction &)>>> + instructionsWithoutDebug() const; + + /// Return an iterator range over the instructions in the block, skipping any + /// debug instructions. + iterator_range<filter_iterator<BasicBlock::iterator, + std::function<bool(Instruction &)>>> + instructionsWithoutDebug(); + + /// Unlink 'this' from the containing function, but do not delete it. void removeFromParent(); - /// \brief Unlink 'this' from the containing function and delete it. + /// Unlink 'this' from the containing function and delete it. /// // \returns an iterator pointing to the element after the erased one. SymbolTableList<BasicBlock>::iterator eraseFromParent(); - /// \brief Unlink this basic block from its current function and insert it - /// into the function that \p MovePos lives in, right before \p MovePos. + /// Unlink this basic block from its current function and insert it into + /// the function that \p MovePos lives in, right before \p MovePos. void moveBefore(BasicBlock *MovePos); - /// \brief Unlink this basic block from its current function and insert it + /// Unlink this basic block from its current function and insert it /// right after \p MovePos in the function \p MovePos lives in. void moveAfter(BasicBlock *MovePos); - /// \brief Insert unlinked basic block into a function. + /// Insert unlinked basic block into a function. /// /// Inserts an unlinked basic block into \c Parent. If \c InsertBefore is /// provided, inserts before that basic block, otherwise inserts at the end. @@ -206,7 +218,7 @@ public: /// \pre \a getParent() is \c nullptr. void insertInto(Function *Parent, BasicBlock *InsertBefore = nullptr); - /// \brief Return the predecessor of this block if it has a single predecessor + /// Return the predecessor of this block if it has a single predecessor /// block. Otherwise return a null pointer. const BasicBlock *getSinglePredecessor() const; BasicBlock *getSinglePredecessor() { @@ -214,7 +226,7 @@ public: static_cast<const BasicBlock *>(this)->getSinglePredecessor()); } - /// \brief Return the predecessor of this block if it has a unique predecessor + /// Return the predecessor of this block if it has a unique predecessor /// block. Otherwise return a null pointer. /// /// Note that unique predecessor doesn't mean single edge, there can be @@ -226,7 +238,7 @@ public: static_cast<const BasicBlock *>(this)->getUniquePredecessor()); } - /// \brief Return the successor of this block if it has a single successor. + /// Return the successor of this block if it has a single successor. /// Otherwise return a null pointer. /// /// This method is analogous to getSinglePredecessor above. @@ -236,7 +248,7 @@ public: static_cast<const BasicBlock *>(this)->getSingleSuccessor()); } - /// \brief Return the successor of this block if it has a unique successor. + /// Return the successor of this block if it has a unique successor. /// Otherwise return a null pointer. /// /// This method is analogous to getUniquePredecessor above. @@ -310,28 +322,28 @@ public: } iterator_range<phi_iterator> phis(); - /// \brief Return the underlying instruction list container. + /// Return the underlying instruction list container. /// /// Currently you need to access the underlying instruction list container /// directly if you want to modify it. const InstListType &getInstList() const { return InstList; } InstListType &getInstList() { return InstList; } - /// \brief Returns a pointer to a member of the instruction list. + /// Returns a pointer to a member of the instruction list. static InstListType BasicBlock::*getSublistAccess(Instruction*) { return &BasicBlock::InstList; } - /// \brief Returns a pointer to the symbol table if one exists. + /// Returns a pointer to the symbol table if one exists. ValueSymbolTable *getValueSymbolTable(); - /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. + /// Methods for support type inquiry through isa, cast, and dyn_cast. static bool classof(const Value *V) { return V->getValueID() == Value::BasicBlockVal; } - /// \brief Cause all subinstructions to "let go" of all the references that - /// said subinstructions are maintaining. + /// Cause all subinstructions to "let go" of all the references that said + /// subinstructions are maintaining. /// /// This allows one to 'delete' a whole class at a time, even though there may /// be circular references... first all references are dropped, and all use @@ -340,8 +352,8 @@ public: /// except operator delete. void dropAllReferences(); - /// \brief Notify the BasicBlock that the predecessor \p Pred is no longer - /// able to reach it. + /// Notify the BasicBlock that the predecessor \p Pred is no longer able to + /// reach it. /// /// This is actually not used to update the Predecessor list, but is actually /// used to update the PHI nodes that reside in the block. Note that this @@ -350,8 +362,7 @@ public: bool canSplitPredecessors() const; - /// \brief Split the basic block into two basic blocks at the specified - /// instruction. + /// Split the basic block into two basic blocks at the specified instruction. /// /// Note that all instructions BEFORE the specified iterator stay as part of /// the original basic block, an unconditional branch is added to the original @@ -371,37 +382,37 @@ public: return splitBasicBlock(I->getIterator(), BBName); } - /// \brief Returns true if there are any uses of this basic block other than + /// Returns true if there are any uses of this basic block other than /// direct branches, switches, etc. to it. bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; } - /// \brief Update all phi nodes in this basic block's successors to refer to - /// basic block \p New instead of to it. + /// Update all phi nodes in this basic block's successors to refer to basic + /// block \p New instead of to it. void replaceSuccessorsPhiUsesWith(BasicBlock *New); - /// \brief Return true if this basic block is an exception handling block. + /// Return true if this basic block is an exception handling block. bool isEHPad() const { return getFirstNonPHI()->isEHPad(); } - /// \brief Return true if this basic block is a landing pad. + /// Return true if this basic block is a landing pad. /// /// Being a ``landing pad'' means that the basic block is the destination of /// the 'unwind' edge of an invoke instruction. bool isLandingPad() const; - /// \brief Return the landingpad instruction associated with the landing pad. + /// Return the landingpad instruction associated with the landing pad. const LandingPadInst *getLandingPadInst() const; LandingPadInst *getLandingPadInst() { return const_cast<LandingPadInst *>( static_cast<const BasicBlock *>(this)->getLandingPadInst()); } - /// \brief Return true if it is legal to hoist instructions into this block. + /// Return true if it is legal to hoist instructions into this block. bool isLegalToHoistInto() const; Optional<uint64_t> getIrrLoopHeaderWeight() const; private: - /// \brief Increment the internal refcount of the number of BlockAddresses + /// Increment the internal refcount of the number of BlockAddresses /// referencing this BasicBlock by \p Amt. /// /// This is almost always 0, sometimes one possibly, but almost never 2, and @@ -412,8 +423,8 @@ private: "Refcount wrap-around"); } - /// \brief Shadow Value::setValueSubclassData with a private forwarding method - /// so that any future subclasses cannot accidentally use it. + /// Shadow Value::setValueSubclassData with a private forwarding method so + /// that any future subclasses cannot accidentally use it. void setValueSubclassData(unsigned short D) { Value::setValueSubclassData(D); } @@ -422,6 +433,10 @@ private: // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef) +/// Advance \p It while it points to a debug instruction and return the result. +/// This assumes that \p It is not at the end of a block. +BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It); + } // end namespace llvm #endif // LLVM_IR_BASICBLOCK_H diff --git a/contrib/llvm/include/llvm/IR/CFG.h b/contrib/llvm/include/llvm/IR/CFG.h index e259e42e1ce4..f4988e7f1fec 100644 --- a/contrib/llvm/include/llvm/IR/CFG.h +++ b/contrib/llvm/include/llvm/IR/CFG.h @@ -107,6 +107,9 @@ inline const_pred_iterator pred_end(const BasicBlock *BB) { inline bool pred_empty(const BasicBlock *BB) { return pred_begin(BB) == pred_end(BB); } +inline unsigned pred_size(const BasicBlock *BB) { + return std::distance(pred_begin(BB), pred_end(BB)); +} inline pred_range predecessors(BasicBlock *BB) { return pred_range(pred_begin(BB), pred_end(BB)); } @@ -140,6 +143,9 @@ inline succ_const_iterator succ_end(const BasicBlock *BB) { inline bool succ_empty(const BasicBlock *BB) { return succ_begin(BB) == succ_end(BB); } +inline unsigned succ_size(const BasicBlock *BB) { + return std::distance(succ_begin(BB), succ_end(BB)); +} inline succ_range successors(BasicBlock *BB) { return succ_range(succ_begin(BB), succ_end(BB)); } diff --git a/contrib/llvm/include/llvm/IR/CallSite.h b/contrib/llvm/include/llvm/IR/CallSite.h index 5b10da8f2aee..2162ccb982b0 100644 --- a/contrib/llvm/include/llvm/IR/CallSite.h +++ b/contrib/llvm/include/llvm/IR/CallSite.h @@ -637,7 +637,8 @@ public: if (hasRetAttr(Attribute::NonNull)) return true; else if (getDereferenceableBytes(AttributeList::ReturnIndex) > 0 && - getType()->getPointerAddressSpace() == 0) + !NullPointerIsDefined(getCaller(), + getType()->getPointerAddressSpace())) return true; return false; diff --git a/contrib/llvm/include/llvm/IR/CallingConv.h b/contrib/llvm/include/llvm/IR/CallingConv.h index 84fe836adc35..b9c02d7ed424 100644 --- a/contrib/llvm/include/llvm/IR/CallingConv.h +++ b/contrib/llvm/include/llvm/IR/CallingConv.h @@ -26,7 +26,7 @@ namespace CallingConv { /// A set of enums which specify the assigned numeric values for known llvm /// calling conventions. - /// @brief LLVM Calling Convention Representation + /// LLVM Calling Convention Representation enum { /// C - The default llvm calling convention, compatible with C. This /// convention is the only calling convention that supports varargs calls. @@ -139,11 +139,11 @@ namespace CallingConv { /// Intel_OCL_BI - Calling conventions for Intel OpenCL built-ins Intel_OCL_BI = 77, - /// \brief The C convention as specified in the x86-64 supplement to the + /// The C convention as specified in the x86-64 supplement to the /// System V ABI, used on most non-Windows systems. X86_64_SysV = 78, - /// \brief The C convention as implemented on Windows/x86-64 and + /// The C convention as implemented on Windows/x86-64 and /// AArch64. This 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, @@ -153,17 +153,17 @@ namespace CallingConv { /// registers to variadic functions. Win64 = 79, - /// \brief MSVC calling convention that passes vectors and vector aggregates + /// MSVC calling convention that passes vectors and vector aggregates /// in SSE registers. X86_VectorCall = 80, - /// \brief Calling convention used by HipHop Virtual Machine (HHVM) to + /// Calling convention used by HipHop Virtual Machine (HHVM) to /// perform calls to and from translation cache, and for calling PHP /// functions. /// HHVM calling convention supports tail/sibling call elimination. HHVM = 81, - /// \brief HHVM calling convention for invoking C/C++ helpers. + /// HHVM calling convention for invoking C/C++ helpers. HHVM_C = 82, /// X86_INTR - x86 hardware interrupt context. Callee may take one or two diff --git a/contrib/llvm/include/llvm/IR/Comdat.h b/contrib/llvm/include/llvm/IR/Comdat.h index fa87093ca50a..555121e928f7 100644 --- a/contrib/llvm/include/llvm/IR/Comdat.h +++ b/contrib/llvm/include/llvm/IR/Comdat.h @@ -16,6 +16,9 @@ #ifndef LLVM_IR_COMDAT_H #define LLVM_IR_COMDAT_H +#include "llvm-c/Types.h" +#include "llvm/Support/CBindingWrapping.h" + namespace llvm { class raw_ostream; @@ -55,6 +58,9 @@ private: SelectionKind SK = Any; }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Comdat, LLVMComdatRef) + inline raw_ostream &operator<<(raw_ostream &OS, const Comdat &C) { C.print(OS); return OS; diff --git a/contrib/llvm/include/llvm/IR/Constant.h b/contrib/llvm/include/llvm/IR/Constant.h index 0c94b58a3112..5fdf0ea00f00 100644 --- a/contrib/llvm/include/llvm/IR/Constant.h +++ b/contrib/llvm/include/llvm/IR/Constant.h @@ -38,7 +38,7 @@ class APInt; /// structurally equivalent constants will always have the same address. /// Constants are created on demand as needed and never deleted: thus clients /// don't have to worry about the lifetime of the objects. -/// @brief LLVM Constant Representation +/// LLVM Constant Representation class Constant : public User { protected: Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps) @@ -71,6 +71,26 @@ public: /// Return true if the value is the smallest signed value. bool isMinSignedValue() const; + /// Return true if this is a finite and non-zero floating-point scalar + /// constant or a vector constant with all finite and non-zero elements. + bool isFiniteNonZeroFP() const; + + /// Return true if this is a normal (as opposed to denormal) floating-point + /// scalar constant or a vector constant with all normal elements. + bool isNormalFP() const; + + /// Return true if this scalar has an exact multiplicative inverse or this + /// vector has an exact multiplicative inverse for each element in the vector. + bool hasExactInverseFP() const; + + /// Return true if this is a floating-point NaN constant or a vector + /// floating-point constant with all NaN elements. + bool isNaN() const; + + /// Return true if this is a vector constant that includes any undefined + /// elements. + bool containsUndefElement() const; + /// Return true if evaluation of this constant could trap. This is true for /// things like constant expressions that could divide by zero. bool canTrap() const; @@ -137,7 +157,7 @@ public: /// @returns the value for an integer or vector of integer constant of the /// given type that has all its bits set to true. - /// @brief Get the all ones value + /// Get the all ones value static Constant *getAllOnesValue(Type* Ty); /// Return the value for an integer or pointer constant, or a vector thereof, diff --git a/contrib/llvm/include/llvm/IR/ConstantRange.h b/contrib/llvm/include/llvm/IR/ConstantRange.h index 6889e2658244..1adda3269abc 100644 --- a/contrib/llvm/include/llvm/IR/ConstantRange.h +++ b/contrib/llvm/include/llvm/IR/ConstantRange.h @@ -54,7 +54,7 @@ public: /// Initialize a range to hold the single specified value. ConstantRange(APInt Value); - /// @brief Initialize a range of values explicitly. This will assert out if + /// Initialize a range of values explicitly. This will assert out if /// Lower==Upper and Lower != Min or Max value for its type. It will also /// assert out if the two APInt's are not the same bit width. ConstantRange(APInt Lower, APInt Upper); diff --git a/contrib/llvm/include/llvm/IR/Constants.h b/contrib/llvm/include/llvm/IR/Constants.h index 0094fd54992a..f9d5ebc560c7 100644 --- a/contrib/llvm/include/llvm/IR/Constants.h +++ b/contrib/llvm/include/llvm/IR/Constants.h @@ -80,7 +80,7 @@ public: //===----------------------------------------------------------------------===// /// This is the shared class of boolean and integer constants. This class /// represents both boolean and integral constants. -/// @brief Class for constant integers. +/// Class for constant integers. class ConstantInt final : public ConstantData { friend class Constant; @@ -107,7 +107,7 @@ public: /// to fit the type, unless isSigned is true, in which case the value will /// be interpreted as a 64-bit signed integer and sign-extended to fit /// the type. - /// @brief Get a ConstantInt for a specific value. + /// Get a ConstantInt for a specific value. static ConstantInt *get(IntegerType *Ty, uint64_t V, bool isSigned = false); @@ -115,7 +115,7 @@ public: /// value V will be canonicalized to a an unsigned APInt. Accessing it with /// either getSExtValue() or getZExtValue() will yield a correctly sized and /// signed value for the type Ty. - /// @brief Get a ConstantInt for a specific signed value. + /// Get a ConstantInt for a specific signed value. static ConstantInt *getSigned(IntegerType *Ty, int64_t V); static Constant *getSigned(Type *Ty, int64_t V); @@ -134,7 +134,7 @@ public: /// Return the constant as an APInt value reference. This allows clients to /// obtain a full-precision copy of the value. - /// @brief Return the constant's value. + /// Return the constant's value. inline const APInt &getValue() const { return Val; } @@ -145,7 +145,7 @@ public: /// Return the constant as a 64-bit unsigned integer value after it /// has been zero extended as appropriate for the type of this constant. Note /// that this method can assert if the value does not fit in 64 bits. - /// @brief Return the zero extended value. + /// Return the zero extended value. inline uint64_t getZExtValue() const { return Val.getZExtValue(); } @@ -153,7 +153,7 @@ public: /// Return the constant as a 64-bit integer value after it has been sign /// extended as appropriate for the type of this constant. Note that /// this method can assert if the value does not fit in 64 bits. - /// @brief Return the sign extended value. + /// Return the sign extended value. inline int64_t getSExtValue() const { return Val.getSExtValue(); } @@ -161,7 +161,7 @@ public: /// A helper method that can be used to determine if the constant contained /// within is equal to a constant. This only works for very small values, /// because this is all that can be represented with all types. - /// @brief Determine if this constant's value is same as an unsigned char. + /// Determine if this constant's value is same as an unsigned char. bool equalsInt(uint64_t V) const { return Val == V; } @@ -181,7 +181,7 @@ public: /// the signed version avoids callers having to convert a signed quantity /// to the appropriate unsigned type before calling the method. /// @returns true if V is a valid value for type Ty - /// @brief Determine if the value is in range for the given type. + /// Determine if the value is in range for the given type. static bool isValueValidForType(Type *Ty, uint64_t V); static bool isValueValidForType(Type *Ty, int64_t V); @@ -197,7 +197,7 @@ public: /// This is just a convenience method to make client code smaller for a /// common case. It also correctly performs the comparison without the /// potential for an assertion from getZExtValue(). - /// @brief Determine if the value is one. + /// Determine if the value is one. bool isOne() const { return Val.isOneValue(); } @@ -205,7 +205,7 @@ public: /// This function will return true iff every bit in this constant is set /// to true. /// @returns true iff this constant's bits are all set to true. - /// @brief Determine if the value is all ones. + /// Determine if the value is all ones. bool isMinusOne() const { return Val.isAllOnesValue(); } @@ -214,7 +214,7 @@ public: /// value that may be represented by the constant's type. /// @returns true iff this is the largest value that may be represented /// by this type. - /// @brief Determine if the value is maximal. + /// Determine if the value is maximal. bool isMaxValue(bool isSigned) const { if (isSigned) return Val.isMaxSignedValue(); @@ -226,7 +226,7 @@ public: /// value that may be represented by this constant's type. /// @returns true if this is the smallest value that may be represented by /// this type. - /// @brief Determine if the value is minimal. + /// Determine if the value is minimal. bool isMinValue(bool isSigned) const { if (isSigned) return Val.isMinSignedValue(); @@ -238,7 +238,7 @@ public: /// active bits bigger than 64 bits or a value greater than the given uint64_t /// value. /// @returns true iff this constant is greater or equal to the given number. - /// @brief Determine if the value is greater or equal to the given number. + /// Determine if the value is greater or equal to the given number. bool uge(uint64_t Num) const { return Val.uge(Num); } @@ -247,12 +247,12 @@ public: /// return it, otherwise return the limit value. This causes the value /// to saturate to the limit. /// @returns the min of the value of the constant and the specified value - /// @brief Get the constant's value with a saturation limit + /// Get the constant's value with a saturation limit uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { return Val.getLimitedValue(Limit); } - /// @brief Methods to support type inquiry through isa, cast, and dyn_cast. + /// Methods to support type inquiry through isa, cast, and dyn_cast. static bool classof(const Value *V) { return V->getValueID() == ConstantIntVal; } @@ -283,6 +283,11 @@ public: /// for simple constant values like 2.0/1.0 etc, that are known-valid both as /// host double and as the target format. static Constant *get(Type* Ty, double V); + + /// If Ty is a vector type, return a Constant with a splat of the given + /// value. Otherwise return a ConstantFP for the given value. + static Constant *get(Type *Ty, const APFloat &V); + static Constant *get(Type* Ty, StringRef Str); static ConstantFP *get(LLVMContext &Context, const APFloat &V); static Constant *getNaN(Type *Ty, bool Negative = false, unsigned type = 0); @@ -687,15 +692,33 @@ class ConstantDataArray final : public ConstantDataSequential { public: ConstantDataArray(const ConstantDataArray &) = delete; - /// get() constructors - Return a constant with array type with an element + /// get() constructor - Return a constant with array type with an element /// count and element type matching the ArrayRef passed in. Note that this /// can return a ConstantAggregateZero object. - static Constant *get(LLVMContext &Context, ArrayRef<uint8_t> Elts); - static Constant *get(LLVMContext &Context, ArrayRef<uint16_t> Elts); - static Constant *get(LLVMContext &Context, ArrayRef<uint32_t> Elts); - static Constant *get(LLVMContext &Context, ArrayRef<uint64_t> Elts); - static Constant *get(LLVMContext &Context, ArrayRef<float> Elts); - static Constant *get(LLVMContext &Context, ArrayRef<double> Elts); + template <typename ElementTy> + static Constant *get(LLVMContext &Context, ArrayRef<ElementTy> Elts) { + const char *Data = reinterpret_cast<const char *>(Elts.data()); + return getRaw(StringRef(Data, Elts.size() * sizeof(ElementTy)), Elts.size(), + Type::getScalarTy<ElementTy>(Context)); + } + + /// get() constructor - ArrayTy needs to be compatible with + /// ArrayRef<ElementTy>. Calls get(LLVMContext, ArrayRef<ElementTy>). + template <typename ArrayTy> + static Constant *get(LLVMContext &Context, ArrayTy &Elts) { + return ConstantDataArray::get(Context, makeArrayRef(Elts)); + } + + /// get() constructor - Return a constant with array type with an element + /// count and element type matching the NumElements and ElementTy parameters + /// passed in. Note that this can return a ConstantAggregateZero object. + /// ElementTy needs to be one of i8/i16/i32/i64/float/double. Data is the + /// buffer containing the elements. Be careful to make sure Data uses the + /// right endianness, the buffer will be used as-is. + static Constant *getRaw(StringRef Data, uint64_t NumElements, Type *ElementTy) { + Type *Ty = ArrayType::get(ElementTy, NumElements); + return getImpl(Data, Ty); + } /// getFP() constructors - Return a constant with array type with an element /// count and element type of float with precision matching the number of @@ -802,7 +825,7 @@ public: /// Return the ConstantTokenNone. static ConstantTokenNone *get(LLVMContext &Context); - /// @brief Methods to support type inquiry through isa, cast, and dyn_cast. + /// Methods to support type inquiry through isa, cast, and dyn_cast. static bool classof(const Value *V) { return V->getValueID() == ConstantTokenNoneVal; } @@ -995,10 +1018,15 @@ public: return getLShr(C1, C2, true); } - /// Return the identity for the given binary operation, - /// i.e. a constant C such that X op C = X and C op X = X for every X. It - /// returns null if the operator doesn't have an identity. - static Constant *getBinOpIdentity(unsigned Opcode, Type *Ty); + /// Return the identity constant for a binary opcode. + /// The identity constant C is defined as X op C = X and C op X = X for every + /// X when the binary operation is commutative. If the binop is not + /// commutative, callers can acquire the operand 1 identity constant by + /// setting AllowRHSConstant to true. For example, any shift has a zero + /// identity constant for operand 1: X shift 0 = X. + /// Return nullptr if the operator does not have an identity constant. + static Constant *getBinOpIdentity(unsigned Opcode, Type *Ty, + bool AllowRHSConstant = false); /// Return the absorbing element for the given binary /// operation, i.e. a constant C such that X op C = C and C op X = C for @@ -1009,7 +1037,7 @@ public: /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); - /// \brief Convenience function for getting a Cast operation. + /// Convenience function for getting a Cast operation. /// /// \param ops The opcode for the conversion /// \param C The constant to be converted @@ -1018,62 +1046,62 @@ public: static Constant *getCast(unsigned ops, Constant *C, Type *Ty, bool OnlyIfReduced = false); - // @brief Create a ZExt or BitCast cast constant expression + // Create a ZExt or BitCast cast constant expression static Constant *getZExtOrBitCast( Constant *C, ///< The constant to zext or bitcast Type *Ty ///< The type to zext or bitcast C to ); - // @brief Create a SExt or BitCast cast constant expression + // Create a SExt or BitCast cast constant expression static Constant *getSExtOrBitCast( Constant *C, ///< The constant to sext or bitcast Type *Ty ///< The type to sext or bitcast C to ); - // @brief Create a Trunc or BitCast cast constant expression + // Create a Trunc or BitCast cast constant expression static Constant *getTruncOrBitCast( Constant *C, ///< The constant to trunc or bitcast Type *Ty ///< The type to trunc or bitcast C to ); - /// @brief Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant + /// Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant /// expression. static Constant *getPointerCast( Constant *C, ///< The pointer value to be casted (operand 0) Type *Ty ///< The type to which cast should be made ); - /// @brief Create a BitCast or AddrSpaceCast for a pointer type depending on + /// Create a BitCast or AddrSpaceCast for a pointer type depending on /// the address space. static Constant *getPointerBitCastOrAddrSpaceCast( Constant *C, ///< The constant to addrspacecast or bitcast Type *Ty ///< The type to bitcast or addrspacecast C to ); - /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts + /// Create a ZExt, Bitcast or Trunc for integer -> integer casts static Constant *getIntegerCast( Constant *C, ///< The integer constant to be casted Type *Ty, ///< The integer type to cast to bool isSigned ///< Whether C should be treated as signed or not ); - /// @brief Create a FPExt, Bitcast or FPTrunc for fp -> fp casts + /// Create a FPExt, Bitcast or FPTrunc for fp -> fp casts static Constant *getFPCast( Constant *C, ///< The integer constant to be casted Type *Ty ///< The integer type to cast to ); - /// @brief Return true if this is a convert constant expression + /// Return true if this is a convert constant expression bool isCast() const; - /// @brief Return true if this is a compare constant expression + /// Return true if this is a compare constant expression bool isCompare() const; - /// @brief Return true if this is an insertvalue or extractvalue expression, + /// Return true if this is an insertvalue or extractvalue expression, /// and the getIndices() method may be used. bool hasIndices() const; - /// @brief Return true if this is a getelementptr expression and all + /// Return true if this is a getelementptr expression and all /// the index operands are compile-time known integers within the /// corresponding notional static array extents. Note that this is /// not equivalant to, a subset of, or a superset of the "inbounds" @@ -1093,7 +1121,7 @@ public: static Constant *get(unsigned Opcode, Constant *C1, Constant *C2, unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr); - /// \brief Return an ICmp or FCmp comparison operator constant expression. + /// Return an ICmp or FCmp comparison operator constant expression. /// /// \param OnlyIfReduced see \a getWithOperands() docs. static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2, diff --git a/contrib/llvm/include/llvm/IR/DIBuilder.h b/contrib/llvm/include/llvm/IR/DIBuilder.h index 3c2074dfe788..06c9421ec1d6 100644 --- a/contrib/llvm/include/llvm/IR/DIBuilder.h +++ b/contrib/llvm/include/llvm/IR/DIBuilder.h @@ -18,7 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" -#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -46,6 +46,7 @@ namespace llvm { DICompileUnit *CUNode; ///< The one compile unit created by this DIBuiler. Function *DeclareFn; ///< llvm.dbg.declare Function *ValueFn; ///< llvm.dbg.value + Function *LabelFn; ///< llvm.dbg.label SmallVector<Metadata *, 4> AllEnumTypes; /// Track the RetainTypes, since they can be updated later on. @@ -69,6 +70,9 @@ namespace llvm { /// copy. DenseMap<MDNode *, SmallVector<TrackingMDNodeRef, 1>> PreservedVariables; + /// Each subprogram's preserved labels. + DenseMap<MDNode *, SmallVector<TrackingMDNodeRef, 1>> PreservedLabels; + /// Create a temporary. /// /// Create an \a temporary node and track it in \a UnresolvedNodes. @@ -79,6 +83,10 @@ namespace llvm { DIExpression *Expr, const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore); + /// Internal helper for insertLabel. + Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, + BasicBlock *InsertBB, Instruction *InsertBefore); + /// Internal helper for insertDbgValueIntrinsic. Instruction * insertDbgValueIntrinsic(llvm::Value *Val, DILocalVariable *VarInfo, @@ -90,7 +98,10 @@ namespace llvm { /// /// If \c AllowUnresolved, collect unresolved nodes attached to the module /// in order to resolve cycles during \a finalize(). - explicit DIBuilder(Module &M, bool AllowUnresolved = true); + /// + /// If \p CU is given a value other than nullptr, then set \p CUNode to CU. + explicit DIBuilder(Module &M, bool AllowUnresolved = true, + DICompileUnit *CU = nullptr); DIBuilder(const DIBuilder &) = delete; DIBuilder &operator=(const DIBuilder &) = delete; @@ -138,11 +149,13 @@ namespace llvm { /// Create a file descriptor to hold debugging information for a file. /// \param Filename File name. /// \param Directory Directory. - /// \param CSKind Checksum kind (e.g. CSK_None, CSK_MD5, CSK_SHA1, etc.). - /// \param Checksum Checksum data. - DIFile *createFile(StringRef Filename, StringRef Directory, - DIFile::ChecksumKind CSKind = DIFile::CSK_None, - StringRef Checksum = StringRef()); + /// \param Checksum Optional checksum kind (e.g. CSK_MD5, CSK_SHA1, etc.) + /// and value. + /// \param Source Optional source text. + DIFile * + createFile(StringRef Filename, StringRef Directory, + Optional<DIFile::ChecksumInfo<StringRef>> Checksum = None, + Optional<StringRef> Source = None); /// Create debugging information entry for a macro. /// \param Parent Macro parent (could be nullptr). @@ -163,7 +176,7 @@ namespace llvm { DIFile *File); /// Create a single enumerator value. - DIEnumerator *createEnumerator(StringRef Name, int64_t Val); + DIEnumerator *createEnumerator(StringRef Name, int64_t Val, bool IsUnsigned = false); /// Create a DWARF unspecified type. DIBasicType *createUnspecifiedType(StringRef Name); @@ -232,10 +245,11 @@ namespace llvm { /// \param Ty Original type. /// \param BaseTy Base type. Ty is inherits from base. /// \param BaseOffset Base offset. + /// \param VBPtrOffset Virtual base pointer offset. /// \param Flags Flags to describe inheritance attribute, /// e.g. private DIDerivedType *createInheritance(DIType *Ty, DIType *BaseTy, - uint64_t BaseOffset, + uint64_t BaseOffset, uint32_t VBPtrOffset, DINode::DIFlags Flags); /// Create debugging information entry for a member. @@ -255,6 +269,27 @@ namespace llvm { uint64_t OffsetInBits, DINode::DIFlags Flags, DIType *Ty); + /// Create debugging information entry for a variant. A variant + /// normally should be a member of a variant part. + /// \param Scope Member scope. + /// \param Name Member name. + /// \param File File where this member is defined. + /// \param LineNo Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param OffsetInBits Member offset. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Discriminant The discriminant for this branch; null for + /// the default branch + /// \param Ty Parent type. + DIDerivedType *createVariantMemberType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNo, + uint64_t SizeInBits, + uint32_t AlignInBits, + uint64_t OffsetInBits, + Constant *Discriminant, + DINode::DIFlags Flags, DIType *Ty); + /// Create debugging information entry for a bit field member. /// \param Scope Member scope. /// \param Name Member name. @@ -376,6 +411,27 @@ namespace llvm { unsigned RunTimeLang = 0, StringRef UniqueIdentifier = ""); + /// Create debugging information entry for a variant part. A + /// variant part normally has a discriminator (though this is not + /// required) and a number of variant children. + /// \param Scope Scope in which this union is defined. + /// \param Name Union name. + /// \param File File where this member is defined. + /// \param LineNumber Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Discriminator Discriminant member + /// \param Elements Variant elements. + /// \param UniqueIdentifier A unique identifier for the union. + DICompositeType *createVariantPart(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, + DINode::DIFlags Flags, + DIDerivedType *Discriminator, + DINodeArray Elements, + StringRef UniqueIdentifier = ""); + /// Create debugging information for template /// type parameter. /// \param Scope Scope in which this type is defined. @@ -442,10 +498,11 @@ namespace llvm { /// \param Elements Enumeration elements. /// \param UnderlyingType Underlying type of a C++11/ObjC fixed enum. /// \param UniqueIdentifier A unique identifier for the enum. + /// \param IsFixed Boolean flag indicate if this is C++11/ObjC fixed enum. DICompositeType *createEnumerationType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements, - DIType *UnderlyingType, StringRef UniqueIdentifier = ""); + DIType *UnderlyingType, StringRef UniqueIdentifier = "", bool IsFixed = false); /// Create subroutine type. /// \param ParameterTypes An array of subroutine parameter types. This @@ -458,12 +515,15 @@ namespace llvm { DINode::DIFlags Flags = DINode::FlagZero, unsigned CC = 0); - /// Create a new DIType* with "artificial" flag set. - DIType *createArtificialType(DIType *Ty); + /// Create a distinct clone of \p SP with FlagArtificial set. + static DISubprogram *createArtificialSubprogram(DISubprogram *SP); + + /// Create a uniqued clone of \p Ty with FlagArtificial set. + static DIType *createArtificialType(DIType *Ty); - /// Create a new DIType* with the "object pointer" - /// flag set. - DIType *createObjectPointerType(DIType *Ty); + /// Create a uniqued clone of \p Ty with FlagObjectPointer and + /// FlagArtificial set. + static DIType *createObjectPointerType(DIType *Ty); /// Create a permanent forward-declared type. DICompositeType *createForwardDecl(unsigned Tag, StringRef Name, @@ -500,6 +560,7 @@ namespace llvm { /// Create a descriptor for a value range. This /// implicitly uniques the values returned. DISubrange *getOrCreateSubrange(int64_t Lo, int64_t Count); + DISubrange *getOrCreateSubrange(int64_t Lo, Metadata *CountNode); /// Create a new descriptor for the specified variable. /// \param Context Variable scope. @@ -542,6 +603,14 @@ namespace llvm { DINode::DIFlags Flags = DINode::FlagZero, uint32_t AlignInBits = 0); + /// Create a new descriptor for an label. + /// + /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually + /// leads to a \a DISubprogram. + DILabel * + createLabel(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, + bool AlwaysPreserve = false); + /// Create a new descriptor for a parameter variable. /// /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually @@ -733,6 +802,20 @@ namespace llvm { DIExpression *Expr, const DILocation *DL, Instruction *InsertBefore); + /// Insert a new llvm.dbg.label intrinsic call. + /// \param LabelInfo Label's debug info descriptor. + /// \param DL Debug info location. + /// \param InsertBefore Location for the new intrinsic. + Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, + Instruction *InsertBefore); + + /// Insert a new llvm.dbg.label intrinsic call. + /// \param LabelInfo Label's debug info descriptor. + /// \param DL Debug info location. + /// \param InsertAtEnd Location for the new intrinsic. + Instruction *insertLabel(DILabel *LabelInfo, const DILocation *DL, + BasicBlock *InsertAtEnd); + /// Insert a new llvm.dbg.value intrinsic call. /// \param Val llvm::Value of the variable /// \param VarInfo Variable's debug info descriptor. diff --git a/contrib/llvm/include/llvm/IR/DataLayout.h b/contrib/llvm/include/llvm/IR/DataLayout.h index a6c71a5a2c3e..d796a65e6129 100644 --- a/contrib/llvm/include/llvm/IR/DataLayout.h +++ b/contrib/llvm/include/llvm/IR/DataLayout.h @@ -61,7 +61,7 @@ enum AlignTypeEnum { // sunk down to an FTTI element that is queried rather than a global // preference. -/// \brief Layout alignment element. +/// Layout alignment element. /// /// Stores the alignment data associated with a given alignment type (integer, /// vector, float) and type bit width. @@ -69,7 +69,7 @@ enum AlignTypeEnum { /// \note The unusual order of elements in the structure attempts to reduce /// padding and make the structure slightly more cache friendly. struct LayoutAlignElem { - /// \brief Alignment type from \c AlignTypeEnum + /// Alignment type from \c AlignTypeEnum unsigned AlignType : 8; unsigned TypeBitWidth : 24; unsigned ABIAlign : 16; @@ -81,7 +81,7 @@ struct LayoutAlignElem { bool operator==(const LayoutAlignElem &rhs) const; }; -/// \brief Layout pointer alignment element. +/// Layout pointer alignment element. /// /// Stores the alignment data associated with a given pointer and address space. /// @@ -92,15 +92,17 @@ struct PointerAlignElem { unsigned PrefAlign; uint32_t TypeByteWidth; uint32_t AddressSpace; + uint32_t IndexWidth; /// Initializer static PointerAlignElem get(uint32_t AddressSpace, unsigned ABIAlign, - unsigned PrefAlign, uint32_t TypeByteWidth); + unsigned PrefAlign, uint32_t TypeByteWidth, + uint32_t IndexWidth); bool operator==(const PointerAlignElem &rhs) const; }; -/// \brief A parsed version of the target data layout string in and methods for +/// A parsed version of the target data layout string in and methods for /// querying it. /// /// The target data layout string is specified *by the target* - a frontend @@ -113,6 +115,7 @@ private: unsigned AllocaAddrSpace; unsigned StackNaturalAlign; + unsigned ProgramAddrSpace; enum ManglingModeT { MM_None, @@ -126,7 +129,7 @@ private: SmallVector<unsigned char, 8> LegalIntWidths; - /// \brief Primitive type alignment data. This is sorted by type and bit + /// Primitive type alignment data. This is sorted by type and bit /// width during construction. using AlignmentsTy = SmallVector<LayoutAlignElem, 16>; AlignmentsTy Alignments; @@ -140,7 +143,7 @@ private: AlignmentsTy::iterator findAlignmentLowerBound(AlignTypeEnum AlignType, uint32_t BitWidth); - /// \brief The string representation used to create this DataLayout + /// The string representation used to create this DataLayout std::string StringRepresentation; using PointersTy = SmallVector<PointerAlignElem, 8>; @@ -165,7 +168,8 @@ private: unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width, bool ABIAlign, Type *Ty) const; void setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign, - unsigned PrefAlign, uint32_t TypeByteWidth); + unsigned PrefAlign, uint32_t TypeByteWidth, + uint32_t IndexWidth); /// Internal helper method that returns requested alignment for type. unsigned getAlignment(Type *Ty, bool abi_or_pref) const; @@ -196,6 +200,7 @@ public: BigEndian = DL.isBigEndian(); AllocaAddrSpace = DL.AllocaAddrSpace; StackNaturalAlign = DL.StackNaturalAlign; + ProgramAddrSpace = DL.ProgramAddrSpace; ManglingMode = DL.ManglingMode; LegalIntWidths = DL.LegalIntWidths; Alignments = DL.Alignments; @@ -216,7 +221,7 @@ public: bool isLittleEndian() const { return !BigEndian; } bool isBigEndian() const { return BigEndian; } - /// \brief Returns the string representation of the DataLayout. + /// Returns the string representation of the DataLayout. /// /// This representation is in the same format accepted by the string /// constructor above. This should not be used to compare two DataLayout as @@ -225,10 +230,10 @@ public: return StringRepresentation; } - /// \brief Test if the DataLayout was constructed from an empty string. + /// Test if the DataLayout was constructed from an empty string. bool isDefault() const { return StringRepresentation.empty(); } - /// \brief Returns true if the specified type is known to be a native integer + /// Returns true if the specified type is known to be a native integer /// type supported by the CPU. /// /// For example, i64 is not native on most 32-bit CPUs and i37 is not native @@ -252,10 +257,18 @@ public: unsigned getStackAlignment() const { return StackNaturalAlign; } unsigned getAllocaAddrSpace() const { return AllocaAddrSpace; } + unsigned getProgramAddressSpace() const { return ProgramAddrSpace; } + bool hasMicrosoftFastStdCallMangling() const { return ManglingMode == MM_WinCOFFX86; } + /// Returns true if symbols with leading question marks should not receive IR + /// mangling. True for Windows mangling modes. + bool doNotMangleLeadingQuestionMark() const { + return ManglingMode == MM_WinCOFF || ManglingMode == MM_WinCOFFX86; + } + bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; } StringRef getLinkerPrivateGlobalPrefix() const { @@ -296,7 +309,7 @@ public: static const char *getManglingComponent(const Triple &T); - /// \brief Returns true if the specified type fits in a native integer type + /// 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 @@ -321,6 +334,9 @@ public: /// the backends/clients are updated. unsigned getPointerSize(unsigned AS = 0) const; + // Index size used for address calculation. + unsigned getIndexSize(unsigned AS) const; + /// Return the address spaces containing non-integral pointers. Pointers in /// this address space don't have a well-defined bitwise representation. ArrayRef<unsigned> getNonIntegralAddressSpaces() const { @@ -345,6 +361,11 @@ public: return getPointerSize(AS) * 8; } + /// Size in bits of index used for address calculation in getelementptr. + unsigned getIndexSizeInBits(unsigned AS) const { + return getIndexSize(AS) * 8; + } + /// Layout pointer size, in bits, based on the type. If this function is /// called with a pointer type, then the type size of the pointer is returned. /// If this function is called with a vector of pointers, then the type size @@ -352,6 +373,10 @@ public: /// vector of pointers. unsigned getPointerTypeSizeInBits(Type *) const; + /// Layout size of the index used in GEP calculation. + /// The function should be called with pointer or vector of pointers type. + unsigned getIndexTypeSizeInBits(Type *Ty) const; + unsigned getPointerTypeSize(Type *Ty) const { return getPointerTypeSizeInBits(Ty) / 8; } @@ -373,13 +398,13 @@ public: /// [*] The alloc size depends on the alignment, and thus on the target. /// These values are for x86-32 linux. - /// \brief Returns the number of bits necessary to hold the specified type. + /// Returns the number of bits necessary to hold the specified type. /// /// For example, returns 36 for i36 and 80 for x86_fp80. The type passed must /// have a size (Type::isSized() must return true). uint64_t getTypeSizeInBits(Type *Ty) const; - /// \brief Returns the maximum number of bytes that may be overwritten by + /// Returns the maximum number of bytes that may be overwritten by /// storing the specified type. /// /// For example, returns 5 for i36 and 10 for x86_fp80. @@ -387,7 +412,7 @@ public: return (getTypeSizeInBits(Ty) + 7) / 8; } - /// \brief Returns the maximum number of bits that may be overwritten by + /// Returns the maximum number of bits that may be overwritten by /// storing the specified type; always a multiple of 8. /// /// For example, returns 40 for i36 and 80 for x86_fp80. @@ -395,7 +420,7 @@ public: return 8 * getTypeStoreSize(Ty); } - /// \brief Returns the offset in bytes between successive objects of the + /// Returns the offset in bytes between successive objects of the /// specified type, including alignment padding. /// /// This is the amount that alloca reserves for this type. For example, @@ -405,7 +430,7 @@ public: return alignTo(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); } - /// \brief Returns the offset in bits between successive objects of the + /// Returns the offset in bits between successive objects of the /// specified type, including alignment padding; always a multiple of 8. /// /// This is the amount that alloca reserves for this type. For example, @@ -414,64 +439,69 @@ public: return 8 * getTypeAllocSize(Ty); } - /// \brief Returns the minimum ABI-required alignment for the specified type. + /// Returns the minimum ABI-required alignment for the specified type. unsigned getABITypeAlignment(Type *Ty) const; - /// \brief Returns the minimum ABI-required alignment for an integer type of + /// Returns the minimum ABI-required alignment for an integer type of /// the specified bitwidth. unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const; - /// \brief Returns the preferred stack/global alignment for the specified + /// Returns the preferred stack/global alignment for the specified /// type. /// /// This is always at least as good as the ABI alignment. unsigned getPrefTypeAlignment(Type *Ty) const; - /// \brief Returns the preferred alignment for the specified type, returned as + /// Returns the preferred alignment for the specified type, returned as /// log2 of the value (a shift amount). unsigned getPreferredTypeAlignmentShift(Type *Ty) const; - /// \brief Returns an integer type with size at least as big as that of a + /// Returns an integer type with size at least as big as that of a /// pointer in the given address space. IntegerType *getIntPtrType(LLVMContext &C, unsigned AddressSpace = 0) const; - /// \brief Returns an integer (vector of integer) type with size at least as + /// Returns an integer (vector of integer) type with size at least as /// big as that of a pointer of the given pointer (vector of pointer) type. Type *getIntPtrType(Type *) const; - /// \brief Returns the smallest integer type with size at least as big as + /// Returns the smallest integer type with size at least as big as /// Width bits. Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const; - /// \brief Returns the largest legal integer type, or null if none are set. + /// Returns the largest legal integer type, or null if none are set. Type *getLargestLegalIntType(LLVMContext &C) const { unsigned LargestSize = getLargestLegalIntTypeSizeInBits(); return (LargestSize == 0) ? nullptr : Type::getIntNTy(C, LargestSize); } - /// \brief Returns the size of largest legal integer type size, or 0 if none + /// Returns the size of largest legal integer type size, or 0 if none /// are set. unsigned getLargestLegalIntTypeSizeInBits() const; - /// \brief Returns the offset from the beginning of the type for the specified + /// Returns the type of a GEP index. + /// If it was not specified explicitly, it will be the integer type of the + /// pointer width - IntPtrType. + Type *getIndexType(Type *PtrTy) const; + + /// Returns the offset from the beginning of the type for the specified /// indices. /// /// Note that this takes the element type, not the pointer type. /// This is used to implement getelementptr. int64_t getIndexedOffsetInType(Type *ElemTy, ArrayRef<Value *> Indices) const; - /// \brief Returns a StructLayout object, indicating the alignment of the + /// Returns a StructLayout object, indicating the alignment of the /// struct, its size, and the offsets of its fields. /// /// Note that this information is lazily cached. const StructLayout *getStructLayout(StructType *Ty) const; - /// \brief Returns the preferred alignment of the specified global. + /// Returns the preferred alignment of the specified global. /// /// This includes an explicitly requested alignment (if the global has one). unsigned getPreferredAlignment(const GlobalVariable *GV) const; - /// \brief Returns the preferred alignment of the specified global, returned + /// Returns the preferred alignment of the specified global, returned /// in log form. /// /// This includes an explicitly requested alignment (if the global has one). @@ -506,7 +536,7 @@ public: /// NB: Padding in nested element is not taken into account. bool hasPadding() const { return IsPadded; } - /// \brief Given a valid byte offset into the structure, returns the structure + /// Given a valid byte offset into the structure, returns the structure /// index that contains it. unsigned getElementContainingOffset(uint64_t Offset) const; diff --git a/contrib/llvm/include/llvm/IR/DebugInfo.h b/contrib/llvm/include/llvm/IR/DebugInfo.h index 1d8e7e2855fd..01178af3c9ff 100644 --- a/contrib/llvm/include/llvm/IR/DebugInfo.h +++ b/contrib/llvm/include/llvm/IR/DebugInfo.h @@ -28,10 +28,10 @@ class DbgDeclareInst; class DbgValueInst; class Module; -/// \brief Find subprogram that is enclosing this scope. +/// Find subprogram that is enclosing this scope. DISubprogram *getDISubprogram(const MDNode *Scope); -/// \brief Strip debug info in the module if it exists. +/// Strip debug info in the module if it exists. /// /// To do this, we remove all calls to the debugger intrinsics and any named /// metadata for debugging. We also remove debug locations for instructions. @@ -51,10 +51,10 @@ bool stripDebugInfo(Function &F); /// All debug type metadata nodes are unreachable and garbage collected. bool stripNonLineTableDebugInfo(Module &M); -/// \brief Return Debug Info Metadata Version by checking module flags. +/// Return Debug Info Metadata Version by checking module flags. unsigned getDebugMetadataVersionFromModule(const Module &M); -/// \brief Utility to find all debug info in a module. +/// Utility to find all debug info in a module. /// /// DebugInfoFinder tries to list all debug info MDNodes used in a module. To /// list debug info MDNodes used by an instruction, DebugInfoFinder uses @@ -64,30 +64,33 @@ unsigned getDebugMetadataVersionFromModule(const Module &M); /// used by the CUs. class DebugInfoFinder { public: - /// \brief Process entire module and collect debug info anchors. + /// Process entire module and collect debug info anchors. void processModule(const Module &M); + /// Process a single instruction and collect debug info anchors. + void processInstruction(const Module &M, const Instruction &I); - /// \brief Process DbgDeclareInst. + /// Process DbgDeclareInst. void processDeclare(const Module &M, const DbgDeclareInst *DDI); - /// \brief Process DbgValueInst. + /// Process DbgValueInst. void processValue(const Module &M, const DbgValueInst *DVI); - /// \brief Process debug info location. + /// Process debug info location. void processLocation(const Module &M, const DILocation *Loc); - /// \brief Clear all lists. + /// Clear all lists. void reset(); private: void InitializeTypeMap(const Module &M); - void processType(DIType *DT); - void processSubprogram(DISubprogram *SP); + void processCompileUnit(DICompileUnit *CU); void processScope(DIScope *Scope); + void processSubprogram(DISubprogram *SP); + void processType(DIType *DT); bool addCompileUnit(DICompileUnit *CU); bool addGlobalVariable(DIGlobalVariableExpression *DIG); + bool addScope(DIScope *Scope); bool addSubprogram(DISubprogram *SP); bool addType(DIType *DT); - bool addScope(DIScope *Scope); public: using compile_unit_iterator = diff --git a/contrib/llvm/include/llvm/IR/DebugInfoFlags.def b/contrib/llvm/include/llvm/IR/DebugInfoFlags.def index 7ea6346998fe..b1f5fac64232 100644 --- a/contrib/llvm/include/llvm/IR/DebugInfoFlags.def +++ b/contrib/llvm/include/llvm/IR/DebugInfoFlags.def @@ -43,6 +43,11 @@ HANDLE_DI_FLAG((1 << 18), IntroducedVirtual) HANDLE_DI_FLAG((1 << 19), BitField) HANDLE_DI_FLAG((1 << 20), NoReturn) HANDLE_DI_FLAG((1 << 21), MainSubprogram) +HANDLE_DI_FLAG((1 << 22), TypePassByValue) +HANDLE_DI_FLAG((1 << 23), TypePassByReference) +HANDLE_DI_FLAG((1 << 24), FixedEnum) +HANDLE_DI_FLAG((1 << 25), Thunk) +HANDLE_DI_FLAG((1 << 26), Trivial) // To avoid needing a dedicated value for IndirectVirtualBase, we use // the bitwise or of Virtual and FwdDecl, which does not otherwise @@ -52,7 +57,7 @@ HANDLE_DI_FLAG((1 << 2) | (1 << 5), IndirectVirtualBase) #ifdef DI_FLAG_LARGEST_NEEDED // intended to be used with ADT/BitmaskEnum.h // NOTE: always must be equal to largest flag, check this when adding new flag -HANDLE_DI_FLAG((1 << 21), Largest) +HANDLE_DI_FLAG((1 << 26), Largest) #undef DI_FLAG_LARGEST_NEEDED #endif diff --git a/contrib/llvm/include/llvm/IR/DebugInfoMetadata.h b/contrib/llvm/include/llvm/IR/DebugInfoMetadata.h index 75b0c43b6512..820746851104 100644 --- a/contrib/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/contrib/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -18,11 +18,13 @@ #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/Metadata.h" #include "llvm/Support/Casting.h" #include <cassert> @@ -230,6 +232,7 @@ public: case DITemplateValueParameterKind: case DIGlobalVariableKind: case DILocalVariableKind: + case DILabelKind: case DIObjCPropertyKind: case DIImportedEntityKind: case DIModuleKind: @@ -332,31 +335,53 @@ class DISubrange : public DINode { friend class LLVMContextImpl; friend class MDNode; - int64_t Count; int64_t LowerBound; - DISubrange(LLVMContext &C, StorageType Storage, int64_t Count, - int64_t LowerBound) - : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, None), - Count(Count), LowerBound(LowerBound) {} + DISubrange(LLVMContext &C, StorageType Storage, Metadata *Node, + int64_t LowerBound, ArrayRef<Metadata *> Ops) + : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops), + LowerBound(LowerBound) {} + ~DISubrange() = default; static DISubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t LowerBound, StorageType Storage, bool ShouldCreate = true); + static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, + int64_t LowerBound, StorageType Storage, + bool ShouldCreate = true); + TempDISubrange cloneImpl() const { - return getTemporary(getContext(), getCount(), getLowerBound()); + return getTemporary(getContext(), getRawCountNode(), getLowerBound()); } public: DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0), (Count, LowerBound)) + DEFINE_MDNODE_GET(DISubrange, (Metadata *CountNode, int64_t LowerBound = 0), + (CountNode, LowerBound)) + TempDISubrange clone() const { return cloneImpl(); } int64_t getLowerBound() const { return LowerBound; } - int64_t getCount() const { return Count; } + + Metadata *getRawCountNode() const { + return getOperand(0).get(); + } + + typedef PointerUnion<ConstantInt*, DIVariable*> CountType; + + CountType getCount() const { + if (auto *MD = dyn_cast<ConstantAsMetadata>(getRawCountNode())) + return CountType(cast<ConstantInt>(MD->getValue())); + + if (auto *DV = dyn_cast<DIVariable>(getRawCountNode())) + return CountType(DV); + + return CountType(); + } static bool classof(const Metadata *MD) { return MD->getMetadataID() == DISubrangeKind; @@ -372,36 +397,38 @@ class DIEnumerator : public DINode { friend class MDNode; int64_t Value; - DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, - ArrayRef<Metadata *> Ops) + bool IsUnsigned, ArrayRef<Metadata *> Ops) : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), - Value(Value) {} + Value(Value) { + SubclassData32 = IsUnsigned; + } ~DIEnumerator() = default; static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, - StringRef Name, StorageType Storage, - bool ShouldCreate = true) { - return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage, - ShouldCreate); + bool IsUnsigned, StringRef Name, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Value, IsUnsigned, + getCanonicalMDString(Context, Name), Storage, ShouldCreate); } static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, - MDString *Name, StorageType Storage, - bool ShouldCreate = true); + bool IsUnsigned, MDString *Name, + StorageType Storage, bool ShouldCreate = true); TempDIEnumerator cloneImpl() const { - return getTemporary(getContext(), getValue(), getName()); + return getTemporary(getContext(), getValue(), isUnsigned(), getName()); } public: - DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, StringRef Name), - (Value, Name)) - DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, MDString *Name), - (Value, Name)) + DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, StringRef Name), + (Value, IsUnsigned, Name)) + DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, MDString *Name), + (Value, IsUnsigned, Name)) TempDIEnumerator clone() const { return cloneImpl(); } int64_t getValue() const { return Value; } + bool isUnsigned() const { return SubclassData32; } StringRef getName() const { return getStringOperand(0); } MDString *getRawName() const { return getOperandAs<MDString>(0); } @@ -429,6 +456,7 @@ public: inline StringRef getFilename() const; inline StringRef getDirectory() const; + inline Optional<StringRef> getSource() const; StringRef getName() const; DIScopeRef getScope() const; @@ -473,63 +501,103 @@ class DIFile : public DIScope { friend class MDNode; public: - // These values must be explictly set, as they end up in the final object - // file. + /// Which algorithm (e.g. MD5) a checksum was generated with. + /// + /// The encoding is explicit because it is used directly in Bitcode. The + /// value 0 is reserved to indicate the absence of a checksum in Bitcode. enum ChecksumKind { - CSK_None = 0, + // The first variant was originally CSK_None, encoded as 0. The new + // internal representation removes the need for this by wrapping the + // ChecksumInfo in an Optional, but to preserve Bitcode compatibility the 0 + // encoding is reserved. CSK_MD5 = 1, CSK_SHA1 = 2, CSK_Last = CSK_SHA1 // Should be last enumeration. }; + /// A single checksum, represented by a \a Kind and a \a Value (a string). + template <typename T> + struct ChecksumInfo { + /// The kind of checksum which \a Value encodes. + ChecksumKind Kind; + /// The string value of the checksum. + T Value; + + ChecksumInfo(ChecksumKind Kind, T Value) : Kind(Kind), Value(Value) { } + ~ChecksumInfo() = default; + bool operator==(const ChecksumInfo<T> &X) const { + return Kind == X.Kind && Value == X.Value; + } + bool operator!=(const ChecksumInfo<T> &X) const { return !(*this == X); } + StringRef getKindAsString() const { return getChecksumKindAsString(Kind); } + }; + private: - ChecksumKind CSKind; + Optional<ChecksumInfo<MDString *>> Checksum; + Optional<MDString *> Source; - DIFile(LLVMContext &C, StorageType Storage, ChecksumKind CSK, + DIFile(LLVMContext &C, StorageType Storage, + Optional<ChecksumInfo<MDString *>> CS, Optional<MDString *> Src, ArrayRef<Metadata *> Ops) : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops), - CSKind(CSK) {} + Checksum(CS), Source(Src) {} ~DIFile() = default; static DIFile *getImpl(LLVMContext &Context, StringRef Filename, - StringRef Directory, ChecksumKind CSK, StringRef CS, + StringRef Directory, + Optional<ChecksumInfo<StringRef>> CS, + Optional<StringRef> Source, StorageType Storage, bool ShouldCreate = true) { + Optional<ChecksumInfo<MDString *>> MDChecksum; + if (CS) + MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); return getImpl(Context, getCanonicalMDString(Context, Filename), - getCanonicalMDString(Context, Directory), CSK, - getCanonicalMDString(Context, CS), Storage, ShouldCreate); + getCanonicalMDString(Context, Directory), MDChecksum, + Source ? Optional<MDString *>(getCanonicalMDString(Context, *Source)) : None, + Storage, ShouldCreate); } static DIFile *getImpl(LLVMContext &Context, MDString *Filename, - MDString *Directory, ChecksumKind CSK, MDString *CS, - StorageType Storage, bool ShouldCreate = true); + MDString *Directory, + Optional<ChecksumInfo<MDString *>> CS, + Optional<MDString *> Source, StorageType Storage, + bool ShouldCreate = true); TempDIFile cloneImpl() const { return getTemporary(getContext(), getFilename(), getDirectory(), - getChecksumKind(), getChecksum()); + getChecksum(), getSource()); } public: DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory, - ChecksumKind CSK = CSK_None, - StringRef CS = StringRef()), - (Filename, Directory, CSK, CS)) + Optional<ChecksumInfo<StringRef>> CS = None, + Optional<StringRef> Source = None), + (Filename, Directory, CS, Source)) DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory, - ChecksumKind CSK = CSK_None, - MDString *CS = nullptr), - (Filename, Directory, CSK, CS)) + Optional<ChecksumInfo<MDString *>> CS = None, + Optional<MDString *> Source = None), + (Filename, Directory, CS, Source)) TempDIFile clone() const { return cloneImpl(); } StringRef getFilename() const { return getStringOperand(0); } StringRef getDirectory() const { return getStringOperand(1); } - StringRef getChecksum() const { return getStringOperand(2); } - ChecksumKind getChecksumKind() const { return CSKind; } - StringRef getChecksumKindAsString() const; + Optional<ChecksumInfo<StringRef>> getChecksum() const { + Optional<ChecksumInfo<StringRef>> StringRefChecksum; + if (Checksum) + StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString()); + return StringRefChecksum; + } + Optional<StringRef> getSource() const { + return Source ? Optional<StringRef>((*Source)->getString()) : None; + } MDString *getRawFilename() const { return getOperandAs<MDString>(0); } MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } - MDString *getRawChecksum() const { return getOperandAs<MDString>(2); } + Optional<ChecksumInfo<MDString *>> getRawChecksum() const { return Checksum; } + Optional<MDString *> getRawSource() const { return Source; } - static ChecksumKind getChecksumKind(StringRef CSKindStr); + static StringRef getChecksumKindAsString(ChecksumKind CSKind); + static Optional<ChecksumKind> getChecksumKind(StringRef CSKindStr); static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIFileKind; @@ -548,6 +616,12 @@ StringRef DIScope::getDirectory() const { return ""; } +Optional<StringRef> DIScope::getSource() const { + if (auto *F = getFile()) + return F->getSource(); + return None; +} + /// Base class for types. /// /// TODO: Remove the hardcoded name and context, since many types don't use @@ -605,9 +679,11 @@ public: Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs<MDString>(2); } - void setFlags(DIFlags NewFlags) { - assert(!isUniqued() && "Cannot set flags on uniqued nodes"); - Flags = NewFlags; + /// Returns a new temporary DIType with updated Flags + TempDIType cloneWithFlags(DIFlags NewFlags) const { + auto NewTy = clone(); + NewTy->Flags = NewFlags; + return NewTy; } bool isPrivate() const { @@ -633,6 +709,10 @@ public: bool isStaticMember() const { return getFlags() & FlagStaticMember; } bool isLValueReference() const { return getFlags() & FlagLValueReference; } bool isRValueReference() const { return getFlags() & FlagRValueReference; } + bool isTypePassByValue() const { return getFlags() & FlagTypePassByValue; } + bool isTypePassByReference() const { + return getFlags() & FlagTypePassByReference; + } static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { @@ -698,6 +778,12 @@ public: unsigned getEncoding() const { return Encoding; } + enum class Signedness { Signed, Unsigned }; + + /// Return the signedness of this type, or None if this type is neither + /// signed nor unsigned. + Optional<Signedness> getSignedness() const; + static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIBasicTypeKind; } @@ -713,7 +799,7 @@ class DIDerivedType : public DIType { friend class LLVMContextImpl; friend class MDNode; - /// \brief The DWARF address space of the memory pointed to or referenced by a + /// The DWARF address space of the memory pointed to or referenced by a /// pointer or reference type respectively. Optional<unsigned> DWARFAddressSpace; @@ -788,7 +874,8 @@ public: /// Get extra data associated with this derived type. /// /// Class type for pointer-to-members, objective-c property node for ivars, - /// or global constant wrapper for static members. + /// global constant wrapper for static members, or virtual base pointer offset + /// for inheritance. /// /// TODO: Separate out types that need this extra operand: pointer-to-member /// types and member fields (static members and ivars). @@ -806,6 +893,14 @@ public: return dyn_cast_or_null<DIObjCProperty>(getExtraData()); } + uint32_t getVBPtrOffset() const { + assert(getTag() == dwarf::DW_TAG_inheritance); + if (auto *CM = cast_or_null<ConstantAsMetadata>(getExtraData())) + if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue())) + return static_cast<uint32_t>(CI->getZExtValue()); + return 0; + } + Constant *getStorageOffsetInBits() const { assert(getTag() == dwarf::DW_TAG_member && isBitField()); if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) @@ -819,6 +914,12 @@ public: return C->getValue(); return nullptr; } + Constant *getDiscriminantValue() const { + assert(getTag() == dwarf::DW_TAG_member && !isStaticMember()); + if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) + return C->getValue(); + return nullptr; + } /// @} static bool classof(const Metadata *MD) { @@ -861,12 +962,13 @@ class DICompositeType : public DIType { uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang, DITypeRef VTableHolder, DITemplateParameterArray TemplateParams, - StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { + StringRef Identifier, DIDerivedType *Discriminator, + StorageType Storage, bool ShouldCreate = true) { return getImpl( Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), RuntimeLang, VTableHolder, TemplateParams.get(), - getCanonicalMDString(Context, Identifier), Storage, ShouldCreate); + getCanonicalMDString(Context, Identifier), Discriminator, Storage, ShouldCreate); } static DICompositeType * getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, @@ -874,14 +976,15 @@ class DICompositeType : public DIType { uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams, - MDString *Identifier, StorageType Storage, bool ShouldCreate = true); + MDString *Identifier, Metadata *Discriminator, + StorageType Storage, bool ShouldCreate = true); TempDICompositeType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), getScope(), getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), getFlags(), getElements(), getRuntimeLang(), getVTableHolder(), - getTemplateParams(), getIdentifier()); + getTemplateParams(), getIdentifier(), getDiscriminator()); } public: @@ -892,10 +995,10 @@ public: DIFlags Flags, DINodeArray Elements, unsigned RuntimeLang, DITypeRef VTableHolder, DITemplateParameterArray TemplateParams = nullptr, - StringRef Identifier = ""), + StringRef Identifier = "", DIDerivedType *Discriminator = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, - VTableHolder, TemplateParams, Identifier)) + VTableHolder, TemplateParams, Identifier, Discriminator)) DEFINE_MDNODE_GET(DICompositeType, (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, @@ -903,10 +1006,11 @@ public: uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams = nullptr, - MDString *Identifier = nullptr), + MDString *Identifier = nullptr, + Metadata *Discriminator = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, - VTableHolder, TemplateParams, Identifier)) + VTableHolder, TemplateParams, Identifier, Discriminator)) TempDICompositeType clone() const { return cloneImpl(); } @@ -923,7 +1027,7 @@ public: Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, - Metadata *TemplateParams); + Metadata *TemplateParams, Metadata *Discriminator); static DICompositeType *getODRTypeIfExists(LLVMContext &Context, MDString &Identifier); @@ -942,7 +1046,7 @@ public: Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, - Metadata *TemplateParams); + Metadata *TemplateParams, Metadata *Discriminator); DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); } DINodeArray getElements() const { @@ -960,6 +1064,8 @@ public: Metadata *getRawVTableHolder() const { return getOperand(5); } Metadata *getRawTemplateParams() const { return getOperand(6); } MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } + Metadata *getRawDiscriminator() const { return getOperand(8); } + DIDerivedType *getDiscriminator() const { return getOperandAs<DIDerivedType>(8); } /// Replace operands. /// @@ -1060,7 +1166,7 @@ public: }; static Optional<DebugEmissionKind> getEmissionKind(StringRef Str); - static const char *EmissionKindString(DebugEmissionKind EK); + static const char *emissionKindString(DebugEmissionKind EK); private: unsigned SourceLanguage; @@ -1337,6 +1443,7 @@ public: DIFile *getFile() const { return getScope()->getFile(); } StringRef getFilename() const { return getScope()->getFilename(); } StringRef getDirectory() const { return getScope()->getDirectory(); } + Optional<StringRef> getSource() const { return getScope()->getSource(); } /// Get the scope where this is inlined. /// @@ -1380,7 +1487,7 @@ public: /// /// The above 3 components are encoded into a 32bit unsigned integer in /// order. If the lowest bit is 1, the current component is empty, and the - /// next component will start in the next bit. Otherwise, the the current + /// next component will start in the next bit. Otherwise, the current /// component is non-empty, and its content starts in the next bit. The /// length of each components is either 5 bit or 12 bit: if the 7th bit /// is 0, the bit 2~6 (5 bits) are used to represent the component; if the @@ -1408,26 +1515,25 @@ public: /// discriminator. inline const DILocation *cloneWithDuplicationFactor(unsigned DF) const; + enum { NoGeneratedLocation = false, WithGeneratedLocation = true }; + /// When two instructions are combined into a single instruction we also /// need to combine the original locations into a single location. /// /// When the locations are the same we can use either location. When they - /// differ, we need a third location which is distinct from either. If - /// they have the same file/line but have a different discriminator we - /// could create a location with a new discriminator. If they are from - /// different files/lines the location is ambiguous and can't be - /// represented in a single line entry. In this case, no location - /// should be set, unless the merged instruction is a call, which we will - /// set the merged debug location as line 0 of the nearest common scope - /// where 2 locations are inlined from. This only applies to Instruction; - /// for MachineInstruction, as it is post-inline, we will treat the call - /// instruction the same way as other instructions. + /// differ, we need a third location which is distinct from either. If they + /// have the same file/line but have a different discriminator we could + /// create a location with a new discriminator. If they are from different + /// files/lines the location is ambiguous and can't be represented in a line + /// entry. In this case, if \p GenerateLocation is true, we will set the + /// merged debug location as line 0 of the nearest common scope where the two + /// locations are inlined from. /// - /// \p ForInst: The Instruction the merged DILocation is for. If the - /// Instruction is unavailable or non-existent, use nullptr. + /// \p GenerateLocation: Whether the merged location can be generated when + /// \p LocA and \p LocB differ. static const DILocation * getMergedLocation(const DILocation *LocA, const DILocation *LocB, - const Instruction *ForInst = nullptr); + bool GenerateLocation = NoGeneratedLocation); /// Returns the base discriminator for a given encoded discriminator \p D. static unsigned getBaseDiscriminatorFromDiscriminator(unsigned D) { @@ -1521,13 +1627,13 @@ class DISubprogram : public DILocalScope { unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, bool IsOptimized, DICompileUnit *Unit, DITemplateParameterArray TemplateParams, DISubprogram *Declaration, - DILocalVariableArray Variables, DITypeArray ThrownTypes, + DINodeArray RetainedNodes, DITypeArray ThrownTypes, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, - Unit, TemplateParams.get(), Declaration, Variables.get(), + Unit, TemplateParams.get(), Declaration, RetainedNodes.get(), ThrownTypes.get(), Storage, ShouldCreate); } static DISubprogram * @@ -1536,7 +1642,7 @@ class DISubprogram : public DILocalScope { bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, bool IsOptimized, Metadata *Unit, - Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate = true); TempDISubprogram cloneImpl() const { @@ -1545,7 +1651,7 @@ class DISubprogram : public DILocalScope { isDefinition(), getScopeLine(), getContainingType(), getVirtuality(), getVirtualIndex(), getThisAdjustment(), getFlags(), isOptimized(), getUnit(), - getTemplateParams(), getDeclaration(), getVariables(), + getTemplateParams(), getDeclaration(), getRetainedNodes(), getThrownTypes()); } @@ -1559,12 +1665,12 @@ public: bool IsOptimized, DICompileUnit *Unit, DITemplateParameterArray TemplateParams = nullptr, DISubprogram *Declaration = nullptr, - DILocalVariableArray Variables = nullptr, + DINodeArray RetainedNodes = nullptr, DITypeArray ThrownTypes = nullptr), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit, - TemplateParams, Declaration, Variables, ThrownTypes)) + TemplateParams, Declaration, RetainedNodes, ThrownTypes)) DEFINE_MDNODE_GET( DISubprogram, (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, @@ -1572,15 +1678,22 @@ public: unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, bool IsOptimized, Metadata *Unit, Metadata *TemplateParams = nullptr, - Metadata *Declaration = nullptr, Metadata *Variables = nullptr, + Metadata *Declaration = nullptr, Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, ThisAdjustment, - Flags, IsOptimized, Unit, TemplateParams, Declaration, Variables, + Flags, IsOptimized, Unit, TemplateParams, Declaration, RetainedNodes, ThrownTypes)) TempDISubprogram clone() const { return cloneImpl(); } + /// Returns a new temporary DISubprogram with updated Flags + TempDISubprogram cloneWithFlags(DIFlags NewFlags) const { + auto NewSP = clone(); + NewSP->Flags = NewFlags; + return NewSP; + } + public: unsigned getLine() const { return Line; } unsigned getVirtuality() const { return Virtuality; } @@ -1623,6 +1736,11 @@ public: /// Return true if this subprogram is C++11 noreturn or C11 _Noreturn bool isNoReturn() const { return getFlags() & FlagNoReturn; } + // Check if this routine is a compiler-generated thunk. + // + // Returns true if this subprogram is a thunk generated by the compiler. + bool isThunk() const { return getFlags() & FlagThunk; } + DIScopeRef getScope() const { return DIScopeRef(getRawScope()); } StringRef getName() const { return getStringOperand(2); } @@ -1645,8 +1763,8 @@ public: DISubprogram *getDeclaration() const { return cast_or_null<DISubprogram>(getRawDeclaration()); } - DILocalVariableArray getVariables() const { - return cast_or_null<MDTuple>(getRawVariables()); + DINodeArray getRetainedNodes() const { + return cast_or_null<MDTuple>(getRawRetainedNodes()); } DITypeArray getThrownTypes() const { return cast_or_null<MDTuple>(getRawThrownTypes()); @@ -1658,7 +1776,7 @@ public: Metadata *getRawType() const { return getOperand(4); } Metadata *getRawUnit() const { return getOperand(5); } Metadata *getRawDeclaration() const { return getOperand(6); } - Metadata *getRawVariables() const { return getOperand(7); } + Metadata *getRawRetainedNodes() const { return getOperand(7); } Metadata *getRawContainingType() const { return getNumOperands() > 8 ? getOperandAs<Metadata>(8) : nullptr; } @@ -2094,6 +2212,14 @@ public: /// Determines the size of the variable's type. Optional<uint64_t> getSizeInBits() const; + /// Return the signedness of this variable's type, or None if this type is + /// neither signed nor unsigned. + Optional<DIBasicType::Signedness> getSignedness() const { + if (auto *BT = dyn_cast<DIBasicType>(getType().resolve())) + return BT->getSignedness(); + return None; + } + StringRef getFilename() const { if (auto *F = getFile()) return F->getFilename(); @@ -2106,6 +2232,12 @@ public: return ""; } + Optional<StringRef> getSource() const { + if (auto *F = getFile()) + return F->getSource(); + return None; + } + Metadata *getRawScope() const { return getOperand(0); } MDString *getRawName() const { return getOperandAs<MDString>(1); } Metadata *getRawFile() const { return getOperand(2); } @@ -2194,6 +2326,11 @@ public: /// /// Return the number of elements in the operand (1 + args). unsigned getSize() const; + + /// Append the elements of this operand to \p V. + void appendToVector(SmallVectorImpl<uint64_t> &V) const { + V.append(get(), get() + getSize()); + } }; /// An iterator for expression operands. @@ -2297,10 +2434,29 @@ public: /// Prepend \p DIExpr with a deref and offset operation and optionally turn it /// into a stack value. - static DIExpression *prepend(const DIExpression *DIExpr, bool DerefBefore, + static DIExpression *prepend(const DIExpression *Expr, bool DerefBefore, int64_t Offset = 0, bool DerefAfter = false, bool StackValue = false); + /// Prepend \p DIExpr with the given opcodes and optionally turn it into a + /// stack value. + static DIExpression *prependOpcodes(const DIExpression *Expr, + SmallVectorImpl<uint64_t> &Ops, + bool StackValue = false); + + /// Append the opcodes \p Ops to \p DIExpr. Unlike \ref appendToStack, the + /// returned expression is a stack value only if \p DIExpr is a stack value. + /// If \p DIExpr describes a fragment, the returned expression will describe + /// the same fragment. + static DIExpression *append(const DIExpression *Expr, ArrayRef<uint64_t> Ops); + + /// Convert \p DIExpr into a stack value if it isn't one already by appending + /// DW_OP_deref if needed, and appending \p Ops to the resulting expression. + /// If \p DIExpr describes a fragment, the returned expression will describe + /// the same fragment. + static DIExpression *appendToStack(const DIExpression *Expr, + ArrayRef<uint64_t> Ops); + /// Create a DIExpression to describe one part of an aggregate variable that /// is fragmented across multiple Values. The DW_OP_LLVM_fragment operation /// will be appended to the elements of \c Expr. If \c Expr already contains @@ -2314,6 +2470,32 @@ public: static Optional<DIExpression *> createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits); + + /// Determine the relative position of the fragments described by this + /// DIExpression and \p Other. + /// Returns -1 if this is entirely before Other, 0 if this and Other overlap, + /// 1 if this is entirely after Other. + int fragmentCmp(const DIExpression *Other) const { + auto Fragment1 = *getFragmentInfo(); + auto Fragment2 = *Other->getFragmentInfo(); + unsigned l1 = Fragment1.OffsetInBits; + unsigned l2 = Fragment2.OffsetInBits; + unsigned r1 = l1 + Fragment1.SizeInBits; + unsigned r2 = l2 + Fragment2.SizeInBits; + if (r1 <= l2) + return -1; + else if (r2 <= l1) + return 1; + else + return 0; + } + + /// Check if fragments overlap between this DIExpression and \p Other. + bool fragmentsOverlap(const DIExpression *Other) const { + if (!isFragment() || !Other->isFragment()) + return true; + return fragmentCmp(Other) == 0; + } }; /// Global variables. @@ -2476,6 +2658,76 @@ public: } }; +/// Label. +/// +class DILabel : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + DILabel(LLVMContext &C, StorageType Storage, unsigned Line, + ArrayRef<Metadata *> Ops) + : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops), Line(Line) {} + ~DILabel() = default; + + static DILabel *getImpl(LLVMContext &Context, DIScope *Scope, + StringRef Name, DIFile *File, unsigned Line, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, + Line, Storage, ShouldCreate); + } + static DILabel *getImpl(LLVMContext &Context, Metadata *Scope, + MDString *Name, Metadata *File, unsigned Line, + StorageType Storage, + bool ShouldCreate = true); + + TempDILabel cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), getFile(), + getLine()); + } + +public: + DEFINE_MDNODE_GET(DILabel, + (DILocalScope * Scope, StringRef Name, DIFile *File, + unsigned Line), + (Scope, Name, File, Line)) + DEFINE_MDNODE_GET(DILabel, + (Metadata * Scope, MDString *Name, Metadata *File, + unsigned Line), + (Scope, Name, File, Line)) + + TempDILabel clone() const { return cloneImpl(); } + + /// Get the local scope for this label. + /// + /// Labels must be defined in a local scope. + DILocalScope *getScope() const { + return cast_or_null<DILocalScope>(getRawScope()); + } + unsigned getLine() const { return Line; } + StringRef getName() const { return getStringOperand(1); } + DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } + + Metadata *getRawScope() const { return getOperand(0); } + MDString *getRawName() const { return getOperandAs<MDString>(1); } + Metadata *getRawFile() const { return getOperand(2); } + + /// Check that a location is valid for this label. + /// + /// Check that \c DL exists, is in the same subprogram, and has the same + /// inlined-at location as \c this. (Otherwise, it's not a valid attachment + /// to a \a DbgInfoIntrinsic.) + bool isValidLocationForIntrinsic(const DILocation *DL) const { + return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DILabelKind; + } +}; + class DIObjCProperty : public DINode { friend class LLVMContextImpl; friend class MDNode; @@ -2547,6 +2799,12 @@ public: return ""; } + Optional<StringRef> getSource() const { + if (auto *F = getFile()) + return F->getSource(); + return None; + } + MDString *getRawName() const { return getOperandAs<MDString>(0); } Metadata *getRawFile() const { return getOperand(1); } MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } diff --git a/contrib/llvm/include/llvm/IR/DebugLoc.h b/contrib/llvm/include/llvm/IR/DebugLoc.h index eef1212abc4b..9f619ffc5c4d 100644 --- a/contrib/llvm/include/llvm/IR/DebugLoc.h +++ b/contrib/llvm/include/llvm/IR/DebugLoc.h @@ -24,7 +24,7 @@ namespace llvm { class raw_ostream; class DILocation; - /// \brief A debug info location. + /// A debug info location. /// /// This class is a wrapper around a tracking reference to an \a DILocation /// pointer. @@ -37,10 +37,10 @@ namespace llvm { public: DebugLoc() = default; - /// \brief Construct from an \a DILocation. + /// Construct from an \a DILocation. DebugLoc(const DILocation *L); - /// \brief Construct from an \a MDNode. + /// Construct from an \a MDNode. /// /// Note: if \c N is not an \a DILocation, a verifier check will fail, and /// accessors will crash. However, construction from other nodes is @@ -48,7 +48,7 @@ namespace llvm { /// IR. explicit DebugLoc(const MDNode *N); - /// \brief Get the underlying \a DILocation. + /// Get the underlying \a DILocation. /// /// \pre !*this or \c isa<DILocation>(getAsMDNode()). /// @{ @@ -58,7 +58,7 @@ namespace llvm { DILocation &operator*() const { return *get(); } /// @} - /// \brief Check for null. + /// Check for null. /// /// Check for null in a way that is safe with broken debug info. Unlike /// the conversion to \c DILocation, this doesn't require that \c Loc is of @@ -66,10 +66,10 @@ namespace llvm { /// \a Instruction::hasMetadata(). explicit operator bool() const { return Loc; } - /// \brief Check whether this has a trivial destructor. + /// Check whether this has a trivial destructor. bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } - /// \brief Create a new DebugLoc. + /// Create a new DebugLoc. /// /// Create a new DebugLoc at the specified line/col and scope/inline. This /// forwards to \a DILocation::get(). @@ -95,12 +95,12 @@ namespace llvm { MDNode *getScope() const; DILocation *getInlinedAt() const; - /// \brief Get the fully inlined-at scope for a DebugLoc. + /// Get the fully inlined-at scope for a DebugLoc. /// /// Gets the inlined-at scope for a DebugLoc. MDNode *getInlinedAtScope() const; - /// \brief Find the debug info location for the start of the function. + /// Find the debug info location for the start of the function. /// /// Walk up the scope chain of given debug loc and find line number info /// for the function. @@ -109,7 +109,7 @@ namespace llvm { /// find the subprogram, and then DILocation::get(). DebugLoc getFnDebugLoc() const; - /// \brief Return \c this as a bar \a MDNode. + /// Return \c this as a bar \a MDNode. MDNode *getAsMDNode() const { return Loc; } bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } @@ -117,7 +117,7 @@ namespace llvm { void dump() const; - /// \brief prints source location /path/to/file.exe:line:col @[inlined at] + /// prints source location /path/to/file.exe:line:col @[inlined at] void print(raw_ostream &OS) const; }; diff --git a/contrib/llvm/include/llvm/IR/DerivedTypes.h b/contrib/llvm/include/llvm/IR/DerivedTypes.h index 6e5e085873ab..9526d6287d2f 100644 --- a/contrib/llvm/include/llvm/IR/DerivedTypes.h +++ b/contrib/llvm/include/llvm/IR/DerivedTypes.h @@ -36,7 +36,7 @@ class LLVMContext; /// Class to represent integer types. Note that this class is also used to /// represent the built-in integer types: Int1Ty, Int8Ty, Int16Ty, Int32Ty and /// Int64Ty. -/// @brief Integer representation type +/// Integer representation type class IntegerType : public Type { friend class LLVMContextImpl; @@ -59,10 +59,10 @@ public: /// If an IntegerType with the same NumBits value was previously instantiated, /// that instance will be returned. Otherwise a new one will be created. Only /// one instance with a given NumBits value is ever created. - /// @brief Get or create an IntegerType instance. + /// Get or create an IntegerType instance. static IntegerType *get(LLVMContext &C, unsigned NumBits); - /// @brief Get the number of bits in this IntegerType + /// Get the number of bits in this IntegerType unsigned getBitWidth() const { return getSubclassData(); } /// Return a bitmask with ones set for all of the bits that can be set by an @@ -79,13 +79,13 @@ public: /// For example, this is 0xFF for an 8 bit integer, 0xFFFF for i16, etc. /// @returns a bit mask with ones set for all the bits of this type. - /// @brief Get a bit mask for this type. + /// Get a bit mask for this type. APInt getMask() const; /// This method determines if the width of this IntegerType is a power-of-2 /// in terms of 8 bit bytes. /// @returns true if this is a power-of-2 byte width. - /// @brief Is this a power-of-2 byte-width IntegerType ? + /// Is this a power-of-2 byte-width IntegerType ? bool isPowerOf2ByteWidth() const; /// Methods for support type inquiry through isa, cast, and dyn_cast. @@ -193,7 +193,7 @@ public: /// StructType::create() forms. /// /// Independent of what kind of struct you have, the body of a struct type are -/// laid out in memory consequtively with the elements directly one after the +/// laid out in memory consecutively with the elements directly one after the /// other (if the struct is packed) or (if not packed) with padding between the /// elements as defined by DataLayout (which is required to match what the code /// generator for a target expects). diff --git a/contrib/llvm/include/llvm/IR/DiagnosticHandler.h b/contrib/llvm/include/llvm/IR/DiagnosticHandler.h index 9256d4850df1..51873bea3d41 100644 --- a/contrib/llvm/include/llvm/IR/DiagnosticHandler.h +++ b/contrib/llvm/include/llvm/IR/DiagnosticHandler.h @@ -18,7 +18,7 @@ namespace llvm { class DiagnosticInfo; -/// \brief This is the base class for diagnostic handling in LLVM. +/// This is the base class for diagnostic handling in LLVM. /// The handleDiagnostics method must be overriden by the subclasses to handle /// diagnostic. The *RemarkEnabled methods can be overriden to control /// which remarks are enabled. diff --git a/contrib/llvm/include/llvm/IR/DiagnosticInfo.h b/contrib/llvm/include/llvm/IR/DiagnosticInfo.h index 020b67d6b711..81d4ae84bf01 100644 --- a/contrib/llvm/include/llvm/IR/DiagnosticInfo.h +++ b/contrib/llvm/include/llvm/IR/DiagnosticInfo.h @@ -39,7 +39,7 @@ class LLVMContext; class Module; class SMDiagnostic; -/// \brief Defines the different supported severity of a diagnostic. +/// Defines the different supported severity of a diagnostic. enum DiagnosticSeverity : char { DS_Error, DS_Warning, @@ -49,7 +49,7 @@ enum DiagnosticSeverity : char { DS_Note }; -/// \brief Defines the different supported kind of a diagnostic. +/// 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, @@ -79,7 +79,7 @@ enum DiagnosticKind { DK_FirstPluginKind }; -/// \brief Get the next available kind ID for a plugin diagnostic. +/// 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 @@ -89,7 +89,7 @@ enum DiagnosticKind { /// DiagnosticKind values. int getNextAvailablePluginDiagnosticKind(); -/// \brief This is the base abstract class for diagnostic reporting in +/// 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 @@ -389,20 +389,20 @@ private: DiagnosticLocation Loc; }; -/// \brief Common features for diagnostics dealing with optimization remarks +/// Common features for diagnostics dealing with optimization remarks /// that are used by both IR and MIR passes. class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase { public: - /// \brief Used to set IsVerbose via the stream interface. + /// Used to set IsVerbose via the stream interface. struct setIsVerbose {}; - /// \brief When an instance of this is inserted into the stream, the arguments + /// When an instance of this is inserted into the stream, the arguments /// following will not appear in the remark printed in the compiler output /// (-Rpass) but only in the optimization record file /// (-fsave-optimization-record). struct setExtraArgs {}; - /// \brief Used in the streaming interface as the general argument type. It + /// Used in the streaming interface as the general argument type. It /// internally converts everything into a key-value pair. struct Argument { std::string Key; @@ -415,6 +415,7 @@ public: Argument(StringRef Key, const Type *T); Argument(StringRef Key, StringRef S); Argument(StringRef Key, int N); + Argument(StringRef Key, float N); Argument(StringRef Key, long N); Argument(StringRef Key, long long N); Argument(StringRef Key, unsigned N); @@ -503,7 +504,7 @@ protected: /// The remark is expected to be noisy. bool IsVerbose = false; - /// \brief If positive, the index of the first argument that only appear in + /// If positive, the index of the first argument that only appear in /// the optimization records and not in the remark printed in the compiler /// output. int FirstExtraArgIndex = -1; @@ -586,7 +587,7 @@ operator<<(RemarkT &R, return R; } -/// \brief Common features for diagnostics dealing with optimization remarks +/// Common features for diagnostics dealing with optimization remarks /// that are used by IR passes. class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase { public: @@ -608,7 +609,7 @@ public: Loc), CodeRegion(CodeRegion) {} - /// \brief This is ctor variant allows a pass to build an optimization remark + /// This is ctor variant allows a pass to build an optimization remark /// from an existing remark. /// /// This is useful when a transformation pass (e.g LV) wants to emit a remark @@ -711,7 +712,7 @@ public: const DiagnosticLocation &Loc, const Value *CodeRegion); - /// \brief Same as above but \p Inst is used to derive code region and debug + /// Same as above but \p Inst is used to derive code region and debug /// location. OptimizationRemarkMissed(const char *PassName, StringRef RemarkName, const Instruction *Inst); @@ -752,7 +753,7 @@ public: const DiagnosticLocation &Loc, const Value *CodeRegion); - /// \brief This is ctor variant allows a pass to build an optimization remark + /// This is ctor variant allows a pass to build an optimization remark /// from an existing remark. /// /// This is useful when a transformation pass (e.g LV) wants to emit a remark @@ -763,7 +764,7 @@ public: const OptimizationRemarkAnalysis &Orig) : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {} - /// \brief Same as above but \p Inst is used to derive code region and debug + /// Same as above but \p Inst is used to derive code region and debug /// location. OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, const Instruction *Inst); diff --git a/contrib/llvm/include/llvm/IR/DiagnosticPrinter.h b/contrib/llvm/include/llvm/IR/DiagnosticPrinter.h index 59c83291affa..25c47cdd1a12 100644 --- a/contrib/llvm/include/llvm/IR/DiagnosticPrinter.h +++ b/contrib/llvm/include/llvm/IR/DiagnosticPrinter.h @@ -28,7 +28,7 @@ class StringRef; class Twine; class Value; -/// \brief Interface for custom diagnostic printing. +/// Interface for custom diagnostic printing. class DiagnosticPrinter { public: virtual ~DiagnosticPrinter() = default; @@ -58,7 +58,7 @@ public: virtual DiagnosticPrinter &operator<<(const SMDiagnostic &Diag) = 0; }; -/// \brief Basic diagnostic printer that uses an underlying raw_ostream. +/// Basic diagnostic printer that uses an underlying raw_ostream. class DiagnosticPrinterRawOStream : public DiagnosticPrinter { protected: raw_ostream &Stream; diff --git a/contrib/llvm/include/llvm/IR/DomTreeUpdater.h b/contrib/llvm/include/llvm/IR/DomTreeUpdater.h new file mode 100644 index 000000000000..81ba670ac0f5 --- /dev/null +++ b/contrib/llvm/include/llvm/IR/DomTreeUpdater.h @@ -0,0 +1,259 @@ +//===- DomTreeUpdater.h - DomTree/Post DomTree Updater ----------*- 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 DomTreeUpdater class, which provides a uniform way to +// update dominator tree related data structures. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DOMTREEUPDATER_H +#define LLVM_DOMTREEUPDATER_H + +#include "llvm/Analysis/PostDominators.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/GenericDomTree.h" +#include <functional> +#include <vector> + +namespace llvm { +class DomTreeUpdater { +public: + enum class UpdateStrategy : unsigned char { Eager = 0, Lazy = 1 }; + + explicit DomTreeUpdater(UpdateStrategy Strategy_) : Strategy(Strategy_) {} + DomTreeUpdater(DominatorTree &DT_, UpdateStrategy Strategy_) + : DT(&DT_), Strategy(Strategy_) {} + DomTreeUpdater(DominatorTree *DT_, UpdateStrategy Strategy_) + : DT(DT_), Strategy(Strategy_) {} + DomTreeUpdater(PostDominatorTree &PDT_, UpdateStrategy Strategy_) + : PDT(&PDT_), Strategy(Strategy_) {} + DomTreeUpdater(PostDominatorTree *PDT_, UpdateStrategy Strategy_) + : PDT(PDT_), Strategy(Strategy_) {} + DomTreeUpdater(DominatorTree &DT_, PostDominatorTree &PDT_, + UpdateStrategy Strategy_) + : DT(&DT_), PDT(&PDT_), Strategy(Strategy_) {} + DomTreeUpdater(DominatorTree *DT_, PostDominatorTree *PDT_, + UpdateStrategy Strategy_) + : DT(DT_), PDT(PDT_), Strategy(Strategy_) {} + + ~DomTreeUpdater() { flush(); } + + /// Returns true if the current strategy is Lazy. + bool isLazy() const { return Strategy == UpdateStrategy::Lazy; }; + + /// Returns true if the current strategy is Eager. + bool isEager() const { return Strategy == UpdateStrategy::Eager; }; + + /// Returns true if it holds a DominatorTree. + bool hasDomTree() const { return DT != nullptr; } + + /// Returns true if it holds a PostDominatorTree. + bool hasPostDomTree() const { return PDT != nullptr; } + + /// Returns true if there is BasicBlock awaiting deletion. + /// The deletion will only happen until a flush event and + /// all available trees are up-to-date. + /// Returns false under Eager UpdateStrategy. + bool hasPendingDeletedBB() const { return !DeletedBBs.empty(); } + + /// Returns true if DelBB is awaiting deletion. + /// Returns false under Eager UpdateStrategy. + bool isBBPendingDeletion(BasicBlock *DelBB) const; + + /// Returns true if either of DT or PDT is valid and the tree has at + /// least one update pending. If DT or PDT is nullptr it is treated + /// as having no pending updates. This function does not check + /// whether there is BasicBlock awaiting deletion. + /// Returns false under Eager UpdateStrategy. + bool hasPendingUpdates() const; + + /// Returns true if there are DominatorTree updates queued. + /// Returns false under Eager UpdateStrategy or DT is nullptr. + bool hasPendingDomTreeUpdates() const; + + /// Returns true if there are PostDominatorTree updates queued. + /// Returns false under Eager UpdateStrategy or PDT is nullptr. + bool hasPendingPostDomTreeUpdates() const; + + /// Apply updates on all available trees. Under Eager UpdateStrategy with + /// ForceRemoveDuplicates enabled or under Lazy UpdateStrategy, it will + /// discard duplicated updates and self-dominance updates. If both DT and PDT + /// are nullptrs, this function discards all updates. The Eager Strategy + /// applies the updates immediately while the Lazy Strategy queues the + /// updates. It is required for the state of the LLVM IR to be updated + /// *before* applying the Updates because the internal update routine will + /// analyze the current state of the relationship between a pair of (From, To) + /// BasicBlocks to determine whether a single update needs to be discarded. + void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates, + bool ForceRemoveDuplicates = false); + + /// Notify all available trees on an edge insertion. If both DT and PDT are + /// nullptrs, this function discards the update. Under either Strategy, + /// self-dominance update will be removed. The Eager Strategy applies + /// the update immediately while the Lazy Strategy queues the update. + /// It is recommended to only use this method when you have exactly one + /// insertion (and no deletions). It is recommended to use applyUpdates() in + /// all other cases. This function has to be called *after* making the update + /// on the actual CFG. An internal functions checks if the edge exists in the + /// CFG in DEBUG mode. + void insertEdge(BasicBlock *From, BasicBlock *To); + + /// Notify all available trees on an edge insertion. + /// Under either Strategy, the following updates will be discard silently + /// 1. Invalid - Inserting an edge that does not exist in the CFG. + /// 2. Self-dominance update. + /// 3. Both DT and PDT are nullptrs. + /// The Eager Strategy applies the update immediately while the Lazy Strategy + /// queues the update. It is recommended to only use this method when you have + /// exactly one insertion (and no deletions) and want to discard an invalid + /// update. + void insertEdgeRelaxed(BasicBlock *From, BasicBlock *To); + + /// Notify all available trees on an edge deletion. If both DT and PDT are + /// nullptrs, this function discards the update. Under either Strategy, + /// self-dominance update will be removed. The Eager Strategy applies + /// the update immediately while the Lazy Strategy queues the update. + /// It is recommended to only use this method when you have exactly one + /// deletion (and no insertions). It is recommended to use applyUpdates() in + /// all other cases. This function has to be called *after* making the update + /// on the actual CFG. An internal functions checks if the edge doesn't exist + /// in the CFG in DEBUG mode. + void deleteEdge(BasicBlock *From, BasicBlock *To); + + /// Notify all available trees on an edge deletion. + /// Under either Strategy, the following updates will be discard silently + /// 1. Invalid - Deleting an edge that still exists in the CFG. + /// 2. Self-dominance update. + /// 3. Both DT and PDT are nullptrs. + /// The Eager Strategy applies the update immediately while the Lazy Strategy + /// queues the update. It is recommended to only use this method when you have + /// exactly one deletion (and no insertions) and want to discard an invalid + /// update. + void deleteEdgeRelaxed(BasicBlock *From, BasicBlock *To); + + /// Delete DelBB. DelBB will be removed from its Parent and + /// erased from available trees if it exists and finally get deleted. + /// Under Eager UpdateStrategy, DelBB will be processed immediately. + /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and + /// all available trees are up-to-date. Assert if any instruction of DelBB is + /// modified while awaiting deletion. When both DT and PDT are nullptrs, DelBB + /// will be queued until flush() is called. + void deleteBB(BasicBlock *DelBB); + + /// Delete DelBB. DelBB will be removed from its Parent and + /// erased from available trees if it exists. Then the callback will + /// be called. Finally, DelBB will be deleted. + /// Under Eager UpdateStrategy, DelBB will be processed immediately. + /// Under Lazy UpdateStrategy, DelBB will be queued until a flush event and + /// all available trees are up-to-date. Assert if any instruction of DelBB is + /// modified while awaiting deletion. Multiple callbacks can be queued for one + /// DelBB under Lazy UpdateStrategy. + void callbackDeleteBB(BasicBlock *DelBB, + std::function<void(BasicBlock *)> Callback); + + /// Recalculate all available trees. + /// Under Lazy Strategy, available trees will only be recalculated if there + /// are pending updates or there is BasicBlock awaiting deletion. Returns true + /// if at least one tree is recalculated. + bool recalculate(Function &F); + + /// Flush DomTree updates and return DomTree. + /// It also flush out of date updates applied by all available trees + /// and flush Deleted BBs if both trees are up-to-date. + /// It must only be called when it has a DomTree. + DominatorTree &getDomTree(); + + /// Flush PostDomTree updates and return PostDomTree. + /// It also flush out of date updates applied by all available trees + /// and flush Deleted BBs if both trees are up-to-date. + /// It must only be called when it has a PostDomTree. + PostDominatorTree &getPostDomTree(); + + /// Apply all pending updates to available trees and flush all BasicBlocks + /// awaiting deletion. + /// Does nothing under Eager UpdateStrategy. + void flush(); + + /// Debug method to help view the internal state of this class. + LLVM_DUMP_METHOD void dump() const; + +private: + class CallBackOnDeletion final : public CallbackVH { + public: + CallBackOnDeletion(BasicBlock *V, + std::function<void(BasicBlock *)> Callback) + : CallbackVH(V), DelBB(V), Callback_(Callback) {} + + private: + BasicBlock *DelBB = nullptr; + std::function<void(BasicBlock *)> Callback_; + + void deleted() override { + Callback_(DelBB); + CallbackVH::deleted(); + } + }; + + SmallVector<DominatorTree::UpdateType, 16> PendUpdates; + size_t PendDTUpdateIndex = 0; + size_t PendPDTUpdateIndex = 0; + DominatorTree *DT = nullptr; + PostDominatorTree *PDT = nullptr; + const UpdateStrategy Strategy; + SmallPtrSet<BasicBlock *, 8> DeletedBBs; + std::vector<CallBackOnDeletion> Callbacks; + bool IsRecalculatingDomTree = false; + bool IsRecalculatingPostDomTree = false; + + /// First remove all the instructions of DelBB and then make sure DelBB has a + /// valid terminator instruction which is necessary to have when DelBB still + /// has to be inside of its parent Function while awaiting deletion under Lazy + /// UpdateStrategy to prevent other routines from asserting the state of the + /// IR is inconsistent. Assert if DelBB is nullptr or has predecessors. + void validateDeleteBB(BasicBlock *DelBB); + + /// Returns true if at least one BasicBlock is deleted. + bool forceFlushDeletedBB(); + + /// Deduplicate and remove unnecessary updates (no-ops) when using Lazy + /// UpdateStrategy. Returns true if the update is queued for update. + bool applyLazyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From, + BasicBlock *To); + + /// Helper function to apply all pending DomTree updates. + void applyDomTreeUpdates(); + + /// Helper function to apply all pending PostDomTree updates. + void applyPostDomTreeUpdates(); + + /// Helper function to flush deleted BasicBlocks if all available + /// trees are up-to-date. + void tryFlushDeletedBB(); + + /// Drop all updates applied by all available trees and delete BasicBlocks if + /// all available trees are up-to-date. + void dropOutOfDateUpdates(); + + /// Erase Basic Block node that has been unlinked from Function + /// in the DomTree and PostDomTree. + void eraseDelBBNode(BasicBlock *DelBB); + + /// Returns true if the update appears in the LLVM IR. + /// It is used to check whether an update is valid in + /// insertEdge/deleteEdge or is unnecessary in the batch update. + bool isUpdateValid(DominatorTree::UpdateType Update) const; + + /// Returns true if the update is self dominance. + bool isSelfDominance(DominatorTree::UpdateType Update) const; +}; +} // namespace llvm + +#endif // LLVM_DOMTREEUPDATER_H diff --git a/contrib/llvm/include/llvm/IR/Dominators.h b/contrib/llvm/include/llvm/IR/Dominators.h index 6ad99e516fba..f9e992b0ef0c 100644 --- a/contrib/llvm/include/llvm/IR/Dominators.h +++ b/contrib/llvm/include/llvm/IR/Dominators.h @@ -63,8 +63,10 @@ extern template void DeleteEdge<BBPostDomTree>(BBPostDomTree &DT, extern template void ApplyUpdates<BBDomTree>(BBDomTree &DT, BBUpdates); extern template void ApplyUpdates<BBPostDomTree>(BBPostDomTree &DT, BBUpdates); -extern template bool Verify<BBDomTree>(const BBDomTree &DT); -extern template bool Verify<BBPostDomTree>(const BBPostDomTree &DT); +extern template bool Verify<BBDomTree>(const BBDomTree &DT, + BBDomTree::VerificationLevel VL); +extern template bool Verify<BBPostDomTree>(const BBPostDomTree &DT, + BBPostDomTree::VerificationLevel VL); } // namespace DomTreeBuilder using DomTreeNode = DomTreeNodeBase<BasicBlock>; @@ -119,7 +121,7 @@ template <> struct DenseMapInfo<BasicBlockEdge> { } }; -/// \brief Concrete subclass of DominatorTreeBase that is used to compute a +/// Concrete subclass of DominatorTreeBase that is used to compute a /// normal dominator tree. /// /// Definition: A block is said to be forward statically reachable if there is @@ -148,19 +150,10 @@ class DominatorTree : public DominatorTreeBase<BasicBlock, false> { bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &); - /// \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(); - return !R || !OtherR || R->getBlock() != OtherR->getBlock() || - Base::compare(Other); - } - // Ensure base-class overloads are visible. using Base::dominates; - /// \brief Return true if Def dominates a use in User. + /// 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! @@ -178,15 +171,9 @@ class DominatorTree : public DominatorTreeBase<BasicBlock, false> { // Ensure base class overloads are visible. using Base::isReachableFromEntry; - /// \brief Provide an overload for a Use. + /// 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; - // Pop up a GraphViz/gv window with the Dominator Tree rendered using `dot`. void viewGraph(const Twine &Name, const Twine &Title); void viewGraph(); @@ -234,20 +221,20 @@ template <> struct GraphTraits<DominatorTree*> } }; -/// \brief Analysis pass which computes a \c DominatorTree. +/// Analysis pass which computes a \c DominatorTree. class DominatorTreeAnalysis : public AnalysisInfoMixin<DominatorTreeAnalysis> { friend AnalysisInfoMixin<DominatorTreeAnalysis>; static AnalysisKey Key; public: - /// \brief Provide the result typedef for this analysis pass. + /// Provide the result typedef for this analysis pass. using Result = DominatorTree; - /// \brief Run the analysis pass over a function and produce a dominator tree. + /// Run the analysis pass over a function and produce a dominator tree. DominatorTree run(Function &F, FunctionAnalysisManager &); }; -/// \brief Printer pass for the \c DominatorTree. +/// Printer pass for the \c DominatorTree. class DominatorTreePrinterPass : public PassInfoMixin<DominatorTreePrinterPass> { raw_ostream &OS; @@ -258,12 +245,12 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Verifier pass for the \c DominatorTree. +/// Verifier pass for the \c DominatorTree. struct DominatorTreeVerifierPass : PassInfoMixin<DominatorTreeVerifierPass> { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Legacy analysis pass which computes a \c DominatorTree. +/// Legacy analysis pass which computes a \c DominatorTree. class DominatorTreeWrapperPass : public FunctionPass { DominatorTree DT; @@ -290,6 +277,93 @@ public: void print(raw_ostream &OS, const Module *M = nullptr) const override; }; +//===------------------------------------- +/// Class to defer updates to a DominatorTree. +/// +/// Definition: Applying updates to every edge insertion and deletion is +/// expensive and not necessary. When one needs the DominatorTree for analysis +/// they can request a flush() to perform a larger batch update. This has the +/// advantage of the DominatorTree inspecting the set of updates to find +/// duplicates or unnecessary subtree updates. +/// +/// The scope of DeferredDominance operates at a Function level. +/// +/// It is not necessary for the user to scrub the updates for duplicates or +/// updates that point to the same block (Delete, BB_A, BB_A). Performance +/// can be gained if the caller attempts to batch updates before submitting +/// to applyUpdates(ArrayRef) in cases where duplicate edge requests will +/// occur. +/// +/// It is required for the state of the LLVM IR to be applied *before* +/// submitting updates. The update routines must analyze the current state +/// between a pair of (From, To) basic blocks to determine if the update +/// needs to be queued. +/// Example (good): +/// TerminatorInstructionBB->removeFromParent(); +/// DDT->deleteEdge(BB, Successor); +/// Example (bad): +/// DDT->deleteEdge(BB, Successor); +/// TerminatorInstructionBB->removeFromParent(); +class DeferredDominance { +public: + DeferredDominance(DominatorTree &DT_) : DT(DT_) {} + + /// Queues multiple updates and discards duplicates. + void applyUpdates(ArrayRef<DominatorTree::UpdateType> Updates); + + /// Helper method for a single edge insertion. It's almost always + /// better to batch updates and call applyUpdates to quickly remove duplicate + /// edges. This is best used when there is only a single insertion needed to + /// update Dominators. + void insertEdge(BasicBlock *From, BasicBlock *To); + + /// Helper method for a single edge deletion. It's almost always better + /// to batch updates and call applyUpdates to quickly remove duplicate edges. + /// This is best used when there is only a single deletion needed to update + /// Dominators. + void deleteEdge(BasicBlock *From, BasicBlock *To); + + /// Delays the deletion of a basic block until a flush() event. + void deleteBB(BasicBlock *DelBB); + + /// Returns true if DelBB is awaiting deletion at a flush() event. + bool pendingDeletedBB(BasicBlock *DelBB); + + /// Returns true if pending DT updates are queued for a flush() event. + bool pending(); + + /// Flushes all pending updates and block deletions. Returns a + /// correct DominatorTree reference to be used by the caller for analysis. + DominatorTree &flush(); + + /// Drops all internal state and forces a (slow) recalculation of the + /// DominatorTree based on the current state of the LLVM IR in F. This should + /// only be used in corner cases such as the Entry block of F being deleted. + void recalculate(Function &F); + + /// Debug method to help view the state of pending updates. + LLVM_DUMP_METHOD void dump() const; + +private: + DominatorTree &DT; + SmallVector<DominatorTree::UpdateType, 16> PendUpdates; + SmallPtrSet<BasicBlock *, 8> DeletedBBs; + + /// Apply an update (Kind, From, To) to the internal queued updates. The + /// update is only added when determined to be necessary. Checks for + /// self-domination, unnecessary updates, duplicate requests, and balanced + /// pairs of requests are all performed. Returns true if the update is + /// queued and false if it is discarded. + bool applyUpdate(DominatorTree::UpdateKind Kind, BasicBlock *From, + BasicBlock *To); + + /// Performs all pending basic block deletions. We have to defer the deletion + /// of these blocks until after the DominatorTree updates are applied. The + /// internal workings of the DominatorTree code expect every update's From + /// and To blocks to exist and to be a member of the same Function. + bool flushDelBB(); +}; + } // end namespace llvm #endif // LLVM_IR_DOMINATORS_H diff --git a/contrib/llvm/include/llvm/IR/Function.h b/contrib/llvm/include/llvm/IR/Function.h index def842f5fcee..c8d6b0776fbf 100644 --- a/contrib/llvm/include/llvm/IR/Function.h +++ b/contrib/llvm/include/llvm/IR/Function.h @@ -141,6 +141,11 @@ public: // Provide fast operand accessors. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + /// Returns the number of non-debug IR instructions in this function. + /// This is equivalent to the sum of the sizes of each basic block contained + /// within this function. + unsigned getInstructionCount(); + /// Returns the FunctionType for me. FunctionType *getFunctionType() const { return cast<FunctionType>(getValueType()); @@ -181,7 +186,7 @@ public: static Intrinsic::ID lookupIntrinsicID(StringRef Name); - /// \brief Recalculate the ID for this function if it is an Intrinsic defined + /// Recalculate the ID for this function if it is an Intrinsic defined /// in llvm/Intrinsics.h. Sets the intrinsic ID to Intrinsic::not_intrinsic /// if the name of this function does not match an intrinsic in that header. /// Note, this method does not need to be called directly, as it is called @@ -201,53 +206,86 @@ public: setValueSubclassData((getSubclassDataFromValue() & 0xc00f) | (ID << 4)); } - /// @brief Return the attribute list for this Function. + /// Return the attribute list for this Function. AttributeList getAttributes() const { return AttributeSets; } - /// @brief Set the attribute list for this Function. + /// Set the attribute list for this Function. void setAttributes(AttributeList Attrs) { AttributeSets = Attrs; } - /// @brief Add function attributes to this function. + /// Add function attributes to this function. void addFnAttr(Attribute::AttrKind Kind) { addAttribute(AttributeList::FunctionIndex, Kind); } - /// @brief Add function attributes to this function. + /// Add function attributes to this function. void addFnAttr(StringRef Kind, StringRef Val = StringRef()) { addAttribute(AttributeList::FunctionIndex, Attribute::get(getContext(), Kind, Val)); } - /// @brief Add function attributes to this function. + /// Add function attributes to this function. void addFnAttr(Attribute Attr) { addAttribute(AttributeList::FunctionIndex, Attr); } - /// @brief Remove function attributes from this function. + /// Remove function attributes from this function. void removeFnAttr(Attribute::AttrKind Kind) { removeAttribute(AttributeList::FunctionIndex, Kind); } - /// @brief Remove function attribute from this function. + /// Remove function attribute from this function. void removeFnAttr(StringRef Kind) { setAttributes(getAttributes().removeAttribute( getContext(), AttributeList::FunctionIndex, Kind)); } - /// \brief Set the entry count for this function. + enum ProfileCountType { PCT_Invalid, PCT_Real, PCT_Synthetic }; + + /// Class to represent profile counts. + /// + /// This class represents both real and synthetic profile counts. + class ProfileCount { + private: + uint64_t Count; + ProfileCountType PCT; + static ProfileCount Invalid; + + public: + ProfileCount() : Count(-1), PCT(PCT_Invalid) {} + ProfileCount(uint64_t Count, ProfileCountType PCT) + : Count(Count), PCT(PCT) {} + bool hasValue() const { return PCT != PCT_Invalid; } + uint64_t getCount() const { return Count; } + ProfileCountType getType() const { return PCT; } + bool isSynthetic() const { return PCT == PCT_Synthetic; } + explicit operator bool() { return hasValue(); } + bool operator!() const { return !hasValue(); } + // Update the count retaining the same profile count type. + ProfileCount &setCount(uint64_t C) { + Count = C; + return *this; + } + static ProfileCount getInvalid() { return ProfileCount(-1, PCT_Invalid); } + }; + + /// Set the entry count for this function. /// /// Entry count is the number of times this function was executed based on - /// pgo data. \p Imports points to a set of GUIDs that needs to be imported - /// by the function for sample PGO, to enable the same inlines as the - /// profiled optimized binary. - void setEntryCount(uint64_t Count, + /// pgo data. \p Imports points to a set of GUIDs that needs to + /// be imported by the function for sample PGO, to enable the same inlines as + /// the profiled optimized binary. + void setEntryCount(ProfileCount Count, const DenseSet<GlobalValue::GUID> *Imports = nullptr); - /// \brief Get the entry count for this function. + /// A convenience wrapper for setting entry count + void setEntryCount(uint64_t Count, ProfileCountType Type = PCT_Real, + const DenseSet<GlobalValue::GUID> *Imports = nullptr); + + /// Get the entry count for this function. /// /// Entry count is the number of times the function was executed based on /// pgo data. - Optional<uint64_t> getEntryCount() const; + ProfileCount getEntryCount() const; /// Return true if the function is annotated with profile data. /// @@ -265,27 +303,27 @@ public: /// Get the section prefix for this function. Optional<StringRef> getSectionPrefix() const; - /// @brief Return true if the function has the attribute. + /// Return true if the function has the attribute. bool hasFnAttribute(Attribute::AttrKind Kind) const { return AttributeSets.hasFnAttribute(Kind); } - /// @brief Return true if the function has the attribute. + /// Return true if the function has the attribute. bool hasFnAttribute(StringRef Kind) const { return AttributeSets.hasFnAttribute(Kind); } - /// @brief Return the attribute for the given attribute kind. + /// Return the attribute for the given attribute kind. Attribute getFnAttribute(Attribute::AttrKind Kind) const { return getAttribute(AttributeList::FunctionIndex, Kind); } - /// @brief Return the attribute for the given attribute kind. + /// Return the attribute for the given attribute kind. Attribute getFnAttribute(StringRef Kind) const { return getAttribute(AttributeList::FunctionIndex, Kind); } - /// \brief Return the stack alignment for the function. + /// Return the stack alignment for the function. unsigned getFnStackAlignment() const { if (!hasFnAttribute(Attribute::StackAlignment)) return 0; @@ -301,110 +339,110 @@ public: void setGC(std::string Str); void clearGC(); - /// @brief adds the attribute to the list of attributes. + /// adds the attribute to the list of attributes. void addAttribute(unsigned i, Attribute::AttrKind Kind); - /// @brief adds the attribute to the list of attributes. + /// adds the attribute to the list of attributes. void addAttribute(unsigned i, Attribute Attr); - /// @brief adds the attributes to the list of attributes. + /// adds the attributes to the list of attributes. void addAttributes(unsigned i, const AttrBuilder &Attrs); - /// @brief adds the attribute to the list of attributes for the given arg. + /// adds the attribute to the list of attributes for the given arg. void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); - /// @brief adds the attribute to the list of attributes for the given arg. + /// adds the attribute to the list of attributes for the given arg. void addParamAttr(unsigned ArgNo, Attribute Attr); - /// @brief adds the attributes to the list of attributes for the given arg. + /// adds the attributes to the list of attributes for the given arg. void addParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs); - /// @brief removes the attribute from the list of attributes. + /// removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute::AttrKind Kind); - /// @brief removes the attribute from the list of attributes. + /// removes the attribute from the list of attributes. void removeAttribute(unsigned i, StringRef Kind); - /// @brief removes the attributes from the list of attributes. + /// removes the attributes from the list of attributes. void removeAttributes(unsigned i, const AttrBuilder &Attrs); - /// @brief removes the attribute from the list of attributes. + /// removes the attribute from the list of attributes. void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); - /// @brief removes the attribute from the list of attributes. + /// removes the attribute from the list of attributes. void removeParamAttr(unsigned ArgNo, StringRef Kind); - /// @brief removes the attribute from the list of attributes. + /// removes the attribute from the list of attributes. void removeParamAttrs(unsigned ArgNo, const AttrBuilder &Attrs); - /// @brief check if an attributes is in the list of attributes. + /// check if an attributes is in the list of attributes. bool hasAttribute(unsigned i, Attribute::AttrKind Kind) const { return getAttributes().hasAttribute(i, Kind); } - /// @brief check if an attributes is in the list of attributes. + /// check if an attributes is in the list of attributes. bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const { return getAttributes().hasParamAttribute(ArgNo, Kind); } - /// @brief gets the attribute from the list of attributes. + /// gets the attribute from the list of attributes. Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const { return AttributeSets.getAttribute(i, Kind); } - /// @brief gets the attribute from the list of attributes. + /// gets the attribute from the list of attributes. Attribute getAttribute(unsigned i, StringRef Kind) const { return AttributeSets.getAttribute(i, Kind); } - /// @brief adds the dereferenceable attribute to the list of attributes. + /// adds the dereferenceable attribute to the list of attributes. void addDereferenceableAttr(unsigned i, uint64_t Bytes); - /// @brief adds the dereferenceable attribute to the list of attributes for + /// adds the dereferenceable attribute to the list of attributes for /// the given arg. void addDereferenceableParamAttr(unsigned ArgNo, uint64_t Bytes); - /// @brief adds the dereferenceable_or_null attribute to the list of + /// adds the dereferenceable_or_null attribute to the list of /// attributes. void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); - /// @brief adds the dereferenceable_or_null attribute to the list of + /// adds the dereferenceable_or_null attribute to the list of /// attributes for the given arg. void addDereferenceableOrNullParamAttr(unsigned ArgNo, uint64_t Bytes); - /// @brief Extract the alignment for a call or parameter (0=unknown). + /// Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned ArgNo) const { return AttributeSets.getParamAlignment(ArgNo); } - /// @brief Extract the number of dereferenceable bytes for a call or + /// Extract the number of dereferenceable bytes for a call or /// parameter (0=unknown). /// @param i AttributeList index, referring to a return value or argument. uint64_t getDereferenceableBytes(unsigned i) const { return AttributeSets.getDereferenceableBytes(i); } - /// @brief Extract the number of dereferenceable bytes for a parameter. + /// Extract the number of dereferenceable bytes for a parameter. /// @param ArgNo Index of an argument, with 0 being the first function arg. uint64_t getParamDereferenceableBytes(unsigned ArgNo) const { return AttributeSets.getParamDereferenceableBytes(ArgNo); } - /// @brief Extract the number of dereferenceable_or_null bytes for a call or + /// Extract the number of dereferenceable_or_null bytes for a call or /// parameter (0=unknown). /// @param i AttributeList index, referring to a return value or argument. uint64_t getDereferenceableOrNullBytes(unsigned i) const { return AttributeSets.getDereferenceableOrNullBytes(i); } - /// @brief Extract the number of dereferenceable_or_null bytes for a + /// Extract the number of dereferenceable_or_null bytes for a /// parameter. /// @param ArgNo AttributeList ArgNo, referring to an argument. uint64_t getParamDereferenceableOrNullBytes(unsigned ArgNo) const { return AttributeSets.getParamDereferenceableOrNullBytes(ArgNo); } - /// @brief Determine if the function does not access memory. + /// Determine if the function does not access memory. bool doesNotAccessMemory() const { return hasFnAttribute(Attribute::ReadNone); } @@ -412,7 +450,7 @@ public: addFnAttr(Attribute::ReadNone); } - /// @brief Determine if the function does not access or only reads memory. + /// Determine if the function does not access or only reads memory. bool onlyReadsMemory() const { return doesNotAccessMemory() || hasFnAttribute(Attribute::ReadOnly); } @@ -420,7 +458,7 @@ public: addFnAttr(Attribute::ReadOnly); } - /// @brief Determine if the function does not access or only writes memory. + /// Determine if the function does not access or only writes memory. bool doesNotReadMemory() const { return doesNotAccessMemory() || hasFnAttribute(Attribute::WriteOnly); } @@ -428,14 +466,14 @@ public: addFnAttr(Attribute::WriteOnly); } - /// @brief Determine if the call can access memmory only using pointers based + /// Determine if the call can access memmory only using pointers based /// on its arguments. bool onlyAccessesArgMemory() const { return hasFnAttribute(Attribute::ArgMemOnly); } void setOnlyAccessesArgMemory() { addFnAttr(Attribute::ArgMemOnly); } - /// @brief Determine if the function may only access memory that is + /// Determine if the function may only access memory that is /// inaccessible from the IR. bool onlyAccessesInaccessibleMemory() const { return hasFnAttribute(Attribute::InaccessibleMemOnly); @@ -444,7 +482,7 @@ public: addFnAttr(Attribute::InaccessibleMemOnly); } - /// @brief Determine if the function may only access memory that is + /// Determine if the function may only access memory that is /// either inaccessible from the IR or pointed to by its arguments. bool onlyAccessesInaccessibleMemOrArgMem() const { return hasFnAttribute(Attribute::InaccessibleMemOrArgMemOnly); @@ -453,7 +491,7 @@ public: addFnAttr(Attribute::InaccessibleMemOrArgMemOnly); } - /// @brief Determine if the function cannot return. + /// Determine if the function cannot return. bool doesNotReturn() const { return hasFnAttribute(Attribute::NoReturn); } @@ -461,7 +499,10 @@ public: addFnAttr(Attribute::NoReturn); } - /// @brief Determine if the function cannot unwind. + /// Determine if the function should not perform indirect branch tracking. + bool doesNoCfCheck() const { return hasFnAttribute(Attribute::NoCfCheck); } + + /// Determine if the function cannot unwind. bool doesNotThrow() const { return hasFnAttribute(Attribute::NoUnwind); } @@ -469,7 +510,7 @@ public: addFnAttr(Attribute::NoUnwind); } - /// @brief Determine if the call cannot be duplicated. + /// Determine if the call cannot be duplicated. bool cannotDuplicate() const { return hasFnAttribute(Attribute::NoDuplicate); } @@ -477,7 +518,7 @@ public: addFnAttr(Attribute::NoDuplicate); } - /// @brief Determine if the call is convergent. + /// Determine if the call is convergent. bool isConvergent() const { return hasFnAttribute(Attribute::Convergent); } @@ -488,7 +529,7 @@ public: removeFnAttr(Attribute::Convergent); } - /// @brief Determine if the call has sideeffects. + /// Determine if the call has sideeffects. bool isSpeculatable() const { return hasFnAttribute(Attribute::Speculatable); } @@ -505,7 +546,7 @@ public: addFnAttr(Attribute::NoRecurse); } - /// @brief True if the ABI mandates (or the user requested) that this + /// True if the ABI mandates (or the user requested) that this /// function be in a unwind table. bool hasUWTable() const { return hasFnAttribute(Attribute::UWTable); @@ -514,19 +555,19 @@ public: addFnAttr(Attribute::UWTable); } - /// @brief True if this function needs an unwind table. + /// True if this function needs an unwind table. bool needsUnwindTableEntry() const { return hasUWTable() || !doesNotThrow(); } - /// @brief Determine if the function returns a structure through first + /// Determine if the function returns a structure through first /// or second pointer argument. bool hasStructRetAttr() const { return AttributeSets.hasParamAttribute(0, Attribute::StructRet) || AttributeSets.hasParamAttribute(1, Attribute::StructRet); } - /// @brief Determine if the parameter or return value is marked with NoAlias + /// Determine if the parameter or return value is marked with NoAlias /// attribute. bool returnDoesNotAlias() const { return AttributeSets.hasAttribute(AttributeList::ReturnIndex, @@ -643,30 +684,30 @@ public: size_t arg_size() const { return NumArgs; } bool arg_empty() const { return arg_size() == 0; } - /// \brief Check whether this function has a personality function. + /// Check whether this function has a personality function. bool hasPersonalityFn() const { return getSubclassDataFromValue() & (1<<3); } - /// \brief Get the personality function associated with this function. + /// Get the personality function associated with this function. Constant *getPersonalityFn() const; void setPersonalityFn(Constant *Fn); - /// \brief Check whether this function has prefix data. + /// Check whether this function has prefix data. bool hasPrefixData() const { return getSubclassDataFromValue() & (1<<1); } - /// \brief Get the prefix data associated with this function. + /// Get the prefix data associated with this function. Constant *getPrefixData() const; void setPrefixData(Constant *PrefixData); - /// \brief Check whether this function has prologue data. + /// Check whether this function has prologue data. bool hasPrologueData() const { return getSubclassDataFromValue() & (1<<2); } - /// \brief Get the prologue data associated with this function. + /// Get the prologue data associated with this function. Constant *getPrologueData() const; void setPrologueData(Constant *PrologueData); @@ -726,12 +767,12 @@ public: /// setjmp or other function that gcc recognizes as "returning twice". bool callsFunctionThatReturnsTwice() const; - /// \brief Set the attached subprogram. + /// Set the attached subprogram. /// /// Calls \a setMetadata() with \a LLVMContext::MD_dbg. void setSubprogram(DISubprogram *SP); - /// \brief Get the attached subprogram. + /// Get the attached subprogram. /// /// Calls \a getMetadata() with \a LLVMContext::MD_dbg and casts the result /// to \a DISubprogram. @@ -740,6 +781,12 @@ public: /// Returns true if we should emit debug info for profiling. bool isDebugInfoForProfiling() const; + /// Check if null pointer dereferencing is considered undefined behavior for + /// the function. + /// Return value: false => null pointer dereference is undefined. + /// Return value: true => null pointer dereference is not undefined. + bool nullPointerIsDefined() const; + private: void allocHungoffUselist(); template<int Idx> void setHungoffOperand(Constant *C); @@ -752,6 +799,13 @@ private: void setValueSubclassDataBit(unsigned Bit, bool On); }; +/// Check whether null pointer dereferencing is considered undefined behavior +/// for a given function or an address space. +/// Null pointer access in non-zero address space is not considered undefined. +/// Return value: false => null pointer dereference is undefined. +/// Return value: true => null pointer dereference is not undefined. +bool NullPointerIsDefined(const Function *F, unsigned AS = 0); + template <> struct OperandTraits<Function> : public HungoffOperandTraits<3> {}; diff --git a/contrib/llvm/include/llvm/IR/GlobalObject.h b/contrib/llvm/include/llvm/IR/GlobalObject.h index 278b193567f1..1fd3568100c2 100644 --- a/contrib/llvm/include/llvm/IR/GlobalObject.h +++ b/contrib/llvm/include/llvm/IR/GlobalObject.h @@ -105,6 +105,14 @@ public: /// Check if this has any metadata. bool hasMetadata() const { return hasMetadataHashEntry(); } + /// Check if this has any metadata of the given kind. + bool hasMetadata(unsigned KindID) const { + return getMetadata(KindID) != nullptr; + } + bool hasMetadata(StringRef Kind) const { + return getMetadata(Kind) != nullptr; + } + /// Get the current metadata attachments for the given kind, if any. /// /// These functions require that the function have at most a single attachment @@ -143,7 +151,9 @@ public: getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const; /// Erase all metadata attachments with the given kind. - void eraseMetadata(unsigned KindID); + /// + /// \returns true if any metadata was removed. + bool eraseMetadata(unsigned KindID); /// Copy metadata from Src, adjusting offsets by Offset. void copyMetadata(const GlobalObject *Src, unsigned Offset); diff --git a/contrib/llvm/include/llvm/IR/GlobalValue.h b/contrib/llvm/include/llvm/IR/GlobalValue.h index 1793de7887fc..9d9f4f65a6b5 100644 --- a/contrib/llvm/include/llvm/IR/GlobalValue.h +++ b/contrib/llvm/include/llvm/IR/GlobalValue.h @@ -44,7 +44,7 @@ namespace Intrinsic { class GlobalValue : public Constant { public: - /// @brief An enumeration for the kinds of linkage for global values. + /// An enumeration for the kinds of linkage for global values. enum LinkageTypes { ExternalLinkage = 0,///< Externally visible function AvailableExternallyLinkage, ///< Available for inspection, not emission. @@ -59,14 +59,14 @@ public: CommonLinkage ///< Tentative definitions. }; - /// @brief An enumeration for the kinds of visibility of global values. + /// An enumeration for the kinds of visibility of global values. enum VisibilityTypes { DefaultVisibility = 0, ///< The GV is visible HiddenVisibility, ///< The GV is hidden ProtectedVisibility ///< The GV is protected }; - /// @brief Storage classes of global values for PE targets. + /// Storage classes of global values for PE targets. enum DLLStorageClassTypes { DefaultStorageClass = 0, DLLImportStorageClass = 1, ///< Function to be imported from DLL @@ -77,11 +77,12 @@ protected: GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace) : Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps), - ValueType(Ty), Linkage(Linkage), Visibility(DefaultVisibility), + ValueType(Ty), Visibility(DefaultVisibility), UnnamedAddrVal(unsigned(UnnamedAddr::None)), DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), - HasLLVMReservedName(false), IsDSOLocal(false), - IntID((Intrinsic::ID)0U), Parent(nullptr) { + HasLLVMReservedName(false), IsDSOLocal(false), IntID((Intrinsic::ID)0U), + Parent(nullptr) { + setLinkage(Linkage); setName(Name); } @@ -109,12 +110,12 @@ protected: unsigned IsDSOLocal : 1; private: - friend class Constant; - // Give subclasses access to what otherwise would be wasted padding. // (17 + 4 + 2 + 2 + 2 + 3 + 1 + 1) == 32. unsigned SubClassData : GlobalValueSubClassDataBits; + friend class Constant; + void destroyConstantImpl(); Value *handleOperandChangeImpl(Value *From, Value *To); @@ -142,8 +143,14 @@ private: llvm_unreachable("Fully covered switch above!"); } + void maybeSetDsoLocal() { + if (hasLocalLinkage() || + (!hasDefaultVisibility() && !hasExternalWeakLinkage())) + setDSOLocal(true); + } + protected: - /// \brief The intrinsic ID for this subclass (which must be a Function). + /// The intrinsic ID for this subclass (which must be a Function). /// /// This member is defined by this class, but not used for anything. /// Subclasses can use it to store their intrinsic ID, if they have one. @@ -232,6 +239,7 @@ public: assert((!hasLocalLinkage() || V == DefaultVisibility) && "local linkage requires default visibility"); Visibility = V; + maybeSetDsoLocal(); } /// If the value is "Thread Local", its value isn't shared by the threads. @@ -437,6 +445,7 @@ public: if (isLocalLinkage(LT)) Visibility = DefaultVisibility; Linkage = LT; + maybeSetDsoLocal(); } LinkageTypes getLinkage() const { return LinkageTypes(Linkage); } @@ -563,6 +572,13 @@ public: V->getValueID() == Value::GlobalAliasVal || V->getValueID() == Value::GlobalIFuncVal; } + + /// True if GV can be left out of the object symbol table. This is the case + /// for linkonce_odr values whose address is not significant. While legal, it + /// is not normally profitable to omit them from the .o symbol table. Using + /// this analysis makes sense when the information can be passed down to the + /// linker or we are in LTO. + bool canBeOmittedFromSymbolTable() const; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/IR/GlobalVariable.h b/contrib/llvm/include/llvm/IR/GlobalVariable.h index 34ace6f2b4f4..03b9ec46ebb4 100644 --- a/contrib/llvm/include/llvm/IR/GlobalVariable.h +++ b/contrib/llvm/include/llvm/IR/GlobalVariable.h @@ -68,9 +68,6 @@ public: ~GlobalVariable() { dropAllReferences(); - - // FIXME: needed by operator delete - setGlobalVariableNumOperands(1); } // allocate space for exactly one operand @@ -78,6 +75,16 @@ public: return User::operator new(s, 1); } + // delete space for exactly one operand as created in the corresponding new operator + void operator delete(void *ptr){ + assert(ptr != nullptr && "must not be nullptr"); + User *Obj = static_cast<User *>(ptr); + // Number of operands can be set to 0 after construction and initialization. Make sure + // that number of operands is reset to 1, as this is needed in User::operator delete + Obj->setGlobalVariableNumOperands(1); + User::operator delete(Obj); + } + /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); diff --git a/contrib/llvm/include/llvm/IR/IRBuilder.h b/contrib/llvm/include/llvm/IR/IRBuilder.h index e687ca689d46..70641ba25d2e 100644 --- a/contrib/llvm/include/llvm/IR/IRBuilder.h +++ b/contrib/llvm/include/llvm/IR/IRBuilder.h @@ -1,4 +1,4 @@ -//===---- llvm/IRBuilder.h - Builder for LLVM Instructions ------*- C++ -*-===// +//===- llvm/IRBuilder.h - Builder for LLVM Instructions ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -42,20 +42,19 @@ #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Casting.h" -#include <algorithm> #include <cassert> #include <cstddef> #include <cstdint> #include <functional> +#include <utility> namespace llvm { class APInt; class MDNode; -class Module; class Use; -/// \brief This provides the default implementation of the IRBuilder +/// This provides the default implementation of the IRBuilder /// 'InsertHelper' method that is called whenever an instruction is created by /// IRBuilder and needs to be inserted. /// @@ -86,7 +85,7 @@ protected: } }; -/// \brief Common base class shared among various IRBuilders. +/// Common base class shared among various IRBuilders. class IRBuilderBase { DebugLoc CurDbgLocation; @@ -112,7 +111,7 @@ public: // Builder configuration methods //===--------------------------------------------------------------------===// - /// \brief Clear the insertion point: created instructions will not be + /// Clear the insertion point: created instructions will not be /// inserted into a block. void ClearInsertionPoint() { BB = nullptr; @@ -123,14 +122,14 @@ public: BasicBlock::iterator GetInsertPoint() const { return InsertPt; } LLVMContext &getContext() const { return Context; } - /// \brief This specifies that created instructions should be appended to the + /// This specifies that created instructions should be appended to the /// end of the specified block. void SetInsertPoint(BasicBlock *TheBB) { BB = TheBB; InsertPt = BB->end(); } - /// \brief This specifies that created instructions should be inserted before + /// This specifies that created instructions should be inserted before /// the specified instruction. void SetInsertPoint(Instruction *I) { BB = I->getParent(); @@ -139,7 +138,7 @@ public: SetCurrentDebugLocation(I->getDebugLoc()); } - /// \brief This specifies that created instructions should be inserted at the + /// This specifies that created instructions should be inserted at the /// specified point. void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { BB = TheBB; @@ -148,20 +147,20 @@ public: SetCurrentDebugLocation(IP->getDebugLoc()); } - /// \brief Set location information used by debugging information. + /// Set location information used by debugging information. void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); } - /// \brief Get location information used by debugging information. + /// Get location information used by debugging information. const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } - /// \brief If this builder has a current debug location, set it on the + /// If this builder has a current debug location, set it on the /// specified instruction. void SetInstDebugLocation(Instruction *I) const { if (CurDbgLocation) I->setDebugLoc(CurDbgLocation); } - /// \brief Get the return type of the current function that we're emitting + /// Get the return type of the current function that we're emitting /// into. Type *getCurrentFunctionReturnType() const; @@ -171,33 +170,33 @@ public: BasicBlock::iterator Point; public: - /// \brief Creates a new insertion point which doesn't point to anything. + /// Creates a new insertion point which doesn't point to anything. InsertPoint() = default; - /// \brief Creates a new insertion point at the given location. + /// Creates a new insertion point at the given location. InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint) - : Block(InsertBlock), Point(InsertPoint) {} + : Block(InsertBlock), Point(InsertPoint) {} - /// \brief Returns true if this insert point is set. + /// Returns true if this insert point is set. bool isSet() const { return (Block != nullptr); } BasicBlock *getBlock() const { return Block; } BasicBlock::iterator getPoint() const { return Point; } }; - /// \brief Returns the current insert point. + /// Returns the current insert point. InsertPoint saveIP() const { return InsertPoint(GetInsertBlock(), GetInsertPoint()); } - /// \brief Returns the current insert point, clearing it in the process. + /// Returns the current insert point, clearing it in the process. InsertPoint saveAndClearIP() { InsertPoint IP(GetInsertBlock(), GetInsertPoint()); ClearInsertionPoint(); return IP; } - /// \brief Sets the current insert point to a previously-saved location. + /// Sets the current insert point to a previously-saved location. void restoreIP(InsertPoint IP) { if (IP.isSet()) SetInsertPoint(IP.getBlock(), IP.getPoint()); @@ -205,26 +204,26 @@ public: ClearInsertionPoint(); } - /// \brief Get the floating point math metadata being used. + /// Get the floating point math metadata being used. MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } - /// \brief Get the flags to be applied to created floating point ops + /// Get the flags to be applied to created floating point ops FastMathFlags getFastMathFlags() const { return FMF; } - /// \brief Clear the fast-math flags. + /// Clear the fast-math flags. void clearFastMathFlags() { FMF.clear(); } - /// \brief Set the floating point math metadata to be used. + /// Set the floating point math metadata to be used. void setDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } - /// \brief Set the fast-math flags to be used with generated fp-math operators + /// Set the fast-math flags to be used with generated fp-math operators void setFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } //===--------------------------------------------------------------------===// // RAII helpers. //===--------------------------------------------------------------------===// - // \brief RAII object that stores the current insertion point and restores it + // RAII object that stores the current insertion point and restores it // when the object is destroyed. This includes the debug location. class InsertPointGuard { IRBuilderBase &Builder; @@ -246,7 +245,7 @@ public: } }; - // \brief RAII object that stores the current fast math settings and restores + // RAII object that stores the current fast math settings and restores // them when the object is destroyed. class FastMathFlagGuard { IRBuilderBase &Builder; @@ -270,7 +269,7 @@ public: // Miscellaneous creation methods. //===--------------------------------------------------------------------===// - /// \brief Make a new global variable with initializer type i8* + /// Make a new global variable with initializer type i8* /// /// Make a new global variable with an initializer that has array of i8 type /// filled in with the null terminated string value specified. The new global @@ -279,48 +278,48 @@ public: GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = "", unsigned AddressSpace = 0); - /// \brief Get a constant value representing either true or false. + /// Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { return ConstantInt::get(getInt1Ty(), V); } - /// \brief Get the constant value for i1 true. + /// Get the constant value for i1 true. ConstantInt *getTrue() { return ConstantInt::getTrue(Context); } - /// \brief Get the constant value for i1 false. + /// Get the constant value for i1 false. ConstantInt *getFalse() { return ConstantInt::getFalse(Context); } - /// \brief Get a constant 8-bit value. + /// Get a constant 8-bit value. ConstantInt *getInt8(uint8_t C) { return ConstantInt::get(getInt8Ty(), C); } - /// \brief Get a constant 16-bit value. + /// Get a constant 16-bit value. ConstantInt *getInt16(uint16_t C) { return ConstantInt::get(getInt16Ty(), C); } - /// \brief Get a constant 32-bit value. + /// Get a constant 32-bit value. ConstantInt *getInt32(uint32_t C) { return ConstantInt::get(getInt32Ty(), C); } - /// \brief Get a constant 64-bit value. + /// Get a constant 64-bit value. ConstantInt *getInt64(uint64_t C) { return ConstantInt::get(getInt64Ty(), C); } - /// \brief Get a constant N-bit value, zero extended or truncated from + /// 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. + /// Get a constant integer value. ConstantInt *getInt(const APInt &AI) { return ConstantInt::get(Context, AI); } @@ -329,65 +328,65 @@ public: // Type creation methods //===--------------------------------------------------------------------===// - /// \brief Fetch the type representing a single bit + /// Fetch the type representing a single bit IntegerType *getInt1Ty() { return Type::getInt1Ty(Context); } - /// \brief Fetch the type representing an 8-bit integer. + /// Fetch the type representing an 8-bit integer. IntegerType *getInt8Ty() { return Type::getInt8Ty(Context); } - /// \brief Fetch the type representing a 16-bit integer. + /// Fetch the type representing a 16-bit integer. IntegerType *getInt16Ty() { return Type::getInt16Ty(Context); } - /// \brief Fetch the type representing a 32-bit integer. + /// Fetch the type representing a 32-bit integer. IntegerType *getInt32Ty() { return Type::getInt32Ty(Context); } - /// \brief Fetch the type representing a 64-bit integer. + /// Fetch the type representing a 64-bit integer. IntegerType *getInt64Ty() { return Type::getInt64Ty(Context); } - /// \brief Fetch the type representing a 128-bit integer. + /// Fetch the type representing a 128-bit integer. IntegerType *getInt128Ty() { return Type::getInt128Ty(Context); } - /// \brief Fetch the type representing an N-bit integer. + /// Fetch the type representing an N-bit integer. IntegerType *getIntNTy(unsigned N) { return Type::getIntNTy(Context, N); } - /// \brief Fetch the type representing a 16-bit floating point value. + /// Fetch the type representing a 16-bit floating point value. Type *getHalfTy() { return Type::getHalfTy(Context); } - /// \brief Fetch the type representing a 32-bit floating point value. + /// Fetch the type representing a 32-bit floating point value. Type *getFloatTy() { return Type::getFloatTy(Context); } - /// \brief Fetch the type representing a 64-bit floating point value. + /// Fetch the type representing a 64-bit floating point value. Type *getDoubleTy() { return Type::getDoubleTy(Context); } - /// \brief Fetch the type representing void. + /// Fetch the type representing void. Type *getVoidTy() { return Type::getVoidTy(Context); } - /// \brief Fetch the type representing a pointer to an 8-bit integer value. + /// Fetch the type representing a pointer to an 8-bit integer value. PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { return Type::getInt8PtrTy(Context, AddrSpace); } - /// \brief Fetch the type representing a pointer to an integer value. + /// Fetch the type representing a pointer to an integer value. IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) { return DL.getIntPtrType(Context, AddrSpace); } @@ -396,7 +395,7 @@ public: // Intrinsic creation methods //===--------------------------------------------------------------------===// - /// \brief Create and insert a memset to the specified pointer and the + /// Create and insert a memset to the specified pointer and the /// specified value. /// /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is @@ -415,27 +414,54 @@ public: MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr); - /// \brief Create and insert a memcpy between the specified pointers. + /// Create and insert an element unordered-atomic memset of the region of + /// memory starting at the given pointer to the given value. + /// + /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. + CallInst *CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val, + uint64_t Size, unsigned Align, + uint32_t ElementSize, + MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateElementUnorderedAtomicMemSet(Ptr, Val, getInt64(Size), Align, + ElementSize, TBAATag, ScopeTag, + NoAliasTag); + } + + CallInst *CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val, + Value *Size, unsigned Align, + uint32_t ElementSize, + MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); + + /// Create and insert a memcpy between the specified pointers. /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is /// specified, it will be added to the instruction. Likewise with alias.scope /// and noalias tags. - CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + CallInst *CreateMemCpy(Value *Dst, unsigned DstAlign, Value *Src, + unsigned SrcAlign, uint64_t Size, bool isVolatile = false, MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr) { - return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, - TBAAStructTag, ScopeTag, NoAliasTag); + return CreateMemCpy(Dst, DstAlign, Src, SrcAlign, getInt64(Size), + isVolatile, TBAATag, TBAAStructTag, ScopeTag, + NoAliasTag); } - CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, + CallInst *CreateMemCpy(Value *Dst, unsigned DstAlign, Value *Src, + unsigned SrcAlign, Value *Size, bool isVolatile = false, MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr); - /// \brief Create and insert an element unordered-atomic memcpy between the + /// Create and insert an element unordered-atomic memcpy between the /// specified pointers. /// /// DstAlign/SrcAlign are the alignments of the Dst/Src pointers, respectively. @@ -459,70 +485,95 @@ public: MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr); - /// \brief Create and insert a memmove between the specified + /// Create and insert a memmove between the specified /// pointers. /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is /// specified, it will be added to the instruction. Likewise with alias.scope /// and noalias tags. - CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *ScopeTag = nullptr, + CallInst *CreateMemMove(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, + uint64_t Size, bool isVolatile = false, + MDNode *TBAATag = nullptr, MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr) { - return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, + return CreateMemMove(Dst, DstAlign, Src, SrcAlign, getInt64(Size), isVolatile, TBAATag, ScopeTag, NoAliasTag); } - CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr, + CallInst *CreateMemMove(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, + Value *Size, bool isVolatile = false, MDNode *TBAATag = nullptr, MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr); - /// \brief Create a vector fadd reduction intrinsic of the source vector. + /// \brief Create and insert an element unordered-atomic memmove between the + /// specified pointers. + /// + /// DstAlign/SrcAlign are the alignments of the Dst/Src pointers, + /// respectively. + /// + /// If the pointers aren't i8*, they will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. + CallInst *CreateElementUnorderedAtomicMemMove( + Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, + uint64_t Size, uint32_t ElementSize, MDNode *TBAATag = nullptr, + MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateElementUnorderedAtomicMemMove( + Dst, DstAlign, Src, SrcAlign, getInt64(Size), ElementSize, TBAATag, + TBAAStructTag, ScopeTag, NoAliasTag); + } + + CallInst *CreateElementUnorderedAtomicMemMove( + Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, Value *Size, + uint32_t ElementSize, MDNode *TBAATag = nullptr, + MDNode *TBAAStructTag = nullptr, MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); + + /// Create a vector fadd reduction intrinsic of the source vector. /// The first parameter is a scalar accumulator value for ordered reductions. CallInst *CreateFAddReduce(Value *Acc, Value *Src); - /// \brief Create a vector fmul reduction intrinsic of the source vector. + /// Create a vector fmul reduction intrinsic of the source vector. /// The first parameter is a scalar accumulator value for ordered reductions. CallInst *CreateFMulReduce(Value *Acc, Value *Src); - /// \brief Create a vector int add reduction intrinsic of the source vector. + /// Create a vector int add reduction intrinsic of the source vector. CallInst *CreateAddReduce(Value *Src); - /// \brief Create a vector int mul reduction intrinsic of the source vector. + /// Create a vector int mul reduction intrinsic of the source vector. CallInst *CreateMulReduce(Value *Src); - /// \brief Create a vector int AND reduction intrinsic of the source vector. + /// Create a vector int AND reduction intrinsic of the source vector. CallInst *CreateAndReduce(Value *Src); - /// \brief Create a vector int OR reduction intrinsic of the source vector. + /// Create a vector int OR reduction intrinsic of the source vector. CallInst *CreateOrReduce(Value *Src); - /// \brief Create a vector int XOR reduction intrinsic of the source vector. + /// Create a vector int XOR reduction intrinsic of the source vector. CallInst *CreateXorReduce(Value *Src); - /// \brief Create a vector integer max reduction intrinsic of the source + /// Create a vector integer max reduction intrinsic of the source /// vector. CallInst *CreateIntMaxReduce(Value *Src, bool IsSigned = false); - /// \brief Create a vector integer min reduction intrinsic of the source + /// Create a vector integer min reduction intrinsic of the source /// vector. CallInst *CreateIntMinReduce(Value *Src, bool IsSigned = false); - /// \brief Create a vector float max reduction intrinsic of the source + /// Create a vector float max reduction intrinsic of the source /// vector. CallInst *CreateFPMaxReduce(Value *Src, bool NoNaN = false); - /// \brief Create a vector float min reduction intrinsic of the source + /// Create a vector float min reduction intrinsic of the source /// vector. CallInst *CreateFPMinReduce(Value *Src, bool NoNaN = false); - /// \brief Create a lifetime.start intrinsic. + /// Create a lifetime.start intrinsic. /// /// If the pointer isn't i8* it will be converted. CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = nullptr); - /// \brief Create a lifetime.end intrinsic. + /// Create a lifetime.end intrinsic. /// /// If the pointer isn't i8* it will be converted. CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr); @@ -532,29 +583,29 @@ public: /// If the pointer isn't i8* it will be converted. CallInst *CreateInvariantStart(Value *Ptr, ConstantInt *Size = nullptr); - /// \brief Create a call to Masked Load intrinsic + /// Create a call to Masked Load intrinsic CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask, Value *PassThru = nullptr, const Twine &Name = ""); - /// \brief Create a call to Masked Store intrinsic + /// Create a call to Masked Store intrinsic CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align, Value *Mask); - /// \brief Create a call to Masked Gather intrinsic + /// Create a call to Masked Gather intrinsic CallInst *CreateMaskedGather(Value *Ptrs, unsigned Align, Value *Mask = nullptr, Value *PassThru = nullptr, const Twine& Name = ""); - /// \brief Create a call to Masked Scatter intrinsic + /// Create a call to Masked Scatter intrinsic CallInst *CreateMaskedScatter(Value *Val, Value *Ptrs, unsigned Align, Value *Mask = nullptr); - /// \brief Create an assume intrinsic call that allows the optimizer to + /// Create an assume intrinsic call that allows the optimizer to /// assume that the provided condition will be true. CallInst *CreateAssumption(Value *Cond); - /// \brief Create a call to the experimental.gc.statepoint intrinsic to + /// Create a call to the experimental.gc.statepoint intrinsic to /// start a new statepoint sequence. CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, Value *ActualCallee, @@ -563,7 +614,7 @@ public: ArrayRef<Value *> GCArgs, const Twine &Name = ""); - /// \brief Create a call to the experimental.gc.statepoint intrinsic to + /// Create a call to the experimental.gc.statepoint intrinsic to /// start a new statepoint sequence. CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, Value *ActualCallee, uint32_t Flags, @@ -573,16 +624,16 @@ public: ArrayRef<Value *> GCArgs, const Twine &Name = ""); - // \brief Conveninence function for the common case when CallArgs are filled - // in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be - // .get()'ed to get the Value pointer. + /// Conveninence function for the common case when CallArgs are filled + /// in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be + /// .get()'ed to get the Value pointer. CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, Value *ActualCallee, ArrayRef<Use> CallArgs, ArrayRef<Value *> DeoptArgs, ArrayRef<Value *> GCArgs, const Twine &Name = ""); - /// brief Create an invoke to the experimental.gc.statepoint intrinsic to + /// Create an invoke to the experimental.gc.statepoint intrinsic to /// start a new statepoint sequence. InvokeInst * CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, @@ -591,7 +642,7 @@ public: ArrayRef<Value *> DeoptArgs, ArrayRef<Value *> GCArgs, const Twine &Name = ""); - /// brief Create an invoke to the experimental.gc.statepoint intrinsic to + /// Create an invoke to the experimental.gc.statepoint intrinsic to /// start a new statepoint sequence. InvokeInst *CreateGCStatepointInvoke( uint64_t ID, uint32_t NumPatchBytes, Value *ActualInvokee, @@ -610,13 +661,13 @@ public: ArrayRef<Value *> DeoptArgs, ArrayRef<Value *> GCArgs, const Twine &Name = ""); - /// \brief Create a call to the experimental.gc.result intrinsic to extract + /// Create a call to the experimental.gc.result intrinsic to extract /// the result from a call wrapped in a statepoint. CallInst *CreateGCResult(Instruction *Statepoint, Type *ResultType, const Twine &Name = ""); - /// \brief Create a call to the experimental.gc.relocate intrinsics to + /// Create a call to the experimental.gc.relocate intrinsics to /// project the relocated value of one pointer from the statepoint. CallInst *CreateGCRelocate(Instruction *Statepoint, int BaseOffset, @@ -630,6 +681,18 @@ public: Value *LHS, Value *RHS, const Twine &Name = ""); + /// Create a call to intrinsic \p ID with no operands. + CallInst *CreateIntrinsic(Intrinsic::ID ID, + Instruction *FMFSource = nullptr, + const Twine &Name = ""); + + /// Create a call to intrinsic \p ID with 1 or more operands assuming the + /// intrinsic and all operands have the same type. If \p FMFSource is + /// provided, copy fast-math-flags from that instruction to the intrinsic. + CallInst *CreateIntrinsic(Intrinsic::ID ID, ArrayRef<Value *> Args, + Instruction *FMFSource = nullptr, + const Twine &Name = ""); + /// Create call to the minnum intrinsic. CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, Name); @@ -637,11 +700,11 @@ public: /// Create call to the maxnum intrinsic. CallInst *CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, Name); + return CreateBinaryIntrinsic(Intrinsic::maxnum, LHS, RHS, Name); } private: - /// \brief Create a call to a masked intrinsic with given Id. + /// Create a call to a masked intrinsic with given Id. CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef<Value *> Ops, ArrayRef<Type *> OverloadedTypes, const Twine &Name = ""); @@ -649,7 +712,7 @@ private: Value *getCastedInt8PtrValue(Value *Ptr); }; -/// \brief This provides a uniform API for creating instructions and inserting +/// This provides a uniform API for creating instructions and inserting /// them into a basic block: either at the end of a BasicBlock, or at a specific /// iterator location in a block. /// @@ -677,7 +740,7 @@ public: explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr, ArrayRef<OperandBundleDef> OpBundles = None) - : IRBuilderBase(C, FPMathTag, OpBundles), Folder() {} + : IRBuilderBase(C, FPMathTag, OpBundles) {} explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = nullptr, ArrayRef<OperandBundleDef> OpBundles = None) @@ -687,13 +750,13 @@ public: explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr, ArrayRef<OperandBundleDef> OpBundles = None) - : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles), Folder() { + : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles) { SetInsertPoint(TheBB); } explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr, ArrayRef<OperandBundleDef> OpBundles = None) - : IRBuilderBase(IP->getContext(), FPMathTag, OpBundles), Folder() { + : IRBuilderBase(IP->getContext(), FPMathTag, OpBundles) { SetInsertPoint(IP); } @@ -707,14 +770,14 @@ public: IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = nullptr, ArrayRef<OperandBundleDef> OpBundles = None) - : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles), Folder() { + : IRBuilderBase(TheBB->getContext(), FPMathTag, OpBundles) { SetInsertPoint(TheBB, IP); } - /// \brief Get the constant folder being used. + /// Get the constant folder being used. const T &getFolder() { return Folder; } - /// \brief Insert and return the specified instruction. + /// Insert and return the specified instruction. template<typename InstTy> InstTy *Insert(InstTy *I, const Twine &Name = "") const { this->InsertHelper(I, Name, BB, InsertPt); @@ -722,7 +785,7 @@ public: return I; } - /// \brief No-op overload to handle constants. + /// No-op overload to handle constants. Constant *Insert(Constant *C, const Twine& = "") const { return C; } @@ -732,7 +795,7 @@ public: //===--------------------------------------------------------------------===// private: - /// \brief Helper to add branch weight and unpredictable metadata onto an + /// Helper to add branch weight and unpredictable metadata onto an /// instruction. /// \returns The annotated instruction. template <typename InstTy> @@ -745,17 +808,17 @@ private: } public: - /// \brief Create a 'ret void' instruction. + /// Create a 'ret void' instruction. ReturnInst *CreateRetVoid() { return Insert(ReturnInst::Create(Context)); } - /// \brief Create a 'ret <val>' instruction. + /// Create a 'ret <val>' instruction. ReturnInst *CreateRet(Value *V) { return Insert(ReturnInst::Create(Context, V)); } - /// \brief Create a sequence of N insertvalue instructions, + /// Create a sequence of N insertvalue instructions, /// with one Value from the retVals array each, that build a aggregate /// return value one value at a time, and a ret instruction to return /// the resulting aggregate value. @@ -769,12 +832,12 @@ public: return Insert(ReturnInst::Create(Context, V)); } - /// \brief Create an unconditional 'br label X' instruction. + /// Create an unconditional 'br label X' instruction. BranchInst *CreateBr(BasicBlock *Dest) { return Insert(BranchInst::Create(Dest)); } - /// \brief Create a conditional 'br Cond, TrueDest, FalseDest' + /// Create a conditional 'br Cond, TrueDest, FalseDest' /// instruction. BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights = nullptr, @@ -783,7 +846,7 @@ public: BranchWeights, Unpredictable)); } - /// \brief Create a conditional 'br Cond, TrueDest, FalseDest' + /// Create a conditional 'br Cond, TrueDest, FalseDest' /// instruction. Copy branch meta data if available. BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, Instruction *MDSrc) { @@ -796,7 +859,7 @@ public: return Insert(Br); } - /// \brief Create a switch instruction with the specified value, default dest, + /// Create a switch instruction with the specified value, default dest, /// and with a hint for the number of cases that will be added (for efficient /// allocation). SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10, @@ -806,14 +869,14 @@ public: BranchWeights, Unpredictable)); } - /// \brief Create an indirect branch instruction with the specified address + /// Create an indirect branch instruction with the specified address /// operand, with an optional hint for the number of destinations that will be /// added (for efficient allocation). IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) { return Insert(IndirectBrInst::Create(Addr, NumDests)); } - /// \brief Create an invoke instruction. + /// Create an invoke instruction. InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef<Value *> Args = None, @@ -878,150 +941,128 @@ private: return BO; } - Instruction *AddFPMathAttributes(Instruction *I, - MDNode *FPMathTag, - FastMathFlags FMF) const { - if (!FPMathTag) - FPMathTag = DefaultFPMathTag; - if (FPMathTag) - I->setMetadata(LLVMContext::MD_fpmath, FPMathTag); + Instruction *setFPAttrs(Instruction *I, MDNode *FPMD, + FastMathFlags FMF) const { + if (!FPMD) + FPMD = DefaultFPMathTag; + if (FPMD) + I->setMetadata(LLVMContext::MD_fpmath, FPMD); I->setFastMathFlags(FMF); return I; } + Value *foldConstant(Instruction::BinaryOps Opc, Value *L, + Value *R, const Twine &Name = nullptr) const { + auto *LC = dyn_cast<Constant>(L); + auto *RC = dyn_cast<Constant>(R); + return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr; + } + public: Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) + if (auto *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateAdd(LC, RC, HasNUW, HasNSW), Name); return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, HasNUW, HasNSW); } + Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateAdd(LHS, RHS, Name, false, true); } + Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateAdd(LHS, RHS, Name, true, false); } - Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFAdd(LC, RC), Name); - return Insert(AddFPMathAttributes(BinaryOperator::CreateFAdd(LHS, RHS), - FPMathTag, FMF), Name); - } + Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) + if (auto *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateSub(LC, RC, HasNUW, HasNSW), Name); return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, HasNUW, HasNSW); } + Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateSub(LHS, RHS, Name, false, true); } + Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateSub(LHS, RHS, Name, true, false); } - Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFSub(LC, RC), Name); - return Insert(AddFPMathAttributes(BinaryOperator::CreateFSub(LHS, RHS), - FPMathTag, FMF), Name); - } + Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) + if (auto *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateMul(LC, RC, HasNUW, HasNSW), Name); return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, HasNUW, HasNSW); } + Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateMul(LHS, RHS, Name, false, true); } + Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateMul(LHS, RHS, Name, true, false); } - Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFMul(LC, RC), Name); - return Insert(AddFPMathAttributes(BinaryOperator::CreateFMul(LHS, RHS), - FPMathTag, FMF), Name); - } + Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "", bool isExact = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) + if (auto *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateUDiv(LC, RC, isExact), Name); if (!isExact) return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name); } + Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateUDiv(LHS, RHS, Name, true); } + Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "", bool isExact = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) + if (auto *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateSDiv(LC, RC, isExact), Name); if (!isExact) return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name); } + Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateSDiv(LHS, RHS, Name, true); } - Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFDiv(LC, RC), Name); - return Insert(AddFPMathAttributes(BinaryOperator::CreateFDiv(LHS, RHS), - FPMathTag, FMF), Name); - } + Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateURem(LC, RC), Name); + if (Value *V = foldConstant(Instruction::URem, LHS, RHS, Name)) return V; return Insert(BinaryOperator::CreateURem(LHS, RHS), Name); } + Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateSRem(LC, RC), Name); + if (Value *V = foldConstant(Instruction::SRem, LHS, RHS, Name)) return V; return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); } - Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFRem(LC, RC), Name); - return Insert(AddFPMathAttributes(BinaryOperator::CreateFRem(LHS, RHS), - FPMathTag, FMF), Name); - } Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) + if (auto *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateShl(LC, RC, HasNUW, HasNSW), Name); return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name, HasNUW, HasNSW); } + Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, HasNUW, HasNSW); } + Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, @@ -1030,17 +1071,19 @@ public: Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "", bool isExact = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) + if (auto *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateLShr(LC, RC, isExact), Name); if (!isExact) return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name); } + Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "", bool isExact = false) { return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } + Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "", bool isExact = false) { return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); @@ -1048,103 +1091,196 @@ public: Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "", bool isExact = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) + if (auto *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateAShr(LC, RC, isExact), Name); if (!isExact) return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name); } + Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "", bool isExact = false) { return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } + Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "", bool isExact = false) { return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *RC = dyn_cast<Constant>(RHS)) { + if (auto *RC = dyn_cast<Constant>(RHS)) { if (isa<ConstantInt>(RC) && cast<ConstantInt>(RC)->isMinusOne()) return LHS; // LHS & -1 -> LHS - if (Constant *LC = dyn_cast<Constant>(LHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) return Insert(Folder.CreateAnd(LC, RC), Name); } return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name); } + Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") { return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } + Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") { return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *RC = dyn_cast<Constant>(RHS)) { + if (auto *RC = dyn_cast<Constant>(RHS)) { if (RC->isNullValue()) return LHS; // LHS | 0 -> LHS - if (Constant *LC = dyn_cast<Constant>(LHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) return Insert(Folder.CreateOr(LC, RC), Name); } return Insert(BinaryOperator::CreateOr(LHS, RHS), Name); } + Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") { return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } + Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") { return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateXor(LC, RC), Name); + if (Value *V = foldConstant(Instruction::Xor, LHS, RHS, Name)) return V; return Insert(BinaryOperator::CreateXor(LHS, RHS), Name); } + Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") { return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } + Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") { return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } + Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "", + MDNode *FPMD = nullptr) { + if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V; + Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF); + return Insert(I, Name); + } + + /// Copy fast-math-flags from an instruction rather than using the builder's + /// default FMF. + Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource, + const Twine &Name = "") { + if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V; + Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr, + FMFSource->getFastMathFlags()); + return Insert(I, Name); + } + + Value *CreateFSub(Value *L, Value *R, const Twine &Name = "", + MDNode *FPMD = nullptr) { + if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; + Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF); + return Insert(I, Name); + } + + /// Copy fast-math-flags from an instruction rather than using the builder's + /// default FMF. + Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource, + const Twine &Name = "") { + if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; + Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr, + FMFSource->getFastMathFlags()); + return Insert(I, Name); + } + + Value *CreateFMul(Value *L, Value *R, const Twine &Name = "", + MDNode *FPMD = nullptr) { + if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; + Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF); + return Insert(I, Name); + } + + /// Copy fast-math-flags from an instruction rather than using the builder's + /// default FMF. + Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource, + const Twine &Name = "") { + if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; + Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr, + FMFSource->getFastMathFlags()); + return Insert(I, Name); + } + + Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "", + MDNode *FPMD = nullptr) { + if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; + Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF); + return Insert(I, Name); + } + + /// Copy fast-math-flags from an instruction rather than using the builder's + /// default FMF. + Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource, + const Twine &Name = "") { + if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; + Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr, + FMFSource->getFastMathFlags()); + return Insert(I, Name); + } + + Value *CreateFRem(Value *L, Value *R, const Twine &Name = "", + MDNode *FPMD = nullptr) { + if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; + Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF); + return Insert(I, Name); + } + + /// Copy fast-math-flags from an instruction rather than using the builder's + /// default FMF. + Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource, + const Twine &Name = "") { + if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; + Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr, + FMFSource->getFastMathFlags()); + return Insert(I, Name); + } + Value *CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateBinOp(Opc, LC, RC), Name); + if (Value *V = foldConstant(Opc, LHS, RHS, Name)) return V; Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS); if (isa<FPMathOperator>(BinOp)) - BinOp = AddFPMathAttributes(BinOp, FPMathTag, FMF); + BinOp = setFPAttrs(BinOp, FPMathTag, FMF); return Insert(BinOp, Name); } Value *CreateNeg(Value *V, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { - if (Constant *VC = dyn_cast<Constant>(V)) + if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name); BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name); if (HasNUW) BO->setHasNoUnsignedWrap(); if (HasNSW) BO->setHasNoSignedWrap(); return BO; } + Value *CreateNSWNeg(Value *V, const Twine &Name = "") { return CreateNeg(V, Name, false, true); } + Value *CreateNUWNeg(Value *V, const Twine &Name = "") { return CreateNeg(V, Name, true, false); } + Value *CreateFNeg(Value *V, const Twine &Name = "", MDNode *FPMathTag = nullptr) { - if (Constant *VC = dyn_cast<Constant>(V)) + if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateFNeg(VC), Name); - return Insert(AddFPMathAttributes(BinaryOperator::CreateFNeg(V), - FPMathTag, FMF), Name); + return Insert(setFPAttrs(BinaryOperator::CreateFNeg(V), FPMathTag, FMF), + Name); } + Value *CreateNot(Value *V, const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(V)) + if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateNot(VC), Name); return Insert(BinaryOperator::CreateNot(V), Name); } @@ -1163,26 +1299,32 @@ public: const DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); return Insert(new AllocaInst(Ty, DL.getAllocaAddrSpace(), ArraySize), Name); } - // \brief Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of - // converting the string to 'bool' for the isVolatile parameter. + + /// Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of + /// converting the string to 'bool' for the isVolatile parameter. LoadInst *CreateLoad(Value *Ptr, const char *Name) { return Insert(new LoadInst(Ptr), Name); } + LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") { return Insert(new LoadInst(Ptr), Name); } + LoadInst *CreateLoad(Type *Ty, Value *Ptr, const Twine &Name = "") { return Insert(new LoadInst(Ty, Ptr), Name); } + LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") { return Insert(new LoadInst(Ptr, nullptr, isVolatile), Name); } + StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { return Insert(new StoreInst(Val, Ptr, isVolatile)); } - // \brief Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")' - // correctly, instead of converting the string to 'bool' for the isVolatile - // parameter. + + /// Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")' + /// correctly, instead of converting the string to 'bool' for the isVolatile + /// parameter. LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, const char *Name) { LoadInst *LI = CreateLoad(Ptr, Name); LI->setAlignment(Align); @@ -1200,17 +1342,20 @@ public: LI->setAlignment(Align); return LI; } + StoreInst *CreateAlignedStore(Value *Val, Value *Ptr, unsigned Align, bool isVolatile = false) { StoreInst *SI = CreateStore(Val, Ptr, isVolatile); SI->setAlignment(Align); return SI; } + FenceInst *CreateFence(AtomicOrdering Ordering, SyncScope::ID SSID = SyncScope::System, const Twine &Name = "") { return Insert(new FenceInst(Context, Ordering, SSID), Name); } + AtomicCmpXchgInst * CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, AtomicOrdering SuccessOrdering, @@ -1219,18 +1364,21 @@ public: return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering, FailureOrdering, SSID)); } + AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, AtomicOrdering Ordering, SyncScope::ID SSID = SyncScope::System) { return Insert(new AtomicRMWInst(Op, Ptr, Val, Ordering, SSID)); } + Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { return CreateGEP(nullptr, Ptr, IdxList, Name); } + Value *CreateGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { - if (Constant *PC = dyn_cast<Constant>(Ptr)) { + if (auto *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. size_t i, e; for (i = 0, e = IdxList.size(); i != e; ++i) @@ -1241,13 +1389,15 @@ public: } return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name); } + Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { return CreateInBoundsGEP(nullptr, Ptr, IdxList, Name); } + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { - if (Constant *PC = dyn_cast<Constant>(Ptr)) { + if (auto *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. size_t i, e; for (i = 0, e = IdxList.size(); i != e; ++i) @@ -1259,43 +1409,50 @@ public: } return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name); } + Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { return CreateGEP(nullptr, Ptr, Idx, Name); } + Value *CreateGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") { - if (Constant *PC = dyn_cast<Constant>(Ptr)) - if (Constant *IC = dyn_cast<Constant>(Idx)) + if (auto *PC = dyn_cast<Constant>(Ptr)) + if (auto *IC = dyn_cast<Constant>(Idx)) return Insert(Folder.CreateGetElementPtr(Ty, PC, IC), Name); return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") { - if (Constant *PC = dyn_cast<Constant>(Ptr)) - if (Constant *IC = dyn_cast<Constant>(Idx)) + if (auto *PC = dyn_cast<Constant>(Ptr)) + if (auto *IC = dyn_cast<Constant>(Idx)) return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IC), Name); return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } + Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { return CreateConstGEP1_32(nullptr, Ptr, Idx0, Name); } + Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); - if (Constant *PC = dyn_cast<Constant>(Ptr)) + if (auto *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateGetElementPtr(Ty, PC, Idx), Name); return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } + Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); - if (Constant *PC = dyn_cast<Constant>(Ptr)) + if (auto *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idx), Name); return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } + Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name = "") { Value *Idxs[] = { @@ -1303,11 +1460,12 @@ public: ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; - if (Constant *PC = dyn_cast<Constant>(Ptr)) + if (auto *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateGetElementPtr(Ty, PC, Idxs), Name); return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name); } + Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name = "") { Value *Idxs[] = { @@ -1315,28 +1473,31 @@ public: ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; - if (Constant *PC = dyn_cast<Constant>(Ptr)) + if (auto *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idxs), Name); return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name); } + Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); - if (Constant *PC = dyn_cast<Constant>(Ptr)) + if (auto *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idx), Name); return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); } + Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); - if (Constant *PC = dyn_cast<Constant>(Ptr)) + if (auto *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idx), Name); return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); } + Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { Value *Idxs[] = { @@ -1344,11 +1505,12 @@ public: ConstantInt::get(Type::getInt64Ty(Context), Idx1) }; - if (Constant *PC = dyn_cast<Constant>(Ptr)) + if (auto *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idxs), Name); return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name); } + Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { Value *Idxs[] = { @@ -1356,25 +1518,31 @@ public: ConstantInt::get(Type::getInt64Ty(Context), Idx1) }; - if (Constant *PC = dyn_cast<Constant>(Ptr)) + if (auto *PC = dyn_cast<Constant>(Ptr)) return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idxs), Name); return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name); } + Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name = "") { return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name); } - /// \brief Same as CreateGlobalString, but return a pointer with "i8*" type + Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { + return CreateConstInBoundsGEP2_32(nullptr, Ptr, 0, Idx, Name); + } + + /// Same as CreateGlobalString, but return a pointer with "i8*" type /// instead of a pointer to array of i8. - Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "", - unsigned AddressSpace = 0) { - GlobalVariable *gv = CreateGlobalString(Str, Name, AddressSpace); - Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); - Value *Args[] = { zero, zero }; - return CreateInBoundsGEP(gv->getValueType(), gv, Args, Name); + Constant *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "", + unsigned AddressSpace = 0) { + GlobalVariable *GV = CreateGlobalString(Str, Name, AddressSpace); + Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + Constant *Indices[] = {Zero, Zero}; + return ConstantExpr::getInBoundsGetElementPtr(GV->getValueType(), GV, + Indices); } //===--------------------------------------------------------------------===// @@ -1384,13 +1552,16 @@ public: Value *CreateTrunc(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::Trunc, V, DestTy, Name); } + Value *CreateZExt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::ZExt, V, DestTy, Name); } + Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::SExt, V, DestTy, Name); } - /// \brief Create a ZExt or Trunc from the integer value V to DestTy. Return + + /// Create a ZExt or Trunc from the integer value V to DestTy. Return /// the value untouched if the type of V is already DestTy. Value *CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name = "") { @@ -1404,7 +1575,8 @@ public: return CreateTrunc(V, DestTy, Name); return V; } - /// \brief Create a SExt or Trunc from the integer value V to DestTy. Return + + /// Create a SExt or Trunc from the integer value V to DestTy. Return /// the value untouched if the type of V is already DestTy. Value *CreateSExtOrTrunc(Value *V, Type *DestTy, const Twine &Name = "") { @@ -1418,78 +1590,93 @@ public: return CreateTrunc(V, DestTy, Name); return V; } + Value *CreateFPToUI(Value *V, Type *DestTy, const Twine &Name = ""){ return CreateCast(Instruction::FPToUI, V, DestTy, Name); } + Value *CreateFPToSI(Value *V, Type *DestTy, const Twine &Name = ""){ return CreateCast(Instruction::FPToSI, V, DestTy, Name); } + Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){ return CreateCast(Instruction::UIToFP, V, DestTy, Name); } + Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){ return CreateCast(Instruction::SIToFP, V, DestTy, Name); } + Value *CreateFPTrunc(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::FPTrunc, V, DestTy, Name); } + Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::FPExt, V, DestTy, Name); } + Value *CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::PtrToInt, V, DestTy, Name); } + Value *CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::IntToPtr, V, DestTy, Name); } + Value *CreateBitCast(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::BitCast, V, DestTy, Name); } + Value *CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name); } + Value *CreateZExtOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; - if (Constant *VC = dyn_cast<Constant>(V)) + if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name); } + Value *CreateSExtOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; - if (Constant *VC = dyn_cast<Constant>(V)) + if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name); } + Value *CreateTruncOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; - if (Constant *VC = dyn_cast<Constant>(V)) + if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name); } + Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; - if (Constant *VC = dyn_cast<Constant>(V)) + if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateCast(Op, VC, DestTy), Name); return Insert(CastInst::Create(Op, V, DestTy), Name); } + Value *CreatePointerCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; - if (Constant *VC = dyn_cast<Constant>(V)) + if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreatePointerCast(VC, DestTy), Name); return Insert(CastInst::CreatePointerCast(V, DestTy), Name); } @@ -1499,7 +1686,7 @@ public: if (V->getType() == DestTy) return V; - if (Constant *VC = dyn_cast<Constant>(V)) { + if (auto *VC = dyn_cast<Constant>(V)) { return Insert(Folder.CreatePointerBitCastOrAddrSpaceCast(VC, DestTy), Name); } @@ -1512,7 +1699,7 @@ public: const Twine &Name = "") { if (V->getType() == DestTy) return V; - if (Constant *VC = dyn_cast<Constant>(V)) + if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } @@ -1529,16 +1716,15 @@ public: return CreateBitCast(V, DestTy, Name); } -public: Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) return V; - if (Constant *VC = dyn_cast<Constant>(V)) + if (auto *VC = dyn_cast<Constant>(V)) return Insert(Folder.CreateFPCast(VC, DestTy), Name); return Insert(CastInst::CreateFPCast(V, DestTy), Name); } - // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a + // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a // compile time error, instead of converting the string to bool for the // isSigned parameter. Value *CreateIntCast(Value *, Type *, const char *) = delete; @@ -1550,30 +1736,39 @@ public: Value *CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateICmp(ICmpInst::ICMP_EQ, LHS, RHS, Name); } + Value *CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateICmp(ICmpInst::ICMP_NE, LHS, RHS, Name); } + Value *CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateICmp(ICmpInst::ICMP_UGT, LHS, RHS, Name); } + Value *CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateICmp(ICmpInst::ICMP_UGE, LHS, RHS, Name); } + Value *CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateICmp(ICmpInst::ICMP_ULT, LHS, RHS, Name); } + Value *CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateICmp(ICmpInst::ICMP_ULE, LHS, RHS, Name); } + Value *CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateICmp(ICmpInst::ICMP_SGT, LHS, RHS, Name); } + Value *CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateICmp(ICmpInst::ICMP_SGE, LHS, RHS, Name); } + Value *CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateICmp(ICmpInst::ICMP_SLT, LHS, RHS, Name); } + Value *CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name); } @@ -1582,54 +1777,67 @@ public: MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name, FPMathTag); } + Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name, FPMathTag); @@ -1637,18 +1845,18 @@ public: Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) + if (auto *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateICmp(P, LC, RC), Name); return Insert(new ICmpInst(P, LHS, RHS), Name); } + Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name = "", MDNode *FPMathTag = nullptr) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) + if (auto *LC = dyn_cast<Constant>(LHS)) + if (auto *RC = dyn_cast<Constant>(RHS)) return Insert(Folder.CreateFCmp(P, LC, RC), Name); - return Insert(AddFPMathAttributes(new FCmpInst(P, LHS, RHS), - FPMathTag, FMF), Name); + return Insert(setFPAttrs(new FCmpInst(P, LHS, RHS), FPMathTag, FMF), Name); } //===--------------------------------------------------------------------===// @@ -1662,8 +1870,8 @@ public: CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args = None, const Twine &Name = "", MDNode *FPMathTag = nullptr) { - PointerType *PTy = cast<PointerType>(Callee->getType()); - FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); + auto *PTy = cast<PointerType>(Callee->getType()); + auto *FTy = cast<FunctionType>(PTy->getElementType()); return CreateCall(FTy, Callee, Args, Name, FPMathTag); } @@ -1672,7 +1880,7 @@ public: MDNode *FPMathTag = nullptr) { CallInst *CI = CallInst::Create(FTy, Callee, Args, DefaultOperandBundles); if (isa<FPMathOperator>(CI)) - CI = cast<CallInst>(AddFPMathAttributes(CI, FPMathTag, FMF)); + CI = cast<CallInst>(setFPAttrs(CI, FPMathTag, FMF)); return Insert(CI, Name); } @@ -1681,7 +1889,7 @@ public: const Twine &Name = "", MDNode *FPMathTag = nullptr) { CallInst *CI = CallInst::Create(Callee, Args, OpBundles); if (isa<FPMathOperator>(CI)) - CI = cast<CallInst>(AddFPMathAttributes(CI, FPMathTag, FMF)); + CI = cast<CallInst>(setFPAttrs(CI, FPMathTag, FMF)); return Insert(CI, Name); } @@ -1692,9 +1900,9 @@ public: Value *CreateSelect(Value *C, Value *True, Value *False, const Twine &Name = "", Instruction *MDFrom = nullptr) { - if (Constant *CC = dyn_cast<Constant>(C)) - if (Constant *TC = dyn_cast<Constant>(True)) - if (Constant *FC = dyn_cast<Constant>(False)) + if (auto *CC = dyn_cast<Constant>(C)) + if (auto *TC = dyn_cast<Constant>(True)) + if (auto *FC = dyn_cast<Constant>(False)) return Insert(Folder.CreateSelect(CC, TC, FC), Name); SelectInst *Sel = SelectInst::Create(C, True, False); @@ -1712,8 +1920,8 @@ public: Value *CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(Vec)) - if (Constant *IC = dyn_cast<Constant>(Idx)) + if (auto *VC = dyn_cast<Constant>(Vec)) + if (auto *IC = dyn_cast<Constant>(Idx)) return Insert(Folder.CreateExtractElement(VC, IC), Name); return Insert(ExtractElementInst::Create(Vec, Idx), Name); } @@ -1725,9 +1933,9 @@ public: Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(Vec)) - if (Constant *NC = dyn_cast<Constant>(NewElt)) - if (Constant *IC = dyn_cast<Constant>(Idx)) + if (auto *VC = dyn_cast<Constant>(Vec)) + if (auto *NC = dyn_cast<Constant>(NewElt)) + if (auto *IC = dyn_cast<Constant>(Idx)) return Insert(Folder.CreateInsertElement(VC, NC, IC), Name); return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); } @@ -1739,9 +1947,9 @@ public: Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name = "") { - if (Constant *V1C = dyn_cast<Constant>(V1)) - if (Constant *V2C = dyn_cast<Constant>(V2)) - if (Constant *MC = dyn_cast<Constant>(Mask)) + if (auto *V1C = dyn_cast<Constant>(V1)) + if (auto *V2C = dyn_cast<Constant>(V2)) + if (auto *MC = dyn_cast<Constant>(Mask)) return Insert(Folder.CreateShuffleVector(V1C, V2C, MC), Name); return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); } @@ -1755,7 +1963,7 @@ public: Value *CreateExtractValue(Value *Agg, ArrayRef<unsigned> Idxs, const Twine &Name = "") { - if (Constant *AggC = dyn_cast<Constant>(Agg)) + if (auto *AggC = dyn_cast<Constant>(Agg)) return Insert(Folder.CreateExtractValue(AggC, Idxs), Name); return Insert(ExtractValueInst::Create(Agg, Idxs), Name); } @@ -1763,8 +1971,8 @@ public: Value *CreateInsertValue(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, const Twine &Name = "") { - if (Constant *AggC = dyn_cast<Constant>(Agg)) - if (Constant *ValC = dyn_cast<Constant>(Val)) + if (auto *AggC = dyn_cast<Constant>(Agg)) + if (auto *ValC = dyn_cast<Constant>(Val)) return Insert(Folder.CreateInsertValue(AggC, ValC, Idxs), Name); return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name); } @@ -1778,19 +1986,19 @@ public: // Utility creation methods //===--------------------------------------------------------------------===// - /// \brief Return an i1 value testing if \p Arg is null. + /// Return an i1 value testing if \p Arg is null. Value *CreateIsNull(Value *Arg, const Twine &Name = "") { return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()), Name); } - /// \brief Return an i1 value testing if \p Arg is not null. + /// Return an i1 value testing if \p Arg is not null. Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") { return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()), Name); } - /// \brief Return the i64 difference between two pointer values, dividing out + /// Return the i64 difference between two pointer values, dividing out /// the size of the pointed-to objects. /// /// This is intended to implement C-style pointer subtraction. As such, the @@ -1799,7 +2007,7 @@ public: Value *CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name = "") { assert(LHS->getType() == RHS->getType() && "Pointer subtraction operand types must match!"); - PointerType *ArgType = cast<PointerType>(LHS->getType()); + auto *ArgType = cast<PointerType>(LHS->getType()); Value *LHS_int = CreatePtrToInt(LHS, Type::getInt64Ty(Context)); Value *RHS_int = CreatePtrToInt(RHS, Type::getInt64Ty(Context)); Value *Difference = CreateSub(LHS_int, RHS_int); @@ -1808,35 +2016,62 @@ public: Name); } - /// \brief Create an invariant.group.barrier intrinsic call, that stops - /// optimizer to propagate equality using invariant.group metadata. - /// If Ptr type is different from pointer to i8, it's casted to pointer to i8 - /// in the same address space before call and casted back to Ptr type after - /// call. - Value *CreateInvariantGroupBarrier(Value *Ptr) { + /// Create a launder.invariant.group intrinsic call. If Ptr type is + /// different from pointer to i8, it's casted to pointer to i8 in the same + /// address space before call and casted back to Ptr type after call. + Value *CreateLaunderInvariantGroup(Value *Ptr) { assert(isa<PointerType>(Ptr->getType()) && - "invariant.group.barrier only applies to pointers."); + "launder.invariant.group only applies to pointers."); + // FIXME: we could potentially avoid casts to/from i8*. auto *PtrType = Ptr->getType(); auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace()); if (PtrType != Int8PtrTy) Ptr = CreateBitCast(Ptr, Int8PtrTy); Module *M = BB->getParent()->getParent(); - Function *FnInvariantGroupBarrier = Intrinsic::getDeclaration( - M, Intrinsic::invariant_group_barrier, {Int8PtrTy}); + Function *FnLaunderInvariantGroup = Intrinsic::getDeclaration( + M, Intrinsic::launder_invariant_group, {Int8PtrTy}); - assert(FnInvariantGroupBarrier->getReturnType() == Int8PtrTy && - FnInvariantGroupBarrier->getFunctionType()->getParamType(0) == + assert(FnLaunderInvariantGroup->getReturnType() == Int8PtrTy && + FnLaunderInvariantGroup->getFunctionType()->getParamType(0) == Int8PtrTy && - "InvariantGroupBarrier should take and return the same type"); + "LaunderInvariantGroup should take and return the same type"); - CallInst *Fn = CreateCall(FnInvariantGroupBarrier, {Ptr}); + CallInst *Fn = CreateCall(FnLaunderInvariantGroup, {Ptr}); if (PtrType != Int8PtrTy) return CreateBitCast(Fn, PtrType); return Fn; } - /// \brief Return a vector value that contains \arg V broadcasted to \p + /// \brief Create a strip.invariant.group intrinsic call. If Ptr type is + /// different from pointer to i8, it's casted to pointer to i8 in the same + /// address space before call and casted back to Ptr type after call. + Value *CreateStripInvariantGroup(Value *Ptr) { + assert(isa<PointerType>(Ptr->getType()) && + "strip.invariant.group only applies to pointers."); + + // FIXME: we could potentially avoid casts to/from i8*. + auto *PtrType = Ptr->getType(); + auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace()); + if (PtrType != Int8PtrTy) + Ptr = CreateBitCast(Ptr, Int8PtrTy); + Module *M = BB->getParent()->getParent(); + Function *FnStripInvariantGroup = Intrinsic::getDeclaration( + M, Intrinsic::strip_invariant_group, {Int8PtrTy}); + + assert(FnStripInvariantGroup->getReturnType() == Int8PtrTy && + FnStripInvariantGroup->getFunctionType()->getParamType(0) == + Int8PtrTy && + "StripInvariantGroup should take and return the same type"); + + CallInst *Fn = CreateCall(FnStripInvariantGroup, {Ptr}); + + if (PtrType != Int8PtrTy) + return CreateBitCast(Fn, PtrType); + return Fn; + } + + /// Return a vector value that contains \arg V broadcasted to \p /// NumElts elements. Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = "") { assert(NumElts > 0 && "Cannot splat to an empty vector!"); @@ -1852,11 +2087,11 @@ public: return CreateShuffleVector(V, Undef, Zeros, Name + ".splat"); } - /// \brief Return a value that has been extracted from a larger integer type. + /// Return a value that has been extracted from a larger integer type. Value *CreateExtractInteger(const DataLayout &DL, Value *From, IntegerType *ExtractedTy, uint64_t Offset, const Twine &Name) { - IntegerType *IntTy = cast<IntegerType>(From->getType()); + auto *IntTy = cast<IntegerType>(From->getType()); assert(DL.getTypeStoreSize(ExtractedTy) + Offset <= DL.getTypeStoreSize(IntTy) && "Element extends past full value"); @@ -1877,7 +2112,7 @@ public: } private: - /// \brief Helper function that creates an assume intrinsic call that + /// Helper function that creates an assume intrinsic call that /// represents an alignment assumption on the provided Ptr, Mask, Type /// and Offset. CallInst *CreateAlignmentAssumptionHelper(const DataLayout &DL, @@ -1888,7 +2123,7 @@ private: if (OffsetValue) { bool IsOffsetZero = false; - if (ConstantInt *CI = dyn_cast<ConstantInt>(OffsetValue)) + if (const auto *CI = dyn_cast<ConstantInt>(OffsetValue)) IsOffsetZero = CI->isZero(); if (!IsOffsetZero) { @@ -1906,7 +2141,7 @@ private: } public: - /// \brief Create an assume intrinsic call that represents an alignment + /// Create an assume intrinsic call that represents an alignment /// assumption on the provided pointer. /// /// An optional offset can be provided, and if it is provided, the offset @@ -1917,15 +2152,15 @@ public: Value *OffsetValue = nullptr) { assert(isa<PointerType>(PtrValue->getType()) && "trying to create an alignment assumption on a non-pointer?"); - PointerType *PtrTy = cast<PointerType>(PtrValue->getType()); + auto *PtrTy = cast<PointerType>(PtrValue->getType()); Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); Value *Mask = ConstantInt::get(IntPtrTy, Alignment > 0 ? Alignment - 1 : 0); return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, OffsetValue); } - // - /// \brief Create an assume intrinsic call that represents an alignment + + /// Create an assume intrinsic call that represents an alignment /// assumption on the provided pointer. /// /// An optional offset can be provided, and if it is provided, the offset @@ -1939,7 +2174,7 @@ public: Value *OffsetValue = nullptr) { assert(isa<PointerType>(PtrValue->getType()) && "trying to create an alignment assumption on a non-pointer?"); - PointerType *PtrTy = cast<PointerType>(PtrValue->getType()); + auto *PtrTy = cast<PointerType>(PtrValue->getType()); Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); if (Alignment->getType() != IntPtrTy) diff --git a/contrib/llvm/include/llvm/IR/IRPrintingPasses.h b/contrib/llvm/include/llvm/IR/IRPrintingPasses.h index 0825e0696cac..e4ac5d4d88a3 100644 --- a/contrib/llvm/include/llvm/IR/IRPrintingPasses.h +++ b/contrib/llvm/include/llvm/IR/IRPrintingPasses.h @@ -23,6 +23,7 @@ #include <string> namespace llvm { +class Pass; class BasicBlockPass; class Function; class FunctionPass; @@ -32,18 +33,18 @@ class PreservedAnalyses; class raw_ostream; template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager; -/// \brief Create and return a pass that writes the module to the specified +/// Create and return a pass that writes the module to the specified /// \c raw_ostream. ModulePass *createPrintModulePass(raw_ostream &OS, const std::string &Banner = "", bool ShouldPreserveUseListOrder = false); -/// \brief Create and return a pass that prints functions to the specified +/// 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 +/// Create and return a pass that writes the BB to the specified /// \c raw_ostream. BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS, const std::string &Banner = ""); @@ -54,7 +55,10 @@ BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS, /// non-printable characters in it. void printLLVMNameWithoutPrefix(raw_ostream &OS, StringRef Name); -/// \brief Pass for printing a Module as LLVM's text IR assembly. +/// Return true if a pass is for IR printing. +bool isIRPrintingPass(Pass *P); + +/// 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. @@ -73,7 +77,7 @@ public: static StringRef name() { return "PrintModulePass"; } }; -/// \brief Pass for printing a Function as LLVM's text IR assembly. +/// 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. diff --git a/contrib/llvm/include/llvm/IR/InstVisitor.h b/contrib/llvm/include/llvm/IR/InstVisitor.h index 55579819fd34..65074025a083 100644 --- a/contrib/llvm/include/llvm/IR/InstVisitor.h +++ b/contrib/llvm/include/llvm/IR/InstVisitor.h @@ -32,7 +32,7 @@ namespace llvm { visit##CLASS_TO_VISIT(static_cast<CLASS_TO_VISIT&>(I)) -/// @brief Base class for instruction visitors +/// Base class for instruction visitors /// /// Instruction visitors are used when you want to perform different actions /// for different kinds of instructions without having to use lots of casts @@ -213,6 +213,7 @@ public: // Handle the special instrinsic instruction classes. RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgInfoIntrinsic);} RetTy visitDbgValueInst(DbgValueInst &I) { DELEGATE(DbgInfoIntrinsic);} + RetTy visitDbgLabelInst(DbgLabelInst &I) { DELEGATE(DbgInfoIntrinsic);} RetTy visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { DELEGATE(IntrinsicInst); } RetTy visitMemSetInst(MemSetInst &I) { DELEGATE(MemIntrinsic); } RetTy visitMemCpyInst(MemCpyInst &I) { DELEGATE(MemTransferInst); } @@ -272,6 +273,7 @@ private: default: DELEGATE(IntrinsicInst); case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst); case Intrinsic::dbg_value: DELEGATE(DbgValueInst); + case Intrinsic::dbg_label: DELEGATE(DbgLabelInst); case Intrinsic::memcpy: DELEGATE(MemCpyInst); case Intrinsic::memmove: DELEGATE(MemMoveInst); case Intrinsic::memset: DELEGATE(MemSetInst); diff --git a/contrib/llvm/include/llvm/IR/InstrTypes.h b/contrib/llvm/include/llvm/IR/InstrTypes.h index 871f702f95f2..ad0012048ac9 100644 --- a/contrib/llvm/include/llvm/IR/InstrTypes.h +++ b/contrib/llvm/include/llvm/IR/InstrTypes.h @@ -25,6 +25,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/LLVMContext.h" @@ -80,7 +81,7 @@ public: return isa<Instruction>(V) && classof(cast<Instruction>(V)); } - // \brief Returns true if this terminator relates to exception handling. + // Returns true if this terminator relates to exception handling. bool isExceptional() const { switch (getOpcode()) { case Instruction::CatchSwitch: @@ -117,7 +118,7 @@ public: return idx < TermInst->getNumSuccessors(); } - /// \brief Proxy object to allow write access in operator[] + /// Proxy object to allow write access in operator[] class SuccessorProxy { Self it; @@ -391,6 +392,37 @@ public: return BO; } + static BinaryOperator *CreateFAddFMF(Value *V1, Value *V2, + BinaryOperator *FMFSource, + const Twine &Name = "") { + return CreateWithCopiedFlags(Instruction::FAdd, V1, V2, FMFSource, Name); + } + static BinaryOperator *CreateFSubFMF(Value *V1, Value *V2, + BinaryOperator *FMFSource, + const Twine &Name = "") { + return CreateWithCopiedFlags(Instruction::FSub, V1, V2, FMFSource, Name); + } + static BinaryOperator *CreateFMulFMF(Value *V1, Value *V2, + BinaryOperator *FMFSource, + const Twine &Name = "") { + return CreateWithCopiedFlags(Instruction::FMul, V1, V2, FMFSource, Name); + } + static BinaryOperator *CreateFDivFMF(Value *V1, Value *V2, + BinaryOperator *FMFSource, + const Twine &Name = "") { + return CreateWithCopiedFlags(Instruction::FDiv, V1, V2, FMFSource, Name); + } + static BinaryOperator *CreateFRemFMF(Value *V1, Value *V2, + BinaryOperator *FMFSource, + const Twine &Name = "") { + return CreateWithCopiedFlags(Instruction::FRem, V1, V2, FMFSource, Name); + } + static BinaryOperator *CreateFNegFMF(Value *Op, BinaryOperator *FMFSource, + const Twine &Name = "") { + Value *Zero = ConstantFP::getNegativeZero(Op->getType()); + return CreateWithCopiedFlags(Instruction::FSub, Zero, Op, FMFSource); + } + static BinaryOperator *CreateNSW(BinaryOps Opc, Value *V1, Value *V2, const Twine &Name = "") { BinaryOperator *BO = Create(Opc, V1, V2, Name); @@ -556,16 +588,16 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) /// can be performed with code like: /// /// if (isa<CastInst>(Instr)) { ... } -/// @brief Base class of casting instructions. +/// Base class of casting instructions. class CastInst : public UnaryInstruction { protected: - /// @brief Constructor with insert-before-instruction semantics for subclasses + /// Constructor with insert-before-instruction semantics for subclasses CastInst(Type *Ty, unsigned iType, Value *S, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) : UnaryInstruction(Ty, iType, S, InsertBefore) { setName(NameStr); } - /// @brief Constructor with insert-at-end-of-block semantics for subclasses + /// Constructor with insert-at-end-of-block semantics for subclasses CastInst(Type *Ty, unsigned iType, Value *S, const Twine &NameStr, BasicBlock *InsertAtEnd) : UnaryInstruction(Ty, iType, S, InsertAtEnd) { @@ -578,7 +610,7 @@ public: /// CastOps category (Instruction::isCast(opcode) returns true). This /// constructor has insert-before-instruction semantics to automatically /// insert the new CastInst before InsertBefore (if it is non-null). - /// @brief Construct any of the CastInst subclasses + /// Construct any of the CastInst subclasses static CastInst *Create( Instruction::CastOps, ///< The opcode of the cast instruction Value *S, ///< The value to be casted (operand 0) @@ -591,7 +623,7 @@ public: /// CastOps category. This constructor has insert-at-end-of-block semantics /// to automatically insert the new CastInst at the end of InsertAtEnd (if /// its non-null). - /// @brief Construct any of the CastInst subclasses + /// Construct any of the CastInst subclasses static CastInst *Create( Instruction::CastOps, ///< The opcode for the cast instruction Value *S, ///< The value to be casted (operand 0) @@ -600,7 +632,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Create a ZExt or BitCast cast instruction + /// Create a ZExt or BitCast cast instruction static CastInst *CreateZExtOrBitCast( Value *S, ///< The value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made @@ -608,7 +640,7 @@ public: Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); - /// @brief Create a ZExt or BitCast cast instruction + /// Create a ZExt or BitCast cast instruction static CastInst *CreateZExtOrBitCast( Value *S, ///< The value to be casted (operand 0) Type *Ty, ///< The type to which operand is casted @@ -616,7 +648,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Create a SExt or BitCast cast instruction + /// Create a SExt or BitCast cast instruction static CastInst *CreateSExtOrBitCast( Value *S, ///< The value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made @@ -624,7 +656,7 @@ public: Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); - /// @brief Create a SExt or BitCast cast instruction + /// Create a SExt or BitCast cast instruction static CastInst *CreateSExtOrBitCast( Value *S, ///< The value to be casted (operand 0) Type *Ty, ///< The type to which operand is casted @@ -632,7 +664,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Create a BitCast AddrSpaceCast, or a PtrToInt cast instruction. + /// Create a BitCast AddrSpaceCast, or a PtrToInt cast instruction. static CastInst *CreatePointerCast( Value *S, ///< The pointer value to be casted (operand 0) Type *Ty, ///< The type to which operand is casted @@ -640,7 +672,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction. + /// Create a BitCast, AddrSpaceCast or a PtrToInt cast instruction. static CastInst *CreatePointerCast( Value *S, ///< The pointer value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made @@ -648,7 +680,7 @@ public: Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); - /// @brief Create a BitCast or an AddrSpaceCast cast instruction. + /// Create a BitCast or an AddrSpaceCast cast instruction. static CastInst *CreatePointerBitCastOrAddrSpaceCast( Value *S, ///< The pointer value to be casted (operand 0) Type *Ty, ///< The type to which operand is casted @@ -656,7 +688,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Create a BitCast or an AddrSpaceCast cast instruction. + /// Create a BitCast or an AddrSpaceCast cast instruction. static CastInst *CreatePointerBitCastOrAddrSpaceCast( Value *S, ///< The pointer value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made @@ -664,7 +696,7 @@ public: Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); - /// @brief Create a BitCast, a PtrToInt, or an IntToPTr cast instruction. + /// Create a BitCast, a PtrToInt, or an IntToPTr cast instruction. /// /// If the value is a pointer type and the destination an integer type, /// creates a PtrToInt cast. If the value is an integer type and the @@ -677,7 +709,7 @@ public: Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); - /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. + /// Create a ZExt, BitCast, or Trunc for int -> int casts. static CastInst *CreateIntegerCast( Value *S, ///< The pointer value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made @@ -686,7 +718,7 @@ public: Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); - /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. + /// Create a ZExt, BitCast, or Trunc for int -> int casts. static CastInst *CreateIntegerCast( Value *S, ///< The integer value to be casted (operand 0) Type *Ty, ///< The integer type to which operand is casted @@ -695,7 +727,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts + /// Create an FPExt, BitCast, or FPTrunc for fp -> fp casts static CastInst *CreateFPCast( Value *S, ///< The floating point value to be casted Type *Ty, ///< The floating point type to cast to @@ -703,7 +735,7 @@ public: Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); - /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts + /// Create an FPExt, BitCast, or FPTrunc for fp -> fp casts static CastInst *CreateFPCast( Value *S, ///< The floating point value to be casted Type *Ty, ///< The floating point type to cast to @@ -711,7 +743,7 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Create a Trunc or BitCast cast instruction + /// Create a Trunc or BitCast cast instruction static CastInst *CreateTruncOrBitCast( Value *S, ///< The value to be casted (operand 0) Type *Ty, ///< The type to which cast should be made @@ -719,7 +751,7 @@ public: Instruction *InsertBefore = nullptr ///< Place to insert the instruction ); - /// @brief Create a Trunc or BitCast cast instruction + /// Create a Trunc or BitCast cast instruction static CastInst *CreateTruncOrBitCast( Value *S, ///< The value to be casted (operand 0) Type *Ty, ///< The type to which operand is casted @@ -727,19 +759,19 @@ public: BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); - /// @brief Check whether it is valid to call getCastOpcode for these types. + /// Check whether it is valid to call getCastOpcode for these types. static bool isCastable( Type *SrcTy, ///< The Type from which the value should be cast. Type *DestTy ///< The Type to which the value should be cast. ); - /// @brief Check whether a bitcast between these types is valid + /// Check whether a bitcast between these types is valid static bool isBitCastable( Type *SrcTy, ///< The Type from which the value should be cast. Type *DestTy ///< The Type to which the value should be cast. ); - /// @brief Check whether a bitcast, inttoptr, or ptrtoint cast between these + /// Check whether a bitcast, inttoptr, or ptrtoint cast between these /// types is valid and a no-op. /// /// This ensures that any pointer<->integer cast has enough bits in the @@ -751,7 +783,7 @@ public: /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. - /// @brief Infer the opcode for cast operand and type + /// Infer the opcode for cast operand and type static Instruction::CastOps getCastOpcode( const Value *Val, ///< The value to cast bool SrcIsSigned, ///< Whether to treat the source as signed @@ -763,14 +795,14 @@ public: /// only deals with integer source and destination types. To simplify that /// logic, this method is provided. /// @returns true iff the cast has only integral typed operand and dest type. - /// @brief Determine if this is an integer-only cast. + /// Determine if this is an integer-only cast. bool isIntegerCast() const; /// A lossless cast is one that does not alter the basic value. It implies /// a no-op cast but is more stringent, preventing things like int->float, /// long->double, or int->ptr. /// @returns true iff the cast is lossless. - /// @brief Determine if this is a lossless cast. + /// Determine if this is a lossless cast. bool isLosslessCast() const; /// A no-op cast is one that can be effected without changing any bits. @@ -779,7 +811,7 @@ public: /// involving Integer and Pointer types. They are no-op casts if the integer /// is the same size as the pointer. However, pointer size varies with /// platform. - /// @brief Determine if the described cast is a no-op cast. + /// Determine if the described cast is a no-op cast. static bool isNoopCast( Instruction::CastOps Opcode, ///< Opcode of cast Type *SrcTy, ///< SrcTy of cast @@ -787,7 +819,7 @@ public: const DataLayout &DL ///< DataLayout to get the Int Ptr type from. ); - /// @brief Determine if this cast is a no-op cast. + /// Determine if this cast is a no-op cast. /// /// \param DL is the DataLayout to determine pointer size. bool isNoopCast(const DataLayout &DL) const; @@ -797,7 +829,7 @@ public: /// @returns 0 if the CastInst pair can't be eliminated, otherwise /// returns Instruction::CastOps value for a cast that can replace /// the pair, casting SrcTy to DstTy. - /// @brief Determine if a cast pair is eliminable + /// Determine if a cast pair is eliminable static unsigned isEliminableCastPair( Instruction::CastOps firstOpcode, ///< Opcode of first cast Instruction::CastOps secondOpcode, ///< Opcode of second cast @@ -809,23 +841,23 @@ public: Type *DstIntPtrTy ///< Integer type corresponding to Ptr DstTy, or null ); - /// @brief Return the opcode of this CastInst + /// Return the opcode of this CastInst Instruction::CastOps getOpcode() const { return Instruction::CastOps(Instruction::getOpcode()); } - /// @brief Return the source type, as a convenience + /// Return the source type, as a convenience Type* getSrcTy() const { return getOperand(0)->getType(); } - /// @brief Return the destination type, as a convenience + /// Return the destination type, as a convenience Type* getDestTy() const { return getType(); } /// This method can be used to determine if a cast from S to DstTy using /// Opcode op is valid or not. /// @returns true iff the proposed cast is valid. - /// @brief Determine if a cast is valid without creating one. + /// Determine if a cast is valid without creating one. static bool castIsValid(Instruction::CastOps op, Value *S, Type *DstTy); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Instruction *I) { return I->isCast(); } @@ -839,7 +871,7 @@ public: //===----------------------------------------------------------------------===// /// This class is the base class for the comparison instructions. -/// @brief Abstract base class of comparison instructions. +/// Abstract base class of comparison instructions. class CmpInst : public Instruction { public: /// This enumeration lists the possible predicates for CmpInst subclasses. @@ -905,7 +937,7 @@ public: /// the two operands. Optionally (if InstBefore is specified) insert the /// instruction into a BasicBlock right before the specified instruction. /// The specified Instruction is allowed to be a dereferenced end iterator. - /// @brief Create a CmpInst + /// Create a CmpInst static CmpInst *Create(OtherOps Op, Predicate predicate, Value *S1, Value *S2, const Twine &Name = "", @@ -914,21 +946,21 @@ public: /// Construct a compare instruction, given the opcode, the predicate and the /// two operands. Also automatically insert this instruction to the end of /// the BasicBlock specified. - /// @brief Create a CmpInst + /// Create a CmpInst static CmpInst *Create(OtherOps Op, Predicate predicate, Value *S1, Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); - /// @brief Get the opcode casted to the right type + /// Get the opcode casted to the right type OtherOps getOpcode() const { return static_cast<OtherOps>(Instruction::getOpcode()); } - /// @brief Return the predicate for this instruction. + /// Return the predicate for this instruction. Predicate getPredicate() const { return Predicate(getSubclassDataFromInstruction()); } - /// @brief Set the predicate for this instruction to the specified value. + /// Set the predicate for this instruction to the specified value. void setPredicate(Predicate P) { setInstructionSubclassData(P); } static bool isFPPredicate(Predicate P) { @@ -947,7 +979,7 @@ public: /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. /// @returns the inverse predicate for the instruction's current predicate. - /// @brief Return the inverse of the instruction's predicate. + /// Return the inverse of the instruction's predicate. Predicate getInversePredicate() const { return getInversePredicate(getPredicate()); } @@ -955,7 +987,7 @@ public: /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. /// @returns the inverse predicate for predicate provided in \p pred. - /// @brief Return the inverse of a given predicate + /// Return the inverse of a given predicate static Predicate getInversePredicate(Predicate pred); /// For example, EQ->EQ, SLE->SGE, ULT->UGT, @@ -963,81 +995,109 @@ public: /// @returns the predicate that would be the result of exchanging the two /// operands of the CmpInst instruction without changing the result /// produced. - /// @brief Return the predicate as if the operands were swapped + /// Return the predicate as if the operands were swapped Predicate getSwappedPredicate() const { return getSwappedPredicate(getPredicate()); } /// This is a static version that you can use without an instruction /// available. - /// @brief Return the predicate as if the operands were swapped. + /// Return the predicate as if the operands were swapped. static Predicate getSwappedPredicate(Predicate pred); - /// @brief Provide more efficient getOperand methods. + /// For predicate of kind "is X or equal to 0" returns the predicate "is X". + /// For predicate of kind "is X" returns the predicate "is X or equal to 0". + /// does not support other kind of predicates. + /// @returns the predicate that does not contains is equal to zero if + /// it had and vice versa. + /// Return the flipped strictness of predicate + Predicate getFlippedStrictnessPredicate() const { + return getFlippedStrictnessPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction + /// available. + /// Return the flipped strictness of predicate + static Predicate getFlippedStrictnessPredicate(Predicate pred); + + /// For example, SGT -> SGE, SLT -> SLE, ULT -> ULE, UGT -> UGE. + /// Returns the non-strict version of strict comparisons. + Predicate getNonStrictPredicate() const { + return getNonStrictPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction + /// available. + /// @returns the non-strict version of comparison provided in \p pred. + /// If \p pred is not a strict comparison predicate, returns \p pred. + /// Returns the non-strict version of strict comparisons. + static Predicate getNonStrictPredicate(Predicate pred); + + /// Provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); /// This is just a convenience that dispatches to the subclasses. - /// @brief Swap the operands and adjust predicate accordingly to retain + /// Swap the operands and adjust predicate accordingly to retain /// the same comparison. void swapOperands(); /// This is just a convenience that dispatches to the subclasses. - /// @brief Determine if this CmpInst is commutative. + /// Determine if this CmpInst is commutative. bool isCommutative() const; /// This is just a convenience that dispatches to the subclasses. - /// @brief Determine if this is an equals/not equals predicate. + /// Determine if this is an equals/not equals predicate. bool isEquality() const; /// @returns true if the comparison is signed, false otherwise. - /// @brief Determine if this instruction is using a signed comparison. + /// Determine if this instruction is using a signed comparison. bool isSigned() const { return isSigned(getPredicate()); } /// @returns true if the comparison is unsigned, false otherwise. - /// @brief Determine if this instruction is using an unsigned comparison. + /// Determine if this instruction is using an unsigned comparison. bool isUnsigned() const { return isUnsigned(getPredicate()); } /// For example, ULT->SLT, ULE->SLE, UGT->SGT, UGE->SGE, SLT->Failed assert /// @returns the signed version of the unsigned predicate pred. - /// @brief return the signed version of a predicate + /// return the signed version of a predicate static Predicate getSignedPredicate(Predicate pred); /// For example, ULT->SLT, ULE->SLE, UGT->SGT, UGE->SGE, SLT->Failed assert /// @returns the signed version of the predicate for this instruction (which /// has to be an unsigned predicate). - /// @brief return the signed version of a predicate + /// return the signed version of a predicate Predicate getSignedPredicate() { return getSignedPredicate(getPredicate()); } /// This is just a convenience. - /// @brief Determine if this is true when both operands are the same. + /// Determine if this is true when both operands are the same. bool isTrueWhenEqual() const { return isTrueWhenEqual(getPredicate()); } /// This is just a convenience. - /// @brief Determine if this is false when both operands are the same. + /// Determine if this is false when both operands are the same. bool isFalseWhenEqual() const { return isFalseWhenEqual(getPredicate()); } /// @returns true if the predicate is unsigned, false otherwise. - /// @brief Determine if the predicate is an unsigned operation. + /// Determine if the predicate is an unsigned operation. static bool isUnsigned(Predicate predicate); /// @returns true if the predicate is signed, false otherwise. - /// @brief Determine if the predicate is an signed operation. + /// Determine if the predicate is an signed operation. static bool isSigned(Predicate predicate); - /// @brief Determine if the predicate is an ordered operation. + /// Determine if the predicate is an ordered operation. static bool isOrdered(Predicate predicate); - /// @brief Determine if the predicate is an unordered operation. + /// Determine if the predicate is an unordered operation. static bool isUnordered(Predicate predicate); /// Determine if the predicate is true when comparing a value with itself. @@ -1054,7 +1114,7 @@ public: /// operands. static bool isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2); - /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Instruction *I) { return I->getOpcode() == Instruction::ICmp || I->getOpcode() == Instruction::FCmp; @@ -1063,7 +1123,7 @@ public: return isa<Instruction>(V) && classof(cast<Instruction>(V)); } - /// @brief Create a result type for fcmp/icmp + /// Create a result type for fcmp/icmp static Type* makeCmpResultType(Type* opnd_type) { if (VectorType* vt = dyn_cast<VectorType>(opnd_type)) { return VectorType::get(Type::getInt1Ty(opnd_type->getContext()), @@ -1121,7 +1181,7 @@ public: /// Convenience accessors - /// \brief Return the outer EH-pad this funclet is nested within. + /// Return the outer EH-pad this funclet is nested within. /// /// Note: This returns the associated CatchSwitchInst if this FuncletPadInst /// is a CatchPadInst. @@ -1157,7 +1217,7 @@ struct OperandTraits<FuncletPadInst> DEFINE_TRANSPARENT_OPERAND_ACCESSORS(FuncletPadInst, Value) -/// \brief A lightweight accessor for an operand bundle meant to be passed +/// A lightweight accessor for an operand bundle meant to be passed /// around by value. struct OperandBundleUse { ArrayRef<Use> Inputs; @@ -1166,7 +1226,7 @@ struct OperandBundleUse { explicit OperandBundleUse(StringMapEntry<uint32_t> *Tag, ArrayRef<Use> Inputs) : Inputs(Inputs), Tag(Tag) {} - /// \brief Return true if the operand at index \p Idx in this operand bundle + /// Return true if the operand at index \p Idx in this operand bundle /// has the attribute A. bool operandHasAttr(unsigned Idx, Attribute::AttrKind A) const { if (isDeoptOperandBundle()) @@ -1177,12 +1237,12 @@ struct OperandBundleUse { return false; } - /// \brief Return the tag of this operand bundle as a string. + /// Return the tag of this operand bundle as a string. StringRef getTagName() const { return Tag->getKey(); } - /// \brief Return the tag of this operand bundle as an integer. + /// Return the tag of this operand bundle as an integer. /// /// Operand bundle tags are interned by LLVMContextImpl::getOrInsertBundleTag, /// and this function returns the unique integer getOrInsertBundleTag @@ -1191,22 +1251,22 @@ struct OperandBundleUse { return Tag->getValue(); } - /// \brief Return true if this is a "deopt" operand bundle. + /// Return true if this is a "deopt" operand bundle. bool isDeoptOperandBundle() const { return getTagID() == LLVMContext::OB_deopt; } - /// \brief Return true if this is a "funclet" operand bundle. + /// Return true if this is a "funclet" operand bundle. bool isFuncletOperandBundle() const { return getTagID() == LLVMContext::OB_funclet; } private: - /// \brief Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag. + /// Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag. StringMapEntry<uint32_t> *Tag; }; -/// \brief A container for an operand bundle being viewed as a set of values +/// A container for an operand bundle being viewed as a set of values /// rather than a set of uses. /// /// Unlike OperandBundleUse, OperandBundleDefT owns the memory it carries, and @@ -1241,7 +1301,7 @@ public: using OperandBundleDef = OperandBundleDefT<Value *>; using ConstOperandBundleDef = OperandBundleDefT<const Value *>; -/// \brief A mixin to add operand bundle functionality to llvm instruction +/// A mixin to add operand bundle functionality to llvm instruction /// classes. /// /// OperandBundleUser uses the descriptor area co-allocated with the host User @@ -1289,21 +1349,21 @@ using ConstOperandBundleDef = OperandBundleDefT<const Value *>; /// Currently operand bundle users with hung-off operands are not supported. template <typename InstrTy, typename OpIteratorTy> class OperandBundleUser { public: - /// \brief Return the number of operand bundles associated with this User. + /// Return the number of operand bundles associated with this User. unsigned getNumOperandBundles() const { return std::distance(bundle_op_info_begin(), bundle_op_info_end()); } - /// \brief Return true if this User has any operand bundles. + /// Return true if this User has any operand bundles. bool hasOperandBundles() const { return getNumOperandBundles() != 0; } - /// \brief Return the index of the first bundle operand in the Use array. + /// Return the index of the first bundle operand in the Use array. unsigned getBundleOperandsStartIndex() const { assert(hasOperandBundles() && "Don't call otherwise!"); return bundle_op_info_begin()->Begin; } - /// \brief Return the index of the last bundle operand in the Use array. + /// Return the index of the last bundle operand in the Use array. unsigned getBundleOperandsEndIndex() const { assert(hasOperandBundles() && "Don't call otherwise!"); return bundle_op_info_end()[-1].End; @@ -1315,7 +1375,7 @@ public: Idx < getBundleOperandsEndIndex(); } - /// \brief Return the total number operands (not operand bundles) used by + /// Return the total number operands (not operand bundles) used by /// every operand bundle in this OperandBundleUser. unsigned getNumTotalBundleOperands() const { if (!hasOperandBundles()) @@ -1328,13 +1388,13 @@ public: return End - Begin; } - /// \brief Return the operand bundle at a specific index. + /// Return the operand bundle at a specific index. OperandBundleUse getOperandBundleAt(unsigned Index) const { assert(Index < getNumOperandBundles() && "Index out of bounds!"); return operandBundleFromBundleOpInfo(*(bundle_op_info_begin() + Index)); } - /// \brief Return the number of operand bundles with the tag Name attached to + /// Return the number of operand bundles with the tag Name attached to /// this instruction. unsigned countOperandBundlesOfType(StringRef Name) const { unsigned Count = 0; @@ -1345,7 +1405,7 @@ public: return Count; } - /// \brief Return the number of operand bundles with the tag ID attached to + /// Return the number of operand bundles with the tag ID attached to /// this instruction. unsigned countOperandBundlesOfType(uint32_t ID) const { unsigned Count = 0; @@ -1356,7 +1416,7 @@ public: return Count; } - /// \brief Return an operand bundle by name, if present. + /// Return an operand bundle by name, if present. /// /// It is an error to call this for operand bundle types that may have /// multiple instances of them on the same instruction. @@ -1372,7 +1432,7 @@ public: return None; } - /// \brief Return an operand bundle by tag ID, if present. + /// Return an operand bundle by tag ID, if present. /// /// It is an error to call this for operand bundle types that may have /// multiple instances of them on the same instruction. @@ -1388,7 +1448,7 @@ public: return None; } - /// \brief Return the list of operand bundles attached to this instruction as + /// Return the list of operand bundles attached to this instruction as /// a vector of OperandBundleDefs. /// /// This function copies the OperandBundeUse instances associated with this @@ -1400,7 +1460,7 @@ public: Defs.emplace_back(getOperandBundleAt(i)); } - /// \brief Return the operand bundle for the operand at index OpIdx. + /// Return the operand bundle for the operand at index OpIdx. /// /// It is an error to call this with an OpIdx that does not correspond to an /// bundle operand. @@ -1408,7 +1468,7 @@ public: return operandBundleFromBundleOpInfo(getBundleOpInfoForOperand(OpIdx)); } - /// \brief Return true if this operand bundle user has operand bundles that + /// Return true if this operand bundle user has operand bundles that /// may read from the heap. bool hasReadingOperandBundles() const { // Implementation note: this is a conservative implementation of operand @@ -1417,7 +1477,7 @@ public: return hasOperandBundles(); } - /// \brief Return true if this operand bundle user has operand bundles that + /// Return true if this operand bundle user has operand bundles that /// may write to the heap. bool hasClobberingOperandBundles() const { for (auto &BOI : bundle_op_infos()) { @@ -1433,7 +1493,7 @@ public: return false; } - /// \brief Return true if the bundle operand at index \p OpIdx has the + /// Return true if the bundle operand at index \p OpIdx has the /// attribute \p A. bool bundleOperandHasAttr(unsigned OpIdx, Attribute::AttrKind A) const { auto &BOI = getBundleOpInfoForOperand(OpIdx); @@ -1441,7 +1501,7 @@ public: return OBU.operandHasAttr(OpIdx - BOI.Begin, A); } - /// \brief Return true if \p Other has the same sequence of operand bundle + /// Return true if \p Other has the same sequence of operand bundle /// tags with the same number of operands on each one of them as this /// OperandBundleUser. bool hasIdenticalOperandBundleSchema( @@ -1453,7 +1513,7 @@ public: Other.bundle_op_info_begin()); } - /// \brief Return true if this operand bundle user contains operand bundles + /// Return true if this operand bundle user contains operand bundles /// with tags other than those specified in \p IDs. bool hasOperandBundlesOtherThan(ArrayRef<uint32_t> IDs) const { for (unsigned i = 0, e = getNumOperandBundles(); i != e; ++i) { @@ -1465,7 +1525,7 @@ public: } protected: - /// \brief Is the function attribute S disallowed by some operand bundle on + /// Is the function attribute S disallowed by some operand bundle on /// this operand bundle user? bool isFnAttrDisallowedByOpBundle(StringRef S) const { // Operand bundles only possibly disallow readnone, readonly and argmenonly @@ -1473,7 +1533,7 @@ protected: return false; } - /// \brief Is the function attribute A disallowed by some operand bundle on + /// Is the function attribute A disallowed by some operand bundle on /// this operand bundle user? bool isFnAttrDisallowedByOpBundle(Attribute::AttrKind A) const { switch (A) { @@ -1499,18 +1559,18 @@ protected: llvm_unreachable("switch has a default case!"); } - /// \brief Used to keep track of an operand bundle. See the main comment on + /// Used to keep track of an operand bundle. See the main comment on /// OperandBundleUser above. struct BundleOpInfo { - /// \brief The operand bundle tag, interned by + /// The operand bundle tag, interned by /// LLVMContextImpl::getOrInsertBundleTag. StringMapEntry<uint32_t> *Tag; - /// \brief The index in the Use& vector where operands for this operand + /// The index in the Use& vector where operands for this operand /// bundle starts. uint32_t Begin; - /// \brief The index in the Use& vector where operands for this operand + /// The index in the Use& vector where operands for this operand /// bundle ends. uint32_t End; @@ -1519,7 +1579,7 @@ protected: } }; - /// \brief Simple helper function to map a BundleOpInfo to an + /// Simple helper function to map a BundleOpInfo to an /// OperandBundleUse. OperandBundleUse operandBundleFromBundleOpInfo(const BundleOpInfo &BOI) const { @@ -1531,7 +1591,7 @@ protected: using bundle_op_iterator = BundleOpInfo *; using const_bundle_op_iterator = const BundleOpInfo *; - /// \brief Return the start of the list of BundleOpInfo instances associated + /// Return the start of the list of BundleOpInfo instances associated /// with this OperandBundleUser. bundle_op_iterator bundle_op_info_begin() { if (!static_cast<InstrTy *>(this)->hasDescriptor()) @@ -1541,7 +1601,7 @@ protected: return reinterpret_cast<bundle_op_iterator>(BytesBegin); } - /// \brief Return the start of the list of BundleOpInfo instances associated + /// Return the start of the list of BundleOpInfo instances associated /// with this OperandBundleUser. const_bundle_op_iterator bundle_op_info_begin() const { auto *NonConstThis = @@ -1549,7 +1609,7 @@ protected: return NonConstThis->bundle_op_info_begin(); } - /// \brief Return the end of the list of BundleOpInfo instances associated + /// Return the end of the list of BundleOpInfo instances associated /// with this OperandBundleUser. bundle_op_iterator bundle_op_info_end() { if (!static_cast<InstrTy *>(this)->hasDescriptor()) @@ -1559,7 +1619,7 @@ protected: return reinterpret_cast<bundle_op_iterator>(BytesEnd); } - /// \brief Return the end of the list of BundleOpInfo instances associated + /// Return the end of the list of BundleOpInfo instances associated /// with this OperandBundleUser. const_bundle_op_iterator bundle_op_info_end() const { auto *NonConstThis = @@ -1567,17 +1627,17 @@ protected: return NonConstThis->bundle_op_info_end(); } - /// \brief Return the range [\p bundle_op_info_begin, \p bundle_op_info_end). + /// Return the range [\p bundle_op_info_begin, \p bundle_op_info_end). iterator_range<bundle_op_iterator> bundle_op_infos() { return make_range(bundle_op_info_begin(), bundle_op_info_end()); } - /// \brief Return the range [\p bundle_op_info_begin, \p bundle_op_info_end). + /// Return the range [\p bundle_op_info_begin, \p bundle_op_info_end). iterator_range<const_bundle_op_iterator> bundle_op_infos() const { return make_range(bundle_op_info_begin(), bundle_op_info_end()); } - /// \brief Populate the BundleOpInfo instances and the Use& vector from \p + /// Populate the BundleOpInfo instances and the Use& vector from \p /// Bundles. Return the op_iterator pointing to the Use& one past the last /// last bundle operand use. /// @@ -1608,7 +1668,7 @@ protected: return It; } - /// \brief Return the BundleOpInfo for the operand at index OpIdx. + /// Return the BundleOpInfo for the operand at index OpIdx. /// /// It is an error to call this with an OpIdx that does not correspond to an /// bundle operand. @@ -1620,7 +1680,7 @@ protected: llvm_unreachable("Did not find operand bundle for operand!"); } - /// \brief Return the total number of values used in \p Bundles. + /// Return the total number of values used in \p Bundles. static unsigned CountBundleInputs(ArrayRef<OperandBundleDef> Bundles) { unsigned Total = 0; for (auto &B : Bundles) diff --git a/contrib/llvm/include/llvm/IR/Instruction.h b/contrib/llvm/include/llvm/IR/Instruction.h index 6af9cbfae5de..a3bf25056ee5 100644 --- a/contrib/llvm/include/llvm/IR/Instruction.h +++ b/contrib/llvm/include/llvm/IR/Instruction.h @@ -128,6 +128,7 @@ public: const char *getOpcodeName() const { return getOpcodeName(getOpcode()); } bool isTerminator() const { return isTerminator(getOpcode()); } bool isBinaryOp() const { return isBinaryOp(getOpcode()); } + bool isIntDivRem() const { return isIntDivRem(getOpcode()); } bool isShift() { return isShift(getOpcode()); } bool isCast() const { return isCast(getOpcode()); } bool isFuncletPad() const { return isFuncletPad(getOpcode()); } @@ -142,6 +143,10 @@ public: return Opcode >= BinaryOpsBegin && Opcode < BinaryOpsEnd; } + static inline bool isIntDivRem(unsigned Opcode) { + return Opcode == UDiv || Opcode == SDiv || Opcode == URem || Opcode == SRem; + } + /// Determine if the Opcode is one of the shift instructions. static inline bool isShift(unsigned Opcode) { return Opcode >= Shl && Opcode <= AShr; @@ -284,7 +289,7 @@ public: /// Return the debug location for this node as a DebugLoc. const DebugLoc &getDebugLoc() const { return DbgLoc; } - /// Set or clear the nsw flag on this instruction, which must be an operator + /// Set or clear the nuw flag on this instruction, which must be an operator /// which supports this flag. See LangRef.html for the meaning of this flag. void setHasNoUnsignedWrap(bool b = true); @@ -535,6 +540,14 @@ public: /// matters, isSafeToSpeculativelyExecute may be more appropriate. bool mayHaveSideEffects() const { return mayWriteToMemory() || mayThrow(); } + /// Return true if the instruction can be removed if the result is unused. + /// + /// When constant folding some instructions cannot be removed even if their + /// results are unused. Specifically terminator instructions and calls that + /// may have side effects cannot be removed without semantically changing the + /// generated program. + bool isSafeToRemove() const; + /// Return true if the instruction is a variety of EH-block. bool isEHPad() const { switch (getOpcode()) { @@ -548,6 +561,14 @@ public: } } + /// Return a pointer to the next non-debug instruction in the same basic + /// block as 'this', or nullptr if no such instruction exists. + const Instruction *getNextNonDebugInstruction() const; + Instruction *getNextNonDebugInstruction() { + return const_cast<Instruction *>( + static_cast<const Instruction *>(this)->getNextNonDebugInstruction()); + } + /// Create a copy of 'this' instruction that is identical in all ways except /// the following: /// * The instruction has no parent @@ -582,7 +603,7 @@ public: /// be identical. /// @returns true if the specified instruction is the same operation as /// the current one. - /// @brief Determine if one instruction is the same operation as another. + /// Determine if one instruction is the same operation as another. bool isSameOperationAs(const Instruction *I, unsigned flags = 0) const; /// Return true if there are any uses of this instruction in blocks other than diff --git a/contrib/llvm/include/llvm/IR/Instructions.h b/contrib/llvm/include/llvm/IR/Instructions.h index c1122d137f24..a2cb84a071f2 100644 --- a/contrib/llvm/include/llvm/IR/Instructions.h +++ b/contrib/llvm/include/llvm/IR/Instructions.h @@ -98,6 +98,10 @@ public: return cast<PointerType>(Instruction::getType()); } + /// Get allocation size in bits. Returns None if size can't be determined, + /// e.g. in case of a VLA. + Optional<uint64_t> getAllocationSizeInBits(const DataLayout &DL) const; + /// Return the type that is being allocated by the instruction. Type *getAllocatedType() const { return AllocatedType; } /// for use only in special circumstances that need to generically @@ -1346,224 +1350,71 @@ public: } }; -//===----------------------------------------------------------------------===// -/// This class represents a function call, abstracting a target -/// machine's calling convention. This class uses low bit of the SubClassData -/// field to indicate whether or not this is a tail call. The rest of the bits -/// hold the calling convention of the call. -/// -class CallInst : public Instruction, - public OperandBundleUser<CallInst, User::op_iterator> { - friend class OperandBundleUser<CallInst, User::op_iterator>; +class CallInst; +class InvokeInst; - AttributeList Attrs; ///< parameter attributes for call - FunctionType *FTy; +template <class T> struct CallBaseParent { using type = Instruction; }; - CallInst(const CallInst &CI); - - /// Construct a CallInst given a range of arguments. - /// Construct a CallInst from a range of arguments - inline CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, - ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, - Instruction *InsertBefore); - - inline CallInst(Value *Func, ArrayRef<Value *> Args, - ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, - Instruction *InsertBefore) - : CallInst(cast<FunctionType>( - cast<PointerType>(Func->getType())->getElementType()), - Func, Args, Bundles, NameStr, InsertBefore) {} - - inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, - Instruction *InsertBefore) - : CallInst(Func, Args, None, NameStr, InsertBefore) {} - - /// Construct a CallInst given a range of arguments. - /// Construct a CallInst from a range of arguments - inline CallInst(Value *Func, ArrayRef<Value *> Args, - ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, - BasicBlock *InsertAtEnd); - - explicit CallInst(Value *F, const Twine &NameStr, - Instruction *InsertBefore); - - CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd); - - void init(Value *Func, ArrayRef<Value *> Args, - ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) { - init(cast<FunctionType>( - cast<PointerType>(Func->getType())->getElementType()), - Func, Args, Bundles, NameStr); - } - void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, - ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr); - void init(Value *Func, const Twine &NameStr); - - bool hasDescriptor() const { return HasDescriptor; } +template <> struct CallBaseParent<InvokeInst> { using type = TerminatorInst; }; +//===----------------------------------------------------------------------===// +/// Base class for all callable instructions (InvokeInst and CallInst) +/// Holds everything related to calling a function, abstracting from the base +/// type @p BaseInstTy and the concrete instruction @p InstTy +/// +template <class InstTy> +class CallBase : public CallBaseParent<InstTy>::type, + public OperandBundleUser<InstTy, User::op_iterator> { protected: - // Note: Instruction needs to be a friend here to call cloneImpl. - friend class Instruction; - - CallInst *cloneImpl() const; - -public: - static CallInst *Create(Value *Func, ArrayRef<Value *> Args, - ArrayRef<OperandBundleDef> Bundles = None, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return Create(cast<FunctionType>( - cast<PointerType>(Func->getType())->getElementType()), - Func, Args, Bundles, NameStr, InsertBefore); - } - - static CallInst *Create(Value *Func, ArrayRef<Value *> Args, - const Twine &NameStr, - Instruction *InsertBefore = nullptr) { - return Create(cast<FunctionType>( - cast<PointerType>(Func->getType())->getElementType()), - Func, Args, None, NameStr, InsertBefore); - } - - static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, - const Twine &NameStr, - Instruction *InsertBefore = nullptr) { - return new (unsigned(Args.size() + 1)) - CallInst(Ty, Func, Args, None, NameStr, InsertBefore); - } - - static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, - ArrayRef<OperandBundleDef> Bundles = None, - const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - const unsigned TotalOps = - unsigned(Args.size()) + CountBundleInputs(Bundles) + 1; - const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); - - return new (TotalOps, DescriptorBytes) - CallInst(Ty, Func, Args, Bundles, NameStr, InsertBefore); - } + AttributeList Attrs; ///< parameter attributes for callable + FunctionType *FTy; + using BaseInstTy = typename CallBaseParent<InstTy>::type; - static CallInst *Create(Value *Func, ArrayRef<Value *> Args, - ArrayRef<OperandBundleDef> Bundles, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - const unsigned TotalOps = - unsigned(Args.size()) + CountBundleInputs(Bundles) + 1; - const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); + template <class... ArgsTy> + CallBase(AttributeList const &A, FunctionType *FT, ArgsTy &&... Args) + : BaseInstTy(std::forward<ArgsTy>(Args)...), Attrs(A), FTy(FT) {} + bool hasDescriptor() const { return Value::HasDescriptor; } - return new (TotalOps, DescriptorBytes) - CallInst(Func, Args, Bundles, NameStr, InsertAtEnd); - } + using BaseInstTy::BaseInstTy; - static CallInst *Create(Value *Func, ArrayRef<Value *> Args, - const Twine &NameStr, BasicBlock *InsertAtEnd) { - return new (unsigned(Args.size() + 1)) - CallInst(Func, Args, None, NameStr, InsertAtEnd); - } + using OperandBundleUser<InstTy, + User::op_iterator>::isFnAttrDisallowedByOpBundle; + using OperandBundleUser<InstTy, User::op_iterator>::getNumTotalBundleOperands; + using OperandBundleUser<InstTy, User::op_iterator>::bundleOperandHasAttr; + using Instruction::getSubclassDataFromInstruction; + using Instruction::setInstructionSubclassData; - static CallInst *Create(Value *F, const Twine &NameStr = "", - Instruction *InsertBefore = nullptr) { - return new(1) CallInst(F, NameStr, InsertBefore); - } +public: + using Instruction::getContext; + using OperandBundleUser<InstTy, User::op_iterator>::hasOperandBundles; + using OperandBundleUser<InstTy, + User::op_iterator>::getBundleOperandsStartIndex; - static CallInst *Create(Value *F, const Twine &NameStr, - BasicBlock *InsertAtEnd) { - return new(1) CallInst(F, NameStr, InsertAtEnd); + static bool classof(const Instruction *I) { + llvm_unreachable( + "CallBase is not meant to be used as part of the classof hierarchy"); } - /// Create a clone of \p CI with a different set of operand bundles and - /// insert it before \p InsertPt. +public: + /// Return the parameter attributes for this call. /// - /// The returned call instruction is identical \p CI in every way except that - /// the operand bundles for the new instruction are set to the operand bundles - /// in \p Bundles. - static CallInst *Create(CallInst *CI, ArrayRef<OperandBundleDef> Bundles, - Instruction *InsertPt = nullptr); + AttributeList getAttributes() const { return Attrs; } - /// Generate the IR for a call to malloc: - /// 1. Compute the malloc call's argument as the specified type's size, - /// possibly multiplied by the array size if the array size is not - /// constant 1. - /// 2. Call malloc with that argument. - /// 3. Bitcast the result of the malloc call to the specified type. - static Instruction *CreateMalloc(Instruction *InsertBefore, - Type *IntPtrTy, Type *AllocTy, - Value *AllocSize, Value *ArraySize = nullptr, - Function* MallocF = nullptr, - const Twine &Name = ""); - static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, - Type *IntPtrTy, Type *AllocTy, - Value *AllocSize, Value *ArraySize = nullptr, - Function* MallocF = nullptr, - const Twine &Name = ""); - static Instruction *CreateMalloc(Instruction *InsertBefore, - Type *IntPtrTy, Type *AllocTy, - Value *AllocSize, Value *ArraySize = nullptr, - ArrayRef<OperandBundleDef> Bundles = None, - Function* MallocF = nullptr, - const Twine &Name = ""); - static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, - Type *IntPtrTy, Type *AllocTy, - Value *AllocSize, Value *ArraySize = nullptr, - ArrayRef<OperandBundleDef> Bundles = None, - Function* MallocF = nullptr, - const Twine &Name = ""); - /// Generate the IR for a call to the builtin free function. - static Instruction *CreateFree(Value *Source, - Instruction *InsertBefore); - static Instruction *CreateFree(Value *Source, - BasicBlock *InsertAtEnd); - static Instruction *CreateFree(Value *Source, - ArrayRef<OperandBundleDef> Bundles, - Instruction *InsertBefore); - static Instruction *CreateFree(Value *Source, - ArrayRef<OperandBundleDef> Bundles, - BasicBlock *InsertAtEnd); + /// Set the parameter attributes for this call. + /// + void setAttributes(AttributeList A) { Attrs = A; } FunctionType *getFunctionType() const { return FTy; } void mutateFunctionType(FunctionType *FTy) { - mutateType(FTy->getReturnType()); + Value::mutateType(FTy->getReturnType()); this->FTy = FTy; } - // Note that 'musttail' implies 'tail'. - enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2, - TCK_NoTail = 3 }; - TailCallKind getTailCallKind() const { - return TailCallKind(getSubclassDataFromInstruction() & 3); - } - - bool isTailCall() const { - unsigned Kind = getSubclassDataFromInstruction() & 3; - return Kind == TCK_Tail || Kind == TCK_MustTail; - } - - bool isMustTailCall() const { - return (getSubclassDataFromInstruction() & 3) == TCK_MustTail; - } - - bool isNoTailCall() const { - return (getSubclassDataFromInstruction() & 3) == TCK_NoTail; - } - - void setTailCall(bool isTC = true) { - setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | - unsigned(isTC ? TCK_Tail : TCK_None)); - } - - void setTailCallKind(TailCallKind TCK) { - setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | - unsigned(TCK)); - } - - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - /// Return the number of call arguments. /// unsigned getNumArgOperands() const { - return getNumOperands() - getNumTotalBundleOperands() - 1; + return getNumOperands() - getNumTotalBundleOperands() - InstTy::ArgOffset; } /// getArgOperand/setArgOperand - Return/set the i-th call argument. @@ -1578,46 +1429,112 @@ public: } /// Return the iterator pointing to the beginning of the argument list. - op_iterator arg_begin() { return op_begin(); } + User::op_iterator arg_begin() { return op_begin(); } /// Return the iterator pointing to the end of the argument list. - op_iterator arg_end() { + User::op_iterator arg_end() { // [ call args ], [ operand bundles ], callee - return op_end() - getNumTotalBundleOperands() - 1; + return op_end() - getNumTotalBundleOperands() - InstTy::ArgOffset; } /// Iteration adapter for range-for loops. - iterator_range<op_iterator> arg_operands() { + iterator_range<User::op_iterator> arg_operands() { return make_range(arg_begin(), arg_end()); } /// Return the iterator pointing to the beginning of the argument list. - const_op_iterator arg_begin() const { return op_begin(); } + User::const_op_iterator arg_begin() const { return op_begin(); } /// Return the iterator pointing to the end of the argument list. - const_op_iterator arg_end() const { + User::const_op_iterator arg_end() const { // [ call args ], [ operand bundles ], callee - return op_end() - getNumTotalBundleOperands() - 1; + return op_end() - getNumTotalBundleOperands() - InstTy::ArgOffset; } /// Iteration adapter for range-for loops. - iterator_range<const_op_iterator> arg_operands() const { + iterator_range<User::const_op_iterator> arg_operands() const { return make_range(arg_begin(), arg_end()); } /// Wrappers for getting the \c Use of a call argument. const Use &getArgOperandUse(unsigned i) const { assert(i < getNumArgOperands() && "Out of bounds!"); - return getOperandUse(i); + return User::getOperandUse(i); } Use &getArgOperandUse(unsigned i) { assert(i < getNumArgOperands() && "Out of bounds!"); - return getOperandUse(i); + return User::getOperandUse(i); } /// If one of the arguments has the 'returned' attribute, return its /// operand value. Otherwise, return nullptr. - Value *getReturnedArgOperand() const; + Value *getReturnedArgOperand() const { + unsigned Index; + + if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index) + return getArgOperand(Index - AttributeList::FirstArgIndex); + if (const Function *F = getCalledFunction()) + if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) && + Index) + return getArgOperand(Index - AttributeList::FirstArgIndex); + + return nullptr; + } + + User::op_iterator op_begin() { + return OperandTraits<CallBase>::op_begin(this); + } + + User::const_op_iterator op_begin() const { + return OperandTraits<CallBase>::op_begin(const_cast<CallBase *>(this)); + } + + User::op_iterator op_end() { return OperandTraits<CallBase>::op_end(this); } + + User::const_op_iterator op_end() const { + return OperandTraits<CallBase>::op_end(const_cast<CallBase *>(this)); + } + + Value *getOperand(unsigned i_nocapture) const { + assert(i_nocapture < OperandTraits<CallBase>::operands(this) && + "getOperand() out of range!"); + return cast_or_null<Value>(OperandTraits<CallBase>::op_begin( + const_cast<CallBase *>(this))[i_nocapture] + .get()); + } + + void setOperand(unsigned i_nocapture, Value *Val_nocapture) { + assert(i_nocapture < OperandTraits<CallBase>::operands(this) && + "setOperand() out of range!"); + OperandTraits<CallBase>::op_begin(this)[i_nocapture] = Val_nocapture; + } + + unsigned getNumOperands() const { + return OperandTraits<CallBase>::operands(this); + } + template <int Idx_nocapture> Use &Op() { + return User::OpFrom<Idx_nocapture>(this); + } + template <int Idx_nocapture> const Use &Op() const { + return User::OpFrom<Idx_nocapture>(this); + } + + /// Return the function called, or null if this is an + /// indirect function invocation. + /// + Function *getCalledFunction() const { + return dyn_cast<Function>(Op<-InstTy::ArgOffset>()); + } + + /// Determine whether this call has the given attribute. + bool hasFnAttr(Attribute::AttrKind Kind) const { + assert(Kind != Attribute::NoBuiltin && + "Use CallBase::isNoBuiltin() to check for Attribute::NoBuiltin"); + return hasFnAttrImpl(Kind); + } + + /// Determine whether this call has the given attribute. + bool hasFnAttr(StringRef Kind) const { return hasFnAttrImpl(Kind); } /// getCallingConv/setCallingConv - Get or set the calling convention of this /// function call. @@ -1631,62 +1548,103 @@ public: (ID << 2)); } - /// Return the parameter attributes for this call. - /// - AttributeList getAttributes() const { return Attrs; } - - /// Set the parameter attributes for this call. - /// - void setAttributes(AttributeList A) { Attrs = A; } /// adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attribute::AttrKind Kind); + void addAttribute(unsigned i, Attribute::AttrKind Kind) { + AttributeList PAL = getAttributes(); + PAL = PAL.addAttribute(getContext(), i, Kind); + setAttributes(PAL); + } /// adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attribute Attr); + void addAttribute(unsigned i, Attribute Attr) { + AttributeList PAL = getAttributes(); + PAL = PAL.addAttribute(getContext(), i, Attr); + setAttributes(PAL); + } /// Adds the attribute to the indicated argument - void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); + void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { + assert(ArgNo < getNumArgOperands() && "Out of bounds"); + AttributeList PAL = getAttributes(); + PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind); + setAttributes(PAL); + } /// Adds the attribute to the indicated argument - void addParamAttr(unsigned ArgNo, Attribute Attr); + void addParamAttr(unsigned ArgNo, Attribute Attr) { + assert(ArgNo < getNumArgOperands() && "Out of bounds"); + AttributeList PAL = getAttributes(); + PAL = PAL.addParamAttribute(getContext(), ArgNo, Attr); + setAttributes(PAL); + } /// removes the attribute from the list of attributes. - void removeAttribute(unsigned i, Attribute::AttrKind Kind); + void removeAttribute(unsigned i, Attribute::AttrKind Kind) { + AttributeList PAL = getAttributes(); + PAL = PAL.removeAttribute(getContext(), i, Kind); + setAttributes(PAL); + } /// removes the attribute from the list of attributes. - void removeAttribute(unsigned i, StringRef Kind); + void removeAttribute(unsigned i, StringRef Kind) { + AttributeList PAL = getAttributes(); + PAL = PAL.removeAttribute(getContext(), i, Kind); + setAttributes(PAL); + } /// Removes the attribute from the given argument - void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); + void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) { + assert(ArgNo < getNumArgOperands() && "Out of bounds"); + AttributeList PAL = getAttributes(); + PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind); + setAttributes(PAL); + } /// Removes the attribute from the given argument - void removeParamAttr(unsigned ArgNo, StringRef Kind); + void removeParamAttr(unsigned ArgNo, StringRef Kind) { + assert(ArgNo < getNumArgOperands() && "Out of bounds"); + AttributeList PAL = getAttributes(); + PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind); + setAttributes(PAL); + } /// adds the dereferenceable attribute to the list of attributes. - void addDereferenceableAttr(unsigned i, uint64_t Bytes); + void addDereferenceableAttr(unsigned i, uint64_t Bytes) { + AttributeList PAL = getAttributes(); + PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes); + setAttributes(PAL); + } /// adds the dereferenceable_or_null attribute to the list of /// attributes. - void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); - - /// Determine whether this call has the given attribute. - bool hasFnAttr(Attribute::AttrKind Kind) const { - assert(Kind != Attribute::NoBuiltin && - "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); - return hasFnAttrImpl(Kind); - } - - /// Determine whether this call has the given attribute. - bool hasFnAttr(StringRef Kind) const { - return hasFnAttrImpl(Kind); + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) { + AttributeList PAL = getAttributes(); + PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes); + setAttributes(PAL); } /// Determine whether the return value has the given attribute. - bool hasRetAttr(Attribute::AttrKind Kind) const; + bool hasRetAttr(Attribute::AttrKind Kind) const { + if (Attrs.hasAttribute(AttributeList::ReturnIndex, Kind)) + return true; + + // Look at the callee, if available. + if (const Function *F = getCalledFunction()) + return F->getAttributes().hasAttribute(AttributeList::ReturnIndex, Kind); + return false; + } /// Determine whether the argument or parameter has the given attribute. - bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const; + bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { + assert(ArgNo < getNumArgOperands() && "Param index out of bounds!"); + + if (Attrs.hasParamAttribute(ArgNo, Kind)) + return true; + if (const Function *F = getCalledFunction()) + return F->getAttributes().hasParamAttribute(ArgNo, Kind); + return false; + } /// Get the attribute of a given kind at a position. Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const { @@ -1709,7 +1667,6 @@ public: assert(ArgNo < getNumArgOperands() && "Out of bounds"); return getAttributes().getParamAttr(ArgNo, Kind); } - /// Return true if the data operand at index \p i has the attribute \p /// A. /// @@ -1723,7 +1680,28 @@ public: /// \p i in [1, arg_size + 1) -> argument number (\p i - 1) /// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index /// (\p i - 1) in the operand list. - bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const; + bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const { + // There are getNumOperands() - (InstTy::ArgOffset - 1) data operands. + // The last operand is the callee. + assert(i < (getNumOperands() - InstTy::ArgOffset + 1) && + "Data operand index out of bounds!"); + + // The attribute A can either be directly specified, if the operand in + // question is a call argument; or be indirectly implied by the kind of its + // containing operand bundle, if the operand is a bundle operand. + + if (i == AttributeList::ReturnIndex) + return hasRetAttr(Kind); + + // FIXME: Avoid these i - 1 calculations and update the API to use + // zero-based indices. + if (i < (getNumArgOperands() + 1)) + return paramHasAttr(i - 1, Kind); + + assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) && + "Must be either a call argument or an operand bundle!"); + return bundleOperandHasAttr(i - 1, Kind); + } /// Extract the alignment of the return value. unsigned getRetAlignment() const { return Attrs.getRetAlignment(); } @@ -1745,7 +1723,7 @@ public: return Attrs.getDereferenceableOrNullBytes(i); } - /// @brief Determine if the return value is marked with NoAlias attribute. + /// Determine if the return value is marked with NoAlias attribute. bool returnDoesNotAlias() const { return Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias); } @@ -1765,15 +1743,6 @@ public: void setIsNoInline() { addAttribute(AttributeList::FunctionIndex, Attribute::NoInline); } - - /// Return true if the call can return twice - bool canReturnTwice() const { - return hasFnAttr(Attribute::ReturnsTwice); - } - void setCanReturnTwice() { - addAttribute(AttributeList::FunctionIndex, Attribute::ReturnsTwice); - } - /// Determine if the call does not access memory. bool doesNotAccessMemory() const { return hasFnAttr(Attribute::ReadNone); @@ -1798,7 +1767,7 @@ public: addAttribute(AttributeList::FunctionIndex, Attribute::WriteOnly); } - /// @brief Determine if the call can access memmory only using pointers based + /// Determine if the call can access memmory only using pointers based /// on its arguments. bool onlyAccessesArgMemory() const { return hasFnAttr(Attribute::ArgMemOnly); @@ -1807,7 +1776,7 @@ public: addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly); } - /// @brief Determine if the function may only access memory that is + /// Determine if the function may only access memory that is /// inaccessible from the IR. bool onlyAccessesInaccessibleMemory() const { return hasFnAttr(Attribute::InaccessibleMemOnly); @@ -1816,7 +1785,7 @@ public: addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOnly); } - /// @brief Determine if the function may only access memory that is + /// Determine if the function may only access memory that is /// either inaccessible from the IR or pointed to by its arguments. bool onlyAccessesInaccessibleMemOrArgMem() const { return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly); @@ -1824,26 +1793,28 @@ public: void setOnlyAccessesInaccessibleMemOrArgMem() { addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly); } - /// Determine if the call cannot return. bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } void setDoesNotReturn() { addAttribute(AttributeList::FunctionIndex, Attribute::NoReturn); } + /// Determine if the call should not perform indirect branch tracking. + bool doesNoCfCheck() const { return hasFnAttr(Attribute::NoCfCheck); } + /// Determine if the call cannot unwind. bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); } void setDoesNotThrow() { addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind); } - /// Determine if the call cannot be duplicated. + /// Determine if the invoke cannot be duplicated. bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); } void setCannotDuplicate() { addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate); } - /// Determine if the call is convergent + /// Determine if the invoke is convergent bool isConvergent() const { return hasFnAttr(Attribute::Convergent); } void setConvergent() { addAttribute(AttributeList::FunctionIndex, Attribute::Convergent); @@ -1866,18 +1837,10 @@ public: bool hasByValArgument() const { return Attrs.hasAttrSomewhere(Attribute::ByVal); } - - /// Return the function called, or null if this is an - /// indirect function invocation. - /// - Function *getCalledFunction() const { - return dyn_cast<Function>(Op<-1>()); - } - /// Get a pointer to the function that is invoked by this /// instruction. - const Value *getCalledValue() const { return Op<-1>(); } - Value *getCalledValue() { return Op<-1>(); } + const Value *getCalledValue() const { return Op<-InstTy::ArgOffset>(); } + Value *getCalledValue() { return Op<-InstTy::ArgOffset>(); } /// Set the function called. void setCalledFunction(Value* Fn) { @@ -1889,23 +1852,10 @@ public: this->FTy = FTy; assert(FTy == cast<FunctionType>( cast<PointerType>(Fn->getType())->getElementType())); - Op<-1>() = Fn; - } - - /// Check if this call is an inline asm statement. - bool isInlineAsm() const { - return isa<InlineAsm>(Op<-1>()); + Op<-InstTy::ArgOffset>() = Fn; } - // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Call; - } - static bool classof(const Value *V) { - return isa<Instruction>(V) && classof(cast<Instruction>(V)); - } - -private: +protected: template <typename AttrKind> bool hasFnAttrImpl(AttrKind Kind) const { if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind)) return true; @@ -1920,7 +1870,227 @@ private: Kind); return false; } +}; + +//===----------------------------------------------------------------------===// +/// This class represents a function call, abstracting a target +/// machine's calling convention. This class uses low bit of the SubClassData +/// field to indicate whether or not this is a tail call. The rest of the bits +/// hold the calling convention of the call. +/// +class CallInst : public CallBase<CallInst> { + friend class OperandBundleUser<CallInst, User::op_iterator>; + + CallInst(const CallInst &CI); + + /// Construct a CallInst given a range of arguments. + /// Construct a CallInst from a range of arguments + inline CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, + Instruction *InsertBefore); + + inline CallInst(Value *Func, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, + Instruction *InsertBefore) + : CallInst(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, Args, Bundles, NameStr, InsertBefore) {} + + inline CallInst(Value *Func, ArrayRef<Value *> Args, const Twine &NameStr, + Instruction *InsertBefore) + : CallInst(Func, Args, None, NameStr, InsertBefore) {} + + /// Construct a CallInst given a range of arguments. + /// Construct a CallInst from a range of arguments + inline CallInst(Value *Func, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, + BasicBlock *InsertAtEnd); + + explicit CallInst(Value *F, const Twine &NameStr, Instruction *InsertBefore); + + CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd); + + void init(Value *Func, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) { + init(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, Args, Bundles, NameStr); + } + void init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr); + void init(Value *Func, const Twine &NameStr); + +protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + + CallInst *cloneImpl() const; + +public: + static constexpr int ArgOffset = 1; + + static CallInst *Create(Value *Func, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles = None, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + return Create(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, Args, Bundles, NameStr, InsertBefore); + } + + static CallInst *Create(Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr, + Instruction *InsertBefore = nullptr) { + return Create(cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()), + Func, Args, None, NameStr, InsertBefore); + } + + static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr, + Instruction *InsertBefore = nullptr) { + return new (unsigned(Args.size() + 1)) + CallInst(Ty, Func, Args, None, NameStr, InsertBefore); + } + + static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles = None, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + const unsigned TotalOps = + unsigned(Args.size()) + CountBundleInputs(Bundles) + 1; + const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); + + return new (TotalOps, DescriptorBytes) + CallInst(Ty, Func, Args, Bundles, NameStr, InsertBefore); + } + + static CallInst *Create(Value *Func, ArrayRef<Value *> Args, + ArrayRef<OperandBundleDef> Bundles, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + const unsigned TotalOps = + unsigned(Args.size()) + CountBundleInputs(Bundles) + 1; + const unsigned DescriptorBytes = Bundles.size() * sizeof(BundleOpInfo); + + return new (TotalOps, DescriptorBytes) + CallInst(Func, Args, Bundles, NameStr, InsertAtEnd); + } + static CallInst *Create(Value *Func, ArrayRef<Value *> Args, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + return new (unsigned(Args.size() + 1)) + CallInst(Func, Args, None, NameStr, InsertAtEnd); + } + + static CallInst *Create(Value *F, const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + return new (1) CallInst(F, NameStr, InsertBefore); + } + + static CallInst *Create(Value *F, const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new (1) CallInst(F, NameStr, InsertAtEnd); + } + + /// Create a clone of \p CI with a different set of operand bundles and + /// insert it before \p InsertPt. + /// + /// The returned call instruction is identical \p CI in every way except that + /// the operand bundles for the new instruction are set to the operand bundles + /// in \p Bundles. + static CallInst *Create(CallInst *CI, ArrayRef<OperandBundleDef> Bundles, + Instruction *InsertPt = nullptr); + + /// Generate the IR for a call to malloc: + /// 1. Compute the malloc call's argument as the specified type's size, + /// possibly multiplied by the array size if the array size is not + /// constant 1. + /// 2. Call malloc with that argument. + /// 3. Bitcast the result of the malloc call to the specified type. + static Instruction *CreateMalloc(Instruction *InsertBefore, Type *IntPtrTy, + Type *AllocTy, Value *AllocSize, + Value *ArraySize = nullptr, + Function *MallocF = nullptr, + const Twine &Name = ""); + static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, Type *IntPtrTy, + Type *AllocTy, Value *AllocSize, + Value *ArraySize = nullptr, + Function *MallocF = nullptr, + const Twine &Name = ""); + static Instruction *CreateMalloc(Instruction *InsertBefore, Type *IntPtrTy, + Type *AllocTy, Value *AllocSize, + Value *ArraySize = nullptr, + ArrayRef<OperandBundleDef> Bundles = None, + Function *MallocF = nullptr, + const Twine &Name = ""); + static Instruction *CreateMalloc(BasicBlock *InsertAtEnd, Type *IntPtrTy, + Type *AllocTy, Value *AllocSize, + Value *ArraySize = nullptr, + ArrayRef<OperandBundleDef> Bundles = None, + Function *MallocF = nullptr, + const Twine &Name = ""); + /// Generate the IR for a call to the builtin free function. + static Instruction *CreateFree(Value *Source, Instruction *InsertBefore); + static Instruction *CreateFree(Value *Source, BasicBlock *InsertAtEnd); + static Instruction *CreateFree(Value *Source, + ArrayRef<OperandBundleDef> Bundles, + Instruction *InsertBefore); + static Instruction *CreateFree(Value *Source, + ArrayRef<OperandBundleDef> Bundles, + BasicBlock *InsertAtEnd); + + // Note that 'musttail' implies 'tail'. + enum TailCallKind { + TCK_None = 0, + TCK_Tail = 1, + TCK_MustTail = 2, + TCK_NoTail = 3 + }; + TailCallKind getTailCallKind() const { + return TailCallKind(getSubclassDataFromInstruction() & 3); + } + + bool isTailCall() const { + unsigned Kind = getSubclassDataFromInstruction() & 3; + return Kind == TCK_Tail || Kind == TCK_MustTail; + } + + bool isMustTailCall() const { + return (getSubclassDataFromInstruction() & 3) == TCK_MustTail; + } + + bool isNoTailCall() const { + return (getSubclassDataFromInstruction() & 3) == TCK_NoTail; + } + + void setTailCall(bool isTC = true) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | + unsigned(isTC ? TCK_Tail : TCK_None)); + } + + void setTailCallKind(TailCallKind TCK) { + setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) | + unsigned(TCK)); + } + + /// Return true if the call can return twice + bool canReturnTwice() const { return hasFnAttr(Attribute::ReturnsTwice); } + void setCanReturnTwice() { + addAttribute(AttributeList::FunctionIndex, Attribute::ReturnsTwice); + } + + /// Check if this call is an inline asm statement. + bool isInlineAsm() const { return isa<InlineAsm>(Op<-1>()); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Call; + } + static bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } + +private: // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. void setInstructionSubclassData(unsigned short D) { @@ -1929,17 +2099,19 @@ private: }; template <> -struct OperandTraits<CallInst> : public VariadicOperandTraits<CallInst, 1> { -}; +struct OperandTraits<CallBase<CallInst>> + : public VariadicOperandTraits<CallBase<CallInst>, 1> {}; CallInst::CallInst(Value *Func, ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, BasicBlock *InsertAtEnd) - : Instruction( - cast<FunctionType>(cast<PointerType>(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Call, OperandTraits<CallInst>::op_end(this) - - (Args.size() + CountBundleInputs(Bundles) + 1), + : CallBase<CallInst>( + cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()) + ->getReturnType(), + Instruction::Call, + OperandTraits<CallBase<CallInst>>::op_end(this) - + (Args.size() + CountBundleInputs(Bundles) + 1), unsigned(Args.size() + CountBundleInputs(Bundles) + 1), InsertAtEnd) { init(Func, Args, Bundles, NameStr); } @@ -1947,19 +2119,14 @@ CallInst::CallInst(Value *Func, ArrayRef<Value *> Args, CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(Ty->getReturnType(), Instruction::Call, - OperandTraits<CallInst>::op_end(this) - - (Args.size() + CountBundleInputs(Bundles) + 1), - unsigned(Args.size() + CountBundleInputs(Bundles) + 1), - InsertBefore) { + : CallBase<CallInst>(Ty->getReturnType(), Instruction::Call, + OperandTraits<CallBase<CallInst>>::op_end(this) - + (Args.size() + CountBundleInputs(Bundles) + 1), + unsigned(Args.size() + CountBundleInputs(Bundles) + 1), + InsertBefore) { init(Ty, Func, Args, Bundles, NameStr); } -// Note: if you get compile errors about private methods then -// please update your code to use the high-level operand -// interfaces. See line 943 above. -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CallInst, Value) - //===----------------------------------------------------------------------===// // SelectInst Class //===----------------------------------------------------------------------===// @@ -2263,7 +2430,7 @@ public: /// Return the shuffle mask value for the specified element of the mask. /// Return -1 if the element is undef. - static int getMaskValue(Constant *Mask, unsigned Elt); + static int getMaskValue(const Constant *Mask, unsigned Elt); /// Return the shuffle mask value of this instruction for the given element /// index. Return -1 if the element is undef. @@ -2273,7 +2440,8 @@ public: /// Convert the input shuffle mask operand to a vector of integers. Undefined /// elements of the mask are returned as -1. - static void getShuffleMask(Constant *Mask, SmallVectorImpl<int> &Result); + static void getShuffleMask(const Constant *Mask, + SmallVectorImpl<int> &Result); /// Return the mask for this instruction as a vector of integers. Undefined /// elements of the mask are returned as -1. @@ -2287,6 +2455,176 @@ public: return Mask; } + /// Return true if this shuffle returns a vector with a different number of + /// elements than its source elements. + /// Example: shufflevector <4 x n> A, <4 x n> B, <1,2> + bool changesLength() const { + unsigned NumSourceElts = Op<0>()->getType()->getVectorNumElements(); + unsigned NumMaskElts = getMask()->getType()->getVectorNumElements(); + return NumSourceElts != NumMaskElts; + } + + /// Return true if this shuffle mask chooses elements from exactly one source + /// vector. + /// Example: <7,5,undef,7> + /// This assumes that vector operands are the same length as the mask. + static bool isSingleSourceMask(ArrayRef<int> Mask); + static bool isSingleSourceMask(const Constant *Mask) { + assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); + SmallVector<int, 16> MaskAsInts; + getShuffleMask(Mask, MaskAsInts); + return isSingleSourceMask(MaskAsInts); + } + + /// Return true if this shuffle chooses elements from exactly one source + /// vector without changing the length of that vector. + /// Example: shufflevector <4 x n> A, <4 x n> B, <3,0,undef,3> + /// TODO: Optionally allow length-changing shuffles. + bool isSingleSource() const { + return !changesLength() && isSingleSourceMask(getMask()); + } + + /// Return true if this shuffle mask chooses elements from exactly one source + /// vector without lane crossings. A shuffle using this mask is not + /// necessarily a no-op because it may change the number of elements from its + /// input vectors or it may provide demanded bits knowledge via undef lanes. + /// Example: <undef,undef,2,3> + static bool isIdentityMask(ArrayRef<int> Mask); + static bool isIdentityMask(const Constant *Mask) { + assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); + SmallVector<int, 16> MaskAsInts; + getShuffleMask(Mask, MaskAsInts); + return isIdentityMask(MaskAsInts); + } + + /// Return true if this shuffle mask chooses elements from exactly one source + /// vector without lane crossings and does not change the number of elements + /// from its input vectors. + /// Example: shufflevector <4 x n> A, <4 x n> B, <4,undef,6,undef> + /// TODO: Optionally allow length-changing shuffles. + bool isIdentity() const { + return !changesLength() && isIdentityMask(getShuffleMask()); + } + + /// Return true if this shuffle mask chooses elements from its source vectors + /// without lane crossings. A shuffle using this mask would be + /// equivalent to a vector select with a constant condition operand. + /// Example: <4,1,6,undef> + /// This returns false if the mask does not choose from both input vectors. + /// In that case, the shuffle is better classified as an identity shuffle. + /// This assumes that vector operands are the same length as the mask + /// (a length-changing shuffle can never be equivalent to a vector select). + static bool isSelectMask(ArrayRef<int> Mask); + static bool isSelectMask(const Constant *Mask) { + assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); + SmallVector<int, 16> MaskAsInts; + getShuffleMask(Mask, MaskAsInts); + return isSelectMask(MaskAsInts); + } + + /// Return true if this shuffle chooses elements from its source vectors + /// without lane crossings and all operands have the same number of elements. + /// In other words, this shuffle is equivalent to a vector select with a + /// constant condition operand. + /// Example: shufflevector <4 x n> A, <4 x n> B, <undef,1,6,3> + /// This returns false if the mask does not choose from both input vectors. + /// In that case, the shuffle is better classified as an identity shuffle. + /// TODO: Optionally allow length-changing shuffles. + bool isSelect() const { + return !changesLength() && isSelectMask(getMask()); + } + + /// Return true if this shuffle mask swaps the order of elements from exactly + /// one source vector. + /// Example: <7,6,undef,4> + /// This assumes that vector operands are the same length as the mask. + static bool isReverseMask(ArrayRef<int> Mask); + static bool isReverseMask(const Constant *Mask) { + assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); + SmallVector<int, 16> MaskAsInts; + getShuffleMask(Mask, MaskAsInts); + return isReverseMask(MaskAsInts); + } + + /// Return true if this shuffle swaps the order of elements from exactly + /// one source vector. + /// Example: shufflevector <4 x n> A, <4 x n> B, <3,undef,1,undef> + /// TODO: Optionally allow length-changing shuffles. + bool isReverse() const { + return !changesLength() && isReverseMask(getMask()); + } + + /// Return true if this shuffle mask chooses all elements with the same value + /// as the first element of exactly one source vector. + /// Example: <4,undef,undef,4> + /// This assumes that vector operands are the same length as the mask. + static bool isZeroEltSplatMask(ArrayRef<int> Mask); + static bool isZeroEltSplatMask(const Constant *Mask) { + assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); + SmallVector<int, 16> MaskAsInts; + getShuffleMask(Mask, MaskAsInts); + return isZeroEltSplatMask(MaskAsInts); + } + + /// Return true if all elements of this shuffle are the same value as the + /// first element of exactly one source vector without changing the length + /// of that vector. + /// Example: shufflevector <4 x n> A, <4 x n> B, <undef,0,undef,0> + /// TODO: Optionally allow length-changing shuffles. + /// TODO: Optionally allow splats from other elements. + bool isZeroEltSplat() const { + return !changesLength() && isZeroEltSplatMask(getMask()); + } + + /// Return true if this shuffle mask is a transpose mask. + /// Transpose vector masks transpose a 2xn matrix. They read corresponding + /// even- or odd-numbered vector elements from two n-dimensional source + /// vectors and write each result into consecutive elements of an + /// n-dimensional destination vector. Two shuffles are necessary to complete + /// the transpose, one for the even elements and another for the odd elements. + /// This description closely follows how the TRN1 and TRN2 AArch64 + /// instructions operate. + /// + /// For example, a simple 2x2 matrix can be transposed with: + /// + /// ; Original matrix + /// m0 = < a, b > + /// m1 = < c, d > + /// + /// ; Transposed matrix + /// t0 = < a, c > = shufflevector m0, m1, < 0, 2 > + /// t1 = < b, d > = shufflevector m0, m1, < 1, 3 > + /// + /// For matrices having greater than n columns, the resulting nx2 transposed + /// matrix is stored in two result vectors such that one vector contains + /// interleaved elements from all the even-numbered rows and the other vector + /// contains interleaved elements from all the odd-numbered rows. For example, + /// a 2x4 matrix can be transposed with: + /// + /// ; Original matrix + /// m0 = < a, b, c, d > + /// m1 = < e, f, g, h > + /// + /// ; Transposed matrix + /// t0 = < a, e, c, g > = shufflevector m0, m1 < 0, 4, 2, 6 > + /// t1 = < b, f, d, h > = shufflevector m0, m1 < 1, 5, 3, 7 > + static bool isTransposeMask(ArrayRef<int> Mask); + static bool isTransposeMask(const Constant *Mask) { + assert(Mask->getType()->isVectorTy() && "Shuffle needs vector constant."); + SmallVector<int, 16> MaskAsInts; + getShuffleMask(Mask, MaskAsInts); + return isTransposeMask(MaskAsInts); + } + + /// Return true if this shuffle transposes the elements of its inputs without + /// changing the length of the vectors. This operation may also be known as a + /// merge or interleave. See the description for isTransposeMask() for the + /// exact specification. + /// Example: shufflevector <4 x n> A, <4 x n> B, <0,4,2,6> + bool isTranspose() const { + return !changesLength() && isTransposeMask(getMask()); + } + /// Change values in a shuffle permute mask assuming the two vector operands /// of length InVecNumElts have swapped position. static void commuteShuffleMask(MutableArrayRef<int> Mask, @@ -3547,13 +3885,9 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) /// Invoke instruction. The SubclassData field is used to hold the /// calling convention of the call. /// -class InvokeInst : public TerminatorInst, - public OperandBundleUser<InvokeInst, User::op_iterator> { +class InvokeInst : public CallBase<InvokeInst> { friend class OperandBundleUser<InvokeInst, User::op_iterator>; - AttributeList Attrs; - FunctionType *FTy; - InvokeInst(const InvokeInst &BI); /// Construct an InvokeInst given a range of arguments. @@ -3580,7 +3914,6 @@ class InvokeInst : public TerminatorInst, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd); - bool hasDescriptor() const { return HasDescriptor; } void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles, @@ -3601,6 +3934,7 @@ protected: InvokeInst *cloneImpl() const; public: + static constexpr int ArgOffset = 3; static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, const Twine &NameStr, @@ -3674,299 +4008,15 @@ public: static InvokeInst *Create(InvokeInst *II, ArrayRef<OperandBundleDef> Bundles, Instruction *InsertPt = nullptr); - /// Provide fast operand accessors - DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - - FunctionType *getFunctionType() const { return FTy; } - - void mutateFunctionType(FunctionType *FTy) { - mutateType(FTy->getReturnType()); - this->FTy = FTy; - } - - /// Return the number of invoke arguments. - /// - unsigned getNumArgOperands() const { - return getNumOperands() - getNumTotalBundleOperands() - 3; - } - - /// getArgOperand/setArgOperand - Return/set the i-th invoke argument. - /// - Value *getArgOperand(unsigned i) const { - assert(i < getNumArgOperands() && "Out of bounds!"); - return getOperand(i); - } - void setArgOperand(unsigned i, Value *v) { - assert(i < getNumArgOperands() && "Out of bounds!"); - setOperand(i, v); - } - - /// Return the iterator pointing to the beginning of the argument list. - op_iterator arg_begin() { return op_begin(); } - - /// Return the iterator pointing to the end of the argument list. - op_iterator arg_end() { - // [ invoke args ], [ operand bundles ], normal dest, unwind dest, callee - return op_end() - getNumTotalBundleOperands() - 3; - } - - /// Iteration adapter for range-for loops. - iterator_range<op_iterator> arg_operands() { - return make_range(arg_begin(), arg_end()); - } - - /// Return the iterator pointing to the beginning of the argument list. - const_op_iterator arg_begin() const { return op_begin(); } - - /// Return the iterator pointing to the end of the argument list. - const_op_iterator arg_end() const { - // [ invoke args ], [ operand bundles ], normal dest, unwind dest, callee - return op_end() - getNumTotalBundleOperands() - 3; - } - - /// Iteration adapter for range-for loops. - iterator_range<const_op_iterator> arg_operands() const { - return make_range(arg_begin(), arg_end()); - } - - /// Wrappers for getting the \c Use of a invoke argument. - const Use &getArgOperandUse(unsigned i) const { - assert(i < getNumArgOperands() && "Out of bounds!"); - return getOperandUse(i); - } - Use &getArgOperandUse(unsigned i) { - assert(i < getNumArgOperands() && "Out of bounds!"); - return getOperandUse(i); - } - - /// If one of the arguments has the 'returned' attribute, return its - /// operand value. Otherwise, return nullptr. - Value *getReturnedArgOperand() const; - - /// getCallingConv/setCallingConv - Get or set the calling convention of this - /// function call. - CallingConv::ID getCallingConv() const { - return static_cast<CallingConv::ID>(getSubclassDataFromInstruction()); - } - void setCallingConv(CallingConv::ID CC) { - auto ID = static_cast<unsigned>(CC); - assert(!(ID & ~CallingConv::MaxID) && "Unsupported calling convention"); - setInstructionSubclassData(ID); - } - - /// Return the parameter attributes for this invoke. - /// - AttributeList getAttributes() const { return Attrs; } - - /// Set the parameter attributes for this invoke. - /// - void setAttributes(AttributeList A) { Attrs = A; } - - /// adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attribute::AttrKind Kind); - - /// adds the attribute to the list of attributes. - void addAttribute(unsigned i, Attribute Attr); - - /// Adds the attribute to the indicated argument - void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); - - /// removes the attribute from the list of attributes. - void removeAttribute(unsigned i, Attribute::AttrKind Kind); - - /// removes the attribute from the list of attributes. - void removeAttribute(unsigned i, StringRef Kind); - - /// Removes the attribute from the given argument - void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind); - - /// adds the dereferenceable attribute to the list of attributes. - void addDereferenceableAttr(unsigned i, uint64_t Bytes); - - /// adds the dereferenceable_or_null attribute to the list of - /// attributes. - void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); - - /// Determine whether this call has the given attribute. - bool hasFnAttr(Attribute::AttrKind Kind) const { - assert(Kind != Attribute::NoBuiltin && - "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); - return hasFnAttrImpl(Kind); - } - - /// Determine whether this call has the given attribute. - bool hasFnAttr(StringRef Kind) const { - return hasFnAttrImpl(Kind); - } - - /// Determine whether the return value has the given attribute. - bool hasRetAttr(Attribute::AttrKind Kind) const; - - /// Determine whether the argument or parameter has the given attribute. - bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const; - - /// Get the attribute of a given kind at a position. - Attribute getAttribute(unsigned i, Attribute::AttrKind Kind) const { - return getAttributes().getAttribute(i, Kind); - } - - /// Get the attribute of a given kind at a position. - Attribute getAttribute(unsigned i, StringRef Kind) const { - return getAttributes().getAttribute(i, Kind); - } - - /// Return true if the data operand at index \p i has the attribute \p - /// A. - /// - /// Data operands include invoke arguments and values used in operand bundles, - /// but does not include the invokee operand, or the two successor blocks. - /// This routine dispatches to the underlying AttributeList or the - /// OperandBundleUser as appropriate. - /// - /// The index \p i is interpreted as - /// - /// \p i == Attribute::ReturnIndex -> the return value - /// \p i in [1, arg_size + 1) -> argument number (\p i - 1) - /// \p i in [arg_size + 1, data_operand_size + 1) -> bundle operand at index - /// (\p i - 1) in the operand list. - bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const; - - /// Extract the alignment of the return value. - unsigned getRetAlignment() const { return Attrs.getRetAlignment(); } - - /// Extract the alignment for a call or parameter (0=unknown). - unsigned getParamAlignment(unsigned ArgNo) const { - return Attrs.getParamAlignment(ArgNo); - } - - /// Extract the number of dereferenceable bytes for a call or - /// parameter (0=unknown). - uint64_t getDereferenceableBytes(unsigned i) const { - return Attrs.getDereferenceableBytes(i); - } - - /// Extract the number of dereferenceable_or_null bytes for a call or - /// parameter (0=unknown). - uint64_t getDereferenceableOrNullBytes(unsigned i) const { - return Attrs.getDereferenceableOrNullBytes(i); - } - - /// @brief Determine if the return value is marked with NoAlias attribute. - bool returnDoesNotAlias() const { - return Attrs.hasAttribute(AttributeList::ReturnIndex, Attribute::NoAlias); - } - - /// Return true if the call should not be treated as a call to a - /// builtin. - bool isNoBuiltin() const { - // We assert in hasFnAttr if one passes in Attribute::NoBuiltin, so we have - // to check it by hand. - return hasFnAttrImpl(Attribute::NoBuiltin) && - !hasFnAttrImpl(Attribute::Builtin); - } - - /// Determine if the call requires strict floating point semantics. - bool isStrictFP() const { return hasFnAttr(Attribute::StrictFP); } - - /// Return true if the call should not be inlined. - bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } - void setIsNoInline() { - addAttribute(AttributeList::FunctionIndex, Attribute::NoInline); - } - - /// Determine if the call does not access memory. - bool doesNotAccessMemory() const { - return hasFnAttr(Attribute::ReadNone); - } - void setDoesNotAccessMemory() { - addAttribute(AttributeList::FunctionIndex, Attribute::ReadNone); - } - - /// Determine if the call does not access or only reads memory. - bool onlyReadsMemory() const { - return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); - } - void setOnlyReadsMemory() { - addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly); - } - - /// Determine if the call does not access or only writes memory. - bool doesNotReadMemory() const { - return doesNotAccessMemory() || hasFnAttr(Attribute::WriteOnly); - } - void setDoesNotReadMemory() { - addAttribute(AttributeList::FunctionIndex, Attribute::WriteOnly); - } - - /// @brief Determine if the call access memmory only using it's pointer - /// arguments. - bool onlyAccessesArgMemory() const { - return hasFnAttr(Attribute::ArgMemOnly); - } - void setOnlyAccessesArgMemory() { - addAttribute(AttributeList::FunctionIndex, Attribute::ArgMemOnly); - } - - /// @brief Determine if the function may only access memory that is - /// inaccessible from the IR. - bool onlyAccessesInaccessibleMemory() const { - return hasFnAttr(Attribute::InaccessibleMemOnly); - } - void setOnlyAccessesInaccessibleMemory() { - addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOnly); - } - - /// @brief Determine if the function may only access memory that is - /// either inaccessible from the IR or pointed to by its arguments. - bool onlyAccessesInaccessibleMemOrArgMem() const { - return hasFnAttr(Attribute::InaccessibleMemOrArgMemOnly); - } - void setOnlyAccessesInaccessibleMemOrArgMem() { - addAttribute(AttributeList::FunctionIndex, Attribute::InaccessibleMemOrArgMemOnly); - } - - /// Determine if the call cannot return. - bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } - void setDoesNotReturn() { - addAttribute(AttributeList::FunctionIndex, Attribute::NoReturn); - } + /// Determine if the call should not perform indirect branch tracking. + bool doesNoCfCheck() const { return hasFnAttr(Attribute::NoCfCheck); } /// Determine if the call cannot unwind. bool doesNotThrow() const { return hasFnAttr(Attribute::NoUnwind); } void setDoesNotThrow() { addAttribute(AttributeList::FunctionIndex, Attribute::NoUnwind); } - - /// Determine if the invoke cannot be duplicated. - bool cannotDuplicate() const {return hasFnAttr(Attribute::NoDuplicate); } - void setCannotDuplicate() { - addAttribute(AttributeList::FunctionIndex, Attribute::NoDuplicate); - } - - /// Determine if the invoke is convergent - bool isConvergent() const { return hasFnAttr(Attribute::Convergent); } - void setConvergent() { - addAttribute(AttributeList::FunctionIndex, Attribute::Convergent); - } - void setNotConvergent() { - removeAttribute(AttributeList::FunctionIndex, Attribute::Convergent); - } - - /// Determine if the call returns a structure through first - /// pointer argument. - bool hasStructRetAttr() const { - if (getNumArgOperands() == 0) - return false; - - // Be friendly and also check the callee. - return paramHasAttr(0, Attribute::StructRet); - } - - /// Determine if any call argument is an aggregate passed by value. - bool hasByValArgument() const { - return Attrs.hasAttrSomewhere(Attribute::ByVal); - } - + /// Return the function called, or null if this is an /// indirect function invocation. /// @@ -4031,20 +4081,6 @@ public: } private: - template <typename AttrKind> bool hasFnAttrImpl(AttrKind Kind) const { - if (Attrs.hasAttribute(AttributeList::FunctionIndex, Kind)) - return true; - - // Operand bundles override attributes on the called function, but don't - // override attributes directly present on the invoke instruction. - if (isFnAttrDisallowedByOpBundle(Kind)) - return false; - - if (const Function *F = getCalledFunction()) - return F->getAttributes().hasAttribute(AttributeList::FunctionIndex, - Kind); - return false; - } // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -4054,16 +4090,17 @@ private: }; template <> -struct OperandTraits<InvokeInst> : public VariadicOperandTraits<InvokeInst, 3> { -}; +struct OperandTraits<CallBase<InvokeInst>> + : public VariadicOperandTraits<CallBase<InvokeInst>, 3> {}; InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles, unsigned Values, const Twine &NameStr, Instruction *InsertBefore) - : TerminatorInst(Ty->getReturnType(), Instruction::Invoke, - OperandTraits<InvokeInst>::op_end(this) - Values, Values, - InsertBefore) { + : CallBase<InvokeInst>(Ty->getReturnType(), Instruction::Invoke, + OperandTraits<CallBase<InvokeInst>>::op_end(this) - + Values, + Values, InsertBefore) { init(Ty, Func, IfNormal, IfException, Args, Bundles, NameStr); } @@ -4071,15 +4108,16 @@ InvokeInst::InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef<Value *> Args, ArrayRef<OperandBundleDef> Bundles, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd) - : TerminatorInst( - cast<FunctionType>(cast<PointerType>(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Invoke, OperandTraits<InvokeInst>::op_end(this) - Values, - Values, InsertAtEnd) { + : CallBase<InvokeInst>( + cast<FunctionType>( + cast<PointerType>(Func->getType())->getElementType()) + ->getReturnType(), + Instruction::Invoke, + OperandTraits<CallBase<InvokeInst>>::op_end(this) - Values, Values, + InsertAtEnd) { init(Func, IfNormal, IfException, Args, Bundles, NameStr); } -DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InvokeInst, Value) //===----------------------------------------------------------------------===// // ResumeInst Class @@ -5190,6 +5228,26 @@ public: } }; +/// A helper function that returns the pointer operand of a load or store +/// instruction. Returns nullptr if not load or store. +inline Value *getLoadStorePointerOperand(Value *V) { + if (auto *Load = dyn_cast<LoadInst>(V)) + return Load->getPointerOperand(); + if (auto *Store = dyn_cast<StoreInst>(V)) + return Store->getPointerOperand(); + return nullptr; +} + +/// A helper function that returns the pointer operand of a load, store +/// or GEP instruction. Returns nullptr if not load, store, or GEP. +inline Value *getPointerOperand(Value *V) { + if (auto *Ptr = getLoadStorePointerOperand(V)) + return Ptr; + if (auto *Gep = dyn_cast<GetElementPtrInst>(V)) + return Gep->getPointerOperand(); + return nullptr; +} + } // end namespace llvm #endif // LLVM_IR_INSTRUCTIONS_H diff --git a/contrib/llvm/include/llvm/IR/IntrinsicInst.h b/contrib/llvm/include/llvm/IR/IntrinsicInst.h index 2ca0a24cbae1..6650afcca7fb 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicInst.h +++ b/contrib/llvm/include/llvm/IR/IntrinsicInst.h @@ -93,6 +93,10 @@ namespace llvm { return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); } + /// Get the size (in bits) of the variable, or fragment of the variable that + /// is described. + Optional<uint64_t> getFragmentSizeInBits() const; + /// \name Casting methods /// @{ static bool classof(const IntrinsicInst *I) { @@ -100,6 +104,7 @@ namespace llvm { case Intrinsic::dbg_declare: case Intrinsic::dbg_value: case Intrinsic::dbg_addr: + case Intrinsic::dbg_label: return true; default: return false; } @@ -159,6 +164,32 @@ namespace llvm { /// @} }; + /// This represents the llvm.dbg.label instruction. + class DbgLabelInst : public DbgInfoIntrinsic { + public: + DILabel *getLabel() const { + return cast<DILabel>(getRawVariable()); + } + + Metadata *getRawVariable() const { + return cast<MetadataAsValue>(getArgOperand(0))->getMetadata(); + } + + Metadata *getRawExpression() const { + return nullptr; + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// @{ + static bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_label; + } + static bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + /// @} + }; + /// This is the common base class for constrained floating point intrinsics. class ConstrainedFPIntrinsic : public IntrinsicInst { public: @@ -243,6 +274,8 @@ namespace llvm { return cast<PointerType>(getRawDest()->getType())->getAddressSpace(); } + unsigned getDestAlignment() const { return getParamAlignment(ARG_DEST); } + /// Set the specified arguments of the instruction. void setDest(Value *Ptr) { assert(getRawDest()->getType() == Ptr->getType() && @@ -250,6 +283,13 @@ namespace llvm { setArgOperand(ARG_DEST, Ptr); } + void setDestAlignment(unsigned Align) { + removeParamAttr(ARG_DEST, Attribute::Alignment); + if (Align > 0) + addParamAttr(ARG_DEST, + Attribute::getWithAlignment(getContext(), Align)); + } + void setLength(Value *L) { assert(getLength()->getType() == L->getType() && "setLength called with value of wrong type!"); @@ -257,6 +297,71 @@ namespace llvm { } }; + /// Common base class for all memory transfer intrinsics. Simply provides + /// common methods. + template <class BaseCL> class MemTransferBase : public BaseCL { + private: + enum { ARG_SOURCE = 1 }; + + public: + /// Return the arguments to the instruction. + Value *getRawSource() const { + return const_cast<Value *>(BaseCL::getArgOperand(ARG_SOURCE)); + } + const Use &getRawSourceUse() const { + return BaseCL::getArgOperandUse(ARG_SOURCE); + } + Use &getRawSourceUse() { return BaseCL::getArgOperandUse(ARG_SOURCE); } + + /// This is just like getRawSource, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getSource() const { return getRawSource()->stripPointerCasts(); } + + unsigned getSourceAddressSpace() const { + return cast<PointerType>(getRawSource()->getType())->getAddressSpace(); + } + + unsigned getSourceAlignment() const { + return BaseCL::getParamAlignment(ARG_SOURCE); + } + + void setSource(Value *Ptr) { + assert(getRawSource()->getType() == Ptr->getType() && + "setSource called with pointer of wrong type!"); + BaseCL::setArgOperand(ARG_SOURCE, Ptr); + } + + void setSourceAlignment(unsigned Align) { + BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment); + if (Align > 0) + BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment( + BaseCL::getContext(), Align)); + } + }; + + /// Common base class for all memset intrinsics. Simply provides + /// common methods. + template <class BaseCL> class MemSetBase : public BaseCL { + private: + enum { ARG_VALUE = 1 }; + + public: + Value *getValue() const { + return const_cast<Value *>(BaseCL::getArgOperand(ARG_VALUE)); + } + const Use &getValueUse() const { + return BaseCL::getArgOperandUse(ARG_VALUE); + } + Use &getValueUse() { return BaseCL::getArgOperandUse(ARG_VALUE); } + + void setValue(Value *Val) { + assert(getValue()->getType() == Val->getType() && + "setValue called with value of wrong type!"); + BaseCL::setArgOperand(ARG_VALUE, Val); + } + }; + // The common base class for the atomic memset/memmove/memcpy intrinsics // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove class AtomicMemIntrinsic : public MemIntrinsicBase<AtomicMemIntrinsic> { @@ -299,23 +404,8 @@ namespace llvm { /// This class represents atomic memset intrinsic // i.e. llvm.element.unordered.atomic.memset - class AtomicMemSetInst : public AtomicMemIntrinsic { - private: - enum { ARG_VALUE = 1 }; - + class AtomicMemSetInst : public MemSetBase<AtomicMemIntrinsic> { public: - Value *getValue() const { - return const_cast<Value *>(getArgOperand(ARG_VALUE)); - } - const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); } - Use &getValueUse() { return getArgOperandUse(ARG_VALUE); } - - void setValue(Value *Val) { - assert(getValue()->getType() == Val->getType() && - "setValue called with value of wrong type!"); - setArgOperand(ARG_VALUE, Val); - } - static bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic; } @@ -326,33 +416,8 @@ namespace llvm { // This class wraps the atomic memcpy/memmove intrinsics // i.e. llvm.element.unordered.atomic.memcpy/memmove - class AtomicMemTransferInst : public AtomicMemIntrinsic { - private: - enum { ARG_SOURCE = 1 }; - + class AtomicMemTransferInst : public MemTransferBase<AtomicMemIntrinsic> { public: - /// Return the arguments to the instruction. - Value *getRawSource() const { - return const_cast<Value *>(getArgOperand(ARG_SOURCE)); - } - const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); } - Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); } - - /// This is just like getRawSource, but it strips off any cast - /// instructions that feed it, giving the original input. The returned - /// value is guaranteed to be a pointer. - Value *getSource() const { return getRawSource()->stripPointerCasts(); } - - unsigned getSourceAddressSpace() const { - return cast<PointerType>(getRawSource()->getType())->getAddressSpace(); - } - - void setSource(Value *Ptr) { - assert(getRawSource()->getType() == Ptr->getType() && - "setSource called with pointer of wrong type!"); - setArgOperand(ARG_SOURCE, Ptr); - } - static bool classof(const IntrinsicInst *I) { switch (I->getIntrinsicID()) { case Intrinsic::memcpy_element_unordered_atomic: @@ -394,17 +459,9 @@ namespace llvm { /// This is the common base class for memset/memcpy/memmove. class MemIntrinsic : public MemIntrinsicBase<MemIntrinsic> { private: - enum { ARG_ALIGN = 3, ARG_VOLATILE = 4 }; + enum { ARG_VOLATILE = 3 }; public: - ConstantInt *getAlignmentCst() const { - return cast<ConstantInt>(const_cast<Value *>(getArgOperand(ARG_ALIGN))); - } - - unsigned getAlignment() const { - return getAlignmentCst()->getZExtValue(); - } - ConstantInt *getVolatileCst() const { return cast<ConstantInt>( const_cast<Value *>(getArgOperand(ARG_VOLATILE))); @@ -414,14 +471,8 @@ namespace llvm { return !getVolatileCst()->isZero(); } - void setAlignment(Constant *A) { setArgOperand(ARG_ALIGN, A); } - void setVolatile(Constant *V) { setArgOperand(ARG_VOLATILE, V); } - Type *getAlignmentType() const { - return getArgOperand(ARG_ALIGN)->getType(); - } - // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const IntrinsicInst *I) { switch (I->getIntrinsicID()) { @@ -438,19 +489,8 @@ namespace llvm { }; /// This class wraps the llvm.memset intrinsic. - class MemSetInst : public MemIntrinsic { + class MemSetInst : public MemSetBase<MemIntrinsic> { public: - /// 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() && - "setValue called with value of wrong type!"); - setArgOperand(1, Val); - } - // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::memset; @@ -461,28 +501,8 @@ namespace llvm { }; /// This class wraps the llvm.memcpy/memmove intrinsics. - class MemTransferInst : public MemIntrinsic { + class MemTransferInst : public MemTransferBase<MemIntrinsic> { public: - /// 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); } - - /// This is just like getRawSource, but it strips off any cast - /// instructions that feed it, giving the original input. The returned - /// value is guaranteed to be a pointer. - Value *getSource() const { return getRawSource()->stripPointerCasts(); } - - unsigned getSourceAddressSpace() const { - return cast<PointerType>(getRawSource()->getType())->getAddressSpace(); - } - - void setSource(Value *Ptr) { - assert(getRawSource()->getType() == Ptr->getType() && - "setSource called with pointer of wrong type!"); - setArgOperand(1, Ptr); - } - // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const IntrinsicInst *I) { return I->getIntrinsicID() == Intrinsic::memcpy || @@ -551,23 +571,8 @@ namespace llvm { /// This class represents any memset intrinsic // i.e. llvm.element.unordered.atomic.memset // and llvm.memset - class AnyMemSetInst : public AnyMemIntrinsic { - private: - enum { ARG_VALUE = 1 }; - + class AnyMemSetInst : public MemSetBase<AnyMemIntrinsic> { public: - Value *getValue() const { - return const_cast<Value *>(getArgOperand(ARG_VALUE)); - } - const Use &getValueUse() const { return getArgOperandUse(ARG_VALUE); } - Use &getValueUse() { return getArgOperandUse(ARG_VALUE); } - - void setValue(Value *Val) { - assert(getValue()->getType() == Val->getType() && - "setValue called with value of wrong type!"); - setArgOperand(ARG_VALUE, Val); - } - static bool classof(const IntrinsicInst *I) { switch (I->getIntrinsicID()) { case Intrinsic::memset: @@ -585,33 +590,8 @@ namespace llvm { // This class wraps any memcpy/memmove intrinsics // i.e. llvm.element.unordered.atomic.memcpy/memmove // and llvm.memcpy/memmove - class AnyMemTransferInst : public AnyMemIntrinsic { - private: - enum { ARG_SOURCE = 1 }; - + class AnyMemTransferInst : public MemTransferBase<AnyMemIntrinsic> { public: - /// Return the arguments to the instruction. - Value *getRawSource() const { - return const_cast<Value *>(getArgOperand(ARG_SOURCE)); - } - const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); } - Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); } - - /// This is just like getRawSource, but it strips off any cast - /// instructions that feed it, giving the original input. The returned - /// value is guaranteed to be a pointer. - Value *getSource() const { return getRawSource()->stripPointerCasts(); } - - unsigned getSourceAddressSpace() const { - return cast<PointerType>(getRawSource()->getType())->getAddressSpace(); - } - - void setSource(Value *Ptr) { - assert(getRawSource()->getType() == Ptr->getType() && - "setSource called with pointer of wrong type!"); - setArgOperand(ARG_SOURCE, Ptr); - } - static bool classof(const IntrinsicInst *I) { switch (I->getIntrinsicID()) { case Intrinsic::memcpy: diff --git a/contrib/llvm/include/llvm/IR/Intrinsics.h b/contrib/llvm/include/llvm/IR/Intrinsics.h index fc79da7ae0e6..e1e17f983ff8 100644 --- a/contrib/llvm/include/llvm/IR/Intrinsics.h +++ b/contrib/llvm/include/llvm/IR/Intrinsics.h @@ -39,7 +39,7 @@ namespace Intrinsic { // Get the intrinsic enums generated from Intrinsics.td #define GET_INTRINSIC_ENUM_VALUES -#include "llvm/IR/Intrinsics.gen" +#include "llvm/IR/IntrinsicEnums.inc" #undef GET_INTRINSIC_ENUM_VALUES , num_intrinsics }; @@ -97,7 +97,7 @@ namespace Intrinsic { /// intrinsic. This is returned by getIntrinsicInfoTableEntries. struct IITDescriptor { enum IITDescriptorKind { - Void, VarArg, MMX, Token, Metadata, Half, Float, Double, + Void, VarArg, MMX, Token, Metadata, Half, Float, Double, Quad, Integer, Vector, Pointer, Struct, Argument, ExtendArgument, TruncArgument, HalfVecArgument, SameVecWidthArgument, PtrToArgument, PtrToElt, VecOfAnyPtrsToElt diff --git a/contrib/llvm/include/llvm/IR/Intrinsics.td b/contrib/llvm/include/llvm/IR/Intrinsics.td index a2a1f26292ce..64455573ff19 100644 --- a/contrib/llvm/include/llvm/IR/Intrinsics.td +++ b/contrib/llvm/include/llvm/IR/Intrinsics.td @@ -117,6 +117,7 @@ def IntrHasSideEffects : IntrinsicProperty; class LLVMType<ValueType vt> { ValueType VT = vt; + int isAny = 0; } class LLVMQualPointerType<LLVMType elty, int addrspace> @@ -131,6 +132,8 @@ class LLVMPointerType<LLVMType elty> class LLVMAnyPointerType<LLVMType elty> : LLVMType<iPTRAny>{ LLVMType ElTy = elty; + + let isAny = 1; } // Match the type of another intrinsic parameter. Number is an index into the @@ -163,10 +166,12 @@ class LLVMVectorOfAnyPointersToElt<int num> : LLVMMatchType<num>; class LLVMHalfElementsVectorType<int num> : LLVMMatchType<num>; def llvm_void_ty : LLVMType<isVoid>; -def llvm_any_ty : LLVMType<Any>; -def llvm_anyint_ty : LLVMType<iAny>; -def llvm_anyfloat_ty : LLVMType<fAny>; -def llvm_anyvector_ty : LLVMType<vAny>; +let isAny = 1 in { + def llvm_any_ty : LLVMType<Any>; + def llvm_anyint_ty : LLVMType<iAny>; + def llvm_anyfloat_ty : LLVMType<fAny>; + def llvm_anyvector_ty : LLVMType<vAny>; +} def llvm_i1_ty : LLVMType<i1>; def llvm_i8_ty : LLVMType<i8>; def llvm_i16_ty : LLVMType<i16>; @@ -249,7 +254,6 @@ def llvm_v8f64_ty : LLVMType<v8f64>; // 8 x double def llvm_vararg_ty : LLVMType<isVoid>; // this means vararg here - //===----------------------------------------------------------------------===// // Intrinsic Definitions. //===----------------------------------------------------------------------===// @@ -390,17 +394,17 @@ def int_instrprof_value_profile : Intrinsic<[], def int_memcpy : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, - llvm_i32_ty, llvm_i1_ty], + llvm_i1_ty], [IntrArgMemOnly, NoCapture<0>, NoCapture<1>, WriteOnly<0>, ReadOnly<1>]>; def int_memmove : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, - llvm_i32_ty, llvm_i1_ty], + llvm_i1_ty], [IntrArgMemOnly, NoCapture<0>, NoCapture<1>, ReadOnly<1>]>; def int_memset : Intrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, - llvm_i32_ty, llvm_i1_ty], + llvm_i1_ty], [IntrArgMemOnly, NoCapture<0>, WriteOnly<0>]>; // FIXME: Add version of these floating point intrinsics which allow non-default @@ -573,6 +577,10 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_ctlz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; def int_cttz : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; def int_bitreverse : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; + def int_fshl : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; + def int_fshr : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; } //===------------------------ Debugger Intrinsics -------------------------===// @@ -595,6 +603,8 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in { [llvm_metadata_ty, llvm_metadata_ty, llvm_metadata_ty]>; + def int_dbg_label : Intrinsic<[], + [llvm_metadata_ty]>; } //===------------------ Exception Handling Intrinsics----------------------===// @@ -706,16 +716,26 @@ def int_invariant_end : Intrinsic<[], llvm_anyptr_ty], [IntrArgMemOnly, NoCapture<2>]>; -// invariant.group.barrier can't be marked with 'readnone' (IntrNoMem), +// launder.invariant.group can't be marked with 'readnone' (IntrNoMem), // because it would cause CSE of two barriers with the same argument. -// Readonly and argmemonly says that barrier only reads its argument and -// it can be CSE only if memory didn't change between 2 barriers call, -// which is valid. +// Inaccessiblememonly says that the barrier doesn't read the argument, +// but it changes state not accessible to this module. This way +// we can DSE through the barrier because it doesn't read the value +// after store. Although the barrier doesn't modify any memory it +// can't be marked as readonly, because it would be possible to +// CSE 2 barriers with store in between. // The argument also can't be marked with 'returned' attribute, because // it would remove barrier. -def int_invariant_group_barrier : Intrinsic<[llvm_anyptr_ty], +// Note that it is still experimental, which means that its semantics +// might change in the future. +def int_launder_invariant_group : Intrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>], - [IntrReadMem, IntrArgMemOnly]>; + [IntrInaccessibleMemOnly, IntrSpeculatable]>; + + +def int_strip_invariant_group : Intrinsic<[llvm_anyptr_ty], + [LLVMMatchType<0>], + [IntrSpeculatable, IntrNoMem]>; //===------------------------ Stackmap Intrinsics -------------------------===// // @@ -768,6 +788,7 @@ def int_coro_free : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty], def int_coro_end : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_i1_ty], []>; def int_coro_frame : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; +def int_coro_noop : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; def int_coro_size : Intrinsic<[llvm_anyint_ty], [], [IntrNoMem]>; def int_coro_save : Intrinsic<[llvm_token_ty], [llvm_ptr_ty], []>; @@ -874,6 +895,10 @@ def int_type_checked_load : Intrinsic<[llvm_ptr_ty, llvm_i1_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_metadata_ty], [IntrNoMem]>; +// Create a branch funnel that implements an indirect call to a limited set of +// callees. This needs to be a musttail call. +def int_icall_branch_funnel : Intrinsic<[], [llvm_vararg_ty], []>; + def int_load_relative: Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_anyint_ty], [IntrReadMem, IntrArgMemOnly]>; @@ -883,6 +908,10 @@ def int_load_relative: Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_anyint_ty], // Takes a pointer to a string and the length of the string. def int_xray_customevent : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], [NoCapture<0>, ReadOnly<0>, IntrWriteMem]>; +// Typed event logging for x-ray. +// Takes a numeric type tag, a pointer to a string and the length of the string. +def int_xray_typedevent : Intrinsic<[], [llvm_i16_ty, llvm_ptr_ty, llvm_i32_ty], + [NoCapture<1>, ReadOnly<1>, IntrWriteMem]>; //===----------------------------------------------------------------------===// //===------ Memory intrinsics with element-wise atomicity guarantees ------===// diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td b/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td index 65c9aaab975d..688e863c1afe 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsAArch64.td @@ -146,6 +146,14 @@ let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". class AdvSIMD_CvtFPToFx_Intrinsic : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + + class AdvSIMD_1Arg_Intrinsic + : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrNoMem]>; + + class AdvSIMD_Dot_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, LLVMMatchType<1>], + [IntrNoMem]>; } // Arithmetic ops @@ -244,7 +252,7 @@ let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in { // Vector Max def int_aarch64_neon_smax : AdvSIMD_2VectorArg_Intrinsic; def int_aarch64_neon_umax : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_fmax : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_fmax : AdvSIMD_2FloatArg_Intrinsic; def int_aarch64_neon_fmaxnmp : AdvSIMD_2VectorArg_Intrinsic; // Vector Max Across Lanes @@ -256,7 +264,7 @@ let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in { // Vector Min def int_aarch64_neon_smin : AdvSIMD_2VectorArg_Intrinsic; def int_aarch64_neon_umin : AdvSIMD_2VectorArg_Intrinsic; - def int_aarch64_neon_fmin : AdvSIMD_2VectorArg_Intrinsic; + def int_aarch64_neon_fmin : AdvSIMD_2FloatArg_Intrinsic; def int_aarch64_neon_fminnmp : AdvSIMD_2VectorArg_Intrinsic; // Vector Min/Max Number @@ -354,7 +362,7 @@ let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in { def int_aarch64_neon_sqxtun : AdvSIMD_1VectorArg_Narrow_Intrinsic; // Vector Absolute Value - def int_aarch64_neon_abs : AdvSIMD_1IntArg_Intrinsic; + def int_aarch64_neon_abs : AdvSIMD_1Arg_Intrinsic; // Vector Saturating Absolute Value def int_aarch64_neon_sqabs : AdvSIMD_1IntArg_Intrinsic; @@ -412,6 +420,10 @@ let TargetPrefix = "aarch64", IntrProperties = [IntrNoMem] in { // Scalar FP Inexact Narrowing def int_aarch64_sisd_fcvtxn : Intrinsic<[llvm_float_ty], [llvm_double_ty], [IntrNoMem]>; + + // v8.2-A Dot Product + def int_aarch64_neon_udot : AdvSIMD_Dot_Intrinsic; + def int_aarch64_neon_sdot : AdvSIMD_Dot_Intrinsic; } let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". @@ -572,6 +584,14 @@ def int_aarch64_neon_tbx3 : AdvSIMD_Tbx3_Intrinsic; def int_aarch64_neon_tbx4 : AdvSIMD_Tbx4_Intrinsic; let TargetPrefix = "aarch64" in { + class FPCR_Get_Intrinsic + : Intrinsic<[llvm_i64_ty], [], [IntrNoMem]>; +} + +// FPCR +def int_aarch64_get_fpcr : FPCR_Get_Intrinsic; + +let TargetPrefix = "aarch64" in { class Crypto_AES_DataKey_Intrinsic : Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/contrib/llvm/include/llvm/IR/IntrinsicsAMDGPU.td index 3397fa41db1b..8555db01645f 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsAMDGPU.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsAMDGPU.td @@ -17,6 +17,13 @@ class AMDGPUReadPreloadRegisterIntrinsic class AMDGPUReadPreloadRegisterIntrinsicNamed<string name> : Intrinsic<[llvm_i32_ty], [], [IntrNoMem, IntrSpeculatable]>, GCCBuiltin<name>; +// Used to tag image and resource intrinsics with information used to generate +// mem operands. +class AMDGPURsrcIntrinsic<int rsrcarg, bit isimage = 0> { + int RsrcArg = rsrcarg; + bit IsImage = isimage; +} + let TargetPrefix = "r600" in { multiclass AMDGPUReadPreloadRegisterIntrinsic_xyz { @@ -69,6 +76,59 @@ def int_r600_cube : Intrinsic< [llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem, IntrSpeculatable] >; +def int_r600_store_stream_output : Intrinsic< + [], [llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [] +>; + +class TextureIntrinsicFloatInput : Intrinsic<[llvm_v4f32_ty], [ + llvm_v4f32_ty, // Coord + llvm_i32_ty, // offset_x + llvm_i32_ty, // offset_y, + llvm_i32_ty, // offset_z, + llvm_i32_ty, // resource_id + llvm_i32_ty, // samplerid + llvm_i32_ty, // coord_type_x + llvm_i32_ty, // coord_type_y + llvm_i32_ty, // coord_type_z + llvm_i32_ty], // coord_type_w + [IntrNoMem] +>; + +class TextureIntrinsicInt32Input : Intrinsic<[llvm_v4i32_ty], [ + llvm_v4i32_ty, // Coord + llvm_i32_ty, // offset_x + llvm_i32_ty, // offset_y, + llvm_i32_ty, // offset_z, + llvm_i32_ty, // resource_id + llvm_i32_ty, // samplerid + llvm_i32_ty, // coord_type_x + llvm_i32_ty, // coord_type_y + llvm_i32_ty, // coord_type_z + llvm_i32_ty], // coord_type_w + [IntrNoMem] +>; + +def int_r600_store_swizzle : + Intrinsic<[], [llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty], [] +>; + +def int_r600_tex : TextureIntrinsicFloatInput; +def int_r600_texc : TextureIntrinsicFloatInput; +def int_r600_txl : TextureIntrinsicFloatInput; +def int_r600_txlc : TextureIntrinsicFloatInput; +def int_r600_txb : TextureIntrinsicFloatInput; +def int_r600_txbc : TextureIntrinsicFloatInput; +def int_r600_txf : TextureIntrinsicInt32Input; +def int_r600_txq : TextureIntrinsicInt32Input; +def int_r600_ddx : TextureIntrinsicFloatInput; +def int_r600_ddy : TextureIntrinsicFloatInput; + +def int_r600_dot4 : Intrinsic<[llvm_float_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem, IntrSpeculatable] +>; + +def int_r600_kill : Intrinsic<[], [llvm_float_ty], []>; + } // End TargetPrefix = "r600" let TargetPrefix = "amdgcn" in { @@ -83,22 +143,22 @@ defm int_amdgcn_workgroup_id : AMDGPUReadPreloadRegisterIntrinsic_xyz_named def int_amdgcn_dispatch_ptr : GCCBuiltin<"__builtin_amdgcn_dispatch_ptr">, - Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [], + Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 4>], [], [IntrNoMem, IntrSpeculatable]>; def int_amdgcn_queue_ptr : GCCBuiltin<"__builtin_amdgcn_queue_ptr">, - Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [], + Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 4>], [], [IntrNoMem, IntrSpeculatable]>; def int_amdgcn_kernarg_segment_ptr : GCCBuiltin<"__builtin_amdgcn_kernarg_segment_ptr">, - Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [], + Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 4>], [], [IntrNoMem, IntrSpeculatable]>; def int_amdgcn_implicitarg_ptr : GCCBuiltin<"__builtin_amdgcn_implicitarg_ptr">, - Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [], + Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 4>], [], [IntrNoMem, IntrSpeculatable]>; def int_amdgcn_groupstaticsize : @@ -111,7 +171,7 @@ def int_amdgcn_dispatch_id : def int_amdgcn_implicit_buffer_ptr : GCCBuiltin<"__builtin_amdgcn_implicit_buffer_ptr">, - Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 2>], [], + Intrinsic<[LLVMQualPointerType<llvm_i8_ty, 4>], [], [IntrNoMem, IntrSpeculatable]>; // Set EXEC to the 64-bit value given. @@ -300,6 +360,12 @@ def int_amdgcn_sffbh : [IntrNoMem, IntrSpeculatable] >; +// v_mad_f32|f16/v_mac_f32|f16, selected regardless of denorm support. +def int_amdgcn_fmad_ftz : + Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable] +>; // Fields should mirror atomicrmw class AMDGPUAtomicIncIntrin : Intrinsic<[llvm_anyint_ty], @@ -315,165 +381,414 @@ class AMDGPUAtomicIncIntrin : Intrinsic<[llvm_anyint_ty], def int_amdgcn_atomic_inc : AMDGPUAtomicIncIntrin; def int_amdgcn_atomic_dec : AMDGPUAtomicIncIntrin; -class AMDGPUImageLoad<bit NoMem = 0> : Intrinsic < - [llvm_anyfloat_ty], // vdata(VGPR) - [llvm_anyint_ty, // vaddr(VGPR) - llvm_anyint_ty, // rsrc(SGPR) - llvm_i32_ty, // dmask(imm) - llvm_i1_ty, // glc(imm) - llvm_i1_ty, // slc(imm) - llvm_i1_ty, // lwe(imm) - llvm_i1_ty], // da(imm) - !if(NoMem, [IntrNoMem], [IntrReadMem]), "", - !if(NoMem, [], [SDNPMemOperand])>; +class AMDGPULDSF32Intrin<string clang_builtin> : + GCCBuiltin<clang_builtin>, + Intrinsic<[llvm_float_ty], + [LLVMQualPointerType<llvm_float_ty, 3>, + llvm_float_ty, + llvm_i32_ty, // ordering + llvm_i32_ty, // scope + llvm_i1_ty], // isVolatile + [IntrArgMemOnly, NoCapture<0>] +>; -def int_amdgcn_image_load : AMDGPUImageLoad; -def int_amdgcn_image_load_mip : AMDGPUImageLoad; -def int_amdgcn_image_getresinfo : AMDGPUImageLoad<1>; +def int_amdgcn_ds_fadd : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_faddf">; +def int_amdgcn_ds_fmin : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_fminf">; +def int_amdgcn_ds_fmax : AMDGPULDSF32Intrin<"__builtin_amdgcn_ds_fmaxf">; -class AMDGPUImageStore : Intrinsic < - [], - [llvm_anyfloat_ty, // vdata(VGPR) - llvm_anyint_ty, // vaddr(VGPR) - llvm_anyint_ty, // rsrc(SGPR) - llvm_i32_ty, // dmask(imm) - llvm_i1_ty, // glc(imm) - llvm_i1_ty, // slc(imm) - llvm_i1_ty, // lwe(imm) - llvm_i1_ty], // da(imm) - [IntrWriteMem], "", [SDNPMemOperand]>; +} // TargetPrefix = "amdgcn" + +// New-style image intrinsics + +////////////////////////////////////////////////////////////////////////// +// Dimension-aware image intrinsics framework +////////////////////////////////////////////////////////////////////////// + +// Helper class to represent (type, name) combinations of arguments. The +// argument names are explanatory and used as DAG operand names for codegen +// pattern matching. +class AMDGPUArg<LLVMType ty, string name> { + LLVMType Type = ty; + string Name = name; +} + +// Return [AMDGPUArg<basety, names[0]>, AMDGPUArg<LLVMMatchType<0>, names[1]>, ...] +class makeArgList<list<string> names, LLVMType basety> { + list<AMDGPUArg> ret = + !listconcat([AMDGPUArg<basety, names[0]>], + !foreach(name, !tail(names), AMDGPUArg<LLVMMatchType<0>, name>)); +} + +// Return arglist, with LLVMMatchType's references shifted by 'shift'. +class arglistmatchshift<list<AMDGPUArg> arglist, int shift> { + list<AMDGPUArg> ret = + !foreach(arg, arglist, + !if(!isa<LLVMMatchType>(arg.Type), + AMDGPUArg<LLVMMatchType<!add(!cast<LLVMMatchType>(arg.Type).Number, shift)>, + arg.Name>, + arg)); +} -def int_amdgcn_image_store : AMDGPUImageStore; -def int_amdgcn_image_store_mip : AMDGPUImageStore; +// Return the concatenation of the given arglists. LLVMMatchType's are adjusted +// accordingly, and shifted by an additional 'shift'. +class arglistconcat<list<list<AMDGPUArg>> arglists, int shift = 0> { + list<AMDGPUArg> ret = + !foldl([]<AMDGPUArg>, arglists, lhs, rhs, + !listconcat( + lhs, + arglistmatchshift<rhs, + !add(shift, !foldl(0, lhs, a, b, + !add(a, b.Type.isAny)))>.ret)); +} -class AMDGPUImageSample<bit NoMem = 0> : Intrinsic < - [llvm_anyfloat_ty], // vdata(VGPR) - [llvm_anyfloat_ty, // vaddr(VGPR) - llvm_anyint_ty, // rsrc(SGPR) - llvm_v4i32_ty, // sampler(SGPR) - llvm_i32_ty, // dmask(imm) - llvm_i1_ty, // unorm(imm) - llvm_i1_ty, // glc(imm) - llvm_i1_ty, // slc(imm) - llvm_i1_ty, // lwe(imm) - llvm_i1_ty], // da(imm) - !if(NoMem, [IntrNoMem], [IntrReadMem]), "", - !if(NoMem, [], [SDNPMemOperand])>; +// Represent texture/image types / dimensionality. +class AMDGPUDimProps<string name, list<string> coord_names, list<string> slice_names> { + AMDGPUDimProps Dim = !cast<AMDGPUDimProps>(NAME); + string Name = name; // e.g. "2darraymsaa" + bit DA = 0; // DA bit in MIMG encoding -// Basic sample -def int_amdgcn_image_sample : AMDGPUImageSample; -def int_amdgcn_image_sample_cl : AMDGPUImageSample; -def int_amdgcn_image_sample_d : AMDGPUImageSample; -def int_amdgcn_image_sample_d_cl : AMDGPUImageSample; -def int_amdgcn_image_sample_l : AMDGPUImageSample; -def int_amdgcn_image_sample_b : AMDGPUImageSample; -def int_amdgcn_image_sample_b_cl : AMDGPUImageSample; -def int_amdgcn_image_sample_lz : AMDGPUImageSample; -def int_amdgcn_image_sample_cd : AMDGPUImageSample; -def int_amdgcn_image_sample_cd_cl : AMDGPUImageSample; + list<AMDGPUArg> CoordSliceArgs = + makeArgList<!listconcat(coord_names, slice_names), llvm_anyfloat_ty>.ret; + list<AMDGPUArg> CoordSliceIntArgs = + makeArgList<!listconcat(coord_names, slice_names), llvm_anyint_ty>.ret; + list<AMDGPUArg> GradientArgs = + makeArgList<!listconcat(!foreach(name, coord_names, "d" # name # "dh"), + !foreach(name, coord_names, "d" # name # "dv")), + llvm_anyfloat_ty>.ret; -// Sample with comparison -def int_amdgcn_image_sample_c : AMDGPUImageSample; -def int_amdgcn_image_sample_c_cl : AMDGPUImageSample; -def int_amdgcn_image_sample_c_d : AMDGPUImageSample; -def int_amdgcn_image_sample_c_d_cl : AMDGPUImageSample; -def int_amdgcn_image_sample_c_l : AMDGPUImageSample; -def int_amdgcn_image_sample_c_b : AMDGPUImageSample; -def int_amdgcn_image_sample_c_b_cl : AMDGPUImageSample; -def int_amdgcn_image_sample_c_lz : AMDGPUImageSample; -def int_amdgcn_image_sample_c_cd : AMDGPUImageSample; -def int_amdgcn_image_sample_c_cd_cl : AMDGPUImageSample; + bits<8> NumCoords = !size(CoordSliceArgs); + bits<8> NumGradients = !size(GradientArgs); +} -// Sample with offsets -def int_amdgcn_image_sample_o : AMDGPUImageSample; -def int_amdgcn_image_sample_cl_o : AMDGPUImageSample; -def int_amdgcn_image_sample_d_o : AMDGPUImageSample; -def int_amdgcn_image_sample_d_cl_o : AMDGPUImageSample; -def int_amdgcn_image_sample_l_o : AMDGPUImageSample; -def int_amdgcn_image_sample_b_o : AMDGPUImageSample; -def int_amdgcn_image_sample_b_cl_o : AMDGPUImageSample; -def int_amdgcn_image_sample_lz_o : AMDGPUImageSample; -def int_amdgcn_image_sample_cd_o : AMDGPUImageSample; -def int_amdgcn_image_sample_cd_cl_o : AMDGPUImageSample; +def AMDGPUDim1D : AMDGPUDimProps<"1d", ["s"], []>; +def AMDGPUDim2D : AMDGPUDimProps<"2d", ["s", "t"], []>; +def AMDGPUDim3D : AMDGPUDimProps<"3d", ["s", "t", "r"], []>; +let DA = 1 in { + def AMDGPUDimCube : AMDGPUDimProps<"cube", ["s", "t"], ["face"]>; + def AMDGPUDim1DArray : AMDGPUDimProps<"1darray", ["s"], ["slice"]>; + def AMDGPUDim2DArray : AMDGPUDimProps<"2darray", ["s", "t"], ["slice"]>; +} +def AMDGPUDim2DMsaa : AMDGPUDimProps<"2dmsaa", ["s", "t"], ["fragid"]>; +let DA = 1 in { + def AMDGPUDim2DArrayMsaa : AMDGPUDimProps<"2darraymsaa", ["s", "t"], ["slice", "fragid"]>; +} -// Sample with comparison and offsets -def int_amdgcn_image_sample_c_o : AMDGPUImageSample; -def int_amdgcn_image_sample_c_cl_o : AMDGPUImageSample; -def int_amdgcn_image_sample_c_d_o : AMDGPUImageSample; -def int_amdgcn_image_sample_c_d_cl_o : AMDGPUImageSample; -def int_amdgcn_image_sample_c_l_o : AMDGPUImageSample; -def int_amdgcn_image_sample_c_b_o : AMDGPUImageSample; -def int_amdgcn_image_sample_c_b_cl_o : AMDGPUImageSample; -def int_amdgcn_image_sample_c_lz_o : AMDGPUImageSample; -def int_amdgcn_image_sample_c_cd_o : AMDGPUImageSample; -def int_amdgcn_image_sample_c_cd_cl_o : AMDGPUImageSample; +def AMDGPUDims { + list<AMDGPUDimProps> NoMsaa = [AMDGPUDim1D, AMDGPUDim2D, AMDGPUDim3D, + AMDGPUDimCube, AMDGPUDim1DArray, + AMDGPUDim2DArray]; + list<AMDGPUDimProps> Msaa = [AMDGPUDim2DMsaa, AMDGPUDim2DArrayMsaa]; + list<AMDGPUDimProps> All = !listconcat(NoMsaa, Msaa); +} -// Basic gather4 -def int_amdgcn_image_gather4 : AMDGPUImageSample; -def int_amdgcn_image_gather4_cl : AMDGPUImageSample; -def int_amdgcn_image_gather4_l : AMDGPUImageSample; -def int_amdgcn_image_gather4_b : AMDGPUImageSample; -def int_amdgcn_image_gather4_b_cl : AMDGPUImageSample; -def int_amdgcn_image_gather4_lz : AMDGPUImageSample; +// Represent sample variants, i.e. _C, _O, _B, ... and combinations thereof. +class AMDGPUSampleVariant<string ucmod, string lcmod, list<AMDGPUArg> extra_addr> { + string UpperCaseMod = ucmod; + string LowerCaseMod = lcmod; -// Gather4 with comparison -def int_amdgcn_image_gather4_c : AMDGPUImageSample; -def int_amdgcn_image_gather4_c_cl : AMDGPUImageSample; -def int_amdgcn_image_gather4_c_l : AMDGPUImageSample; -def int_amdgcn_image_gather4_c_b : AMDGPUImageSample; -def int_amdgcn_image_gather4_c_b_cl : AMDGPUImageSample; -def int_amdgcn_image_gather4_c_lz : AMDGPUImageSample; + // {offset} {bias} {z-compare} + list<AMDGPUArg> ExtraAddrArgs = extra_addr; + bit Gradients = 0; -// Gather4 with offsets -def int_amdgcn_image_gather4_o : AMDGPUImageSample; -def int_amdgcn_image_gather4_cl_o : AMDGPUImageSample; -def int_amdgcn_image_gather4_l_o : AMDGPUImageSample; -def int_amdgcn_image_gather4_b_o : AMDGPUImageSample; -def int_amdgcn_image_gather4_b_cl_o : AMDGPUImageSample; -def int_amdgcn_image_gather4_lz_o : AMDGPUImageSample; + // Name of the {lod} or {clamp} argument that is appended to the coordinates, + // if any. + string LodOrClamp = ""; +} -// Gather4 with comparison and offsets -def int_amdgcn_image_gather4_c_o : AMDGPUImageSample; -def int_amdgcn_image_gather4_c_cl_o : AMDGPUImageSample; -def int_amdgcn_image_gather4_c_l_o : AMDGPUImageSample; -def int_amdgcn_image_gather4_c_b_o : AMDGPUImageSample; -def int_amdgcn_image_gather4_c_b_cl_o : AMDGPUImageSample; -def int_amdgcn_image_gather4_c_lz_o : AMDGPUImageSample; +// AMDGPUSampleVariants: all variants supported by IMAGE_SAMPLE +// AMDGPUSampleVariantsNoGradients: variants supported by IMAGE_GATHER4 +defset list<AMDGPUSampleVariant> AMDGPUSampleVariants = { + multiclass AMDGPUSampleHelper_Offset<string ucmod, string lcmod, + list<AMDGPUArg> extra_addr> { + def NAME#lcmod : AMDGPUSampleVariant<ucmod, lcmod, extra_addr>; + def NAME#lcmod#_o : AMDGPUSampleVariant< + ucmod#"_O", lcmod#"_o", !listconcat([AMDGPUArg<llvm_i32_ty, "offset">], extra_addr)>; + } -def int_amdgcn_image_getlod : AMDGPUImageSample<1>; + multiclass AMDGPUSampleHelper_Compare<string ucmod, string lcmod, + list<AMDGPUArg> extra_addr> { + defm NAME : AMDGPUSampleHelper_Offset<ucmod, lcmod, extra_addr>; + defm NAME : AMDGPUSampleHelper_Offset< + "_C"#ucmod, "_c"#lcmod, !listconcat(extra_addr, [AMDGPUArg<llvm_float_ty, "zcompare">])>; + } -class AMDGPUImageAtomic : Intrinsic < - [llvm_i32_ty], - [llvm_i32_ty, // vdata(VGPR) - llvm_anyint_ty, // vaddr(VGPR) - llvm_v8i32_ty, // rsrc(SGPR) - llvm_i1_ty, // r128(imm) - llvm_i1_ty, // da(imm) - llvm_i1_ty], // slc(imm) - [], "", [SDNPMemOperand]>; + multiclass AMDGPUSampleHelper_Clamp<string ucmod, string lcmod, + list<AMDGPUArg> extra_addr> { + defm NAME : AMDGPUSampleHelper_Compare<ucmod, lcmod, extra_addr>; + let LodOrClamp = "clamp" in + defm NAME : AMDGPUSampleHelper_Compare<ucmod#"_CL", lcmod#"_cl", extra_addr>; + } -def int_amdgcn_image_atomic_swap : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_add : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_sub : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_smin : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_umin : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_smax : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_umax : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_and : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_or : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_xor : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_inc : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_dec : AMDGPUImageAtomic; -def int_amdgcn_image_atomic_cmpswap : Intrinsic < - [llvm_i32_ty], - [llvm_i32_ty, // src(VGPR) - llvm_i32_ty, // cmp(VGPR) - llvm_anyint_ty, // vaddr(VGPR) - llvm_v8i32_ty, // rsrc(SGPR) - llvm_i1_ty, // r128(imm) - llvm_i1_ty, // da(imm) - llvm_i1_ty], // slc(imm) - [], "", [SDNPMemOperand]>; + defset list<AMDGPUSampleVariant> AMDGPUSampleVariantsNoGradients = { + defm AMDGPUSample : AMDGPUSampleHelper_Clamp<"", "", []>; + defm AMDGPUSample : AMDGPUSampleHelper_Clamp< + "_B", "_b", [AMDGPUArg<llvm_anyfloat_ty, "bias">]>; + let LodOrClamp = "lod" in + defm AMDGPUSample : AMDGPUSampleHelper_Compare<"_L", "_l", []>; + defm AMDGPUSample : AMDGPUSampleHelper_Compare<"_LZ", "_lz", []>; + } + + let Gradients = 1 in { + defm AMDGPUSample : AMDGPUSampleHelper_Clamp<"_D", "_d", []>; + defm AMDGPUSample : AMDGPUSampleHelper_Clamp<"_CD", "_cd", []>; + } +} + +// Helper class to capture the profile of a dimension-aware image intrinsic. +// This information is used to generate the intrinsic's type and to inform +// codegen pattern matching. +class AMDGPUDimProfile<string opmod, + AMDGPUDimProps dim> { + AMDGPUDimProps Dim = dim; + string OpMod = opmod; // the corresponding instruction is named IMAGE_OpMod + + // These are entended to be overwritten by subclasses + bit IsSample = 0; + bit IsAtomic = 0; + list<LLVMType> RetTypes = []; + list<AMDGPUArg> DataArgs = []; + list<AMDGPUArg> ExtraAddrArgs = []; + bit Gradients = 0; + string LodClampMip = ""; + + int NumRetAndDataAnyTypes = + !foldl(0, !listconcat(RetTypes, !foreach(arg, DataArgs, arg.Type)), a, b, + !add(a, b.isAny)); + + list<AMDGPUArg> AddrArgs = + arglistconcat<[ExtraAddrArgs, + !if(Gradients, dim.GradientArgs, []), + !listconcat(!if(IsSample, dim.CoordSliceArgs, dim.CoordSliceIntArgs), + !if(!eq(LodClampMip, ""), + []<AMDGPUArg>, + [AMDGPUArg<LLVMMatchType<0>, LodClampMip>]))], + NumRetAndDataAnyTypes>.ret; + list<LLVMType> AddrTypes = !foreach(arg, AddrArgs, arg.Type); + list<AMDGPUArg> AddrDefaultArgs = + !foreach(arg, AddrArgs, + AMDGPUArg<!if(!or(arg.Type.isAny, !isa<LLVMMatchType>(arg.Type)), + !if(IsSample, llvm_float_ty, llvm_i32_ty), arg.Type), + arg.Name>); + list<AMDGPUArg> AddrA16Args = + !foreach(arg, AddrArgs, + AMDGPUArg<!if(!or(arg.Type.isAny, !isa<LLVMMatchType>(arg.Type)), + !if(IsSample, llvm_half_ty, llvm_i16_ty), arg.Type), + arg.Name>); +} + +class AMDGPUDimProfileCopy<AMDGPUDimProfile base> : AMDGPUDimProfile<base.OpMod, base.Dim> { + let IsSample = base.IsSample; + let IsAtomic = base.IsAtomic; + let RetTypes = base.RetTypes; + let DataArgs = base.DataArgs; + let ExtraAddrArgs = base.ExtraAddrArgs; + let Gradients = base.Gradients; + let LodClampMip = base.LodClampMip; +} + +class AMDGPUDimSampleProfile<string opmod, + AMDGPUDimProps dim, + AMDGPUSampleVariant sample> : AMDGPUDimProfile<opmod, dim> { + let IsSample = 1; + let RetTypes = [llvm_anyfloat_ty]; + let ExtraAddrArgs = sample.ExtraAddrArgs; + let Gradients = sample.Gradients; + let LodClampMip = sample.LodOrClamp; +} + +class AMDGPUDimNoSampleProfile<string opmod, + AMDGPUDimProps dim, + list<LLVMType> retty, + list<AMDGPUArg> dataargs, + bit Mip = 0> : AMDGPUDimProfile<opmod, dim> { + let RetTypes = retty; + let DataArgs = dataargs; + let LodClampMip = !if(Mip, "mip", ""); +} + +class AMDGPUDimAtomicProfile<string opmod, + AMDGPUDimProps dim, + list<AMDGPUArg> dataargs> : AMDGPUDimProfile<opmod, dim> { + let RetTypes = [llvm_anyint_ty]; + let DataArgs = dataargs; + let IsAtomic = 1; +} + +class AMDGPUDimGetResInfoProfile<AMDGPUDimProps dim> : AMDGPUDimProfile<"GET_RESINFO", dim> { + let RetTypes = [llvm_anyfloat_ty]; + let DataArgs = []; + let AddrArgs = [AMDGPUArg<llvm_anyint_ty, "mip">]; + let LodClampMip = "mip"; +} + +// All dimension-aware intrinsics are derived from this class. +class AMDGPUImageDimIntrinsic<AMDGPUDimProfile P_, + list<IntrinsicProperty> props, + list<SDNodeProperty> sdnodeprops> : Intrinsic< + P_.RetTypes, // vdata(VGPR) -- for load/atomic-with-return + !listconcat( + !foreach(arg, P_.DataArgs, arg.Type), // vdata(VGPR) -- for store/atomic + !if(P_.IsAtomic, [], [llvm_i32_ty]), // dmask(imm) + P_.AddrTypes, // vaddr(VGPR) + [llvm_v8i32_ty], // rsrc(SGPR) + !if(P_.IsSample, [llvm_v4i32_ty, // samp(SGPR) + llvm_i1_ty], []), // unorm(imm) + [llvm_i32_ty, // texfailctrl(imm; bit 0 = tfe, bit 1 = lwe) + llvm_i32_ty]), // cachepolicy(imm; bit 0 = glc, bit 1 = slc) + props, "", sdnodeprops>, + AMDGPURsrcIntrinsic<!add(!size(P_.DataArgs), !size(P_.AddrTypes), + !if(P_.IsAtomic, 0, 1)), 1> { + AMDGPUDimProfile P = P_; + + AMDGPUImageDimIntrinsic Intr = !cast<AMDGPUImageDimIntrinsic>(NAME); + + let TargetPrefix = "amdgcn"; +} + +// Marker class for intrinsics with a DMask that determines the returned +// channels. +class AMDGPUImageDMaskIntrinsic; + +defset list<AMDGPUImageDimIntrinsic> AMDGPUImageDimIntrinsics = { + + ////////////////////////////////////////////////////////////////////////// + // Load and store intrinsics + ////////////////////////////////////////////////////////////////////////// + multiclass AMDGPUImageDimIntrinsicsNoMsaa<string opmod, + list<LLVMType> retty, + list<AMDGPUArg> dataargs, + list<IntrinsicProperty> props, + list<SDNodeProperty> sdnodeprops, + bit Mip = 0> { + foreach dim = AMDGPUDims.NoMsaa in { + def !strconcat(NAME, "_", dim.Name) + : AMDGPUImageDimIntrinsic< + AMDGPUDimNoSampleProfile<opmod, dim, retty, dataargs, Mip>, + props, sdnodeprops>; + } + } + + multiclass AMDGPUImageDimIntrinsicsAll<string opmod, + list<LLVMType> retty, + list<AMDGPUArg> dataargs, + list<IntrinsicProperty> props, + list<SDNodeProperty> sdnodeprops, + bit Mip = 0> { + foreach dim = AMDGPUDims.All in { + def !strconcat(NAME, "_", dim.Name) + : AMDGPUImageDimIntrinsic< + AMDGPUDimNoSampleProfile<opmod, dim, retty, dataargs, Mip>, + props, sdnodeprops>; + } + } + + defm int_amdgcn_image_load + : AMDGPUImageDimIntrinsicsAll<"LOAD", [llvm_anyfloat_ty], [], [IntrReadMem], + [SDNPMemOperand]>, + AMDGPUImageDMaskIntrinsic; + defm int_amdgcn_image_load_mip + : AMDGPUImageDimIntrinsicsNoMsaa<"LOAD_MIP", [llvm_anyfloat_ty], [], + [IntrReadMem], [SDNPMemOperand], 1>, + AMDGPUImageDMaskIntrinsic; + + defm int_amdgcn_image_store : AMDGPUImageDimIntrinsicsAll< + "STORE", [], [AMDGPUArg<llvm_anyfloat_ty, "vdata">], + [IntrWriteMem], [SDNPMemOperand]>; + defm int_amdgcn_image_store_mip : AMDGPUImageDimIntrinsicsNoMsaa< + "STORE_MIP", [], [AMDGPUArg<llvm_anyfloat_ty, "vdata">], + [IntrWriteMem], [SDNPMemOperand], 1>; + + ////////////////////////////////////////////////////////////////////////// + // sample and getlod intrinsics + ////////////////////////////////////////////////////////////////////////// + multiclass AMDGPUImageDimSampleDims<string opmod, + AMDGPUSampleVariant sample, + bit NoMem = 0> { + foreach dim = AMDGPUDims.NoMsaa in { + def !strconcat(NAME, "_", dim.Name) : AMDGPUImageDimIntrinsic< + AMDGPUDimSampleProfile<opmod, dim, sample>, + !if(NoMem, [IntrNoMem], [IntrReadMem]), + !if(NoMem, [], [SDNPMemOperand])>; + } + } + + foreach sample = AMDGPUSampleVariants in { + defm int_amdgcn_image_sample # sample.LowerCaseMod + : AMDGPUImageDimSampleDims<"SAMPLE" # sample.UpperCaseMod, sample>, + AMDGPUImageDMaskIntrinsic; + } + + defm int_amdgcn_image_getlod + : AMDGPUImageDimSampleDims<"GET_LOD", AMDGPUSample, 1>, + AMDGPUImageDMaskIntrinsic; + + ////////////////////////////////////////////////////////////////////////// + // getresinfo intrinsics + ////////////////////////////////////////////////////////////////////////// + foreach dim = AMDGPUDims.All in { + def !strconcat("int_amdgcn_image_getresinfo_", dim.Name) + : AMDGPUImageDimIntrinsic<AMDGPUDimGetResInfoProfile<dim>, [IntrNoMem], []>, + AMDGPUImageDMaskIntrinsic; + } + + ////////////////////////////////////////////////////////////////////////// + // gather4 intrinsics + ////////////////////////////////////////////////////////////////////////// + foreach sample = AMDGPUSampleVariantsNoGradients in { + foreach dim = [AMDGPUDim2D, AMDGPUDimCube, AMDGPUDim2DArray] in { + def int_amdgcn_image_gather4 # sample.LowerCaseMod # _ # dim.Name: + AMDGPUImageDimIntrinsic< + AMDGPUDimSampleProfile<"GATHER4" # sample.UpperCaseMod, dim, sample>, + [IntrReadMem], [SDNPMemOperand]>; + } + } +} + +////////////////////////////////////////////////////////////////////////// +// atomic intrinsics +////////////////////////////////////////////////////////////////////////// +defset list<AMDGPUImageDimIntrinsic> AMDGPUImageDimAtomicIntrinsics = { + multiclass AMDGPUImageDimAtomicX<string opmod, list<AMDGPUArg> dataargs> { + foreach dim = AMDGPUDims.All in { + def !strconcat(NAME, "_", dim.Name) + : AMDGPUImageDimIntrinsic< + AMDGPUDimAtomicProfile<opmod, dim, dataargs>, + [], [SDNPMemOperand]>; + } + } + + multiclass AMDGPUImageDimAtomic<string opmod> { + defm "" : AMDGPUImageDimAtomicX<opmod, [AMDGPUArg<LLVMMatchType<0>, "vdata">]>; + } + + defm int_amdgcn_image_atomic_swap : AMDGPUImageDimAtomic<"ATOMIC_SWAP">; + defm int_amdgcn_image_atomic_add : AMDGPUImageDimAtomic<"ATOMIC_ADD">; + defm int_amdgcn_image_atomic_sub : AMDGPUImageDimAtomic<"ATOMIC_SUB">; + defm int_amdgcn_image_atomic_smin : AMDGPUImageDimAtomic<"ATOMIC_SMIN">; + defm int_amdgcn_image_atomic_umin : AMDGPUImageDimAtomic<"ATOMIC_UMIN">; + defm int_amdgcn_image_atomic_smax : AMDGPUImageDimAtomic<"ATOMIC_SMAX">; + defm int_amdgcn_image_atomic_umax : AMDGPUImageDimAtomic<"ATOMIC_UMAX">; + defm int_amdgcn_image_atomic_and : AMDGPUImageDimAtomic<"ATOMIC_AND">; + defm int_amdgcn_image_atomic_or : AMDGPUImageDimAtomic<"ATOMIC_OR">; + defm int_amdgcn_image_atomic_xor : AMDGPUImageDimAtomic<"ATOMIC_XOR">; + + // TODO: INC/DEC are weird: they seem to have a vdata argument in hardware, + // even though it clearly shouldn't be needed + defm int_amdgcn_image_atomic_inc : AMDGPUImageDimAtomic<"ATOMIC_INC">; + defm int_amdgcn_image_atomic_dec : AMDGPUImageDimAtomic<"ATOMIC_DEC">; + + defm int_amdgcn_image_atomic_cmpswap : + AMDGPUImageDimAtomicX<"ATOMIC_CMPSWAP", [AMDGPUArg<LLVMMatchType<0>, "src">, + AMDGPUArg<LLVMMatchType<0>, "cmp">]>; +} + +////////////////////////////////////////////////////////////////////////// +// Buffer intrinsics +////////////////////////////////////////////////////////////////////////// + +let TargetPrefix = "amdgcn" in { + +defset list<AMDGPURsrcIntrinsic> AMDGPUBufferIntrinsics = { class AMDGPUBufferLoad : Intrinsic < [llvm_anyfloat_ty], @@ -482,7 +797,8 @@ class AMDGPUBufferLoad : Intrinsic < llvm_i32_ty, // offset(SGPR/VGPR/imm) llvm_i1_ty, // glc(imm) llvm_i1_ty], // slc(imm) - [IntrReadMem], "", [SDNPMemOperand]>; + [IntrReadMem], "", [SDNPMemOperand]>, + AMDGPURsrcIntrinsic<0>; def int_amdgcn_buffer_load_format : AMDGPUBufferLoad; def int_amdgcn_buffer_load : AMDGPUBufferLoad; @@ -494,7 +810,8 @@ class AMDGPUBufferStore : Intrinsic < llvm_i32_ty, // offset(SGPR/VGPR/imm) llvm_i1_ty, // glc(imm) llvm_i1_ty], // slc(imm) - [IntrWriteMem], "", [SDNPMemOperand]>; + [IntrWriteMem], "", [SDNPMemOperand]>, + AMDGPURsrcIntrinsic<1>; def int_amdgcn_buffer_store_format : AMDGPUBufferStore; def int_amdgcn_buffer_store : AMDGPUBufferStore; @@ -509,7 +826,8 @@ def int_amdgcn_tbuffer_load : Intrinsic < llvm_i32_ty, // nfmt(imm) llvm_i1_ty, // glc(imm) llvm_i1_ty], // slc(imm) - [IntrReadMem], "", [SDNPMemOperand]>; + [IntrReadMem], "", [SDNPMemOperand]>, + AMDGPURsrcIntrinsic<0>; def int_amdgcn_tbuffer_store : Intrinsic < [], @@ -523,7 +841,8 @@ def int_amdgcn_tbuffer_store : Intrinsic < llvm_i32_ty, // nfmt(imm) llvm_i1_ty, // glc(imm) llvm_i1_ty], // slc(imm) - [IntrWriteMem], "", [SDNPMemOperand]>; + [IntrWriteMem], "", [SDNPMemOperand]>, + AMDGPURsrcIntrinsic<1>; class AMDGPUBufferAtomic : Intrinsic < [llvm_i32_ty], @@ -532,7 +851,8 @@ class AMDGPUBufferAtomic : Intrinsic < llvm_i32_ty, // vindex(VGPR) llvm_i32_ty, // offset(SGPR/VGPR/imm) llvm_i1_ty], // slc(imm) - [], "", [SDNPMemOperand]>; + [], "", [SDNPMemOperand]>, + AMDGPURsrcIntrinsic<1, 0>; def int_amdgcn_buffer_atomic_swap : AMDGPUBufferAtomic; def int_amdgcn_buffer_atomic_add : AMDGPUBufferAtomic; def int_amdgcn_buffer_atomic_sub : AMDGPUBufferAtomic; @@ -551,7 +871,10 @@ def int_amdgcn_buffer_atomic_cmpswap : Intrinsic< llvm_i32_ty, // vindex(VGPR) llvm_i32_ty, // offset(SGPR/VGPR/imm) llvm_i1_ty], // slc(imm) - [], "", [SDNPMemOperand]>; + [], "", [SDNPMemOperand]>, + AMDGPURsrcIntrinsic<2, 0>; + +} // defset AMDGPUBufferIntrinsics // Uses that do not set the done bit should set IntrWriteMem on the // call site. @@ -753,6 +1076,19 @@ def int_amdgcn_readlane : GCCBuiltin<"__builtin_amdgcn_readlane">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>; +// The value to write and lane select arguments must be uniform across the +// currently active threads of the current wave. Otherwise, the result is +// undefined. +def int_amdgcn_writelane : + GCCBuiltin<"__builtin_amdgcn_writelane">, + Intrinsic<[llvm_i32_ty], [ + llvm_i32_ty, // uniform value to write: returned by the selected lane + llvm_i32_ty, // uniform lane select + llvm_i32_ty // returned by all lanes other than the selected one + ], + [IntrNoMem, IntrConvergent] +>; + def int_amdgcn_alignbit : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrSpeculatable] @@ -851,6 +1187,109 @@ def int_amdgcn_ds_bpermute : GCCBuiltin<"__builtin_amdgcn_ds_bpermute">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrConvergent]>; +//===----------------------------------------------------------------------===// +// Deep learning intrinsics. +//===----------------------------------------------------------------------===// + +// f32 %r = llvm.amdgcn.fdot2(v2f16 %a, v2f16 %b, f32 %c) +// %r = %a[0] * %b[0] + %a[1] * %b[1] + %c +def int_amdgcn_fdot2 : + GCCBuiltin<"__builtin_amdgcn_fdot2">, + Intrinsic< + [llvm_float_ty], // %r + [ + llvm_v2f16_ty, // %a + llvm_v2f16_ty, // %b + llvm_float_ty // %c + ], + [IntrNoMem, IntrSpeculatable] + >; + +// i32 %r = llvm.amdgcn.sdot2(v2i16 %a, v2i16 %b, i32 %c) +// %r = %a[0] * %b[0] + %a[1] * %b[1] + %c +def int_amdgcn_sdot2 : + GCCBuiltin<"__builtin_amdgcn_sdot2">, + Intrinsic< + [llvm_i32_ty], // %r + [ + llvm_v2i16_ty, // %a + llvm_v2i16_ty, // %b + llvm_i32_ty // %c + ], + [IntrNoMem, IntrSpeculatable] + >; + +// u32 %r = llvm.amdgcn.udot2(v2u16 %a, v2u16 %b, u32 %c) +// %r = %a[0] * %b[0] + %a[1] * %b[1] + %c +def int_amdgcn_udot2 : + GCCBuiltin<"__builtin_amdgcn_udot2">, + Intrinsic< + [llvm_i32_ty], // %r + [ + llvm_v2i16_ty, // %a + llvm_v2i16_ty, // %b + llvm_i32_ty // %c + ], + [IntrNoMem, IntrSpeculatable] + >; + +// i32 %r = llvm.amdgcn.sdot4(v4i8 (as i32) %a, v4i8 (as i32) %b, i32 %c) +// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] + %c +def int_amdgcn_sdot4 : + GCCBuiltin<"__builtin_amdgcn_sdot4">, + Intrinsic< + [llvm_i32_ty], // %r + [ + llvm_i32_ty, // %a + llvm_i32_ty, // %b + llvm_i32_ty // %c + ], + [IntrNoMem, IntrSpeculatable] + >; + +// u32 %r = llvm.amdgcn.udot4(v4u8 (as u32) %a, v4u8 (as u32) %b, u32 %c) +// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] + %c +def int_amdgcn_udot4 : + GCCBuiltin<"__builtin_amdgcn_udot4">, + Intrinsic< + [llvm_i32_ty], // %r + [ + llvm_i32_ty, // %a + llvm_i32_ty, // %b + llvm_i32_ty // %c + ], + [IntrNoMem, IntrSpeculatable] + >; + +// i32 %r = llvm.amdgcn.sdot8(v8i4 (as i32) %a, v8i4 (as i32) %b, i32 %c) +// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] + +// %a[4] * %b[4] + %a[5] * %b[5] + %a[6] * %b[6] + %a[7] * %b[7] + %c +def int_amdgcn_sdot8 : + GCCBuiltin<"__builtin_amdgcn_sdot8">, + Intrinsic< + [llvm_i32_ty], // %r + [ + llvm_i32_ty, // %a + llvm_i32_ty, // %b + llvm_i32_ty // %c + ], + [IntrNoMem, IntrSpeculatable] + >; + +// u32 %r = llvm.amdgcn.udot8(v8u4 (as u32) %a, v8u4 (as u32) %b, u32 %c) +// %r = %a[0] * %b[0] + %a[1] * %b[1] + %a[2] * %b[2] + %a[3] * %b[3] + +// %a[4] * %b[4] + %a[5] * %b[5] + %a[6] * %b[6] + %a[7] * %b[7] + %c +def int_amdgcn_udot8 : + GCCBuiltin<"__builtin_amdgcn_udot8">, + Intrinsic< + [llvm_i32_ty], // %r + [ + llvm_i32_ty, // %a + llvm_i32_ty, // %b + llvm_i32_ty // %c + ], + [IntrNoMem, IntrSpeculatable] + >; //===----------------------------------------------------------------------===// // Special Intrinsics for backend internal use only. No frontend diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsARM.td b/contrib/llvm/include/llvm/IR/IntrinsicsARM.td index fe3861301689..f25d2f1dbb5d 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsARM.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsARM.td @@ -369,6 +369,10 @@ class Neon_3Arg_Long_Intrinsic : Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMTruncatedType<0>, LLVMTruncatedType<0>], [IntrNoMem]>; + +class Neon_1FloatArg_Intrinsic + : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + class Neon_CvtFxToFP_Intrinsic : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; class Neon_CvtFPToFx_Intrinsic @@ -591,8 +595,8 @@ def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic; def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic; def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic; -// Vector Rounding -def int_arm_neon_vrintn : Neon_1Arg_Intrinsic; +// Vector and Scalar Rounding. +def int_arm_neon_vrintn : Neon_1FloatArg_Intrinsic; def int_arm_neon_vrintx : Neon_1Arg_Intrinsic; def int_arm_neon_vrinta : Neon_1Arg_Intrinsic; def int_arm_neon_vrintz : Neon_1Arg_Intrinsic; @@ -616,6 +620,18 @@ def int_arm_neon_vld4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, [llvm_anyptr_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; +def int_arm_neon_vld1x2 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], + [IntrReadMem, IntrArgMemOnly]>; +def int_arm_neon_vld1x3 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], + [IntrReadMem, IntrArgMemOnly]>; +def int_arm_neon_vld1x4 : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [LLVMAnyPointerType<LLVMMatchType<0>>], + [IntrReadMem, IntrArgMemOnly]>; + // Vector load N-element structure to one lane. // Source operands are: the address, the N input vectors (since only one // lane is assigned), the lane number, and the alignment. @@ -636,6 +652,20 @@ def int_arm_neon_vld4lane : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; +// Vector load N-element structure to all lanes. +// Source operands are the address and alignment. +def int_arm_neon_vld2dup : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>], + [llvm_anyptr_ty, llvm_i32_ty], + [IntrReadMem, IntrArgMemOnly]>; +def int_arm_neon_vld3dup : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>], + [llvm_anyptr_ty, llvm_i32_ty], + [IntrReadMem, IntrArgMemOnly]>; +def int_arm_neon_vld4dup : Intrinsic<[llvm_anyvector_ty, LLVMMatchType<0>, + LLVMMatchType<0>, LLVMMatchType<0>], + [llvm_anyptr_ty, llvm_i32_ty], + [IntrReadMem, IntrArgMemOnly]>; + // Interleaving vector stores from N-element structures. // Source operands are: the address, the N vectors, and the alignment. def int_arm_neon_vst1 : Intrinsic<[], @@ -655,6 +685,20 @@ def int_arm_neon_vst4 : Intrinsic<[], LLVMMatchType<1>, llvm_i32_ty], [IntrArgMemOnly]>; +def int_arm_neon_vst1x2 : Intrinsic<[], + [llvm_anyptr_ty, llvm_anyvector_ty, + LLVMMatchType<1>], + [IntrArgMemOnly, NoCapture<0>]>; +def int_arm_neon_vst1x3 : Intrinsic<[], + [llvm_anyptr_ty, llvm_anyvector_ty, + LLVMMatchType<1>, LLVMMatchType<1>], + [IntrArgMemOnly, NoCapture<0>]>; +def int_arm_neon_vst1x4 : Intrinsic<[], + [llvm_anyptr_ty, llvm_anyvector_ty, + LLVMMatchType<1>, LLVMMatchType<1>, + LLVMMatchType<1>], + [IntrArgMemOnly, NoCapture<0>]>; + // Vector store N-element structure from one lane. // Source operands are: the address, the N vectors, the lane number, and // the alignment. @@ -713,4 +757,14 @@ 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; +// Armv8.2-A dot product instructions +class Neon_Dot_Intrinsic + : Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty, + LLVMMatchType<1>], + [IntrNoMem]>; +def int_arm_neon_udot : Neon_Dot_Intrinsic; +def int_arm_neon_sdot : Neon_Dot_Intrinsic; + + } // end TargetPrefix diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsHexagon.td b/contrib/llvm/include/llvm/IR/IntrinsicsHexagon.td index 5c96702bca76..25f4215d68a8 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsHexagon.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsHexagon.td @@ -21,6 +21,13 @@ let TargetPrefix = "hexagon" in { list<IntrinsicProperty> properties> : GCCBuiltin<!strconcat("__builtin_", GCCIntSuffix)>, Intrinsic<ret_types, param_types, properties>; + + /// Hexagon_NonGCC_Intrinsic - Base class for bitcode convertible Hexagon + /// intrinsics. + class Hexagon_NonGCC_Intrinsic<list<LLVMType> ret_types, + list<LLVMType> param_types, + list<IntrinsicProperty> properties> + : Intrinsic<ret_types, param_types, properties>; } //===----------------------------------------------------------------------===// @@ -424,13 +431,13 @@ class Hexagon_mem_memsisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [IntrWriteMem]>; class Hexagon_mem_memdisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [IntrWriteMem]>; class Hexagon_mem_memmemsisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, @@ -442,13 +449,13 @@ class Hexagon_mem_memsisisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [IntrWriteMem]>; class Hexagon_mem_memdisisi_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_ptr_ty], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], - [IntrArgMemOnly]>; + [IntrWriteMem]>; class Hexagon_v256_v256v256_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, @@ -636,41 +643,6 @@ class Hexagon_df_dfdfdfqi_Intrinsic<string GCCIntSuffix> // This one below will not be auto-generated, // so make sure, you don't overwrite this one. // -// BUILTIN_INFO(SI_to_SXTHI_asrh,SI_ftype_SI,1) -// -def int_hexagon_SI_to_SXTHI_asrh : -Hexagon_si_si_Intrinsic<"SI_to_SXTHI_asrh">; -// -// BUILTIN_INFO_NONCONST(brev_ldd,PTR_ftype_PTRPTRSI,3) -// -def int_hexagon_brev_ldd : -Hexagon_mem_memmemsi_Intrinsic<"brev_ldd">; -// -// BUILTIN_INFO_NONCONST(brev_ldw,PTR_ftype_PTRPTRSI,3) -// -def int_hexagon_brev_ldw : -Hexagon_mem_memmemsi_Intrinsic<"brev_ldw">; -// -// BUILTIN_INFO_NONCONST(brev_ldh,PTR_ftype_PTRPTRSI,3) -// -def int_hexagon_brev_ldh : -Hexagon_mem_memmemsi_Intrinsic<"brev_ldh">; -// -// BUILTIN_INFO_NONCONST(brev_lduh,PTR_ftype_PTRPTRSI,3) -// -def int_hexagon_brev_lduh : -Hexagon_mem_memmemsi_Intrinsic<"brev_lduh">; -// -// BUILTIN_INFO_NONCONST(brev_ldb,PTR_ftype_PTRPTRSI,3) -// -def int_hexagon_brev_ldb : -Hexagon_mem_memmemsi_Intrinsic<"brev_ldb">; -// -// BUILTIN_INFO_NONCONST(brev_ldub,PTR_ftype_PTRPTRSI,3) -// -def int_hexagon_brev_ldub : -Hexagon_mem_memmemsi_Intrinsic<"brev_ldub">; -// // BUILTIN_INFO_NONCONST(circ_ldd,PTR_ftype_PTRPTRSISI,4) // def int_hexagon_circ_ldd : @@ -702,31 +674,6 @@ def int_hexagon_circ_ldub : Hexagon_mem_memmemsisi_Intrinsic<"circ_ldub">; // -// BUILTIN_INFO_NONCONST(brev_stb,PTR_ftype_PTRSISI,3) -// -def int_hexagon_brev_stb : -Hexagon_mem_memsisi_Intrinsic<"brev_stb">; -// -// BUILTIN_INFO_NONCONST(brev_sthhi,PTR_ftype_PTRSISI,3) -// -def int_hexagon_brev_sthhi : -Hexagon_mem_memsisi_Intrinsic<"brev_sthhi">; -// -// BUILTIN_INFO_NONCONST(brev_sth,PTR_ftype_PTRSISI,3) -// -def int_hexagon_brev_sth : -Hexagon_mem_memsisi_Intrinsic<"brev_sth">; -// -// BUILTIN_INFO_NONCONST(brev_stw,PTR_ftype_PTRSISI,3) -// -def int_hexagon_brev_stw : -Hexagon_mem_memsisi_Intrinsic<"brev_stw">; -// -// BUILTIN_INFO_NONCONST(brev_std,PTR_ftype_PTRSISI,3) -// -def int_hexagon_brev_std : -Hexagon_mem_memdisi_Intrinsic<"brev_std">; -// // BUILTIN_INFO_NONCONST(circ_std,PTR_ftype_PTRDISISI,4) // def int_hexagon_circ_std : @@ -9300,6 +9247,60 @@ Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorentq_128B">; def int_hexagon_V6_vmaskedstorentnq_128B : Hexagon_vv128ivmemv1024_Intrinsic<"HEXAGON_V6_vmaskedstorentnq_128B">; +multiclass Hexagon_custom_circ_ld_Intrinsic<LLVMType ElTy> { + def NAME#_pci : Hexagon_NonGCC_Intrinsic< + [ElTy, llvm_ptr_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], + [IntrArgMemOnly, NoCapture<3>]>; + def NAME#_pcr : Hexagon_NonGCC_Intrinsic< + [ElTy, llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_ptr_ty], + [IntrArgMemOnly, NoCapture<2>]>; +} + +defm int_hexagon_L2_loadrub : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>; +defm int_hexagon_L2_loadrb : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>; +defm int_hexagon_L2_loadruh : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>; +defm int_hexagon_L2_loadrh : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>; +defm int_hexagon_L2_loadri : Hexagon_custom_circ_ld_Intrinsic<llvm_i32_ty>; +defm int_hexagon_L2_loadrd : Hexagon_custom_circ_ld_Intrinsic<llvm_i64_ty>; + +multiclass Hexagon_custom_circ_st_Intrinsic<LLVMType ElTy> { + def NAME#_pci : Hexagon_NonGCC_Intrinsic< + [llvm_ptr_ty], + [llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty, ElTy, llvm_ptr_ty], + [IntrArgMemOnly, NoCapture<4>]>; + def NAME#_pcr : Hexagon_NonGCC_Intrinsic< + [llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, ElTy, llvm_ptr_ty], + [IntrArgMemOnly, NoCapture<3>]>; +} + +defm int_hexagon_S2_storerb : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>; +defm int_hexagon_S2_storerh : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>; +defm int_hexagon_S2_storerf : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>; +defm int_hexagon_S2_storeri : Hexagon_custom_circ_st_Intrinsic<llvm_i32_ty>; +defm int_hexagon_S2_storerd : Hexagon_custom_circ_st_Intrinsic<llvm_i64_ty>; + +// The front-end emits the intrinsic call with only two arguments. The third +// argument from the builtin is already used by front-end to write to memory +// by generating a store. +class Hexagon_custom_brev_ld_Intrinsic<LLVMType ElTy> + : Hexagon_NonGCC_Intrinsic< + [ElTy, llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadMem]>; + +def int_hexagon_L2_loadrub_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i32_ty>; +def int_hexagon_L2_loadrb_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i32_ty>; +def int_hexagon_L2_loadruh_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i32_ty>; +def int_hexagon_L2_loadrh_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i32_ty>; +def int_hexagon_L2_loadri_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i32_ty>; +def int_hexagon_L2_loadrd_pbr : Hexagon_custom_brev_ld_Intrinsic<llvm_i64_ty>; + +def int_hexagon_S2_storerb_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_stb">; +def int_hexagon_S2_storerh_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_sth">; +def int_hexagon_S2_storerf_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_sthhi">; +def int_hexagon_S2_storeri_pbr : Hexagon_mem_memsisi_Intrinsic<"brev_stw">; +def int_hexagon_S2_storerd_pbr : Hexagon_mem_memdisi_Intrinsic<"brev_std">; + /// /// HexagonV62 intrinsics diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td b/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td index 73622ce9303f..7f694f68969e 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsNVVM.td @@ -3884,96 +3884,100 @@ def int_nvvm_match_all_sync_i64p : // // WMMA.LOAD -class NVVM_WMMA_LD_ALSTS<string Abc, string Layout, string Space, - string Type, LLVMType regty, int WithStride> +class NVVM_WMMA_LD_GALSTS<string Geometry, string Abc, string Layout, + string Type, LLVMType regty, int WithStride> : Intrinsic<!if(!eq(Abc#Type,"cf16"), [regty, regty, regty, regty], [regty, regty, regty, regty, regty, regty, regty, regty]), - !if(WithStride, [llvm_ptr_ty, llvm_i32_ty], [llvm_ptr_ty]), - [], // Properties must be set during instantiation. - "llvm.nvvm.wmma.load."#Abc#".sync."#Layout#".m16n16k16" - #Space - #!if(WithStride,".stride","") - #"."#Type>; + !if(WithStride, [llvm_anyptr_ty, llvm_i32_ty], [llvm_anyptr_ty]), + [IntrReadMem, IntrArgMemOnly, ReadOnly<0>, NoCapture<0>], + "llvm.nvvm.wmma." + # Geometry + # ".load" + # "." # Abc + # "." # Layout + # !if(WithStride, ".stride", "") + # "." # Type>; -multiclass NVVM_WMMA_LD_ALST<string Abc, string Layout, string Space, - string Type, LLVMType regty> { - def _stride: NVVM_WMMA_LD_ALSTS<Abc, Layout, Space, Type, regty, 1>; - def NAME : NVVM_WMMA_LD_ALSTS<Abc, Layout, Space, Type, regty, 0>; +multiclass NVVM_WMMA_LD_GALT<string Geometry, string Abc, string Layout, + string Type, LLVMType regty> { + def _stride: NVVM_WMMA_LD_GALSTS<Geometry, Abc, Layout, Type, regty, 1>; + def NAME : NVVM_WMMA_LD_GALSTS<Geometry, Abc, Layout, Type, regty, 0>; } -multiclass NVVM_WMMA_LD_ALT<string Abc, string Layout, - string Type, LLVMType regty> { - defm _global: NVVM_WMMA_LD_ALST<Abc, Layout, ".global", Type, regty>; - defm _shared: NVVM_WMMA_LD_ALST<Abc, Layout, ".shared", Type, regty>; - defm NAME: NVVM_WMMA_LD_ALST<Abc, Layout, "", Type, regty>; +multiclass NVVM_WMMA_LD_GAT<string Geometry, string Abc, + string Type, LLVMType regty> { + defm _row: NVVM_WMMA_LD_GALT<Geometry, Abc, "row", Type, regty>; + defm _col: NVVM_WMMA_LD_GALT<Geometry, Abc, "col", Type, regty>; } -multiclass NVVM_WMMA_LD_AT<string Abc, string Type, LLVMType regty> { - defm _row: NVVM_WMMA_LD_ALT<Abc, "row", Type, regty>; - defm _col: NVVM_WMMA_LD_ALT<Abc, "col", Type, regty>; +multiclass NVVM_WMMA_LD_G<string Geometry> { + defm _a_f16: NVVM_WMMA_LD_GAT<Geometry, "a", "f16", llvm_v2f16_ty>; + defm _b_f16: NVVM_WMMA_LD_GAT<Geometry, "b", "f16", llvm_v2f16_ty>; + defm _c_f16: NVVM_WMMA_LD_GAT<Geometry, "c", "f16", llvm_v2f16_ty>; + defm _c_f32: NVVM_WMMA_LD_GAT<Geometry, "c", "f32", llvm_float_ty>; } -// For some reason ReadOnly<N> and NoCapture<N> confuses tblgen if they are -// passed to Intrinsic<> form inside of a multiclass. Setting them globally -// outside of the multiclass works. -let IntrProperties = [IntrReadMem, IntrArgMemOnly, - ReadOnly<0>, NoCapture<0>] in { - defm int_nvvm_wmma_load_a_f16: NVVM_WMMA_LD_AT<"a", "f16", llvm_v2f16_ty>; - defm int_nvvm_wmma_load_b_f16: NVVM_WMMA_LD_AT<"b", "f16", llvm_v2f16_ty>; - defm int_nvvm_wmma_load_c_f16: NVVM_WMMA_LD_AT<"c", "f16", llvm_v2f16_ty>; - defm int_nvvm_wmma_load_c_f32: NVVM_WMMA_LD_AT<"c", "f32", llvm_float_ty>; +multiclass NVVM_WMMA_LD { + defm _m32n8k16_load: NVVM_WMMA_LD_G<"m32n8k16">; + defm _m16n16k16_load: NVVM_WMMA_LD_G<"m16n16k16">; + defm _m8n32k16_load: NVVM_WMMA_LD_G<"m8n32k16">; } +defm int_nvvm_wmma: NVVM_WMMA_LD; + // WMMA.STORE.D -class NVVM_WMMA_STD_LSTS<string Layout, string Space, - string Type, LLVMType regty, int WithStride, - // This is only used to create a typed empty array we - // need to pass to !if below. - list<LLVMType>Empty=[]> +class NVVM_WMMA_STD_GLSTS<string Geometry, string Layout, + string Type, LLVMType regty, int WithStride, + // This is only used to create a typed empty array we + // need to pass to !if below. + list<LLVMType>Empty=[]> : Intrinsic<[], !listconcat( - [llvm_ptr_ty], + [llvm_anyptr_ty], !if(!eq(Type,"f16"), [regty, regty, regty, regty], [regty, regty, regty, regty, regty, regty, regty, regty]), !if(WithStride, [llvm_i32_ty], Empty)), - [], // Properties must be set during instantiation. - "llvm.nvvm.wmma.store.d.sync."#Layout - #".m16n16k16"#Space - #!if(WithStride,".stride","") - #"."#Type>; + [IntrWriteMem, IntrArgMemOnly, WriteOnly<0>, NoCapture<0>], + "llvm.nvvm.wmma." + # Geometry + # ".store.d" + # "." # Layout + # !if(WithStride, ".stride", "") + # "." # Type>; -multiclass NVVM_WMMA_STD_LST<string Layout, string Space, - string Type, LLVMType regty> { - def _stride: NVVM_WMMA_STD_LSTS<Layout, Space, Type, regty, 1>; - def NAME: NVVM_WMMA_STD_LSTS<Layout, Space, Type, regty, 0>; +multiclass NVVM_WMMA_STD_GLT<string Geometry, string Layout, + string Type, LLVMType regty> { + def _stride: NVVM_WMMA_STD_GLSTS<Geometry, Layout, Type, regty, 1>; + def NAME: NVVM_WMMA_STD_GLSTS<Geometry, Layout, Type, regty, 0>; } -multiclass NVVM_WMMA_STD_LT<string Layout, string Type, LLVMType regty> { - defm _global: NVVM_WMMA_STD_LST<Layout, ".global", Type, regty>; - defm _shared: NVVM_WMMA_STD_LST<Layout, ".shared", Type, regty>; - defm NAME: NVVM_WMMA_STD_LST<Layout, "", Type, regty>; +multiclass NVVM_WMMA_STD_GT<string Geometry, string Type, LLVMType regty> { + defm _row: NVVM_WMMA_STD_GLT<Geometry, "row", Type, regty>; + defm _col: NVVM_WMMA_STD_GLT<Geometry, "col", Type, regty>; } - -multiclass NVVM_WMMA_STD_T<string Type, LLVMType regty> { - defm _row: NVVM_WMMA_STD_LT<"row", Type, regty>; - defm _col: NVVM_WMMA_STD_LT<"col", Type, regty>; +multiclass NVVM_WMMA_STD_G<string Geometry> { + defm _d_f16: NVVM_WMMA_STD_GT<Geometry, "f16", llvm_v2f16_ty>; + defm _d_f32: NVVM_WMMA_STD_GT<Geometry, "f32", llvm_float_ty>; } -let IntrProperties = [IntrWriteMem, IntrArgMemOnly, - WriteOnly<0>, NoCapture<0>] in { - defm int_nvvm_wmma_store_d_f16: NVVM_WMMA_STD_T<"f16", llvm_v2f16_ty>; - defm int_nvvm_wmma_store_d_f32: NVVM_WMMA_STD_T<"f32", llvm_float_ty>; +multiclass NVVM_WMMA_STD { + defm _m32n8k16_store: NVVM_WMMA_STD_G<"m32n8k16">; + defm _m16n16k16_store: NVVM_WMMA_STD_G<"m16n16k16">; + defm _m8n32k16_store: NVVM_WMMA_STD_G<"m8n32k16">; } +defm int_nvvm_wmma: NVVM_WMMA_STD; + // WMMA.MMA -class NVVM_WMMA_MMA_ABDCS<string ALayout, string BLayout, - string DType, LLVMType d_regty, - string CType, LLVMType c_regty, - string Satfinite = ""> +class NVVM_WMMA_MMA_GABDCS<string Geometry, + string ALayout, string BLayout, + string DType, LLVMType d_regty, + string CType, LLVMType c_regty, + string Satfinite = ""> : Intrinsic<!if(!eq(DType,"f16"), [d_regty, d_regty, d_regty, d_regty], [d_regty, d_regty, d_regty, d_regty, @@ -3990,39 +3994,54 @@ class NVVM_WMMA_MMA_ABDCS<string ALayout, string BLayout, [c_regty, c_regty, c_regty, c_regty, c_regty, c_regty, c_regty, c_regty])), [IntrNoMem], - "llvm.nvvm.wmma.mma.sync."#ALayout#"."#BLayout - #".m16n16k16."#DType#"."#CType#Satfinite>; + "llvm.nvvm.wmma." + # Geometry + # ".mma" + # "." # ALayout + # "." # BLayout + # "." # DType + # "." # CType + # Satfinite> { +} -multiclass NVVM_WMMA_MMA_ABDC<string ALayout, string BLayout, - string DType, LLVMType d_regty, - string CType, LLVMType c_regty> { - def NAME : NVVM_WMMA_MMA_ABDCS<ALayout, BLayout, - DType, d_regty, - CType, c_regty>; - def _satfinite: NVVM_WMMA_MMA_ABDCS<ALayout, BLayout, - DType, d_regty, - CType, c_regty,".satfinite">; +multiclass NVVM_WMMA_MMA_GABDC<string Geometry, string ALayout, string BLayout, + string DType, LLVMType d_regty, + string CType, LLVMType c_regty> { + def NAME : NVVM_WMMA_MMA_GABDCS<Geometry, ALayout, BLayout, + DType, d_regty, CType, c_regty>; + def _satfinite: NVVM_WMMA_MMA_GABDCS<Geometry, ALayout, BLayout, + DType, d_regty, CType, c_regty,".satfinite">; } -multiclass NVVM_WMMA_MMA_ABD<string ALayout, string BLayout, +multiclass NVVM_WMMA_MMA_GABD<string Geometry, string ALayout, string BLayout, string DType, LLVMType d_regty> { - defm _f16: NVVM_WMMA_MMA_ABDC<ALayout, BLayout, DType, d_regty, + defm _f16: NVVM_WMMA_MMA_GABDC<Geometry, ALayout, BLayout, DType, d_regty, "f16", llvm_v2f16_ty>; - defm _f32: NVVM_WMMA_MMA_ABDC<ALayout, BLayout, DType, d_regty, + defm _f32: NVVM_WMMA_MMA_GABDC<Geometry, ALayout, BLayout, DType, d_regty, "f32", llvm_float_ty>; } -multiclass NVVM_WMMA_MMA_AB<string ALayout, string BLayout> { - defm _f16: NVVM_WMMA_MMA_ABD<ALayout, BLayout, "f16", llvm_v2f16_ty>; - defm _f32: NVVM_WMMA_MMA_ABD<ALayout, BLayout, "f32", llvm_float_ty>; +multiclass NVVM_WMMA_MMA_GAB<string Geometry, string ALayout, string BLayout> { + defm _f16: NVVM_WMMA_MMA_GABD<Geometry, ALayout, BLayout, "f16", llvm_v2f16_ty>; + defm _f32: NVVM_WMMA_MMA_GABD<Geometry, ALayout, BLayout, "f32", llvm_float_ty>; +} + +multiclass NVVM_WMMA_MMA_GA<string Geometry, string ALayout> { + defm _col: NVVM_WMMA_MMA_GAB<Geometry, ALayout, "col">; + defm _row: NVVM_WMMA_MMA_GAB<Geometry, ALayout, "row">; +} + +multiclass NVVM_WMMA_MMA_G<string Geometry> { + defm _col: NVVM_WMMA_MMA_GA<Geometry, "col">; + defm _row: NVVM_WMMA_MMA_GA<Geometry, "row">; } -multiclass NVVM_WMMA_MMA_A<string ALayout> { - defm _col: NVVM_WMMA_MMA_AB<ALayout, "col">; - defm _row: NVVM_WMMA_MMA_AB<ALayout, "row">; +multiclass NVVM_WMMA_MMA { + defm _m32n8k16_mma : NVVM_WMMA_MMA_G<"m32n8k16">; + defm _m16n16k16_mma : NVVM_WMMA_MMA_G<"m16n16k16">; + defm _m8n32k16_mma : NVVM_WMMA_MMA_G<"m8n32k16">; } -defm int_nvvm_wmma_mma_sync_col: NVVM_WMMA_MMA_A<"col">; -defm int_nvvm_wmma_mma_sync_row: NVVM_WMMA_MMA_A<"row">; +defm int_nvvm_wmma : NVVM_WMMA_MMA; } // let TargetPrefix = "nvvm" diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td index a302d5726aa3..c4e753af25ca 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -61,6 +61,29 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">, Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; + + def int_ppc_truncf128_round_to_odd + : GCCBuiltin<"__builtin_truncf128_round_to_odd">, + Intrinsic <[llvm_double_ty], [llvm_f128_ty], [IntrNoMem]>; + def int_ppc_sqrtf128_round_to_odd + : GCCBuiltin<"__builtin_sqrtf128_round_to_odd">, + Intrinsic <[llvm_f128_ty], [llvm_f128_ty], [IntrNoMem]>; + def int_ppc_addf128_round_to_odd + : GCCBuiltin<"__builtin_addf128_round_to_odd">, + Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; + def int_ppc_subf128_round_to_odd + : GCCBuiltin<"__builtin_subf128_round_to_odd">, + Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; + def int_ppc_mulf128_round_to_odd + : GCCBuiltin<"__builtin_mulf128_round_to_odd">, + Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; + def int_ppc_divf128_round_to_odd + : GCCBuiltin<"__builtin_divf128_round_to_odd">, + Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; + def int_ppc_fmaf128_round_to_odd + : GCCBuiltin<"__builtin_fmaf128_round_to_odd">, + Intrinsic <[llvm_f128_ty], [llvm_f128_ty,llvm_f128_ty,llvm_f128_ty], [IntrNoMem]>; + } diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/contrib/llvm/include/llvm/IR/IntrinsicsWebAssembly.td index 640ef627bc46..7afc755a1e37 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsWebAssembly.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsWebAssembly.td @@ -8,19 +8,60 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file defines all of the WebAssembly-specific intrinsics. +/// This file defines all of the WebAssembly-specific intrinsics. /// //===----------------------------------------------------------------------===// let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.". -// Note that current_memory is not IntrNoMem because it must be sequenced with -// respect to grow_memory calls. +// Query the current memory size, and increase the current memory size. +// Note that memory.size is not IntrNoMem because it must be sequenced with +// respect to memory.grow calls. +def int_wasm_memory_size : Intrinsic<[llvm_anyint_ty], + [llvm_i32_ty], + [IntrReadMem]>; +def int_wasm_memory_grow : Intrinsic<[llvm_anyint_ty], + [llvm_i32_ty, LLVMMatchType<0>], + []>; + +// These are the old names. +def int_wasm_mem_size : Intrinsic<[llvm_anyint_ty], + [llvm_i32_ty], + [IntrReadMem]>; +def int_wasm_mem_grow : Intrinsic<[llvm_anyint_ty], + [llvm_i32_ty, LLVMMatchType<0>], + []>; + +// These are the old old names. They also lack the immediate field. def int_wasm_current_memory : Intrinsic<[llvm_anyint_ty], [], [IntrReadMem]>; def int_wasm_grow_memory : Intrinsic<[llvm_anyint_ty], [LLVMMatchType<0>], []>; +//===----------------------------------------------------------------------===// // Exception handling intrinsics -def int_wasm_throw: Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], [Throws]>; -def int_wasm_rethrow: Intrinsic<[], [], [Throws]>; +//===----------------------------------------------------------------------===// + +// throw / rethrow +def int_wasm_throw : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], + [Throws, IntrNoReturn]>; +def int_wasm_rethrow : Intrinsic<[], [], [Throws, IntrNoReturn]>; + +// Since wasm does not use landingpad instructions, these instructions return +// exception pointer and selector values until we lower them in WasmEHPrepare. +def int_wasm_get_exception : Intrinsic<[llvm_ptr_ty], [llvm_token_ty], + [IntrHasSideEffects]>; +def int_wasm_get_ehselector : Intrinsic<[llvm_i32_ty], [llvm_token_ty], + [IntrHasSideEffects]>; + +// wasm.catch returns the pointer to the exception object caught by wasm 'catch' +// instruction. +def int_wasm_catch : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], + [IntrHasSideEffects]>; + +// WebAssembly EH must maintain the landingpads in the order assigned to them +// by WasmEHPrepare pass to generate landingpad table in EHStreamer. This is +// used in order to give them the indices in WasmEHPrepare. +def int_wasm_landingpad_index: Intrinsic<[], [llvm_i32_ty], [IntrNoMem]>; +// Returns LSDA address of the current function. +def int_wasm_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; } diff --git a/contrib/llvm/include/llvm/IR/IntrinsicsX86.td b/contrib/llvm/include/llvm/IR/IntrinsicsX86.td index 7c000e2b1dc7..905afc130d8f 100644 --- a/contrib/llvm/include/llvm/IR/IntrinsicsX86.td +++ b/contrib/llvm/include/llvm/IR/IntrinsicsX86.td @@ -63,6 +63,12 @@ let TargetPrefix = "x86" in { Intrinsic<[llvm_i64_ty], [llvm_i32_ty], []>; } +// Read processor ID. +let TargetPrefix = "x86" in { + def int_x86_rdpid : GCCBuiltin<"__builtin_ia32_rdpid">, + Intrinsic<[llvm_i32_ty], [], []>; +} + //===----------------------------------------------------------------------===// // CET SS let TargetPrefix = "x86" in { @@ -174,12 +180,6 @@ let TargetPrefix = "x86" in { // Arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_sse_sqrt_ps : GCCBuiltin<"__builtin_ia32_sqrtps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], - [IntrNoMem]>; def int_x86_sse_rcp_ss : GCCBuiltin<"__builtin_ia32_rcpss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; @@ -211,6 +211,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse_cmp_ss : GCCBuiltin<"__builtin_ia32_cmpss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + // NOTE: This comparison intrinsic is not used by clang as long as the + // distinction in signaling behaviour is not implemented. def int_x86_sse_cmp_ps : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; @@ -263,12 +265,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_x86_sse_cvttss2si64 : GCCBuiltin<"__builtin_ia32_cvttss2si64">, Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_sse_cvtsi2ss : // TODO: Remove this intrinsic. - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse_cvtsi642ss : // TODO: Remove this intrinsic. - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i64_ty], [IntrNoMem]>; def int_x86_sse_cvtps2pi : GCCBuiltin<"__builtin_ia32_cvtps2pi">, Intrinsic<[llvm_x86mmx_ty], [llvm_v4f32_ty], [IntrNoMem]>; @@ -304,12 +300,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // FP arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_sse2_sqrt_pd : GCCBuiltin<"__builtin_ia32_sqrtpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], - [IntrNoMem]>; def int_x86_sse2_min_sd : GCCBuiltin<"__builtin_ia32_minsd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; @@ -329,6 +319,8 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_cmp_sd : GCCBuiltin<"__builtin_ia32_cmpsd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + // NOTE: This comparison intrinsic is not used by clang as long as the + // distinction in signaling behaviour is not implemented. def int_x86_sse2_cmp_pd : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; @@ -402,9 +394,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw128">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem, Commutative]>; - def int_x86_sse2_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem, Commutative]>; @@ -468,8 +457,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Conversion ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_cvtdq2ps : GCCBuiltin<"__builtin_ia32_cvtdq2ps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4i32_ty], [IntrNoMem]>; def int_x86_sse2_cvtpd2dq : GCCBuiltin<"__builtin_ia32_cvtpd2dq">, Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; def int_x86_sse2_cvttpd2dq : GCCBuiltin<"__builtin_ia32_cvttpd2dq">, @@ -488,18 +475,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; def int_x86_sse2_cvttsd2si64 : GCCBuiltin<"__builtin_ia32_cvttsd2si64">, Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_cvtsi2sd : // TODO: Remove this intrinsic. - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_sse2_cvtsi642sd : // TODO: Remove this intrinsic. - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_i64_ty], [IntrNoMem]>; def int_x86_sse2_cvtsd2ss : GCCBuiltin<"__builtin_ia32_cvtsd2ss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_sse2_cvtss2sd : // TODO: Remove this intrinsic. - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_v4f32_ty], [IntrNoMem]>; def int_x86_sse_cvtpd2pi : GCCBuiltin<"__builtin_ia32_cvtpd2pi">, Intrinsic<[llvm_x86mmx_ty], [llvm_v2f64_ty], [IntrNoMem]>; def int_x86_sse_cvttpd2pi: GCCBuiltin<"__builtin_ia32_cvttpd2pi">, @@ -797,13 +775,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [IntrNoMem]>; } -// Vector multiply -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse41_pmuldq : GCCBuiltin<"__builtin_ia32_pmuldq128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem, Commutative]>; -} - // Vector insert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">, @@ -982,11 +953,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx_sqrt_pd_256 : GCCBuiltin<"__builtin_ia32_sqrtpd256">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx_sqrt_ps_256 : GCCBuiltin<"__builtin_ia32_sqrtps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx_rsqrt_ps_256 : GCCBuiltin<"__builtin_ia32_rsqrtps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty], [IntrNoMem]>; @@ -1033,325 +999,99 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_vpermilvarps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermi2var_d_128 : - GCCBuiltin<"__builtin_ia32_vpermi2vard128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_d_256 : - GCCBuiltin<"__builtin_ia32_vpermi2vard256_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_d_512 : - GCCBuiltin<"__builtin_ia32_vpermi2vard512_mask">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_hi_128 : - GCCBuiltin<"__builtin_ia32_vpermi2varhi128_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_hi_256 : - GCCBuiltin<"__builtin_ia32_vpermi2varhi256_mask">, - Intrinsic<[llvm_v16i16_ty], - [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_hi_512 : - GCCBuiltin<"__builtin_ia32_vpermi2varhi512_mask">, - Intrinsic<[llvm_v32i16_ty], - [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_pd_128 : - GCCBuiltin<"__builtin_ia32_vpermi2varpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_pd_256 : - GCCBuiltin<"__builtin_ia32_vpermi2varpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_pd_512 : - GCCBuiltin<"__builtin_ia32_vpermi2varpd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_ps_128 : - GCCBuiltin<"__builtin_ia32_vpermi2varps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_ps_256 : - GCCBuiltin<"__builtin_ia32_vpermi2varps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_ps_512 : - GCCBuiltin<"__builtin_ia32_vpermi2varps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_q_128 : - GCCBuiltin<"__builtin_ia32_vpermi2varq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_q_256 : - GCCBuiltin<"__builtin_ia32_vpermi2varq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermi2var_q_512 : - GCCBuiltin<"__builtin_ia32_vpermi2varq512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_d_512: - GCCBuiltin<"__builtin_ia32_vpermt2vard512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_q_512: - GCCBuiltin<"__builtin_ia32_vpermt2varq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_ps_512: - GCCBuiltin<"__builtin_ia32_vpermt2varps512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, - llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_pd_512: - GCCBuiltin<"__builtin_ia32_vpermt2varpd512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8i64_ty, - llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_d_128 : - GCCBuiltin<"__builtin_ia32_vpermt2vard128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vpermt2var_d_128 : - GCCBuiltin<"__builtin_ia32_vpermt2vard128_maskz">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_d_256 : - GCCBuiltin<"__builtin_ia32_vpermt2vard256_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vpermt2var_d_256 : - GCCBuiltin<"__builtin_ia32_vpermt2vard256_maskz">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vpermt2var_d_512 : - GCCBuiltin<"__builtin_ia32_vpermt2vard512_maskz">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_hi_128 : - GCCBuiltin<"__builtin_ia32_vpermt2varhi128_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vpermt2var_hi_128 : - GCCBuiltin<"__builtin_ia32_vpermt2varhi128_maskz">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_hi_256 : - GCCBuiltin<"__builtin_ia32_vpermt2varhi256_mask">, - Intrinsic<[llvm_v16i16_ty], - [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vpermt2var_hi_256 : - GCCBuiltin<"__builtin_ia32_vpermt2varhi256_maskz">, - Intrinsic<[llvm_v16i16_ty], - [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_hi_512 : - GCCBuiltin<"__builtin_ia32_vpermt2varhi512_mask">, - Intrinsic<[llvm_v32i16_ty], - [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vpermt2var_hi_512 : - GCCBuiltin<"__builtin_ia32_vpermt2varhi512_maskz">, - Intrinsic<[llvm_v32i16_ty], - [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_pd_128 : - GCCBuiltin<"__builtin_ia32_vpermt2varpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2i64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_d_128 : + GCCBuiltin<"__builtin_ia32_vpermi2vard128">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpermt2var_pd_128 : - GCCBuiltin<"__builtin_ia32_vpermt2varpd128_maskz">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2i64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_pd_256 : - GCCBuiltin<"__builtin_ia32_vpermt2varpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4i64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vpermt2var_pd_256 : - GCCBuiltin<"__builtin_ia32_vpermt2varpd256_maskz">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4i64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vpermt2var_pd_512 : - GCCBuiltin<"__builtin_ia32_vpermt2varpd512_maskz">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8i64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_ps_128 : - GCCBuiltin<"__builtin_ia32_vpermt2varps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vpermt2var_ps_128 : - GCCBuiltin<"__builtin_ia32_vpermt2varps128_maskz">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vpermt2var_ps_256 : - GCCBuiltin<"__builtin_ia32_vpermt2varps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8i32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_d_256 : + GCCBuiltin<"__builtin_ia32_vpermi2vard256">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpermt2var_ps_256 : - GCCBuiltin<"__builtin_ia32_vpermt2varps256_maskz">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8i32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_d_512 : + GCCBuiltin<"__builtin_ia32_vpermi2vard512">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty], + [IntrNoMem]>; - def int_x86_avx512_maskz_vpermt2var_ps_512 : - GCCBuiltin<"__builtin_ia32_vpermt2varps512_maskz">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16i32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_hi_128 : + GCCBuiltin<"__builtin_ia32_vpermi2varhi128">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermt2var_q_128 : - GCCBuiltin<"__builtin_ia32_vpermt2varq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_hi_256 : + GCCBuiltin<"__builtin_ia32_vpermi2varhi256">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty], + [IntrNoMem]>; - def int_x86_avx512_maskz_vpermt2var_q_128 : - GCCBuiltin<"__builtin_ia32_vpermt2varq128_maskz">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_hi_512 : + GCCBuiltin<"__builtin_ia32_vpermi2varhi512">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty], + [IntrNoMem]>; - def int_x86_avx512_mask_vpermt2var_q_256 : - GCCBuiltin<"__builtin_ia32_vpermt2varq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_pd_128 : + GCCBuiltin<"__builtin_ia32_vpermi2varpd128">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2i64_ty, llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpermt2var_q_256 : - GCCBuiltin<"__builtin_ia32_vpermt2varq256_maskz">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_pd_256 : + GCCBuiltin<"__builtin_ia32_vpermi2varpd256">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4i64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpermt2var_q_512 : - GCCBuiltin<"__builtin_ia32_vpermt2varq512_maskz">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_pd_512 : + GCCBuiltin<"__builtin_ia32_vpermi2varpd512">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8i64_ty, llvm_v8f64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermi2var_qi_128 : - GCCBuiltin<"__builtin_ia32_vpermi2varqi128_mask">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, - llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_ps_128 : + GCCBuiltin<"__builtin_ia32_vpermi2varps128">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4i32_ty, llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermt2var_qi_128 : - GCCBuiltin<"__builtin_ia32_vpermt2varqi128_mask">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, - llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_ps_256 : + GCCBuiltin<"__builtin_ia32_vpermi2varps256">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8i32_ty, llvm_v8f32_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpermt2var_qi_128 : - GCCBuiltin<"__builtin_ia32_vpermt2varqi128_maskz">, - Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, - llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_ps_512 : + GCCBuiltin<"__builtin_ia32_vpermi2varps512">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16i32_ty, llvm_v16f32_ty], + [IntrNoMem]>; - def int_x86_avx512_mask_vpermi2var_qi_256 : - GCCBuiltin<"__builtin_ia32_vpermi2varqi256_mask">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, - llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_q_128 : + GCCBuiltin<"__builtin_ia32_vpermi2varq128">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermt2var_qi_256 : - GCCBuiltin<"__builtin_ia32_vpermt2varqi256_mask">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, - llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_q_256 : + GCCBuiltin<"__builtin_ia32_vpermi2varq256">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpermt2var_qi_256 : - GCCBuiltin<"__builtin_ia32_vpermt2varqi256_maskz">, - Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, - llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_q_512 : + GCCBuiltin<"__builtin_ia32_vpermi2varq512">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermi2var_qi_512 : - GCCBuiltin<"__builtin_ia32_vpermi2varqi512_mask">, - Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, - llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_qi_128 : + GCCBuiltin<"__builtin_ia32_vpermi2varqi128">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermt2var_qi_512 : - GCCBuiltin<"__builtin_ia32_vpermt2varqi512_mask">, - Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, - llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_qi_256 : + GCCBuiltin<"__builtin_ia32_vpermi2varqi256">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpermt2var_qi_512 : - GCCBuiltin<"__builtin_ia32_vpermt2varqi512_maskz">, - Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, - llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], - [IntrNoMem]>; + def int_x86_avx512_vpermi2var_qi_512 : + GCCBuiltin<"__builtin_ia32_vpermi2varqi512">, + Intrinsic<[llvm_v64i8_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty], [IntrNoMem]>; def int_x86_avx512_vpermilvar_pd_512 : GCCBuiltin<"__builtin_ia32_vpermilvarpd512">, @@ -1450,8 +1190,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector convert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx_cvtdq2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtdq2ps256">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8i32_ty], [IntrNoMem]>; def int_x86_avx_cvt_pd2_ps_256 : GCCBuiltin<"__builtin_ia32_cvtpd2ps256">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f64_ty], [IntrNoMem]>; def int_x86_avx_cvt_ps2dq_256 : GCCBuiltin<"__builtin_ia32_cvtps2dq256">, @@ -1512,29 +1250,23 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_i32_ty], [llvm_v4i64_ty, llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_fpclass_pd_128 : - GCCBuiltin<"__builtin_ia32_fpclasspd128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_i32_ty, llvm_i8_ty], + def int_x86_avx512_fpclass_pd_128 : + Intrinsic<[llvm_v2i1_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_fpclass_pd_256 : - GCCBuiltin<"__builtin_ia32_fpclasspd256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4f64_ty, llvm_i32_ty, llvm_i8_ty], + def int_x86_avx512_fpclass_pd_256 : + Intrinsic<[llvm_v4i1_ty], [llvm_v4f64_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_fpclass_pd_512 : - GCCBuiltin<"__builtin_ia32_fpclasspd512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_i8_ty], + def int_x86_avx512_fpclass_pd_512 : + Intrinsic<[llvm_v8i1_ty], [llvm_v8f64_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_fpclass_ps_128 : - GCCBuiltin<"__builtin_ia32_fpclassps128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_i32_ty, llvm_i8_ty], + def int_x86_avx512_fpclass_ps_128 : + Intrinsic<[llvm_v4i1_ty], [llvm_v4f32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_fpclass_ps_256 : - GCCBuiltin<"__builtin_ia32_fpclassps256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8f32_ty, llvm_i32_ty, llvm_i8_ty], + def int_x86_avx512_fpclass_ps_256 : + Intrinsic<[llvm_v8i1_ty], [llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_fpclass_ps_512 : - GCCBuiltin<"__builtin_ia32_fpclassps512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_i16_ty], + def int_x86_avx512_fpclass_ps_512 : + Intrinsic<[llvm_v16i1_ty], [llvm_v16f32_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_fpclass_sd : GCCBuiltin<"__builtin_ia32_fpclasssd_mask">, @@ -1600,11 +1332,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_maskstoreps256">, Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, llvm_v8f32_ty], [IntrArgMemOnly]>; - - def int_x86_avx512_mask_store_ss : - GCCBuiltin<"__builtin_ia32_storess_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrArgMemOnly]>; } // BITALG bits shuffle @@ -1661,12 +1388,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw256">, Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem, Commutative]>; - def int_x86_avx2_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem, Commutative]>; - def int_x86_avx2_pmul_dq : GCCBuiltin<"__builtin_ia32_pmuldq256">, - Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, - llvm_v8i32_ty], [IntrNoMem, Commutative]>; def int_x86_avx2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem, Commutative]>; @@ -1870,15 +1591,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw256">, Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem, Commutative]>; - def int_x86_avx512_mask_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128_mask">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmul_hr_sw_256 : GCCBuiltin<"__builtin_ia32_pmulhrsw256_mask">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, - llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmul_hr_sw_512 : GCCBuiltin<"__builtin_ia32_pmulhrsw512_mask">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, - llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_pmul_hr_sw_512 : GCCBuiltin<"__builtin_ia32_pmulhrsw512">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, + llvm_v32i16_ty], [IntrNoMem, Commutative]>; } // Vector blend @@ -2025,81 +1740,81 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prorv_d_128 : GCCBuiltin<"__builtin_ia32_prorvd128_mask">, + def int_x86_avx512_prorv_d_128 : GCCBuiltin<"__builtin_ia32_prorvd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prorv_d_256 : GCCBuiltin<"__builtin_ia32_prorvd256_mask">, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512_prorv_d_256 : GCCBuiltin<"__builtin_ia32_prorvd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prorv_d_512 : GCCBuiltin<"__builtin_ia32_prorvd512_mask">, + llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx512_prorv_d_512 : GCCBuiltin<"__builtin_ia32_prorvd512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prorv_q_128 : GCCBuiltin<"__builtin_ia32_prorvq128_mask">, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_prorv_q_128 : GCCBuiltin<"__builtin_ia32_prorvq128">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prorv_q_256 : GCCBuiltin<"__builtin_ia32_prorvq256_mask">, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx512_prorv_q_256 : GCCBuiltin<"__builtin_ia32_prorvq256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prorv_q_512 : GCCBuiltin<"__builtin_ia32_prorvq512_mask">, + llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx512_prorv_q_512 : GCCBuiltin<"__builtin_ia32_prorvq512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v8i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prol_d_128 : GCCBuiltin<"__builtin_ia32_prold128_mask">, + def int_x86_avx512_prol_d_128 : GCCBuiltin<"__builtin_ia32_prold128">, Intrinsic<[llvm_v4i32_ty] , [llvm_v4i32_ty, - llvm_i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prol_d_256 : GCCBuiltin<"__builtin_ia32_prold256_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_prol_d_256 : GCCBuiltin<"__builtin_ia32_prold256">, Intrinsic<[llvm_v8i32_ty] , [llvm_v8i32_ty, - llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prol_d_512 : GCCBuiltin<"__builtin_ia32_prold512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_prol_d_512 : GCCBuiltin<"__builtin_ia32_prold512">, Intrinsic<[llvm_v16i32_ty] , [llvm_v16i32_ty, - llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prol_q_128 : GCCBuiltin<"__builtin_ia32_prolq128_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_prol_q_128 : GCCBuiltin<"__builtin_ia32_prolq128">, Intrinsic<[llvm_v2i64_ty] , [llvm_v2i64_ty, - llvm_i32_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prol_q_256 : GCCBuiltin<"__builtin_ia32_prolq256_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_prol_q_256 : GCCBuiltin<"__builtin_ia32_prolq256">, Intrinsic<[llvm_v4i64_ty] , [llvm_v4i64_ty, - llvm_i32_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prol_q_512 : GCCBuiltin<"__builtin_ia32_prolq512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_prol_q_512 : GCCBuiltin<"__builtin_ia32_prolq512">, Intrinsic<[llvm_v8i64_ty] , [llvm_v8i64_ty, - llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prolv_d_128 : GCCBuiltin<"__builtin_ia32_prolvd128_mask">, + def int_x86_avx512_prolv_d_128 : GCCBuiltin<"__builtin_ia32_prolvd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prolv_d_256 : GCCBuiltin<"__builtin_ia32_prolvd256_mask">, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512_prolv_d_256 : GCCBuiltin<"__builtin_ia32_prolvd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prolv_d_512 : GCCBuiltin<"__builtin_ia32_prolvd512_mask">, + llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx512_prolv_d_512 : GCCBuiltin<"__builtin_ia32_prolvd512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prolv_q_128 : GCCBuiltin<"__builtin_ia32_prolvq128_mask">, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_prolv_q_128 : GCCBuiltin<"__builtin_ia32_prolvq128">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prolv_q_256 : GCCBuiltin<"__builtin_ia32_prolvq256_mask">, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx512_prolv_q_256 : GCCBuiltin<"__builtin_ia32_prolvq256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_prolv_q_512 : GCCBuiltin<"__builtin_ia32_prolvq512_mask">, + llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx512_prolv_q_512 : GCCBuiltin<"__builtin_ia32_prolvq512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pror_d_128 : GCCBuiltin<"__builtin_ia32_prord128_mask">, + llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_pror_d_128 : GCCBuiltin<"__builtin_ia32_prord128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, - llvm_i32_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pror_d_256 : GCCBuiltin<"__builtin_ia32_prord256_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_pror_d_256 : GCCBuiltin<"__builtin_ia32_prord256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pror_d_512 : GCCBuiltin<"__builtin_ia32_prord512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_pror_d_512 : GCCBuiltin<"__builtin_ia32_prord512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pror_q_128 : GCCBuiltin<"__builtin_ia32_prorq128_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_pror_q_128 : GCCBuiltin<"__builtin_ia32_prorq128">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, - llvm_i32_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pror_q_256 : GCCBuiltin<"__builtin_ia32_prorq256_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_pror_q_256 : GCCBuiltin<"__builtin_ia32_prorq256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_i32_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pror_q_512 : GCCBuiltin<"__builtin_ia32_prorq512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_pror_q_512 : GCCBuiltin<"__builtin_ia32_prorq512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem]>; } @@ -2188,754 +1903,115 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // FMA3 and FMA4 let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_fma_vfmadd_ss : GCCBuiltin<"__builtin_ia32_vfmaddss3">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmadd_sd : GCCBuiltin<"__builtin_ia32_vfmaddsd3">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma4_vfmadd_ss : GCCBuiltin<"__builtin_ia32_vfmaddss">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma4_vfmadd_sd : GCCBuiltin<"__builtin_ia32_vfmaddsd">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfmadd_ps : GCCBuiltin<"__builtin_ia32_vfmaddps">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmadd_pd : GCCBuiltin<"__builtin_ia32_vfmaddpd">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], - [IntrNoMem]>; - - def int_x86_fma_vfmsub_ss : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmsub_sd : // TODO: remove this intrinsic - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfmsub_ps : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmsub_pd : // TODO: remove this intrinsic - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfmsub_ps_256 : // TODO: remove this intrinsic - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmsub_pd_256 : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmadd_ss : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmadd_sd : // TODO: remove this intrinsic - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmadd_ps : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmadd_pd : // TODO: remove this intrinsic - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmadd_ps_256 : // TODO: remove this intrinsic - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmadd_pd_256 : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmsub_ss : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmsub_sd : // TODO: remove this intrinsic - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmsub_ps : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmsub_pd : // TODO: remove this intrinsic - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmsub_ps_256 : // TODO: remove this intrinsic - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfnmsub_pd_256 : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmaddsub_pd : GCCBuiltin<"__builtin_ia32_vfmaddsubpd">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfmaddsub_ps_256 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps256">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmaddsub_pd_256 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd256">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfmsubadd_ps : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmsubadd_pd : // TODO: remove this intrinsic - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], - [IntrNoMem]>; - def int_x86_fma_vfmsubadd_ps_256 : // TODO: remove this intrinsic - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty], - [IntrNoMem]>; - def int_x86_fma_vfmsubadd_pd_256 : // TODO: remove this intrinsic - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfmadd_pd_128 : - GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmadd_pd_128 : - GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask3">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmadd_pd_128 : - GCCBuiltin<"__builtin_ia32_vfmaddpd128_maskz">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfmadd_pd_256 : - GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmadd_pd_256 : - GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask3">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmadd_pd_256 : - GCCBuiltin<"__builtin_ia32_vfmaddpd256_maskz">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfmadd_pd_512 : - GCCBuiltin<"__builtin_ia32_vfmaddpd512_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_mask3_vfmadd_pd_512 : - GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask3">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmadd_pd_512 : - GCCBuiltin<"__builtin_ia32_vfmaddpd512_maskz">, - 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_vfmadd_ps_128 : - GCCBuiltin<"__builtin_ia32_vfmaddps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmadd_ps_128 : - GCCBuiltin<"__builtin_ia32_vfmaddps128_mask3">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmadd_ps_128 : - GCCBuiltin<"__builtin_ia32_vfmaddps128_maskz">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfmadd_ps_256 : - GCCBuiltin<"__builtin_ia32_vfmaddps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmadd_ps_256 : - GCCBuiltin<"__builtin_ia32_vfmaddps256_mask3">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmadd_ps_256 : - GCCBuiltin<"__builtin_ia32_vfmaddps256_maskz">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfmadd_ps_512 : - GCCBuiltin<"__builtin_ia32_vfmaddps512_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_mask3_vfmadd_ps_512 : - GCCBuiltin<"__builtin_ia32_vfmaddps512_mask3">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmadd_ps_512 : - GCCBuiltin<"__builtin_ia32_vfmaddps512_maskz">, - 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_vfmaddsub_pd_128 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmaddsub_pd_128 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask3">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmaddsub_pd_128 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_maskz">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfmaddsub_pd_256 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmaddsub_pd_256 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask3">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmaddsub_pd_256 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_maskz">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfmaddsub_pd_512 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_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_mask3_vfmaddsub_pd_512 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask3">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmaddsub_pd_512 : - GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_maskz">, - 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_vfmaddsub_ps_128 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmaddsub_ps_128 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask3">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmaddsub_ps_128 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps128_maskz">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfmaddsub_ps_256 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmaddsub_ps_256 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask3">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmaddsub_ps_256 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps256_maskz">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfmaddsub_ps_512 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps512_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_mask3_vfmaddsub_ps_512 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps512_mask3">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmaddsub_ps_512 : - GCCBuiltin<"__builtin_ia32_vfmaddsubps512_maskz">, - 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_vfmadd_sd : - GCCBuiltin<"__builtin_ia32_vfmaddsd3_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_mask_vfmadd_ss : - GCCBuiltin<"__builtin_ia32_vfmaddss3_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_maskz_vfmadd_sd : - GCCBuiltin<"__builtin_ia32_vfmaddsd3_maskz">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_maskz_vfmadd_ss : - GCCBuiltin<"__builtin_ia32_vfmaddss3_maskz">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmadd_sd : - GCCBuiltin<"__builtin_ia32_vfmaddsd3_mask3">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmadd_ss : - GCCBuiltin<"__builtin_ia32_vfmaddss3_mask3">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsub_sd : - GCCBuiltin<"__builtin_ia32_vfmsubsd3_mask3">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsub_ss : - GCCBuiltin<"__builtin_ia32_vfmsubss3_mask3">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsub_pd_128 : - GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask3">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsub_pd_256 : - GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask3">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsub_pd_512 : - GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask3">, + def int_x86_avx512_vfmadd_pd_512 : Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsub_ps_128 : - GCCBuiltin<"__builtin_ia32_vfmsubps128_mask3">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsub_ps_256 : - GCCBuiltin<"__builtin_ia32_vfmsubps256_mask3">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsub_ps_512 : - GCCBuiltin<"__builtin_ia32_vfmsubps512_mask3">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsubadd_pd_128 : - GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask3">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsubadd_pd_256 : - GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask3">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsubadd_pd_512 : - GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask3">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsubadd_ps_128 : - GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask3">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfmsubadd_ps_256 : - GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask3">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask3_vfmsubadd_ps_512 : - GCCBuiltin<"__builtin_ia32_vfmsubaddps512_mask3">, + def int_x86_avx512_vfmadd_ps_512 : 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_vfnmadd_pd_128 : - GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vfnmadd_pd_256 : - GCCBuiltin<"__builtin_ia32_vfnmaddpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfnmadd_pd_512 : - GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">, + // TODO: Can we use 2 vfmadds+shufflevector? + def int_x86_avx512_vfmaddsub_pd_512 : 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_vfnmadd_ps_128 : - GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vfnmadd_ps_256 : - GCCBuiltin<"__builtin_ia32_vfnmaddps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfnmadd_ps_512 : - GCCBuiltin<"__builtin_ia32_vfnmaddps512_mask">, + def int_x86_avx512_vfmaddsub_ps_512 : Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask3_vfnmsub_sd : - GCCBuiltin<"__builtin_ia32_vfnmsubsd3_mask3">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask3_vfnmsub_ss : - GCCBuiltin<"__builtin_ia32_vfnmsubss3_mask3">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, - llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_vfnmsub_pd_128 : - GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfnmsub_pd_128 : - GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask3">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfnmsub_pd_256 : - GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfnmsub_pd_256 : - GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask3">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfnmsub_pd_512 : - GCCBuiltin<"__builtin_ia32_vfnmsubpd512_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_mask3_vfnmsub_pd_512 : - GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask3">, - 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_vfnmsub_ps_128 : - GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask3_vfnmsub_ps_128 : - GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask3">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfnmsub_ps_256 : - GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask3_vfnmsub_ps_256 : - GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask3">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_vfnmsub_ps_512 : - GCCBuiltin<"__builtin_ia32_vfnmsubps512_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_mask3_vfnmsub_ps_512 : - GCCBuiltin<"__builtin_ia32_vfnmsubps512_mask3">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, - llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vfmadd_f64 : + Intrinsic<[llvm_double_ty], + [llvm_double_ty, llvm_double_ty, llvm_double_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_vfmadd_f32 : + Intrinsic<[llvm_float_ty], + [llvm_float_ty, llvm_float_ty, llvm_float_ty, llvm_i32_ty], + [IntrNoMem]>; - def int_x86_avx512_mask_vpmadd52h_uq_128 : - GCCBuiltin<"__builtin_ia32_vpmadd52huq128_mask">, + def int_x86_avx512_vpmadd52h_uq_128 : + GCCBuiltin<"__builtin_ia32_vpmadd52huq128">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpmadd52h_uq_128 : - GCCBuiltin<"__builtin_ia32_vpmadd52huq128_maskz">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpmadd52l_uq_128 : - GCCBuiltin<"__builtin_ia32_vpmadd52luq128_mask">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpmadd52l_uq_128 : - GCCBuiltin<"__builtin_ia32_vpmadd52luq128_maskz">, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx512_vpmadd52l_uq_128 : + GCCBuiltin<"__builtin_ia32_vpmadd52luq128">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, - llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpmadd52h_uq_256 : - GCCBuiltin<"__builtin_ia32_vpmadd52huq256_mask">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, - llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpmadd52h_uq_256 : - GCCBuiltin<"__builtin_ia32_vpmadd52huq256_maskz">, - Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, - llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpmadd52l_uq_256 : - GCCBuiltin<"__builtin_ia32_vpmadd52luq256_mask">, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_avx512_vpmadd52h_uq_256 : + GCCBuiltin<"__builtin_ia32_vpmadd52huq256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, - llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpmadd52l_uq_256 : - GCCBuiltin<"__builtin_ia32_vpmadd52luq256_maskz">, + llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx512_vpmadd52l_uq_256 : + GCCBuiltin<"__builtin_ia32_vpmadd52luq256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, - llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpmadd52h_uq_512 : - GCCBuiltin<"__builtin_ia32_vpmadd52huq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpmadd52h_uq_512 : - GCCBuiltin<"__builtin_ia32_vpmadd52huq512_maskz">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpmadd52l_uq_512 : - GCCBuiltin<"__builtin_ia32_vpmadd52luq512_mask">, + llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx512_vpmadd52h_uq_512 : + GCCBuiltin<"__builtin_ia32_vpmadd52huq512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpmadd52l_uq_512 : - GCCBuiltin<"__builtin_ia32_vpmadd52luq512_maskz">, + llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_vpmadd52l_uq_512 : + GCCBuiltin<"__builtin_ia32_vpmadd52luq512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + llvm_v8i64_ty], [IntrNoMem]>; } // VNNI let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_mask_vpdpbusd_128 : - GCCBuiltin<"__builtin_ia32_vpdpbusd128_mask">, + def int_x86_avx512_vpdpbusd_128 : + GCCBuiltin<"__builtin_ia32_vpdpbusd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpbusd_128 : - GCCBuiltin<"__builtin_ia32_vpdpbusd128_maskz">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpbusd_256 : - GCCBuiltin<"__builtin_ia32_vpdpbusd256_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpbusd_256 : - GCCBuiltin<"__builtin_ia32_vpdpbusd256_maskz">, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpdpbusd_256 : + GCCBuiltin<"__builtin_ia32_vpdpbusd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpbusd_512 : - GCCBuiltin<"__builtin_ia32_vpdpbusd512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpbusd_512 : - GCCBuiltin<"__builtin_ia32_vpdpbusd512_maskz">, + llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpdpbusd_512 : + GCCBuiltin<"__builtin_ia32_vpdpbusd512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + llvm_v16i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpbusds_128 : - GCCBuiltin<"__builtin_ia32_vpdpbusds128_mask">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpbusds_128 : - GCCBuiltin<"__builtin_ia32_vpdpbusds128_maskz">, + def int_x86_avx512_vpdpbusds_128 : + GCCBuiltin<"__builtin_ia32_vpdpbusds128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpbusds_256 : - GCCBuiltin<"__builtin_ia32_vpdpbusds256_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpbusds_256 : - GCCBuiltin<"__builtin_ia32_vpdpbusds256_maskz">, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpdpbusds_256 : + GCCBuiltin<"__builtin_ia32_vpdpbusds256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpbusds_512 : - GCCBuiltin<"__builtin_ia32_vpdpbusds512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpbusds_512 : - GCCBuiltin<"__builtin_ia32_vpdpbusds512_maskz">, + llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpdpbusds_512 : + GCCBuiltin<"__builtin_ia32_vpdpbusds512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + llvm_v16i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpwssd_128 : - GCCBuiltin<"__builtin_ia32_vpdpwssd128_mask">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpwssd_128 : - GCCBuiltin<"__builtin_ia32_vpdpwssd128_maskz">, + def int_x86_avx512_vpdpwssd_128 : + GCCBuiltin<"__builtin_ia32_vpdpwssd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpwssd_256 : - GCCBuiltin<"__builtin_ia32_vpdpwssd256_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpwssd_256 : - GCCBuiltin<"__builtin_ia32_vpdpwssd256_maskz">, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpdpwssd_256 : + GCCBuiltin<"__builtin_ia32_vpdpwssd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpwssd_512 : - GCCBuiltin<"__builtin_ia32_vpdpwssd512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpwssd_512 : - GCCBuiltin<"__builtin_ia32_vpdpwssd512_maskz">, + llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpdpwssd_512 : + GCCBuiltin<"__builtin_ia32_vpdpwssd512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + llvm_v16i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpwssds_128 : - GCCBuiltin<"__builtin_ia32_vpdpwssds128_mask">, - Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpwssds_128 : - GCCBuiltin<"__builtin_ia32_vpdpwssds128_maskz">, + def int_x86_avx512_vpdpwssds_128 : + GCCBuiltin<"__builtin_ia32_vpdpwssds128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpwssds_256 : - GCCBuiltin<"__builtin_ia32_vpdpwssds256_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpwssds_256 : - GCCBuiltin<"__builtin_ia32_vpdpwssds256_maskz">, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpdpwssds_256 : + GCCBuiltin<"__builtin_ia32_vpdpwssds256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpdpwssds_512 : - GCCBuiltin<"__builtin_ia32_vpdpwssds512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_vpdpwssds_512 : - GCCBuiltin<"__builtin_ia32_vpdpwssds512_maskz">, + llvm_v8i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpdpwssds_512 : + GCCBuiltin<"__builtin_ia32_vpdpwssds512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + llvm_v16i32_ty], [IntrNoMem]>; } //===----------------------------------------------------------------------===// @@ -3050,62 +2126,62 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_vpmacsdd">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmacsdqh : GCCBuiltin<"__builtin_ia32_vpmacsdqh">, Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmacsdql : GCCBuiltin<"__builtin_ia32_vpmacsdql">, Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmacssdd : GCCBuiltin<"__builtin_ia32_vpmacssdd">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmacssdqh : GCCBuiltin<"__builtin_ia32_vpmacssdqh">, Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmacssdql : GCCBuiltin<"__builtin_ia32_vpmacssdql">, Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v2i64_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmacsswd : GCCBuiltin<"__builtin_ia32_vpmacsswd">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmacssww : GCCBuiltin<"__builtin_ia32_vpmacssww">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmacswd : GCCBuiltin<"__builtin_ia32_vpmacswd">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmacsww : GCCBuiltin<"__builtin_ia32_vpmacsww">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmadcsswd : GCCBuiltin<"__builtin_ia32_vpmadcsswd">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpmadcswd : GCCBuiltin<"__builtin_ia32_vpmadcswd">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty], - [IntrNoMem]>; + [IntrNoMem, Commutative]>; def int_x86_xop_vpperm : GCCBuiltin<"__builtin_ia32_vpperm">, Intrinsic<[llvm_v16i8_ty], @@ -3383,48 +2459,42 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } // Permute let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_mask_permvar_df_256 : GCCBuiltin<"__builtin_ia32_permvardf256_mask">, + def int_x86_avx512_permvar_df_256 : GCCBuiltin<"__builtin_ia32_permvardf256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_df_512 : GCCBuiltin<"__builtin_ia32_permvardf512_mask">, + llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_df_512 : GCCBuiltin<"__builtin_ia32_permvardf512">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, - llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_di_256 : GCCBuiltin<"__builtin_ia32_permvardi256_mask">, + llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_di_256 : GCCBuiltin<"__builtin_ia32_permvardi256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, - llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_di_512 : GCCBuiltin<"__builtin_ia32_permvardi512_mask">, + llvm_v4i64_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_di_512 : GCCBuiltin<"__builtin_ia32_permvardi512">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, - llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_hi_128 : GCCBuiltin<"__builtin_ia32_permvarhi128_mask">, + llvm_v8i64_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_hi_128 : GCCBuiltin<"__builtin_ia32_permvarhi128">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, - llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_hi_256 : GCCBuiltin<"__builtin_ia32_permvarhi256_mask">, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_hi_256 : GCCBuiltin<"__builtin_ia32_permvarhi256">, Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, - llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_hi_512 : GCCBuiltin<"__builtin_ia32_permvarhi512_mask">, + llvm_v16i16_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_hi_512 : GCCBuiltin<"__builtin_ia32_permvarhi512">, Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, - llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_qi_128 : GCCBuiltin<"__builtin_ia32_permvarqi128_mask">, + llvm_v32i16_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_qi_128 : GCCBuiltin<"__builtin_ia32_permvarqi128">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, - llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_qi_256 : GCCBuiltin<"__builtin_ia32_permvarqi256_mask">, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_qi_256 : GCCBuiltin<"__builtin_ia32_permvarqi256">, Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, - llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_qi_512 : GCCBuiltin<"__builtin_ia32_permvarqi512_mask">, + llvm_v32i8_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_qi_512 : GCCBuiltin<"__builtin_ia32_permvarqi512">, Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, - llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_sf_256 : GCCBuiltin<"__builtin_ia32_permvarsf256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_sf_512 : GCCBuiltin<"__builtin_ia32_permvarsf512_mask">, + llvm_v64i8_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_sf_512 : GCCBuiltin<"__builtin_ia32_permvarsf512">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, - llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_si_256 : GCCBuiltin<"__builtin_ia32_permvarsi256_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, - llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_permvar_si_512 : GCCBuiltin<"__builtin_ia32_permvarsi512_mask">, + llvm_v16i32_ty], [IntrNoMem]>; + def int_x86_avx512_permvar_si_512 : GCCBuiltin<"__builtin_ia32_permvarsi512">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, - llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + llvm_v16i32_ty], [IntrNoMem]>; } // Pack ops. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". @@ -3717,44 +2787,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". //===----------------------------------------------------------------------===// // AVX512 -// Mask ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - // Mask instructions - // 16-bit mask - def int_x86_avx512_kand_w : // TODO: remove this intrinsic - Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_kandn_w : // TODO: remove this intrinsic - Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_knot_w : // TODO: remove this intrinsic - Intrinsic<[llvm_i16_ty], [llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_kor_w : // TODO: remove this intrinsic - Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_kxor_w : // TODO: remove this intrinsic - Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_kxnor_w : // TODO: remove this intrinsic - Intrinsic<[llvm_i16_ty], [llvm_i16_ty, llvm_i16_ty], - [IntrNoMem]>; - 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_kunpck_wd : GCCBuiltin<"__builtin_ia32_kunpcksi">, - Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_avx512_kunpck_dq : GCCBuiltin<"__builtin_ia32_kunpckdi">, - Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], - [IntrNoMem]>; - 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_w : GCCBuiltin<"__builtin_ia32_kortestchi">, - Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty], - [IntrNoMem]>; -} - // Conversion ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_cvttss2si : GCCBuiltin<"__builtin_ia32_vcvttss2si32">, @@ -3779,9 +2811,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_cvttsd2usi64 : GCCBuiltin<"__builtin_ia32_vcvttsd2usi64">, Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_cvtusi2sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd32">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd64">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>; @@ -3810,35 +2839,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_cvtsi2sd64 : GCCBuiltin<"__builtin_ia32_cvtsi2sd64">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_cvtb2mask_128 : GCCBuiltin<"__builtin_ia32_cvtb2mask128">, - Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; - def int_x86_avx512_cvtb2mask_256 : GCCBuiltin<"__builtin_ia32_cvtb2mask256">, - Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty], [IntrNoMem]>; - def int_x86_avx512_cvtb2mask_512 : GCCBuiltin<"__builtin_ia32_cvtb2mask512">, - Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty], [IntrNoMem]>; - - def int_x86_avx512_cvtw2mask_128 : GCCBuiltin<"__builtin_ia32_cvtw2mask128">, - Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty], [IntrNoMem]>; - def int_x86_avx512_cvtw2mask_256 : GCCBuiltin<"__builtin_ia32_cvtw2mask256">, - Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; - def int_x86_avx512_cvtw2mask_512 : GCCBuiltin<"__builtin_ia32_cvtw2mask512">, - Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty], [IntrNoMem]>; - - def int_x86_avx512_cvtd2mask_128 : GCCBuiltin<"__builtin_ia32_cvtd2mask128">, - Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty], [IntrNoMem]>; - def int_x86_avx512_cvtd2mask_256 : GCCBuiltin<"__builtin_ia32_cvtd2mask256">, - Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx512_cvtd2mask_512 : GCCBuiltin<"__builtin_ia32_cvtd2mask512">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty], [IntrNoMem]>; - - def int_x86_avx512_cvtq2mask_128 : GCCBuiltin<"__builtin_ia32_cvtq2mask128">, - Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_avx512_cvtq2mask_256 : GCCBuiltin<"__builtin_ia32_cvtq2mask256">, - Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty], [IntrNoMem]>; - def int_x86_avx512_cvtq2mask_512 : GCCBuiltin<"__builtin_ia32_cvtq2mask512">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty], [IntrNoMem]>; - } // Pack ops. @@ -3859,18 +2859,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector convert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_mask_cvtdq2ps_128 : - GCCBuiltin<"__builtin_ia32_cvtdq2ps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtdq2ps_256 : - GCCBuiltin<"__builtin_ia32_cvtdq2ps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_cvtdq2ps_512 : GCCBuiltin<"__builtin_ia32_cvtdq2ps512_mask">, Intrinsic<[llvm_v16f32_ty], @@ -3883,24 +2871,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtpd2dq_256 : - GCCBuiltin<"__builtin_ia32_cvtpd2dq256_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_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_cvtpd2ps_256 : - GCCBuiltin<"__builtin_ia32_cvtpd2ps256_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f64_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_cvtpd2ps_512 : GCCBuiltin<"__builtin_ia32_cvtpd2ps512_mask">, Intrinsic<[llvm_v8f32_ty], @@ -3997,18 +2973,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtps2pd_128 : - GCCBuiltin<"__builtin_ia32_cvtps2pd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v4f32_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtps2pd_256 : - GCCBuiltin<"__builtin_ia32_cvtps2pd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f32_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_cvtps2pd_512 : GCCBuiltin<"__builtin_ia32_cvtps2pd512_mask">, Intrinsic<[llvm_v8f64_ty], @@ -4069,18 +3033,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtqq2pd_128 : - GCCBuiltin<"__builtin_ia32_cvtqq2pd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtqq2pd_256 : - GCCBuiltin<"__builtin_ia32_cvtqq2pd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_cvtqq2pd_512 : GCCBuiltin<"__builtin_ia32_cvtqq2pd512_mask">, Intrinsic<[llvm_v8f64_ty], @@ -4111,12 +3063,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvttpd2dq_256 : - GCCBuiltin<"__builtin_ia32_cvttpd2dq256_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_cvttpd2dq_512 : GCCBuiltin<"__builtin_ia32_cvttpd2dq512_mask">, Intrinsic<[llvm_v8i32_ty], @@ -4177,18 +3123,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvttps2dq_128 : - GCCBuiltin<"__builtin_ia32_cvttps2dq128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvttps2dq_256 : - GCCBuiltin<"__builtin_ia32_cvttps2dq256_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_cvttps2dq_512 : GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">, Intrinsic<[llvm_v16i32_ty], @@ -4249,36 +3183,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtudq2ps_128 : - GCCBuiltin<"__builtin_ia32_cvtudq2ps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtudq2ps_256 : - GCCBuiltin<"__builtin_ia32_cvtudq2ps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8i32_ty, llvm_v8f32_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_cvtuqq2pd_128 : - GCCBuiltin<"__builtin_ia32_cvtuqq2pd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_cvtuqq2pd_256 : - GCCBuiltin<"__builtin_ia32_cvtuqq2pd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_cvtuqq2pd_512 : GCCBuiltin<"__builtin_ia32_cvtuqq2pd512_mask">, Intrinsic<[llvm_v8f64_ty], @@ -4361,13 +3271,6 @@ def int_x86_avx512_mask_range_ps_512 : GCCBuiltin<"__builtin_ia32_rangeps512_mas // Vector load with broadcast let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - // TODO: Remove the broadcast intrinsics with no gcc builtin and autoupgrade - def int_x86_avx512_vbroadcast_ss_512 : - Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - - def int_x86_avx512_vbroadcast_sd_512 : - Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_broadcastmw_512 : GCCBuiltin<"__builtin_ia32_broadcastmw512">, Intrinsic<[llvm_v16i32_ty], [llvm_i16_ty], [IntrNoMem]>; @@ -4391,42 +3294,43 @@ 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_mask_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512_mask">, + def int_x86_avx512_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512">, 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_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512">, 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_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512">, 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_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512">, 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_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512">, 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_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512">, 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_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512">, 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_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512_mask">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512">, 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_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512_mask">, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512">, 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">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512">, 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">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512">, 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">, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_add_ss_round : GCCBuiltin<"__builtin_ia32_addss_round_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, @@ -4514,31 +3418,17 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". 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_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss_round_mask">, + def int_x86_avx512_mask_sqrt_ss : Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd_round_mask">, + def int_x86_avx512_mask_sqrt_sd : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_sqrt_pd_128 : GCCBuiltin<"__builtin_ia32_sqrtpd128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_sqrt_pd_256 : GCCBuiltin<"__builtin_ia32_sqrtpd256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_sqrt_ps_128 : GCCBuiltin<"__builtin_ia32_sqrtps128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_sqrt_ps_256 : GCCBuiltin<"__builtin_ia32_sqrtps256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_pd_512 : + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_ps_512 : + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_fixupimm_pd_128 : GCCBuiltin<"__builtin_ia32_fixupimmpd128_mask">, Intrinsic<[llvm_v2f64_ty], @@ -4787,148 +3677,105 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } // Integer arithmetic ops let TargetPrefix = "x86" in { - def int_x86_avx512_mask_padds_b_128 : GCCBuiltin<"__builtin_ia32_paddsb128_mask">, + def int_x86_avx512_mask_padds_b_128 : // FIXME: remove this intrinsic Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_padds_b_256 : GCCBuiltin<"__builtin_ia32_paddsb256_mask">, + def int_x86_avx512_mask_padds_b_256 : // FIXME: remove this intrinsic Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_padds_b_512 : GCCBuiltin<"__builtin_ia32_paddsb512_mask">, Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_padds_w_128 : GCCBuiltin<"__builtin_ia32_paddsw128_mask">, + def int_x86_avx512_mask_padds_w_128 : // FIXME: remove this intrinsic Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_padds_w_256 : GCCBuiltin<"__builtin_ia32_paddsw256_mask">, + def int_x86_avx512_mask_padds_w_256 : // FIXME: remove this intrinsic Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_padds_w_512 : GCCBuiltin<"__builtin_ia32_paddsw512_mask">, Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_paddus_b_128 : GCCBuiltin<"__builtin_ia32_paddusb128_mask">, + def int_x86_avx512_mask_paddus_b_128 : // FIXME: remove this intrinsic Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_paddus_b_256 : GCCBuiltin<"__builtin_ia32_paddusb256_mask">, + def int_x86_avx512_mask_paddus_b_256 : // FIXME: remove this intrinsic Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_paddus_b_512 : GCCBuiltin<"__builtin_ia32_paddusb512_mask">, Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_paddus_w_128 : GCCBuiltin<"__builtin_ia32_paddusw128_mask">, + def int_x86_avx512_mask_paddus_w_128 : // FIXME: remove this intrinsic Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_paddus_w_256 : GCCBuiltin<"__builtin_ia32_paddusw256_mask">, + def int_x86_avx512_mask_paddus_w_256 : // FIXME: remove this intrinsic Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_paddus_w_512 : GCCBuiltin<"__builtin_ia32_paddusw512_mask">, Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_psubs_b_128 : GCCBuiltin<"__builtin_ia32_psubsb128_mask">, + def int_x86_avx512_mask_psubs_b_128 : // FIXME: remove this intrinsic Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_psubs_b_256 : GCCBuiltin<"__builtin_ia32_psubsb256_mask">, + def int_x86_avx512_mask_psubs_b_256 : // FIXME: remove this intrinsic Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_psubs_b_512 : GCCBuiltin<"__builtin_ia32_psubsb512_mask">, Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_psubs_w_128 : GCCBuiltin<"__builtin_ia32_psubsw128_mask">, + def int_x86_avx512_mask_psubs_w_128 : // FIXME: remove this intrinsic Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_psubs_w_256 : GCCBuiltin<"__builtin_ia32_psubsw256_mask">, + def int_x86_avx512_mask_psubs_w_256 : // FIXME: remove this intrinsic Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_psubs_w_512 : GCCBuiltin<"__builtin_ia32_psubsw512_mask">, Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_psubus_b_128 : GCCBuiltin<"__builtin_ia32_psubusb128_mask">, + def int_x86_avx512_mask_psubus_b_128 : // FIXME: remove this intrinsic Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_psubus_b_256 : GCCBuiltin<"__builtin_ia32_psubusb256_mask">, + def int_x86_avx512_mask_psubus_b_256 : // FIXME: remove this intrinsic Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_psubus_b_512 : GCCBuiltin<"__builtin_ia32_psubusb512_mask">, Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; - def int_x86_avx512_mask_psubus_w_128 : GCCBuiltin<"__builtin_ia32_psubusw128_mask">, + def int_x86_avx512_mask_psubus_w_128 : // FIXME: remove this intrinsic Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_psubus_w_256 : GCCBuiltin<"__builtin_ia32_psubusw256_mask">, + def int_x86_avx512_mask_psubus_w_256 : // FIXME: remove this intrinsic Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_psubus_w_512 : GCCBuiltin<"__builtin_ia32_psubusw512_mask">, Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty], [IntrNoMem]>; - def int_x86_avx512_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512">, - Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmulhu_w_512 : GCCBuiltin<"__builtin_ia32_pmulhuw512_mask">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, - llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmulh_w_512 : GCCBuiltin<"__builtin_ia32_pmulhw512_mask">, - Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, - llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmulhu_w_128 : GCCBuiltin<"__builtin_ia32_pmulhuw128_mask">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmulhu_w_256 : GCCBuiltin<"__builtin_ia32_pmulhuw256_mask">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, - llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmulh_w_128 : GCCBuiltin<"__builtin_ia32_pmulhw128_mask">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmulh_w_256 : GCCBuiltin<"__builtin_ia32_pmulhw256_mask">, - Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, - llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmaddw_d_128 : - GCCBuiltin<"__builtin_ia32_pmaddwd128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmaddw_d_256 : - GCCBuiltin<"__builtin_ia32_pmaddwd256_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmaddw_d_512 : - GCCBuiltin<"__builtin_ia32_pmaddwd512_mask">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmaddubs_w_128 : - GCCBuiltin<"__builtin_ia32_pmaddubsw128_mask">, - Intrinsic<[llvm_v8i16_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v8i16_ty, llvm_i8_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmaddubs_w_256 : - GCCBuiltin<"__builtin_ia32_pmaddubsw256_mask">, - Intrinsic<[llvm_v16i16_ty], - [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v16i16_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pmaddubs_w_512 : - GCCBuiltin<"__builtin_ia32_pmaddubsw512_mask">, - Intrinsic<[llvm_v32i16_ty], - [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v32i16_ty, llvm_i32_ty], - [IntrNoMem]>; + def int_x86_avx512_pmulhu_w_512 : GCCBuiltin<"__builtin_ia32_pmulhuw512">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, + llvm_v32i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx512_pmulh_w_512 : GCCBuiltin<"__builtin_ia32_pmulhw512">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, + llvm_v32i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx512_pmaddw_d_512 : GCCBuiltin<"__builtin_ia32_pmaddwd512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v32i16_ty, + llvm_v32i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx512_pmaddubs_w_512 : GCCBuiltin<"__builtin_ia32_pmaddubsw512">, + Intrinsic<[llvm_v32i16_ty], [llvm_v64i8_ty, + llvm_v64i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_dbpsadbw_128 : - GCCBuiltin<"__builtin_ia32_dbpsadbw128_mask">, + def int_x86_avx512_dbpsadbw_128 : + GCCBuiltin<"__builtin_ia32_dbpsadbw128">, Intrinsic<[llvm_v8i16_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_v8i16_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_dbpsadbw_256 : - GCCBuiltin<"__builtin_ia32_dbpsadbw256_mask">, + def int_x86_avx512_dbpsadbw_256 : + GCCBuiltin<"__builtin_ia32_dbpsadbw256">, Intrinsic<[llvm_v16i16_ty], - [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, llvm_v16i16_ty, - llvm_i16_ty], [IntrNoMem]>; + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_dbpsadbw_512 : - GCCBuiltin<"__builtin_ia32_dbpsadbw512_mask">, + def int_x86_avx512_dbpsadbw_512 : + GCCBuiltin<"__builtin_ia32_dbpsadbw512">, Intrinsic<[llvm_v32i16_ty], - [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, llvm_v32i16_ty, - llvm_i32_ty], [IntrNoMem]>; + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty], [IntrNoMem]>; } // Gather and Scatter ops @@ -5299,31 +4146,6 @@ let TargetPrefix = "x86" in { Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_store_ps_512 : - GCCBuiltin<"__builtin_ia32_compressstoresf512_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, - llvm_i16_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_pd_512 : - GCCBuiltin<"__builtin_ia32_compressstoredf512_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_ps_256 : - GCCBuiltin<"__builtin_ia32_compressstoresf256_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_pd_256 : - GCCBuiltin<"__builtin_ia32_compressstoredf256_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_ps_128 : - GCCBuiltin<"__builtin_ia32_compressstoresf128_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_pd_128 : - GCCBuiltin<"__builtin_ia32_compressstoredf128_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_d_512 : GCCBuiltin<"__builtin_ia32_compresssi512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, @@ -5349,31 +4171,6 @@ let TargetPrefix = "x86" in { Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_store_d_512 : - GCCBuiltin<"__builtin_ia32_compressstoresi512_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, - llvm_i16_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_q_512 : - GCCBuiltin<"__builtin_ia32_compressstoredi512_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_d_256 : - GCCBuiltin<"__builtin_ia32_compressstoresi256_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_q_256 : - GCCBuiltin<"__builtin_ia32_compressstoredi256_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_d_128 : - GCCBuiltin<"__builtin_ia32_compressstoresi128_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_q_128 : - GCCBuiltin<"__builtin_ia32_compressstoredi128_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_b_512 : GCCBuiltin<"__builtin_ia32_compressqi512_mask">, Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, @@ -5399,31 +4196,6 @@ let TargetPrefix = "x86" in { Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_compress_store_b_512 : - GCCBuiltin<"__builtin_ia32_compressstoreqi512_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v64i8_ty, - llvm_i64_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_w_512 : - GCCBuiltin<"__builtin_ia32_compressstorehi512_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v32i16_ty, - llvm_i32_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_b_256 : - GCCBuiltin<"__builtin_ia32_compressstoreqi256_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v32i8_ty, - llvm_i32_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_w_256 : - GCCBuiltin<"__builtin_ia32_compressstorehi256_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v16i16_ty, - llvm_i16_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_b_128 : - GCCBuiltin<"__builtin_ia32_compressstoreqi128_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v16i8_ty, - llvm_i16_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_compress_store_w_128 : - GCCBuiltin<"__builtin_ia32_compressstorehi128_mask">, - Intrinsic<[], [llvm_ptr_ty, llvm_v8i16_ty, - llvm_i8_ty], [IntrArgMemOnly]>; - // expand def int_x86_avx512_mask_expand_ps_512 : GCCBuiltin<"__builtin_ia32_expandsf512_mask">, @@ -5450,31 +4222,6 @@ let TargetPrefix = "x86" in { Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_load_ps_512 : - GCCBuiltin<"__builtin_ia32_expandloadsf512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, - llvm_i16_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_pd_512 : - GCCBuiltin<"__builtin_ia32_expandloaddf512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_ps_256 : - GCCBuiltin<"__builtin_ia32_expandloadsf256_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_pd_256 : - GCCBuiltin<"__builtin_ia32_expandloaddf256_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_ps_128 : - GCCBuiltin<"__builtin_ia32_expandloadsf128_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_pd_128 : - GCCBuiltin<"__builtin_ia32_expandloaddf128_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_d_512 : GCCBuiltin<"__builtin_ia32_expandsi512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, @@ -5500,31 +4247,6 @@ let TargetPrefix = "x86" in { Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_expand_load_d_512 : - GCCBuiltin<"__builtin_ia32_expandloadsi512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty, - llvm_i16_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_q_512 : - GCCBuiltin<"__builtin_ia32_expandloaddi512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_d_256 : - GCCBuiltin<"__builtin_ia32_expandloadsi256_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_q_256 : - GCCBuiltin<"__builtin_ia32_expandloaddi256_mask">, - Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_d_128 : - GCCBuiltin<"__builtin_ia32_expandloadsi128_mask">, - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_q_128 : - GCCBuiltin<"__builtin_ia32_expandloaddi128_mask">, - Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_b_512 : GCCBuiltin<"__builtin_ia32_expandqi512_mask">, Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, @@ -5549,130 +4271,87 @@ let TargetPrefix = "x86" in { GCCBuiltin<"__builtin_ia32_expandhi128_mask">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_expand_load_b_512 : - GCCBuiltin<"__builtin_ia32_expandloadqi512_mask">, - Intrinsic<[llvm_v64i8_ty], [llvm_ptr_ty, llvm_v64i8_ty, - llvm_i64_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_w_512 : - GCCBuiltin<"__builtin_ia32_expandloadhi512_mask">, - Intrinsic<[llvm_v32i16_ty], [llvm_ptr_ty, llvm_v32i16_ty, - llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_b_256 : - GCCBuiltin<"__builtin_ia32_expandloadqi256_mask">, - Intrinsic<[llvm_v32i8_ty], [llvm_ptr_ty, llvm_v32i8_ty, - llvm_i32_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_w_256 : - GCCBuiltin<"__builtin_ia32_expandloadhi256_mask">, - Intrinsic<[llvm_v16i16_ty], [llvm_ptr_ty, llvm_v16i16_ty, - llvm_i16_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_b_128 : - GCCBuiltin<"__builtin_ia32_expandloadqi128_mask">, - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_v16i8_ty, - llvm_i16_ty], [IntrReadMem, IntrArgMemOnly]>; - def int_x86_avx512_mask_expand_load_w_128 : - GCCBuiltin<"__builtin_ia32_expandloadhi128_mask">, - Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty, llvm_v8i16_ty, - llvm_i8_ty], [IntrReadMem, IntrArgMemOnly]>; } // VBMI2 Concat & Shift let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_mask_vpshld_q_512 : - GCCBuiltin<"__builtin_ia32_vpshldq512_mask">, + def int_x86_avx512_vpshld_q_512 : + GCCBuiltin<"__builtin_ia32_vpshldq512">, Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_v8i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshld_q_256 : - GCCBuiltin<"__builtin_ia32_vpshldq256_mask">, + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshld_q_256 : + GCCBuiltin<"__builtin_ia32_vpshldq256">, Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_v4i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshld_q_128 : - GCCBuiltin<"__builtin_ia32_vpshldq128_mask">, + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshld_q_128 : + GCCBuiltin<"__builtin_ia32_vpshldq128">, Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshld_d_512 : - GCCBuiltin<"__builtin_ia32_vpshldd512_mask">, + def int_x86_avx512_vpshld_d_512 : + GCCBuiltin<"__builtin_ia32_vpshldd512">, Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, llvm_v16i32_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshld_d_256 : - GCCBuiltin<"__builtin_ia32_vpshldd256_mask">, + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshld_d_256 : + GCCBuiltin<"__builtin_ia32_vpshldd256">, Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_v8i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshld_d_128 : - GCCBuiltin<"__builtin_ia32_vpshldd128_mask">, + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshld_d_128 : + GCCBuiltin<"__builtin_ia32_vpshldd128">, Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshld_w_512 : - GCCBuiltin<"__builtin_ia32_vpshldw512_mask">, + def int_x86_avx512_vpshld_w_512 : + GCCBuiltin<"__builtin_ia32_vpshldw512">, Intrinsic<[llvm_v32i16_ty], - [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, llvm_v32i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshld_w_256 : - GCCBuiltin<"__builtin_ia32_vpshldw256_mask">, + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshld_w_256 : + GCCBuiltin<"__builtin_ia32_vpshldw256">, Intrinsic<[llvm_v16i16_ty], - [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, llvm_v16i16_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshld_w_128 : - GCCBuiltin<"__builtin_ia32_vpshldw128_mask">, + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshld_w_128 : + GCCBuiltin<"__builtin_ia32_vpshldw128">, Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshrd_q_512 : - GCCBuiltin<"__builtin_ia32_vpshrdq512_mask">, + def int_x86_avx512_vpshrd_q_512 : + GCCBuiltin<"__builtin_ia32_vpshrdq512">, Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_v8i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshrd_q_256 : - GCCBuiltin<"__builtin_ia32_vpshrdq256_mask">, + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshrd_q_256 : + GCCBuiltin<"__builtin_ia32_vpshrdq256">, Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_v4i64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshrd_q_128 : - GCCBuiltin<"__builtin_ia32_vpshrdq128_mask">, + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshrd_q_128 : + GCCBuiltin<"__builtin_ia32_vpshrdq128">, Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_v2i64_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshrd_d_512 : - GCCBuiltin<"__builtin_ia32_vpshrdd512_mask">, + def int_x86_avx512_vpshrd_d_512 : + GCCBuiltin<"__builtin_ia32_vpshrdd512">, Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, llvm_v16i32_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshrd_d_256 : - GCCBuiltin<"__builtin_ia32_vpshrdd256_mask">, + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshrd_d_256 : + GCCBuiltin<"__builtin_ia32_vpshrdd256">, Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_v8i32_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshrd_d_128 : - GCCBuiltin<"__builtin_ia32_vpshrdd128_mask">, + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshrd_d_128 : + GCCBuiltin<"__builtin_ia32_vpshrdd128">, Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_v4i32_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshrd_w_512 : - GCCBuiltin<"__builtin_ia32_vpshrdw512_mask">, + def int_x86_avx512_vpshrd_w_512 : + GCCBuiltin<"__builtin_ia32_vpshrdw512">, Intrinsic<[llvm_v32i16_ty], - [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, llvm_v32i16_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshrd_w_256 : - GCCBuiltin<"__builtin_ia32_vpshrdw256_mask">, + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshrd_w_256 : + GCCBuiltin<"__builtin_ia32_vpshrdw256">, Intrinsic<[llvm_v16i16_ty], - [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, llvm_v16i16_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpshrd_w_128 : - GCCBuiltin<"__builtin_ia32_vpshrdw128_mask">, + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_vpshrd_w_128 : + GCCBuiltin<"__builtin_ia32_vpshrdw128">, Intrinsic<[llvm_v8i16_ty], - [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, llvm_v8i16_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_vpshldv_w_128 : GCCBuiltin<"__builtin_ia32_vpshldvw128_mask">, @@ -5978,7 +4657,6 @@ let TargetPrefix = "x86" in { [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrArgMemOnly]>; def int_x86_avx512_mask_pmov_qw_512 : - GCCBuiltin<"__builtin_ia32_pmovqw512_mask">, Intrinsic<[llvm_v8i16_ty], [llvm_v8i64_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; @@ -6037,8 +4715,7 @@ let TargetPrefix = "x86" in { Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qd_256 : - GCCBuiltin<"__builtin_ia32_pmovqd256_mask">, + def int_x86_avx512_mask_pmov_qd_256 : // FIXME: Replace with trunc+select. Intrinsic<[llvm_v4i32_ty], [llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; @@ -6067,8 +4744,7 @@ let TargetPrefix = "x86" in { Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_qd_512 : - GCCBuiltin<"__builtin_ia32_pmovqd512_mask">, + def int_x86_avx512_mask_pmov_qd_512 : // FIXME: Replace with trunc+select. Intrinsic<[llvm_v8i32_ty], [llvm_v8i64_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; @@ -6158,7 +4834,6 @@ let TargetPrefix = "x86" in { [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrArgMemOnly]>; def int_x86_avx512_mask_pmov_db_512 : - GCCBuiltin<"__builtin_ia32_pmovdb512_mask">, Intrinsic<[llvm_v16i8_ty], [llvm_v16i32_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; @@ -6248,7 +4923,6 @@ let TargetPrefix = "x86" in { [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrArgMemOnly]>; def int_x86_avx512_mask_pmov_dw_512 : - GCCBuiltin<"__builtin_ia32_pmovdw512_mask">, Intrinsic<[llvm_v16i16_ty], [llvm_v16i32_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; @@ -6307,8 +4981,7 @@ let TargetPrefix = "x86" in { Intrinsic<[], [llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_wb_256 : - GCCBuiltin<"__builtin_ia32_pmovwb256_mask">, + def int_x86_avx512_mask_pmov_wb_256 : // FIXME: Replace with trunc+select. Intrinsic<[llvm_v16i8_ty], [llvm_v16i16_ty, llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; @@ -6337,8 +5010,7 @@ let TargetPrefix = "x86" in { Intrinsic<[], [llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty], [IntrArgMemOnly]>; - def int_x86_avx512_mask_pmov_wb_512 : - GCCBuiltin<"__builtin_ia32_pmovwb512_mask">, + def int_x86_avx512_mask_pmov_wb_512 : // FIXME: Replace with trunc+select. Intrinsic<[llvm_v32i8_ty], [llvm_v32i16_ty, llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; @@ -6371,105 +5043,66 @@ let TargetPrefix = "x86" in { // Bitwise ternary logic let TargetPrefix = "x86" in { - def int_x86_avx512_mask_pternlog_d_128 : - GCCBuiltin<"__builtin_ia32_pternlogd128_mask">, - Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_maskz_pternlog_d_128 : - GCCBuiltin<"__builtin_ia32_pternlogd128_maskz">, + def int_x86_avx512_pternlog_d_128 : + GCCBuiltin<"__builtin_ia32_pternlogd128">, Intrinsic<[llvm_v4i32_ty], - [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_pternlog_d_256 : - GCCBuiltin<"__builtin_ia32_pternlogd256_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; - def int_x86_avx512_maskz_pternlog_d_256 : - GCCBuiltin<"__builtin_ia32_pternlogd256_maskz">, + def int_x86_avx512_pternlog_d_256 : + GCCBuiltin<"__builtin_ia32_pternlogd256">, Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_pternlog_d_512 : - GCCBuiltin<"__builtin_ia32_pternlogd512_mask">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, - llvm_i16_ty], [IntrNoMem]>; + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], + [IntrNoMem]>; - def int_x86_avx512_maskz_pternlog_d_512 : - GCCBuiltin<"__builtin_ia32_pternlogd512_maskz">, + def int_x86_avx512_pternlog_d_512 : + GCCBuiltin<"__builtin_ia32_pternlogd512">, Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, - llvm_i16_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_pternlog_q_128 : - GCCBuiltin<"__builtin_ia32_pternlogq128_mask">, - Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_maskz_pternlog_q_128 : - GCCBuiltin<"__builtin_ia32_pternlogq128_maskz">, + def int_x86_avx512_pternlog_q_128 : + GCCBuiltin<"__builtin_ia32_pternlogq128">, Intrinsic<[llvm_v2i64_ty], - [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_pternlog_q_256 : - GCCBuiltin<"__builtin_ia32_pternlogq256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; - def int_x86_avx512_maskz_pternlog_q_256 : - GCCBuiltin<"__builtin_ia32_pternlogq256_maskz">, + def int_x86_avx512_pternlog_q_256 : + GCCBuiltin<"__builtin_ia32_pternlogq256">, Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, - llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_pternlog_q_512 : - GCCBuiltin<"__builtin_ia32_pternlogq512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], + [IntrNoMem]>; - def int_x86_avx512_maskz_pternlog_q_512 : - GCCBuiltin<"__builtin_ia32_pternlogq512_maskz">, + def int_x86_avx512_pternlog_q_512 : + GCCBuiltin<"__builtin_ia32_pternlogq512">, Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, - llvm_i8_ty], [IntrNoMem]>; + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty], + [IntrNoMem]>; } // Misc. let TargetPrefix = "x86" in { - 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_cmp_ps_256 : - GCCBuiltin<"__builtin_ia32_cmpps256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cmp_pd_256 : - GCCBuiltin<"__builtin_ia32_cmppd256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cmp_ps_128 : - GCCBuiltin<"__builtin_ia32_cmpps128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cmp_pd_128 : - GCCBuiltin<"__builtin_ia32_cmppd128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + // NOTE: These comparison intrinsics are not used by clang as long as the + // distinction in signaling behaviour is not implemented. + def int_x86_avx512_cmp_ps_512 : + Intrinsic<[llvm_v16i1_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cmp_pd_512 : + Intrinsic<[llvm_v8i1_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cmp_ps_256 : + Intrinsic<[llvm_v8i1_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cmp_pd_256 : + Intrinsic<[llvm_v4i1_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cmp_ps_128 : + Intrinsic<[llvm_v4i1_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cmp_pd_128 : + Intrinsic<[llvm_v2i1_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_ss : GCCBuiltin<"__builtin_ia32_cmpss_mask">, Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_v4f32_ty, @@ -6518,3 +5151,65 @@ let TargetPrefix = "x86" in { def int_x86_clzero : GCCBuiltin<"__builtin_ia32_clzero">, Intrinsic<[], [llvm_ptr_ty], []>; } + +//===----------------------------------------------------------------------===// +// Cache write back intrinsics + +let TargetPrefix = "x86" in { + // Write back and invalidate + def int_x86_wbinvd : GCCBuiltin<"__builtin_ia32_wbinvd">, + Intrinsic<[], [], []>; + + // Write back no-invalidate + def int_x86_wbnoinvd : GCCBuiltin<"__builtin_ia32_wbnoinvd">, + Intrinsic<[], [], []>; +} + +//===----------------------------------------------------------------------===// +// Cache-line demote + +let TargetPrefix = "x86" in { + def int_x86_cldemote : GCCBuiltin<"__builtin_ia32_cldemote">, + Intrinsic<[], [llvm_ptr_ty], []>; +} + +//===----------------------------------------------------------------------===// +// Wait and pause enhancements +let TargetPrefix = "x86" in { + def int_x86_umonitor : GCCBuiltin<"__builtin_ia32_umonitor">, + Intrinsic<[], [llvm_ptr_ty], []>; + def int_x86_umwait : GCCBuiltin<"__builtin_ia32_umwait">, + Intrinsic<[llvm_i8_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; + def int_x86_tpause : GCCBuiltin<"__builtin_ia32_tpause">, + Intrinsic<[llvm_i8_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; +} + +//===----------------------------------------------------------------------===// +// Direct Move Instructions + +let TargetPrefix = "x86" in { + def int_x86_directstore32 : GCCBuiltin<"__builtin_ia32_directstore_u32">, + Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], []>; + def int_x86_directstore64 : GCCBuiltin<"__builtin_ia32_directstore_u64">, + Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty], []>; + def int_x86_movdir64b : GCCBuiltin<"__builtin_ia32_movdir64b">, + Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], []>; +} + +//===----------------------------------------------------------------------===// +// PTWrite - Write data to processor trace pocket + +let TargetPrefix = "x86" in { + def int_x86_ptwrite32 : GCCBuiltin<"__builtin_ia32_ptwrite32">, + Intrinsic<[], [llvm_i32_ty], []>; + def int_x86_ptwrite64 : GCCBuiltin<"__builtin_ia32_ptwrite64">, + Intrinsic<[], [llvm_i64_ty], []>; +} + +//===----------------------------------------------------------------------===// +// INVPCID - Invalidate Process-Context Identifier + +let TargetPrefix = "x86" in { + def int_x86_invpcid : GCCBuiltin<"__builtin_ia32_invpcid">, + Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty], []>; +} diff --git a/contrib/llvm/include/llvm/IR/LLVMContext.h b/contrib/llvm/include/llvm/IR/LLVMContext.h index a95634d32c21..ebd445553167 100644 --- a/contrib/llvm/include/llvm/IR/LLVMContext.h +++ b/contrib/llvm/include/llvm/IR/LLVMContext.h @@ -31,7 +31,7 @@ class Function; class Instruction; class LLVMContextImpl; class Module; -class OptBisect; +class OptPassGate; template <typename T> class SmallVectorImpl; class SMDiagnostic; class StringRef; @@ -76,7 +76,7 @@ public: // Pinned metadata names, which always have the same value. This is a // compile-time performance optimization, not a correctness optimization. - enum { + enum : unsigned { MD_dbg = 0, // "dbg" MD_tbaa = 1, // "tbaa" MD_prof = 2, // "prof" @@ -108,7 +108,7 @@ public: /// operand bundle tags that LLVM has special knowledge of are listed here. /// Additionally, this scheme allows LLVM to efficiently check for specific /// operand bundle tags without comparing strings. - enum { + enum : unsigned { OB_deopt = 0, // "deopt" OB_funclet = 1, // "funclet" OB_gc_transition = 2, // "gc-transition" @@ -229,23 +229,23 @@ public: /// to caller. std::unique_ptr<DiagnosticHandler> getDiagnosticHandler(); - /// \brief Return if a code hotness metric should be included in optimization + /// Return if a code hotness metric should be included in optimization /// diagnostics. bool getDiagnosticsHotnessRequested() const; - /// \brief Set if a code hotness metric should be included in optimization + /// Set if a code hotness metric should be included in optimization /// diagnostics. void setDiagnosticsHotnessRequested(bool Requested); - /// \brief Return the minimum hotness value a diagnostic would need in order + /// Return the minimum hotness value a diagnostic would need in order /// to be included in optimization diagnostics. If there is no minimum, this /// returns None. uint64_t getDiagnosticsHotnessThreshold() const; - /// \brief Set the minimum hotness value a diagnostic needs in order to be + /// Set the minimum hotness value a diagnostic needs in order to be /// included in optimization diagnostics. void setDiagnosticsHotnessThreshold(uint64_t Threshold); - /// \brief Return the YAML file used by the backend to save optimization + /// Return the YAML file used by the backend to save optimization /// diagnostics. If null, diagnostics are not saved in a file but only /// emitted via the diagnostic handler. yaml::Output *getDiagnosticsOutputFile(); @@ -256,11 +256,11 @@ public: /// set, the handler is invoked for each diagnostic message. void setDiagnosticsOutputFile(std::unique_ptr<yaml::Output> F); - /// \brief Get the prefix that should be printed in front of a diagnostic of + /// Get the prefix that should be printed in front of a diagnostic of /// the given \p Severity static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity); - /// \brief Report a message to the currently installed diagnostic handler. + /// Report a message to the currently installed diagnostic handler. /// /// This function returns, in particular in the case of error reporting /// (DI.Severity == \a DS_Error), so the caller should leave the compilation @@ -272,7 +272,7 @@ public: /// "warning: " for \a DS_Warning, and "note: " for \a DS_Note. void diagnose(const DiagnosticInfo &DI); - /// \brief Registers a yield callback with the given context. + /// Registers a yield callback with the given context. /// /// The yield callback function may be called by LLVM to transfer control back /// to the client that invoked the LLVM compilation. This can be used to yield @@ -291,7 +291,7 @@ public: /// control to LLVM. Other LLVM contexts are unaffected by this restriction. void setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle); - /// \brief Calls the yield callback (if applicable). + /// Calls the yield callback (if applicable). /// /// This transfers control of the current thread back to the client, which may /// suspend the current thread. Only call this method when LLVM doesn't hold @@ -307,7 +307,7 @@ public: void emitError(const Instruction *I, const Twine &ErrorStr); void emitError(const Twine &ErrorStr); - /// \brief Query for a debug option's value. + /// Query for a debug option's value. /// /// This function returns typed data populated from command line parsing. template <typename ValT, typename Base, ValT(Base::*Mem)> @@ -315,9 +315,17 @@ public: return OptionRegistry::instance().template get<ValT, Base, Mem>(); } - /// \brief Access the object which manages optimization bisection for failure - /// analysis. - OptBisect &getOptBisect(); + /// Access the object which can disable optional passes and individual + /// optimizations at compile time. + OptPassGate &getOptPassGate() const; + + /// Set the object which can disable optional passes and individual + /// optimizations at compile time. + /// + /// The lifetime of the object must be guaranteed to extend as long as the + /// LLVMContext is used by compilation. + void setOptPassGate(OptPassGate&); + private: // Module needs access to the add/removeModule methods. friend class Module; diff --git a/contrib/llvm/include/llvm/IR/LegacyPassManagers.h b/contrib/llvm/include/llvm/IR/LegacyPassManagers.h index 3dc4a776dba0..90036c6ce248 100644 --- a/contrib/llvm/include/llvm/IR/LegacyPassManagers.h +++ b/contrib/llvm/include/llvm/IR/LegacyPassManagers.h @@ -403,6 +403,15 @@ public: InheritedAnalysis[Index++] = (*I)->getAvailableAnalysis(); } + /// Set the initial size of the module if the user has specified that they + /// want remarks for size. + /// Returns 0 if the remark was not requested. + unsigned initSizeRemarkInfo(Module &M); + + /// Emit a remark signifying that the number of IR instructions in the module + /// changed. + void emitInstrCountChangedRemark(Pass *P, Module &M, unsigned CountBefore); + protected: // Top level manager. PMTopLevelManager *TPM; diff --git a/contrib/llvm/include/llvm/IR/MDBuilder.h b/contrib/llvm/include/llvm/IR/MDBuilder.h index dff1ca12407f..174616c7ab1d 100644 --- a/contrib/llvm/include/llvm/IR/MDBuilder.h +++ b/contrib/llvm/include/llvm/IR/MDBuilder.h @@ -38,17 +38,17 @@ class MDBuilder { public: MDBuilder(LLVMContext &context) : Context(context) {} - /// \brief Return the given string as metadata. + /// Return the given string as metadata. MDString *createString(StringRef Str); - /// \brief Return the given constant as metadata. + /// Return the given constant as metadata. ConstantAsMetadata *createConstant(Constant *C); //===------------------------------------------------------------------===// // FPMath metadata. //===------------------------------------------------------------------===// - /// \brief Return metadata with the given settings. The special value 0.0 + /// Return metadata with the given settings. The special value 0.0 /// for the Accuracy parameter indicates the default (maximal precision) /// setting. MDNode *createFPMath(float Accuracy); @@ -57,19 +57,20 @@ public: // Prof metadata. //===------------------------------------------------------------------===// - /// \brief Return metadata containing two branch weights. + /// Return metadata containing two branch weights. MDNode *createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight); - /// \brief Return metadata containing a number of branch weights. + /// Return metadata containing a number of branch weights. MDNode *createBranchWeights(ArrayRef<uint32_t> Weights); /// Return metadata specifying that a branch or switch is unpredictable. MDNode *createUnpredictable(); - /// Return metadata containing the entry \p Count for a function, and the + /// Return metadata containing the entry \p Count for a function, a boolean + /// \Synthetic indicating whether the counts were synthetized, and the /// GUIDs stored in \p Imports that need to be imported for sample PGO, to /// enable the same inlines as the profiled optimized binary - MDNode *createFunctionEntryCount(uint64_t Count, + MDNode *createFunctionEntryCount(uint64_t Count, bool Synthetic, const DenseSet<GlobalValue::GUID> *Imports); /// Return metadata containing the section prefix for a function. @@ -79,17 +80,17 @@ public: // Range metadata. //===------------------------------------------------------------------===// - /// \brief Return metadata describing the range [Lo, Hi). + /// Return metadata describing the range [Lo, Hi). MDNode *createRange(const APInt &Lo, const APInt &Hi); - /// \brief Return metadata describing the range [Lo, Hi). + /// Return metadata describing the range [Lo, Hi). MDNode *createRange(Constant *Lo, Constant *Hi); //===------------------------------------------------------------------===// // Callees metadata. //===------------------------------------------------------------------===// - /// \brief Return metadata indicating the possible callees of indirect + /// Return metadata indicating the possible callees of indirect /// calls. MDNode *createCallees(ArrayRef<Function *> Callees); @@ -98,28 +99,28 @@ public: //===------------------------------------------------------------------===// protected: - /// \brief Return metadata appropriate for a AA root node (scope or TBAA). + /// Return metadata appropriate for a AA root node (scope or TBAA). /// Each returned node is distinct from all other metadata and will never /// be identified (uniqued) with anything else. MDNode *createAnonymousAARoot(StringRef Name = StringRef(), MDNode *Extra = nullptr); public: - /// \brief Return metadata appropriate for a TBAA root node. Each returned + /// Return metadata appropriate for a TBAA root node. Each returned /// node is distinct from all other metadata and will never be identified /// (uniqued) with anything else. MDNode *createAnonymousTBAARoot() { return createAnonymousAARoot(); } - /// \brief Return metadata appropriate for an alias scope domain node. + /// Return metadata appropriate for an alias scope domain node. /// Each returned node is distinct from all other metadata and will never /// be identified (uniqued) with anything else. MDNode *createAnonymousAliasScopeDomain(StringRef Name = StringRef()) { return createAnonymousAARoot(Name); } - /// \brief Return metadata appropriate for an alias scope root node. + /// Return metadata appropriate for an alias scope root node. /// Each returned node is distinct from all other metadata and will never /// be identified (uniqued) with anything else. MDNode *createAnonymousAliasScope(MDNode *Domain, @@ -127,22 +128,22 @@ public: return createAnonymousAARoot(Name, Domain); } - /// \brief Return metadata appropriate for a TBAA root node with the given + /// Return metadata appropriate for a TBAA root node with the given /// name. This may be identified (uniqued) with other roots with the same /// name. MDNode *createTBAARoot(StringRef Name); - /// \brief Return metadata appropriate for an alias scope domain node with + /// Return metadata appropriate for an alias scope domain node with /// the given name. This may be identified (uniqued) with other roots with /// the same name. MDNode *createAliasScopeDomain(StringRef Name); - /// \brief Return metadata appropriate for an alias scope node with + /// Return metadata appropriate for an alias scope node with /// the given name. This may be identified (uniqued) with other scopes with /// the same name and domain. MDNode *createAliasScope(StringRef Name, MDNode *Domain); - /// \brief Return metadata for a non-root TBAA node with the given name, + /// Return metadata for a non-root TBAA node with the given name, /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. MDNode *createTBAANode(StringRef Name, MDNode *Parent, bool isConstant = false); @@ -155,33 +156,33 @@ public: Offset(Offset), Size(Size), Type(Type) {} }; - /// \brief Return metadata for a tbaa.struct node with the given + /// Return metadata for a tbaa.struct node with the given /// struct field descriptions. MDNode *createTBAAStructNode(ArrayRef<TBAAStructField> Fields); - /// \brief Return metadata for a TBAA struct node in the type DAG + /// Return metadata for a TBAA struct node in the type DAG /// with the given name, a list of pairs (offset, field type in the type DAG). MDNode * createTBAAStructTypeNode(StringRef Name, ArrayRef<std::pair<MDNode *, uint64_t>> Fields); - /// \brief Return metadata for a TBAA scalar type node with the + /// Return metadata for a TBAA scalar type node with the /// given name, an offset and a parent in the TBAA type DAG. MDNode *createTBAAScalarTypeNode(StringRef Name, MDNode *Parent, uint64_t Offset = 0); - /// \brief Return metadata for a TBAA tag node with the given + /// Return metadata for a TBAA tag node with the given /// base type, access type and offset relative to the base type. MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, uint64_t Offset, bool IsConstant = false); - /// \brief Return metadata for a TBAA type node in the TBAA type DAG with the + /// Return metadata for a TBAA type node in the TBAA type DAG with the /// given parent type, size in bytes, type identifier and a list of fields. MDNode *createTBAATypeNode(MDNode *Parent, uint64_t Size, Metadata *Id, ArrayRef<TBAAStructField> Fields = ArrayRef<TBAAStructField>()); - /// \brief Return metadata for a TBAA access tag with the given base type, + /// Return metadata for a TBAA access tag with the given base type, /// final access type, offset of the access relative to the base type, size of /// the access and flag indicating whether the accessed object can be /// considered immutable for the purposes of the TBAA analysis. @@ -189,7 +190,11 @@ public: uint64_t Offset, uint64_t Size, bool IsImmutable = false); - /// \brief Return metadata containing an irreducible loop header weight. + /// Return mutable version of the given mutable or immutable TBAA + /// access tag. + MDNode *createMutableTBAAAccessTag(MDNode *Tag); + + /// Return metadata containing an irreducible loop header weight. MDNode *createIrrLoopHeaderWeight(uint64_t Weight); }; diff --git a/contrib/llvm/include/llvm/IR/Mangler.h b/contrib/llvm/include/llvm/IR/Mangler.h index 56ee21392ccd..0261c00f524c 100644 --- a/contrib/llvm/include/llvm/IR/Mangler.h +++ b/contrib/llvm/include/llvm/IR/Mangler.h @@ -50,6 +50,9 @@ public: void emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV, const Triple &TT, Mangler &Mangler); +void emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV, + const Triple &T, Mangler &M); + } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/IR/Metadata.def b/contrib/llvm/include/llvm/IR/Metadata.def index 03cdcab7dc47..70a03f28b488 100644 --- a/contrib/llvm/include/llvm/IR/Metadata.def +++ b/contrib/llvm/include/llvm/IR/Metadata.def @@ -108,6 +108,7 @@ HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DITemplateValueParameter) HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIGlobalVariable) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILocalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILabel) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIObjCProperty) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DIImportedEntity) HANDLE_SPECIALIZED_MDNODE_BRANCH(DIMacroNode) diff --git a/contrib/llvm/include/llvm/IR/Metadata.h b/contrib/llvm/include/llvm/IR/Metadata.h index bc0b87a6c348..9ac97f4224ac 100644 --- a/contrib/llvm/include/llvm/IR/Metadata.h +++ b/contrib/llvm/include/llvm/IR/Metadata.h @@ -52,20 +52,20 @@ enum LLVMConstants : uint32_t { DEBUG_METADATA_VERSION = 3 // Current debug info version number. }; -/// \brief Root of the metadata hierarchy. +/// Root of the metadata hierarchy. /// /// This is a root class for typeless data in the IR. class Metadata { friend class ReplaceableMetadataImpl; - /// \brief RTTI. + /// RTTI. const unsigned char SubclassID; protected: - /// \brief Active type of storage. + /// Active type of storage. enum StorageType { Uniqued, Distinct, Temporary }; - /// \brief Storage flag for non-uniqued, otherwise unowned, metadata. + /// Storage flag for non-uniqued, otherwise unowned, metadata. unsigned char Storage; // TODO: expose remaining bits to subclasses. @@ -86,7 +86,7 @@ protected: ~Metadata() = default; - /// \brief Default handling of a changed operand, which asserts. + /// Default handling of a changed operand, which asserts. /// /// If subclasses pass themselves in as owners to a tracking node reference, /// they must provide an implementation of this method. @@ -97,7 +97,7 @@ protected: public: unsigned getMetadataID() const { return SubclassID; } - /// \brief User-friendly dump. + /// User-friendly dump. /// /// If \c M is provided, metadata nodes will be numbered canonically; /// otherwise, pointer addresses are substituted. @@ -110,7 +110,7 @@ public: void dump(const Module *M) const; /// @} - /// \brief Print. + /// Print. /// /// Prints definition of \c this. /// @@ -123,7 +123,7 @@ public: bool IsForDebug = false) const; /// @} - /// \brief Print as operand. + /// Print as operand. /// /// Prints reference of \c this. /// @@ -162,7 +162,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { return OS; } -/// \brief Metadata wrapper in the Value hierarchy. +/// Metadata wrapper in the Value hierarchy. /// /// A member of the \a Value hierarchy to represent a reference to metadata. /// This allows, e.g., instrinsics to have metadata as operands. @@ -177,7 +177,7 @@ class MetadataAsValue : public Value { MetadataAsValue(Type *Ty, Metadata *MD); - /// \brief Drop use of metadata (during teardown). + /// Drop use of metadata (during teardown). void dropUse() { MD = nullptr; } public: @@ -198,7 +198,7 @@ private: void untrack(); }; -/// \brief API for tracking metadata references through RAUW and deletion. +/// API for tracking metadata references through RAUW and deletion. /// /// Shared API for updating \a Metadata pointers in subclasses that support /// RAUW. @@ -207,7 +207,7 @@ private: /// user-friendly tracking reference. class MetadataTracking { public: - /// \brief Track the reference to metadata. + /// Track the reference to metadata. /// /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets @@ -220,7 +220,7 @@ public: return track(&MD, *MD, static_cast<Metadata *>(nullptr)); } - /// \brief Track the reference to metadata for \a Metadata. + /// Track the reference to metadata for \a Metadata. /// /// As \a track(Metadata*&), but with support for calling back to \c Owner to /// tell it that its operand changed. This could trigger \c Owner being @@ -229,7 +229,7 @@ public: return track(Ref, MD, &Owner); } - /// \brief Track the reference to metadata for \a MetadataAsValue. + /// Track the reference to metadata for \a MetadataAsValue. /// /// As \a track(Metadata*&), but with support for calling back to \c Owner to /// tell it that its operand changed. This could trigger \c Owner being @@ -238,13 +238,13 @@ public: return track(Ref, MD, &Owner); } - /// \brief Stop tracking a reference to metadata. + /// Stop tracking a reference to metadata. /// /// Stops \c *MD from tracking \c MD. static void untrack(Metadata *&MD) { untrack(&MD, *MD); } static void untrack(void *Ref, Metadata &MD); - /// \brief Move tracking from one reference to another. + /// Move tracking from one reference to another. /// /// Semantically equivalent to \c untrack(MD) followed by \c track(New), /// except that ownership callbacks are maintained. @@ -257,19 +257,19 @@ public: } static bool retrack(void *Ref, Metadata &MD, void *New); - /// \brief Check whether metadata is replaceable. + /// Check whether metadata is replaceable. static bool isReplaceable(const Metadata &MD); using OwnerTy = PointerUnion<MetadataAsValue *, Metadata *>; private: - /// \brief Track a reference to metadata for an owner. + /// Track a reference to metadata for an owner. /// /// Generalized version of tracking. static bool track(void *Ref, Metadata &MD, OwnerTy Owner); }; -/// \brief Shared implementation of use-lists for replaceable metadata. +/// Shared implementation of use-lists for replaceable metadata. /// /// Most metadata cannot be RAUW'ed. This is a shared implementation of /// use-lists and associated API for the two that support it (\a ValueAsMetadata @@ -294,12 +294,12 @@ public: LLVMContext &getContext() const { return Context; } - /// \brief Replace all uses of this with MD. + /// Replace all uses of this with MD. /// /// Replace all uses of this with \c MD, which is allowed to be null. void replaceAllUsesWith(Metadata *MD); - /// \brief Resolve all uses of this. + /// Resolve all uses of this. /// /// Resolve all uses of this, turning off RAUW permanently. If \c /// ResolveUsers, call \a MDNode::resolve() on any users whose last operand @@ -326,7 +326,7 @@ private: static bool isReplaceable(const Metadata &MD); }; -/// \brief Value wrapper in the Metadata hierarchy. +/// Value wrapper in the Metadata hierarchy. /// /// This is a custom value handle that allows other metadata to refer to /// classes in the Value hierarchy. @@ -340,7 +340,7 @@ class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl { Value *V; - /// \brief Drop users without RAUW (during teardown). + /// Drop users without RAUW (during teardown). void dropUsers() { ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false); } @@ -382,7 +382,7 @@ public: static void handleRAUW(Value *From, Value *To); protected: - /// \brief Handle collisions after \a Value::replaceAllUsesWith(). + /// Handle collisions after \a Value::replaceAllUsesWith(). /// /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped /// \a Value gets RAUW'ed and the target already exists, this is used to @@ -444,7 +444,7 @@ public: } }; -/// \brief Transitional API for extracting constants from Metadata. +/// Transitional API for extracting constants from Metadata. /// /// This namespace contains transitional functions for metadata that points to /// \a Constants. @@ -520,7 +520,7 @@ template <class V, class M> struct IsValidReference { } // end namespace detail -/// \brief Check whether Metadata has a Value. +/// Check whether Metadata has a Value. /// /// As an analogue to \a isa(), check whether \c MD has an \a Value inside of /// type \c X. @@ -539,7 +539,7 @@ inline return hasa(&MD); } -/// \brief Extract a Value from Metadata. +/// Extract a Value from Metadata. /// /// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD. template <class X, class Y> @@ -554,7 +554,7 @@ inline return extract(&MD); } -/// \brief Extract a Value from Metadata, allowing null. +/// Extract a Value from Metadata, allowing null. /// /// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X /// from \c MD, allowing \c MD to be null. @@ -566,7 +566,7 @@ extract_or_null(Y &&MD) { return nullptr; } -/// \brief Extract a Value from Metadata, if any. +/// Extract a Value from Metadata, if any. /// /// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X /// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a @@ -579,7 +579,7 @@ dyn_extract(Y &&MD) { return nullptr; } -/// \brief Extract a Value from Metadata, if any, allowing null. +/// Extract a Value from Metadata, if any, allowing null. /// /// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X /// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a @@ -595,7 +595,7 @@ dyn_extract_or_null(Y &&MD) { } // end namespace mdconst //===----------------------------------------------------------------------===// -/// \brief A single uniqued string. +/// A single uniqued string. /// /// These are used to efficiently contain a byte sequence for metadata. /// MDString is always unnamed. @@ -622,22 +622,22 @@ public: using iterator = StringRef::iterator; - /// \brief Pointer to the first byte of the string. + /// Pointer to the first byte of the string. iterator begin() const { return getString().begin(); } - /// \brief Pointer to one byte past the end of the string. + /// Pointer to one byte past the end of the string. iterator end() const { return getString().end(); } const unsigned char *bytes_begin() const { return getString().bytes_begin(); } const unsigned char *bytes_end() const { return getString().bytes_end(); } - /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. + /// Methods for support type inquiry through isa, cast, and dyn_cast. static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDStringKind; } }; -/// \brief A collection of metadata nodes that might be associated with a +/// A collection of metadata nodes that might be associated with a /// memory access used by the alias-analysis infrastructure. struct AAMDNodes { explicit AAMDNodes(MDNode *T = nullptr, MDNode *S = nullptr, @@ -652,16 +652,16 @@ struct AAMDNodes { explicit operator bool() const { return TBAA || Scope || NoAlias; } - /// \brief The tag for type-based alias analysis. + /// The tag for type-based alias analysis. MDNode *TBAA; - /// \brief The tag for alias scope specification (used with noalias). + /// The tag for alias scope specification (used with noalias). MDNode *Scope; - /// \brief The tag specifying the noalias scope. + /// The tag specifying the noalias scope. MDNode *NoAlias; - /// \brief Given two sets of AAMDNodes that apply to the same pointer, + /// Given two sets of AAMDNodes that apply to the same pointer, /// give the best AAMDNodes that are compatible with both (i.e. a set of /// nodes whose allowable aliasing conclusions are a subset of those /// allowable by both of the inputs). However, for efficiency @@ -699,7 +699,7 @@ struct DenseMapInfo<AAMDNodes> { } }; -/// \brief Tracking metadata reference owned by Metadata. +/// Tracking metadata reference owned by Metadata. /// /// Similar to \a TrackingMDRef, but it's expected to be owned by an instance /// of \a Metadata, which has the option of registering itself for callbacks to @@ -761,7 +761,7 @@ template <> struct simplify_type<const MDOperand> { static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); } }; -/// \brief Pointer to the context, with optional RAUW support. +/// Pointer to the context, with optional RAUW support. /// /// Either a raw (non-null) pointer to the \a LLVMContext, or an owned pointer /// to \a ReplaceableMetadataImpl (which has a reference to \a LLVMContext). @@ -785,7 +785,7 @@ public: operator LLVMContext &() { return getContext(); } - /// \brief Whether this contains RAUW support. + /// Whether this contains RAUW support. bool hasReplaceableUses() const { return Ptr.is<ReplaceableMetadataImpl *>(); } @@ -809,7 +809,7 @@ public: return getReplaceableUses(); } - /// \brief Assign RAUW support to this. + /// Assign RAUW support to this. /// /// Make this replaceable, taking ownership of \c ReplaceableUses (which must /// not be null). @@ -822,7 +822,7 @@ public: Ptr = ReplaceableUses.release(); } - /// \brief Drop RAUW support. + /// Drop RAUW support. /// /// Cede ownership of RAUW support, returning it. std::unique_ptr<ReplaceableMetadataImpl> takeReplaceableUses() { @@ -843,7 +843,7 @@ struct TempMDNodeDeleter { #define HANDLE_MDNODE_BRANCH(CLASS) HANDLE_MDNODE_LEAF(CLASS) #include "llvm/IR/Metadata.def" -/// \brief Metadata node. +/// Metadata node. /// /// Metadata nodes can be uniqued, like constants, or distinct. Temporary /// metadata nodes (with full support for RAUW) can be used to delay uniquing @@ -876,12 +876,12 @@ protected: void *operator new(size_t Size, unsigned NumOps); void operator delete(void *Mem); - /// \brief Required by std, but never called. + /// Required by std, but never called. void operator delete(void *, unsigned) { llvm_unreachable("Constructor throws?"); } - /// \brief Required by std, but never called. + /// Required by std, but never called. void operator delete(void *, unsigned, bool) { llvm_unreachable("Constructor throws?"); } @@ -910,10 +910,10 @@ public: static inline TempMDTuple getTemporary(LLVMContext &Context, ArrayRef<Metadata *> MDs); - /// \brief Create a (temporary) clone of this. + /// Create a (temporary) clone of this. TempMDNode clone() const; - /// \brief Deallocate a node created by getTemporary. + /// Deallocate a node created by getTemporary. /// /// Calls \c replaceAllUsesWith(nullptr) before deleting, so any remaining /// references will be reset. @@ -921,10 +921,10 @@ public: LLVMContext &getContext() const { return Context.getContext(); } - /// \brief Replace a specific operand. + /// Replace a specific operand. void replaceOperandWith(unsigned I, Metadata *New); - /// \brief Check if node is fully resolved. + /// Check if node is fully resolved. /// /// If \a isTemporary(), this always returns \c false; if \a isDistinct(), /// this always returns \c true. @@ -941,7 +941,7 @@ public: bool isDistinct() const { return Storage == Distinct; } bool isTemporary() const { return Storage == Temporary; } - /// \brief RAUW a temporary. + /// RAUW a temporary. /// /// \pre \a isTemporary() must be \c true. void replaceAllUsesWith(Metadata *MD) { @@ -950,7 +950,7 @@ public: Context.getReplaceableUses()->replaceAllUsesWith(MD); } - /// \brief Resolve cycles. + /// Resolve cycles. /// /// Once all forward declarations have been resolved, force cycles to be /// resolved. @@ -961,7 +961,7 @@ public: /// Resolve a unique, unresolved node. void resolve(); - /// \brief Replace a temporary node with a permanent one. + /// Replace a temporary node with a permanent one. /// /// Try to create a uniqued version of \c N -- in place, if possible -- and /// return it. If \c N cannot be uniqued, return a distinct node instead. @@ -971,7 +971,7 @@ public: return cast<T>(N.release()->replaceWithPermanentImpl()); } - /// \brief Replace a temporary node with a uniqued one. + /// Replace a temporary node with a uniqued one. /// /// Create a uniqued version of \c N -- in place, if possible -- and return /// it. Takes ownership of the temporary node. @@ -983,7 +983,7 @@ public: return cast<T>(N.release()->replaceWithUniquedImpl()); } - /// \brief Replace a temporary node with a distinct one. + /// Replace a temporary node with a distinct one. /// /// Create a distinct version of \c N -- in place, if possible -- and return /// it. Takes ownership of the temporary node. @@ -999,7 +999,7 @@ private: MDNode *replaceWithDistinctImpl(); protected: - /// \brief Set an operand. + /// Set an operand. /// /// Sets the operand directly, without worrying about uniquing. void setOperand(unsigned I, Metadata *New); @@ -1019,14 +1019,14 @@ private: void decrementUnresolvedOperandCount(); void countUnresolvedOperands(); - /// \brief Mutate this to be "uniqued". + /// Mutate this to be "uniqued". /// /// Mutate this so that \a isUniqued(). /// \pre \a isTemporary(). /// \pre already added to uniquing set. void makeUniqued(); - /// \brief Mutate this to be "distinct". + /// Mutate this to be "distinct". /// /// Mutate this so that \a isDistinct(). /// \pre \a isTemporary(). @@ -1069,10 +1069,10 @@ public: return op_begin()[I]; } - /// \brief Return number of MDNode operands. + /// Return number of MDNode operands. unsigned getNumOperands() const { return NumOperands; } - /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -1084,10 +1084,10 @@ public: } } - /// \brief Check whether MDNode is a vtable access. + /// Check whether MDNode is a vtable access. bool isTBAAVtableAccess() const; - /// \brief Methods for metadata merging. + /// Methods for metadata merging. static MDNode *concatenate(MDNode *A, MDNode *B); static MDNode *intersect(MDNode *A, MDNode *B); static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); @@ -1097,7 +1097,7 @@ public: static MDNode *getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B); }; -/// \brief Tuple of metadata. +/// Tuple of metadata. /// /// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by /// default based on their operands. @@ -1125,7 +1125,7 @@ class MDTuple : public MDNode { } public: - /// \brief Get the hash, if any. + /// Get the hash, if any. unsigned getHash() const { return SubclassData32; } static MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) { @@ -1136,14 +1136,14 @@ public: return getImpl(Context, MDs, Uniqued, /* ShouldCreate */ false); } - /// \brief Return a distinct node. + /// Return a distinct node. /// /// Return a distinct node -- i.e., a node that is not uniqued. static MDTuple *getDistinct(LLVMContext &Context, ArrayRef<Metadata *> MDs) { return getImpl(Context, MDs, Distinct); } - /// \brief Return a temporary node. + /// Return a temporary node. /// /// For use in constructing cyclic MDNode structures. A temporary MDNode is /// not uniqued, may be RAUW'd, and must be manually deleted with @@ -1153,7 +1153,7 @@ public: return TempMDTuple(getImpl(Context, MDs, Temporary)); } - /// \brief Return a (temporary) clone of this. + /// Return a (temporary) clone of this. TempMDTuple clone() const { return cloneImpl(); } static bool classof(const Metadata *MD) { @@ -1182,7 +1182,7 @@ void TempMDNodeDeleter::operator()(MDNode *Node) const { MDNode::deleteTemporary(Node); } -/// \brief Typed iterator through MDNode operands. +/// Typed iterator through MDNode operands. /// /// An iterator that transforms an \a MDNode::iterator into an iterator over a /// particular Metadata subclass. @@ -1213,7 +1213,7 @@ public: bool operator!=(const TypedMDOperandIterator &X) const { return I != X.I; } }; -/// \brief Typed, array-like tuple of metadata. +/// Typed, array-like tuple of metadata. /// /// This is a wrapper for \a MDTuple that makes it act like an array holding a /// particular type of metadata. @@ -1314,7 +1314,7 @@ public: }; //===----------------------------------------------------------------------===// -/// \brief A tuple of MDNodes. +/// A tuple of MDNodes. /// /// Despite its name, a NamedMDNode isn't itself an MDNode. NamedMDNodes belong /// to modules, have names, and contain lists of MDNodes. @@ -1377,7 +1377,7 @@ public: NamedMDNode(const NamedMDNode &) = delete; ~NamedMDNode(); - /// \brief Drop all references and remove the node from parent module. + /// Drop all references and remove the node from parent module. void eraseFromParent(); /// Remove all uses and clear node vector. @@ -1385,7 +1385,7 @@ public: /// Drop all references to this node's operands. void clearOperands(); - /// \brief Get the module that holds this named metadata collection. + /// Get the module that holds this named metadata collection. inline Module *getParent() { return Parent; } inline const Module *getParent() const { return Parent; } diff --git a/contrib/llvm/include/llvm/IR/Module.h b/contrib/llvm/include/llvm/IR/Module.h index 196e32e3615c..a405f7df3efe 100644 --- a/contrib/llvm/include/llvm/IR/Module.h +++ b/contrib/llvm/include/llvm/IR/Module.h @@ -59,7 +59,7 @@ class StructType; /// A module maintains a GlobalValRefMap object that is used to hold all /// constant references to global variables in the module. When a global /// variable is destroyed, it should have no entries in the GlobalValueRefMap. -/// @brief The main container class for the LLVM Intermediate Representation. +/// The main container class for the LLVM Intermediate Representation. class Module { /// @name Types And Enumerations /// @{ @@ -207,13 +207,18 @@ public: /// @returns the module identifier as a string const std::string &getModuleIdentifier() const { return ModuleID; } + /// Returns the number of non-debug IR instructions in the module. + /// This is equivalent to the sum of the IR instruction counts of each + /// function contained in the module. + unsigned getInstructionCount(); + /// Get the module's original source file name. When compiling from /// bitcode, this is taken from a bitcode record where it was recorded. /// For other compiles it is the same as the ModuleID, which would /// contain the source file name. const std::string &getSourceFileName() const { return SourceFileName; } - /// \brief Get a short "name" for the module. + /// Get a short "name" for the module. /// /// This is useful for debugging or logging. It is essentially a convenience /// wrapper around getModuleIdentifier(). @@ -251,9 +256,16 @@ public: /// versions when the pass does not change. std::unique_ptr<RandomNumberGenerator> createRNG(const Pass* P) const; -/// @} -/// @name Module Level Mutators -/// @{ + /// Return true if size-info optimization remark is enabled, false + /// otherwise. + bool shouldEmitInstrCountChangedRemark() { + return getContext().getDiagHandlerPtr()->isAnalysisRemarkEnabled( + "size-info"); + } + + /// @} + /// @name Module Level Mutators + /// @{ /// Set the module identifier. void setModuleIdentifier(StringRef ID) { ModuleID = ID; } @@ -795,14 +807,14 @@ public: /// @name Utility functions for querying Debug information. /// @{ - /// \brief Returns the Number of Register ParametersDwarf Version by checking + /// Returns the Number of Register ParametersDwarf Version by checking /// module flags. unsigned getNumberRegisterParameters() const; - /// \brief Returns the Dwarf Version by checking module flags. + /// Returns the Dwarf Version by checking module flags. unsigned getDwarfVersion() const; - /// \brief Returns the CodeView Version by checking module flags. + /// Returns the CodeView Version by checking module flags. /// Returns zero if not present in module. unsigned getCodeViewFlag() const; @@ -810,10 +822,10 @@ public: /// @name Utility functions for querying and setting PIC level /// @{ - /// \brief Returns the PIC level (small or large model) + /// Returns the PIC level (small or large model) PICLevel::Level getPICLevel() const; - /// \brief Set the PIC level (small or large model) + /// Set the PIC level (small or large model) void setPICLevel(PICLevel::Level PL); /// @} @@ -821,28 +833,35 @@ public: /// @name Utility functions for querying and setting PIE level /// @{ - /// \brief Returns the PIE level (small or large model) + /// Returns the PIE level (small or large model) PIELevel::Level getPIELevel() const; - /// \brief Set the PIE level (small or large model) + /// Set the PIE level (small or large model) void setPIELevel(PIELevel::Level PL); /// @} /// @name Utility functions for querying and setting PGO summary /// @{ - /// \brief Attach profile summary metadata to this module. + /// Attach profile summary metadata to this module. void setProfileSummary(Metadata *M); - /// \brief Returns profile summary metadata + /// Returns profile summary metadata Metadata *getProfileSummary(); /// @} + /// Returns true if PLT should be avoided for RTLib calls. + bool getRtLibUseGOT() const; + + /// Set that PLT should be avoid for RTLib calls. + void setRtLibUseGOT(); + + /// Take ownership of the given memory buffer. void setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB); }; -/// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect +/// Given "llvm.used" or "llvm.compiler.used" as a global name, collect /// the initializer elements of that global in Set and return the global itself. GlobalVariable *collectUsedGlobalVariables(const Module &M, SmallPtrSetImpl<GlobalValue *> &Set, diff --git a/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h b/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h index dd7a0db83774..fdf3d4b5f1ce 100644 --- a/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h +++ b/contrib/llvm/include/llvm/IR/ModuleSummaryIndex.h @@ -25,6 +25,10 @@ #include "llvm/ADT/StringRef.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Module.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/ScaledNumber.h" +#include "llvm/Support/StringSaver.h" #include <algorithm> #include <array> #include <cassert> @@ -45,7 +49,7 @@ template <typename T> struct MappingTraits; } // end namespace yaml -/// \brief Class to accumulate and hold information about a callee. +/// Class to accumulate and hold information about a callee. struct CalleeInfo { enum class HotnessType : uint8_t { Unknown = 0, @@ -54,13 +58,44 @@ struct CalleeInfo { Hot = 3, Critical = 4 }; - HotnessType Hotness = HotnessType::Unknown; - CalleeInfo() = default; - explicit CalleeInfo(HotnessType Hotness) : Hotness(Hotness) {} + // The size of the bit-field might need to be adjusted if more values are + // added to HotnessType enum. + uint32_t Hotness : 3; + + /// The value stored in RelBlockFreq has to be interpreted as the digits of + /// a scaled number with a scale of \p -ScaleShift. + uint32_t RelBlockFreq : 29; + static constexpr int32_t ScaleShift = 8; + static constexpr uint64_t MaxRelBlockFreq = (1 << 29) - 1; + + CalleeInfo() + : Hotness(static_cast<uint32_t>(HotnessType::Unknown)), RelBlockFreq(0) {} + explicit CalleeInfo(HotnessType Hotness, uint64_t RelBF) + : Hotness(static_cast<uint32_t>(Hotness)), RelBlockFreq(RelBF) {} void updateHotness(const HotnessType OtherHotness) { - Hotness = std::max(Hotness, OtherHotness); + Hotness = std::max(Hotness, static_cast<uint32_t>(OtherHotness)); + } + + HotnessType getHotness() const { return HotnessType(Hotness); } + + /// Update \p RelBlockFreq from \p BlockFreq and \p EntryFreq + /// + /// BlockFreq is divided by EntryFreq and added to RelBlockFreq. To represent + /// fractional values, the result is represented as a fixed point number with + /// scale of -ScaleShift. + void updateRelBlockFreq(uint64_t BlockFreq, uint64_t EntryFreq) { + if (EntryFreq == 0) + return; + using Scaled64 = ScaledNumber<uint64_t>; + Scaled64 Temp(BlockFreq, ScaleShift); + Temp /= Scaled64::get(EntryFreq); + + uint64_t Sum = + SaturatingAdd<uint64_t>(Temp.toInt<uint64_t>(), RelBlockFreq); + Sum = std::min(Sum, uint64_t(MaxRelBlockFreq)); + RelBlockFreq = static_cast<uint32_t>(Sum); } }; @@ -69,9 +104,29 @@ class GlobalValueSummary; using GlobalValueSummaryList = std::vector<std::unique_ptr<GlobalValueSummary>>; struct GlobalValueSummaryInfo { - /// The GlobalValue corresponding to this summary. This is only used in - /// per-module summaries. - const GlobalValue *GV = nullptr; + union NameOrGV { + NameOrGV(bool HaveGVs) { + if (HaveGVs) + GV = nullptr; + else + Name = ""; + } + + /// The GlobalValue corresponding to this summary. This is only used in + /// per-module summaries and when the IR is available. E.g. when module + /// analysis is being run, or when parsing both the IR and the summary + /// from assembly. + const GlobalValue *GV; + + /// Summary string representation. This StringRef points to BC module + /// string table and is valid until module data is stored in memory. + /// This is guaranteed to happen until runThinLTOBackend function is + /// called, so it is safe to use this field during thin link. This field + /// is only valid if summary index was loaded from BC file. + StringRef Name; + } U; + + GlobalValueSummaryInfo(bool HaveGVs) : U(HaveGVs) {} /// List of global value summary structures for a particular value held /// in the GlobalValueMap. Requires a vector in the case of multiple @@ -91,44 +146,98 @@ using GlobalValueSummaryMapTy = /// Struct that holds a reference to a particular GUID in a global value /// summary. struct ValueInfo { - const GlobalValueSummaryMapTy::value_type *Ref = nullptr; + PointerIntPair<const GlobalValueSummaryMapTy::value_type *, 1, bool> + RefAndFlag; ValueInfo() = default; - ValueInfo(const GlobalValueSummaryMapTy::value_type *Ref) : Ref(Ref) {} + ValueInfo(bool HaveGVs, const GlobalValueSummaryMapTy::value_type *R) { + RefAndFlag.setPointer(R); + RefAndFlag.setInt(HaveGVs); + } - operator bool() const { return Ref; } + operator bool() const { return getRef(); } - GlobalValue::GUID getGUID() const { return Ref->first; } - const GlobalValue *getValue() const { return Ref->second.GV; } + GlobalValue::GUID getGUID() const { return getRef()->first; } + const GlobalValue *getValue() const { + assert(haveGVs()); + return getRef()->second.U.GV; + } ArrayRef<std::unique_ptr<GlobalValueSummary>> getSummaryList() const { - return Ref->second.SummaryList; + return getRef()->second.SummaryList; + } + + StringRef name() const { + return haveGVs() ? getRef()->second.U.GV->getName() + : getRef()->second.U.Name; } + + bool haveGVs() const { return RefAndFlag.getInt(); } + + const GlobalValueSummaryMapTy::value_type *getRef() const { + return RefAndFlag.getPointer(); + } + + bool isDSOLocal() const; }; +inline raw_ostream &operator<<(raw_ostream &OS, const ValueInfo &VI) { + OS << VI.getGUID(); + if (!VI.name().empty()) + OS << " (" << VI.name() << ")"; + return OS; +} + +inline bool operator==(const ValueInfo &A, const ValueInfo &B) { + assert(A.getRef() && B.getRef() && + "Need ValueInfo with non-null Ref for comparison"); + return A.getRef() == B.getRef(); +} + +inline bool operator!=(const ValueInfo &A, const ValueInfo &B) { + assert(A.getRef() && B.getRef() && + "Need ValueInfo with non-null Ref for comparison"); + return A.getRef() != B.getRef(); +} + +inline bool operator<(const ValueInfo &A, const ValueInfo &B) { + assert(A.getRef() && B.getRef() && + "Need ValueInfo with non-null Ref to compare GUIDs"); + return A.getGUID() < B.getGUID(); +} + template <> struct DenseMapInfo<ValueInfo> { static inline ValueInfo getEmptyKey() { - return ValueInfo((GlobalValueSummaryMapTy::value_type *)-1); + return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8); } static inline ValueInfo getTombstoneKey() { - return ValueInfo((GlobalValueSummaryMapTy::value_type *)-2); + return ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-16); + } + + static inline bool isSpecialKey(ValueInfo V) { + return V == getTombstoneKey() || V == getEmptyKey(); } - static bool isEqual(ValueInfo L, ValueInfo R) { return L.Ref == R.Ref; } - static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.Ref; } + static bool isEqual(ValueInfo L, ValueInfo R) { + // We are not supposed to mix ValueInfo(s) with different HaveGVs flag + // in a same container. + assert(isSpecialKey(L) || isSpecialKey(R) || (L.haveGVs() == R.haveGVs())); + return L.getRef() == R.getRef(); + } + static unsigned getHashValue(ValueInfo I) { return (uintptr_t)I.getRef(); } }; -/// \brief Function and variable summary information to aid decisions and +/// Function and variable summary information to aid decisions and /// implementation of importing. class GlobalValueSummary { public: - /// \brief Sububclass discriminator (for dyn_cast<> et al.) + /// Sububclass discriminator (for dyn_cast<> et al.) enum SummaryKind : unsigned { AliasKind, FunctionKind, GlobalVarKind }; /// Group flags (Linkage, NotEligibleToImport, etc.) as a bitfield. struct GVFlags { - /// \brief The linkage type of the associated global value. + /// The linkage type of the associated global value. /// /// One use is to flag values that have local linkage types and need to /// have module identifier appended before placing into the combined @@ -170,7 +279,7 @@ private: /// GUID includes the module level id in the hash. GlobalValue::GUID OriginalName = 0; - /// \brief Path of module IR containing value's definition, used to locate + /// Path of module IR containing value's definition, used to locate /// module during importing. /// /// This is only used during parsing of the combined index, or when @@ -185,8 +294,6 @@ private: /// are listed in the derived FunctionSummary object. std::vector<ValueInfo> RefEdgeList; - bool isLive() const { return Flags.Live; } - protected: GlobalValueSummary(SummaryKind K, GVFlags Flags, std::vector<ValueInfo> Refs) : Kind(K), Flags(Flags), RefEdgeList(std::move(Refs)) { @@ -199,7 +306,7 @@ public: /// Returns the hash of the original name, it is identical to the GUID for /// externally visible symbols, but not for local ones. - GlobalValue::GUID getOriginalName() { return OriginalName; } + GlobalValue::GUID getOriginalName() const { return OriginalName; } /// Initialize the original name hash in this summary. void setOriginalName(GlobalValue::GUID Name) { OriginalName = Name; } @@ -215,7 +322,7 @@ public: StringRef modulePath() const { return ModulePath; } /// Get the flags for this GlobalValue (see \p struct GVFlags). - GVFlags flags() { return Flags; } + GVFlags flags() const { return Flags; } /// Return linkage type recorded for this global value. GlobalValue::LinkageTypes linkage() const { @@ -231,6 +338,8 @@ public: /// Return true if this global value can't be imported. bool notEligibleToImport() const { return Flags.NotEligibleToImport; } + bool isLive() const { return Flags.Live; } + void setLive(bool Live) { Flags.Live = Live; } void setDSOLocal(bool Local) { Flags.DSOLocal = Local; } @@ -249,11 +358,9 @@ public: const GlobalValueSummary *getBaseObject() const; friend class ModuleSummaryIndex; - friend void computeDeadSymbols(class ModuleSummaryIndex &, - const DenseSet<GlobalValue::GUID> &); }; -/// \brief Alias summary information. +/// Alias summary information. class AliasSummary : public GlobalValueSummary { GlobalValueSummary *AliaseeSummary; // AliaseeGUID is only set and accessed when we are building a combined index @@ -273,6 +380,8 @@ public: void setAliasee(GlobalValueSummary *Aliasee) { AliaseeSummary = Aliasee; } void setAliaseeGUID(GlobalValue::GUID GUID) { AliaseeGUID = GUID; } + bool hasAliasee() const { return !!AliaseeSummary; } + const GlobalValueSummary &getAliasee() const { assert(AliaseeSummary && "Unexpected missing aliasee summary"); return *AliaseeSummary; @@ -300,13 +409,20 @@ inline GlobalValueSummary *GlobalValueSummary::getBaseObject() { return this; } -/// \brief Function summary information to aid decisions and implementation of +/// Function summary information to aid decisions and implementation of /// importing. class FunctionSummary : public GlobalValueSummary { public: /// <CalleeValueInfo, CalleeInfo> call edge pair. using EdgeTy = std::pair<ValueInfo, CalleeInfo>; + /// Types for -force-summary-edges-cold debugging option. + enum ForceSummaryHotnessType : unsigned { + FSHT_None, + FSHT_AllNonCritical, + FSHT_All + }; + /// An "identifier" for a virtual function. This contains the type identifier /// represented as a GUID and the offset from the address point to the virtual /// function pointer, where "address point" is as defined in the Itanium ABI: @@ -324,6 +440,26 @@ public: std::vector<uint64_t> Args; }; + /// All type identifier related information. Because these fields are + /// relatively uncommon we only allocate space for them if necessary. + struct TypeIdInfo { + /// List of type identifiers used by this function in llvm.type.test + /// intrinsics referenced by something other than an llvm.assume intrinsic, + /// represented as GUIDs. + std::vector<GlobalValue::GUID> TypeTests; + + /// List of virtual calls made by this function using (respectively) + /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics that do + /// not have all constant integer arguments. + std::vector<VFuncId> TypeTestAssumeVCalls, TypeCheckedLoadVCalls; + + /// List of virtual calls made by this function using (respectively) + /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics with + /// all constant integer arguments. + std::vector<ConstVCall> TypeTestAssumeConstVCalls, + TypeCheckedLoadConstVCalls; + }; + /// Function attribute flags. Used to track if a function accesses memory, /// recurses or aliases. struct FFlags { @@ -333,6 +469,25 @@ public: unsigned ReturnDoesNotAlias : 1; }; + /// Create an empty FunctionSummary (with specified call edges). + /// Used to represent external nodes and the dummy root node. + static FunctionSummary + makeDummyFunctionSummary(std::vector<FunctionSummary::EdgeTy> Edges) { + return FunctionSummary( + FunctionSummary::GVFlags( + GlobalValue::LinkageTypes::AvailableExternallyLinkage, + /*NotEligibleToImport=*/true, /*Live=*/true, /*IsLocal=*/false), + 0, FunctionSummary::FFlags{}, std::vector<ValueInfo>(), + std::move(Edges), std::vector<GlobalValue::GUID>(), + std::vector<FunctionSummary::VFuncId>(), + std::vector<FunctionSummary::VFuncId>(), + std::vector<FunctionSummary::ConstVCall>(), + std::vector<FunctionSummary::ConstVCall>()); + } + + /// A dummy node to reference external functions that aren't in the index + static FunctionSummary ExternalNode; + private: /// Number of instructions (ignoring debug instructions, e.g.) computed /// during the initial compile step when the summary index is first built. @@ -345,25 +500,6 @@ private: /// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function. std::vector<EdgeTy> CallGraphEdgeList; - /// All type identifier related information. Because these fields are - /// relatively uncommon we only allocate space for them if necessary. - struct TypeIdInfo { - /// List of type identifiers used by this function in llvm.type.test - /// intrinsics other than by an llvm.assume intrinsic, represented as GUIDs. - std::vector<GlobalValue::GUID> TypeTests; - - /// List of virtual calls made by this function using (respectively) - /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics that do - /// not have all constant integer arguments. - std::vector<VFuncId> TypeTestAssumeVCalls, TypeCheckedLoadVCalls; - - /// List of virtual calls made by this function using (respectively) - /// llvm.assume(llvm.type.test) or llvm.type.checked.load intrinsics with - /// all constant integer arguments. - std::vector<ConstVCall> TypeTestAssumeConstVCalls, - TypeCheckedLoadConstVCalls; - }; - std::unique_ptr<TypeIdInfo> TIdInfo; public: @@ -393,7 +529,7 @@ public: } /// Get function attribute flags. - FFlags &fflags() { return FunFlags; } + FFlags fflags() const { return FunFlags; } /// Get the instruction count recorded for this function. unsigned instCount() const { return InstCount; } @@ -452,6 +588,10 @@ public: TIdInfo = llvm::make_unique<TypeIdInfo>(); TIdInfo->TypeTests.push_back(Guid); } + + const TypeIdInfo *getTypeIdInfo() const { return TIdInfo.get(); }; + + friend struct GraphTraits<ValueInfo>; }; template <> struct DenseMapInfo<FunctionSummary::VFuncId> { @@ -488,7 +628,7 @@ template <> struct DenseMapInfo<FunctionSummary::ConstVCall> { } }; -/// \brief Global variable summary information to aid decisions and +/// Global variable summary information to aid decisions and /// implementation of importing. /// /// Currently this doesn't add anything to the base \p GlobalValueSummary, @@ -538,8 +678,11 @@ struct TypeTestResolution { struct WholeProgramDevirtResolution { enum Kind { - Indir, ///< Just do a regular virtual call - SingleImpl, ///< Single implementation devirtualization + Indir, ///< Just do a regular virtual call + SingleImpl, ///< Single implementation devirtualization + BranchFunnel, ///< When retpoline mitigation is enabled, use a branch funnel + ///< that is defined in the merged module. Otherwise same as + ///< Indir. } TheKind = Indir; std::string SingleImplName; @@ -607,7 +750,6 @@ private: /// Mapping from type identifiers to summary information for that type /// identifier. - // FIXME: Add bitcode read/write support for this field. std::map<std::string, TypeIdSummary> TypeIdMap; /// Mapping from original ID to GUID. If original ID can map to multiple @@ -619,24 +761,111 @@ private: /// considered live. bool WithGlobalValueDeadStripping = false; + /// Indicates that distributed backend should skip compilation of the + /// module. Flag is suppose to be set by distributed ThinLTO indexing + /// when it detected that the module is not needed during the final + /// linking. As result distributed backend should just output a minimal + /// valid object file. + bool SkipModuleByDistributedBackend = false; + + /// If true then we're performing analysis of IR module, or parsing along with + /// the IR from assembly. The value of 'false' means we're reading summary + /// from BC or YAML source. Affects the type of value stored in NameOrGV + /// union. + bool HaveGVs; + std::set<std::string> CfiFunctionDefs; std::set<std::string> CfiFunctionDecls; + // Used in cases where we want to record the name of a global, but + // don't have the string owned elsewhere (e.g. the Strtab on a module). + StringSaver Saver; + BumpPtrAllocator Alloc; + // YAML I/O support. friend yaml::MappingTraits<ModuleSummaryIndex>; GlobalValueSummaryMapTy::value_type * getOrInsertValuePtr(GlobalValue::GUID GUID) { - return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo{}).first; + return &*GlobalValueMap.emplace(GUID, GlobalValueSummaryInfo(HaveGVs)) + .first; } public: + // See HaveGVs variable comment. + ModuleSummaryIndex(bool HaveGVs) : HaveGVs(HaveGVs), Saver(Alloc) {} + + bool haveGVs() const { return HaveGVs; } + gvsummary_iterator begin() { return GlobalValueMap.begin(); } const_gvsummary_iterator begin() const { return GlobalValueMap.begin(); } gvsummary_iterator end() { return GlobalValueMap.end(); } const_gvsummary_iterator end() const { return GlobalValueMap.end(); } size_t size() const { return GlobalValueMap.size(); } + /// Convenience function for doing a DFS on a ValueInfo. Marks the function in + /// the FunctionHasParent map. + static void discoverNodes(ValueInfo V, + std::map<ValueInfo, bool> &FunctionHasParent) { + if (!V.getSummaryList().size()) + return; // skip external functions that don't have summaries + + // Mark discovered if we haven't yet + auto S = FunctionHasParent.emplace(V, false); + + // Stop if we've already discovered this node + if (!S.second) + return; + + FunctionSummary *F = + dyn_cast<FunctionSummary>(V.getSummaryList().front().get()); + assert(F != nullptr && "Expected FunctionSummary node"); + + for (auto &C : F->calls()) { + // Insert node if necessary + auto S = FunctionHasParent.emplace(C.first, true); + + // Skip nodes that we're sure have parents + if (!S.second && S.first->second) + continue; + + if (S.second) + discoverNodes(C.first, FunctionHasParent); + else + S.first->second = true; + } + } + + // Calculate the callgraph root + FunctionSummary calculateCallGraphRoot() { + // Functions that have a parent will be marked in FunctionHasParent pair. + // Once we've marked all functions, the functions in the map that are false + // have no parent (so they're the roots) + std::map<ValueInfo, bool> FunctionHasParent; + + for (auto &S : *this) { + // Skip external functions + if (!S.second.SummaryList.size() || + !isa<FunctionSummary>(S.second.SummaryList.front().get())) + continue; + discoverNodes(ValueInfo(HaveGVs, &S), FunctionHasParent); + } + + std::vector<FunctionSummary::EdgeTy> Edges; + // create edges to all roots in the Index + for (auto &P : FunctionHasParent) { + if (P.second) + continue; // skip over non-root nodes + Edges.push_back(std::make_pair(P.first, CalleeInfo{})); + } + if (Edges.empty()) { + // Failed to find root - return an empty node + return FunctionSummary::makeDummyFunctionSummary({}); + } + auto CallGraphRoot = FunctionSummary::makeDummyFunctionSummary(Edges); + return CallGraphRoot; + } + bool withGlobalValueDeadStripping() const { return WithGlobalValueDeadStripping; } @@ -644,27 +873,54 @@ public: WithGlobalValueDeadStripping = true; } + bool skipModuleByDistributedBackend() const { + return SkipModuleByDistributedBackend; + } + void setSkipModuleByDistributedBackend() { + SkipModuleByDistributedBackend = true; + } + bool isGlobalValueLive(const GlobalValueSummary *GVS) const { return !WithGlobalValueDeadStripping || GVS->isLive(); } bool isGUIDLive(GlobalValue::GUID GUID) const; + /// Return a ValueInfo for the index value_type (convenient when iterating + /// index). + ValueInfo getValueInfo(const GlobalValueSummaryMapTy::value_type &R) const { + return ValueInfo(HaveGVs, &R); + } + /// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo(). ValueInfo getValueInfo(GlobalValue::GUID GUID) const { auto I = GlobalValueMap.find(GUID); - return ValueInfo(I == GlobalValueMap.end() ? nullptr : &*I); + return ValueInfo(HaveGVs, I == GlobalValueMap.end() ? nullptr : &*I); } /// Return a ValueInfo for \p GUID. ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID) { - return ValueInfo(getOrInsertValuePtr(GUID)); + return ValueInfo(HaveGVs, getOrInsertValuePtr(GUID)); + } + + // Save a string in the Index. Use before passing Name to + // getOrInsertValueInfo when the string isn't owned elsewhere (e.g. on the + // module's Strtab). + StringRef saveString(std::string String) { return Saver.save(String); } + + /// Return a ValueInfo for \p GUID setting value \p Name. + ValueInfo getOrInsertValueInfo(GlobalValue::GUID GUID, StringRef Name) { + assert(!HaveGVs); + auto VP = getOrInsertValuePtr(GUID); + VP->second.U.Name = Name; + return ValueInfo(HaveGVs, VP); } /// Return a ValueInfo for \p GV and mark it as belonging to GV. ValueInfo getOrInsertValueInfo(const GlobalValue *GV) { + assert(HaveGVs); auto VP = getOrInsertValuePtr(GV->getGUID()); - VP->second.GV = GV; - return ValueInfo(VP); + VP->second.U.GV = GV; + return ValueInfo(HaveGVs, VP); } /// Return the GUID for \p OriginalId in the OidGuidMap. @@ -679,6 +935,12 @@ public: std::set<std::string> &cfiFunctionDecls() { return CfiFunctionDecls; } const std::set<std::string> &cfiFunctionDecls() const { return CfiFunctionDecls; } + /// Add a global value summary for a value. + void addGlobalValueSummary(const GlobalValue &GV, + std::unique_ptr<GlobalValueSummary> Summary) { + addGlobalValueSummary(getOrInsertValueInfo(&GV), std::move(Summary)); + } + /// Add a global value summary for a value of the given name. void addGlobalValueSummary(StringRef ValueName, std::unique_ptr<GlobalValueSummary> Summary) { @@ -692,7 +954,7 @@ public: addOriginalName(VI.getGUID(), Summary->getOriginalName()); // Here we have a notionally const VI, but the value it points to is owned // by the non-const *this. - const_cast<GlobalValueSummaryMapTy::value_type *>(VI.Ref) + const_cast<GlobalValueSummaryMapTy::value_type *>(VI.getRef()) ->second.SummaryList.push_back(std::move(Summary)); } @@ -730,8 +992,7 @@ public: GlobalValueSummary *getGlobalValueSummary(const GlobalValue &GV, bool PerModuleIndex = true) const { assert(GV.hasName() && "Can't get GlobalValueSummary for GV with no name"); - return getGlobalValueSummary(GlobalValue::getGUID(GV.getName()), - PerModuleIndex); + return getGlobalValueSummary(GV.getGUID(), PerModuleIndex); } /// Returns the first GlobalValueSummary for \p ValueGUID, asserting that @@ -788,6 +1049,13 @@ public: return &*ModulePathStringTable.insert({ModPath, {ModId, Hash}}).first; } + /// Return module entry for module with the given \p ModPath. + ModuleInfo *getModule(StringRef ModPath) { + auto It = ModulePathStringTable.find(ModPath); + assert(It != ModulePathStringTable.end() && "Module not registered"); + return &*It; + } + /// Check if the given Module has any functions available for exporting /// in the index. We consider any module present in the ModulePathStringTable /// to have exported functions. @@ -814,7 +1082,7 @@ public: return &I->second; } - /// Collect for the given module the list of function it defines + /// Collect for the given module the list of functions it defines /// (GUID -> Summary). void collectDefinedFunctionsForModule(StringRef ModulePath, GVSummaryMapTy &GVSummaryMap) const; @@ -823,6 +1091,65 @@ public: /// Summary). void collectDefinedGVSummariesPerModule( StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries) const; + + /// Print to an output stream. + void print(raw_ostream &OS, bool IsForDebug = false) const; + + /// Dump to stderr (for debugging). + void dump() const; + + /// Export summary to dot file for GraphViz. + void exportToDot(raw_ostream& OS) const; + + /// Print out strongly connected components for debugging. + void dumpSCCs(raw_ostream &OS); +}; + +/// GraphTraits definition to build SCC for the index +template <> struct GraphTraits<ValueInfo> { + typedef ValueInfo NodeRef; + + static NodeRef valueInfoFromEdge(FunctionSummary::EdgeTy &P) { + return P.first; + } + using ChildIteratorType = + mapped_iterator<std::vector<FunctionSummary::EdgeTy>::iterator, + decltype(&valueInfoFromEdge)>; + + static NodeRef getEntryNode(ValueInfo V) { return V; } + + static ChildIteratorType child_begin(NodeRef N) { + if (!N.getSummaryList().size()) // handle external function + return ChildIteratorType( + FunctionSummary::ExternalNode.CallGraphEdgeList.begin(), + &valueInfoFromEdge); + FunctionSummary *F = + cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject()); + return ChildIteratorType(F->CallGraphEdgeList.begin(), &valueInfoFromEdge); + } + + static ChildIteratorType child_end(NodeRef N) { + if (!N.getSummaryList().size()) // handle external function + return ChildIteratorType( + FunctionSummary::ExternalNode.CallGraphEdgeList.end(), + &valueInfoFromEdge); + FunctionSummary *F = + cast<FunctionSummary>(N.getSummaryList().front()->getBaseObject()); + return ChildIteratorType(F->CallGraphEdgeList.end(), &valueInfoFromEdge); + } +}; + +template <> +struct GraphTraits<ModuleSummaryIndex *> : public GraphTraits<ValueInfo> { + static NodeRef getEntryNode(ModuleSummaryIndex *I) { + std::unique_ptr<GlobalValueSummary> Root = + make_unique<FunctionSummary>(I->calculateCallGraphRoot()); + GlobalValueSummaryInfo G(I->haveGVs()); + G.SummaryList.push_back(std::move(Root)); + static auto P = + GlobalValueSummaryMapTy::value_type(GlobalValue::GUID(0), std::move(G)); + return ValueInfo(I->haveGVs(), &P); + } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h b/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h index 4687f2d53e7e..1b339ab32cf1 100644 --- a/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h +++ b/contrib/llvm/include/llvm/IR/ModuleSummaryIndexYAML.h @@ -98,6 +98,8 @@ template <> struct ScalarEnumerationTraits<WholeProgramDevirtResolution::Kind> { static void enumeration(IO &io, WholeProgramDevirtResolution::Kind &value) { io.enumCase(value, "Indir", WholeProgramDevirtResolution::Indir); io.enumCase(value, "SingleImpl", WholeProgramDevirtResolution::SingleImpl); + io.enumCase(value, "BranchFunnel", + WholeProgramDevirtResolution::BranchFunnel); } }; @@ -136,6 +138,7 @@ template <> struct MappingTraits<TypeIdSummary> { struct FunctionSummaryYaml { unsigned Linkage; bool NotEligibleToImport, Live, IsLocal; + std::vector<uint64_t> Refs; std::vector<uint64_t> TypeTests; std::vector<FunctionSummary::VFuncId> TypeTestAssumeVCalls, TypeCheckedLoadVCalls; @@ -178,6 +181,7 @@ template <> struct MappingTraits<FunctionSummaryYaml> { io.mapOptional("NotEligibleToImport", summary.NotEligibleToImport); io.mapOptional("Live", summary.Live); io.mapOptional("Local", summary.IsLocal); + io.mapOptional("Refs", summary.Refs); io.mapOptional("TypeTests", summary.TypeTests); io.mapOptional("TypeTestAssumeVCalls", summary.TypeTestAssumeVCalls); io.mapOptional("TypeCheckedLoadVCalls", summary.TypeCheckedLoadVCalls); @@ -207,13 +211,21 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> { io.setError("key not an integer"); return; } - auto &Elem = V[KeyInt]; + if (!V.count(KeyInt)) + V.emplace(KeyInt, /*IsAnalysis=*/false); + auto &Elem = V.find(KeyInt)->second; for (auto &FSum : FSums) { + std::vector<ValueInfo> Refs; + for (auto &RefGUID : FSum.Refs) { + if (!V.count(RefGUID)) + V.emplace(RefGUID, /*IsAnalysis=*/false); + Refs.push_back(ValueInfo(/*IsAnalysis=*/false, &*V.find(RefGUID))); + } Elem.SummaryList.push_back(llvm::make_unique<FunctionSummary>( GlobalValueSummary::GVFlags( static_cast<GlobalValue::LinkageTypes>(FSum.Linkage), FSum.NotEligibleToImport, FSum.Live, FSum.IsLocal), - 0, FunctionSummary::FFlags{}, ArrayRef<ValueInfo>{}, + 0, FunctionSummary::FFlags{}, Refs, ArrayRef<FunctionSummary::EdgeTy>{}, std::move(FSum.TypeTests), std::move(FSum.TypeTestAssumeVCalls), std::move(FSum.TypeCheckedLoadVCalls), @@ -225,15 +237,20 @@ template <> struct CustomMappingTraits<GlobalValueSummaryMapTy> { for (auto &P : V) { std::vector<FunctionSummaryYaml> FSums; for (auto &Sum : P.second.SummaryList) { - if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get())) + if (auto *FSum = dyn_cast<FunctionSummary>(Sum.get())) { + std::vector<uint64_t> Refs; + for (auto &VI : FSum->refs()) + Refs.push_back(VI.getGUID()); FSums.push_back(FunctionSummaryYaml{ FSum->flags().Linkage, static_cast<bool>(FSum->flags().NotEligibleToImport), static_cast<bool>(FSum->flags().Live), - static_cast<bool>(FSum->flags().DSOLocal), FSum->type_tests(), - FSum->type_test_assume_vcalls(), FSum->type_checked_load_vcalls(), + static_cast<bool>(FSum->flags().DSOLocal), Refs, + FSum->type_tests(), FSum->type_test_assume_vcalls(), + FSum->type_checked_load_vcalls(), FSum->type_test_assume_const_vcalls(), FSum->type_checked_load_const_vcalls()}); + } } if (!FSums.empty()) io.mapRequired(llvm::utostr(P.first).c_str(), FSums); diff --git a/contrib/llvm/include/llvm/IR/Operator.h b/contrib/llvm/include/llvm/IR/Operator.h index 01746e4b6a29..939cec7f4aa4 100644 --- a/contrib/llvm/include/llvm/IR/Operator.h +++ b/contrib/llvm/include/llvm/IR/Operator.h @@ -207,17 +207,28 @@ public: bool isFast() const { return all(); } /// Flag setters - void setAllowReassoc() { Flags |= AllowReassoc; } - void setNoNaNs() { Flags |= NoNaNs; } - void setNoInfs() { Flags |= NoInfs; } - void setNoSignedZeros() { Flags |= NoSignedZeros; } - void setAllowReciprocal() { Flags |= AllowReciprocal; } - // TODO: Change the other set* functions to take a parameter? - void setAllowContract(bool B) { + void setAllowReassoc(bool B = true) { + Flags = (Flags & ~AllowReassoc) | B * AllowReassoc; + } + void setNoNaNs(bool B = true) { + Flags = (Flags & ~NoNaNs) | B * NoNaNs; + } + void setNoInfs(bool B = true) { + Flags = (Flags & ~NoInfs) | B * NoInfs; + } + void setNoSignedZeros(bool B = true) { + Flags = (Flags & ~NoSignedZeros) | B * NoSignedZeros; + } + void setAllowReciprocal(bool B = true) { + Flags = (Flags & ~AllowReciprocal) | B * AllowReciprocal; + } + void setAllowContract(bool B = true) { Flags = (Flags & ~AllowContract) | B * AllowContract; } - void setApproxFunc() { Flags |= ApproxFunc; } - void setFast() { set(); } + void setApproxFunc(bool B = true) { + Flags = (Flags & ~ApproxFunc) | B * ApproxFunc; + } + void setFast(bool B = true) { B ? set() : clear(); } void operator&=(const FastMathFlags &OtherFlags) { Flags &= OtherFlags.Flags; @@ -507,7 +518,7 @@ public: }); } - /// \brief Accumulate the constant address offset of this GEP if possible. + /// Accumulate the constant address offset of this GEP if possible. /// /// This routine accepts an APInt into which it will accumulate the constant /// offset of this GEP if the GEP is in fact constant. If the GEP is not diff --git a/contrib/llvm/include/llvm/IR/OptBisect.h b/contrib/llvm/include/llvm/IR/OptBisect.h index 09e67aa79246..aa24c94c0130 100644 --- a/contrib/llvm/include/llvm/IR/OptBisect.h +++ b/contrib/llvm/include/llvm/IR/OptBisect.h @@ -20,14 +20,34 @@ namespace llvm { class Pass; +class Module; +class Function; +class BasicBlock; +class Region; +class Loop; +class CallGraphSCC; + +/// Extensions to this class implement mechanisms to disable passes and +/// individual optimizations at compile time. +class OptPassGate { +public: + virtual ~OptPassGate() = default; + + virtual bool shouldRunPass(const Pass *P, const Module &U) { return true; } + virtual bool shouldRunPass(const Pass *P, const Function &U) {return true; } + virtual bool shouldRunPass(const Pass *P, const BasicBlock &U) { return true; } + virtual bool shouldRunPass(const Pass *P, const Region &U) { return true; } + virtual bool shouldRunPass(const Pass *P, const Loop &U) { return true; } + virtual bool shouldRunPass(const Pass *P, const CallGraphSCC &U) { return true; } +}; /// This class implements a mechanism to disable passes and individual /// optimizations at compile time based on a command line option /// (-opt-bisect-limit) in order to perform a bisecting search for /// optimization-related problems. -class OptBisect { +class OptBisect : public OptPassGate { public: - /// \brief Default constructor, initializes the OptBisect state based on the + /// Default constructor, initializes the OptBisect state based on the /// -opt-bisect-limit command line argument. /// /// By default, bisection is disabled. @@ -36,20 +56,26 @@ public: /// through LLVMContext. OptBisect(); + virtual ~OptBisect() = default; + /// Checks the bisect limit to determine if the specified pass should run. /// - /// This function will immediate return true if bisection is disabled. If the - /// bisect limit is set to -1, the function will print a message describing + /// These functions immediately return true if bisection is disabled. If the + /// bisect limit is set to -1, the functions print a message describing /// the pass and the bisect number assigned to it and return true. Otherwise, - /// the function will print a message with the bisect number assigned to the + /// the functions print a message with the bisect number assigned to the /// pass and indicating whether or not the pass will be run and return true if - /// the bisect limit has not yet been exceded or false if it has. + /// the bisect limit has not yet been exceeded or false if it has. /// - /// Most passes should not call this routine directly. Instead, it is called - /// through a helper routine provided by the pass base class. For instance, - /// function passes should call FunctionPass::skipFunction(). - template <class UnitT> - bool shouldRunPass(const Pass *P, const UnitT &U); + /// Most passes should not call these routines directly. Instead, they are + /// called through helper routines provided by the pass base classes. For + /// instance, function passes should call FunctionPass::skipFunction(). + bool shouldRunPass(const Pass *P, const Module &U) override; + bool shouldRunPass(const Pass *P, const Function &U) override; + bool shouldRunPass(const Pass *P, const BasicBlock &U) override; + bool shouldRunPass(const Pass *P, const Region &U) override; + bool shouldRunPass(const Pass *P, const Loop &U) override; + bool shouldRunPass(const Pass *P, const CallGraphSCC &U) override; private: bool checkPass(const StringRef PassName, const StringRef TargetDesc); diff --git a/contrib/llvm/include/llvm/IR/PassManager.h b/contrib/llvm/include/llvm/IR/PassManager.h index 4f838a719512..a5d4aaf71c0e 100644 --- a/contrib/llvm/include/llvm/IR/PassManager.h +++ b/contrib/llvm/include/llvm/IR/PassManager.h @@ -152,17 +152,17 @@ private: /// ``` class PreservedAnalyses { public: - /// \brief Convenience factory function for the empty preserved set. + /// Convenience factory function for the empty preserved set. static PreservedAnalyses none() { return PreservedAnalyses(); } - /// \brief Construct a special preserved set that preserves all passes. + /// Construct a special preserved set that preserves all passes. static PreservedAnalyses all() { PreservedAnalyses PA; PA.PreservedIDs.insert(&AllAnalysesKey); return PA; } - /// \brief Construct a preserved analyses object with a single preserved set. + /// Construct a preserved analyses object with a single preserved set. template <typename AnalysisSetT> static PreservedAnalyses allInSet() { PreservedAnalyses PA; @@ -173,7 +173,7 @@ public: /// Mark an analysis as preserved. template <typename AnalysisT> void preserve() { preserve(AnalysisT::ID()); } - /// \brief Given an analysis's ID, mark the analysis as preserved, adding it + /// Given an analysis's ID, mark the analysis as preserved, adding it /// to the set. void preserve(AnalysisKey *ID) { // Clear this ID from the explicit not-preserved set if present. @@ -218,7 +218,7 @@ public: NotPreservedAnalysisIDs.insert(ID); } - /// \brief Intersect this set with another in place. + /// 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. @@ -240,7 +240,7 @@ public: PreservedIDs.erase(ID); } - /// \brief Intersect this set with a temporary other set in place. + /// 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. @@ -402,7 +402,7 @@ struct AnalysisInfoMixin : PassInfoMixin<DerivedT> { } }; -/// \brief Manages a sequence of passes over a particular unit of IR. +/// Manages a sequence of passes over a particular unit of IR. /// /// A pass manager contains a sequence of passes to run over a particular unit /// of IR (e.g. Functions, Modules). It is itself a valid pass over that unit of @@ -420,7 +420,7 @@ template <typename IRUnitT, class PassManager : public PassInfoMixin< PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> { public: - /// \brief Construct a pass manager. + /// Construct a pass manager. /// /// If \p DebugLogging is true, we'll log our progress to llvm::dbgs(). explicit PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} @@ -439,7 +439,7 @@ public: return *this; } - /// \brief Run all of the passes in this manager over the given unit of IR. + /// Run all of the passes in this manager over the given unit of IR. /// ExtraArgs are passed to each pass. PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) { @@ -496,21 +496,21 @@ private: std::vector<std::unique_ptr<PassConceptT>> Passes; - /// \brief Flag indicating whether we should do debug logging. + /// Flag indicating whether we should do debug logging. bool DebugLogging; }; extern template class PassManager<Module>; -/// \brief Convenience typedef for a pass manager over modules. +/// Convenience typedef for a pass manager over modules. using ModulePassManager = PassManager<Module>; extern template class PassManager<Function>; -/// \brief Convenience typedef for a pass manager over functions. +/// Convenience typedef for a pass manager over functions. using FunctionPassManager = PassManager<Function>; -/// \brief A container for analyses that lazily runs them and caches their +/// A container for analyses that lazily runs them and caches their /// results. /// /// This class can manage analyses for any IR unit where the address of the IR @@ -527,7 +527,7 @@ private: detail::AnalysisPassConcept<IRUnitT, PreservedAnalyses, Invalidator, ExtraArgTs...>; - /// \brief List of analysis pass IDs and associated concept pointers. + /// List of analysis pass IDs and associated concept pointers. /// /// Requires iterators to be valid across appending new entries and arbitrary /// erases. Provides the analysis ID to enable finding iterators to a given @@ -536,10 +536,10 @@ private: using AnalysisResultListT = std::list<std::pair<AnalysisKey *, std::unique_ptr<ResultConceptT>>>; - /// \brief Map type from IRUnitT pointer to our custom list type. + /// Map type from IRUnitT pointer to our custom list type. using AnalysisResultListMapT = DenseMap<IRUnitT *, AnalysisResultListT>; - /// \brief Map type from a pair of analysis ID and IRUnitT pointer to an + /// Map type from a pair of analysis ID and IRUnitT pointer to an /// iterator into a particular result list (which is where the actual analysis /// result is stored). using AnalysisResultMapT = @@ -634,14 +634,14 @@ public: const AnalysisResultMapT &Results; }; - /// \brief Construct an empty analysis manager. + /// Construct an empty analysis manager. /// /// If \p DebugLogging is true, we'll log our progress to llvm::dbgs(). AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} AnalysisManager(AnalysisManager &&) = default; AnalysisManager &operator=(AnalysisManager &&) = default; - /// \brief Returns true if the analysis manager has an empty results cache. + /// Returns true if the analysis manager has an empty results cache. bool empty() const { assert(AnalysisResults.empty() == AnalysisResultLists.empty() && "The storage and index of analysis results disagree on how many " @@ -649,7 +649,7 @@ public: return AnalysisResults.empty(); } - /// \brief Clear any cached analysis results for a single unit of IR. + /// Clear any cached analysis results for a single unit of IR. /// /// This doesn't invalidate, but instead simply deletes, the relevant results. /// It is useful when the IR is being removed and we want to clear out all the @@ -669,7 +669,7 @@ public: AnalysisResultLists.erase(ResultsListI); } - /// \brief Clear all analysis results cached by this AnalysisManager. + /// Clear all analysis results cached by this AnalysisManager. /// /// Like \c clear(IRUnitT&), this doesn't invalidate the results; it simply /// deletes them. This lets you clean up the AnalysisManager when the set of @@ -680,7 +680,7 @@ public: AnalysisResultLists.clear(); } - /// \brief Get the result of an analysis pass for a given IR unit. + /// Get the result of an analysis pass for a given IR unit. /// /// Runs the analysis if a cached result is not available. template <typename PassT> @@ -697,7 +697,7 @@ public: return static_cast<ResultModelT &>(ResultConcept).Result; } - /// \brief Get the cached result of an analysis pass for a given IR unit. + /// Get the cached result of an analysis pass for a given IR unit. /// /// This method never runs the analysis. /// @@ -718,7 +718,7 @@ public: return &static_cast<ResultModelT *>(ResultConcept)->Result; } - /// \brief Register an analysis pass with the manager. + /// Register an analysis pass with the manager. /// /// The parameter is a callable whose result is an analysis pass. This allows /// passing in a lambda to construct the analysis. @@ -752,7 +752,7 @@ public: return true; } - /// \brief Invalidate a specific analysis pass for an IR module. + /// Invalidate a specific analysis pass for an IR module. /// /// Note that the analysis result can disregard invalidation, if it determines /// it is in fact still valid. @@ -762,7 +762,7 @@ public: invalidateImpl(PassT::ID(), IR); } - /// \brief Invalidate cached analyses for an IR unit. + /// Invalidate cached analyses for an IR unit. /// /// Walk through all of the analyses pertaining to this unit of IR and /// invalidate them, unless they are preserved by the PreservedAnalyses set. @@ -829,7 +829,7 @@ public: } private: - /// \brief Look up a registered analysis pass. + /// Look up a registered analysis pass. PassConceptT &lookUpPass(AnalysisKey *ID) { typename AnalysisPassMapT::iterator PI = AnalysisPasses.find(ID); assert(PI != AnalysisPasses.end() && @@ -837,7 +837,7 @@ private: return *PI->second; } - /// \brief Look up a registered analysis pass. + /// Look up a registered analysis pass. const PassConceptT &lookUpPass(AnalysisKey *ID) const { typename AnalysisPassMapT::const_iterator PI = AnalysisPasses.find(ID); assert(PI != AnalysisPasses.end() && @@ -845,7 +845,7 @@ private: return *PI->second; } - /// \brief Get an analysis result, running the pass if necessary. + /// Get an analysis result, running the pass if necessary. ResultConceptT &getResultImpl(AnalysisKey *ID, IRUnitT &IR, ExtraArgTs... ExtraArgs) { typename AnalysisResultMapT::iterator RI; @@ -874,14 +874,14 @@ private: return *RI->second->second; } - /// \brief Get a cached analysis result or return null. + /// Get a cached analysis result or return null. ResultConceptT *getCachedResultImpl(AnalysisKey *ID, IRUnitT &IR) const { typename AnalysisResultMapT::const_iterator RI = AnalysisResults.find({ID, &IR}); return RI == AnalysisResults.end() ? nullptr : &*RI->second->second; } - /// \brief Invalidate a function pass result. + /// Invalidate a function pass result. void invalidateImpl(AnalysisKey *ID, IRUnitT &IR) { typename AnalysisResultMapT::iterator RI = AnalysisResults.find({ID, &IR}); @@ -895,38 +895,38 @@ private: AnalysisResults.erase(RI); } - /// \brief Map type from module analysis pass ID to pass concept pointer. + /// Map type from module analysis pass ID to pass concept pointer. using AnalysisPassMapT = DenseMap<AnalysisKey *, std::unique_ptr<PassConceptT>>; - /// \brief Collection of module analysis passes, indexed by ID. + /// Collection of module analysis passes, indexed by ID. AnalysisPassMapT AnalysisPasses; - /// \brief Map from function to a list of function analysis results. + /// Map from function to a list of function analysis results. /// /// Provides linear time removal of all analysis results for a function and /// the ultimate storage for a particular cached analysis result. AnalysisResultListMapT AnalysisResultLists; - /// \brief Map from an analysis ID and function to a particular cached + /// Map from an analysis ID and function to a particular cached /// analysis result. AnalysisResultMapT AnalysisResults; - /// \brief Indicates whether we log to \c llvm::dbgs(). + /// Indicates whether we log to \c llvm::dbgs(). bool DebugLogging; }; extern template class AnalysisManager<Module>; -/// \brief Convenience typedef for the Module analysis manager. +/// Convenience typedef for the Module analysis manager. using ModuleAnalysisManager = AnalysisManager<Module>; extern template class AnalysisManager<Function>; -/// \brief Convenience typedef for the Function analysis manager. +/// Convenience typedef for the Function analysis manager. using FunctionAnalysisManager = AnalysisManager<Function>; -/// \brief An analysis over an "outer" IR unit that provides access to an +/// An analysis over an "outer" IR unit that provides access to an /// analysis manager over an "inner" IR unit. The inner unit must be contained /// in the outer unit. /// @@ -977,10 +977,10 @@ public: return *this; } - /// \brief Accessor for the analysis manager. + /// Accessor for the analysis manager. AnalysisManagerT &getManager() { return *InnerAM; } - /// \brief Handler for invalidation of the outer IR unit, \c IRUnitT. + /// Handler for invalidation of the outer IR unit, \c IRUnitT. /// /// If the proxy analysis itself is not preserved, we assume that the set of /// inner IR objects contained in IRUnit may have changed. In this case, @@ -1001,7 +1001,7 @@ public: explicit InnerAnalysisManagerProxy(AnalysisManagerT &InnerAM) : InnerAM(&InnerAM) {} - /// \brief Run the analysis pass and create our proxy result object. + /// 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 outer analysis cache so that we can proxy @@ -1040,7 +1040,7 @@ bool FunctionAnalysisManagerModuleProxy::Result::invalidate( extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager, Module>; -/// \brief An analysis over an "inner" IR unit that provides access to an +/// An analysis over an "inner" IR unit that provides access to an /// analysis manager over a "outer" IR unit. The inner unit must be contained /// in the outer unit. /// @@ -1063,7 +1063,7 @@ class OuterAnalysisManagerProxy : public AnalysisInfoMixin< OuterAnalysisManagerProxy<AnalysisManagerT, IRUnitT, ExtraArgTs...>> { public: - /// \brief Result proxy object for \c OuterAnalysisManagerProxy. + /// Result proxy object for \c OuterAnalysisManagerProxy. class Result { public: explicit Result(const AnalysisManagerT &AM) : AM(&AM) {} @@ -1130,7 +1130,7 @@ public: OuterAnalysisManagerProxy(const AnalysisManagerT &AM) : AM(&AM) {} - /// \brief Run the analysis pass and create our proxy result object. + /// Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c AM reference into the /// result. Result run(IRUnitT &, AnalysisManager<IRUnitT, ExtraArgTs...> &, @@ -1157,7 +1157,7 @@ extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager, using ModuleAnalysisManagerFunctionProxy = OuterAnalysisManagerProxy<ModuleAnalysisManager, Function>; -/// \brief Trivial adaptor that maps from a module to its functions. +/// Trivial adaptor that maps from a module to its functions. /// /// Designed to allow composition of a FunctionPass(Manager) and /// a ModulePassManager, by running the FunctionPass(Manager) over every @@ -1187,7 +1187,7 @@ public: explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass) : Pass(std::move(Pass)) {} - /// \brief Runs the function pass across every function in the module. + /// Runs the function pass across every function in the module. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM) { FunctionAnalysisManager &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); @@ -1223,7 +1223,7 @@ private: FunctionPassT Pass; }; -/// \brief A function to deduce a function pass type and wrap it in the +/// A function to deduce a function pass type and wrap it in the /// templated adaptor. template <typename FunctionPassT> ModuleToFunctionPassAdaptor<FunctionPassT> @@ -1231,7 +1231,7 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) { return ModuleToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)); } -/// \brief A utility pass template to force an analysis result to be available. +/// A utility pass template to force an analysis result to be available. /// /// If there are extra arguments at the pass's run level there may also be /// extra arguments to the analysis manager's \c getResult routine. We can't @@ -1246,7 +1246,7 @@ template <typename AnalysisT, typename IRUnitT, struct RequireAnalysisPass : PassInfoMixin<RequireAnalysisPass<AnalysisT, IRUnitT, AnalysisManagerT, ExtraArgTs...>> { - /// \brief Run this pass over some unit of IR. + /// Run this pass over some unit of IR. /// /// This pass can be run over any unit of IR and use any analysis manager /// provided they satisfy the basic API requirements. When this pass is @@ -1261,12 +1261,12 @@ struct RequireAnalysisPass } }; -/// \brief A no-op pass template which simply forces a specific analysis result +/// A no-op pass template which simply forces a specific analysis result /// to be invalidated. template <typename AnalysisT> struct InvalidateAnalysisPass : PassInfoMixin<InvalidateAnalysisPass<AnalysisT>> { - /// \brief Run this pass over some unit of IR. + /// Run this pass over some unit of IR. /// /// This pass can be run over any unit of IR and use any analysis manager, /// provided they satisfy the basic API requirements. When this pass is @@ -1280,12 +1280,12 @@ struct InvalidateAnalysisPass } }; -/// \brief A utility pass that does nothing, but preserves no analyses. +/// A utility pass that does nothing, but preserves no analyses. /// /// Because this preserves no analyses, any analysis passes queried after this /// pass runs will recompute fresh results. struct InvalidateAllAnalysesPass : PassInfoMixin<InvalidateAllAnalysesPass> { - /// \brief Run this pass over some unit of IR. + /// Run this pass over some unit of IR. template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs> PreservedAnalyses run(IRUnitT &, AnalysisManagerT &, ExtraArgTs &&...) { return PreservedAnalyses::none(); diff --git a/contrib/llvm/include/llvm/IR/PassManagerInternal.h b/contrib/llvm/include/llvm/IR/PassManagerInternal.h index 9195d4dfa428..16a3258b4121 100644 --- a/contrib/llvm/include/llvm/IR/PassManagerInternal.h +++ b/contrib/llvm/include/llvm/IR/PassManagerInternal.h @@ -29,17 +29,17 @@ template <typename IRUnitT> class AllAnalysesOn; template <typename IRUnitT, typename... ExtraArgTs> class AnalysisManager; class PreservedAnalyses; -/// \brief Implementation details of the pass manager interfaces. +/// Implementation details of the pass manager interfaces. namespace detail { -/// \brief Template for the abstract base class used to dispatch +/// Template for the abstract base class used to dispatch /// polymorphically over pass objects. template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs> struct PassConcept { // Boiler plate necessary for the container of derived classes. virtual ~PassConcept() = default; - /// \brief The polymorphic API which runs the pass over a given IR entity. + /// The polymorphic API which runs the pass over a given IR entity. /// /// Note that actual pass object can omit the analysis manager argument if /// desired. Also that the analysis manager may be null if there is no @@ -47,11 +47,11 @@ struct PassConcept { virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM, ExtraArgTs... ExtraArgs) = 0; - /// \brief Polymorphic method to access the name of a pass. + /// Polymorphic method to access the name of a pass. virtual StringRef name() = 0; }; -/// \brief A template wrapper used to implement the polymorphic API. +/// A template wrapper used to implement the polymorphic API. /// /// Can be instantiated for any object which provides a \c run method accepting /// an \c IRUnitT& and an \c AnalysisManager<IRUnit>&. It requires the pass to @@ -85,7 +85,7 @@ struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> { PassT Pass; }; -/// \brief Abstract concept of an analysis result. +/// Abstract concept of an analysis result. /// /// This concept is parameterized over the IR unit that this result pertains /// to. @@ -93,7 +93,7 @@ template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT> struct AnalysisResultConcept { virtual ~AnalysisResultConcept() = default; - /// \brief Method to try and mark a result as invalid. + /// 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. @@ -112,7 +112,7 @@ struct AnalysisResultConcept { InvalidatorT &Inv) = 0; }; -/// \brief SFINAE metafunction for computing whether \c ResultT provides an +/// SFINAE metafunction for computing whether \c ResultT provides an /// \c invalidate member function. template <typename IRUnitT, typename ResultT> class ResultHasInvalidateMethod { using EnabledType = char; @@ -148,7 +148,7 @@ public: enum { Value = sizeof(check<ResultT>(rank<2>())) == sizeof(EnabledType) }; }; -/// \brief Wrapper to model the analysis result concept. +/// 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 @@ -160,7 +160,7 @@ template <typename IRUnitT, typename PassT, typename ResultT, ResultHasInvalidateMethod<IRUnitT, ResultT>::Value> struct AnalysisResultModel; -/// \brief Specialization of \c AnalysisResultModel which provides the default +/// Specialization of \c AnalysisResultModel which provides the default /// invalidate functionality. template <typename IRUnitT, typename PassT, typename ResultT, typename PreservedAnalysesT, typename InvalidatorT> @@ -184,7 +184,7 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, return *this; } - /// \brief The model bases invalidation solely on being in the preserved set. + /// 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 @@ -199,7 +199,7 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, ResultT Result; }; -/// \brief Specialization of \c AnalysisResultModel which delegates invalidate +/// Specialization of \c AnalysisResultModel which delegates invalidate /// handling to \c ResultT. template <typename IRUnitT, typename PassT, typename ResultT, typename PreservedAnalysesT, typename InvalidatorT> @@ -223,7 +223,7 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, return *this; } - /// \brief The model delegates to the \c ResultT method. + /// The model delegates to the \c ResultT method. bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA, InvalidatorT &Inv) override { return Result.invalidate(IR, PA, Inv); @@ -232,7 +232,7 @@ struct AnalysisResultModel<IRUnitT, PassT, ResultT, PreservedAnalysesT, ResultT Result; }; -/// \brief Abstract concept of an analysis pass. +/// Abstract concept of an analysis pass. /// /// This concept is parameterized over the IR unit that it can run over and /// produce an analysis result. @@ -241,7 +241,7 @@ template <typename IRUnitT, typename PreservedAnalysesT, typename InvalidatorT, struct AnalysisPassConcept { virtual ~AnalysisPassConcept() = default; - /// \brief Method to run this analysis over a unit of IR. + /// 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< @@ -249,11 +249,11 @@ struct AnalysisPassConcept { run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM, ExtraArgTs... ExtraArgs) = 0; - /// \brief Polymorphic method to access the name of a pass. + /// Polymorphic method to access the name of a pass. virtual StringRef name() = 0; }; -/// \brief Wrapper to model the analysis pass concept. +/// Wrapper to model the analysis pass concept. /// /// Can wrap any type which implements a suitable \c run method. The method /// must accept an \c IRUnitT& and an \c AnalysisManager<IRUnitT>& as arguments @@ -283,7 +283,7 @@ struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT, AnalysisResultModel<IRUnitT, PassT, typename PassT::Result, PreservedAnalysesT, InvalidatorT>; - /// \brief The model delegates to the \c PassT::run method. + /// The model delegates to the \c PassT::run method. /// /// The return is wrapped in an \c AnalysisResultModel. std::unique_ptr< @@ -293,7 +293,7 @@ struct AnalysisPassModel : AnalysisPassConcept<IRUnitT, PreservedAnalysesT, return llvm::make_unique<ResultModelT>(Pass.run(IR, AM, ExtraArgs...)); } - /// \brief The model delegates to a static \c PassT::name method. + /// The model delegates to a static \c PassT::name method. /// /// The returned string ref must point to constant immutable data! StringRef name() override { return PassT::name(); } diff --git a/contrib/llvm/include/llvm/IR/PatternMatch.h b/contrib/llvm/include/llvm/IR/PatternMatch.h index 245d72fbd16e..af0616cd8221 100644 --- a/contrib/llvm/include/llvm/IR/PatternMatch.h +++ b/contrib/llvm/include/llvm/IR/PatternMatch.h @@ -8,10 +8,10 @@ //===----------------------------------------------------------------------===// // // This file provides a simple and efficient mechanism for performing general -// tree-based pattern matches on the LLVM IR. The power of these routines is +// tree-based pattern matches on the LLVM IR. The power of these routines is // that it allows you to write concise patterns that are expressive and easy to -// understand. The other major advantage of this is that it allows you to -// trivially capture/bind elements in the pattern to variables. For example, +// understand. The other major advantage of this is that it allows you to +// trivially capture/bind elements in the pattern to variables. For example, // you can do something like this: // // Value *Exp = ... @@ -68,26 +68,26 @@ template <typename Class> struct class_match { template <typename ITy> bool match(ITy *V) { return isa<Class>(V); } }; -/// \brief Match an arbitrary value and ignore it. +/// Match an arbitrary value and ignore it. inline class_match<Value> m_Value() { return class_match<Value>(); } -/// \brief Match an arbitrary binary operation and ignore it. +/// Match an arbitrary binary operation and ignore it. inline class_match<BinaryOperator> m_BinOp() { return class_match<BinaryOperator>(); } -/// \brief Matches any compare instruction and ignore it. +/// Matches any compare instruction and ignore it. inline class_match<CmpInst> m_Cmp() { return class_match<CmpInst>(); } -/// \brief Match an arbitrary ConstantInt and ignore it. +/// Match an arbitrary ConstantInt and ignore it. inline class_match<ConstantInt> m_ConstantInt() { return class_match<ConstantInt>(); } -/// \brief Match an arbitrary undef constant. +/// Match an arbitrary undef constant. inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); } -/// \brief Match an arbitrary Constant and ignore it. +/// Match an arbitrary Constant and ignore it. inline class_match<Constant> m_Constant() { return class_match<Constant>(); } /// Matching combinators @@ -132,89 +132,6 @@ inline match_combine_and<LTy, RTy> m_CombineAnd(const LTy &L, const RTy &R) { return match_combine_and<LTy, RTy>(L, R); } -struct match_zero { - template <typename ITy> bool match(ITy *V) { - if (const auto *C = dyn_cast<Constant>(V)) - return C->isNullValue(); - return false; - } -}; - -/// \brief Match an arbitrary zero/null constant. This includes -/// zero_initializer for vectors and ConstantPointerNull for pointers. -inline match_zero m_Zero() { return match_zero(); } - -struct match_neg_zero { - template <typename ITy> bool match(ITy *V) { - if (const auto *C = dyn_cast<Constant>(V)) - return C->isNegativeZeroValue(); - return false; - } -}; - -/// \brief Match an arbitrary zero/null constant. This includes -/// zero_initializer for vectors and ConstantPointerNull for pointers. For -/// floating point constants, this will match negative zero but not positive -/// zero -inline match_neg_zero m_NegZero() { return match_neg_zero(); } - -struct match_any_zero { - template <typename ITy> bool match(ITy *V) { - if (const auto *C = dyn_cast<Constant>(V)) - return C->isZeroValue(); - return false; - } -}; - -/// \brief - Match an arbitrary zero/null constant. This includes -/// zero_initializer for vectors and ConstantPointerNull for pointers. For -/// floating point constants, this will match negative zero and positive zero -inline match_any_zero m_AnyZero() { return match_any_zero(); } - -struct match_nan { - template <typename ITy> bool match(ITy *V) { - if (const auto *C = dyn_cast<ConstantFP>(V)) - return C->isNaN(); - return false; - } -}; - -/// Match an arbitrary NaN constant. This includes quiet and signalling nans. -inline match_nan m_NaN() { return match_nan(); } - -struct match_one { - template <typename ITy> bool match(ITy *V) { - if (const auto *C = dyn_cast<Constant>(V)) - return C->isOneValue(); - return false; - } -}; - -/// \brief Match an integer 1 or a vector with all elements equal to 1. -inline match_one m_One() { return match_one(); } - -struct match_all_ones { - template <typename ITy> bool match(ITy *V) { - if (const auto *C = dyn_cast<Constant>(V)) - return C->isAllOnesValue(); - return false; - } -}; - -/// \brief Match an integer or vector with all bits set to true. -inline match_all_ones m_AllOnes() { return match_all_ones(); } - -struct match_sign_mask { - template <typename ITy> bool match(ITy *V) { - if (const auto *C = dyn_cast<Constant>(V)) - return C->isMinSignedValue(); - return false; - } -}; - -/// \brief Match an integer or vector with only the sign bit(s) set. -inline match_sign_mask m_SignMask() { return match_sign_mask(); } - struct apint_match { const APInt *&Res; @@ -255,11 +172,11 @@ struct apfloat_match { } }; -/// \brief Match a ConstantInt or splatted ConstantVector, binding the +/// Match a ConstantInt or splatted ConstantVector, binding the /// specified pointer to the contained APInt. inline apint_match m_APInt(const APInt *&Res) { return Res; } -/// \brief Match a ConstantFP or splatted ConstantVector, binding the +/// Match a ConstantFP or splatted ConstantVector, binding the /// specified pointer to the contained APFloat. inline apfloat_match m_APFloat(const APFloat *&Res) { return Res; } @@ -278,26 +195,44 @@ template <int64_t Val> struct constantint_match { } }; -/// \brief Match a ConstantInt with a specific value. +/// Match a ConstantInt with a specific value. template <int64_t Val> inline constantint_match<Val> m_ConstantInt() { return constantint_match<Val>(); } -/// \brief This helper class is used to match scalar and vector constants that +/// This helper class is used to match scalar and vector integer constants that /// satisfy a specified predicate. +/// For vector constants, undefined elements are ignored. template <typename Predicate> struct cst_pred_ty : public Predicate { template <typename ITy> bool match(ITy *V) { if (const auto *CI = dyn_cast<ConstantInt>(V)) return this->isValue(CI->getValue()); - if (V->getType()->isVectorTy()) - if (const auto *C = dyn_cast<Constant>(V)) + if (V->getType()->isVectorTy()) { + if (const auto *C = dyn_cast<Constant>(V)) { if (const auto *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue())) return this->isValue(CI->getValue()); + + // Non-splat vector constant: check each element for a match. + unsigned NumElts = V->getType()->getVectorNumElements(); + assert(NumElts != 0 && "Constant vector with no elements?"); + for (unsigned i = 0; i != NumElts; ++i) { + Constant *Elt = C->getAggregateElement(i); + if (!Elt) + return false; + if (isa<UndefValue>(Elt)) + continue; + auto *CI = dyn_cast<ConstantInt>(Elt); + if (!CI || !this->isValue(CI->getValue())) + return false; + } + return true; + } + } return false; } }; -/// \brief This helper class is used to match scalar and vector constants that +/// This helper class is used to match scalar and vector constants that /// satisfy a specified predicate, and bind them to an APInt. template <typename Predicate> struct api_pred_ty : public Predicate { const APInt *&Res; @@ -322,20 +257,202 @@ template <typename Predicate> struct api_pred_ty : public Predicate { } }; -struct is_power2 { - bool isValue(const APInt &C) { return C.isPowerOf2(); } +/// This helper class is used to match scalar and vector floating-point +/// constants that satisfy a specified predicate. +/// For vector constants, undefined elements are ignored. +template <typename Predicate> struct cstfp_pred_ty : public Predicate { + template <typename ITy> bool match(ITy *V) { + if (const auto *CF = dyn_cast<ConstantFP>(V)) + return this->isValue(CF->getValueAPF()); + if (V->getType()->isVectorTy()) { + if (const auto *C = dyn_cast<Constant>(V)) { + if (const auto *CF = dyn_cast_or_null<ConstantFP>(C->getSplatValue())) + return this->isValue(CF->getValueAPF()); + + // Non-splat vector constant: check each element for a match. + unsigned NumElts = V->getType()->getVectorNumElements(); + assert(NumElts != 0 && "Constant vector with no elements?"); + for (unsigned i = 0; i != NumElts; ++i) { + Constant *Elt = C->getAggregateElement(i); + if (!Elt) + return false; + if (isa<UndefValue>(Elt)) + continue; + auto *CF = dyn_cast<ConstantFP>(Elt); + if (!CF || !this->isValue(CF->getValueAPF())) + return false; + } + return true; + } + } + return false; + } }; -/// \brief Match an integer or vector power of 2. -inline cst_pred_ty<is_power2> m_Power2() { return cst_pred_ty<is_power2>(); } -inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { return V; } +/////////////////////////////////////////////////////////////////////////////// +// +// Encapsulate constant value queries for use in templated predicate matchers. +// This allows checking if constants match using compound predicates and works +// with vector constants, possibly with relaxed constraints. For example, ignore +// undef values. +// +/////////////////////////////////////////////////////////////////////////////// + +struct is_all_ones { + bool isValue(const APInt &C) { return C.isAllOnesValue(); } +}; +/// Match an integer or vector with all bits set. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty<is_all_ones> m_AllOnes() { + return cst_pred_ty<is_all_ones>(); +} struct is_maxsignedvalue { bool isValue(const APInt &C) { return C.isMaxSignedValue(); } }; +/// Match an integer or vector with values having all bits except for the high +/// bit set (0x7f...). +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty<is_maxsignedvalue> m_MaxSignedValue() { + return cst_pred_ty<is_maxsignedvalue>(); +} +inline api_pred_ty<is_maxsignedvalue> m_MaxSignedValue(const APInt *&V) { + return V; +} -inline cst_pred_ty<is_maxsignedvalue> m_MaxSignedValue() { return cst_pred_ty<is_maxsignedvalue>(); } -inline api_pred_ty<is_maxsignedvalue> m_MaxSignedValue(const APInt *&V) { return V; } +struct is_negative { + bool isValue(const APInt &C) { return C.isNegative(); } +}; +/// Match an integer or vector of negative values. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty<is_negative> m_Negative() { + return cst_pred_ty<is_negative>(); +} +inline api_pred_ty<is_negative> m_Negative(const APInt *&V) { + return V; +} + +struct is_nonnegative { + bool isValue(const APInt &C) { return C.isNonNegative(); } +}; +/// Match an integer or vector of nonnegative values. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty<is_nonnegative> m_NonNegative() { + return cst_pred_ty<is_nonnegative>(); +} +inline api_pred_ty<is_nonnegative> m_NonNegative(const APInt *&V) { + return V; +} + +struct is_one { + bool isValue(const APInt &C) { return C.isOneValue(); } +}; +/// Match an integer 1 or a vector with all elements equal to 1. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty<is_one> m_One() { + return cst_pred_ty<is_one>(); +} + +struct is_zero_int { + bool isValue(const APInt &C) { return C.isNullValue(); } +}; +/// Match an integer 0 or a vector with all elements equal to 0. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty<is_zero_int> m_ZeroInt() { + return cst_pred_ty<is_zero_int>(); +} + +struct is_zero { + template <typename ITy> bool match(ITy *V) { + auto *C = dyn_cast<Constant>(V); + return C && (C->isNullValue() || cst_pred_ty<is_zero_int>().match(C)); + } +}; +/// Match any null constant or a vector with all elements equal to 0. +/// For vectors, this includes constants with undefined elements. +inline is_zero m_Zero() { + return is_zero(); +} + +struct is_power2 { + bool isValue(const APInt &C) { return C.isPowerOf2(); } +}; +/// Match an integer or vector power-of-2. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty<is_power2> m_Power2() { + return cst_pred_ty<is_power2>(); +} +inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { + return V; +} + +struct is_power2_or_zero { + bool isValue(const APInt &C) { return !C || C.isPowerOf2(); } +}; +/// Match an integer or vector of 0 or power-of-2 values. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty<is_power2_or_zero> m_Power2OrZero() { + return cst_pred_ty<is_power2_or_zero>(); +} +inline api_pred_ty<is_power2_or_zero> m_Power2OrZero(const APInt *&V) { + return V; +} + +struct is_sign_mask { + bool isValue(const APInt &C) { return C.isSignMask(); } +}; +/// Match an integer or vector with only the sign bit(s) set. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty<is_sign_mask> m_SignMask() { + return cst_pred_ty<is_sign_mask>(); +} + +struct is_lowbit_mask { + bool isValue(const APInt &C) { return C.isMask(); } +}; +/// Match an integer or vector with only the low bit(s) set. +/// For vectors, this includes constants with undefined elements. +inline cst_pred_ty<is_lowbit_mask> m_LowBitMask() { + return cst_pred_ty<is_lowbit_mask>(); +} + +struct is_nan { + bool isValue(const APFloat &C) { return C.isNaN(); } +}; +/// Match an arbitrary NaN constant. This includes quiet and signalling nans. +/// For vectors, this includes constants with undefined elements. +inline cstfp_pred_ty<is_nan> m_NaN() { + return cstfp_pred_ty<is_nan>(); +} + +struct is_any_zero_fp { + bool isValue(const APFloat &C) { return C.isZero(); } +}; +/// Match a floating-point negative zero or positive zero. +/// For vectors, this includes constants with undefined elements. +inline cstfp_pred_ty<is_any_zero_fp> m_AnyZeroFP() { + return cstfp_pred_ty<is_any_zero_fp>(); +} + +struct is_pos_zero_fp { + bool isValue(const APFloat &C) { return C.isPosZero(); } +}; +/// Match a floating-point positive zero. +/// For vectors, this includes constants with undefined elements. +inline cstfp_pred_ty<is_pos_zero_fp> m_PosZeroFP() { + return cstfp_pred_ty<is_pos_zero_fp>(); +} + +struct is_neg_zero_fp { + bool isValue(const APFloat &C) { return C.isNegZero(); } +}; +/// Match a floating-point negative zero. +/// For vectors, this includes constants with undefined elements. +inline cstfp_pred_ty<is_neg_zero_fp> m_NegZeroFP() { + return cstfp_pred_ty<is_neg_zero_fp>(); +} + +/////////////////////////////////////////////////////////////////////////////// template <typename Class> struct bind_ty { Class *&VR; @@ -351,25 +468,25 @@ template <typename Class> struct bind_ty { } }; -/// \brief Match a value, capturing it if we match. +/// Match a value, capturing it if we match. inline bind_ty<Value> m_Value(Value *&V) { return V; } inline bind_ty<const Value> m_Value(const Value *&V) { return V; } -/// \brief Match an instruction, capturing it if we match. +/// Match an instruction, capturing it if we match. inline bind_ty<Instruction> m_Instruction(Instruction *&I) { return I; } -/// \brief Match a binary operator, capturing it if we match. +/// Match a binary operator, capturing it if we match. inline bind_ty<BinaryOperator> m_BinOp(BinaryOperator *&I) { return I; } -/// \brief Match a ConstantInt, capturing the value if we match. +/// Match a ConstantInt, capturing the value if we match. inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; } -/// \brief Match a Constant, capturing the value if we match. +/// Match a Constant, capturing the value if we match. inline bind_ty<Constant> m_Constant(Constant *&C) { return C; } -/// \brief Match a ConstantFP, capturing the value if we match. +/// Match a ConstantFP, capturing the value if we match. inline bind_ty<ConstantFP> m_ConstantFP(ConstantFP *&C) { return C; } -/// \brief Match a specified Value*. +/// Match a specified Value*. struct specificval_ty { const Value *Val; @@ -378,10 +495,26 @@ struct specificval_ty { template <typename ITy> bool match(ITy *V) { return V == Val; } }; -/// \brief Match if we have a specific specified value. +/// Match if we have a specific specified value. inline specificval_ty m_Specific(const Value *V) { return V; } -/// \brief Match a specified floating point value or vector of all elements of +/// Stores a reference to the Value *, not the Value * itself, +/// thus can be used in commutative matchers. +template <typename Class> struct deferredval_ty { + Class *const &Val; + + deferredval_ty(Class *const &V) : Val(V) {} + + template <typename ITy> bool match(ITy *const V) { return V == Val; } +}; + +/// A commutative-friendly version of m_Specific(). +inline deferredval_ty<Value> m_Deferred(Value *const &V) { return V; } +inline deferredval_ty<const Value> m_Deferred(const Value *const &V) { + return V; +} + +/// Match a specified floating point value or vector of all elements of /// that value. struct specific_fpval { double Val; @@ -399,11 +532,11 @@ struct specific_fpval { } }; -/// \brief Match a specific floating point value or vector with all elements +/// Match a specific floating point value or vector with all elements /// equal to the value. inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } -/// \brief Match a float 1.0 or vector with all elements equal to 1.0. +/// Match a float 1.0 or vector with all elements equal to 1.0. inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } struct bind_const_intval_ty { @@ -421,7 +554,7 @@ struct bind_const_intval_ty { } }; -/// \brief Match a specified integer value or vector of all elements of that +/// Match a specified integer value or vector of all elements of that // value. struct specific_intval { uint64_t Val; @@ -438,11 +571,11 @@ struct specific_intval { } }; -/// \brief Match a specific integer value or vector with all elements equal to +/// Match a specific integer value or vector with all elements equal to /// the value. inline specific_intval m_SpecificInt(uint64_t V) { return specific_intval(V); } -/// \brief Match a ConstantInt and bind to its value. This does not match +/// Match a ConstantInt and bind to its value. This does not match /// ConstantInts wider than 64-bits. inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; } @@ -454,13 +587,15 @@ struct AnyBinaryOp_match { LHS_t L; RHS_t R; + // The evaluation order is always stable, regardless of Commutability. + // The LHS is always matched first. AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} template <typename OpTy> bool match(OpTy *V) { if (auto *I = dyn_cast<BinaryOperator>(V)) return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || - (Commutable && R.match(I->getOperand(0)) && - L.match(I->getOperand(1))); + (Commutable && L.match(I->getOperand(1)) && + R.match(I->getOperand(0))); return false; } }; @@ -480,20 +615,22 @@ struct BinaryOp_match { LHS_t L; RHS_t R; + // The evaluation order is always stable, regardless of Commutability. + // The LHS is always matched first. BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} template <typename OpTy> bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opcode) { auto *I = cast<BinaryOperator>(V); return (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || - (Commutable && R.match(I->getOperand(0)) && - L.match(I->getOperand(1))); + (Commutable && L.match(I->getOperand(1)) && + R.match(I->getOperand(0))); } if (auto *CE = dyn_cast<ConstantExpr>(V)) return CE->getOpcode() == Opcode && ((L.match(CE->getOperand(0)) && R.match(CE->getOperand(1))) || - (Commutable && R.match(CE->getOperand(0)) && - L.match(CE->getOperand(1)))); + (Commutable && L.match(CE->getOperand(1)) && + R.match(CE->getOperand(0)))); return false; } }; @@ -522,6 +659,13 @@ inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L, return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R); } +/// Match 'fneg X' as 'fsub -0.0, X'. +template <typename RHS> +inline BinaryOp_match<cstfp_pred_ty<is_neg_zero_fp>, RHS, Instruction::FSub> +m_FNeg(const RHS &X) { + return m_FSub(m_NegZeroFP(), X); +} + template <typename LHS, typename RHS> inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L, const RHS &R) { @@ -746,35 +890,35 @@ struct is_idiv_op { } }; -/// \brief Matches shift operations. +/// Matches shift operations. template <typename LHS, typename RHS> inline BinOpPred_match<LHS, RHS, is_shift_op> m_Shift(const LHS &L, const RHS &R) { return BinOpPred_match<LHS, RHS, is_shift_op>(L, R); } -/// \brief Matches logical shift operations. +/// Matches logical shift operations. template <typename LHS, typename RHS> inline BinOpPred_match<LHS, RHS, is_right_shift_op> m_Shr(const LHS &L, const RHS &R) { return BinOpPred_match<LHS, RHS, is_right_shift_op>(L, R); } -/// \brief Matches logical shift operations. +/// Matches logical shift operations. template <typename LHS, typename RHS> inline BinOpPred_match<LHS, RHS, is_logical_shift_op> m_LogicalShift(const LHS &L, const RHS &R) { return BinOpPred_match<LHS, RHS, is_logical_shift_op>(L, R); } -/// \brief Matches bitwise logic operations. +/// Matches bitwise logic operations. template <typename LHS, typename RHS> inline BinOpPred_match<LHS, RHS, is_bitwiselogic_op> m_BitwiseLogic(const LHS &L, const RHS &R) { return BinOpPred_match<LHS, RHS, is_bitwiselogic_op>(L, R); } -/// \brief Matches integer division operations. +/// Matches integer division operations. template <typename LHS, typename RHS> inline BinOpPred_match<LHS, RHS, is_idiv_op> m_IDiv(const LHS &L, const RHS &R) { @@ -811,14 +955,16 @@ struct CmpClass_match { LHS_t L; RHS_t R; + // The evaluation order is always stable, regardless of Commutability. + // The LHS is always matched first. CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) : Predicate(Pred), L(LHS), R(RHS) {} template <typename OpTy> bool match(OpTy *V) { if (auto *I = dyn_cast<Class>(V)) if ((L.match(I->getOperand(0)) && R.match(I->getOperand(1))) || - (Commutable && R.match(I->getOperand(0)) && - L.match(I->getOperand(1)))) { + (Commutable && L.match(I->getOperand(1)) && + R.match(I->getOperand(0)))) { Predicate = I->getPredicate(); return true; } @@ -871,7 +1017,7 @@ inline SelectClass_match<Cond, LHS, RHS> m_Select(const Cond &C, const LHS &L, return SelectClass_match<Cond, LHS, RHS>(C, L, R); } -/// \brief This matches a select of two constants, e.g.: +/// This matches a select of two constants, e.g.: /// m_SelectCst<-1, 0>(m_Value(V)) template <int64_t L, int64_t R, typename Cond> inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R>> @@ -880,6 +1026,84 @@ m_SelectCst(const Cond &C) { } //===----------------------------------------------------------------------===// +// Matchers for InsertElementInst classes +// + +template <typename Val_t, typename Elt_t, typename Idx_t> +struct InsertElementClass_match { + Val_t V; + Elt_t E; + Idx_t I; + + InsertElementClass_match(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx) + : V(Val), E(Elt), I(Idx) {} + + template <typename OpTy> bool match(OpTy *VV) { + if (auto *II = dyn_cast<InsertElementInst>(VV)) + return V.match(II->getOperand(0)) && E.match(II->getOperand(1)) && + I.match(II->getOperand(2)); + return false; + } +}; + +template <typename Val_t, typename Elt_t, typename Idx_t> +inline InsertElementClass_match<Val_t, Elt_t, Idx_t> +m_InsertElement(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx) { + return InsertElementClass_match<Val_t, Elt_t, Idx_t>(Val, Elt, Idx); +} + +//===----------------------------------------------------------------------===// +// Matchers for ExtractElementInst classes +// + +template <typename Val_t, typename Idx_t> struct ExtractElementClass_match { + Val_t V; + Idx_t I; + + ExtractElementClass_match(const Val_t &Val, const Idx_t &Idx) + : V(Val), I(Idx) {} + + template <typename OpTy> bool match(OpTy *VV) { + if (auto *II = dyn_cast<ExtractElementInst>(VV)) + return V.match(II->getOperand(0)) && I.match(II->getOperand(1)); + return false; + } +}; + +template <typename Val_t, typename Idx_t> +inline ExtractElementClass_match<Val_t, Idx_t> +m_ExtractElement(const Val_t &Val, const Idx_t &Idx) { + return ExtractElementClass_match<Val_t, Idx_t>(Val, Idx); +} + +//===----------------------------------------------------------------------===// +// Matchers for ShuffleVectorInst classes +// + +template <typename V1_t, typename V2_t, typename Mask_t> +struct ShuffleVectorClass_match { + V1_t V1; + V2_t V2; + Mask_t M; + + ShuffleVectorClass_match(const V1_t &v1, const V2_t &v2, const Mask_t &m) + : V1(v1), V2(v2), M(m) {} + + template <typename OpTy> bool match(OpTy *V) { + if (auto *SI = dyn_cast<ShuffleVectorInst>(V)) + return V1.match(SI->getOperand(0)) && V2.match(SI->getOperand(1)) && + M.match(SI->getOperand(2)); + return false; + } +}; + +template <typename V1_t, typename V2_t, typename Mask_t> +inline ShuffleVectorClass_match<V1_t, V2_t, Mask_t> +m_ShuffleVector(const V1_t &v1, const V2_t &v2, const Mask_t &m) { + return ShuffleVectorClass_match<V1_t, V2_t, Mask_t>(v1, v2, m); +} + +//===----------------------------------------------------------------------===// // Matchers for CastInst classes // @@ -895,31 +1119,31 @@ template <typename Op_t, unsigned Opcode> struct CastClass_match { } }; -/// \brief Matches BitCast. +/// Matches BitCast. template <typename OpTy> inline CastClass_match<OpTy, Instruction::BitCast> m_BitCast(const OpTy &Op) { return CastClass_match<OpTy, Instruction::BitCast>(Op); } -/// \brief Matches PtrToInt. +/// Matches PtrToInt. template <typename OpTy> inline CastClass_match<OpTy, Instruction::PtrToInt> m_PtrToInt(const OpTy &Op) { return CastClass_match<OpTy, Instruction::PtrToInt>(Op); } -/// \brief Matches Trunc. +/// Matches Trunc. template <typename OpTy> inline CastClass_match<OpTy, Instruction::Trunc> m_Trunc(const OpTy &Op) { return CastClass_match<OpTy, Instruction::Trunc>(Op); } -/// \brief Matches SExt. +/// Matches SExt. template <typename OpTy> inline CastClass_match<OpTy, Instruction::SExt> m_SExt(const OpTy &Op) { return CastClass_match<OpTy, Instruction::SExt>(Op); } -/// \brief Matches ZExt. +/// Matches ZExt. template <typename OpTy> inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) { return CastClass_match<OpTy, Instruction::ZExt>(Op); @@ -932,25 +1156,25 @@ m_ZExtOrSExt(const OpTy &Op) { return m_CombineOr(m_ZExt(Op), m_SExt(Op)); } -/// \brief Matches UIToFP. +/// Matches UIToFP. template <typename OpTy> inline CastClass_match<OpTy, Instruction::UIToFP> m_UIToFP(const OpTy &Op) { return CastClass_match<OpTy, Instruction::UIToFP>(Op); } -/// \brief Matches SIToFP. +/// Matches SIToFP. template <typename OpTy> inline CastClass_match<OpTy, Instruction::SIToFP> m_SIToFP(const OpTy &Op) { return CastClass_match<OpTy, Instruction::SIToFP>(Op); } -/// \brief Matches FPTrunc +/// Matches FPTrunc template <typename OpTy> inline CastClass_match<OpTy, Instruction::FPTrunc> m_FPTrunc(const OpTy &Op) { return CastClass_match<OpTy, Instruction::FPTrunc>(Op); } -/// \brief Matches FPExt +/// Matches FPExt template <typename OpTy> inline CastClass_match<OpTy, Instruction::FPExt> m_FPExt(const OpTy &Op) { return CastClass_match<OpTy, Instruction::FPExt>(Op); @@ -976,80 +1200,32 @@ template <typename Op_t> struct LoadClass_match { template <typename OpTy> inline LoadClass_match<OpTy> m_Load(const OpTy &Op) { return LoadClass_match<OpTy>(Op); } + //===----------------------------------------------------------------------===// -// Matchers for unary operators +// Matcher for StoreInst classes // -template <typename LHS_t> struct not_match { - LHS_t L; - - not_match(const LHS_t &LHS) : L(LHS) {} - - template <typename OpTy> bool match(OpTy *V) { - if (auto *O = dyn_cast<Operator>(V)) - if (O->getOpcode() == Instruction::Xor) { - if (isAllOnes(O->getOperand(1))) - return L.match(O->getOperand(0)); - if (isAllOnes(O->getOperand(0))) - return L.match(O->getOperand(1)); - } - return false; - } - -private: - bool isAllOnes(Value *V) { - return isa<Constant>(V) && cast<Constant>(V)->isAllOnesValue(); - } -}; - -template <typename LHS> inline not_match<LHS> m_Not(const LHS &L) { return L; } +template <typename ValueOp_t, typename PointerOp_t> struct StoreClass_match { + ValueOp_t ValueOp; + PointerOp_t PointerOp; -template <typename LHS_t> struct neg_match { - LHS_t L; - - neg_match(const LHS_t &LHS) : L(LHS) {} + StoreClass_match(const ValueOp_t &ValueOpMatch, + const PointerOp_t &PointerOpMatch) : + ValueOp(ValueOpMatch), PointerOp(PointerOpMatch) {} template <typename OpTy> bool match(OpTy *V) { - if (auto *O = dyn_cast<Operator>(V)) - if (O->getOpcode() == Instruction::Sub) - return matchIfNeg(O->getOperand(0), O->getOperand(1)); + if (auto *LI = dyn_cast<StoreInst>(V)) + return ValueOp.match(LI->getValueOperand()) && + PointerOp.match(LI->getPointerOperand()); return false; } - -private: - bool matchIfNeg(Value *LHS, Value *RHS) { - return ((isa<ConstantInt>(LHS) && cast<ConstantInt>(LHS)->isZero()) || - isa<ConstantAggregateZero>(LHS)) && - L.match(RHS); - } }; -/// \brief Match an integer negate. -template <typename LHS> inline neg_match<LHS> m_Neg(const LHS &L) { return L; } - -template <typename LHS_t> struct fneg_match { - LHS_t L; - - fneg_match(const LHS_t &LHS) : L(LHS) {} - - template <typename OpTy> bool match(OpTy *V) { - if (auto *O = dyn_cast<Operator>(V)) - if (O->getOpcode() == Instruction::FSub) - return matchIfFNeg(O->getOperand(0), O->getOperand(1)); - return false; - } - -private: - bool matchIfFNeg(Value *LHS, Value *RHS) { - if (const auto *C = dyn_cast<ConstantFP>(LHS)) - return C->isNegativeZeroValue() && L.match(RHS); - return false; - } -}; - -/// \brief Match a floating point negate. -template <typename LHS> inline fneg_match<LHS> m_FNeg(const LHS &L) { - return L; +/// Matches StoreInst. +template <typename ValueOpTy, typename PointerOpTy> +inline StoreClass_match<ValueOpTy, PointerOpTy> +m_Store(const ValueOpTy &ValueOp, const PointerOpTy &PointerOp) { + return StoreClass_match<ValueOpTy, PointerOpTy>(ValueOp, PointerOp); } //===----------------------------------------------------------------------===// @@ -1106,6 +1282,8 @@ struct MaxMin_match { LHS_t L; RHS_t R; + // The evaluation order is always stable, regardless of Commutability. + // The LHS is always matched first. MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} template <typename OpTy> bool match(OpTy *V) { @@ -1132,60 +1310,60 @@ struct MaxMin_match { return false; // It does! Bind the operands. return (L.match(LHS) && R.match(RHS)) || - (Commutable && R.match(LHS) && L.match(RHS)); + (Commutable && L.match(RHS) && R.match(LHS)); } }; -/// \brief Helper class for identifying signed max predicates. +/// Helper class for identifying signed max predicates. struct smax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE; } }; -/// \brief Helper class for identifying signed min predicates. +/// Helper class for identifying signed min predicates. struct smin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE; } }; -/// \brief Helper class for identifying unsigned max predicates. +/// Helper class for identifying unsigned max predicates. struct umax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE; } }; -/// \brief Helper class for identifying unsigned min predicates. +/// Helper class for identifying unsigned min predicates. struct umin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE; } }; -/// \brief Helper class for identifying ordered max predicates. +/// Helper class for identifying ordered max predicates. struct ofmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_OGE; } }; -/// \brief Helper class for identifying ordered min predicates. +/// Helper class for identifying ordered min predicates. struct ofmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE; } }; -/// \brief Helper class for identifying unordered max predicates. +/// Helper class for identifying unordered max predicates. struct ufmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_UGT || Pred == CmpInst::FCMP_UGE; } }; -/// \brief Helper class for identifying unordered min predicates. +/// Helper class for identifying unordered min predicates. struct ufmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_ULT || Pred == CmpInst::FCMP_ULE; @@ -1216,7 +1394,7 @@ inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty> m_UMin(const LHS &L, return MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>(L, R); } -/// \brief Match an 'ordered' floating point maximum function. +/// Match an 'ordered' floating point maximum function. /// Floating point has one special value 'NaN'. Therefore, there is no total /// order. However, if we can ignore the 'NaN' value (for example, because of a /// 'no-nans-float-math' flag) a combination of a fcmp and select has 'maximum' @@ -1231,7 +1409,7 @@ inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty> m_OrdFMax(const LHS &L, return MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>(L, R); } -/// \brief Match an 'ordered' floating point minimum function. +/// Match an 'ordered' floating point minimum function. /// Floating point has one special value 'NaN'. Therefore, there is no total /// order. However, if we can ignore the 'NaN' value (for example, because of a /// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum' @@ -1246,7 +1424,7 @@ inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> m_OrdFMin(const LHS &L, return MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>(L, R); } -/// \brief Match an 'unordered' floating point maximum function. +/// Match an 'unordered' floating point maximum function. /// Floating point has one special value 'NaN'. Therefore, there is no total /// order. However, if we can ignore the 'NaN' value (for example, because of a /// 'no-nans-float-math' flag) a combination of a fcmp and select has 'maximum' @@ -1261,7 +1439,7 @@ m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R); } -/// \brief Match an 'unordered' floating point minimum function. +/// Match an 'unordered' floating point minimum function. /// Floating point has one special value 'NaN'. Therefore, there is no total /// order. However, if we can ignore the 'NaN' value (for example, because of a /// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum' @@ -1312,7 +1490,7 @@ struct UAddWithOverflow_match { } }; -/// \brief Match an icmp instruction checking for unsigned overflow on addition. +/// Match an icmp instruction checking for unsigned overflow on addition. /// /// S is matched to the addition whose result is being checked for overflow, and /// L and R are matched to the LHS and RHS of S. @@ -1334,13 +1512,13 @@ template <typename Opnd_t> struct Argument_match { } }; -/// \brief Match an argument. +/// Match an argument. template <unsigned OpI, typename Opnd_t> inline Argument_match<Opnd_t> m_Argument(const Opnd_t &Op) { return Argument_match<Opnd_t>(OpI, Op); } -/// \brief Intrinsic matchers. +/// Intrinsic matchers. struct IntrinsicID_match { unsigned ID; @@ -1383,7 +1561,7 @@ struct m_Intrinsic_Ty<T0, T1, T2, T3> { Argument_match<T3>>; }; -/// \brief Match intrinsic calls like this: +/// Match intrinsic calls like this: /// m_Intrinsic<Intrinsic::fabs>(m_Value(X)) template <Intrinsic::ID IntrID> inline IntrinsicID_match m_Intrinsic() { return IntrinsicID_match(IntrID); @@ -1424,6 +1602,16 @@ inline typename m_Intrinsic_Ty<Opnd0>::Ty m_BSwap(const Opnd0 &Op0) { return m_Intrinsic<Intrinsic::bswap>(Op0); } +template <typename Opnd0> +inline typename m_Intrinsic_Ty<Opnd0>::Ty m_FAbs(const Opnd0 &Op0) { + return m_Intrinsic<Intrinsic::fabs>(Op0); +} + +template <typename Opnd0> +inline typename m_Intrinsic_Ty<Opnd0>::Ty m_FCanonicalize(const Opnd0 &Op0) { + return m_Intrinsic<Intrinsic::canonicalize>(Op0); +} + template <typename Opnd0, typename Opnd1> inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMin(const Opnd0 &Op0, const Opnd1 &Op1) { @@ -1436,57 +1624,17 @@ inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_FMax(const Opnd0 &Op0, return m_Intrinsic<Intrinsic::maxnum>(Op0, Op1); } -template <typename Opnd_t> struct Signum_match { - Opnd_t Val; - Signum_match(const Opnd_t &V) : Val(V) {} - - template <typename OpTy> bool match(OpTy *V) { - unsigned TypeSize = V->getType()->getScalarSizeInBits(); - if (TypeSize == 0) - return false; - - unsigned ShiftWidth = TypeSize - 1; - Value *OpL = nullptr, *OpR = nullptr; - - // This is the representation of signum we match: - // - // signum(x) == (x >> 63) | (-x >>u 63) - // - // An i1 value is its own signum, so it's correct to match - // - // signum(x) == (x >> 0) | (-x >>u 0) - // - // for i1 values. - - auto LHS = m_AShr(m_Value(OpL), m_SpecificInt(ShiftWidth)); - auto RHS = m_LShr(m_Neg(m_Value(OpR)), m_SpecificInt(ShiftWidth)); - auto Signum = m_Or(LHS, RHS); - - return Signum.match(V) && OpL == OpR && Val.match(OpL); - } -}; - -/// \brief Matches a signum pattern. -/// -/// signum(x) = -/// x > 0 -> 1 -/// x == 0 -> 0 -/// x < 0 -> -1 -template <typename Val_t> inline Signum_match<Val_t> m_Signum(const Val_t &V) { - return Signum_match<Val_t>(V); -} - //===----------------------------------------------------------------------===// // Matchers for two-operands operators with the operators in either order // -/// \brief Matches a BinaryOperator with LHS and RHS in either order. +/// Matches a BinaryOperator with LHS and RHS in either order. template <typename LHS, typename RHS> inline AnyBinaryOp_match<LHS, RHS, true> m_c_BinOp(const LHS &L, const RHS &R) { return AnyBinaryOp_match<LHS, RHS, true>(L, R); } -/// \brief Matches an ICmp with a predicate over LHS and RHS in either order. +/// Matches an ICmp with a predicate over LHS and RHS in either order. /// Does not swap the predicate. template <typename LHS, typename RHS> inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true> @@ -1495,41 +1643,55 @@ m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { R); } -/// \brief Matches a Add with LHS and RHS in either order. +/// Matches a Add with LHS and RHS in either order. template <typename LHS, typename RHS> inline BinaryOp_match<LHS, RHS, Instruction::Add, true> m_c_Add(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Add, true>(L, R); } -/// \brief Matches a Mul with LHS and RHS in either order. +/// Matches a Mul with LHS and RHS in either order. template <typename LHS, typename RHS> inline BinaryOp_match<LHS, RHS, Instruction::Mul, true> m_c_Mul(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Mul, true>(L, R); } -/// \brief Matches an And with LHS and RHS in either order. +/// Matches an And with LHS and RHS in either order. template <typename LHS, typename RHS> inline BinaryOp_match<LHS, RHS, Instruction::And, true> m_c_And(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::And, true>(L, R); } -/// \brief Matches an Or with LHS and RHS in either order. +/// Matches an Or with LHS and RHS in either order. template <typename LHS, typename RHS> inline BinaryOp_match<LHS, RHS, Instruction::Or, true> m_c_Or(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Or, true>(L, R); } -/// \brief Matches an Xor with LHS and RHS in either order. +/// Matches an Xor with LHS and RHS in either order. template <typename LHS, typename RHS> inline BinaryOp_match<LHS, RHS, Instruction::Xor, true> m_c_Xor(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Xor, true>(L, R); } +/// Matches a 'Neg' as 'sub 0, V'. +template <typename ValTy> +inline BinaryOp_match<cst_pred_ty<is_zero_int>, ValTy, Instruction::Sub> +m_Neg(const ValTy &V) { + return m_Sub(m_ZeroInt(), V); +} + +/// Matches a 'Not' as 'xor V, -1' or 'xor -1, V'. +template <typename ValTy> +inline BinaryOp_match<ValTy, cst_pred_ty<is_all_ones>, Instruction::Xor, true> +m_Not(const ValTy &V) { + return m_c_Xor(V, m_AllOnes()); +} + /// Matches an SMin with LHS and RHS in either order. template <typename LHS, typename RHS> inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty, true> @@ -1555,6 +1717,60 @@ m_c_UMax(const LHS &L, const RHS &R) { return MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty, true>(L, R); } +/// Matches FAdd with LHS and RHS in either order. +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FAdd, true> +m_c_FAdd(const LHS &L, const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::FAdd, true>(L, R); +} + +/// Matches FMul with LHS and RHS in either order. +template <typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FMul, true> +m_c_FMul(const LHS &L, const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::FMul, true>(L, R); +} + +template <typename Opnd_t> struct Signum_match { + Opnd_t Val; + Signum_match(const Opnd_t &V) : Val(V) {} + + template <typename OpTy> bool match(OpTy *V) { + unsigned TypeSize = V->getType()->getScalarSizeInBits(); + if (TypeSize == 0) + return false; + + unsigned ShiftWidth = TypeSize - 1; + Value *OpL = nullptr, *OpR = nullptr; + + // This is the representation of signum we match: + // + // signum(x) == (x >> 63) | (-x >>u 63) + // + // An i1 value is its own signum, so it's correct to match + // + // signum(x) == (x >> 0) | (-x >>u 0) + // + // for i1 values. + + auto LHS = m_AShr(m_Value(OpL), m_SpecificInt(ShiftWidth)); + auto RHS = m_LShr(m_Neg(m_Value(OpR)), m_SpecificInt(ShiftWidth)); + auto Signum = m_Or(LHS, RHS); + + return Signum.match(V) && OpL == OpR && Val.match(OpL); + } +}; + +/// Matches a signum pattern. +/// +/// signum(x) = +/// x > 0 -> 1 +/// x == 0 -> 0 +/// x < 0 -> -1 +template <typename Val_t> inline Signum_match<Val_t> m_Signum(const Val_t &V) { + return Signum_match<Val_t>(V); +} + } // end namespace PatternMatch } // end namespace llvm diff --git a/contrib/llvm/include/llvm/IR/ProfileSummary.h b/contrib/llvm/include/llvm/IR/ProfileSummary.h index d85ce8c443ec..e38663770a13 100644 --- a/contrib/llvm/include/llvm/IR/ProfileSummary.h +++ b/contrib/llvm/include/llvm/IR/ProfileSummary.h @@ -51,7 +51,7 @@ private: SummaryEntryVector DetailedSummary; uint64_t TotalCount, MaxCount, MaxInternalCount, MaxFunctionCount; uint32_t NumCounts, NumFunctions; - /// \brief Return detailed summary as metadata. + /// Return detailed summary as metadata. Metadata *getDetailedSummaryMD(LLVMContext &Context); public: @@ -67,9 +67,9 @@ public: NumCounts(NumCounts), NumFunctions(NumFunctions) {} Kind getKind() const { return PSK; } - /// \brief Return summary information as metadata. + /// Return summary information as metadata. Metadata *getMD(LLVMContext &Context); - /// \brief Construct profile summary from metdata. + /// Construct profile summary from metdata. static ProfileSummary *getFromMD(Metadata *MD); SummaryEntryVector &getDetailedSummary() { return DetailedSummary; } uint32_t getNumFunctions() { return NumFunctions; } diff --git a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.def b/contrib/llvm/include/llvm/IR/RuntimeLibcalls.def index 7695e9d782ef..7ed90d959f01 100644 --- a/contrib/llvm/include/llvm/CodeGen/RuntimeLibcalls.def +++ b/contrib/llvm/include/llvm/IR/RuntimeLibcalls.def @@ -130,26 +130,51 @@ HANDLE_LIBCALL(LOG_F64, "log") HANDLE_LIBCALL(LOG_F80, "logl") HANDLE_LIBCALL(LOG_F128, "logl") HANDLE_LIBCALL(LOG_PPCF128, "logl") +HANDLE_LIBCALL(LOG_FINITE_F32, "__logf_finite") +HANDLE_LIBCALL(LOG_FINITE_F64, "__log_finite") +HANDLE_LIBCALL(LOG_FINITE_F80, "__logl_finite") +HANDLE_LIBCALL(LOG_FINITE_F128, "__logl_finite") +HANDLE_LIBCALL(LOG_FINITE_PPCF128, "__logl_finite") HANDLE_LIBCALL(LOG2_F32, "log2f") HANDLE_LIBCALL(LOG2_F64, "log2") HANDLE_LIBCALL(LOG2_F80, "log2l") HANDLE_LIBCALL(LOG2_F128, "log2l") HANDLE_LIBCALL(LOG2_PPCF128, "log2l") +HANDLE_LIBCALL(LOG2_FINITE_F32, "__log2f_finite") +HANDLE_LIBCALL(LOG2_FINITE_F64, "__log2_finite") +HANDLE_LIBCALL(LOG2_FINITE_F80, "__log2l_finite") +HANDLE_LIBCALL(LOG2_FINITE_F128, "__log2l_finite") +HANDLE_LIBCALL(LOG2_FINITE_PPCF128, "__log2l_finite") HANDLE_LIBCALL(LOG10_F32, "log10f") HANDLE_LIBCALL(LOG10_F64, "log10") HANDLE_LIBCALL(LOG10_F80, "log10l") HANDLE_LIBCALL(LOG10_F128, "log10l") HANDLE_LIBCALL(LOG10_PPCF128, "log10l") +HANDLE_LIBCALL(LOG10_FINITE_F32, "__log10f_finite") +HANDLE_LIBCALL(LOG10_FINITE_F64, "__log10_finite") +HANDLE_LIBCALL(LOG10_FINITE_F80, "__log10l_finite") +HANDLE_LIBCALL(LOG10_FINITE_F128, "__log10l_finite") +HANDLE_LIBCALL(LOG10_FINITE_PPCF128, "__log10l_finite") HANDLE_LIBCALL(EXP_F32, "expf") HANDLE_LIBCALL(EXP_F64, "exp") HANDLE_LIBCALL(EXP_F80, "expl") HANDLE_LIBCALL(EXP_F128, "expl") HANDLE_LIBCALL(EXP_PPCF128, "expl") +HANDLE_LIBCALL(EXP_FINITE_F32, "__expf_finite") +HANDLE_LIBCALL(EXP_FINITE_F64, "__exp_finite") +HANDLE_LIBCALL(EXP_FINITE_F80, "__expl_finite") +HANDLE_LIBCALL(EXP_FINITE_F128, "__expl_finite") +HANDLE_LIBCALL(EXP_FINITE_PPCF128, "__expl_finite") HANDLE_LIBCALL(EXP2_F32, "exp2f") HANDLE_LIBCALL(EXP2_F64, "exp2") HANDLE_LIBCALL(EXP2_F80, "exp2l") HANDLE_LIBCALL(EXP2_F128, "exp2l") HANDLE_LIBCALL(EXP2_PPCF128, "exp2l") +HANDLE_LIBCALL(EXP2_FINITE_F32, "__exp2f_finite") +HANDLE_LIBCALL(EXP2_FINITE_F64, "__exp2_finite") +HANDLE_LIBCALL(EXP2_FINITE_F80, "__exp2l_finite") +HANDLE_LIBCALL(EXP2_FINITE_F128, "__exp2l_finite") +HANDLE_LIBCALL(EXP2_FINITE_PPCF128, "__exp2l_finite") HANDLE_LIBCALL(SIN_F32, "sinf") HANDLE_LIBCALL(SIN_F64, "sin") HANDLE_LIBCALL(SIN_F80, "sinl") @@ -172,6 +197,11 @@ HANDLE_LIBCALL(POW_F64, "pow") HANDLE_LIBCALL(POW_F80, "powl") HANDLE_LIBCALL(POW_F128, "powl") HANDLE_LIBCALL(POW_PPCF128, "powl") +HANDLE_LIBCALL(POW_FINITE_F32, "__powf_finite") +HANDLE_LIBCALL(POW_FINITE_F64, "__pow_finite") +HANDLE_LIBCALL(POW_FINITE_F80, "__powl_finite") +HANDLE_LIBCALL(POW_FINITE_F128, "__powl_finite") +HANDLE_LIBCALL(POW_FINITE_PPCF128, "__powl_finite") HANDLE_LIBCALL(CEIL_F32, "ceilf") HANDLE_LIBCALL(CEIL_F64, "ceil") HANDLE_LIBCALL(CEIL_F80, "ceill") @@ -221,6 +251,7 @@ HANDLE_LIBCALL(FMAX_PPCF128, "fmaxl") // Conversion HANDLE_LIBCALL(FPEXT_F32_PPCF128, "__gcc_stoq") HANDLE_LIBCALL(FPEXT_F64_PPCF128, "__gcc_dtoq") +HANDLE_LIBCALL(FPEXT_F80_F128, "__extendxftf2") HANDLE_LIBCALL(FPEXT_F64_F128, "__extenddftf2") HANDLE_LIBCALL(FPEXT_F32_F128, "__extendsftf2") HANDLE_LIBCALL(FPEXT_F32_F64, "__extendsfdf2") @@ -237,6 +268,7 @@ HANDLE_LIBCALL(FPROUND_PPCF128_F32, "__gcc_qtos") HANDLE_LIBCALL(FPROUND_F80_F64, "__truncxfdf2") HANDLE_LIBCALL(FPROUND_F128_F64, "__trunctfdf2") HANDLE_LIBCALL(FPROUND_PPCF128_F64, "__gcc_qtod") +HANDLE_LIBCALL(FPROUND_F128_F80, "__trunctfxf2") HANDLE_LIBCALL(FPTOSINT_F32_I32, "__fixsfsi") HANDLE_LIBCALL(FPTOSINT_F32_I64, "__fixsfdi") HANDLE_LIBCALL(FPTOSINT_F32_I128, "__fixsfti") diff --git a/contrib/llvm/include/llvm/IR/Statepoint.h b/contrib/llvm/include/llvm/IR/Statepoint.h index ad9537e9762e..c8e905b21a30 100644 --- a/contrib/llvm/include/llvm/IR/Statepoint.h +++ b/contrib/llvm/include/llvm/IR/Statepoint.h @@ -196,7 +196,7 @@ public: return make_range(arg_begin(), arg_end()); } - /// \brief Return true if the call or the callee has the given attribute. + /// Return true if the call or the callee has the given attribute. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const { Function *F = getCalledFunction(); return getCallSite().paramHasAttr(i + CallArgsBeginPos, A) || @@ -465,7 +465,7 @@ struct StatepointDirectives { /// AS. StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS); -/// Return \c true if the the \p Attr is an attribute that is a statepoint +/// Return \c true if the \p Attr is an attribute that is a statepoint /// directive. bool isStatepointDirectiveAttr(Attribute Attr); diff --git a/contrib/llvm/include/llvm/IR/TrackingMDRef.h b/contrib/llvm/include/llvm/IR/TrackingMDRef.h index bdec904ad1e1..084efada221f 100644 --- a/contrib/llvm/include/llvm/IR/TrackingMDRef.h +++ b/contrib/llvm/include/llvm/IR/TrackingMDRef.h @@ -20,7 +20,7 @@ namespace llvm { -/// \brief Tracking metadata reference. +/// Tracking metadata reference. /// /// This class behaves like \a TrackingVH, but for metadata. class TrackingMDRef { @@ -70,7 +70,7 @@ public: track(); } - /// \brief Check whether this has a trivial destructor. + /// Check whether this has a trivial destructor. /// /// If \c MD isn't replaceable, the destructor will be a no-op. bool hasTrivialDestructor() const { @@ -100,7 +100,7 @@ private: } }; -/// \brief Typed tracking ref. +/// Typed tracking ref. /// /// Track refererences of a particular type. It's useful to use this for \a /// MDNode and \a ValueAsMetadata. @@ -135,7 +135,7 @@ public: void reset() { Ref.reset(); } void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); } - /// \brief Check whether this has a trivial destructor. + /// Check whether this has a trivial destructor. bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); } }; diff --git a/contrib/llvm/include/llvm/IR/Type.h b/contrib/llvm/include/llvm/IR/Type.h index 1574fc334ffc..9c1f99d1b3a2 100644 --- a/contrib/llvm/include/llvm/IR/Type.h +++ b/contrib/llvm/include/llvm/IR/Type.h @@ -208,6 +208,9 @@ public: return getScalarType()->isIntegerTy(BitWidth); } + /// Return true if this is an integer type or a pointer type. + bool isIntOrPtrTy() const { return isIntegerTy() || isPointerTy(); } + /// True if this is an instance of FunctionType. bool isFunctionTy() const { return getTypeID() == FunctionTyID; } @@ -229,7 +232,7 @@ public: /// Return true if this type could be converted with a lossless BitCast to /// type 'Ty'. For example, i8* to i32*. BitCasts are valid for types of the /// same size only where no re-interpretation of the bits is done. - /// @brief Determine if this type could be losslessly bitcast to Ty + /// Determine if this type could be losslessly bitcast to Ty bool canLosslesslyBitCastTo(Type *Ty) const; /// Return true if this type is empty, that is, it has no elements or all of @@ -407,6 +410,20 @@ public: static IntegerType *getInt32Ty(LLVMContext &C); static IntegerType *getInt64Ty(LLVMContext &C); static IntegerType *getInt128Ty(LLVMContext &C); + template <typename ScalarTy> static Type *getScalarTy(LLVMContext &C) { + int noOfBits = sizeof(ScalarTy) * CHAR_BIT; + if (std::is_integral<ScalarTy>::value) { + return (Type*) Type::getIntNTy(C, noOfBits); + } else if (std::is_floating_point<ScalarTy>::value) { + switch (noOfBits) { + case 32: + return Type::getFloatTy(C); + case 64: + return Type::getDoubleTy(C); + } + } + llvm_unreachable("Unsupported type in Type::getScalarTy"); + } //===--------------------------------------------------------------------===// // Convenience methods for getting pointer types with one of the above builtin diff --git a/contrib/llvm/include/llvm/IR/Use.h b/contrib/llvm/include/llvm/IR/Use.h index 0ac13935c7ce..25c44e0871a9 100644 --- a/contrib/llvm/include/llvm/IR/Use.h +++ b/contrib/llvm/include/llvm/IR/Use.h @@ -36,7 +36,7 @@ template <typename> struct simplify_type; class User; class Value; -/// \brief A Use represents the edge between a Value definition and its users. +/// 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 @@ -57,7 +57,7 @@ class Use { public: Use(const Use &U) = delete; - /// \brief Provide a fast substitute to std::swap<Use> + /// Provide a fast substitute to std::swap<Use> /// that also works with less standard-compliant compilers void swap(Use &RHS); @@ -107,7 +107,7 @@ public: operator Value *() const { return Val; } Value *get() const { return Val; } - /// \brief Returns the User that contains this Use. + /// Returns the User that contains this Use. /// /// For an instruction operand, for example, this will return the /// instruction. @@ -123,16 +123,16 @@ public: Use *getNext() const { return Next; } - /// \brief Return the operand # of this use in its User. + /// Return the operand # of this use in its User. unsigned getOperandNo() const; - /// \brief Initializes the waymarking tags on an array of Uses. + /// 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); - /// \brief Destroys Use operands when the number of operands of + /// Destroys Use operands when the number of operands of /// a User changes. static void zap(Use *Start, const Use *Stop, bool del = false); @@ -161,7 +161,7 @@ private: } }; -/// \brief Allow clients to treat uses just like values when using +/// Allow clients to treat uses just like values when using /// casting operators. template <> struct simplify_type<Use> { using SimpleType = Value *; diff --git a/contrib/llvm/include/llvm/IR/UseListOrder.h b/contrib/llvm/include/llvm/IR/UseListOrder.h index a8b394fc6302..b6bb0f19a0aa 100644 --- a/contrib/llvm/include/llvm/IR/UseListOrder.h +++ b/contrib/llvm/include/llvm/IR/UseListOrder.h @@ -23,7 +23,7 @@ namespace llvm { class Function; class Value; -/// \brief Structure to hold a use-list order. +/// Structure to hold a use-list order. struct UseListOrder { const Value *V = nullptr; const Function *F = nullptr; diff --git a/contrib/llvm/include/llvm/IR/User.h b/contrib/llvm/include/llvm/IR/User.h index 4dfa19cf241f..d6a603ce845d 100644 --- a/contrib/llvm/include/llvm/IR/User.h +++ b/contrib/llvm/include/llvm/IR/User.h @@ -36,7 +36,7 @@ namespace llvm { template <typename T> class ArrayRef; template <typename T> class MutableArrayRef; -/// \brief Compile-time customization of User operands. +/// Compile-time customization of User operands. /// /// Customizes operand-related allocators and accessors. template <class> @@ -81,13 +81,13 @@ protected: "Error in initializing hung off uses for User"); } - /// \brief Allocate the array of Uses, followed by a pointer + /// Allocate the array of Uses, followed by a pointer /// (with bottom bit set) to the User. /// \param IsPhi identifies callers which are phi nodes and which need /// N BasicBlock* allocated along with N void allocHungoffUses(unsigned N, bool IsPhi = false); - /// \brief Grow the number of hung off uses. Note that allocHungoffUses + /// Grow the number of hung off uses. Note that allocHungoffUses /// should be called if there are no uses. void growHungoffUses(unsigned N, bool IsPhi = false); @@ -97,15 +97,31 @@ protected: public: User(const User &) = delete; - /// \brief Free memory allocated for User and Use objects. + /// Free memory allocated for User and Use objects. void operator delete(void *Usr); - /// \brief Placement delete - required by std, but never called. - void operator delete(void*, unsigned) { + /// Placement delete - required by std, called if the ctor throws. + void operator delete(void *Usr, unsigned) { + // Note: If a subclass manipulates the information which is required to calculate the + // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has + // to restore the changed information to the original value, since the dtor of that class + // is not called if the ctor fails. + User::operator delete(Usr); + +#ifndef LLVM_ENABLE_EXCEPTIONS llvm_unreachable("Constructor throws?"); +#endif } - /// \brief Placement delete - required by std, but never called. - void operator delete(void*, unsigned, bool) { + /// Placement delete - required by std, called if the ctor throws. + void operator delete(void *Usr, unsigned, bool) { + // Note: If a subclass manipulates the information which is required to calculate the + // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has + // to restore the changed information to the original value, since the dtor of that class + // is not called if the ctor fails. + User::operator delete(Usr); + +#ifndef LLVM_ENABLE_EXCEPTIONS llvm_unreachable("Constructor throws?"); +#endif } protected: @@ -194,7 +210,7 @@ public: NumUserOperands = NumOps; } - /// \brief Subclasses with hung off uses need to manage the operand count + /// Subclasses with hung off uses need to manage the operand count /// themselves. In these instances, the operand count isn't used to find the /// OperandList, so there's no issue in having the operand count change. void setNumHungOffUseOperands(unsigned NumOps) { @@ -226,7 +242,7 @@ public: return const_op_range(op_begin(), op_end()); } - /// \brief Iterator for directly iterating over the operand Values. + /// Iterator for directly iterating over the operand Values. struct value_op_iterator : iterator_adaptor_base<value_op_iterator, op_iterator, std::random_access_iterator_tag, Value *, @@ -268,7 +284,7 @@ public: return make_range(value_op_begin(), value_op_end()); } - /// \brief Drop all references to operands. + /// Drop all references to operands. /// /// This function is in charge of "letting go" of all objects that this User /// refers to. This allows one to 'delete' a whole class at a time, even @@ -281,7 +297,7 @@ public: U.set(nullptr); } - /// \brief Replace uses of one Value with another. + /// Replace uses of one Value with another. /// /// Replaces all references to the "From" definition with references to the /// "To" definition. diff --git a/contrib/llvm/include/llvm/IR/Value.h b/contrib/llvm/include/llvm/IR/Value.h index d848fe921868..f396db995ab0 100644 --- a/contrib/llvm/include/llvm/IR/Value.h +++ b/contrib/llvm/include/llvm/IR/Value.h @@ -57,7 +57,7 @@ using ValueName = StringMapEntry<Value *>; // Value Class //===----------------------------------------------------------------------===// -/// \brief LLVM Value Representation +/// LLVM Value Representation /// /// This is a very important LLVM class. It is the base class of all values /// computed by a program that may be used as operands to other values. Value is @@ -83,7 +83,7 @@ class Value { unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? protected: - /// \brief Hold subclass data that can be dropped. + /// Hold subclass data that can be dropped. /// /// This member is similar to SubclassData, however it is for holding /// information which may be used to aid optimization, but which may be @@ -91,7 +91,7 @@ protected: unsigned char SubclassOptionalData : 7; private: - /// \brief Hold arbitrary subclass data. + /// Hold arbitrary subclass data. /// /// This member is defined by this class, but is not used for anything. /// Subclasses can use it to hold whatever state they find useful. This @@ -99,7 +99,7 @@ private: unsigned short SubclassData; protected: - /// \brief The number of operands in the subclass. + /// The number of operands in the subclass. /// /// This member is defined by this class, but not used for anything. /// Subclasses can use it to store their number of operands, if they have @@ -173,7 +173,7 @@ private: 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. + /// 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 @@ -218,17 +218,17 @@ public: /// Delete a pointer to a generic Value. void deleteValue(); - /// \brief Support for debugging, callable in GDB: V->dump() + /// Support for debugging, callable in GDB: V->dump() void dump() const; - /// \brief Implement operator<< on Value. + /// Implement operator<< on Value. /// @{ void print(raw_ostream &O, bool IsForDebug = false) const; void print(raw_ostream &O, ModuleSlotTracker &MST, bool IsForDebug = false) const; /// @} - /// \brief Print the name of this Value out to the specified raw_ostream. + /// 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 @@ -241,13 +241,13 @@ public: ModuleSlotTracker &MST) const; /// @} - /// \brief All values are typed, get the type of this value. + /// All values are typed, get the type of this value. Type *getType() const { return VTy; } - /// \brief All values hold a context through their type. + /// All values hold a context through their type. LLVMContext &getContext() const; - // \brief All values can potentially be named. + // All values can potentially be named. bool hasName() const { return HasName; } ValueName *getValueName() const; void setValueName(ValueName *VN); @@ -258,35 +258,35 @@ private: void setNameImpl(const Twine &Name); public: - /// \brief Return a constant reference to the value's name. + /// Return a constant reference to the value's name. /// /// This guaranteed to return the same reference as long as the value is not /// modified. If the value has a name, this does a hashtable lookup, so it's /// not free. StringRef getName() const; - /// \brief Change the name of the value. + /// Change the name of the value. /// /// Choose a new unique name if the provided name is taken. /// /// \param Name The new name; or "" if the value's name should be removed. void setName(const Twine &Name); - /// \brief Transfer the name from V to this value. + /// Transfer the name from V to this value. /// /// After taking V's name, sets V's name to empty. /// /// \note It is an error to call V->takeName(V). void takeName(Value *V); - /// \brief Change all uses of this to point to a new Value. + /// Change all uses of this to point to a new Value. /// /// Go through the uses list for this definition and make each use point to /// "V" instead of "this". After this completes, 'this's use list is /// guaranteed to be empty. void replaceAllUsesWith(Value *V); - /// \brief Change non-metadata uses of this to point to a new Value. + /// Change non-metadata uses of this to point to a new Value. /// /// Go through the uses list for this definition and make each use point to /// "V" instead of "this". This function skips metadata entries in the list. @@ -299,12 +299,6 @@ public: /// values or constant users. void replaceUsesOutsideBlock(Value *V, BasicBlock *BB); - /// replaceUsesExceptBlockAddr - Go through the uses list for this definition - /// and make each use point to "V" instead of "this" when the use is outside - /// the block. 'This's use list is expected to have at least one element. - /// Unlike replaceAllUsesWith this function skips blockaddr uses. - void replaceUsesExceptBlockAddr(Value *New); - //---------------------------------------------------------------------- // Methods for handling the chain of uses of this Value. // @@ -411,7 +405,7 @@ public: return materialized_users(); } - /// \brief Return true if there is exactly one user of this value. + /// Return true if there is exactly one user of this value. /// /// This is specialized because it is a common request and does not require /// traversing the whole use list. @@ -421,27 +415,27 @@ public: return ++I == E; } - /// \brief Return true if this Value has exactly N users. + /// Return true if this Value has exactly N users. bool hasNUses(unsigned N) const; - /// \brief Return true if this value has N users or more. + /// Return true if this value has N users or more. /// /// This is logically equivalent to getNumUses() >= N. bool hasNUsesOrMore(unsigned N) const; - /// \brief Check if this value is used in the specified basic block. + /// Check if this value is used in the specified basic block. bool isUsedInBasicBlock(const BasicBlock *BB) const; - /// \brief This method computes the number of uses of this Value. + /// This method computes the number of uses of this Value. /// /// This is a linear time operation. Use hasOneUse, hasNUses, or /// hasNUsesOrMore to check for specific values. unsigned getNumUses() const; - /// \brief This method should only be used by the Use class. + /// This method should only be used by the Use class. void addUse(Use &U) { U.addToList(&UseList); } - /// \brief Concrete subclass of this. + /// Concrete subclass of this. /// /// An enumeration for keeping track of the concrete subclass of Value that /// is actually instantiated. Values of this enumeration are kept in the @@ -456,7 +450,7 @@ public: #include "llvm/IR/Value.def" }; - /// \brief Return an ID for the concrete type of this object. + /// Return an ID for the concrete type of this object. /// /// This is used to implement the classof checks. This should not be used /// for any other purpose, as the values may change as LLVM evolves. Also, @@ -470,36 +464,36 @@ public: return SubclassID; } - /// \brief Return the raw optional flags value contained in this value. + /// Return the raw optional flags value contained in this value. /// /// This should only be used when testing two Values for equivalence. unsigned getRawSubclassOptionalData() const { return SubclassOptionalData; } - /// \brief Clear the optional flags contained in this value. + /// Clear the optional flags contained in this value. void clearSubclassOptionalData() { SubclassOptionalData = 0; } - /// \brief Check the optional flags for equality. + /// Check the optional flags for equality. bool hasSameSubclassOptionalData(const Value *V) const { return SubclassOptionalData == V->SubclassOptionalData; } - /// \brief Return true if there is a value handle associated with this value. + /// Return true if there is a value handle associated with this value. bool hasValueHandle() const { return HasValueHandle; } - /// \brief Return true if there is metadata referencing this value. + /// Return true if there is metadata referencing this value. bool isUsedByMetadata() const { return IsUsedByMD; } - /// \brief Return true if this value is a swifterror value. + /// Return true if this value is a swifterror value. /// /// swifterror values can be either a function argument or an alloca with a /// swifterror attribute. bool isSwiftError() const; - /// \brief Strip off pointer casts, all-zero GEPs, and aliases. + /// Strip off pointer casts, all-zero GEPs, and aliases. /// /// Returns the original uncasted value. If this is called on a non-pointer /// value, it returns 'this'. @@ -509,18 +503,19 @@ public: static_cast<const Value *>(this)->stripPointerCasts()); } - /// \brief Strip off pointer casts, all-zero GEPs, aliases and barriers. + /// Strip off pointer casts, all-zero GEPs, aliases and invariant group + /// info. /// /// Returns the original uncasted value. If this is called on a non-pointer /// value, it returns 'this'. This function should be used only in /// Alias analysis. - const Value *stripPointerCastsAndBarriers() const; - Value *stripPointerCastsAndBarriers() { + const Value *stripPointerCastsAndInvariantGroups() const; + Value *stripPointerCastsAndInvariantGroups() { return const_cast<Value *>( - static_cast<const Value *>(this)->stripPointerCastsAndBarriers()); + static_cast<const Value *>(this)->stripPointerCastsAndInvariantGroups()); } - /// \brief Strip off pointer casts and all-zero GEPs. + /// Strip off pointer casts and all-zero GEPs. /// /// Returns the original uncasted value. If this is called on a non-pointer /// value, it returns 'this'. @@ -530,7 +525,7 @@ public: static_cast<const Value *>(this)->stripPointerCastsNoFollowAliases()); } - /// \brief Strip off pointer casts and all-constant inbounds GEPs. + /// Strip off pointer casts and all-constant inbounds GEPs. /// /// Returns the original pointer value. If this is called on a non-pointer /// value, it returns 'this'. @@ -540,7 +535,7 @@ public: static_cast<const Value *>(this)->stripInBoundsConstantOffsets()); } - /// \brief Accumulate offsets from \a stripInBoundsConstantOffsets(). + /// Accumulate offsets from \a stripInBoundsConstantOffsets(). /// /// Stores the resulting constant offset stripped into the APInt provided. /// The provided APInt will be extended or truncated as needed to be the @@ -555,7 +550,7 @@ public: ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset)); } - /// \brief Strip off pointer casts and inbounds GEPs. + /// Strip off pointer casts and inbounds GEPs. /// /// Returns the original pointer value. If this is called on a non-pointer /// value, it returns 'this'. @@ -565,7 +560,7 @@ public: static_cast<const Value *>(this)->stripInBoundsOffsets()); } - /// \brief Returns the number of bytes known to be dereferenceable for the + /// Returns the number of bytes known to be dereferenceable for the /// pointer value. /// /// If CanBeNull is set by this function the pointer can either be null or be @@ -573,13 +568,13 @@ public: uint64_t getPointerDereferenceableBytes(const DataLayout &DL, bool &CanBeNull) const; - /// \brief Returns an alignment of the pointer value. + /// Returns an alignment of the pointer value. /// /// Returns an alignment which is either specified explicitly, e.g. via /// align attribute of a function argument, or guaranteed by DataLayout. unsigned getPointerAlignment(const DataLayout &DL) const; - /// \brief Translate PHI node to its predecessor from the given basic block. + /// Translate PHI node to its predecessor from the given basic block. /// /// If this value is a PHI node with CurBB as its parent, return the value in /// the PHI node corresponding to PredBB. If not, return ourself. This is @@ -592,14 +587,14 @@ public: static_cast<const Value *>(this)->DoPHITranslation(CurBB, PredBB)); } - /// \brief The maximum alignment for instructions. + /// The maximum alignment for instructions. /// /// This is the greatest alignment value supported by load, store, and alloca /// instructions, and global values. static const unsigned MaxAlignmentExponent = 29; static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent; - /// \brief Mutate the type of this Value to be of the specified type. + /// Mutate the type of this Value to be of the specified type. /// /// Note that this is an extremely dangerous operation which can create /// completely invalid IR very easily. It is strongly recommended that you @@ -609,17 +604,17 @@ public: VTy = Ty; } - /// \brief Sort the use-list. + /// Sort the use-list. /// /// Sorts the Value's use-list by Cmp using a stable mergesort. Cmp is /// expected to compare two \a Use references. template <class Compare> void sortUseList(Compare Cmp); - /// \brief Reverse the use-list. + /// Reverse the use-list. void reverseUseList(); private: - /// \brief Merge two lists together. + /// Merge two lists together. /// /// Merges \c L and \c R using \c Cmp. To enable stable sorts, always pushes /// "equal" items from L before items from R. diff --git a/contrib/llvm/include/llvm/IR/ValueHandle.h b/contrib/llvm/include/llvm/IR/ValueHandle.h index b45cc7b6dc02..d94472ce1be1 100644 --- a/contrib/llvm/include/llvm/IR/ValueHandle.h +++ b/contrib/llvm/include/llvm/IR/ValueHandle.h @@ -22,7 +22,7 @@ namespace llvm { -/// \brief This is the common base class of value handles. +/// This is the common base class of value handles. /// /// ValueHandle's are smart pointers to Value's that have special behavior when /// the value is deleted or ReplaceAllUsesWith'd. See the specific handles @@ -31,7 +31,7 @@ class ValueHandleBase { friend class Value; protected: - /// \brief This indicates what sub class the handle actually is. + /// This indicates what sub class the handle actually is. /// /// This is to avoid having a vtable for the light-weight handle pointers. The /// fully general Callback version does have a vtable. @@ -101,10 +101,10 @@ protected: V != DenseMapInfo<Value *>::getTombstoneKey(); } - /// \brief Remove this ValueHandle from its current use list. + /// Remove this ValueHandle from its current use list. void RemoveFromUseList(); - /// \brief Clear the underlying pointer without clearing the use list. + /// Clear the underlying pointer without clearing the use list. /// /// This should only be used if a derived class has manually removed the /// handle from the use list. @@ -121,20 +121,20 @@ private: HandleBaseKind getKind() const { return PrevPair.getInt(); } void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } - /// \brief Add this ValueHandle to the use list for V. + /// Add this ValueHandle to the use list for V. /// /// List is the address of either the head of the list or a Next node within /// the existing use list. void AddToExistingUseList(ValueHandleBase **List); - /// \brief Add this ValueHandle to the use list after Node. + /// Add this ValueHandle to the use list after Node. void AddToExistingUseListAfter(ValueHandleBase *Node); - /// \brief Add this ValueHandle to the use list for V. + /// Add this ValueHandle to the use list for V. void AddToUseList(); }; -/// \brief A nullable Value handle that is nullable. +/// A nullable Value handle that is nullable. /// /// This is a value handle that points to a value, and nulls itself /// out if that value is deleted. @@ -172,7 +172,7 @@ template <> struct simplify_type<const WeakVH> { static SimpleType getSimplifiedValue(const WeakVH &WVH) { return WVH; } }; -/// \brief Value handle that is nullable, but tries to track the Value. +/// Value handle that is nullable, but tries to track the Value. /// /// This is a value handle that tries hard to point to a Value, even across /// RAUW operations, but will null itself out if the value is destroyed. this @@ -219,7 +219,7 @@ template <> struct simplify_type<const WeakTrackingVH> { } }; -/// \brief Value handle that asserts if the Value is deleted. +/// Value handle that asserts if the Value is deleted. /// /// This is a Value Handle that points to a value and asserts out if the value /// is destroyed while the handle is still live. This is very useful for @@ -318,7 +318,7 @@ struct isPodLike<AssertingVH<T>> { #endif }; -/// \brief Value handle that tracks a Value across RAUW. +/// Value handle that tracks a Value across RAUW. /// /// TrackingVH is designed for situations where a client needs to hold a handle /// to a Value (or subclass) across some operations which may move that value, @@ -379,7 +379,7 @@ public: ValueTy &operator*() const { return *getValPtr(); } }; -/// \brief Value handle with callbacks on RAUW and destruction. +/// Value handle with callbacks on RAUW and destruction. /// /// This is a value handle that allows subclasses to define callbacks that run /// when the underlying Value has RAUW called on it or is destroyed. This @@ -405,7 +405,7 @@ public: return getValPtr(); } - /// \brief Callback for Value destruction. + /// Callback for Value destruction. /// /// Called when this->getValPtr() is destroyed, inside ~Value(), so you /// may call any non-virtual Value method on getValPtr(), but no subclass @@ -418,7 +418,7 @@ public: /// Value that's being destroyed. virtual void deleted() { setValPtr(nullptr); } - /// \brief Callback for Value RAUW. + /// Callback for Value RAUW. /// /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, /// _before_ any of the uses have actually been replaced. If WeakTrackingVH diff --git a/contrib/llvm/include/llvm/IR/ValueMap.h b/contrib/llvm/include/llvm/IR/ValueMap.h index 11d5823ee479..e7e33918a613 100644 --- a/contrib/llvm/include/llvm/IR/ValueMap.h +++ b/contrib/llvm/include/llvm/IR/ValueMap.h @@ -106,8 +106,12 @@ public: : Map(NumInitBuckets), Data() {} explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) : Map(NumInitBuckets), Data(Data) {} + // ValueMap can't be copied nor moved, beucase the callbacks store pointer + // to it. ValueMap(const ValueMap &) = delete; + ValueMap(ValueMap &&) = delete; ValueMap &operator=(const ValueMap &) = delete; + ValueMap &operator=(ValueMap &&) = delete; bool hasMD() const { return bool(MDMap); } MDMapT &MD() { diff --git a/contrib/llvm/include/llvm/IR/ValueSymbolTable.h b/contrib/llvm/include/llvm/IR/ValueSymbolTable.h index 26cbbfabfc0c..012e717c7470 100644 --- a/contrib/llvm/include/llvm/IR/ValueSymbolTable.h +++ b/contrib/llvm/include/llvm/IR/ValueSymbolTable.h @@ -48,13 +48,13 @@ class ValueSymbolTable { /// @name Types /// @{ public: - /// @brief A mapping of names to values. + /// A mapping of names to values. using ValueMap = StringMap<Value*>; - /// @brief An iterator over a ValueMap. + /// An iterator over a ValueMap. using iterator = ValueMap::iterator; - /// @brief A const_iterator over a ValueMap. + /// A const_iterator over a ValueMap. using const_iterator = ValueMap::const_iterator; /// @} @@ -71,35 +71,35 @@ public: /// This method finds the value with the given \p Name in the /// the symbol table. /// @returns the value associated with the \p Name - /// @brief Lookup a named Value. + /// Lookup a named Value. Value *lookup(StringRef Name) const { return vmap.lookup(Name); } /// @returns true iff the symbol table is empty - /// @brief Determine if the symbol table is empty + /// Determine if the symbol table is empty inline bool empty() const { return vmap.empty(); } - /// @brief The number of name/type pairs is returned. + /// The number of name/type pairs is returned. inline unsigned size() const { return unsigned(vmap.size()); } /// This function can be used from the debugger to display the /// content of the symbol table while debugging. - /// @brief Print out symbol table on stderr + /// Print out symbol table on stderr void dump() const; /// @} /// @name Iteration /// @{ - /// @brief Get an iterator that from the beginning of the symbol table. + /// Get an iterator that from the beginning of the symbol table. inline iterator begin() { return vmap.begin(); } - /// @brief Get a const_iterator that from the beginning of the symbol table. + /// Get a const_iterator that from the beginning of the symbol table. inline const_iterator begin() const { return vmap.begin(); } - /// @brief Get an iterator to the end of the symbol table. + /// Get an iterator to the end of the symbol table. inline iterator end() { return vmap.end(); } - /// @brief Get a const_iterator to the end of the symbol table. + /// Get a const_iterator to the end of the symbol table. inline const_iterator end() const { return vmap.end(); } /// @} @@ -111,7 +111,7 @@ private: /// This method adds the provided value \p N to the symbol table. The Value /// must have a name which is used to place the value in the symbol table. /// If the inserted name conflicts, this renames the value. - /// @brief Add a named value to the symbol table + /// Add a named value to the symbol table void reinsertValue(Value *V); /// createValueName - This method attempts to create a value name and insert diff --git a/contrib/llvm/include/llvm/IR/Verifier.h b/contrib/llvm/include/llvm/IR/Verifier.h index bc10f330bc8a..7255132e1e65 100644 --- a/contrib/llvm/include/llvm/IR/Verifier.h +++ b/contrib/llvm/include/llvm/IR/Verifier.h @@ -80,7 +80,7 @@ public: bool visitTBAAMetadata(Instruction &I, const MDNode *MD); }; -/// \brief Check a function for errors, useful for use when debugging a +/// 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, @@ -88,7 +88,7 @@ public: /// returned. bool verifyFunction(const Function &F, raw_ostream *OS = nullptr); -/// \brief Check a module for errors. +/// 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 @@ -124,7 +124,7 @@ public: /// "recovered" from by stripping the debug info. bool verifyModule(bool &BrokenDebugInfo, const Module &M, raw_ostream *OS); -/// \brief Create a verifier pass. +/// 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 diff --git a/contrib/llvm/include/llvm/IRReader/IRReader.h b/contrib/llvm/include/llvm/IRReader/IRReader.h index f5621647db06..bedde8954fbb 100644 --- a/contrib/llvm/include/llvm/IRReader/IRReader.h +++ b/contrib/llvm/include/llvm/IRReader/IRReader.h @@ -15,6 +15,7 @@ #ifndef LLVM_IRREADER_IRREADER_H #define LLVM_IRREADER_IRREADER_H +#include "llvm/ADT/StringRef.h" #include <memory> namespace llvm { @@ -40,9 +41,11 @@ getLazyIRFileModule(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, /// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier. /// This option should only be set to false by llvm-as /// for use inside the LLVM testuite! +/// \param DataLayoutString Override datalayout in the llvm assembly. std::unique_ptr<Module> parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err, LLVMContext &Context, - bool UpgradeDebugInfo = true); + bool UpgradeDebugInfo = true, + StringRef DataLayoutString = ""); /// If the given file holds a bitcode image, return a Module for it. /// Otherwise, attempt to parse it as LLVM Assembly and return a Module @@ -50,9 +53,11 @@ std::unique_ptr<Module> parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err, /// \param UpgradeDebugInfo Run UpgradeDebugInfo, which runs the Verifier. /// This option should only be set to false by llvm-as /// for use inside the LLVM testuite! +/// \param DataLayoutString Override datalayout in the llvm assembly. std::unique_ptr<Module> parseIRFile(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, - bool UpgradeDebugInfo = true); + bool UpgradeDebugInfo = true, + StringRef DataLayoutString = ""); } #endif diff --git a/contrib/llvm/include/llvm/InitializePasses.h b/contrib/llvm/include/llvm/InitializePasses.h index 4c79333f5d2e..d67b1d48f274 100644 --- a/contrib/llvm/include/llvm/InitializePasses.h +++ b/contrib/llvm/include/llvm/InitializePasses.h @@ -37,6 +37,9 @@ void initializeVectorization(PassRegistry&); /// Initialize all passes linked into the InstCombine library. void initializeInstCombine(PassRegistry&); +/// Initialize all passes linked into the AggressiveInstCombine library. +void initializeAggressiveInstCombine(PassRegistry&); + /// Initialize all passes linked into the IPO library. void initializeIPO(PassRegistry&); @@ -64,6 +67,7 @@ void initializeADCELegacyPassPass(PassRegistry&); void initializeAddDiscriminatorsLegacyPassPass(PassRegistry&); void initializeAddressSanitizerModulePass(PassRegistry&); void initializeAddressSanitizerPass(PassRegistry&); +void initializeAggressiveInstCombinerLegacyPassPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlignmentFromAssumptionsPass(PassRegistry&); void initializeAlwaysInlinerLegacyPassPass(PassRegistry&); @@ -73,34 +77,34 @@ void initializeAtomicExpandPass(PassRegistry&); void initializeBDCELegacyPassPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAAWrapperPassPass(PassRegistry&); -void initializeBlockExtractorPassPass(PassRegistry&); +void initializeBlockExtractorPass(PassRegistry &); void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&); void initializeBoundsCheckingLegacyPassPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); void initializeBranchProbabilityInfoWrapperPassPass(PassRegistry&); void initializeBranchRelaxationPass(PassRegistry&); void initializeBreakCriticalEdgesPass(PassRegistry&); -void initializeCallSiteSplittingLegacyPassPass(PassRegistry&); +void initializeBreakFalseDepsPass(PassRegistry&); void initializeCFGOnlyPrinterLegacyPassPass(PassRegistry&); void initializeCFGOnlyViewerLegacyPassPass(PassRegistry&); void initializeCFGPrinterLegacyPassPass(PassRegistry&); void initializeCFGSimplifyPassPass(PassRegistry&); void initializeCFGViewerLegacyPassPass(PassRegistry&); +void initializeCFIInstrInserterPass(PassRegistry&); void initializeCFLAndersAAWrapperPassPass(PassRegistry&); void initializeCFLSteensAAWrapperPassPass(PassRegistry&); void initializeCallGraphDOTPrinterPass(PassRegistry&); void initializeCallGraphPrinterLegacyPassPass(PassRegistry&); void initializeCallGraphViewerPass(PassRegistry&); void initializeCallGraphWrapperPassPass(PassRegistry&); +void initializeCallSiteSplittingLegacyPassPass(PassRegistry&); +void initializeCalledValuePropagationLegacyPassPass(PassRegistry &); void initializeCodeGenPreparePass(PassRegistry&); void initializeConstantHoistingLegacyPassPass(PassRegistry&); -void initializeCalledValuePropagationLegacyPassPass(PassRegistry &); void initializeConstantMergeLegacyPassPass(PassRegistry&); void initializeConstantPropagationPass(PassRegistry&); void initializeCorrelatedValuePropagationPass(PassRegistry&); void initializeCostModelAnalysisPass(PassRegistry&); -void initializeEntryExitInstrumenterPass(PassRegistry&); -void initializePostInlineEntryExitInstrumenterPass(PassRegistry&); void initializeCrossDSOCFIPass(PassRegistry&); void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); @@ -114,8 +118,8 @@ void initializeDemandedBitsWrapperPassPass(PassRegistry&); void initializeDependenceAnalysisPass(PassRegistry&); void initializeDependenceAnalysisWrapperPassPass(PassRegistry&); void initializeDetectDeadLanesPass(PassRegistry&); -void initializeDivergenceAnalysisPass(PassRegistry&); void initializeDivRemPairsLegacyPassPass(PassRegistry&); +void initializeDivergenceAnalysisPass(PassRegistry&); void initializeDomOnlyPrinterPass(PassRegistry&); void initializeDomOnlyViewerPass(PassRegistry&); void initializeDomPrinterPass(PassRegistry&); @@ -126,9 +130,12 @@ void initializeDwarfEHPreparePass(PassRegistry&); void initializeEarlyCSELegacyPassPass(PassRegistry&); void initializeEarlyCSEMemSSALegacyPassPass(PassRegistry&); void initializeEarlyIfConverterPass(PassRegistry&); +void initializeEarlyMachineLICMPass(PassRegistry&); +void initializeEarlyTailDuplicatePass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); void initializeEfficiencySanitizerPass(PassRegistry&); void initializeEliminateAvailableExternallyLegacyPassPass(PassRegistry&); +void initializeEntryExitInstrumenterPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); void initializeExpandMemCmpPassPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); @@ -154,21 +161,22 @@ void initializeGlobalOptLegacyPassPass(PassRegistry&); void initializeGlobalSplitPass(PassRegistry&); void initializeGlobalsAAWrapperPassPass(PassRegistry&); void initializeGuardWideningLegacyPassPass(PassRegistry&); +void initializeHWAddressSanitizerPass(PassRegistry&); void initializeIPCPPass(PassRegistry&); void initializeIPSCCPLegacyPassPass(PassRegistry&); +void initializeIRCELegacyPassPass(PassRegistry&); void initializeIRTranslatorPass(PassRegistry&); void initializeIVUsersWrapperPassPass(PassRegistry&); void initializeIfConverterPass(PassRegistry&); void initializeImplicitNullChecksPass(PassRegistry&); void initializeIndVarSimplifyLegacyPassPass(PassRegistry&); void initializeIndirectBrExpandPassPass(PassRegistry&); -void initializeInductiveRangeCheckEliminationPass(PassRegistry&); void initializeInferAddressSpacesPass(PassRegistry&); void initializeInferFunctionAttrsLegacyPassPass(PassRegistry&); void initializeInlineCostAnalysisPass(PassRegistry&); void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); -void initializeInstSimplifierPass(PassRegistry&); +void initializeInstSimplifyLegacyPassPass(PassRegistry &); void initializeInstrProfilingLegacyPassPass(PassRegistry&); void initializeInstructionCombiningPassPass(PassRegistry&); void initializeInstructionSelectPass(PassRegistry&); @@ -204,6 +212,7 @@ void initializeLoopDataPrefetchLegacyPassPass(PassRegistry&); void initializeLoopDeletionLegacyPassPass(PassRegistry&); void initializeLoopDistributeLegacyPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); +void initializeLoopGuardWideningLegacyPassPass(PassRegistry&); void initializeLoopIdiomRecognizeLegacyPassPass(PassRegistry&); void initializeLoopInfoWrapperPassPass(PassRegistry&); void initializeLoopInstSimplifyLegacyPassPass(PassRegistry&); @@ -216,6 +225,7 @@ void initializeLoopRotateLegacyPassPass(PassRegistry&); void initializeLoopSimplifyCFGLegacyPassPass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); void initializeLoopStrengthReducePass(PassRegistry&); +void initializeLoopUnrollAndJamPass(PassRegistry&); void initializeLoopUnrollPass(PassRegistry&); void initializeLoopUnswitchPass(PassRegistry&); void initializeLoopVectorizePass(PassRegistry&); @@ -229,6 +239,7 @@ void initializeLowerIntrinsicsPass(PassRegistry&); void initializeLowerInvokeLegacyPassPass(PassRegistry&); void initializeLowerSwitchPass(PassRegistry&); void initializeLowerTypeTestsPass(PassRegistry&); +void initializeMIRCanonicalizerPass(PassRegistry &); void initializeMIRPrintingPassPass(PassRegistry&); void initializeMachineBlockFrequencyInfoPass(PassRegistry&); void initializeMachineBlockPlacementPass(PassRegistry&); @@ -265,6 +276,7 @@ void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry&); void initializeMetaRenamerPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); void initializeModuleSummaryIndexWrapperPassPass(PassRegistry&); +void initializeMustExecutePrinterPass(PassRegistry&); void initializeNameAnonGlobalLegacyPassPass(PassRegistry&); void initializeNaryReassociateLegacyPassPass(PassRegistry&); void initializeNewGVNLegacyPassPass(PassRegistry&); @@ -286,6 +298,7 @@ void initializePartialInlinerLegacyPassPass(PassRegistry&); void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry&); void initializePatchableFunctionPass(PassRegistry&); void initializePeepholeOptimizerPass(PassRegistry&); +void initializePhiValuesWrapperPassPass(PassRegistry&); void initializePhysicalRegisterUsageInfoPass(PassRegistry&); void initializePlaceBackedgeSafepointsImplPass(PassRegistry&); void initializePlaceSafepointsPass(PassRegistry&); @@ -294,9 +307,11 @@ void initializePostDomOnlyViewerPass(PassRegistry&); void initializePostDomPrinterPass(PassRegistry&); void initializePostDomViewerPass(PassRegistry&); void initializePostDominatorTreeWrapperPassPass(PassRegistry&); +void initializePostInlineEntryExitInstrumenterPass(PassRegistry&); void initializePostMachineSchedulerPass(PassRegistry&); void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&); void initializePostRAHazardRecognizerPass(PassRegistry&); +void initializePostRAMachineSinkingPass(PassRegistry&); void initializePostRASchedulerPass(PassRegistry&); void initializePreISelIntrinsicLoweringLegacyPassPass(PassRegistry&); void initializePredicateInfoPrinterLegacyPassPass(PassRegistry&); @@ -308,11 +323,14 @@ void initializeProfileSummaryInfoWrapperPassPass(PassRegistry&); void initializePromoteLegacyPassPass(PassRegistry&); void initializePruneEHPass(PassRegistry&); void initializeRABasicPass(PassRegistry&); -void initializeRegAllocFastPass(PassRegistry&); void initializeRAGreedyPass(PassRegistry&); +void initializeReachingDefAnalysisPass(PassRegistry&); void initializeReassociateLegacyPassPass(PassRegistry&); +void initializeRegAllocFastPass(PassRegistry&); void initializeRegBankSelectPass(PassRegistry&); void initializeRegToMemPass(PassRegistry&); +void initializeRegUsageInfoCollectorPass(PassRegistry&); +void initializeRegUsageInfoPropagationPass(PassRegistry&); void initializeRegionInfoPassPass(PassRegistry&); void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); @@ -324,12 +342,12 @@ void initializeResetMachineFunctionPass(PassRegistry&); void initializeReversePostOrderFunctionAttrsLegacyPassPass(PassRegistry&); void initializeRewriteStatepointsForGCLegacyPassPass(PassRegistry &); void initializeRewriteSymbolsLegacyPassPass(PassRegistry&); -void initializeSafepointIRVerifierPass(PassRegistry&); void initializeSCCPLegacyPassPass(PassRegistry&); void initializeSCEVAAWrapperPassPass(PassRegistry&); void initializeSLPVectorizerPass(PassRegistry&); void initializeSROALegacyPassPass(PassRegistry&); void initializeSafeStackLegacyPassPass(PassRegistry&); +void initializeSafepointIRVerifierPass(PassRegistry&); void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&); void initializeSanitizerCoverageModulePass(PassRegistry&); void initializeScalarEvolutionWrapperPassPass(PassRegistry&); @@ -361,9 +379,8 @@ void initializeStripNonDebugSymbolsPass(PassRegistry&); void initializeStripNonLineTableDebugInfoPass(PassRegistry&); void initializeStripSymbolsPass(PassRegistry&); void initializeStructurizeCFGPass(PassRegistry&); -void initializeHWAddressSanitizerPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); -void initializeTailDuplicatePassPass(PassRegistry&); +void initializeTailDuplicatePass(PassRegistry&); void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); void initializeTargetTransformInfoWrapperPassPass(PassRegistry&); @@ -377,12 +394,12 @@ void initializeUnreachableMachineBlockElimPass(PassRegistry&); void initializeVerifierLegacyPassPass(PassRegistry&); void initializeVirtRegMapPass(PassRegistry&); void initializeVirtRegRewriterPass(PassRegistry&); +void initializeWasmEHPreparePass(PassRegistry&); void initializeWholeProgramDevirtPass(PassRegistry&); void initializeWinEHPreparePass(PassRegistry&); void initializeWriteBitcodePassPass(PassRegistry&); void initializeWriteThinLTOBitcodePass(PassRegistry&); void initializeXRayInstrumentationPass(PassRegistry&); -void initializeMIRCanonicalizerPass(PassRegistry &); } // end namespace llvm diff --git a/contrib/llvm/include/llvm/LTO/Caching.h b/contrib/llvm/include/llvm/LTO/Caching.h index 25c719a68b92..7201ab31f5b0 100644 --- a/contrib/llvm/include/llvm/LTO/Caching.h +++ b/contrib/llvm/include/llvm/LTO/Caching.h @@ -24,13 +24,8 @@ namespace lto { /// This type defines the callback to add a pre-existing native object file /// (e.g. in a cache). /// -/// Path is generally expected to be a valid path for the file at the point when -/// the AddBufferFn function is called, but clients should prefer to access MB -/// directly in order to avoid a potential race condition. -/// /// Buffer callbacks must be thread safe. -typedef std::function<void(unsigned Task, std::unique_ptr<MemoryBuffer> MB, - StringRef Path)> +typedef std::function<void(unsigned Task, std::unique_ptr<MemoryBuffer> MB)> AddBufferFn; /// Create a local file system cache which uses the given cache directory and diff --git a/contrib/llvm/include/llvm/LTO/Config.h b/contrib/llvm/include/llvm/LTO/Config.h index 4bd981c090b1..57bba5e34840 100644 --- a/contrib/llvm/include/llvm/LTO/Config.h +++ b/contrib/llvm/include/llvm/LTO/Config.h @@ -73,6 +73,14 @@ struct Config { /// Sample PGO profile path. std::string SampleProfile; + /// The directory to store .dwo files. + std::string DwoDir; + + /// The path to write a .dwo file to. This should generally only be used when + /// running an individual backend directly via thinBackend(), as otherwise + /// all .dwo files will be written to the same path. + std::string DwoPath; + /// Optimization remarks file path. std::string RemarksFilename = ""; @@ -82,6 +90,9 @@ struct Config { /// Whether to emit the pass manager debuggging informations. bool DebugPassManager = false; + /// Statistics output file path. + std::string StatsFile; + bool ShouldDiscardValueNames = true; DiagnosticHandlerFunction DiagHandler; diff --git a/contrib/llvm/include/llvm/LTO/LTO.h b/contrib/llvm/include/llvm/LTO/LTO.h index 2a2b59847281..7d6beab6b441 100644 --- a/contrib/llvm/include/llvm/LTO/LTO.h +++ b/contrib/llvm/include/llvm/LTO/LTO.h @@ -19,7 +19,6 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" -#include "llvm/Analysis/ObjectUtils.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/LTO/Config.h" @@ -210,10 +209,16 @@ ThinBackend createInProcessThinBackend(unsigned ParallelismLevel); /// appends ".thinlto.bc" and writes the index to that path. If /// ShouldEmitImportsFiles is true it also writes a list of imported files to a /// similar path with ".imports" appended instead. +/// LinkedObjectsFile is an output stream to write the list of object files for +/// the final ThinLTO linking. Can be nullptr. +/// OnWrite is callback which receives module identifier and notifies LTO user +/// that index file for the module (and optionally imports file) was created. +using IndexWriteCallback = std::function<void(const std::string &)>; ThinBackend createWriteIndexesThinBackend(std::string OldPrefix, std::string NewPrefix, bool ShouldEmitImportsFiles, - std::string LinkedObjectsFile); + raw_fd_ostream *LinkedObjectsFile, + IndexWriteCallback OnWrite); /// This class implements a resolution-based interface to LLVM's LTO /// functionality. It supports regular LTO, parallel LTO code generation and @@ -320,6 +325,14 @@ private: bool UnnamedAddr = true; + /// True if module contains the prevailing definition. + bool Prevailing = false; + + /// Returns true if module contains the prevailing definition and symbol is + /// an IR symbol. For example when module-level inline asm block is used, + /// symbol can be prevailing in module but have no IR name. + bool isPrevailingIRSymbol() const { return Prevailing && !IRName.empty(); } + /// This field keeps track of the partition number of this global. The /// regular LTO object is partition 0, while each ThinLTO object has its own /// partition number from 1 onwards. diff --git a/contrib/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/contrib/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h index d794535700e5..b32a972542c8 100644 --- a/contrib/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h +++ b/contrib/llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h @@ -131,7 +131,8 @@ public: * To avoid filling the disk space, a few knobs are provided: * - The pruning interval limit the frequency at which the garbage collector * will try to scan the cache directory to prune it from expired entries. - * Setting to -1 disable the pruning (default). + * Setting to -1 disable the pruning (default). Setting to 0 will force + * pruning to occur. * - The pruning expiration time indicates to the garbage collector how old * an entry needs to be to be removed. * - Finally, the garbage collector can be instructed to prune the cache till @@ -149,10 +150,9 @@ public: void setCacheDir(std::string Path) { CacheOptions.Path = std::move(Path); } /// Cache policy: interval (seconds) between two prunes of the cache. Set to a - /// negative value to disable pruning. A value of 0 will be ignored. + /// negative value to disable pruning. A value of 0 will force pruning to + /// occur. void setCachePruningInterval(int Interval) { - if (Interval == 0) - return; if(Interval < 0) CacheOptions.Policy.Interval.reset(); else @@ -168,8 +168,8 @@ public: /** * Sets the maximum cache size that can be persistent across build, in terms - * of percentage of the available space on the the disk. Set to 100 to - * indicate no limit, 50 to indicate that the cache size will not be left over + * of percentage of the available space on the disk. Set to 100 to indicate + * no limit, 50 to indicate that the cache size will not be left over * half the available space. A value over 100 will be reduced to 100, and a * value of 0 will be ignored. * @@ -184,6 +184,21 @@ public: CacheOptions.Policy.MaxSizePercentageOfAvailableSpace = Percentage; } + /// Cache policy: the maximum size for the cache directory in bytes. A value + /// over the amount of available space on the disk will be reduced to the + /// amount of available space. A value of 0 will be ignored. + void setCacheMaxSizeBytes(unsigned MaxSizeBytes) { + if (MaxSizeBytes) + CacheOptions.Policy.MaxSizeBytes = MaxSizeBytes; + } + + /// Cache policy: the maximum number of files in the cache directory. A value + /// of 0 will be ignored. + void setCacheMaxSizeFiles(unsigned MaxSizeFiles) { + if (MaxSizeFiles) + CacheOptions.Policy.MaxSizeFiles = MaxSizeFiles; + } + /**@}*/ /// Set the path to a directory where to save temporaries at various stages of diff --git a/contrib/llvm/include/llvm/LinkAllPasses.h b/contrib/llvm/include/llvm/LinkAllPasses.h index 39d1ec6cffb5..bd432c58b613 100644 --- a/contrib/llvm/include/llvm/LinkAllPasses.h +++ b/contrib/llvm/include/llvm/LinkAllPasses.h @@ -39,14 +39,18 @@ #include "llvm/IR/Function.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/Support/Valgrind.h" +#include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/FunctionAttrs.h" +#include "llvm/Transforms/InstCombine/InstCombine.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Instrumentation/BoundsChecking.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVN.h" +#include "llvm/Transforms/Scalar/InstSimplifyPass.h" +#include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Vectorize.h" @@ -64,6 +68,7 @@ namespace { (void) llvm::createAAEvalPass(); (void) llvm::createAggressiveDCEPass(); + (void) llvm::createAggressiveInstCombinerPass(); (void) llvm::createBitTrackingDCEPass(); (void) llvm::createArgumentPromotionPass(); (void) llvm::createAlignmentFromAssumptionsPass(); @@ -107,10 +112,12 @@ namespace { (void) llvm::createGlobalOptimizerPass(); (void) llvm::createGlobalsAAWrapperPass(); (void) llvm::createGuardWideningPass(); + (void) llvm::createLoopGuardWideningPass(); (void) llvm::createIPConstantPropagationPass(); (void) llvm::createIPSCCPPass(); (void) llvm::createInductiveRangeCheckEliminationPass(); (void) llvm::createIndVarSimplifyPass(); + (void) llvm::createInstSimplifyLegacyPass(); (void) llvm::createInstructionCombiningPass(); (void) llvm::createInternalizePass(); (void) llvm::createLCSSAPass(); @@ -125,6 +132,7 @@ namespace { (void) llvm::createLoopStrengthReducePass(); (void) llvm::createLoopRerollPass(); (void) llvm::createLoopUnrollPass(); + (void) llvm::createLoopUnrollAndJamPass(); (void) llvm::createLoopUnswitchPass(); (void) llvm::createLoopVersioningLICMPass(); (void) llvm::createLoopIdiomPass(); @@ -195,7 +203,6 @@ namespace { (void) llvm::createLowerAtomicPass(); (void) llvm::createCorrelatedValuePropagationPass(); (void) llvm::createMemDepPrinter(); - (void) llvm::createInstructionSimplifierPass(); (void) llvm::createLoopVectorizePass(); (void) llvm::createSLPVectorizerPass(); (void) llvm::createLoadStoreVectorizerPass(); @@ -207,6 +214,7 @@ namespace { (void) llvm::createRewriteSymbolsPass(); (void) llvm::createStraightLineStrengthReducePass(); (void) llvm::createMemDerefPrinter(); + (void) llvm::createMustExecutePrinter(); (void) llvm::createFloat2IntPass(); (void) llvm::createEliminateAvailableExternallyPass(); (void) llvm::createScalarizeMaskedMemIntrinPass(); diff --git a/contrib/llvm/include/llvm/Linker/Linker.h b/contrib/llvm/include/llvm/Linker/Linker.h index 628e0112bd9d..7776c720ec53 100644 --- a/contrib/llvm/include/llvm/Linker/Linker.h +++ b/contrib/llvm/include/llvm/Linker/Linker.h @@ -34,7 +34,7 @@ public: Linker(Module &M); - /// \brief Link \p Src into the composite. + /// Link \p Src into the composite. /// /// Passing OverrideSymbols as true will have symbols from Src /// shadow those in the Dest. diff --git a/contrib/llvm/include/llvm/MC/MCAsmBackend.h b/contrib/llvm/include/llvm/MC/MCAsmBackend.h index ef2007ff6920..030d3c05aa5a 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmBackend.h +++ b/contrib/llvm/include/llvm/MC/MCAsmBackend.h @@ -16,6 +16,7 @@ #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCFragment.h" +#include "llvm/Support/Endian.h" #include <cstdint> #include <memory> @@ -29,6 +30,7 @@ struct MCFixupKindInfo; class MCFragment; class MCInst; class MCObjectStreamer; +class MCObjectTargetWriter; class MCObjectWriter; struct MCCodePaddingContext; class MCRelaxableFragment; @@ -41,21 +43,31 @@ class MCAsmBackend { std::unique_ptr<MCCodePadder> CodePadder; protected: // Can only create subclasses. - MCAsmBackend(); - MCAsmBackend(std::unique_ptr<MCCodePadder> TargetCodePadder); + MCAsmBackend(support::endianness Endian); public: MCAsmBackend(const MCAsmBackend &) = delete; MCAsmBackend &operator=(const MCAsmBackend &) = delete; virtual ~MCAsmBackend(); + const support::endianness Endian; + /// lifetime management virtual void reset() {} /// Create a new MCObjectWriter instance for use by the assembler backend to /// emit the final object file. - virtual std::unique_ptr<MCObjectWriter> - createObjectWriter(raw_pwrite_stream &OS) const = 0; + std::unique_ptr<MCObjectWriter> + createObjectWriter(raw_pwrite_stream &OS) const; + + /// Create an MCObjectWriter that writes two object files: a .o file which is + /// linked into the final program and a .dwo file which is used by debuggers. + /// This function is only supported with ELF targets. + std::unique_ptr<MCObjectWriter> + createDwoObjectWriter(raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS) const; + + virtual std::unique_ptr<MCObjectTargetWriter> + createObjectTargetWriter() const = 0; /// \name Target Fixup Interfaces /// @{ @@ -80,9 +92,16 @@ public: /// the offset specified by the fixup and following the fixup kind as /// appropriate. Errors (such as an out of range fixup value) should be /// reported via \p Ctx. + /// The \p STI is present only for fragments of type MCRelaxableFragment and + /// MCDataFragment with hasInstructions() == true. virtual void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef<char> Data, - uint64_t Value, bool IsResolved) const = 0; + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const = 0; + + /// Check whether the given target requires emitting differences of two + /// symbols as a set of relocations. + virtual bool requiresDiffExpressionRelocations() const { return false; } /// @} @@ -92,14 +111,18 @@ public: /// Check whether the given instruction may need relaxation. /// /// \param Inst - The instruction to test. - virtual bool mayNeedRelaxation(const MCInst &Inst) const = 0; + /// \param STI - The MCSubtargetInfo in effect when the instruction was + /// encoded. + virtual bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const = 0; /// Target specific predicate for whether a given fixup requires the /// associated instruction to be relaxed. virtual bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved, uint64_t Value, const MCRelaxableFragment *DF, - const MCAsmLayout &Layout) const; + const MCAsmLayout &Layout, + const bool WasForced) const; /// Simple predicate for targets where !Resolved implies requiring relaxation virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, @@ -127,7 +150,7 @@ public: /// target cannot generate such a sequence, it should return an error. /// /// \return - True on success. - virtual bool writeNopData(uint64_t Count, MCObjectWriter *OW) const = 0; + virtual bool writeNopData(raw_ostream &OS, uint64_t Count) const = 0; /// Give backend an opportunity to finish layout after relaxation virtual void finishLayout(MCAssembler const &Asm, @@ -136,7 +159,7 @@ public: /// Handle any target-specific assembler flags. By default, do nothing. virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} - /// \brief Generate the compact unwind encoding for the CFI instructions. + /// Generate the compact unwind encoding for the CFI instructions. virtual uint32_t generateCompactUnwindEncoding(ArrayRef<MCCFIInstruction>) const { return 0; @@ -173,7 +196,7 @@ public: /// \param PF The fragment to relax. /// \param Layout Code layout information. /// - /// \returns true iff any relaxation occured. + /// \returns true iff any relaxation occurred. bool relaxFragment(MCPaddingFragment *PF, MCAsmLayout &Layout); }; diff --git a/contrib/llvm/include/llvm/MC/MCAsmInfo.h b/contrib/llvm/include/llvm/MC/MCAsmInfo.h index c538c46fc072..120fb8fa7492 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmInfo.h +++ b/contrib/llvm/include/llvm/MC/MCAsmInfo.h @@ -84,6 +84,15 @@ protected: /// directive for emitting thread local BSS Symbols. Default is false. bool HasMachoTBSSDirective = false; + /// True if this is a non-GNU COFF target. The COFF port of the GNU linker + /// doesn't handle associative comdats in the way that we would like to use + /// them. + bool HasCOFFAssociativeComdats = false; + + /// True if this is a non-GNU COFF target. For GNU targets, we don't generate + /// constants into comdat sections. + bool HasCOFFComdatConstants = false; + /// This is the maximum possible length of an instruction, which is needed to /// compute the size of an inline asm. Defaults to 4. unsigned MaxInstLength = 4; @@ -344,6 +353,10 @@ protected: /// For example, foo(plt) instead of foo@plt. Defaults to false. bool UseParensForSymbolVariant = false; + /// True if the target supports flags in ".loc" directive, false if only + /// location is allowed. + bool SupportsExtendedDwarfLocDirective = true; + //===--- Prologue State ----------------------------------------------===// std::vector<MCCFIInstruction> InitialFrameState; @@ -416,7 +429,7 @@ public: return nullptr; } - /// \brief True if the section is atomized using the symbols in it. + /// 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). @@ -459,6 +472,8 @@ public: bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } + bool hasCOFFAssociativeComdats() const { return HasCOFFAssociativeComdats; } + bool hasCOFFComdatConstants() const { return HasCOFFComdatConstants; } unsigned getMaxInstLength() const { return MaxInstLength; } unsigned getMinInstAlignment() const { return MinInstAlignment; } bool getDollarIsPC() const { return DollarIsPC; } @@ -579,6 +594,9 @@ public: bool doDwarfFDESymbolsUseAbsDiff() const { return DwarfFDESymbolsUseAbsDiff; } bool useDwarfRegNumForCFI() const { return DwarfRegNumForCFI; } bool useParensForSymbolVariant() const { return UseParensForSymbolVariant; } + bool supportsExtendedDwarfLocDirective() const { + return SupportsExtendedDwarfLocDirective; + } void addInitialFrameState(const MCCFIInstruction &Inst) { InitialFrameState.push_back(Inst); diff --git a/contrib/llvm/include/llvm/MC/MCAsmLayout.h b/contrib/llvm/include/llvm/MC/MCAsmLayout.h index 1b20d5b804a4..b711db319302 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmLayout.h +++ b/contrib/llvm/include/llvm/MC/MCAsmLayout.h @@ -37,11 +37,11 @@ class MCAsmLayout { /// lower ordinal will be valid. mutable DenseMap<const MCSection *, MCFragment *> LastValidFragment; - /// \brief Make sure that the layout for the given fragment is valid, lazily + /// Make sure that the layout for the given fragment is valid, lazily /// computing it if necessary. void ensureValid(const MCFragment *F) const; - /// \brief Is the layout for this fragment valid? + /// Is the layout for this fragment valid? bool isFragmentValid(const MCFragment *F) const; public: @@ -50,12 +50,12 @@ public: /// Get the assembler object this is a layout for. MCAssembler &getAssembler() const { return Assembler; } - /// \brief Invalidate the fragments starting with F because it has been + /// Invalidate the fragments starting with F because it has been /// resized. The fragment's size should have already been updated, but /// its bundle padding will be recomputed. void invalidateFragmentsFrom(MCFragment *F); - /// \brief Perform layout for a single fragment, assuming that the previous + /// Perform layout for a single fragment, assuming that the previous /// fragment has already been laid out correctly, and the parent section has /// been initialized. void layoutFragment(MCFragment *Fragment); @@ -72,31 +72,31 @@ public: /// \name Fragment Layout Data /// @{ - /// \brief Get the offset of the given fragment inside its containing section. + /// Get the offset of the given fragment inside its containing section. uint64_t getFragmentOffset(const MCFragment *F) const; /// @} /// \name Utility Functions /// @{ - /// \brief Get the address space size of the given section, as it effects + /// Get the address space size of the given section, as it effects /// layout. This may differ from the size reported by \see getSectionSize() by /// not including section tail padding. uint64_t getSectionAddressSize(const MCSection *Sec) const; - /// \brief Get the data size of the given section, as emitted to the object + /// Get the data size of the given section, as emitted to the object /// file. This may include additional padding, or be 0 for virtual sections. uint64_t getSectionFileSize(const MCSection *Sec) const; - /// \brief Get the offset of the given symbol, as computed in the current + /// Get the offset of the given symbol, as computed in the current /// layout. /// \return True on success. bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const; - /// \brief Variant that reports a fatal error if the offset is not computable. + /// Variant that reports a fatal error if the offset is not computable. uint64_t getSymbolOffset(const MCSymbol &S) const; - /// \brief If this symbol is equivalent to A + Constant, return A. + /// If this symbol is equivalent to A + Constant, return A. const MCSymbol *getBaseSymbol(const MCSymbol &Symbol) const; /// @} diff --git a/contrib/llvm/include/llvm/MC/MCAsmMacro.h b/contrib/llvm/include/llvm/MC/MCAsmMacro.h index dac8d1a80050..09b32c7ea333 100644 --- a/contrib/llvm/include/llvm/MC/MCAsmMacro.h +++ b/contrib/llvm/include/llvm/MC/MCAsmMacro.h @@ -10,10 +10,124 @@ #ifndef LLVM_MC_MCASMMACRO_H #define LLVM_MC_MCASMMACRO_H -#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/SMLoc.h" +#include <vector> namespace llvm { +/// Target independent representation for an assembler token. +class AsmToken { +public: + enum TokenKind { + // Markers + Eof, Error, + + // String values. + Identifier, + String, + + // Integer values. + Integer, + BigNum, // larger than 64 bits + + // Real values. + Real, + + // Comments + Comment, + HashDirective, + // No-value. + EndOfStatement, + Colon, + Space, + Plus, Minus, Tilde, + Slash, // '/' + BackSlash, // '\' + LParen, RParen, LBrac, RBrac, LCurly, RCurly, + Star, Dot, Comma, Dollar, Equal, EqualEqual, + + Pipe, PipePipe, Caret, + Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash, + Less, LessEqual, LessLess, LessGreater, + Greater, GreaterEqual, GreaterGreater, At, + + // MIPS unary expression operators such as %neg. + PercentCall16, PercentCall_Hi, PercentCall_Lo, PercentDtprel_Hi, + PercentDtprel_Lo, PercentGot, PercentGot_Disp, PercentGot_Hi, PercentGot_Lo, + PercentGot_Ofst, PercentGot_Page, PercentGottprel, PercentGp_Rel, PercentHi, + PercentHigher, PercentHighest, PercentLo, PercentNeg, PercentPcrel_Hi, + PercentPcrel_Lo, PercentTlsgd, PercentTlsldm, PercentTprel_Hi, + PercentTprel_Lo + }; + +private: + TokenKind Kind; + + /// A reference to the entire token contents; this is always a pointer into + /// a memory buffer owned by the source manager. + StringRef Str; + + APInt IntVal; + +public: + AsmToken() = default; + AsmToken(TokenKind Kind, StringRef Str, APInt IntVal) + : Kind(Kind), Str(Str), IntVal(std::move(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; } + bool isNot(TokenKind K) const { return Kind != K; } + + SMLoc getLoc() const; + SMLoc getEndLoc() const; + SMRange getLocRange() const; + + /// Get the contents of a string token (without quotes). + StringRef getStringContents() const { + assert(Kind == String && "This token isn't a string!"); + return Str.slice(1, Str.size() - 1); + } + + /// Get the identifier string for the current token, which should be an + /// identifier or a string. This gets the portion of the string which should + /// be used as the identifier, e.g., it does not include the quotes on + /// strings. + StringRef getIdentifier() const { + if (Kind == Identifier) + return getString(); + return getStringContents(); + } + + /// Get the string for the current token, this includes all characters (for + /// example, the quotes on strings) in the token. + /// + /// The returned StringRef points into the source manager's memory buffer, and + /// is safe to store across calls to Lex(). + StringRef getString() const { return Str; } + + // FIXME: Don't compute this in advance, it makes every token larger, and is + // also not generally what we want (it is nicer for recovery etc. to lex 123br + // 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; + } + + void dump(raw_ostream &OS) const; + void dump() const { dump(dbgs()); } +}; + struct MCAsmMacroParameter { StringRef Name; std::vector<AsmToken> Value; @@ -21,6 +135,9 @@ struct MCAsmMacroParameter { bool Vararg = false; MCAsmMacroParameter() = default; + + void dump() const { dump(dbgs()); } + void dump(raw_ostream &OS) const; }; typedef std::vector<MCAsmMacroParameter> MCAsmMacroParameters; @@ -32,6 +149,9 @@ struct MCAsmMacro { public: MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P) : Name(N), Body(B), Parameters(std::move(P)) {} + + void dump() const { dump(dbgs()); } + void dump(raw_ostream &OS) const; }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCAssembler.h b/contrib/llvm/include/llvm/MC/MCAssembler.h index b91b04414021..0f9499d705e4 100644 --- a/contrib/llvm/include/llvm/MC/MCAssembler.h +++ b/contrib/llvm/include/llvm/MC/MCAssembler.h @@ -99,11 +99,11 @@ public: private: MCContext &Context; - MCAsmBackend &Backend; + std::unique_ptr<MCAsmBackend> Backend; - MCCodeEmitter &Emitter; + std::unique_ptr<MCCodeEmitter> Emitter; - MCObjectWriter &Writer; + std::unique_ptr<MCObjectWriter> Writer; SectionListType Sections; @@ -130,7 +130,7 @@ private: // refactoring too. mutable SmallPtrSet<const MCSymbol *, 32> ThumbFuncs; - /// \brief The bundle alignment size currently set in the assembler. + /// The bundle alignment size currently set in the assembler. /// /// By default it's 0, which means bundling is disabled. unsigned BundleAlignSize; @@ -162,12 +162,14 @@ private: /// evaluates to. /// \param Value [out] On return, the value of the fixup as currently laid /// out. + /// \param WasForced [out] On return, the value in the fixup is set to the + /// correct value if WasForced is true, even if evaluateFixup returns false. /// \return Whether the fixup value was fully resolved. This is true if the /// \p Value result is fixed, otherwise the value may change due to /// relocation. bool evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, - uint64_t &Value) const; + uint64_t &Value, bool &WasForced) const; /// Check whether a fixup can be satisfied, or whether it needs to be relaxed /// (increased in size, in order to hold its value correctly). @@ -178,11 +180,11 @@ private: bool fragmentNeedsRelaxation(const MCRelaxableFragment *IF, const MCAsmLayout &Layout) const; - /// \brief Perform one layout iteration and return true if any offsets + /// Perform one layout iteration and return true if any offsets /// were adjusted. bool layoutOnce(MCAsmLayout &Layout); - /// \brief Perform one layout iteration of the given section and return true + /// Perform one layout iteration of the given section and return true /// if any offsets were adjusted. bool layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec); @@ -214,8 +216,9 @@ public: // concrete and require clients to pass in a target like object. The other // option is to make this abstract, and have targets provide concrete // implementations as we do with AsmParser. - MCAssembler(MCContext &Context, MCAsmBackend &Backend, - MCCodeEmitter &Emitter, MCObjectWriter &Writer); + MCAssembler(MCContext &Context, std::unique_ptr<MCAsmBackend> Backend, + std::unique_ptr<MCCodeEmitter> Emitter, + std::unique_ptr<MCObjectWriter> Writer); MCAssembler(const MCAssembler &) = delete; MCAssembler &operator=(const MCAssembler &) = delete; ~MCAssembler(); @@ -235,8 +238,8 @@ public: /// defining a separate atom. bool isSymbolLinkerVisible(const MCSymbol &SD) const; - /// Emit the section contents using the given object writer. - void writeSectionData(const MCSection *Section, + /// Emit the section contents to \p OS. + void writeSectionData(raw_ostream &OS, const MCSection *Section, const MCAsmLayout &Layout) const; /// Check whether a given symbol has been flagged with .thumb_func. @@ -274,11 +277,17 @@ public: MCContext &getContext() const { return Context; } - MCAsmBackend &getBackend() const { return Backend; } + MCAsmBackend *getBackendPtr() const { return Backend.get(); } - MCCodeEmitter &getEmitter() const { return Emitter; } + MCCodeEmitter *getEmitterPtr() const { return Emitter.get(); } - MCObjectWriter &getWriter() const { return Writer; } + MCObjectWriter *getWriterPtr() const { return Writer.get(); } + + MCAsmBackend &getBackend() const { return *Backend; } + + MCCodeEmitter &getEmitter() const { return *Emitter; } + + MCObjectWriter &getWriter() const { return *Writer; } MCDwarfLineTableParams getDWARFLinetableParams() const { return LTParams; } void setDWARFLinetableParams(MCDwarfLineTableParams P) { LTParams = P; } @@ -409,6 +418,13 @@ public: const MCLOHContainer &getLOHContainer() const { return const_cast<MCAssembler *>(this)->getLOHContainer(); } + + struct CGProfileEntry { + const MCSymbolRefExpr *From; + const MCSymbolRefExpr *To; + uint64_t Count; + }; + std::vector<CGProfileEntry> CGProfile; /// @} /// \name Backend Data Access /// @{ @@ -424,21 +440,22 @@ public: FileNames.push_back(FileName); } - /// \brief Write the necessary bundle padding to the given object writer. + /// Write the necessary bundle padding to \p OS. /// Expects a fragment \p F containing instructions and its size \p FSize. - void writeFragmentPadding(const MCFragment &F, uint64_t FSize, - MCObjectWriter *OW) const; + void writeFragmentPadding(raw_ostream &OS, const MCEncodedFragment &F, + uint64_t FSize) const; /// @} void dump() const; }; -/// \brief Compute the amount of padding required before the fragment \p F to +/// Compute the amount of padding required before the fragment \p F to /// obey bundling restrictions, where \p FOffset is the fragment's offset in /// its section and \p FSize is the fragment's size. -uint64_t computeBundlePadding(const MCAssembler &Assembler, const MCFragment *F, - uint64_t FOffset, uint64_t FSize); +uint64_t computeBundlePadding(const MCAssembler &Assembler, + const MCEncodedFragment *F, uint64_t FOffset, + uint64_t FSize); } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCCodePadder.h b/contrib/llvm/include/llvm/MC/MCCodePadder.h index 1e91198597c3..4dde6bf59272 100644 --- a/contrib/llvm/include/llvm/MC/MCCodePadder.h +++ b/contrib/llvm/include/llvm/MC/MCCodePadder.h @@ -28,7 +28,6 @@ typedef SmallVector<const MCPaddingFragment *, 8> MCPFRange; struct MCCodePaddingContext { bool IsPaddingActive; - bool IsBasicBlockInsideInnermostLoop; bool IsBasicBlockReachableViaFallthrough; bool IsBasicBlockReachableViaBranch; }; @@ -119,7 +118,7 @@ public: /// \param Fragment The fragment to relax. /// \param Layout Code layout information. /// - /// \returns true iff any relaxation occured. + /// \returns true iff any relaxation occurred. bool relaxFragment(MCPaddingFragment *Fragment, MCAsmLayout &Layout); }; diff --git a/contrib/llvm/include/llvm/MC/MCCodeView.h b/contrib/llvm/include/llvm/MC/MCCodeView.h index c8f14515ed34..1d9e3c6698cf 100644 --- a/contrib/llvm/include/llvm/MC/MCCodeView.h +++ b/contrib/llvm/include/llvm/MC/MCCodeView.h @@ -27,7 +27,7 @@ class MCObjectStreamer; class MCStreamer; class CodeViewContext; -/// \brief Instances of this class represent the information from a +/// Instances of this class represent the information from a /// .cv_loc directive. class MCCVLoc { uint32_t FunctionId; @@ -50,13 +50,13 @@ private: // CodeViewContext manages these public: unsigned getFunctionId() const { return FunctionId; } - /// \brief Get the FileNum of this MCCVLoc. + /// Get the FileNum of this MCCVLoc. unsigned getFileNum() const { return FileNum; } - /// \brief Get the Line of this MCCVLoc. + /// Get the Line of this MCCVLoc. unsigned getLine() const { return Line; } - /// \brief Get the Column of this MCCVLoc. + /// Get the Column of this MCCVLoc. unsigned getColumn() const { return Column; } bool isPrologueEnd() const { return PrologueEnd; } @@ -64,13 +64,13 @@ public: void setFunctionId(unsigned FID) { FunctionId = FID; } - /// \brief Set the FileNum of this MCCVLoc. + /// Set the FileNum of this MCCVLoc. void setFileNum(unsigned fileNum) { FileNum = fileNum; } - /// \brief Set the Line of this MCCVLoc. + /// Set the Line of this MCCVLoc. void setLine(unsigned line) { Line = line; } - /// \brief Set the Column of this MCCVLoc. + /// Set the Column of this MCCVLoc. void setColumn(unsigned column) { assert(column <= UINT16_MAX); Column = column; @@ -80,7 +80,7 @@ public: void setIsStmt(bool IS) { IsStmt = IS; } }; -/// \brief Instances of this class represent the line information for +/// Instances of this class represent the line information for /// the CodeView line table entries. Which is created after a machine /// instruction is assembled and uses an address from a temporary label /// created at the current address in the current section and the info from @@ -201,7 +201,7 @@ public: bool isValidCVFileNumber(unsigned FileNumber); - /// \brief Add a line entry. + /// Add a line entry. void addLineEntry(const MCCVLineEntry &LineEntry); std::vector<MCCVLineEntry> getFunctionLineEntries(unsigned FuncId); diff --git a/contrib/llvm/include/llvm/MC/MCContext.h b/contrib/llvm/include/llvm/MC/MCContext.h index 358f67c4db6d..a712e2d95cbc 100644 --- a/contrib/llvm/include/llvm/MC/MCContext.h +++ b/contrib/llvm/include/llvm/MC/MCContext.h @@ -11,6 +11,7 @@ #define LLVM_MC_MCCONTEXT_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -24,6 +25,8 @@ #include "llvm/MC/SectionKind.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MD5.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -134,6 +137,9 @@ namespace llvm { /// The compilation directory to use for DW_AT_comp_dir. SmallString<128> CompilationDir; + /// Prefix replacement map for source file information. + std::map<const std::string, const std::string> DebugPrefixMap; + /// The main file name if passed in explicitly. std::string MainFileName; @@ -269,7 +275,7 @@ namespace llvm { unsigned UniqueID, const MCSymbolELF *Associated); - /// \brief Map of currently defined macros. + /// Map of currently defined macros. StringMap<MCAsmMacro> MacroMap; public: @@ -292,6 +298,10 @@ namespace llvm { CodeViewContext &getCVContext(); + /// Clear the current cv_loc, if there is one. Avoids lazily creating a + /// CodeViewContext if none is needed. + void clearCVLocSeen(); + void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; } void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; } @@ -335,7 +345,7 @@ namespace llvm { /// Gets a symbol that will be defined to the final stack offset of a local /// variable after codegen. /// - /// \param Idx - The index of a local variable passed to @llvm.localescape. + /// \param Idx - The index of a local variable passed to \@llvm.localescape. MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx); MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName); @@ -475,25 +485,39 @@ namespace llvm { /// \name Dwarf Management /// @{ - /// \brief Get the compilation directory for DW_AT_comp_dir + /// Get the compilation directory for DW_AT_comp_dir /// The compilation directory should be set with \c setCompilationDir before /// calling this function. If it is unset, an empty string will be returned. StringRef getCompilationDir() const { return CompilationDir; } - /// \brief Set the compilation directory for DW_AT_comp_dir + /// Set the compilation directory for DW_AT_comp_dir void setCompilationDir(StringRef S) { CompilationDir = S.str(); } - /// \brief Get the main file name for use in error messages and debug + /// Get the debug prefix map. + const std::map<const std::string, const std::string> & + getDebugPrefixMap() const { + return DebugPrefixMap; + } + + /// Add an entry to the debug prefix map. + void addDebugPrefixMapEntry(const std::string &From, const std::string &To); + + // Remaps all debug directory paths in-place as per the debug prefix map. + void RemapDebugPaths(); + + /// Get the main file name for use in error messages and debug /// info. This can be set to ensure we've got the correct file name /// after preprocessing or for -save-temps. const std::string &getMainFileName() const { return MainFileName; } - /// \brief Set the main file name and override the default. + /// Set the main file name and override the default. void setMainFileName(StringRef S) { MainFileName = S; } /// Creates an entry in the dwarf file and directory tables. - unsigned getDwarfFile(StringRef Directory, StringRef FileName, - unsigned FileNumber, unsigned CUID); + Expected<unsigned> getDwarfFile(StringRef Directory, StringRef FileName, + unsigned FileNumber, + MD5::MD5Result *Checksum, + Optional<StringRef> Source, unsigned CUID); bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0); @@ -532,8 +556,18 @@ namespace llvm { DwarfCompileUnitID = CUIndex; } - void setMCLineTableCompilationDir(unsigned CUID, StringRef CompilationDir) { - getMCDwarfLineTable(CUID).setCompilationDir(CompilationDir); + /// Specifies the "root" file and directory of the compilation unit. + /// These are "file 0" and "directory 0" in DWARF v5. + void setMCLineTableRootFile(unsigned CUID, StringRef CompilationDir, + StringRef Filename, MD5::MD5Result *Checksum, + Optional<StringRef> Source) { + getMCDwarfLineTable(CUID).setRootFile(CompilationDir, Filename, Checksum, + Source); + } + + /// Reports whether MD5 checksum usage is consistent (all-or-none). + bool isDwarfMD5UsageConsistent(unsigned CUID) const { + return getMCDwarfLineTable(CUID).isMD5UsageConsistent(); } /// Saves the information from the currently parsed dwarf .loc directive @@ -639,7 +673,7 @@ namespace llvm { // operator new and delete aren't allowed inside namespaces. // The throw specifications are mandated by the standard. -/// \brief Placement new for using the MCContext's allocator. +/// Placement new for using the MCContext's allocator. /// /// This placement form of operator new uses the MCContext's allocator for /// obtaining memory. It is a non-throwing new, which means that it returns @@ -665,7 +699,7 @@ inline void *operator new(size_t Bytes, llvm::MCContext &C, size_t Alignment = 8) noexcept { return C.allocate(Bytes, Alignment); } -/// \brief Placement delete companion to the new above. +/// Placement delete companion to the new above. /// /// This operator is just a companion to the new above. There is no way of /// invoking it directly; see the new operator for more details. This operator @@ -699,7 +733,7 @@ inline void *operator new[](size_t Bytes, llvm::MCContext &C, return C.allocate(Bytes, Alignment); } -/// \brief Placement delete[] companion to the new[] above. +/// Placement delete[] companion to the new[] above. /// /// This operator is just a companion to the new[] above. There is no way of /// invoking it directly; see the new[] operator for more details. This operator diff --git a/contrib/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h b/contrib/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h index bd3e5d4638e5..df909a0dccd3 100644 --- a/contrib/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h +++ b/contrib/llvm/include/llvm/MC/MCDisassembler/MCExternalSymbolizer.h @@ -22,7 +22,7 @@ namespace llvm { -/// \brief Symbolize using user-provided, C API, callbacks. +/// Symbolize using user-provided, C API, callbacks. /// /// See llvm-c/Disassembler.h. class MCExternalSymbolizer : public MCSymbolizer { diff --git a/contrib/llvm/include/llvm/MC/MCDisassembler/MCRelocationInfo.h b/contrib/llvm/include/llvm/MC/MCDisassembler/MCRelocationInfo.h index 7836e886c303..6030ae660d38 100644 --- a/contrib/llvm/include/llvm/MC/MCDisassembler/MCRelocationInfo.h +++ b/contrib/llvm/include/llvm/MC/MCDisassembler/MCRelocationInfo.h @@ -21,7 +21,7 @@ namespace llvm { class MCContext; class MCExpr; -/// \brief Create MCExprs from relocations found in an object file. +/// Create MCExprs from relocations found in an object file. class MCRelocationInfo { protected: MCContext &Ctx; @@ -32,7 +32,7 @@ public: MCRelocationInfo &operator=(const MCRelocationInfo &) = delete; virtual ~MCRelocationInfo(); - /// \brief Create an MCExpr for the target-specific \p VariantKind. + /// Create an MCExpr for the target-specific \p VariantKind. /// The VariantKinds are defined in llvm-c/Disassembler.h. /// Used by MCExternalSymbolizer. /// \returns If possible, an MCExpr corresponding to VariantKind, else 0. diff --git a/contrib/llvm/include/llvm/MC/MCDisassembler/MCSymbolizer.h b/contrib/llvm/include/llvm/MC/MCDisassembler/MCSymbolizer.h index d85cf5e066f5..0bfa569474ec 100644 --- a/contrib/llvm/include/llvm/MC/MCDisassembler/MCSymbolizer.h +++ b/contrib/llvm/include/llvm/MC/MCDisassembler/MCSymbolizer.h @@ -27,7 +27,7 @@ class MCContext; class MCInst; class raw_ostream; -/// \brief Symbolize and annotate disassembled instructions. +/// Symbolize and annotate disassembled instructions. /// /// For now this mimics the old symbolization logic (from both ARM and x86), that /// relied on user-provided (C API) callbacks to do the actual symbol lookup in @@ -42,7 +42,7 @@ protected: std::unique_ptr<MCRelocationInfo> RelInfo; public: - /// \brief Construct an MCSymbolizer, taking ownership of \p RelInfo. + /// Construct an MCSymbolizer, taking ownership of \p RelInfo. MCSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> RelInfo) : Ctx(Ctx), RelInfo(std::move(RelInfo)) { } @@ -51,7 +51,7 @@ public: MCSymbolizer &operator=(const MCSymbolizer &) = delete; virtual ~MCSymbolizer(); - /// \brief Try to add a symbolic operand instead of \p Value to the MCInst. + /// Try to add a symbolic operand instead of \p Value to the MCInst. /// /// Instead of having a difficult to read immediate, a symbolic operand would /// represent this immediate in a more understandable way, for instance as a @@ -70,7 +70,7 @@ public: bool IsBranch, uint64_t Offset, uint64_t InstSize) = 0; - /// \brief Try to add a comment on the PC-relative load. + /// Try to add a comment on the PC-relative load. /// For instance, in Mach-O, this is used to add annotations to instructions /// that use C string literals, as found in __cstring. virtual void tryAddingPcLoadReferenceComment(raw_ostream &cStream, diff --git a/contrib/llvm/include/llvm/MC/MCDwarf.h b/contrib/llvm/include/llvm/MC/MCDwarf.h index 88ffa04128e6..785f42d2f9d7 100644 --- a/contrib/llvm/include/llvm/MC/MCDwarf.h +++ b/contrib/llvm/include/llvm/MC/MCDwarf.h @@ -16,10 +16,13 @@ #define LLVM_MC_MCDWARF_H #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCSection.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MD5.h" #include <cassert> #include <cstdint> #include <string> @@ -31,6 +34,7 @@ namespace llvm { template <typename T> class ArrayRef; class MCAsmBackend; class MCContext; +class MCDwarfLineStr; class MCObjectStreamer; class MCStreamer; class MCSymbol; @@ -38,21 +42,28 @@ class raw_ostream; class SMLoc; class SourceMgr; -/// \brief Instances of this class represent the name of the dwarf +/// Instances of this class represent the name of the dwarf /// .file directive and its associated dwarf file number in the MC file, /// and MCDwarfFile's are created and uniqued 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). struct MCDwarfFile { - // \brief The base name of the file without its directory path. - // The StringRef references memory allocated in the MCContext. + // The base name of the file without its directory path. std::string Name; - // \brief The index into the list of directory names for this file name. + // The index into the list of directory names for this file name. unsigned DirIndex; + + /// The MD5 checksum, if there is one. Non-owning pointer to data allocated + /// in MCContext. + MD5::MD5Result *Checksum = nullptr; + + /// The source code of the file. Non-owning reference to data allocated in + /// MCContext. + Optional<StringRef> Source; }; -/// \brief Instances of this class represent the information from a +/// Instances of this class represent the information from a /// dwarf .loc directive. class MCDwarfLoc { uint32_t FileNum; @@ -84,55 +95,55 @@ private: // MCContext manages these // for an MCDwarfLoc object. public: - /// \brief Get the FileNum of this MCDwarfLoc. + /// Get the FileNum of this MCDwarfLoc. unsigned getFileNum() const { return FileNum; } - /// \brief Get the Line of this MCDwarfLoc. + /// Get the Line of this MCDwarfLoc. unsigned getLine() const { return Line; } - /// \brief Get the Column of this MCDwarfLoc. + /// Get the Column of this MCDwarfLoc. unsigned getColumn() const { return Column; } - /// \brief Get the Flags of this MCDwarfLoc. + /// Get the Flags of this MCDwarfLoc. unsigned getFlags() const { return Flags; } - /// \brief Get the Isa of this MCDwarfLoc. + /// Get the Isa of this MCDwarfLoc. unsigned getIsa() const { return Isa; } - /// \brief Get the Discriminator of this MCDwarfLoc. + /// Get the Discriminator of this MCDwarfLoc. unsigned getDiscriminator() const { return Discriminator; } - /// \brief Set the FileNum of this MCDwarfLoc. + /// Set the FileNum of this MCDwarfLoc. void setFileNum(unsigned fileNum) { FileNum = fileNum; } - /// \brief Set the Line of this MCDwarfLoc. + /// Set the Line of this MCDwarfLoc. void setLine(unsigned line) { Line = line; } - /// \brief Set the Column of this MCDwarfLoc. + /// Set the Column of this MCDwarfLoc. void setColumn(unsigned column) { assert(column <= UINT16_MAX); Column = column; } - /// \brief Set the Flags of this MCDwarfLoc. + /// Set the Flags of this MCDwarfLoc. void setFlags(unsigned flags) { assert(flags <= UINT8_MAX); Flags = flags; } - /// \brief Set the Isa of this MCDwarfLoc. + /// Set the Isa of this MCDwarfLoc. void setIsa(unsigned isa) { assert(isa <= UINT8_MAX); Isa = isa; } - /// \brief Set the Discriminator of this MCDwarfLoc. + /// Set the Discriminator of this MCDwarfLoc. void setDiscriminator(unsigned discriminator) { Discriminator = discriminator; } }; -/// \brief Instances of this class represent the line information for +/// Instances of this class represent the line information for /// the dwarf line table entries. Which is created after a machine /// instruction is assembled and uses an address from a temporary label /// created at the current address in the current section and the info from @@ -157,13 +168,13 @@ public: static void Make(MCObjectStreamer *MCOS, MCSection *Section); }; -/// \brief Instances of this class represent the line information for a compile +/// Instances of this class represent the line information 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 { public: - // \brief Add an entry to this MCLineSection's line entries. + // Add an entry to this MCLineSection's line entries. void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) { MCLineDivisions[Sec].push_back(LineEntry); } @@ -202,32 +213,69 @@ struct MCDwarfLineTableHeader { SmallVector<std::string, 3> MCDwarfDirs; SmallVector<MCDwarfFile, 3> MCDwarfFiles; StringMap<unsigned> SourceIdMap; - StringRef CompilationDir; + std::string CompilationDir; + MCDwarfFile RootFile; + bool HasSource = false; +private: + bool HasAllMD5 = true; + bool HasAnyMD5 = false; +public: MCDwarfLineTableHeader() = default; - unsigned getFile(StringRef &Directory, StringRef &FileName, - unsigned FileNumber = 0); - std::pair<MCSymbol *, MCSymbol *> Emit(MCStreamer *MCOS, - MCDwarfLineTableParams Params) const; + Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName, + MD5::MD5Result *Checksum, + Optional<StringRef> &Source, + unsigned FileNumber = 0); std::pair<MCSymbol *, MCSymbol *> Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, - ArrayRef<char> SpecialOpcodeLengths) const; + Optional<MCDwarfLineStr> &LineStr) const; + std::pair<MCSymbol *, MCSymbol *> + Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, + ArrayRef<char> SpecialOpcodeLengths, + Optional<MCDwarfLineStr> &LineStr) const; + void resetMD5Usage() { + HasAllMD5 = true; + HasAnyMD5 = false; + } + void trackMD5Usage(bool MD5Used) { + HasAllMD5 &= MD5Used; + HasAnyMD5 |= MD5Used; + } + bool isMD5UsageConsistent() const { + return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5); + } + +private: + void emitV2FileDirTables(MCStreamer *MCOS) const; + void emitV5FileDirTables(MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr, + StringRef CtxCompilationDir) const; }; class MCDwarfDwoLineTable { MCDwarfLineTableHeader Header; public: - void setCompilationDir(StringRef CompilationDir) { - Header.CompilationDir = CompilationDir; + void maybeSetRootFile(StringRef Directory, StringRef FileName, + MD5::MD5Result *Checksum, Optional<StringRef> Source) { + if (!Header.RootFile.Name.empty()) + return; + Header.CompilationDir = Directory; + Header.RootFile.Name = FileName; + Header.RootFile.DirIndex = 0; + Header.RootFile.Checksum = Checksum; + Header.RootFile.Source = Source; + Header.trackMD5Usage(Checksum); + Header.HasSource = Source.hasValue(); } - unsigned getFile(StringRef Directory, StringRef FileName) { - return Header.getFile(Directory, FileName); + unsigned getFile(StringRef Directory, StringRef FileName, + MD5::MD5Result *Checksum, Optional<StringRef> Source) { + return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source)); } - void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params) const; + void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params, + MCSection *Section) const; }; class MCDwarfLineTable { @@ -239,10 +287,42 @@ public: static void Emit(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params); // This emits the Dwarf file and the line tables for a given Compile Unit. - void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params) const; + void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params, + Optional<MCDwarfLineStr> &LineStr) const; + Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName, + MD5::MD5Result *Checksum, + Optional<StringRef> Source, + unsigned FileNumber = 0); unsigned getFile(StringRef &Directory, StringRef &FileName, - unsigned FileNumber = 0); + MD5::MD5Result *Checksum, Optional<StringRef> &Source, + unsigned FileNumber = 0) { + return cantFail(tryGetFile(Directory, FileName, Checksum, Source, + FileNumber)); + } + + void setRootFile(StringRef Directory, StringRef FileName, + MD5::MD5Result *Checksum, Optional<StringRef> Source) { + Header.CompilationDir = Directory; + Header.RootFile.Name = FileName; + Header.RootFile.DirIndex = 0; + Header.RootFile.Checksum = Checksum; + Header.RootFile.Source = Source; + Header.trackMD5Usage(Checksum); + Header.HasSource = Source.hasValue(); + } + + void resetRootFile() { + assert(Header.MCDwarfFiles.empty()); + Header.RootFile.Name.clear(); + Header.resetMD5Usage(); + Header.HasSource = false; + } + + bool hasRootFile() const { return !Header.RootFile.Name.empty(); } + + // Report whether MD5 usage has been consistent (all-or-none). + bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); } MCSymbol *getLabel() const { return Header.Label; @@ -252,10 +332,6 @@ public: Header.Label = Label; } - void setCompilationDir(StringRef CompilationDir) { - Header.CompilationDir = CompilationDir; - } - const SmallVectorImpl<std::string> &getMCDwarfDirs() const { return Header.MCDwarfDirs; } @@ -372,41 +448,41 @@ private: } public: - /// \brief .cfi_def_cfa defines a rule for computing CFA as: take address from + /// .cfi_def_cfa defines a rule for computing CFA as: take address from /// Register and add Offset to it. static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, int Offset) { return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); } - /// \brief .cfi_def_cfa_register modifies a rule for computing CFA. From now + /// .cfi_def_cfa_register modifies a rule for computing CFA. From now /// on Register will be used instead of the old one. Offset remains the same. static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) { return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); } - /// \brief .cfi_def_cfa_offset modifies a rule for computing CFA. Register + /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register /// remains the same, but offset is new. Note that it is the absolute offset /// that will be added to a defined register to the compute CFA address. static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); } - /// \brief .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but + /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but /// Offset is a relative value that is added/subtracted from the previous /// offset. static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) { return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); } - /// \brief .cfi_offset Previous value of Register is saved at offset Offset + /// .cfi_offset Previous value of Register is saved at offset Offset /// from CFA. static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset) { return MCCFIInstruction(OpOffset, L, Register, Offset, ""); } - /// \brief .cfi_rel_offset Previous value of Register is saved at offset + /// .cfi_rel_offset Previous value of Register is saved at offset /// Offset from the current CFA register. This is transformed to .cfi_offset /// using the known displacement of the CFA register from the CFA. static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, @@ -414,54 +490,54 @@ public: return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); } - /// \brief .cfi_register Previous value of Register1 is saved in + /// .cfi_register Previous value of Register1 is saved in /// register Register2. static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, unsigned Register2) { return MCCFIInstruction(OpRegister, L, Register1, Register2); } - /// \brief .cfi_window_save SPARC register window is saved. + /// .cfi_window_save SPARC register window is saved. static MCCFIInstruction createWindowSave(MCSymbol *L) { return MCCFIInstruction(OpWindowSave, L, 0, 0, ""); } - /// \brief .cfi_restore says that the rule for Register is now the same as it + /// .cfi_restore says that the rule for Register is now the same as it /// was at the beginning of the function, after all initial instructions added /// by .cfi_startproc were executed. static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { return MCCFIInstruction(OpRestore, L, Register, 0, ""); } - /// \brief .cfi_undefined From now on the previous value of Register can't be + /// .cfi_undefined From now on the previous value of Register can't be /// restored anymore. static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { return MCCFIInstruction(OpUndefined, L, Register, 0, ""); } - /// \brief .cfi_same_value Current value of Register is the same as in the + /// .cfi_same_value Current value of Register is the same as in the /// previous frame. I.e., no restoration is needed. static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { return MCCFIInstruction(OpSameValue, L, Register, 0, ""); } - /// \brief .cfi_remember_state Save all current rules for all registers. + /// .cfi_remember_state Save all current rules for all registers. static MCCFIInstruction createRememberState(MCSymbol *L) { return MCCFIInstruction(OpRememberState, L, 0, 0, ""); } - /// \brief .cfi_restore_state Restore the previously saved state. + /// .cfi_restore_state Restore the previously saved state. static MCCFIInstruction createRestoreState(MCSymbol *L) { return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); } - /// \brief .cfi_escape Allows the user to add arbitrary bytes to the unwind + /// .cfi_escape Allows the user to add arbitrary bytes to the unwind /// info. static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { return MCCFIInstruction(OpEscape, L, 0, 0, Vals); } - /// \brief A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE + /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) { return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, ""); } diff --git a/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h b/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h index fd8d118ccdc5..bff58fef6af9 100644 --- a/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h +++ b/contrib/llvm/include/llvm/MC/MCELFObjectWriter.h @@ -12,6 +12,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCObjectWriter.h" #include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" #include <cstdint> @@ -50,7 +51,7 @@ struct ELFRelocationEntry { void dump() const { print(errs()); } }; -class MCELFObjectTargetWriter { +class MCELFObjectTargetWriter : public MCObjectTargetWriter { const uint8_t OSABI; const uint16_t EMachine; const unsigned HasRelocationAddend : 1; @@ -63,6 +64,11 @@ protected: public: virtual ~MCELFObjectTargetWriter() = default; + virtual Triple::ObjectFormatType getFormat() const { return Triple::ELF; } + static bool classof(const MCObjectTargetWriter *W) { + return W->getFormat() == Triple::ELF; + } + static uint8_t getOSABI(Triple::OSType OSType) { switch (OSType) { case Triple::CloudABI: @@ -132,7 +138,7 @@ public: } }; -/// \brief Construct a new ELF writer instance. +/// Construct a new ELF writer instance. /// /// \param MOTW - The target specific ELF writer subclass. /// \param OS - The stream to write to. @@ -141,6 +147,11 @@ std::unique_ptr<MCObjectWriter> createELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW, raw_pwrite_stream &OS, bool IsLittleEndian); +std::unique_ptr<MCObjectWriter> +createELFDwoObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW, + raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS, + bool IsLittleEndian); + } // end namespace llvm #endif // LLVM_MC_MCELFOBJECTWRITER_H diff --git a/contrib/llvm/include/llvm/MC/MCELFStreamer.h b/contrib/llvm/include/llvm/MC/MCELFStreamer.h index 2f23cd64ee03..3797079661e4 100644 --- a/contrib/llvm/include/llvm/MC/MCELFStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCELFStreamer.h @@ -24,7 +24,8 @@ class MCInst; class MCELFStreamer : public MCObjectStreamer { public: MCELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter); + std::unique_ptr<MCObjectWriter> OW, + std::unique_ptr<MCCodeEmitter> Emitter); ~MCELFStreamer() override = default; @@ -58,7 +59,8 @@ public: unsigned ByteAlignment) override; void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, - uint64_t Size = 0, unsigned ByteAlignment = 0) override; + uint64_t Size = 0, unsigned ByteAlignment = 0, + SMLoc L = SMLoc()) override; void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, @@ -68,6 +70,9 @@ public: void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned) override; + void emitCGProfileEntry(const MCSymbolRefExpr *From, + const MCSymbolRefExpr *To, uint64_t Count) override; + void FinishImpl() override; void EmitBundleAlignMode(unsigned AlignPow2) override; @@ -80,8 +85,10 @@ private: void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; void fixSymbolsInTLSFixups(const MCExpr *expr); + void finalizeCGProfileEntry(const MCSymbolRefExpr *&S); + void finalizeCGProfile(); - /// \brief Merge the content of the fragment \p EF into the fragment \p DF. + /// Merge the content of the fragment \p EF into the fragment \p DF. void mergeFragment(MCDataFragment *, MCDataFragment *); bool SeenIdent = false; @@ -93,7 +100,7 @@ private: MCELFStreamer *createARMELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, bool RelaxAll, bool IsThumb); diff --git a/contrib/llvm/include/llvm/MC/MCExpr.h b/contrib/llvm/include/llvm/MC/MCExpr.h index fcbbe650d26f..c4dfbe949078 100644 --- a/contrib/llvm/include/llvm/MC/MCExpr.h +++ b/contrib/llvm/include/llvm/MC/MCExpr.h @@ -31,7 +31,7 @@ class StringRef; using SectionAddrMap = DenseMap<const MCSection *, uint64_t>; -/// \brief Base class for the full range of assembler expressions which are +/// Base class for the full range of assembler expressions which are /// needed for parsing. class MCExpr { public: @@ -85,7 +85,7 @@ public: /// \name Expression Evaluation /// @{ - /// \brief Try to evaluate the expression to an absolute value. + /// Try to evaluate the expression to an absolute value. /// /// \param Res - The absolute value, if evaluation succeeds. /// \param Layout - The assembler layout object to use for evaluating symbol @@ -96,11 +96,12 @@ public: const SectionAddrMap &Addrs) const; bool evaluateAsAbsolute(int64_t &Res) const; bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; + bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const; bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; - /// \brief Try to evaluate the expression to a relocatable value, i.e. an + /// Try to evaluate the expression to a relocatable value, i.e. an /// expression of the fixed form (a - b + constant). /// /// \param Res - The relocatable value, if evaluation succeeds. @@ -110,14 +111,14 @@ public: bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const; - /// \brief Try to evaluate the expression to the form (a - b + constant) where + /// Try to evaluate the expression to the form (a - b + constant) where /// neither a nor b are variables. /// /// This is a more aggressive variant of evaluateAsRelocatable. The intended /// use is for when relocations are not available, like the .size directive. bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const; - /// \brief Find the "associated section" for this expression, which is + /// Find the "associated section" for this expression, which is /// currently defined as the absolute section for constants, or /// otherwise the section associated with the first defined symbol in the /// expression. @@ -131,7 +132,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { return OS; } -//// \brief Represent a constant integer expression. +//// Represent a constant integer expression. class MCConstantExpr : public MCExpr { int64_t Value; @@ -157,7 +158,7 @@ public: } }; -/// \brief Represent a reference to a symbol from inside an expression. +/// Represent a reference to a symbol from inside an expression. /// /// A symbol reference in an expression may be a use of a label, a use of an /// assembler variable (defined constant), or constitute an implicit definition @@ -217,6 +218,8 @@ public: VK_PPC_LO, // symbol@l VK_PPC_HI, // symbol@h VK_PPC_HA, // symbol@ha + VK_PPC_HIGH, // symbol@high + VK_PPC_HIGHA, // symbol@higha VK_PPC_HIGHER, // symbol@higher VK_PPC_HIGHERA, // symbol@highera VK_PPC_HIGHEST, // symbol@highest @@ -233,6 +236,8 @@ public: VK_PPC_TPREL_LO, // symbol@tprel@l VK_PPC_TPREL_HI, // symbol@tprel@h VK_PPC_TPREL_HA, // symbol@tprel@ha + VK_PPC_TPREL_HIGH, // symbol@tprel@high + VK_PPC_TPREL_HIGHA, // symbol@tprel@higha VK_PPC_TPREL_HIGHER, // symbol@tprel@higher VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest @@ -240,6 +245,8 @@ public: VK_PPC_DTPREL_LO, // symbol@dtprel@l VK_PPC_DTPREL_HI, // symbol@dtprel@h VK_PPC_DTPREL_HA, // symbol@dtprel@ha + VK_PPC_DTPREL_HIGH, // symbol@dtprel@high + VK_PPC_DTPREL_HIGHA, // symbol@dtprel@higha VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest @@ -285,6 +292,7 @@ public: VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi VK_AMDGPU_REL32_LO, // symbol@rel32@lo VK_AMDGPU_REL32_HI, // symbol@rel32@hi + VK_AMDGPU_REL64, // symbol@rel64 VK_TPREL, VK_DTPREL @@ -346,7 +354,7 @@ public: } }; -/// \brief Unary assembler expressions. +/// Unary assembler expressions. class MCUnaryExpr : public MCExpr { public: enum Opcode { @@ -390,10 +398,10 @@ public: /// \name Accessors /// @{ - /// \brief Get the kind of this unary expression. + /// Get the kind of this unary expression. Opcode getOpcode() const { return Op; } - /// \brief Get the child of this unary expression. + /// Get the child of this unary expression. const MCExpr *getSubExpr() const { return Expr; } /// @} @@ -403,7 +411,7 @@ public: } }; -/// \brief Binary assembler expressions. +/// Binary assembler expressions. class MCBinaryExpr : public MCExpr { public: enum Opcode { @@ -547,13 +555,13 @@ public: /// \name Accessors /// @{ - /// \brief Get the kind of this binary expression. + /// Get the kind of this binary expression. Opcode getOpcode() const { return Op; } - /// \brief Get the left-hand side expression of the binary operator. + /// Get the left-hand side expression of the binary operator. const MCExpr *getLHS() const { return LHS; } - /// \brief Get the right-hand side expression of the binary operator. + /// Get the right-hand side expression of the binary operator. const MCExpr *getRHS() const { return RHS; } /// @} @@ -563,7 +571,7 @@ public: } }; -/// \brief This is an extension point for target-specific MCExpr subclasses to +/// This is an extension point for target-specific MCExpr subclasses to /// implement. /// /// NOTE: All subclasses are required to have trivial destructors because @@ -580,6 +588,9 @@ public: virtual bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const = 0; + // This should be set when assigned expressions are not valid ".set" + // expressions, e.g. registers, and must be inlined. + virtual bool inlineAssignedExpr() const { return false; } virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; virtual MCFragment *findAssociatedFragment() const = 0; diff --git a/contrib/llvm/include/llvm/MC/MCFixup.h b/contrib/llvm/include/llvm/MC/MCFixup.h index b83086c327f2..5f301eafc556 100644 --- a/contrib/llvm/include/llvm/MC/MCFixup.h +++ b/contrib/llvm/include/llvm/MC/MCFixup.h @@ -19,7 +19,7 @@ namespace llvm { class MCExpr; -/// \brief Extensible enumeration to represent the type of a fixup. +/// Extensible enumeration to represent the type of a fixup. enum MCFixupKind { FK_Data_1 = 0, ///< A one-byte fixup. FK_Data_2, ///< A two-byte fixup. @@ -41,6 +41,14 @@ enum MCFixupKind { FK_SecRel_2, ///< A two-byte section relative fixup. FK_SecRel_4, ///< A four-byte section relative fixup. FK_SecRel_8, ///< A eight-byte section relative fixup. + FK_Data_Add_1, ///< A one-byte add fixup. + FK_Data_Add_2, ///< A two-byte add fixup. + FK_Data_Add_4, ///< A four-byte add fixup. + FK_Data_Add_8, ///< A eight-byte add fixup. + FK_Data_Sub_1, ///< A one-byte sub fixup. + FK_Data_Sub_2, ///< A two-byte sub fixup. + FK_Data_Sub_4, ///< A four-byte sub fixup. + FK_Data_Sub_8, ///< A eight-byte sub fixup. FirstTargetFixupKind = 128, @@ -49,7 +57,7 @@ enum MCFixupKind { MaxTargetFixupKind = (1 << 8) }; -/// \brief Encode information on a single operation to perform on a byte +/// Encode information on a single operation to perform on a byte /// sequence (e.g., an encoded instruction) which requires assemble- or run- /// time patching. /// @@ -90,6 +98,28 @@ public: return FI; } + /// Return a fixup corresponding to the add half of a add/sub fixup pair for + /// the given Fixup. + static MCFixup createAddFor(const MCFixup &Fixup) { + MCFixup FI; + FI.Value = Fixup.getValue(); + FI.Offset = Fixup.getOffset(); + FI.Kind = (unsigned)getAddKindForKind(Fixup.getKind()); + FI.Loc = Fixup.getLoc(); + return FI; + } + + /// Return a fixup corresponding to the sub half of a add/sub fixup pair for + /// the given Fixup. + static MCFixup createSubFor(const MCFixup &Fixup) { + MCFixup FI; + FI.Value = Fixup.getValue(); + FI.Offset = Fixup.getOffset(); + FI.Kind = (unsigned)getSubKindForKind(Fixup.getKind()); + FI.Loc = Fixup.getLoc(); + return FI; + } + MCFixupKind getKind() const { return MCFixupKind(Kind); } uint32_t getOffset() const { return Offset; } @@ -97,7 +127,7 @@ public: const MCExpr *getValue() const { return Value; } - /// \brief Return the generic fixup kind for a value with the given size. It + /// Return the generic fixup kind for a value with the given size. It /// is an error to pass an unsupported size. static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) { switch (Size) { @@ -109,6 +139,30 @@ public: } } + /// Return the generic fixup kind for an addition with a given size. It + /// is an error to pass an unsupported size. + static MCFixupKind getAddKindForKind(unsigned Kind) { + switch (Kind) { + default: llvm_unreachable("Unknown type to convert!"); + case FK_Data_1: return FK_Data_Add_1; + case FK_Data_2: return FK_Data_Add_2; + case FK_Data_4: return FK_Data_Add_4; + case FK_Data_8: return FK_Data_Add_8; + } + } + + /// Return the generic fixup kind for an subtraction with a given size. It + /// is an error to pass an unsupported size. + static MCFixupKind getSubKindForKind(unsigned Kind) { + switch (Kind) { + default: llvm_unreachable("Unknown type to convert!"); + case FK_Data_1: return FK_Data_Sub_1; + case FK_Data_2: return FK_Data_Sub_2; + case FK_Data_4: return FK_Data_Sub_4; + case FK_Data_8: return FK_Data_Sub_8; + } + } + SMLoc getLoc() const { return Loc; } }; diff --git a/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h b/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h index 58183bd778e6..483abb39403f 100644 --- a/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h +++ b/contrib/llvm/include/llvm/MC/MCFixupKindInfo.h @@ -12,7 +12,7 @@ namespace llvm { -/// \brief Target independent information on a fixup kind. +/// Target independent information on a fixup kind. struct MCFixupKindInfo { enum FixupKindFlags { /// Is this fixup kind PCrelative? This is used by the assembler backend to diff --git a/contrib/llvm/include/llvm/MC/MCFragment.h b/contrib/llvm/include/llvm/MC/MCFragment.h index 85b55e85469a..47b35175fec8 100644 --- a/contrib/llvm/include/llvm/MC/MCFragment.h +++ b/contrib/llvm/include/llvm/MC/MCFragment.h @@ -56,18 +56,13 @@ protected: bool HasInstructions; private: - /// \brief Should this fragment be aligned to the end of a bundle? - bool AlignToBundleEnd; - - uint8_t BundlePadding; - /// LayoutOrder - The layout order of this fragment. unsigned LayoutOrder; /// The data for the section this fragment is in. MCSection *Parent; - /// Atom - The atom this fragment is in, as represented by it's defining + /// Atom - The atom this fragment is in, as represented by its defining /// symbol. const MCSymbol *Atom; @@ -84,7 +79,7 @@ private: protected: MCFragment(FragmentType Kind, bool HasInstructions, - uint8_t BundlePadding, MCSection *Parent = nullptr); + MCSection *Parent = nullptr); ~MCFragment(); @@ -110,26 +105,11 @@ public: unsigned getLayoutOrder() const { return LayoutOrder; } void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } - /// \brief Does this fragment have instructions emitted into it? By default + /// Does this fragment have instructions emitted into it? By default /// this is false, but specific fragment types may set it to true. bool hasInstructions() const { return HasInstructions; } - /// \brief Should this fragment be placed at the end of an aligned bundle? - bool alignToBundleEnd() const { return AlignToBundleEnd; } - void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } - - /// \brief Get the padding size that must be inserted before this fragment. - /// Used for bundling. By default, no padding is inserted. - /// Note that padding size is restricted to 8 bits. This is an optimization - /// to reduce the amount of space used for each fragment. In practice, larger - /// padding should never be required. - uint8_t getBundlePadding() const { return BundlePadding; } - - /// \brief Set the padding size for this fragment. By default it's a no-op, - /// and only some fragments have a meaningful implementation. - void setBundlePadding(uint8_t N) { BundlePadding = N; } - - /// \brief Return true if given frgment has FT_Dummy type. + /// Return true if given frgment has FT_Dummy type. bool isDummy() const { return Kind == FT_Dummy; } void dump() const; @@ -137,8 +117,7 @@ public: class MCDummyFragment : public MCFragment { public: - explicit MCDummyFragment(MCSection *Sec) - : MCFragment(FT_Dummy, false, 0, Sec) {} + explicit MCDummyFragment(MCSection *Sec) : MCFragment(FT_Dummy, false, Sec) {} static bool classof(const MCFragment *F) { return F->getKind() == FT_Dummy; } }; @@ -147,10 +126,19 @@ public: /// data. /// class MCEncodedFragment : public MCFragment { + /// Should this fragment be aligned to the end of a bundle? + bool AlignToBundleEnd = false; + + uint8_t BundlePadding = 0; + protected: MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions, MCSection *Sec) - : MCFragment(FType, HasInstructions, 0, Sec) {} + : MCFragment(FType, HasInstructions, Sec) {} + + /// STI - The MCSubtargetInfo in effect when the instruction was encoded. + /// must be non-null for instructions. + const MCSubtargetInfo *STI = nullptr; public: static bool classof(const MCFragment *F) { @@ -164,6 +152,32 @@ public: return true; } } + + /// Should this fragment be placed at the end of an aligned bundle? + bool alignToBundleEnd() const { return AlignToBundleEnd; } + void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } + + /// Get the padding size that must be inserted before this fragment. + /// Used for bundling. By default, no padding is inserted. + /// Note that padding size is restricted to 8 bits. This is an optimization + /// to reduce the amount of space used for each fragment. In practice, larger + /// padding should never be required. + uint8_t getBundlePadding() const { return BundlePadding; } + + /// Set the padding size for this fragment. By default it's a no-op, + /// and only some fragments have a meaningful implementation. + void setBundlePadding(uint8_t N) { BundlePadding = N; } + + /// Retrieve the MCSubTargetInfo in effect when the instruction was encoded. + /// Guaranteed to be non-null if hasInstructions() == true + const MCSubtargetInfo *getSubtargetInfo() const { return STI; } + + /// Record that the fragment contains instructions with the MCSubtargetInfo in + /// effect when the instruction was encoded. + void setHasInstructions(const MCSubtargetInfo &STI) { + HasInstructions = true; + this->STI = &STI; + } }; /// Interface implemented by fragments that contain encoded instructions and/or @@ -202,6 +216,7 @@ protected: Sec) {} public: + using const_fixup_iterator = SmallVectorImpl<MCFixup>::const_iterator; using fixup_iterator = SmallVectorImpl<MCFixup>::iterator; @@ -228,8 +243,6 @@ public: MCDataFragment(MCSection *Sec = nullptr) : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {} - void setHasInstructions(bool V) { HasInstructions = V; } - static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Data; } @@ -259,20 +272,15 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> { /// Inst - The instruction this is a fragment for. MCInst Inst; - /// STI - The MCSubtargetInfo in effect when the instruction was encoded. - const MCSubtargetInfo &STI; - public: MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI, MCSection *Sec = nullptr) : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec), - Inst(Inst), STI(STI) {} + Inst(Inst) { this->STI = &STI; } const MCInst &getInst() const { return Inst; } void setInst(const MCInst &Value) { Inst = Value; } - const MCSubtargetInfo &getSubtargetInfo() { return STI; } - static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Relaxable; } @@ -300,9 +308,8 @@ class MCAlignFragment : public MCFragment { public: MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize, unsigned MaxBytesToEmit, MCSection *Sec = nullptr) - : MCFragment(FT_Align, false, 0, Sec), Alignment(Alignment), - EmitNops(false), Value(Value), - ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {} + : MCFragment(FT_Align, false, Sec), Alignment(Alignment), EmitNops(false), + Value(Value), ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {} /// \name Accessors /// @{ @@ -370,7 +377,7 @@ public: }; MCPaddingFragment(MCSection *Sec = nullptr) - : MCFragment(FT_Padding, false, 0, Sec), PaddingPoliciesMask(PFK_None), + : MCFragment(FT_Padding, false, Sec), PaddingPoliciesMask(PFK_None), IsInsertionPoint(false), Size(UINT64_C(0)), InstInfo({false, MCInst(), false, {0}}) {} @@ -419,22 +426,23 @@ public: class MCFillFragment : public MCFragment { /// Value to use for filling bytes. - uint8_t Value; - + uint64_t Value; + uint8_t ValueSize; /// The number of bytes to insert. - const MCExpr &Size; + const MCExpr &NumValues; /// Source location of the directive that this fragment was created for. SMLoc Loc; public: - MCFillFragment(uint8_t Value, const MCExpr &Size, SMLoc Loc, - MCSection *Sec = nullptr) - : MCFragment(FT_Fill, false, 0, Sec), Value(Value), Size(Size), Loc(Loc) { - } + MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues, + SMLoc Loc, MCSection *Sec = nullptr) + : MCFragment(FT_Fill, false, Sec), Value(Value), ValueSize(VSize), + NumValues(NumValues), Loc(Loc) {} - uint8_t getValue() const { return Value; } - const MCExpr &getSize() const { return Size; } + uint64_t getValue() const { return Value; } + uint8_t getValueSize() const { return ValueSize; } + const MCExpr &getNumValues() const { return NumValues; } SMLoc getLoc() const { return Loc; } @@ -444,19 +452,19 @@ public: }; class MCOrgFragment : public MCFragment { - /// Offset - The offset this fragment should start at. + /// The offset this fragment should start at. const MCExpr *Offset; - /// Value - Value to use for filling bytes. + /// Value to use for filling bytes. int8_t Value; - /// Loc - Source location of the directive that this fragment was created for. + /// Source location of the directive that this fragment was created for. SMLoc Loc; public: MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc, MCSection *Sec = nullptr) - : MCFragment(FT_Org, false, 0, Sec), Offset(&Offset), Value(Value), Loc(Loc) {} + : MCFragment(FT_Org, false, Sec), Offset(&Offset), Value(Value), Loc(Loc) {} /// \name Accessors /// @{ @@ -485,7 +493,7 @@ class MCLEBFragment : public MCFragment { public: MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr) - : MCFragment(FT_LEB, false, 0, Sec), Value(&Value_), IsSigned(IsSigned_) { + : MCFragment(FT_LEB, false, Sec), Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } @@ -520,7 +528,7 @@ class MCDwarfLineAddrFragment : public MCFragment { public: MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta, MCSection *Sec = nullptr) - : MCFragment(FT_Dwarf, false, 0, Sec), LineDelta(LineDelta), + : MCFragment(FT_Dwarf, false, Sec), LineDelta(LineDelta), AddrDelta(&AddrDelta) { Contents.push_back(0); } @@ -551,7 +559,7 @@ class MCDwarfCallFrameFragment : public MCFragment { public: MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) - : MCFragment(FT_DwarfFrame, false, 0, Sec), AddrDelta(&AddrDelta) { + : MCFragment(FT_DwarfFrame, false, Sec), AddrDelta(&AddrDelta) { Contents.push_back(0); } @@ -576,7 +584,7 @@ class MCSymbolIdFragment : public MCFragment { public: MCSymbolIdFragment(const MCSymbol *Sym, MCSection *Sec = nullptr) - : MCFragment(FT_SymbolId, false, 0, Sec), Sym(Sym) {} + : MCFragment(FT_SymbolId, false, Sec), Sym(Sym) {} /// \name Accessors /// @{ @@ -610,7 +618,7 @@ public: unsigned StartLineNum, const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, MCSection *Sec = nullptr) - : MCFragment(FT_CVInlineLines, false, 0, Sec), SiteFuncId(SiteFuncId), + : MCFragment(FT_CVInlineLines, false, Sec), SiteFuncId(SiteFuncId), StartFileId(StartFileId), StartLineNum(StartLineNum), FnStartSym(FnStartSym), FnEndSym(FnEndSym) {} diff --git a/contrib/llvm/include/llvm/MC/MCInst.h b/contrib/llvm/include/llvm/MC/MCInst.h index db28fd0fd6d9..67bb11a70387 100644 --- a/contrib/llvm/include/llvm/MC/MCInst.h +++ b/contrib/llvm/include/llvm/MC/MCInst.h @@ -30,7 +30,7 @@ class MCInst; class MCInstPrinter; class raw_ostream; -/// \brief Instances of this class represent operands of the MCInst class. +/// Instances of this class represent operands of the MCInst class. /// This is a simple discriminated union. class MCOperand { enum MachineOperandType : unsigned char { @@ -61,13 +61,13 @@ public: bool isExpr() const { return Kind == kExpr; } bool isInst() const { return Kind == kInst; } - /// \brief Returns the register number. + /// Returns the register number. unsigned getReg() const { assert(isReg() && "This is not a register operand!"); return RegVal; } - /// \brief Set the register number. + /// Set the register number. void setReg(unsigned Reg) { assert(isReg() && "This is not a register operand!"); RegVal = Reg; @@ -150,11 +150,13 @@ public: void print(raw_ostream &OS) const; void dump() const; + bool isBareSymbolRef() const; + bool evaluateAsConstantImm(int64_t &Imm) const; }; template <> struct isPodLike<MCOperand> { static const bool value = true; }; -/// \brief Instances of this class represent a single low-level machine +/// Instances of this class represent a single low-level machine /// instruction. class MCInst { unsigned Opcode = 0; @@ -201,7 +203,7 @@ public: void print(raw_ostream &OS) const; void dump() const; - /// \brief Dump the MCInst as prettily as possible using the additional MC + /// Dump the MCInst as prettily as possible using the additional MC /// structures, if given. Operators are separated by the \p Separator /// string. void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer = nullptr, diff --git a/contrib/llvm/include/llvm/MC/MCInstBuilder.h b/contrib/llvm/include/llvm/MC/MCInstBuilder.h index 30609bdb8b27..c5c4f481e7df 100644 --- a/contrib/llvm/include/llvm/MC/MCInstBuilder.h +++ b/contrib/llvm/include/llvm/MC/MCInstBuilder.h @@ -23,42 +23,42 @@ class MCInstBuilder { MCInst Inst; public: - /// \brief Create a new MCInstBuilder for an MCInst with a specific opcode. + /// Create a new MCInstBuilder for an MCInst with a specific opcode. MCInstBuilder(unsigned Opcode) { Inst.setOpcode(Opcode); } - /// \brief Add a new register operand. + /// Add a new register operand. MCInstBuilder &addReg(unsigned Reg) { Inst.addOperand(MCOperand::createReg(Reg)); return *this; } - /// \brief Add a new integer immediate operand. + /// Add a new integer immediate operand. MCInstBuilder &addImm(int64_t Val) { Inst.addOperand(MCOperand::createImm(Val)); return *this; } - /// \brief Add a new floating point immediate operand. + /// Add a new floating point immediate operand. MCInstBuilder &addFPImm(double Val) { Inst.addOperand(MCOperand::createFPImm(Val)); return *this; } - /// \brief Add a new MCExpr operand. + /// Add a new MCExpr operand. MCInstBuilder &addExpr(const MCExpr *Val) { Inst.addOperand(MCOperand::createExpr(Val)); return *this; } - /// \brief Add a new MCInst operand. + /// Add a new MCInst operand. MCInstBuilder &addInst(const MCInst *Val) { Inst.addOperand(MCOperand::createInst(Val)); return *this; } - /// \brief Add an operand. + /// Add an operand. MCInstBuilder &addOperand(const MCOperand &Op) { Inst.addOperand(Op); return *this; diff --git a/contrib/llvm/include/llvm/MC/MCInstPrinter.h b/contrib/llvm/include/llvm/MC/MCInstPrinter.h index 069403074b31..df221e1db0e7 100644 --- a/contrib/llvm/include/llvm/MC/MCInstPrinter.h +++ b/contrib/llvm/include/llvm/MC/MCInstPrinter.h @@ -15,7 +15,6 @@ namespace llvm { -template <typename T> class ArrayRef; class MCAsmInfo; class MCInst; class MCInstrInfo; @@ -36,13 +35,13 @@ enum Style { } // end namespace HexStyle -/// \brief This is an instance of a target assembly language printer that +/// This is an instance of a target assembly language printer that /// converts an MCInst to valid target assembly syntax. class MCInstPrinter { protected: - /// \brief A stream that comments can be emitted to if desired. Each comment + /// A stream that comments can be emitted to if desired. Each comment /// must end with a newline. This will be null if verbose assembly emission - /// is disable. + /// is disabled. raw_ostream *CommentStream = nullptr; const MCAsmInfo &MAI; const MCInstrInfo &MII; @@ -66,18 +65,18 @@ public: virtual ~MCInstPrinter(); - /// \brief Specify a stream to emit comments to. + /// Specify a stream to emit comments to. void setCommentStream(raw_ostream &OS) { CommentStream = &OS; } - /// \brief Print the specified MCInst to the specified raw_ostream. + /// Print the specified MCInst to the specified raw_ostream. virtual void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot, const MCSubtargetInfo &STI) = 0; - /// \brief Return the name of the specified opcode enum (e.g. "MOV32ri") or + /// Return the name of the specified opcode enum (e.g. "MOV32ri") or /// empty if we can't resolve it. StringRef getOpcodeName(unsigned Opcode) const; - /// \brief Print the assembler register name. + /// Print the assembler register name. virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; bool getUseMarkup() const { return UseMarkup; } diff --git a/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h b/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h index dd3e1df477b4..484f03b4d854 100644 --- a/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h +++ b/contrib/llvm/include/llvm/MC/MCInstrAnalysis.h @@ -22,6 +22,8 @@ namespace llvm { +class MCRegisterInfo; + class MCInstrAnalysis { protected: friend class Target; @@ -60,7 +62,32 @@ public: return Info->get(Inst.getOpcode()).isTerminator(); } - /// \brief Given a branch instruction try to get the address the branch + /// Returns true if at least one of the register writes performed by + /// \param Inst implicitly clears the upper portion of all super-registers. + /// + /// Example: on X86-64, a write to EAX implicitly clears the upper half of + /// RAX. Also (still on x86) an XMM write perfomed by an AVX 128-bit + /// instruction implicitly clears the upper portion of the correspondent + /// YMM register. + /// + /// This method also updates an APInt which is used as mask of register + /// writes. There is one bit for every explicit/implicit write performed by + /// the instruction. If a write implicitly clears its super-registers, then + /// the corresponding bit is set (vic. the corresponding bit is cleared). + /// + /// The first bits in the APint are related to explicit writes. The remaining + /// bits are related to implicit writes. The sequence of writes follows the + /// machine operand sequence. For implicit writes, the sequence is defined by + /// the MCInstrDesc. + /// + /// The assumption is that the bit-width of the APInt is correctly set by + /// the caller. The default implementation conservatively assumes that none of + /// the writes clears the upper portion of a super-register. + virtual bool clearsSuperRegisters(const MCRegisterInfo &MRI, + const MCInst &Inst, + APInt &Writes) const; + + /// Given a branch instruction try to get the address the branch /// targets. Return true on success, and the address in Target. virtual bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, diff --git a/contrib/llvm/include/llvm/MC/MCInstrDesc.h b/contrib/llvm/include/llvm/MC/MCInstrDesc.h index ff4c756a66a1..3e000a2210e9 100644 --- a/contrib/llvm/include/llvm/MC/MCInstrDesc.h +++ b/contrib/llvm/include/llvm/MC/MCInstrDesc.h @@ -35,12 +35,12 @@ enum OperandConstraint { EARLY_CLOBBER // Operand is an early clobber register operand }; -/// \brief These are flags set on operands, but should be considered +/// These are flags set on operands, but should be considered /// private, all access should go through the MCOperandInfo accessors. /// See the accessors for a description of what these are. enum OperandFlags { LookupPtrRegClass = 0, Predicate, OptionalDef }; -/// \brief Operands are tagged with one of the values of this enum. +/// Operands are tagged with one of the values of this enum. enum OperandType { OPERAND_UNKNOWN = 0, OPERAND_IMMEDIATE = 1, @@ -60,42 +60,39 @@ enum OperandType { OPERAND_FIRST_TARGET = 12, }; -enum GenericOperandType { -}; - } -/// \brief This holds information about one operand of a machine instruction, +/// This holds information about one operand of a machine instruction, /// indicating the register class for register operands, etc. class MCOperandInfo { public: - /// \brief This specifies the register class enumeration of the operand + /// This specifies the register class enumeration of the operand /// if the operand is a register. If isLookupPtrRegClass is set, then this is /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to /// get a dynamic register class. int16_t RegClass; - /// \brief These are flags from the MCOI::OperandFlags enum. + /// These are flags from the MCOI::OperandFlags enum. uint8_t Flags; - /// \brief Information about the type of the operand. + /// Information about the type of the operand. uint8_t OperandType; - /// \brief The lower 16 bits are used to specify which constraints are set. + /// The lower 16 bits are used to specify which constraints are set. /// The higher 16 bits are used to specify the value of constraints (4 bits /// each). uint32_t Constraints; - /// \brief Set if this operand is a pointer value and it requires a callback + /// Set if this operand is a pointer value and it requires a callback /// to look up its register class. bool isLookupPtrRegClass() const { return Flags & (1 << MCOI::LookupPtrRegClass); } - /// \brief Set if this is one of the operands that made up of the predicate + /// Set if this is one of the operands that made up of the predicate /// operand that controls an isPredicable() instruction. bool isPredicate() const { return Flags & (1 << MCOI::Predicate); } - /// \brief Set if this operand is a optional def. + /// Set if this operand is a optional def. bool isOptionalDef() const { return Flags & (1 << MCOI::OptionalDef); } bool isGenericType() const { @@ -114,7 +111,7 @@ public: //===----------------------------------------------------------------------===// namespace MCID { -/// \brief These should be considered private to the implementation of the +/// These should be considered private to the implementation of the /// MCInstrDesc class. Clients should use the predicate methods on MCInstrDesc, /// not use these directly. These all correspond to bitfields in the /// MCInstrDesc::Flags field. @@ -130,6 +127,7 @@ enum Flag { IndirectBranch, Compare, MoveImm, + MoveReg, Bitcast, Select, DelaySlot, @@ -151,11 +149,12 @@ enum Flag { ExtractSubreg, InsertSubreg, Convergent, - Add + Add, + Trap }; } -/// \brief Describe properties that are true of each instruction in the target +/// Describe properties that are true of each instruction in the target /// description file. This captures information about side effects, register /// use and many other things. There is one instance of this struct for each /// target instruction class, and the MachineInstr class points to this struct @@ -177,12 +176,12 @@ public: // deprecated due to a "complex" reason, below. int64_t DeprecatedFeature; - // A complex method to determine is a certain is deprecated or not, and return - // the reason for deprecation. + // A complex method to determine if a certain instruction is deprecated or + // not, and return the reason for deprecation. bool (*ComplexDeprecationInfo)(MCInst &, const MCSubtargetInfo &, std::string &); - /// \brief Returns the value of the specific constraint if + /// Returns the value of the specific constraint if /// it is set. Returns -1 if it is not set. int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const { @@ -194,15 +193,15 @@ public: return -1; } - /// \brief Returns true if a certain instruction is deprecated and if so + /// Returns true if a certain instruction is deprecated and if so /// returns the reason in \p Info. bool getDeprecatedInfo(MCInst &MI, const MCSubtargetInfo &STI, std::string &Info) const; - /// \brief Return the opcode number for this descriptor. + /// Return the opcode number for this descriptor. unsigned getOpcode() const { return Opcode; } - /// \brief Return the number of declared MachineOperands for this + /// Return the number of declared MachineOperands for this /// MachineInstruction. Note that variadic (isVariadic() returns true) /// instructions may have additional operands at the end of the list, and note /// that the machine instruction may include implicit register def/uses as @@ -218,44 +217,50 @@ public: return make_range(opInfo_begin(), opInfo_end()); } - /// \brief Return the number of MachineOperands that are register + /// Return the number of MachineOperands that are register /// definitions. Register definitions always occur at the start of the /// machine operand list. This is the number of "outs" in the .td file, /// and does not include implicit defs. unsigned getNumDefs() const { return NumDefs; } - /// \brief Return flags of this instruction. + /// Return flags of this instruction. uint64_t getFlags() const { return Flags; } - /// \brief Return true if this instruction can have a variable number of + /// Return true if this instruction can have a variable number of /// operands. In this case, the variable operands will be after the normal /// operands but before the implicit definitions and uses (if any are /// present). bool isVariadic() const { return Flags & (1ULL << MCID::Variadic); } - /// \brief Set if this instruction has an optional definition, e.g. + /// Set if this instruction has an optional definition, e.g. /// ARM instructions which can set condition code if 's' bit is set. bool hasOptionalDef() const { return Flags & (1ULL << MCID::HasOptionalDef); } - /// \brief Return true if this is a pseudo instruction that doesn't + /// Return true if this is a pseudo instruction that doesn't /// correspond to a real machine instruction. bool isPseudo() const { return Flags & (1ULL << MCID::Pseudo); } - /// \brief Return true if the instruction is a return. + /// Return true if the instruction is a return. bool isReturn() const { return Flags & (1ULL << MCID::Return); } - /// \brief Return true if the instruction is an add instruction. + /// Return true if the instruction is an add instruction. bool isAdd() const { return Flags & (1ULL << MCID::Add); } - /// \brief Return true if the instruction is a call. + /// Return true if this instruction is a trap. + bool isTrap() const { return Flags & (1ULL << MCID::Trap); } + + /// Return true if the instruction is a register to register move. + bool isMoveReg() const { return Flags & (1ULL << MCID::MoveReg); } + + /// Return true if the instruction is a call. bool isCall() const { return Flags & (1ULL << MCID::Call); } - /// \brief Returns true if the specified instruction stops control flow + /// Returns true if the specified instruction stops control flow /// from executing the instruction immediately following it. Examples include /// unconditional branches and return instructions. bool isBarrier() const { return Flags & (1ULL << MCID::Barrier); } - /// \brief Returns true if this instruction part of the terminator for + /// Returns true if this instruction part of the terminator for /// a basic block. Typically this is things like return and branch /// instructions. /// @@ -263,17 +268,17 @@ public: /// but before control flow occurs. bool isTerminator() const { return Flags & (1ULL << MCID::Terminator); } - /// \brief Returns true if this is a conditional, unconditional, or + /// Returns true if this is a conditional, unconditional, or /// indirect branch. Predicates below can be used to discriminate between /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to /// get more information. bool isBranch() const { return Flags & (1ULL << MCID::Branch); } - /// \brief Return true if this is an indirect branch, such as a + /// Return true if this is an indirect branch, such as a /// branch through a register. bool isIndirectBranch() const { return Flags & (1ULL << MCID::IndirectBranch); } - /// \brief Return true if this is a branch which may fall + /// Return true if this is a branch which may fall /// through to the next instruction or may transfer control flow to some other /// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more /// information about this branch. @@ -281,7 +286,7 @@ public: return isBranch() & !isBarrier() & !isIndirectBranch(); } - /// \brief Return true if this is a branch which always + /// Return true if this is a branch which always /// transfers control flow to some other block. The /// TargetInstrInfo::AnalyzeBranch method can be used to get more information /// about this branch. @@ -289,40 +294,40 @@ public: return isBranch() & isBarrier() & !isIndirectBranch(); } - /// \brief Return true if this is a branch or an instruction which directly + /// Return true if this is a branch or an instruction which directly /// writes to the program counter. Considered 'may' affect rather than /// 'does' affect as things like predication are not taken into account. bool mayAffectControlFlow(const MCInst &MI, const MCRegisterInfo &RI) const; - /// \brief Return true if this instruction has a predicate operand + /// Return true if this instruction has a predicate operand /// that controls execution. It may be set to 'always', or may be set to other /// values. There are various methods in TargetInstrInfo that can be used to /// control and modify the predicate in this instruction. bool isPredicable() const { return Flags & (1ULL << MCID::Predicable); } - /// \brief Return true if this instruction is a comparison. + /// Return true if this instruction is a comparison. bool isCompare() const { return Flags & (1ULL << MCID::Compare); } - /// \brief Return true if this instruction is a move immediate + /// Return true if this instruction is a move immediate /// (including conditional moves) instruction. bool isMoveImmediate() const { return Flags & (1ULL << MCID::MoveImm); } - /// \brief Return true if this instruction is a bitcast instruction. + /// Return true if this instruction is a bitcast instruction. bool isBitcast() const { return Flags & (1ULL << MCID::Bitcast); } - /// \brief Return true if this is a select instruction. + /// Return true if this is a select instruction. bool isSelect() const { return Flags & (1ULL << MCID::Select); } - /// \brief Return true if this instruction cannot be safely + /// Return true if this instruction cannot be safely /// duplicated. For example, if the instruction has a unique labels attached /// to it, duplicating it would cause multiple definition errors. bool isNotDuplicable() const { return Flags & (1ULL << MCID::NotDuplicable); } - /// \brief Returns true if the specified instruction has a delay slot which + /// Returns true if the specified instruction has a delay slot which /// must be filled by the code generator. bool hasDelaySlot() const { return Flags & (1ULL << MCID::DelaySlot); } - /// \brief Return true for instructions that can be folded as memory operands + /// Return true for instructions that can be folded as memory operands /// in other instructions. The most common use for this is instructions that /// are simple loads from memory that don't modify the loaded value in any /// way, but it can also be used for instructions that can be expressed as @@ -331,7 +336,7 @@ public: /// that return a value in their only virtual register definition. bool canFoldAsLoad() const { return Flags & (1ULL << MCID::FoldableAsLoad); } - /// \brief Return true if this instruction behaves + /// Return true if this instruction behaves /// the same way as the generic REG_SEQUENCE instructions. /// E.g., on ARM, /// dX VMOVDRR rY, rZ @@ -343,7 +348,7 @@ public: /// override accordingly. bool isRegSequenceLike() const { return Flags & (1ULL << MCID::RegSequence); } - /// \brief Return true if this instruction behaves + /// Return true if this instruction behaves /// the same way as the generic EXTRACT_SUBREG instructions. /// E.g., on ARM, /// rX, rY VMOVRRD dZ @@ -358,7 +363,7 @@ public: return Flags & (1ULL << MCID::ExtractSubreg); } - /// \brief Return true if this instruction behaves + /// Return true if this instruction behaves /// the same way as the generic INSERT_SUBREG instructions. /// E.g., on ARM, /// dX = VSETLNi32 dY, rZ, Imm @@ -371,7 +376,7 @@ public: bool isInsertSubregLike() const { return Flags & (1ULL << MCID::InsertSubreg); } - /// \brief Return true if this instruction is convergent. + /// Return true if this instruction is convergent. /// /// Convergent instructions may not be made control-dependent on any /// additional values. @@ -381,18 +386,18 @@ public: // Side Effect Analysis //===--------------------------------------------------------------------===// - /// \brief Return true if this instruction could possibly read memory. + /// Return true if this instruction could possibly read memory. /// Instructions with this flag set are not necessarily simple load /// instructions, they may load a value and modify it, for example. bool mayLoad() const { return Flags & (1ULL << MCID::MayLoad); } - /// \brief Return true if this instruction could possibly modify memory. + /// Return true if this instruction could possibly modify memory. /// Instructions with this flag set are not necessarily simple store /// instructions, they may store a modified value based on their operands, or /// may not actually modify anything, for example. bool mayStore() const { return Flags & (1ULL << MCID::MayStore); } - /// \brief Return true if this instruction has side + /// Return true if this instruction has side /// effects that are not modeled by other flags. This does not return true /// for instructions whose effects are captured by: /// @@ -412,7 +417,7 @@ public: // Flags that indicate whether an instruction can be modified by a method. //===--------------------------------------------------------------------===// - /// \brief Return true if this may be a 2- or 3-address instruction (of the + /// Return true if this may be a 2- or 3-address instruction (of the /// form "X = op Y, Z, ..."), which produces the same result if Y and Z are /// exchanged. If this flag is set, then the /// TargetInstrInfo::commuteInstruction method may be used to hack on the @@ -424,7 +429,7 @@ public: /// commute them. bool isCommutable() const { return Flags & (1ULL << MCID::Commutable); } - /// \brief Return true if this is a 2-address instruction which can be changed + /// Return true if this is a 2-address instruction which can be changed /// into a 3-address instruction if needed. Doing this transformation can be /// profitable in the register allocator, because it means that the /// instruction can use a 2-address form if possible, but degrade into a less @@ -442,7 +447,7 @@ public: return Flags & (1ULL << MCID::ConvertibleTo3Addr); } - /// \brief Return true if this instruction requires custom insertion support + /// Return true if this instruction requires custom insertion support /// when the DAG scheduler is inserting it into a machine basic block. If /// this is true for the instruction, it basically means that it is a pseudo /// instruction used at SelectionDAG time that is expanded out into magic code @@ -454,13 +459,13 @@ public: return Flags & (1ULL << MCID::UsesCustomInserter); } - /// \brief Return true if this instruction requires *adjustment* after + /// Return true if this instruction requires *adjustment* after /// instruction selection by calling a target hook. For example, this can be /// used to fill in ARM 's' optional operand depending on whether the /// conditional flag register is used. bool hasPostISelHook() const { return Flags & (1ULL << MCID::HasPostISelHook); } - /// \brief Returns true if this instruction is a candidate for remat. This + /// Returns true if this instruction is a candidate for remat. This /// flag is only used in TargetInstrInfo method isTriviallyRematerializable. /// /// If this flag is set, the isReallyTriviallyReMaterializable() @@ -470,7 +475,7 @@ public: return Flags & (1ULL << MCID::Rematerializable); } - /// \brief Returns true if this instruction has the same cost (or less) than a + /// Returns true if this instruction has the same cost (or less) than a /// move instruction. This is useful during certain types of optimizations /// (e.g., remat during two-address conversion or machine licm) where we would /// like to remat or hoist the instruction, but not if it costs more than @@ -481,7 +486,7 @@ public: /// for different subtargets. bool isAsCheapAsAMove() const { return Flags & (1ULL << MCID::CheapAsAMove); } - /// \brief Returns true if this instruction source operands have special + /// Returns true if this instruction source operands have special /// register allocation requirements that are not captured by the operand /// register classes. e.g. ARM::STRD's two source registers must be an even / /// odd pair, ARM::STM registers have to be in ascending order. Post-register @@ -491,7 +496,7 @@ public: return Flags & (1ULL << MCID::ExtraSrcRegAllocReq); } - /// \brief Returns true if this instruction def operands have special register + /// Returns true if this instruction def operands have special register /// allocation requirements that are not captured by the operand register /// classes. e.g. ARM::LDRD's two def registers must be an even / odd pair, /// ARM::LDM registers have to be in ascending order. Post-register @@ -501,7 +506,7 @@ public: return Flags & (1ULL << MCID::ExtraDefRegAllocReq); } - /// \brief Return a list of registers that are potentially read by any + /// Return a list of registers that are potentially read by any /// instance of this machine instruction. For example, on X86, the "adc" /// instruction adds two register operands and adds the carry bit in from the /// flags register. In this case, the instruction is marked as implicitly @@ -511,7 +516,7 @@ public: /// This method returns null if the instruction has no implicit uses. const MCPhysReg *getImplicitUses() const { return ImplicitUses; } - /// \brief Return the number of implicit uses this instruction has. + /// Return the number of implicit uses this instruction has. unsigned getNumImplicitUses() const { if (!ImplicitUses) return 0; @@ -521,7 +526,7 @@ public: return i; } - /// \brief Return a list of registers that are potentially written by any + /// Return a list of registers that are potentially written by any /// instance of this machine instruction. For example, on X86, many /// instructions implicitly set the flags register. In this case, they are /// marked as setting the FLAGS. Likewise, many instructions always deposit @@ -533,7 +538,7 @@ public: /// This method returns null if the instruction has no implicit defs. const MCPhysReg *getImplicitDefs() const { return ImplicitDefs; } - /// \brief Return the number of implicit defs this instruct has. + /// Return the number of implicit defs this instruct has. unsigned getNumImplicitDefs() const { if (!ImplicitDefs) return 0; @@ -543,7 +548,7 @@ public: return i; } - /// \brief Return true if this instruction implicitly + /// Return true if this instruction implicitly /// uses the specified physical register. bool hasImplicitUseOfPhysReg(unsigned Reg) const { if (const MCPhysReg *ImpUses = ImplicitUses) @@ -553,22 +558,22 @@ public: return false; } - /// \brief Return true if this instruction implicitly + /// Return true if this instruction implicitly /// defines the specified physical register. bool hasImplicitDefOfPhysReg(unsigned Reg, const MCRegisterInfo *MRI = nullptr) const; - /// \brief Return the scheduling class for this instruction. The + /// Return the scheduling class for this instruction. The /// scheduling class is an index into the InstrItineraryData table. This /// returns zero if there is no known scheduling information for the /// instruction. unsigned getSchedClass() const { return SchedClass; } - /// \brief Return the number of bytes in the encoding of this instruction, + /// Return the number of bytes in the encoding of this instruction, /// or zero if the encoding size cannot be known from the opcode. unsigned getSize() const { return Size; } - /// \brief Find the index of the first operand in the + /// Find the index of the first operand in the /// operand list that is used to represent the predicate. It returns -1 if /// none is found. int findFirstPredOperandIdx() const { @@ -580,7 +585,7 @@ public: return -1; } - /// \brief Return true if this instruction defines the specified physical + /// Return true if this instruction defines the specified physical /// register, either explicitly or implicitly. bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg, const MCRegisterInfo &RI) const; diff --git a/contrib/llvm/include/llvm/MC/MCInstrInfo.h b/contrib/llvm/include/llvm/MC/MCInstrInfo.h index 80f1f320b7c2..18da87cf8929 100644 --- a/contrib/llvm/include/llvm/MC/MCInstrInfo.h +++ b/contrib/llvm/include/llvm/MC/MCInstrInfo.h @@ -20,7 +20,7 @@ namespace llvm { //--------------------------------------------------------------------------- -/// \brief Interface to description of machine instruction set. +/// Interface to description of machine instruction set. class MCInstrInfo { const MCInstrDesc *Desc; // Raw array to allow static init'n const unsigned *InstrNameIndices; // Array for name indices in InstrNameData @@ -28,7 +28,7 @@ class MCInstrInfo { unsigned NumOpcodes; // Number of entries in the desc array public: - /// \brief Initialize MCInstrInfo, called by TableGen auto-generated routines. + /// Initialize MCInstrInfo, called by TableGen auto-generated routines. /// *DO NOT USE*. void InitMCInstrInfo(const MCInstrDesc *D, const unsigned *NI, const char *ND, unsigned NO) { @@ -40,14 +40,14 @@ public: unsigned getNumOpcodes() const { return NumOpcodes; } - /// \brief Return the machine instruction descriptor that corresponds to the + /// Return the machine instruction descriptor that corresponds to the /// specified instruction opcode. const MCInstrDesc &get(unsigned Opcode) const { assert(Opcode < NumOpcodes && "Invalid opcode!"); return Desc[Opcode]; } - /// \brief Returns the name for the instructions with the given opcode. + /// Returns the name for the instructions with the given opcode. StringRef getName(unsigned Opcode) const { assert(Opcode < NumOpcodes && "Invalid opcode!"); return StringRef(&InstrNameData[InstrNameIndices[Opcode]]); diff --git a/contrib/llvm/include/llvm/MC/MCInstrItineraries.h b/contrib/llvm/include/llvm/MC/MCInstrItineraries.h index 4443dd113715..fe81376e0db7 100644 --- a/contrib/llvm/include/llvm/MC/MCInstrItineraries.h +++ b/contrib/llvm/include/llvm/MC/MCInstrItineraries.h @@ -67,12 +67,12 @@ struct InstrStage { int NextCycles_; ///< Number of machine cycles to next stage ReservationKinds Kind_; ///< Kind of the FU reservation - /// \brief Returns the number of cycles the stage is occupied. + /// Returns the number of cycles the stage is occupied. unsigned getCycles() const { return Cycles_; } - /// \brief Returns the choice of FUs. + /// Returns the choice of FUs. unsigned getUnits() const { return Units_; } @@ -81,7 +81,7 @@ struct InstrStage { return Kind_; } - /// \brief Returns the number of cycles from the start of this stage to the + /// Returns the number of cycles from the start of this stage to the /// start of the next stage in the itinerary unsigned getNextCycles() const { return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; @@ -94,11 +94,11 @@ struct InstrStage { /// cycle in which operands are read and written. /// struct InstrItinerary { - int NumMicroOps; ///< # of micro-ops, -1 means it's variable - unsigned FirstStage; ///< Index of first stage in itinerary - unsigned LastStage; ///< Index of last + 1 stage in itinerary - unsigned FirstOperandCycle; ///< Index of first operand rd/wr - unsigned LastOperandCycle; ///< Index of last + 1 operand rd/wr + int16_t NumMicroOps; ///< # of micro-ops, -1 means it's variable + uint16_t FirstStage; ///< Index of first stage in itinerary + uint16_t LastStage; ///< Index of last + 1 stage in itinerary + uint16_t FirstOperandCycle; ///< Index of first operand rd/wr + uint16_t LastOperandCycle; ///< Index of last + 1 operand rd/wr }; //===----------------------------------------------------------------------===// @@ -120,28 +120,28 @@ public: : SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(SchedModel.InstrItineraries) {} - /// \brief Returns true if there are no itineraries. + /// Returns true if there are no itineraries. bool isEmpty() const { return Itineraries == nullptr; } - /// \brief Returns true if the index is for the end marker itinerary. + /// Returns true if the index is for the end marker itinerary. bool isEndMarker(unsigned ItinClassIndx) const { - return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && - (Itineraries[ItinClassIndx].LastStage == ~0U)); + return ((Itineraries[ItinClassIndx].FirstStage == UINT16_MAX) && + (Itineraries[ItinClassIndx].LastStage == UINT16_MAX)); } - /// \brief Return the first stage of the itinerary. + /// Return the first stage of the itinerary. const InstrStage *beginStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; return Stages + StageIdx; } - /// \brief Return the last+1 stage of the itinerary. + /// Return the last+1 stage of the itinerary. const InstrStage *endStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; return Stages + StageIdx; } - /// \brief Return the total stage latency of the given class. The latency is + /// Return the total stage latency of the given class. The latency is /// the maximum completion time for any stage in the itinerary. If no stages /// exist, it defaults to one cycle. unsigned getStageLatency(unsigned ItinClassIndx) const { @@ -160,7 +160,7 @@ public: return Latency; } - /// \brief Return the cycle for the given class and operand. Return -1 if no + /// Return the cycle for the given class and operand. Return -1 if no /// cycle is specified for the operand. int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { if (isEmpty()) @@ -174,7 +174,7 @@ public: return (int)OperandCycles[FirstIdx + OperandIdx]; } - /// \brief Return true if there is a pipeline forwarding between instructions + /// Return true if there is a pipeline forwarding between instructions /// of itinerary classes DefClass and UseClasses so that value produced by an /// instruction of itinerary class DefClass, operand index DefIdx can be /// bypassed when it's read by an instruction of itinerary class UseClass, @@ -197,7 +197,7 @@ public: Forwardings[FirstUseIdx + UseIdx]; } - /// \brief Compute and return the use operand latency of a given itinerary + /// Compute and return the use operand latency of a given itinerary /// class and operand index if the value is produced by an instruction of the /// specified itinerary class and def operand index. int getOperandLatency(unsigned DefClass, unsigned DefIdx, @@ -221,7 +221,7 @@ public: return UseCycle; } - /// \brief Return the number of micro-ops that the given class decodes to. + /// Return the number of micro-ops that the given class decodes to. /// Return -1 for classes that require dynamic lookup via TargetInstrInfo. int getNumMicroOps(unsigned ItinClassIndx) const { if (isEmpty()) diff --git a/contrib/llvm/include/llvm/MC/MCLabel.h b/contrib/llvm/include/llvm/MC/MCLabel.h index b6579fd654ab..aaf70691fc01 100644 --- a/contrib/llvm/include/llvm/MC/MCLabel.h +++ b/contrib/llvm/include/llvm/MC/MCLabel.h @@ -18,11 +18,11 @@ namespace llvm { class raw_ostream; -/// \brief Instances of this class represent a label name in the MC file, +/// Instances of this class represent a label name in the MC file, /// and MCLabel are created and uniqued by the MCContext class. MCLabel /// should only be constructed for valid instances in the object file. class MCLabel { - // \brief The instance number of this Directional Local Label. + // The instance number of this Directional Local Label. unsigned Instance; private: // MCContext creates and uniques these. @@ -34,16 +34,16 @@ public: MCLabel(const MCLabel &) = delete; MCLabel &operator=(const MCLabel &) = delete; - /// \brief Get the current instance of this Directional Local Label. + /// Get the current instance of this Directional Local Label. unsigned getInstance() const { return Instance; } - /// \brief Increment the current instance of this Directional Local Label. + /// Increment the current instance of this Directional Local Label. unsigned incInstance() { return ++Instance; } - /// \brief Print the value to the stream \p OS. + /// Print the value to the stream \p OS. void print(raw_ostream &OS) const; - /// \brief Print the value to stderr. + /// Print the value to stderr. void dump() const; }; diff --git a/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h b/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h index 594869f74632..22fbeb72a4ec 100644 --- a/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h +++ b/contrib/llvm/include/llvm/MC/MCMachObjectWriter.h @@ -26,7 +26,7 @@ namespace llvm { class MachObjectWriter; -class MCMachObjectTargetWriter { +class MCMachObjectTargetWriter : public MCObjectTargetWriter { const unsigned Is64Bit : 1; const uint32_t CPUType; const uint32_t CPUSubtype; @@ -43,6 +43,11 @@ protected: public: virtual ~MCMachObjectTargetWriter(); + virtual Triple::ObjectFormatType getFormat() const { return Triple::MachO; } + static bool classof(const MCObjectTargetWriter *W) { + return W->getFormat() == Triple::MachO; + } + /// \name Lifetime Management /// @{ @@ -116,11 +121,15 @@ class MachObjectWriter : public MCObjectWriter { MachSymbolData *findSymbolData(const MCSymbol &Sym); + void writeWithPadding(StringRef Str, uint64_t Size); + public: MachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW, raw_pwrite_stream &OS, bool IsLittleEndian) - : MCObjectWriter(OS, IsLittleEndian), - TargetObjectWriter(std::move(MOTW)) {} + : TargetObjectWriter(std::move(MOTW)), + W(OS, IsLittleEndian ? support::little : support::big) {} + + support::endian::Writer W; const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const; @@ -260,7 +269,7 @@ public: const MCFragment &FB, bool InSet, bool IsPCRel) const override; - void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; + uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; }; /// Construct a new Mach-O writer instance. diff --git a/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h b/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h index 79bf2b97015f..3a27ef8c8fee 100644 --- a/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h +++ b/contrib/llvm/include/llvm/MC/MCObjectFileInfo.h @@ -14,7 +14,9 @@ #ifndef LLVM_MC_MCOBJECTFILEINFO_H #define LLVM_MC_MCOBJECTFILEINFO_H +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Triple.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/Support/CodeGen.h" namespace llvm { @@ -79,6 +81,7 @@ protected: MCSection *DwarfAbbrevSection; MCSection *DwarfInfoSection; MCSection *DwarfLineSection; + MCSection *DwarfLineStrSection; MCSection *DwarfFrameSection; MCSection *DwarfPubTypesSection; const MCSection *DwarfDebugInlineSection; @@ -91,11 +94,11 @@ protected: // can be enabled by a compiler flag. MCSection *DwarfPubNamesSection; - /// DWARF5 Experimental Debug Info Sections - /// DwarfAccelNamesSection, DwarfAccelObjCSection, - /// DwarfAccelNamespaceSection, DwarfAccelTypesSection - - /// If we use the DWARF accelerated hash tables then we want to emit these - /// sections. + /// Accelerator table sections. DwarfDebugNamesSection is the DWARF v5 + /// accelerator table, while DwarfAccelNamesSection, DwarfAccelObjCSection, + /// DwarfAccelNamespaceSection, DwarfAccelTypesSection are pre-DWARF v5 + /// extensions. + MCSection *DwarfDebugNamesSection; MCSection *DwarfAccelNamesSection; MCSection *DwarfAccelObjCSection; MCSection *DwarfAccelNamespaceSection; @@ -113,6 +116,11 @@ protected: /// The DWARF v5 string offset and address table sections. MCSection *DwarfStrOffSection; MCSection *DwarfAddrSection; + /// The DWARF v5 range list section. + MCSection *DwarfRnglistsSection; + + /// The DWARF v5 range list section for fission. + MCSection *DwarfRnglistsDWOSection; // These are for Fission DWP files. MCSection *DwarfCUIndexSection; @@ -157,6 +165,7 @@ protected: /// Section containing metadata on function stack sizes. MCSection *StackSizesSection; + mutable DenseMap<const MCSymbol *, unsigned> StackSizesUniquing; // ELF specific sections. MCSection *DataRelROSection; @@ -182,6 +191,7 @@ protected: MCSection *ConstTextCoalSection; MCSection *ConstDataSection; MCSection *DataCoalSection; + MCSection *ConstDataCoalSection; MCSection *DataCommonSection; MCSection *DataBSSSection; MCSection *FourByteConstantSection; @@ -196,6 +206,7 @@ protected: MCSection *PDataSection; MCSection *XDataSection; MCSection *SXDataSection; + MCSection *GFIDsSection; public: void InitMCObjectFileInfo(const Triple &TT, bool PIC, MCContext &ctx, @@ -233,6 +244,7 @@ public: MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } MCSection *getDwarfLineSection() const { return DwarfLineSection; } + MCSection *getDwarfLineStrSection() const { return DwarfLineStrSection; } MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } MCSection *getDwarfPubNamesSection() const { return DwarfPubNamesSection; } MCSection *getDwarfPubTypesSection() const { return DwarfPubTypesSection; } @@ -249,9 +261,12 @@ public: MCSection *getDwarfLocSection() const { return DwarfLocSection; } MCSection *getDwarfARangesSection() const { return DwarfARangesSection; } MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } + MCSection *getDwarfRnglistsSection() const { return DwarfRnglistsSection; } MCSection *getDwarfMacinfoSection() const { return DwarfMacinfoSection; } - // DWARF5 Experimental Debug Info Sections + MCSection *getDwarfDebugNamesSection() const { + return DwarfDebugNamesSection; + } MCSection *getDwarfAccelNamesSection() const { return DwarfAccelNamesSection; } @@ -272,6 +287,9 @@ public: MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; } MCSection *getDwarfStrOffSection() const { return DwarfStrOffSection; } MCSection *getDwarfAddrSection() const { return DwarfAddrSection; } + MCSection *getDwarfRnglistsDWOSection() const { + return DwarfRnglistsDWOSection; + } MCSection *getDwarfCUIndexSection() const { return DwarfCUIndexSection; } MCSection *getDwarfTUIndexSection() const { return DwarfTUIndexSection; } MCSection *getDwarfSwiftASTSection() const { return DwarfSwiftASTSection; } @@ -293,7 +311,7 @@ public: MCSection *getStackMapSection() const { return StackMapSection; } MCSection *getFaultMapSection() const { return FaultMapSection; } - MCSection *getStackSizesSection() const { return StackSizesSection; } + MCSection *getStackSizesSection(const MCSection &TextSec) const; // ELF specific sections. MCSection *getDataRelROSection() const { return DataRelROSection; } @@ -323,6 +341,9 @@ public: } const MCSection *getConstDataSection() const { return ConstDataSection; } const MCSection *getDataCoalSection() const { return DataCoalSection; } + const MCSection *getConstDataCoalSection() const { + return ConstDataCoalSection; + } const MCSection *getDataCommonSection() const { return DataCommonSection; } MCSection *getDataBSSSection() const { return DataBSSSection; } const MCSection *getFourByteConstantSection() const { @@ -349,6 +370,7 @@ public: MCSection *getPDataSection() const { return PDataSection; } MCSection *getXDataSection() const { return XDataSection; } MCSection *getSXDataSection() const { return SXDataSection; } + MCSection *getGFIDsSection() const { return GFIDsSection; } MCSection *getEHFrameSection() { return EHFrameSection; diff --git a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h index 43ed00b4a7a7..035206dce939 100644 --- a/contrib/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCObjectStreamer.h @@ -26,7 +26,7 @@ class MCAsmBackend; class raw_ostream; class raw_pwrite_stream; -/// \brief Streaming object file generation interface. +/// Streaming object file generation interface. /// /// This class provides an implementation of the MCStreamer interface which is /// suitable for use with the assembler backend. Specific object file formats @@ -34,9 +34,6 @@ class raw_pwrite_stream; /// to that file format or custom semantics expected by the object writer /// implementation. class MCObjectStreamer : public MCStreamer { - std::unique_ptr<MCObjectWriter> ObjectWriter; - std::unique_ptr<MCAsmBackend> TAB; - std::unique_ptr<MCCodeEmitter> Emitter; std::unique_ptr<MCAssembler> Assembler; MCSection::iterator CurInsertionPoint; bool EmitEHFrame; @@ -51,7 +48,7 @@ class MCObjectStreamer : public MCStreamer { protected: MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter); ~MCObjectStreamer(); @@ -76,7 +73,9 @@ public: /// Get a data fragment to write into, creating a new one if the current /// fragment is not a data fragment. - MCDataFragment *getOrCreateDataFragment(); + /// Optionally a \p STI can be passed in so that a new fragment is created + /// if the Subtarget differs from the current fragment. + MCDataFragment *getOrCreateDataFragment(const MCSubtargetInfo* STI = nullptr); MCPaddingFragment *getOrCreatePaddingFragment(); protected: @@ -91,8 +90,11 @@ protected: public: void visitUsedSymbol(const MCSymbol &Sym) override; - MCAssembler &getAssembler() { return *Assembler; } + /// Create a dummy fragment to assign any pending labels. + void flushPendingLabels() { flushPendingLabels(nullptr); } + MCAssembler &getAssembler() { return *Assembler; } + MCAssembler *getAssemblerPtr() override; /// \name MCStreamer Interface /// @{ @@ -108,7 +110,7 @@ public: void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, bool = false) override; - /// \brief Emit an instruction to a special fragment, because this instruction + /// Emit an instruction to a special fragment, because this instruction /// can change its size during relaxation. virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &); @@ -159,7 +161,8 @@ public: void EmitGPRel32Value(const MCExpr *Value) override; void EmitGPRel64Value(const MCExpr *Value) override; bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc Loc) override; + const MCExpr *Expr, SMLoc Loc, + const MCSubtargetInfo &STI) override; using MCStreamer::emitFill; void emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc = SMLoc()) override; @@ -167,6 +170,9 @@ public: SMLoc Loc = SMLoc()) override; void EmitFileDirective(StringRef Filename) override; + void EmitAddrsig() override; + void EmitAddrsigSym(const MCSymbol *Sym) override; + void FinishImpl() override; /// Emit the absolute difference between two symbols if possible. @@ -179,6 +185,9 @@ public: void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) override; + void emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, + const MCSymbol *Lo) override; + bool mayHaveInstructions(MCSection &Sec) const override; }; diff --git a/contrib/llvm/include/llvm/MC/MCObjectWriter.h b/contrib/llvm/include/llvm/MC/MCObjectWriter.h index cd90690fb186..8bae2bf20083 100644 --- a/contrib/llvm/include/llvm/MC/MCObjectWriter.h +++ b/contrib/llvm/include/llvm/MC/MCObjectWriter.h @@ -12,6 +12,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/raw_ostream.h" @@ -36,22 +37,9 @@ class MCValue; /// points. Once assembly is complete, the object writer is given the /// MCAssembler instance, which contains all the symbol and section data which /// should be emitted as part of writeObject(). -/// -/// The object writer also contains a number of helper methods for writing -/// binary data to the output stream. class MCObjectWriter { - raw_pwrite_stream *OS; - protected: - unsigned IsLittleEndian : 1; - - // Can only create subclasses. - MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian) - : OS(&OS), IsLittleEndian(IsLittleEndian) {} - - unsigned getInitialOffset() { - return OS->tell(); - } + MCObjectWriter() = default; public: MCObjectWriter(const MCObjectWriter &) = delete; @@ -61,11 +49,6 @@ public: /// lifetime management virtual void reset() {} - bool isLittleEndian() const { return IsLittleEndian; } - - raw_pwrite_stream &getStream() { return *OS; } - void setStream(raw_pwrite_stream &NewOS) { OS = &NewOS; } - /// \name High-Level API /// @{ @@ -109,90 +92,31 @@ public: bool InSet, bool IsPCRel) const; - /// Write the object file. + /// Tell the object writer to emit an address-significance table during + /// writeObject(). If this function is not called, all symbols are treated as + /// address-significant. + virtual void emitAddrsigSection() {} + + /// Record the given symbol in the address-significance table to be written + /// diring writeObject(). + virtual void addAddrsigSymbol(const MCSymbol *Sym) {} + + /// Write the object file and returns the number of bytes written. /// /// This routine is called by the assembler after layout and relaxation is /// complete, fixups have been evaluated and applied, and relocations /// generated. - virtual void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0; + virtual uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0; /// @} - /// \name Binary Output - /// @{ - - void write8(uint8_t Value) { *OS << char(Value); } - - void writeLE16(uint16_t Value) { - support::endian::Writer<support::little>(*OS).write(Value); - } - - void writeLE32(uint32_t Value) { - support::endian::Writer<support::little>(*OS).write(Value); - } - - void writeLE64(uint64_t Value) { - support::endian::Writer<support::little>(*OS).write(Value); - } - - void writeBE16(uint16_t Value) { - support::endian::Writer<support::big>(*OS).write(Value); - } - - void writeBE32(uint32_t Value) { - support::endian::Writer<support::big>(*OS).write(Value); - } - - void writeBE64(uint64_t Value) { - support::endian::Writer<support::big>(*OS).write(Value); - } - - void write16(uint16_t Value) { - if (IsLittleEndian) - writeLE16(Value); - else - writeBE16(Value); - } - - void write32(uint32_t Value) { - if (IsLittleEndian) - writeLE32(Value); - else - writeBE32(Value); - } - - void write64(uint64_t Value) { - if (IsLittleEndian) - writeLE64(Value); - else - writeBE64(Value); - } - - void WriteZeros(unsigned N) { - const char Zeros[16] = {0}; - - for (unsigned i = 0, e = N / 16; i != e; ++i) - *OS << StringRef(Zeros, 16); - - *OS << StringRef(Zeros, N % 16); - } - - void writeBytes(const SmallVectorImpl<char> &ByteVec, - unsigned ZeroFillSize = 0) { - writeBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize); - } - - void writeBytes(StringRef Str, unsigned ZeroFillSize = 0) { - // TODO: this version may need to go away once all fragment contents are - // converted to SmallVector<char, N> - assert( - (ZeroFillSize == 0 || Str.size() <= ZeroFillSize) && - "data size greater than fill size, unexpected large write will occur"); - *OS << Str; - if (ZeroFillSize) - WriteZeros(ZeroFillSize - Str.size()); - } +}; - /// @} +/// Base class for classes that define behaviour that is specific to both the +/// target and the object format. +class MCObjectTargetWriter { +public: + virtual ~MCObjectTargetWriter() = default; + virtual Triple::ObjectFormatType getFormat() const = 0; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h index 7836ece2d688..10550b3370e8 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmLexer.h @@ -10,11 +10,9 @@ #ifndef LLVM_MC_MCPARSER_MCASMLEXER_H #define LLVM_MC_MCPARSER_MCASMLEXER_H -#include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/SMLoc.h" +#include "llvm/MC/MCAsmMacro.h" #include <algorithm> #include <cassert> #include <cstddef> @@ -23,113 +21,6 @@ namespace llvm { -/// Target independent representation for an assembler token. -class AsmToken { -public: - enum TokenKind { - // Markers - Eof, Error, - - // String values. - Identifier, - String, - - // Integer values. - Integer, - BigNum, // larger than 64 bits - - // Real values. - Real, - - // Comments - Comment, - HashDirective, - // No-value. - EndOfStatement, - Colon, - Space, - Plus, Minus, Tilde, - Slash, // '/' - BackSlash, // '\' - LParen, RParen, LBrac, RBrac, LCurly, RCurly, - Star, Dot, Comma, Dollar, Equal, EqualEqual, - - Pipe, PipePipe, Caret, - Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash, - Less, LessEqual, LessLess, LessGreater, - Greater, GreaterEqual, GreaterGreater, At, - - // MIPS unary expression operators such as %neg. - PercentCall16, PercentCall_Hi, PercentCall_Lo, PercentDtprel_Hi, - PercentDtprel_Lo, PercentGot, PercentGot_Disp, PercentGot_Hi, PercentGot_Lo, - PercentGot_Ofst, PercentGot_Page, PercentGottprel, PercentGp_Rel, PercentHi, - PercentHigher, PercentHighest, PercentLo, PercentNeg, PercentPcrel_Hi, - PercentPcrel_Lo, PercentTlsgd, PercentTlsldm, PercentTprel_Hi, - PercentTprel_Lo - }; - -private: - TokenKind Kind; - - /// A reference to the entire token contents; this is always a pointer into - /// a memory buffer owned by the source manager. - StringRef Str; - - APInt IntVal; - -public: - AsmToken() = default; - AsmToken(TokenKind Kind, StringRef Str, APInt IntVal) - : Kind(Kind), Str(Str), IntVal(std::move(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; } - bool isNot(TokenKind K) const { return Kind != K; } - - SMLoc getLoc() const; - SMLoc getEndLoc() const; - SMRange getLocRange() const; - - /// Get the contents of a string token (without quotes). - StringRef getStringContents() const { - assert(Kind == String && "This token isn't a string!"); - return Str.slice(1, Str.size() - 1); - } - - /// Get the identifier string for the current token, which should be an - /// identifier or a string. This gets the portion of the string which should - /// be used as the identifier, e.g., it does not include the quotes on - /// strings. - StringRef getIdentifier() const { - if (Kind == Identifier) - return getString(); - return getStringContents(); - } - - /// Get the string for the current token, this includes all characters (for - /// example, the quotes on strings) in the token. - /// - /// The returned StringRef points into the source manager's memory buffer, and - /// is safe to store across calls to Lex(). - StringRef getString() const { return Str; } - - // FIXME: Don't compute this in advance, it makes every token larger, and is - // also not generally what we want (it is nicer for recovery etc. to lex 123br - // 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; - } -}; - /// A callback class which is notified of each comment in an assembly file as /// it is lexed. class AsmCommentConsumer { diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h index 0f79c4777ea9..0d56f36fbae8 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParser.h @@ -91,7 +91,7 @@ private: IdKind Kind; }; -/// \brief Generic Sema callback for assembly parser. +/// Generic Sema callback for assembly parser. class MCAsmParserSemaCallback { public: virtual ~MCAsmParserSemaCallback(); @@ -105,7 +105,7 @@ public: unsigned &Offset) = 0; }; -/// \brief Generic assembler parser interface, for use by target specific +/// Generic assembler parser interface, for use by target specific /// assembly parsers. class MCAsmParser { public: @@ -153,7 +153,7 @@ public: virtual MCContext &getContext() = 0; - /// \brief Return the output streamer for the assembler. + /// Return the output streamer for the assembler. virtual MCStreamer &getStreamer() = 0; MCTargetAsmParser &getTargetParser() const { return *TargetParser; } @@ -168,13 +168,13 @@ public: void setEnablePrintSchedInfo(bool Value) { EnablePrintSchedInfo = Value; } bool shouldPrintSchedInfo() { return EnablePrintSchedInfo; } - /// \brief Run the parser on the input source buffer. + /// Run the parser on the input source buffer. virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; virtual void setParsingInlineAsm(bool V) = 0; virtual bool isParsingInlineAsm() = 0; - /// \brief Parse MS-style inline assembly. + /// Parse MS-style inline assembly. virtual bool parseMSInlineAsm( void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls, @@ -182,22 +182,22 @@ public: SmallVectorImpl<std::string> &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0; - /// \brief Emit a note at the location \p L, with the message \p Msg. + /// Emit a note at the location \p L, with the message \p Msg. virtual void Note(SMLoc L, const Twine &Msg, SMRange Range = None) = 0; - /// \brief Emit a warning at the location \p L, with the message \p Msg. + /// Emit a warning at the location \p L, with the message \p Msg. /// /// \return The return value is true, if warnings are fatal. virtual bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) = 0; - /// \brief Return an error at the location \p L, with the message \p Msg. This + /// Return an error at the location \p L, with the message \p Msg. This /// may be modified before being emitted. /// /// \return The return value is always true, as an idiomatic convenience to /// clients. bool Error(SMLoc L, const Twine &Msg, SMRange Range = None); - /// \brief Emit an error at the location \p L, with the message \p Msg. + /// Emit an error at the location \p L, with the message \p Msg. /// /// \return The return value is always true, as an idiomatic convenience to /// clients. @@ -214,21 +214,23 @@ public: return rv; } + void clearPendingErrors() { PendingErrors.clear(); } + bool addErrorSuffix(const Twine &Suffix); - /// \brief Get the next AsmToken in the stream, possibly handling file + /// Get the next AsmToken in the stream, possibly handling file /// inclusion first. virtual const AsmToken &Lex() = 0; - /// \brief Get the current AsmToken from the stream. + /// Get the current AsmToken from the stream. const AsmToken &getTok() const; - /// \brief Report an error at the current lexer location. + /// Report an error at the current lexer location. bool TokError(const Twine &Msg, SMRange Range = None); bool parseTokenLoc(SMLoc &Loc); bool parseToken(AsmToken::TokenKind T, const Twine &Msg = "unexpected token"); - /// \brief Attempt to parse and consume token, returning true on + /// Attempt to parse and consume token, returning true on /// success. bool parseOptionalToken(AsmToken::TokenKind T); @@ -241,23 +243,23 @@ public: bool check(bool P, const Twine &Msg); bool check(bool P, SMLoc Loc, const Twine &Msg); - /// \brief Parse an identifier or string (as a quoted identifier) and set \p + /// Parse an identifier or string (as a quoted identifier) and set \p /// Res to the identifier contents. virtual bool parseIdentifier(StringRef &Res) = 0; - /// \brief Parse up to the end of statement and return the contents from the + /// Parse up to the end of statement and return the contents from the /// current token until the end of the statement; the current token on exit /// will be either the EndOfStatement or EOF. virtual StringRef parseStringToEndOfStatement() = 0; - /// \brief Parse the current token as a string which may include escaped + /// Parse the current token as a string which may include escaped /// characters and return the string contents. virtual bool parseEscapedString(std::string &Data) = 0; - /// \brief Skip to the end of the current statement, for error recovery. + /// Skip to the end of the current statement, for error recovery. virtual void eatToEndOfStatement() = 0; - /// \brief Parse an arbitrary expression. + /// Parse an arbitrary expression. /// /// \param Res - The value of the expression. The result is undefined /// on error. @@ -265,14 +267,14 @@ public: virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; bool parseExpression(const MCExpr *&Res); - /// \brief Parse a primary expression. + /// Parse a primary expression. /// /// \param Res - The value of the expression. The result is undefined /// on error. /// \return - False on success. virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// \brief Parse an arbitrary expression, assuming that an initial '(' has + /// Parse an arbitrary expression, assuming that an initial '(' has /// already been consumed. /// /// \param Res - The value of the expression. The result is undefined @@ -280,19 +282,19 @@ public: /// \return - False on success. virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// \brief Parse an expression which must evaluate to an absolute value. + /// Parse an expression which must evaluate to an absolute value. /// /// \param Res - The value of the absolute expression. The result is undefined /// on error. /// \return - False on success. virtual bool parseAbsoluteExpression(int64_t &Res) = 0; - /// \brief Ensure that we have a valid section set in the streamer. Otherwise, + /// Ensure that we have a valid section set in the streamer. Otherwise, /// report an error and switch to .text. /// \return - False on success. virtual bool checkForValidSection() = 0; - /// \brief Parse an arbitrary expression of a specified parenthesis depth, + /// Parse an arbitrary expression of a specified parenthesis depth, /// assuming that the initial '(' characters have already been consumed. /// /// \param ParenDepth - Specifies how many trailing expressions outside the @@ -304,7 +306,7 @@ public: SMLoc &EndLoc) = 0; }; -/// \brief Create an MCAsmParser instance. +/// Create an MCAsmParser instance. MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &, const MCAsmInfo &, unsigned CB = 0); diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h index ffb8d7a4a26a..1a132bceddc5 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -20,7 +20,7 @@ namespace llvm { class Twine; -/// \brief Generic interface for extending the MCAsmParser, +/// Generic interface for extending the MCAsmParser, /// which is implemented by target and object file assembly parser /// implementations. class MCAsmParserExtension { @@ -45,7 +45,7 @@ public: MCAsmParserExtension &operator=(const MCAsmParserExtension &) = delete; virtual ~MCAsmParserExtension(); - /// \brief Initialize the extension for parsing using the given \p Parser. + /// Initialize the extension for parsing using the given \p Parser. /// The extension should use the AsmParser interfaces to register its /// parsing routines. virtual void Initialize(MCAsmParser &Parser); diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserUtils.h b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserUtils.h index 84173bb9cb8e..259113bc3860 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserUtils.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCAsmParserUtils.h @@ -25,7 +25,7 @@ namespace MCParserUtils { /// On success, returns false and sets the Symbol and Value output parameters. bool parseAssignmentExpression(StringRef Name, bool allow_redef, MCAsmParser &Parser, MCSymbol *&Symbol, - const MCExpr *&Value); + const MCExpr *&Value, bool AllowExtendedExpr = false); } // namespace MCParserUtils diff --git a/contrib/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/contrib/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h index 9f8550c3887c..2d188a6755e1 100644 --- a/contrib/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h +++ b/contrib/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h @@ -14,6 +14,7 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/Support/SMLoc.h" @@ -133,6 +134,53 @@ enum OperandMatchResultTy { MatchOperand_ParseFail // operand matched but had errors }; +enum class DiagnosticPredicateTy { + Match, + NearMatch, + NoMatch, +}; + +// When an operand is parsed, the assembler will try to iterate through a set of +// possible operand classes that the operand might match and call the +// corresponding PredicateMethod to determine that. +// +// If there are two AsmOperands that would give a specific diagnostic if there +// is no match, there is currently no mechanism to distinguish which operand is +// a closer match. The DiagnosticPredicate distinguishes between 'completely +// no match' and 'near match', so the assembler can decide whether to give a +// specific diagnostic, or use 'InvalidOperand' and continue to find a +// 'better matching' diagnostic. +// +// For example: +// opcode opnd0, onpd1, opnd2 +// +// where: +// opnd2 could be an 'immediate of range [-8, 7]' +// opnd2 could be a 'register + shift/extend'. +// +// If opnd2 is a valid register, but with a wrong shift/extend suffix, it makes +// little sense to give a diagnostic that the operand should be an immediate +// in range [-8, 7]. +// +// This is a light-weight alternative to the 'NearMissInfo' approach +// below which collects *all* possible diagnostics. This alternative +// is optional and fully backward compatible with existing +// PredicateMethods that return a 'bool' (match or no match). +struct DiagnosticPredicate { + DiagnosticPredicateTy Type; + + explicit DiagnosticPredicate(bool Match) + : Type(Match ? DiagnosticPredicateTy::Match + : DiagnosticPredicateTy::NearMatch) {} + DiagnosticPredicate(DiagnosticPredicateTy T) : Type(T) {} + DiagnosticPredicate(const DiagnosticPredicate &) = default; + + operator bool() const { return Type == DiagnosticPredicateTy::Match; } + bool isMatch() const { return Type == DiagnosticPredicateTy::Match; } + bool isNearMatch() const { return Type == DiagnosticPredicateTy::NearMatch; } + bool isNoMatch() const { return Type == DiagnosticPredicateTy::NoMatch; } +}; + // When matching of an assembly instruction fails, there may be multiple // encodings that are close to being a match. It's often ambiguous which one // the programmer intended to use, so we want to report an error which mentions @@ -271,6 +319,7 @@ class MCTargetAsmParser : public MCAsmParserExtension { public: enum MatchResultTy { Match_InvalidOperand, + Match_InvalidTiedOperand, Match_MissingFeature, Match_MnemonicFail, Match_Success, @@ -323,6 +372,11 @@ public: SemaCallback = Callback; } + // Target-specific parsing of assembler-level variable assignment. + virtual bool parseAssignmentExpression(const MCExpr *&Res, SMLoc &EndLoc) { + return getParser().parseExpression(Res, EndLoc); + } + virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0; @@ -400,6 +454,15 @@ public: virtual void convertToMapAndConstraints(unsigned Kind, const OperandVector &Operands) = 0; + /// Returns whether two registers are equal and is used by the tied-operands + /// checks in the AsmMatcher. This method can be overridden allow e.g. a + /// sub- or super-register as the tied operand. + virtual bool regsEqual(const MCParsedAsmOperand &Op1, + const MCParsedAsmOperand &Op2) const { + assert(Op1.isReg() && Op2.isReg() && "Operands not all regs"); + return Op1.getReg() == Op2.getReg(); + } + // Return whether this parser uses assignment statements with equals tokens virtual bool equalIsAsmAssignment() { return true; }; // Return whether this start of statement identifier is a label diff --git a/contrib/llvm/include/llvm/MC/MCRegisterInfo.h b/contrib/llvm/include/llvm/MC/MCRegisterInfo.h index c57c9ef709da..6edfc30b0aa6 100644 --- a/contrib/llvm/include/llvm/MC/MCRegisterInfo.h +++ b/contrib/llvm/include/llvm/MC/MCRegisterInfo.h @@ -240,7 +240,7 @@ public: friend class MCRegUnitMaskIterator; friend class MCRegUnitRootIterator; - /// \brief Initialize MCRegisterInfo, called by TableGen + /// Initialize MCRegisterInfo, called by TableGen /// auto-generated routines. *DO NOT USE*. void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA, unsigned PC, @@ -283,7 +283,7 @@ public: Dwarf2LRegsSize = 0; } - /// \brief Used to initialize LLVM register to Dwarf + /// Used to initialize LLVM register to Dwarf /// register number mapping. Called by TableGen auto-generated routines. /// *DO NOT USE*. void mapLLVMRegsToDwarfRegs(const DwarfLLVMRegPair *Map, unsigned Size, @@ -297,7 +297,7 @@ public: } } - /// \brief Used to initialize Dwarf register to LLVM + /// Used to initialize Dwarf register to LLVM /// register number mapping. Called by TableGen auto-generated routines. /// *DO NOT USE*. void mapDwarfRegsToLLVMRegs(const DwarfLLVMRegPair *Map, unsigned Size, @@ -324,7 +324,7 @@ public: L2CVRegs[LLVMReg] = CVReg; } - /// \brief This method should return the register where the return + /// This method should return the register where the return /// address can be found. unsigned getRARegister() const { return RAReg; @@ -341,86 +341,86 @@ public: return Desc[RegNo]; } - /// \brief Provide a get method, equivalent to [], but more useful with a + /// Provide a get method, equivalent to [], but more useful with a /// pointer to this object. const MCRegisterDesc &get(unsigned RegNo) const { return operator[](RegNo); } - /// \brief Returns the physical register number of sub-register "Index" + /// Returns the physical register number of sub-register "Index" /// for physical register RegNo. Return zero if the sub-register does not /// exist. unsigned getSubReg(unsigned Reg, unsigned Idx) const; - /// \brief Return a super-register of the specified register + /// Return a super-register of the specified register /// Reg so its sub-register of index SubIdx is Reg. unsigned getMatchingSuperReg(unsigned Reg, unsigned SubIdx, const MCRegisterClass *RC) const; - /// \brief For a given register pair, return the sub-register index + /// For a given register pair, return the sub-register index /// if the second register is a sub-register of the first. Return zero /// otherwise. unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const; - /// \brief Get the size of the bit range covered by a sub-register index. + /// Get the size of the bit range covered by a sub-register index. /// If the index isn't continuous, return the sum of the sizes of its parts. /// If the index is used to access subregisters of different sizes, return -1. unsigned getSubRegIdxSize(unsigned Idx) const; - /// \brief Get the offset of the bit range covered by a sub-register index. + /// Get the offset of the bit range covered by a sub-register index. /// If an Offset doesn't make sense (the index isn't continuous, or is used to /// access sub-registers at different offsets), return -1. unsigned getSubRegIdxOffset(unsigned Idx) const; - /// \brief Return the human-readable symbolic target-specific name for the + /// Return the human-readable symbolic target-specific name for the /// specified physical register. const char *getName(unsigned RegNo) const { return RegStrings + get(RegNo).Name; } - /// \brief Return the number of registers this target has (useful for + /// Return the number of registers this target has (useful for /// sizing arrays holding per register information) unsigned getNumRegs() const { return NumRegs; } - /// \brief Return the number of sub-register indices + /// Return the number of sub-register indices /// understood by the target. Index 0 is reserved for the no-op sub-register, /// while 1 to getNumSubRegIndices() - 1 represent real sub-registers. unsigned getNumSubRegIndices() const { return NumSubRegIndices; } - /// \brief Return the number of (native) register units in the + /// Return the number of (native) register units in the /// target. Register units are numbered from 0 to getNumRegUnits() - 1. They /// can be accessed through MCRegUnitIterator defined below. unsigned getNumRegUnits() const { return NumRegUnits; } - /// \brief Map a target register to an equivalent dwarf register + /// Map a target register to an equivalent dwarf register /// number. Returns -1 if there is no equivalent value. The second /// parameter allows targets to use different numberings for EH info and /// debugging info. int getDwarfRegNum(unsigned RegNum, bool isEH) const; - /// \brief Map a dwarf register back to a target register. + /// Map a dwarf register back to a target register. int getLLVMRegNum(unsigned RegNum, bool isEH) const; - /// \brief Map a DWARF EH register back to a target register (same as + /// Map a DWARF EH register back to a target register (same as /// getLLVMRegNum(RegNum, true)) but return -1 if there is no mapping, /// rather than asserting that there must be one. int getLLVMRegNumFromEH(unsigned RegNum) const; - /// \brief Map a target EH register number to an equivalent DWARF register + /// Map a target EH register number to an equivalent DWARF register /// number. int getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const; - /// \brief Map a target register to an equivalent SEH register + /// Map a target register to an equivalent SEH register /// number. Returns LLVM register number if there is no equivalent value. int getSEHRegNum(unsigned RegNum) const; - /// \brief Map a target register to an equivalent CodeView register + /// Map a target register to an equivalent CodeView register /// number. int getCodeViewRegNum(unsigned RegNum) const; @@ -434,7 +434,7 @@ public: return (unsigned)(regclass_end()-regclass_begin()); } - /// \brief Returns the register class associated with the enumeration + /// Returns the register class associated with the enumeration /// value. See class MCOperandInfo. const MCRegisterClass& getRegClass(unsigned i) const { assert(i < getNumRegClasses() && "Register Class ID out of range"); @@ -445,33 +445,33 @@ public: return RegClassStrings + Class->NameIdx; } - /// \brief Returns the encoding for RegNo + /// Returns the encoding for RegNo uint16_t getEncodingValue(unsigned RegNo) const { assert(RegNo < NumRegs && "Attempting to get encoding for invalid register number!"); return RegEncodingTable[RegNo]; } - /// \brief Returns true if RegB is a sub-register of RegA. + /// Returns true if RegB is a sub-register of RegA. bool isSubRegister(unsigned RegA, unsigned RegB) const { return isSuperRegister(RegB, RegA); } - /// \brief Returns true if RegB is a super-register of RegA. + /// Returns true if RegB is a super-register of RegA. bool isSuperRegister(unsigned RegA, unsigned RegB) const; - /// \brief Returns true if RegB is a sub-register of RegA or if RegB == RegA. + /// Returns true if RegB is a sub-register of RegA or if RegB == RegA. bool isSubRegisterEq(unsigned RegA, unsigned RegB) const { return isSuperRegisterEq(RegB, RegA); } - /// \brief Returns true if RegB is a super-register of RegA or if + /// Returns true if RegB is a super-register of RegA or if /// RegB == RegA. bool isSuperRegisterEq(unsigned RegA, unsigned RegB) const { return RegA == RegB || isSuperRegister(RegA, RegB); } - /// \brief Returns true if RegB is a super-register or sub-register of RegA + /// Returns true if RegB is a super-register or sub-register of RegA /// or if RegB == RegA. bool isSuperOrSubRegisterEq(unsigned RegA, unsigned RegB) const { return isSubRegisterEq(RegA, RegB) || isSuperRegister(RegA, RegB); @@ -651,17 +651,17 @@ public: Reg1 = MCRI->RegUnitRoots[RegUnit][1]; } - /// \brief Dereference to get the current root register. + /// Dereference to get the current root register. unsigned operator*() const { return Reg0; } - /// \brief Check if the iterator is at the end of the list. + /// Check if the iterator is at the end of the list. bool isValid() const { return Reg0; } - /// \brief Preincrement to move to the next root register. + /// Preincrement to move to the next root register. void operator++() { assert(isValid() && "Cannot move off the end of the list."); Reg0 = Reg1; diff --git a/contrib/llvm/include/llvm/MC/MCSchedule.h b/contrib/llvm/include/llvm/MC/MCSchedule.h index a79afe163e6c..f2f1dfb36918 100644 --- a/contrib/llvm/include/llvm/MC/MCSchedule.h +++ b/contrib/llvm/include/llvm/MC/MCSchedule.h @@ -15,18 +15,22 @@ #ifndef LLVM_MC_MCSCHEDULE_H #define LLVM_MC_MCSCHEDULE_H +#include "llvm/ADT/Optional.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { struct InstrItinerary; +class MCSubtargetInfo; +class MCInstrInfo; +class MCInst; +class InstrItineraryData; /// Define a kind of processor resource that will be modeled by the scheduler. struct MCProcResourceDesc { -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) const char *Name; -#endif unsigned NumUnits; // Number of resource of this kind unsigned SuperIdx; // Index of the resources kind that contains this kind. @@ -44,6 +48,11 @@ struct MCProcResourceDesc { // an out-of-order cpus. int BufferSize; + // If the resource has sub-units, a pointer to the first element of an array + // of `NumUnits` elements containing the ProcResourceIdx of the sub units. + // nullptr if the resource does not have sub-units. + const unsigned *SubUnitsIdxBegin; + bool operator==(const MCProcResourceDesc &Other) const { return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx && BufferSize == Other.BufferSize; @@ -53,8 +62,8 @@ struct MCProcResourceDesc { /// Identify one of the processor resource kinds consumed by a particular /// scheduling class for the specified number of cycles. struct MCWriteProcResEntry { - unsigned ProcResourceIdx; - unsigned Cycles; + uint16_t ProcResourceIdx; + uint16_t Cycles; bool operator==(const MCWriteProcResEntry &Other) const { return ProcResourceIdx == Other.ProcResourceIdx && Cycles == Other.Cycles; @@ -67,8 +76,8 @@ struct MCWriteProcResEntry { /// the WriteResources of this def. When the operand expands to a sequence of /// writes, this ID is the last write in the sequence. struct MCWriteLatencyEntry { - int Cycles; - unsigned WriteResourceID; + int16_t Cycles; + uint16_t WriteResourceID; bool operator==(const MCWriteLatencyEntry &Other) const { return Cycles == Other.Cycles && WriteResourceID == Other.WriteResourceID; @@ -99,21 +108,21 @@ struct MCReadAdvanceEntry { /// /// Defined as an aggregate struct for creating tables with initializer lists. struct MCSchedClassDesc { - static const unsigned short InvalidNumMicroOps = UINT16_MAX; - static const unsigned short VariantNumMicroOps = UINT16_MAX - 1; + static const unsigned short InvalidNumMicroOps = (1U << 14) - 1; + static const unsigned short VariantNumMicroOps = InvalidNumMicroOps - 1; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) const char* Name; #endif - unsigned short NumMicroOps; - bool BeginGroup; - bool EndGroup; - unsigned WriteProcResIdx; // First index into WriteProcResTable. - unsigned NumWriteProcResEntries; - unsigned WriteLatencyIdx; // First index into WriteLatencyTable. - unsigned NumWriteLatencyEntries; - unsigned ReadAdvanceIdx; // First index into ReadAdvanceTable. - unsigned NumReadAdvanceEntries; + uint16_t NumMicroOps : 14; + bool BeginGroup : 1; + bool EndGroup : 1; + uint16_t WriteProcResIdx; // First index into WriteProcResTable. + uint16_t NumWriteProcResEntries; + uint16_t WriteLatencyIdx; // First index into WriteLatencyTable. + uint16_t NumWriteLatencyEntries; + uint16_t ReadAdvanceIdx; // First index into ReadAdvanceTable. + uint16_t NumReadAdvanceEntries; bool isValid() const { return NumMicroOps != InvalidNumMicroOps; @@ -123,6 +132,64 @@ struct MCSchedClassDesc { } }; +/// Specify the cost of a register definition in terms of number of physical +/// register allocated at register renaming stage. For example, AMD Jaguar. +/// natively supports 128-bit data types, and operations on 256-bit registers +/// (i.e. YMM registers) are internally split into two COPs (complex operations) +/// and each COP updates a physical register. Basically, on Jaguar, a YMM +/// register write effectively consumes two physical registers. That means, +/// the cost of a YMM write in the BtVer2 model is 2. +struct MCRegisterCostEntry { + unsigned RegisterClassID; + unsigned Cost; +}; + +/// A register file descriptor. +/// +/// This struct allows to describe processor register files. In particular, it +/// helps describing the size of the register file, as well as the cost of +/// allocating a register file at register renaming stage. +/// FIXME: this struct can be extended to provide information about the number +/// of read/write ports to the register file. A value of zero for field +/// 'NumPhysRegs' means: this register file has an unbounded number of physical +/// registers. +struct MCRegisterFileDesc { + const char *Name; + uint16_t NumPhysRegs; + uint16_t NumRegisterCostEntries; + // Index of the first cost entry in MCExtraProcessorInfo::RegisterCostTable. + uint16_t RegisterCostEntryIdx; +}; + +/// Provide extra details about the machine processor. +/// +/// This is a collection of "optional" processor information that is not +/// normally used by the LLVM machine schedulers, but that can be consumed by +/// external tools like llvm-mca to improve the quality of the peformance +/// analysis. +struct MCExtraProcessorInfo { + // Actual size of the reorder buffer in hardware. + unsigned ReorderBufferSize; + // Number of instructions retired per cycle. + unsigned MaxRetirePerCycle; + const MCRegisterFileDesc *RegisterFiles; + unsigned NumRegisterFiles; + const MCRegisterCostEntry *RegisterCostTable; + unsigned NumRegisterCostEntries; + + struct PfmCountersInfo { + // An optional name of a performance counter that can be used to measure + // cycles. + const char *CycleCounter; + + // For each MCProcResourceDesc defined by the processor, an optional list of + // names of performance counters that can be used to measure the resource + // utilization. + const char **IssueCounters; + }; + PfmCountersInfo PfmCounters; +}; + /// Machine model for scheduling, bundling, and heuristics. /// /// The machine model directly provides basic information about the @@ -133,9 +200,62 @@ struct MCSchedClassDesc { /// provides a detailed reservation table describing each cycle of instruction /// execution. Subtargets may define any or all of the above categories of data /// depending on the type of CPU and selected scheduler. +/// +/// The machine independent properties defined here are used by the scheduler as +/// an abstract machine model. A real micro-architecture has a number of +/// buffers, queues, and stages. Declaring that a given machine-independent +/// abstract property corresponds to a specific physical property across all +/// subtargets can't be done. Nonetheless, the abstract model is +/// useful. Futhermore, subtargets typically extend this model with processor +/// specific resources to model any hardware features that can be exploited by +/// sceduling heuristics and aren't sufficiently represented in the abstract. +/// +/// The abstract pipeline is built around the notion of an "issue point". This +/// is merely a reference point for counting machine cycles. The physical +/// machine will have pipeline stages that delay execution. The scheduler does +/// not model those delays because they are irrelevant as long as they are +/// consistent. Inaccuracies arise when instructions have different execution +/// delays relative to each other, in addition to their intrinsic latency. Those +/// special cases can be handled by TableGen constructs such as, ReadAdvance, +/// which reduces latency when reading data, and ResourceCycles, which consumes +/// a processor resource when writing data for a number of abstract +/// cycles. +/// +/// TODO: One tool currently missing is the ability to add a delay to +/// ResourceCycles. That would be easy to add and would likely cover all cases +/// currently handled by the legacy itinerary tables. +/// +/// A note on out-of-order execution and, more generally, instruction +/// buffers. Part of the CPU pipeline is always in-order. The issue point, which +/// is the point of reference for counting cycles, only makes sense as an +/// in-order part of the pipeline. Other parts of the pipeline are sometimes +/// falling behind and sometimes catching up. It's only interesting to model +/// those other, decoupled parts of the pipeline if they may be predictably +/// resource constrained in a way that the scheduler can exploit. +/// +/// The LLVM machine model distinguishes between in-order constraints and +/// out-of-order constraints so that the target's scheduling strategy can apply +/// appropriate heuristics. For a well-balanced CPU pipeline, out-of-order +/// resources would not typically be treated as a hard scheduling +/// constraint. For example, in the GenericScheduler, a delay caused by limited +/// out-of-order resources is not directly reflected in the number of cycles +/// that the scheduler sees between issuing an instruction and its dependent +/// instructions. In other words, out-of-order resources don't directly increase +/// the latency between pairs of instructions. However, they can still be used +/// to detect potential bottlenecks across a sequence of instructions and bias +/// the scheduling heuristics appropriately. struct MCSchedModel { // IssueWidth is the maximum number of instructions that may be scheduled in - // the same per-cycle group. + // the same per-cycle group. This is meant to be a hard in-order constraint + // (a.k.a. "hazard"). In the GenericScheduler strategy, no more than + // IssueWidth micro-ops can ever be scheduled in a particular cycle. + // + // In practice, IssueWidth is useful to model any bottleneck between the + // decoder (after micro-op expansion) and the out-of-order reservation + // stations or the decoder bandwidth itself. If the total number of + // reservation stations is also a bottleneck, or if any other pipeline stage + // has a bandwidth limitation, then that can be naturally modeled by adding an + // out-of-order processor resource. unsigned IssueWidth; static const unsigned DefaultIssueWidth = 1; @@ -193,11 +313,21 @@ struct MCSchedModel { friend class InstrItineraryData; const InstrItinerary *InstrItineraries; + const MCExtraProcessorInfo *ExtraProcessorInfo; + + bool hasExtraProcessorInfo() const { return ExtraProcessorInfo; } + unsigned getProcessorID() const { return ProcID; } /// Does this machine model include instruction-level scheduling. bool hasInstrSchedModel() const { return SchedClassTable; } + const MCExtraProcessorInfo &getExtraProcessorInfo() const { + assert(hasExtraProcessorInfo() && + "No extra information available for this model"); + return *ExtraProcessorInfo; + } + /// Return true if this machine model data for all instructions with a /// scheduling class (itinerary class or SchedRW list). bool isComplete() const { return CompleteModel; } @@ -223,11 +353,31 @@ struct MCSchedModel { return &SchedClassTable[SchedClassIdx]; } + /// Returns the latency value for the scheduling class. + static int computeInstrLatency(const MCSubtargetInfo &STI, + const MCSchedClassDesc &SCDesc); + + int computeInstrLatency(const MCSubtargetInfo &STI, unsigned SClass) const; + int computeInstrLatency(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, + const MCInst &Inst) const; + + // Returns the reciprocal throughput information from a MCSchedClassDesc. + static double + getReciprocalThroughput(const MCSubtargetInfo &STI, + const MCSchedClassDesc &SCDesc); + + static double + getReciprocalThroughput(unsigned SchedClass, const InstrItineraryData &IID); + + double + getReciprocalThroughput(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, + const MCInst &Inst) const; + /// Returns the default initialized model. static const MCSchedModel &GetDefaultSchedModel() { return Default; } static const MCSchedModel Default; }; -} // End llvm namespace +} // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/MC/MCSection.h b/contrib/llvm/include/llvm/MC/MCSection.h index 2771b1e67eab..ba5c60d3ba58 100644 --- a/contrib/llvm/include/llvm/MC/MCSection.h +++ b/contrib/llvm/include/llvm/MC/MCSection.h @@ -40,7 +40,7 @@ class MCSection { public: enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO, SV_Wasm }; - /// \brief Express the state of bundle locked groups while emitting code. + /// Express the state of bundle locked groups while emitting code. enum BundleLockStateType { NotBundleLocked, BundleLocked, @@ -65,13 +65,13 @@ private: /// The index of this section in the layout order. unsigned LayoutOrder; - /// \brief Keeping track of bundle-locked state. + /// Keeping track of bundle-locked state. BundleLockStateType BundleLockState = NotBundleLocked; - /// \brief Current nesting depth of bundle_lock directives. + /// Current nesting depth of bundle_lock directives. unsigned BundleLockNestingDepth = 0; - /// \brief We've seen a bundle_lock directive but not its first instruction + /// We've seen a bundle_lock directive but not its first instruction /// yet. bool BundleGroupBeforeFirstInst : 1; diff --git a/contrib/llvm/include/llvm/MC/MCSectionWasm.h b/contrib/llvm/include/llvm/MC/MCSectionWasm.h index cc467ed9837a..ab4cd7b007ec 100644 --- a/contrib/llvm/include/llvm/MC/MCSectionWasm.h +++ b/contrib/llvm/include/llvm/MC/MCSectionWasm.h @@ -26,8 +26,6 @@ class MCSymbol; /// This represents a section on wasm. class MCSectionWasm final : public MCSection { -private: - /// This is the name of the section. The referenced memory is owned by /// TargetLoweringObjectFileWasm's WasmUniqueMap. StringRef SectionName; @@ -39,17 +37,17 @@ private: // The offset of the MC function/data section in the wasm code/data section. // For data relocations the offset is relative to start of the data payload // itself and does not include the size of the section header. - uint64_t SectionOffset; + uint64_t SectionOffset = 0; - // For data sections, this is the offset of the corresponding wasm data + // For data sections, this is the index of of the corresponding wasm data // segment - uint64_t MemoryOffset; + uint32_t SegmentIndex = 0; friend class MCContext; MCSectionWasm(StringRef Section, SectionKind K, const MCSymbolWasm *group, unsigned UniqueID, MCSymbol *Begin) : MCSection(SV_Wasm, K, Begin), SectionName(Section), UniqueID(UniqueID), - Group(group), SectionOffset(0) {} + Group(group) {} void setSectionName(StringRef Name) { SectionName = Name; } @@ -79,8 +77,8 @@ public: uint64_t getSectionOffset() const { return SectionOffset; } void setSectionOffset(uint64_t Offset) { SectionOffset = Offset; } - uint32_t getMemoryOffset() const { return MemoryOffset; } - void setMemoryOffset(uint32_t Offset) { MemoryOffset = Offset; } + uint32_t getSegmentIndex() const { return SegmentIndex; } + void setSegmentIndex(uint32_t Index) { SegmentIndex = Index; } static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; } }; diff --git a/contrib/llvm/include/llvm/MC/MCStreamer.h b/contrib/llvm/include/llvm/MC/MCStreamer.h index 5b564e538bb2..0a5d80c6d778 100644 --- a/contrib/llvm/include/llvm/MC/MCStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCStreamer.h @@ -16,6 +16,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCDirectives.h" @@ -23,6 +24,8 @@ #include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCWinEH.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MD5.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/TargetParser.h" #include <cassert> @@ -167,7 +170,7 @@ private: std::unique_ptr<AssemblerConstantPools> ConstantPools; }; -/// \brief Streaming machine code generation interface. +/// Streaming machine code generation interface. /// /// This interface is intended to provide a programatic interface that is very /// similar to the level that an assembler .s file provides. It has callbacks @@ -194,11 +197,11 @@ class MCStreamer { /// closed. Otherwise, issue an error and return null. WinEH::FrameInfo *EnsureValidWinFrameInfo(SMLoc Loc); - /// \brief Tracks an index to represent the order a symbol was emitted in. + /// Tracks an index to represent the order a symbol was emitted in. /// Zero means we did not emit that symbol. DenseMap<const MCSymbol *, unsigned> SymbolOrdering; - /// \brief This is stack of current and previous section values saved by + /// This is stack of current and previous section values saved by /// PushSection. SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; @@ -208,6 +211,8 @@ class MCStreamer { /// requires. unsigned NextWinCFIID = 0; + bool UseAssemblerInfoForParsing; + protected: MCStreamer(MCContext &Ctx); @@ -244,6 +249,11 @@ public: MCContext &getContext() const { return Context; } + virtual MCAssembler *getAssemblerPtr() { return nullptr; } + + void setUseAssemblerInfoForParsing(bool v) { UseAssemblerInfoForParsing = v; } + bool getUseAssemblerInfoForParsing() { return UseAssemblerInfoForParsing; } + MCTargetStreamer *getTargetStreamer() { return TargetStreamer.get(); } @@ -265,19 +275,19 @@ public: /// \name Assembly File Formatting. /// @{ - /// \brief Return true if this streamer supports verbose assembly and if it is + /// Return true if this streamer supports verbose assembly and if it is /// enabled. virtual bool isVerboseAsm() const { return false; } - /// \brief Return true if this asm streamer supports emitting unformatted text + /// Return true if this asm streamer supports emitting unformatted text /// to the .s file with EmitRawText. virtual bool hasRawTextSupport() const { return false; } - /// \brief Is the integrated assembler required for this streamer to function + /// Is the integrated assembler required for this streamer to function /// correctly? virtual bool isIntegratedAssemblerRequired() const { return false; } - /// \brief Add a textual comment. + /// Add a textual comment. /// /// Typically for comments that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler @@ -292,22 +302,22 @@ public: /// with a false value. virtual void AddComment(const Twine &T, bool EOL = true) {} - /// \brief Return a raw_ostream that comments can be written to. Unlike + /// Return a raw_ostream that comments can be written to. Unlike /// AddComment, you are required to terminate comments with \n if you use this /// method. virtual raw_ostream &GetCommentOS(); - /// \brief Print T and prefix it with the comment string (normally #) and + /// 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); - /// \brief Add explicit comment T. T is required to be a valid + /// Add explicit comment T. T is required to be a valid /// comment in the output and does not need to be escaped. virtual void addExplicitComment(const Twine &T); - /// \brief Emit added explicit comments. + /// Emit added explicit comments. virtual void emitExplicitComments(); /// AddBlankLine - Emit a blank line to a .s file to pretty it up. @@ -318,7 +328,7 @@ public: /// \name Symbol & Section Management /// @{ - /// \brief Return the current section that the streamer is emitting code to. + /// Return the current section that the streamer is emitting code to. MCSectionSubPair getCurrentSection() const { if (!SectionStack.empty()) return SectionStack.back().first; @@ -326,32 +336,32 @@ public: } MCSection *getCurrentSectionOnly() const { return getCurrentSection().first; } - /// \brief Return the previous section that the streamer is emitting code to. + /// Return the previous section that the streamer is emitting code to. MCSectionSubPair getPreviousSection() const { if (!SectionStack.empty()) return SectionStack.back().second; return MCSectionSubPair(); } - /// \brief Returns an index to represent the order a symbol was emitted in. + /// Returns an index to represent the order a symbol was emitted in. /// (zero if we did not emit that symbol) unsigned GetSymbolOrder(const MCSymbol *Sym) const { return SymbolOrdering.lookup(Sym); } - /// \brief Update streamer for a new active section. + /// Update streamer for a new active section. /// /// This is called by PopSection and SwitchSection, if the current /// section changes. virtual void ChangeSection(MCSection *, const MCExpr *); - /// \brief Save the current and previous section on the section stack. + /// Save the current and previous section on the section stack. void PushSection() { SectionStack.push_back( std::make_pair(getCurrentSection(), getPreviousSection())); } - /// \brief Restore the current and previous section from the section stack. + /// Restore the current and previous section from the section stack. /// Calls ChangeSection as needed. /// /// Returns false if the stack was empty. @@ -385,7 +395,7 @@ public: virtual void SwitchSection(MCSection *Section, const MCExpr *Subsection = nullptr); - /// \brief Set the current section where code is being emitted to \p Section. + /// Set the current section where code is being emitted to \p Section. /// This is required to update CurSection. This version does not call /// ChangeSection. void SwitchSectionNoChange(MCSection *Section, @@ -397,18 +407,18 @@ public: SectionStack.back().first = MCSectionSubPair(Section, Subsection); } - /// \brief Create the default sections and set the initial one. + /// Create the default sections and set the initial one. virtual void InitSections(bool NoExecStack); MCSymbol *endSection(MCSection *Section); - /// \brief Sets the symbol's section. + /// Sets the symbol's section. /// /// Each emitted symbol will be tracked in the ordering table, /// so we can sort on them later. void AssignFragment(MCSymbol *Symbol, MCFragment *Fragment); - /// \brief Emit a label for \p Symbol into the current section. + /// Emit a label for \p Symbol into the current section. /// /// This corresponds to an assembler statement such as: /// foo: @@ -422,17 +432,17 @@ public: virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - /// \brief Note in the output the specified \p Flag. + /// Note in the output the specified \p Flag. virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); - /// \brief Emit the given list \p Options of strings as linker + /// Emit the given list \p Options of strings as linker /// options into the output. virtual void EmitLinkerOptions(ArrayRef<std::string> Kind) {} - /// \brief Note in the output the specified region \p Kind. + /// Note in the output the specified region \p Kind. virtual void EmitDataRegion(MCDataRegionType Kind) {} - /// \brief Specify the Mach-O minimum deployment target version. + /// Specify the Mach-O minimum deployment target version. virtual void EmitVersionMin(MCVersionMinType Type, unsigned Major, unsigned Minor, unsigned Update) {} @@ -443,11 +453,11 @@ public: void EmitVersionForTarget(const Triple &Target); - /// \brief Note in the output that the specified \p Func is a Thumb mode + /// Note in the output that the specified \p Func is a Thumb mode /// function (ARM target only). virtual void EmitThumbFunc(MCSymbol *Func); - /// \brief Emit an assignment of \p Value to \p Symbol. + /// Emit an assignment of \p Value to \p Symbol. /// /// This corresponds to an assembler statement such as: /// symbol = value @@ -460,7 +470,7 @@ public: /// \param Value - The value for the symbol. virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - /// \brief Emit an weak reference from \p Alias to \p Symbol. + /// Emit an weak reference from \p Alias to \p Symbol. /// /// This corresponds to an assembler statement such as: /// .weakref alias, symbol @@ -469,53 +479,61 @@ public: /// \param Symbol - The symbol being aliased. virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - /// \brief Add the given \p Attribute to \p Symbol. + /// Add the given \p Attribute to \p Symbol. virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) = 0; - /// \brief Set the \p DescValue for the \p Symbol. + /// Set the \p DescValue for the \p Symbol. /// /// \param Symbol - The symbol to have its n_desc field set. /// \param DescValue - The value to set into the n_desc field. virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); - /// \brief Start emitting COFF symbol definition + /// Start emitting COFF symbol definition /// /// \param Symbol - The symbol to have its External & Type fields set. virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); - /// \brief Emit the storage class of the symbol. + /// Emit the storage class of the symbol. /// /// \param StorageClass - The storage class the symbol should have. virtual void EmitCOFFSymbolStorageClass(int StorageClass); - /// \brief Emit the type of the symbol. + /// Emit the type of the symbol. /// /// \param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) virtual void EmitCOFFSymbolType(int Type); - /// \brief Marks the end of the symbol definition. + /// Marks the end of the symbol definition. virtual void EndCOFFSymbolDef(); virtual void EmitCOFFSafeSEH(MCSymbol const *Symbol); - /// \brief Emits a COFF section index. + /// Emits the symbol table index of a Symbol into the current section. + virtual void EmitCOFFSymbolIndex(MCSymbol const *Symbol); + + /// Emits a COFF section index. /// /// \param Symbol - Symbol the section number relocation should point to. virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol); - /// \brief Emits a COFF section relative relocation. + /// Emits a COFF section relative relocation. /// /// \param Symbol - Symbol the section relative relocation should point to. virtual void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset); - /// \brief Emit an ELF .size directive. + /// Emits a COFF image relative relocation. + /// + /// \param Symbol - Symbol the image relative relocation should point to. + virtual void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset); + + /// Emit an ELF .size directive. /// /// This corresponds to an assembler statement such as: /// .size symbol, expression virtual void emitELFSize(MCSymbol *Symbol, const MCExpr *Value); - /// \brief Emit an ELF .symver directive. + /// Emit an ELF .symver directive. /// /// This corresponds to an assembler statement such as: /// .symver _start, foo@@SOME_VERSION @@ -524,11 +542,11 @@ public: virtual void emitELFSymverDirective(StringRef AliasName, const MCSymbol *Aliasee); - /// \brief Emit a Linker Optimization Hint (LOH) directive. + /// Emit a Linker Optimization Hint (LOH) directive. /// \param Args - Arguments of the LOH. virtual void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {} - /// \brief Emit a common symbol. + /// Emit a common symbol. /// /// \param Symbol - The common symbol to emit. /// \param Size - The size of the common symbol. @@ -537,7 +555,7 @@ public: virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) = 0; - /// \brief Emit a local common (.lcomm) symbol. + /// Emit a local common (.lcomm) symbol. /// /// \param Symbol - The common symbol to emit. /// \param Size - The size of the common symbol. @@ -545,7 +563,7 @@ public: virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); - /// \brief Emit the zerofill section and an optional symbol. + /// Emit the zerofill section and an optional symbol. /// /// \param Section - The zerofill section to create and or to put the symbol /// \param Symbol - The zerofill symbol to emit, if non-NULL. @@ -553,9 +571,10 @@ public: /// \param ByteAlignment - The alignment of the zerofill symbol if /// non-zero. This must be a power of 2 on some targets. virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, - uint64_t Size = 0, unsigned ByteAlignment = 0) = 0; + uint64_t Size = 0, unsigned ByteAlignment = 0, + SMLoc Loc = SMLoc()) = 0; - /// \brief Emit a thread local bss (.tbss) symbol. + /// Emit a thread local bss (.tbss) symbol. /// /// \param Section - The thread local common section. /// \param Symbol - The thread local common symbol to emit. @@ -569,7 +588,7 @@ public: /// \name Generating Data /// @{ - /// \brief Emit the bytes in \p Data into the output. + /// Emit the bytes in \p Data into the output. /// /// This is used to implement assembler directives such as .byte, .ascii, /// etc. @@ -579,7 +598,7 @@ public: /// method uses .byte directives instead of .ascii or .asciz for readability. virtual void EmitBinaryData(StringRef Data); - /// \brief Emit the expression \p Value into the output as a native + /// Emit the expression \p Value into the output as a native /// integer of the given \p Size bytes. /// /// This is used to implement assembler directives such as .word, .quad, @@ -594,7 +613,7 @@ public: void EmitValue(const MCExpr *Value, unsigned Size, SMLoc Loc = SMLoc()); - /// \brief Special case of EmitValue that avoids the client having + /// Special case of EmitValue that avoids the client having /// to pass in a MCExpr for constant integers. virtual void EmitIntValue(uint64_t Value, unsigned Size); @@ -602,70 +621,66 @@ public: virtual void EmitSLEB128Value(const MCExpr *Value); - /// \brief Special case of EmitULEB128Value that avoids the client having to + /// Special case of EmitULEB128Value that avoids the client having to /// pass in a MCExpr for constant integers. void EmitULEB128IntValue(uint64_t Value); - /// \brief Like EmitULEB128Value but pads the output to specific number of - /// bytes. - void EmitPaddedULEB128IntValue(uint64_t Value, unsigned PadTo); - - /// \brief Special case of EmitSLEB128Value that avoids the client having to + /// Special case of EmitSLEB128Value that avoids the client having to /// pass in a MCExpr for constant integers. void EmitSLEB128IntValue(int64_t Value); - /// \brief Special case of EmitValue that avoids the client having to pass in + /// Special case of EmitValue that avoids the client having to pass in /// a MCExpr for MCSymbols. void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, bool IsSectionRelative = false); - /// \brief Emit the expression \p Value into the output as a dtprel + /// Emit the expression \p Value into the output as a dtprel /// (64-bit DTP relative) value. /// /// This is used to implement assembler directives such as .dtpreldword on /// targets that support them. virtual void EmitDTPRel64Value(const MCExpr *Value); - /// \brief Emit the expression \p Value into the output as a dtprel + /// Emit the expression \p Value into the output as a dtprel /// (32-bit DTP relative) value. /// /// This is used to implement assembler directives such as .dtprelword on /// targets that support them. virtual void EmitDTPRel32Value(const MCExpr *Value); - /// \brief Emit the expression \p Value into the output as a tprel + /// Emit the expression \p Value into the output as a tprel /// (64-bit TP relative) value. /// /// This is used to implement assembler directives such as .tpreldword on /// targets that support them. virtual void EmitTPRel64Value(const MCExpr *Value); - /// \brief Emit the expression \p Value into the output as a tprel + /// Emit the expression \p Value into the output as a tprel /// (32-bit TP relative) value. /// /// This is used to implement assembler directives such as .tprelword on /// targets that support them. virtual void EmitTPRel32Value(const MCExpr *Value); - /// \brief Emit the expression \p Value into the output as a gprel64 (64-bit + /// Emit the expression \p Value into the output as a gprel64 (64-bit /// GP relative) value. /// /// This is used to implement assembler directives such as .gpdword on /// targets that support them. virtual void EmitGPRel64Value(const MCExpr *Value); - /// \brief Emit the expression \p Value into the output as a gprel32 (32-bit + /// Emit the expression \p Value into the output as a gprel32 (32-bit /// GP relative) value. /// /// This is used to implement assembler directives such as .gprel32 on /// targets that support them. virtual void EmitGPRel32Value(const MCExpr *Value); - /// \brief Emit NumBytes bytes worth of the value specified by FillValue. + /// Emit NumBytes bytes worth of the value specified by FillValue. /// This implements directives such as '.space'. void emitFill(uint64_t NumBytes, uint8_t FillValue); - /// \brief Emit \p Size bytes worth of the value specified by \p FillValue. + /// Emit \p Size bytes worth of the value specified by \p FillValue. /// /// This is used to implement assembler directives such as .space or .skip. /// @@ -675,7 +690,7 @@ public: virtual void emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc = SMLoc()); - /// \brief Emit \p NumValues copies of \p Size bytes. Each \p Size bytes is + /// Emit \p NumValues copies of \p Size bytes. Each \p Size bytes is /// taken from the lowest order 4 bytes of \p Expr expression. /// /// This is used to implement assembler directives such as .fill. @@ -683,15 +698,14 @@ public: /// \param NumValues - The number of copies of \p Size bytes to emit. /// \param Size - The size (in bytes) of each repeated value. /// \param Expr - The expression from which \p Size bytes are used. - virtual void emitFill(uint64_t NumValues, int64_t Size, int64_t Expr); virtual void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, SMLoc Loc = SMLoc()); - /// \brief Emit NumBytes worth of zeros. + /// Emit NumBytes worth of zeros. /// This function properly handles data in virtual sections. void EmitZeros(uint64_t NumBytes); - /// \brief Emit some number of copies of \p Value until the byte alignment \p + /// Emit some number of copies of \p Value until the byte alignment \p /// ByteAlignment is reached. /// /// If the number of bytes need to emit for the alignment is not a multiple @@ -712,7 +726,7 @@ public: unsigned ValueSize = 1, unsigned MaxBytesToEmit = 0); - /// \brief Emit nops until the byte alignment \p ByteAlignment is reached. + /// Emit nops until the byte alignment \p ByteAlignment is reached. /// /// This used to align code where the alignment bytes may be executed. This /// can emit different bytes for different sizes to optimize execution. @@ -725,7 +739,7 @@ public: virtual void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit = 0); - /// \brief Emit some number of copies of \p Value until the byte offset \p + /// Emit some number of copies of \p Value until the byte offset \p /// Offset is reached. /// /// This is used to implement assembler directives such as .org. @@ -744,21 +758,43 @@ public: /// @} - /// \brief Switch to a new logical file. This is used to implement the '.file + /// Switch to a new logical file. This is used to implement the '.file /// "foo.c"' assembler directive. virtual void EmitFileDirective(StringRef Filename); - /// \brief Emit the "identifiers" directive. This implements the + /// Emit the "identifiers" directive. This implements the /// '.ident "version foo"' assembler directive. virtual void EmitIdent(StringRef IdentString) {} - /// \brief Associate a filename with a specified logical file number. This + /// Associate a filename with a specified logical file number. This /// implements the DWARF2 '.file 4 "foo.c"' assembler directive. - virtual unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, - StringRef Filename, - unsigned CUID = 0); + unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, + StringRef Filename, + MD5::MD5Result *Checksum = nullptr, + Optional<StringRef> Source = None, + unsigned CUID = 0) { + return cantFail( + tryEmitDwarfFileDirective(FileNo, Directory, Filename, Checksum, + Source, CUID)); + } + + /// Associate a filename with a specified logical file number. + /// Also associate a directory, optional checksum, and optional source + /// text with the logical file. This implements the DWARF2 + /// '.file 4 "dir/foo.c"' assembler directive, and the DWARF5 + /// '.file 4 "dir/foo.c" md5 "..." source "..."' assembler directive. + virtual Expected<unsigned> tryEmitDwarfFileDirective( + unsigned FileNo, StringRef Directory, StringRef Filename, + MD5::MD5Result *Checksum = nullptr, Optional<StringRef> Source = None, + unsigned CUID = 0); + + /// Specify the "root" file of the compilation, using the ".file 0" extension. + virtual void emitDwarfFile0Directive(StringRef Directory, StringRef Filename, + MD5::MD5Result *Checksum, + Optional<StringRef> Source, + unsigned CUID = 0); - /// \brief This implements the DWARF2 '.loc fileno lineno ...' assembler + /// This implements the DWARF2 '.loc fileno lineno ...' assembler /// directive. virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, @@ -772,27 +808,27 @@ public: ArrayRef<uint8_t> Checksum, unsigned ChecksumKind); - /// \brief Introduces a function id for use with .cv_loc. + /// Introduces a function id for use with .cv_loc. virtual bool EmitCVFuncIdDirective(unsigned FunctionId); - /// \brief Introduces an inline call site id for use with .cv_loc. Includes + /// Introduces an inline call site id for use with .cv_loc. Includes /// extra information for inline line table generation. virtual bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, unsigned IAFile, unsigned IALine, unsigned IACol, SMLoc Loc); - /// \brief This implements the CodeView '.cv_loc' assembler directive. + /// This implements the CodeView '.cv_loc' assembler directive. virtual void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, unsigned Column, bool PrologueEnd, bool IsStmt, StringRef FileName, SMLoc Loc); - /// \brief This implements the CodeView '.cv_linetable' assembler directive. + /// This implements the CodeView '.cv_linetable' assembler directive. virtual void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, const MCSymbol *FnEnd); - /// \brief This implements the CodeView '.cv_inline_linetable' assembler + /// This implements the CodeView '.cv_inline_linetable' assembler /// directive. virtual void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, unsigned SourceFileId, @@ -800,16 +836,16 @@ public: const MCSymbol *FnStartSym, const MCSymbol *FnEndSym); - /// \brief This implements the CodeView '.cv_def_range' assembler + /// This implements the CodeView '.cv_def_range' assembler /// directive. virtual void EmitCVDefRangeDirective( ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, StringRef FixedSizePortion); - /// \brief This implements the CodeView '.cv_stringtable' assembler directive. + /// This implements the CodeView '.cv_stringtable' assembler directive. virtual void EmitCVStringTableDirective() {} - /// \brief This implements the CodeView '.cv_filechecksums' assembler directive. + /// This implements the CodeView '.cv_filechecksums' assembler directive. virtual void EmitCVFileChecksumsDirective() {} /// This implements the CodeView '.cv_filechecksumoffset' assembler @@ -825,6 +861,10 @@ public: virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size); + /// Emit the absolute difference between two symbols encoded with ULEB128. + virtual void emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, + const MCSymbol *Lo); + virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID); virtual void EmitCFISections(bool EH, bool Debug); void EmitCFIStartProc(bool IsSimple); @@ -867,6 +907,9 @@ public: SMLoc Loc = SMLoc()); virtual void EmitWinEHHandlerData(SMLoc Loc = SMLoc()); + virtual void emitCGProfileEntry(const MCSymbolRefExpr *From, + const MCSymbolRefExpr *To, uint64_t Count); + /// Get the .pdata section used for the given section. Typically the given /// section is either the main .text section or some other COMDAT .text /// section, but it may be any section containing code. @@ -877,41 +920,45 @@ public: virtual void EmitSyntaxDirective(); - /// \brief Emit a .reloc directive. + /// Emit a .reloc directive. /// Returns true if the relocation could not be emitted because Name is not /// known. virtual bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, - const MCExpr *Expr, SMLoc Loc) { + const MCExpr *Expr, SMLoc Loc, + const MCSubtargetInfo &STI) { return true; } - /// \brief Emit the given \p Instruction into the current section. + virtual void EmitAddrsig() {} + virtual void EmitAddrsigSym(const MCSymbol *Sym) {} + + /// Emit the given \p Instruction into the current section. /// PrintSchedInfo == true then schedul comment should be added to output virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, bool PrintSchedInfo = false); - /// \brief Set the bundle alignment mode from now on in the section. + /// Set the bundle alignment mode from now on in the section. /// The argument is the power of 2 to which the alignment is set. The /// value 0 means turn the bundle alignment off. virtual void EmitBundleAlignMode(unsigned AlignPow2); - /// \brief The following instructions are a bundle-locked group. + /// The following instructions are a bundle-locked group. /// /// \param AlignToEnd - If true, the bundle-locked group will be aligned to /// the end of a bundle. virtual void EmitBundleLock(bool AlignToEnd); - /// \brief Ends a bundle-locked group. + /// Ends a bundle-locked group. virtual void EmitBundleUnlock(); - /// \brief If this file is backed by a assembly streamer, this dumps the + /// If this file is backed by a assembly streamer, this dumps the /// specified string in the output .s file. This capability is indicated by /// the hasRawTextSupport() predicate. By default this aborts. void EmitRawText(const Twine &String); - /// \brief Streamer specific finalization. + /// Streamer specific finalization. virtual void FinishImpl(); - /// \brief Finish emission of machine code. + /// Finish emission of machine code. void Finish(); virtual bool mayHaveInstructions(MCSection &Sec) const { return true; } diff --git a/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h b/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h index dd10881b73a8..b3ce523d9c0c 100644 --- a/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h +++ b/contrib/llvm/include/llvm/MC/MCSubtargetInfo.h @@ -27,15 +27,14 @@ namespace llvm { -class MachineInstr; class MCInst; //===----------------------------------------------------------------------===// /// -/// MCSubtargetInfo - Generic base class for all target subtargets. +/// Generic base class for all target subtargets. /// class MCSubtargetInfo { - Triple TargetTriple; // Target triple + Triple TargetTriple; std::string CPU; // CPU being targeted. ArrayRef<SubtargetFeatureKV> ProcFeatures; // Processor feature list ArrayRef<SubtargetFeatureKV> ProcDesc; // Processor descriptions @@ -49,7 +48,7 @@ class MCSubtargetInfo { const InstrStage *Stages; // Instruction itinerary stages const unsigned *OperandCycles; // Itinerary operand cycles - const unsigned *ForwardingPaths; // Forwarding paths + const unsigned *ForwardingPaths; FeatureBitset FeatureBits; // Feature bits for current CPU + FS public: @@ -66,22 +65,10 @@ public: MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete; virtual ~MCSubtargetInfo() = default; - /// getTargetTriple - Return the target triple string. const Triple &getTargetTriple() const { return TargetTriple; } + StringRef getCPU() const { return CPU; } - /// getCPU - Return the CPU string. - StringRef getCPU() const { - return CPU; - } - - /// getFeatureBits - Return the feature bits. - /// - const FeatureBitset& getFeatureBits() const { - return FeatureBits; - } - - /// setFeatureBits - Set the feature bits. - /// + const FeatureBitset& getFeatureBits() const { return FeatureBits; } void setFeatureBits(const FeatureBitset &FeatureBits_) { FeatureBits = FeatureBits_; } @@ -102,16 +89,16 @@ public: /// string. void setDefaultFeatures(StringRef CPU, StringRef FS); - /// ToggleFeature - Toggle a feature and returns the re-computed feature - /// bits. This version does not change the implied bits. + /// Toggle a feature and return the re-computed feature bits. + /// This version does not change the implied bits. FeatureBitset ToggleFeature(uint64_t FB); - /// ToggleFeature - Toggle a feature and returns the re-computed feature - /// bits. This version does not change the implied bits. + /// Toggle a feature and return the re-computed feature bits. + /// This version does not change the implied bits. FeatureBitset ToggleFeature(const FeatureBitset& FB); - /// ToggleFeature - Toggle a set of features and returns the re-computed - /// feature bits. This version will also change all implied bits. + /// Toggle a set of features and return the re-computed feature bits. + /// This version will also change all implied bits. FeatureBitset ToggleFeature(StringRef FS); /// Apply a feature flag and return the re-computed feature bits, including @@ -122,8 +109,7 @@ public: /// the provided string, ignoring all other features. bool checkFeatures(StringRef FS) const; - /// getSchedModelForCPU - Get the machine model of a CPU. - /// + /// Get the machine model of a CPU. const MCSchedModel &getSchedModelForCPU(StringRef CPU) const; /// Get the machine model for this subtarget's CPU. @@ -167,13 +153,19 @@ public: return 0; } - /// getInstrItineraryForCPU - Get scheduling itinerary of a CPU. - /// + /// Get scheduling itinerary of a CPU. InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const; /// Initialize an InstrItineraryData instance. void initInstrItins(InstrItineraryData &InstrItins) const; + /// Resolve a variant scheduling class for the given MCInst and CPU. + virtual unsigned + resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI, + unsigned CPUID) const { + return 0; + } + /// Check whether the CPU string is valid. bool isCPUStringValid(StringRef CPU) const { auto Found = std::lower_bound(ProcDesc.begin(), ProcDesc.end(), CPU); @@ -181,10 +173,6 @@ public: } /// Returns string representation of scheduler comment - virtual std::string getSchedInfoStr(const MachineInstr &MI) const { - return {}; - } - virtual std::string getSchedInfoStr(MCInst const &MCI) const { return {}; } diff --git a/contrib/llvm/include/llvm/MC/MCSymbol.h b/contrib/llvm/include/llvm/MC/MCSymbol.h index 9b1cc6e7d7e8..4681a1be60c4 100644 --- a/contrib/llvm/include/llvm/MC/MCSymbol.h +++ b/contrib/llvm/include/llvm/MC/MCSymbol.h @@ -85,7 +85,7 @@ protected: /// "Lfoo" or ".foo". unsigned IsTemporary : 1; - /// \brief True if this symbol can be redefined. + /// True if this symbol can be redefined. unsigned IsRedefinable : 1; /// IsUsed - True if this symbol has been used. @@ -141,7 +141,7 @@ protected: friend class MCExpr; friend class MCContext; - /// \brief The name for a symbol. + /// The name for a symbol. /// MCSymbol contains a uint64_t so is probably aligned to 8. On a 32-bit /// system, the name is a pointer so isn't going to satisfy the 8 byte /// alignment of uint64_t. Account for that here. @@ -168,24 +168,24 @@ protected: private: void operator delete(void *); - /// \brief Placement delete - required by std, but never called. + /// Placement delete - required by std, but never called. void operator delete(void*, unsigned) { llvm_unreachable("Constructor throws?"); } - /// \brief Placement delete - required by std, but never called. + /// Placement delete - required by std, but never called. void operator delete(void*, unsigned, bool) { llvm_unreachable("Constructor throws?"); } - MCSection *getSectionPtr(bool SetUsed = true) const { - if (MCFragment *F = getFragment(SetUsed)) { + MCSection *getSectionPtr() const { + if (MCFragment *F = getFragment()) { assert(F != AbsolutePseudoFragment); return F->getParent(); } return nullptr; } - /// \brief Get a reference to the name field. Requires that we have a name + /// Get a reference to the name field. Requires that we have a name const StringMapEntry<bool> *&getNameEntryPtr() { assert(FragmentAndHasName.getInt() && "Name is required"); NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this); @@ -221,13 +221,12 @@ public: /// isUsed - Check if this is used. bool isUsed() const { return IsUsed; } - void setUsed(bool Value) const { IsUsed |= Value; } - /// \brief Check if this symbol is redefinable. + /// Check if this symbol is redefinable. bool isRedefinable() const { return IsRedefinable; } - /// \brief Mark this symbol as redefinable. + /// Mark this symbol as redefinable. void setRedefinable(bool Value) { IsRedefinable = Value; } - /// \brief Prepare this symbol to be redefined. + /// Prepare this symbol to be redefined. void redefineIfPossible() { if (IsRedefinable) { if (SymbolContents == SymContentsVariable) { @@ -246,28 +245,28 @@ public: /// isDefined - Check if this symbol is defined (i.e., it has an address). /// /// Defined symbols are either absolute or in some section. - bool isDefined(bool SetUsed = true) const { - return getFragment(SetUsed) != nullptr; - } + bool isDefined() const { return !isUndefined(); } /// isInSection - Check if this symbol is defined in some section (i.e., it /// is defined but not absolute). - bool isInSection(bool SetUsed = true) const { - return isDefined(SetUsed) && !isAbsolute(SetUsed); + bool isInSection() const { + return isDefined() && !isAbsolute(); } /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). - bool isUndefined(bool SetUsed = true) const { return !isDefined(SetUsed); } + bool isUndefined(bool SetUsed = true) const { + return getFragment(SetUsed) == nullptr; + } /// isAbsolute - Check if this is an absolute symbol. - bool isAbsolute(bool SetUsed = true) const { - return getFragment(SetUsed) == AbsolutePseudoFragment; + bool isAbsolute() const { + return getFragment() == AbsolutePseudoFragment; } /// Get the section associated with a defined, non-absolute symbol. - MCSection &getSection(bool SetUsed = true) const { - assert(isInSection(SetUsed) && "Invalid accessor!"); - return *getSectionPtr(SetUsed); + MCSection &getSection() const { + assert(isInSection() && "Invalid accessor!"); + return *getSectionPtr(); } /// Mark the symbol as defined in the fragment \p F. @@ -317,6 +316,8 @@ public: Index = Value; } + bool isUnset() const { return SymbolContents == SymContentsUnset; } + uint64_t getOffset() const { assert((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && diff --git a/contrib/llvm/include/llvm/MC/MCSymbolMachO.h b/contrib/llvm/include/llvm/MC/MCSymbolMachO.h index 25220e4a8109..6125c2050976 100644 --- a/contrib/llvm/include/llvm/MC/MCSymbolMachO.h +++ b/contrib/llvm/include/llvm/MC/MCSymbolMachO.h @@ -14,7 +14,7 @@ namespace llvm { class MCSymbolMachO : public MCSymbol { - /// \brief We store the value for the 'desc' symbol field in the + /// We store the value for the 'desc' symbol field in the /// lowest 16 bits of the implementation defined flags. enum MachOSymbolFlags : uint16_t { // See <mach-o/nlist.h>. SF_DescFlagsMask = 0xFFFF, @@ -104,7 +104,7 @@ public: setFlags(Value & SF_DescFlagsMask); } - /// \brief Get the encoded value of the flags as they will be emitted in to + /// Get the encoded value of the flags as they will be emitted in to /// the MachO binary uint16_t getEncodedFlags(bool EncodeAsAltEntry) const { uint16_t Flags = getFlags(); diff --git a/contrib/llvm/include/llvm/MC/MCSymbolWasm.h b/contrib/llvm/include/llvm/MC/MCSymbolWasm.h index 309ebf96d1b0..e043453dc732 100644 --- a/contrib/llvm/include/llvm/MC/MCSymbolWasm.h +++ b/contrib/llvm/include/llvm/MC/MCSymbolWasm.h @@ -15,15 +15,17 @@ namespace llvm { class MCSymbolWasm : public MCSymbol { -private: - bool IsFunction = false; + wasm::WasmSymbolType Type = wasm::WASM_SYMBOL_TYPE_DATA; bool IsWeak = false; bool IsHidden = false; + bool IsComdat = false; std::string ModuleName; SmallVector<wasm::ValType, 1> Returns; SmallVector<wasm::ValType, 4> Params; + wasm::WasmGlobalType GlobalType; bool ParamsSet = false; bool ReturnsSet = false; + bool GlobalTypeSet = false; /// An expression describing how to calculate the size of a symbol. If a /// symbol has no size this field will be NULL. @@ -40,8 +42,12 @@ public: const MCExpr *getSize() const { return SymbolSize; } void setSize(const MCExpr *SS) { SymbolSize = SS; } - bool isFunction() const { return IsFunction; } - void setIsFunction(bool isFunc) { IsFunction = isFunc; } + bool isFunction() const { return Type == wasm::WASM_SYMBOL_TYPE_FUNCTION; } + bool isData() const { return Type == wasm::WASM_SYMBOL_TYPE_DATA; } + bool isGlobal() const { return Type == wasm::WASM_SYMBOL_TYPE_GLOBAL; } + bool isSection() const { return Type == wasm::WASM_SYMBOL_TYPE_SECTION; } + wasm::WasmSymbolType getType() const { return Type; } + void setType(wasm::WasmSymbolType type) { Type = type; } bool isWeak() const { return IsWeak; } void setWeak(bool isWeak) { IsWeak = isWeak; } @@ -49,7 +55,11 @@ public: bool isHidden() const { return IsHidden; } void setHidden(bool isHidden) { IsHidden = isHidden; } + bool isComdat() const { return IsComdat; } + void setComdat(bool isComdat) { IsComdat = isComdat; } + const StringRef getModuleName() const { return ModuleName; } + void setModuleName(StringRef Name) { ModuleName = Name; } const SmallVector<wasm::ValType, 1> &getReturns() const { assert(ReturnsSet); @@ -70,6 +80,16 @@ public: ParamsSet = true; Params = std::move(Pars); } + + const wasm::WasmGlobalType &getGlobalType() const { + assert(GlobalTypeSet); + return GlobalType; + } + + void setGlobalType(wasm::WasmGlobalType GT) { + GlobalTypeSet = true; + GlobalType = GT; + } }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/MC/MCTargetOptions.h b/contrib/llvm/include/llvm/MC/MCTargetOptions.h index 5509bb3bdc7c..f5d330fbeb22 100644 --- a/contrib/llvm/include/llvm/MC/MCTargetOptions.h +++ b/contrib/llvm/include/llvm/MC/MCTargetOptions.h @@ -21,6 +21,7 @@ enum class ExceptionHandling { SjLj, /// setjmp/longjmp based exceptions ARM, /// ARM EHABI WinEH, /// Windows Exception Handling + Wasm, /// WebAssembly Exception Handling }; enum class DebugCompressionType { diff --git a/contrib/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.def b/contrib/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.inc index 5172fa44511f..5172fa44511f 100644 --- a/contrib/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.def +++ b/contrib/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.inc diff --git a/contrib/llvm/include/llvm/MC/MCValue.h b/contrib/llvm/include/llvm/MC/MCValue.h index ff223f70303b..11f5082ed3f4 100644 --- a/contrib/llvm/include/llvm/MC/MCValue.h +++ b/contrib/llvm/include/llvm/MC/MCValue.h @@ -23,7 +23,7 @@ namespace llvm { class MCAsmInfo; class raw_ostream; -/// \brief This represents an "assembler immediate". +/// 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 @@ -49,13 +49,13 @@ public: const MCSymbolRefExpr *getSymB() const { return SymB; } uint32_t getRefKind() const { return RefKind; } - /// \brief Is this an absolute (as opposed to relocatable) value. + /// Is this an absolute (as opposed to relocatable) value. bool isAbsolute() const { return !SymA && !SymB; } - /// \brief Print the value to the stream \p OS. + /// Print the value to the stream \p OS. void print(raw_ostream &OS) const; - /// \brief Print the value to stderr. + /// Print the value to stderr. void dump() const; MCSymbolRefExpr::VariantKind getAccessVariant() const; diff --git a/contrib/llvm/include/llvm/MC/MCWasmObjectWriter.h b/contrib/llvm/include/llvm/MC/MCWasmObjectWriter.h index a4d5eb857b39..e45030f302ff 100644 --- a/contrib/llvm/include/llvm/MC/MCWasmObjectWriter.h +++ b/contrib/llvm/include/llvm/MC/MCWasmObjectWriter.h @@ -10,18 +10,16 @@ #ifndef LLVM_MC_MCWASMOBJECTWRITER_H #define LLVM_MC_MCWASMOBJECTWRITER_H -#include "llvm/ADT/Triple.h" -#include "llvm/BinaryFormat/Wasm.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/MC/MCObjectWriter.h" +#include <memory> namespace llvm { class MCFixup; -class MCObjectWriter; class MCValue; class raw_pwrite_stream; -class MCWasmObjectTargetWriter { +class MCWasmObjectTargetWriter : public MCObjectTargetWriter { const unsigned Is64Bit : 1; protected: @@ -30,6 +28,11 @@ protected: public: virtual ~MCWasmObjectTargetWriter(); + virtual Triple::ObjectFormatType getFormat() const { return Triple::Wasm; } + static bool classof(const MCObjectTargetWriter *W) { + return W->getFormat() == Triple::Wasm; + } + virtual unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup) const = 0; @@ -39,7 +42,7 @@ public: /// @} }; -/// \brief Construct a new Wasm writer instance. +/// Construct a new Wasm writer instance. /// /// \param MOTW - The target specific Wasm writer subclass. /// \param OS - The stream to write to. diff --git a/contrib/llvm/include/llvm/MC/MCWasmStreamer.h b/contrib/llvm/include/llvm/MC/MCWasmStreamer.h index c0d45451a9ab..01e6a4379287 100644 --- a/contrib/llvm/include/llvm/MC/MCWasmStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCWasmStreamer.h @@ -15,6 +15,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/DataTypes.h" @@ -27,8 +28,10 @@ class raw_ostream; class MCWasmStreamer : public MCObjectStreamer { public: MCWasmStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter) - : MCObjectStreamer(Context, std::move(TAB), OS, std::move(Emitter)), + std::unique_ptr<MCObjectWriter> OW, + std::unique_ptr<MCCodeEmitter> Emitter) + : MCObjectStreamer(Context, std::move(TAB), std::move(OW), + std::move(Emitter)), SeenIdent(false) {} ~MCWasmStreamer() override; @@ -57,7 +60,8 @@ public: unsigned ByteAlignment) override; void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, - uint64_t Size = 0, unsigned ByteAlignment = 0) override; + uint64_t Size = 0, unsigned ByteAlignment = 0, + SMLoc Loc = SMLoc()) override; void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, @@ -73,7 +77,7 @@ private: void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override; void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; - /// \brief Merge the content of the fragment \p EF into the fragment \p DF. + /// Merge the content of the fragment \p EF into the fragment \p DF. void mergeFragment(MCDataFragment *, MCDataFragment *); bool SeenIdent; diff --git a/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h b/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h index 3234bd93cad0..c1d35ea1f6ba 100644 --- a/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/contrib/llvm/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -10,6 +10,7 @@ #ifndef LLVM_MC_MCWINCOFFOBJECTWRITER_H #define LLVM_MC_MCWINCOFFOBJECTWRITER_H +#include "llvm/MC/MCObjectWriter.h" #include <memory> namespace llvm { @@ -17,11 +18,10 @@ namespace llvm { class MCAsmBackend; class MCContext; class MCFixup; -class MCObjectWriter; class MCValue; class raw_pwrite_stream; - class MCWinCOFFObjectTargetWriter { + class MCWinCOFFObjectTargetWriter : public MCObjectTargetWriter { virtual void anchor(); const unsigned Machine; @@ -32,6 +32,11 @@ class raw_pwrite_stream; public: virtual ~MCWinCOFFObjectTargetWriter() = default; + virtual Triple::ObjectFormatType getFormat() const { return Triple::COFF; } + static bool classof(const MCObjectTargetWriter *W) { + return W->getFormat() == Triple::COFF; + } + unsigned getMachine() const { return Machine; } virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsCrossSection, @@ -39,7 +44,7 @@ class raw_pwrite_stream; virtual bool recordRelocation(const MCFixup &) const { return true; } }; - /// \brief Construct a new Win COFF writer instance. + /// Construct a new Win COFF writer instance. /// /// \param MOTW - The target specific WinCOFF writer subclass. /// \param OS - The stream to write to. diff --git a/contrib/llvm/include/llvm/MC/MCWinCOFFStreamer.h b/contrib/llvm/include/llvm/MC/MCWinCOFFStreamer.h index a2500c06efa1..0049d04b4b3f 100644 --- a/contrib/llvm/include/llvm/MC/MCWinCOFFStreamer.h +++ b/contrib/llvm/include/llvm/MC/MCWinCOFFStreamer.h @@ -28,7 +28,8 @@ class raw_pwrite_stream; class MCWinCOFFStreamer : public MCObjectStreamer { public: MCWinCOFFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, - std::unique_ptr<MCCodeEmitter> CE, raw_pwrite_stream &OS); + std::unique_ptr<MCCodeEmitter> CE, + std::unique_ptr<MCObjectWriter> OW); /// state management void reset() override { @@ -50,14 +51,16 @@ public: void EmitCOFFSymbolType(int Type) override; void EndCOFFSymbolDef() override; void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; + void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override; void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; + void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override; void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; void EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, - unsigned ByteAlignment) override; + unsigned ByteAlignment, SMLoc Loc = SMLoc()) override; void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; void EmitIdent(StringRef IdentString) override; diff --git a/contrib/llvm/include/llvm/MC/StringTableBuilder.h b/contrib/llvm/include/llvm/MC/StringTableBuilder.h index 0df3fcd63723..265260fcee4d 100644 --- a/contrib/llvm/include/llvm/MC/StringTableBuilder.h +++ b/contrib/llvm/include/llvm/MC/StringTableBuilder.h @@ -20,10 +20,10 @@ namespace llvm { class raw_ostream; -/// \brief Utility for building string tables with deduplicated suffixes. +/// Utility for building string tables with deduplicated suffixes. class StringTableBuilder { public: - enum Kind { ELF, WinCOFF, MachO, RAW }; + enum Kind { ELF, WinCOFF, MachO, RAW, DWARF }; private: DenseMap<CachedHashStringRef, size_t> StringIndexMap; @@ -39,13 +39,13 @@ public: StringTableBuilder(Kind K, unsigned Alignment = 1); ~StringTableBuilder(); - /// \brief Add a string to the builder. Returns the position of S in the + /// Add a string to the builder. Returns the position of S in the /// table. The position will be changed if finalize is used. /// Can only be used before the table is finalized. size_t add(CachedHashStringRef S); size_t add(StringRef S) { return add(CachedHashStringRef(S)); } - /// \brief Analyze the strings and build the final table. No more strings can + /// Analyze the strings and build the final table. No more strings can /// be added after this point. void finalize(); @@ -53,7 +53,7 @@ public: /// returned by add will still be valid. void finalizeInOrder(); - /// \brief Get the offest of a string in the string table. Can only be used + /// Get the offest of a string in the string table. Can only be used /// after the table is finalized. size_t getOffset(CachedHashStringRef S) const; size_t getOffset(StringRef S) const { diff --git a/contrib/llvm/include/llvm/Object/Archive.h b/contrib/llvm/include/llvm/Object/Archive.h index 5a1512bb9d36..9ef1e4875191 100644 --- a/contrib/llvm/include/llvm/Object/Archive.h +++ b/contrib/llvm/include/llvm/Object/Archive.h @@ -91,9 +91,9 @@ public: const Archive *Parent; ArchiveMemberHeader Header; - /// \brief Includes header but not padding byte. + /// Includes header but not padding byte. StringRef Data; - /// \brief Offset from Data to the start of the file. + /// Offset from Data to the start of the file. uint16_t StartOfFile; Expected<bool> isThinMember() const; diff --git a/contrib/llvm/include/llvm/Object/Binary.h b/contrib/llvm/include/llvm/Object/Binary.h index 5e93691d1fd2..99745e24b8c8 100644 --- a/contrib/llvm/include/llvm/Object/Binary.h +++ b/contrib/llvm/include/llvm/Object/Binary.h @@ -156,7 +156,7 @@ public: } }; -/// @brief Create a Binary from Source, autodetecting the file type. +/// Create a Binary from Source, autodetecting the file type. /// /// @param Source The data to create the Binary from. Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source, diff --git a/contrib/llvm/include/llvm/Object/COFF.h b/contrib/llvm/include/llvm/Object/COFF.h index b072dd5ba7d9..6caadea0175b 100644 --- a/contrib/llvm/include/llvm/Object/COFF.h +++ b/contrib/llvm/include/llvm/Object/COFF.h @@ -16,9 +16,9 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/BinaryFormat/COFF.h" -#include "llvm/DebugInfo/CodeView/CVDebugRecord.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Object/Binary.h" +#include "llvm/Object/CVDebugRecord.h" #include "llvm/Object/Error.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/BinaryByteStream.h" @@ -276,6 +276,7 @@ struct coff_symbol_generic { }; struct coff_aux_section_definition; +struct coff_aux_weak_external; class COFFSymbolRef { public: @@ -360,6 +361,13 @@ public: return getAux<coff_aux_section_definition>(); } + const coff_aux_weak_external *getWeakExternal() const { + if (!getNumberOfAuxSymbols() || + getStorageClass() != COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) + return nullptr; + return getAux<coff_aux_weak_external>(); + } + bool isAbsolute() const { return getSectionNumber() == -1; } @@ -452,11 +460,12 @@ struct coff_section { if (Characteristics & COFF::IMAGE_SCN_TYPE_NO_PAD) return 1; - // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1. + // Bit [20:24] contains section alignment. 0 means use a default alignment + // of 16. uint32_t Shift = (Characteristics >> 20) & 0xF; if (Shift > 0) return 1U << (Shift - 1); - return 1; + return 16; } }; @@ -927,6 +936,7 @@ public: uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; Triple::ArchType getArch() const override; + Expected<uint64_t> getStartAddress() const override; SubtargetFeatures getFeatures() const override { return SubtargetFeatures(); } import_directory_iterator import_directory_begin() const; @@ -963,6 +973,8 @@ public: std::error_code getDataDirectory(uint32_t index, const data_directory *&Res) const; std::error_code getSection(int32_t index, const coff_section *&Res) const; + std::error_code getSection(StringRef SectionName, + const coff_section *&Res) const; template <typename coff_symbol_type> std::error_code getSymbol(uint32_t Index, @@ -1012,8 +1024,7 @@ public: llvm_unreachable("null symbol table pointer!"); } - iterator_range<const coff_relocation *> - getRelocations(const coff_section *Sec) const; + ArrayRef<coff_relocation> getRelocations(const coff_section *Sec) const; std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; uint64_t getSectionSize(const coff_section *Sec) const; diff --git a/contrib/llvm/include/llvm/Object/COFFImportFile.h b/contrib/llvm/include/llvm/Object/COFFImportFile.h index 4b284de679b3..0a4556ad8884 100644 --- a/contrib/llvm/include/llvm/Object/COFFImportFile.h +++ b/contrib/llvm/include/llvm/Object/COFFImportFile.h @@ -74,6 +74,7 @@ struct COFFShortExport { std::string Name; std::string ExtName; std::string SymbolName; + std::string AliasTarget; uint16_t Ordinal = 0; bool Noname = false; @@ -81,10 +82,6 @@ struct COFFShortExport { bool Private = false; bool Constant = false; - bool isWeak() { - return ExtName.size() && ExtName != Name; - } - friend bool operator==(const COFFShortExport &L, const COFFShortExport &R) { return L.Name == R.Name && L.ExtName == R.ExtName && L.Ordinal == R.Ordinal && L.Noname == R.Noname && @@ -98,7 +95,7 @@ struct COFFShortExport { Error writeImportLibrary(StringRef ImportName, StringRef Path, ArrayRef<COFFShortExport> Exports, - COFF::MachineTypes Machine, bool MakeWeakAliases); + COFF::MachineTypes Machine, bool MinGW); } // namespace object } // namespace llvm diff --git a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVDebugRecord.h b/contrib/llvm/include/llvm/Object/CVDebugRecord.h index 5a0bb4266ba2..faad72c0df29 100644 --- a/contrib/llvm/include/llvm/DebugInfo/CodeView/CVDebugRecord.h +++ b/contrib/llvm/include/llvm/Object/CVDebugRecord.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_CODEVIEW_CVDEBUGRECORD_H -#define LLVM_DEBUGINFO_CODEVIEW_CVDEBUGRECORD_H +#ifndef LLVM_OBJECT_CVDEBUGRECORD_H +#define LLVM_OBJECT_CVDEBUGRECORD_H #include "llvm/Support/Endian.h" diff --git a/contrib/llvm/include/llvm/Object/Decompressor.h b/contrib/llvm/include/llvm/Object/Decompressor.h index c8e888d285e4..2a77d2ffbf68 100644 --- a/contrib/llvm/include/llvm/Object/Decompressor.h +++ b/contrib/llvm/include/llvm/Object/Decompressor.h @@ -17,10 +17,10 @@ namespace llvm { namespace object { -/// @brief Decompressor helps to handle decompression of compressed sections. +/// Decompressor helps to handle decompression of compressed sections. class Decompressor { public: - /// @brief Create decompressor object. + /// Create decompressor object. /// @param Name Section name. /// @param Data Section content. /// @param IsLE Flag determines if Data is in little endian form. @@ -28,27 +28,27 @@ public: static Expected<Decompressor> create(StringRef Name, StringRef Data, bool IsLE, bool Is64Bit); - /// @brief Resize the buffer and uncompress section data into it. + /// Resize the buffer and uncompress section data into it. /// @param Out Destination buffer. template <class T> Error resizeAndDecompress(T &Out) { Out.resize(DecompressedSize); return decompress({Out.data(), (size_t)DecompressedSize}); } - /// @brief Uncompress section data to raw buffer provided. + /// Uncompress section data to raw buffer provided. /// @param Buffer Destination buffer. Error decompress(MutableArrayRef<char> Buffer); - /// @brief Return memory buffer size required for decompression. + /// Return memory buffer size required for decompression. uint64_t getDecompressedSize() { return DecompressedSize; } - /// @brief Return true if section is compressed, including gnu-styled case. + /// Return true if section is compressed, including gnu-styled case. static bool isCompressed(const object::SectionRef &Section); - /// @brief Return true if section is a ELF compressed one. + /// Return true if section is a ELF compressed one. static bool isCompressedELFSection(uint64_t Flags, StringRef Name); - /// @brief Return true if section name matches gnu style compressed one. + /// Return true if section name matches gnu style compressed one. static bool isGnuStyle(StringRef Name); private: diff --git a/contrib/llvm/include/llvm/Object/ELF.h b/contrib/llvm/include/llvm/Object/ELF.h index 45c98233dec0..752d468fd25b 100644 --- a/contrib/llvm/include/llvm/Object/ELF.h +++ b/contrib/llvm/include/llvm/Object/ELF.h @@ -32,6 +32,7 @@ namespace llvm { namespace object { StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); +uint32_t getELFRelrRelocationType(uint32_t Machine); StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type); // Subclasses of ELFFile may need this for template instantiation @@ -60,6 +61,7 @@ public: using Elf_Phdr = typename ELFT::Phdr; using Elf_Rel = typename ELFT::Rel; using Elf_Rela = typename ELFT::Rela; + using Elf_Relr = typename ELFT::Relr; using Elf_Verdef = typename ELFT::Verdef; using Elf_Verdaux = typename ELFT::Verdaux; using Elf_Verneed = typename ELFT::Verneed; @@ -67,11 +69,15 @@ public: using Elf_Versym = typename ELFT::Versym; using Elf_Hash = typename ELFT::Hash; using Elf_GnuHash = typename ELFT::GnuHash; + using Elf_Nhdr = typename ELFT::Nhdr; + using Elf_Note = typename ELFT::Note; + using Elf_Note_Iterator = typename ELFT::NoteIterator; using Elf_Dyn_Range = typename ELFT::DynRange; using Elf_Shdr_Range = typename ELFT::ShdrRange; using Elf_Sym_Range = typename ELFT::SymRange; using Elf_Rel_Range = typename ELFT::RelRange; using Elf_Rela_Range = typename ELFT::RelaRange; + using Elf_Relr_Range = typename ELFT::RelrRange; using Elf_Phdr_Range = typename ELFT::PhdrRange; const uint8_t *base() const { @@ -107,8 +113,12 @@ public: StringRef getRelocationTypeName(uint32_t Type) const; void getRelocationTypeName(uint32_t Type, SmallVectorImpl<char> &Result) const; + uint32_t getRelrRelocationType() const; - /// \brief Get the symbol for a given relocation. + const char *getDynamicTagAsString(unsigned Arch, uint64_t Type) const; + const char *getDynamicTagAsString(uint64_t Type) const; + + /// Get the symbol for a given relocation. Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel, const Elf_Shdr *SymTab) const; @@ -126,6 +136,10 @@ public: Expected<Elf_Shdr_Range> sections() const; + Expected<Elf_Dyn_Range> dynamicEntries() const; + + Expected<const uint8_t *> toMappedAddr(uint64_t VAddr) const; + Expected<Elf_Sym_Range> symbols(const Elf_Shdr *Sec) const { if (!Sec) return makeArrayRef<Elf_Sym>(nullptr, nullptr); @@ -140,9 +154,15 @@ public: return getSectionContentsAsArray<Elf_Rel>(Sec); } + Expected<Elf_Relr_Range> relrs(const Elf_Shdr *Sec) const { + return getSectionContentsAsArray<Elf_Relr>(Sec); + } + + Expected<std::vector<Elf_Rela>> decode_relrs(Elf_Relr_Range relrs) const; + Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr *Sec) const; - /// \brief Iterate over program header table. + /// Iterate over program header table. Expected<Elf_Phdr_Range> program_headers() const { if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr)) return createError("invalid e_phentsize"); @@ -155,6 +175,73 @@ public: return makeArrayRef(Begin, Begin + getHeader()->e_phnum); } + /// Get an iterator over notes in a program header. + /// + /// The program header must be of type \c PT_NOTE. + /// + /// \param Phdr the program header to iterate over. + /// \param Err [out] an error to support fallible iteration, which should + /// be checked after iteration ends. + Elf_Note_Iterator notes_begin(const Elf_Phdr &Phdr, Error &Err) const { + if (Phdr.p_type != ELF::PT_NOTE) { + Err = createError("attempt to iterate notes of non-note program header"); + return Elf_Note_Iterator(Err); + } + if (Phdr.p_offset + Phdr.p_filesz > getBufSize()) { + Err = createError("invalid program header offset/size"); + return Elf_Note_Iterator(Err); + } + return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err); + } + + /// Get an iterator over notes in a section. + /// + /// The section must be of type \c SHT_NOTE. + /// + /// \param Shdr the section to iterate over. + /// \param Err [out] an error to support fallible iteration, which should + /// be checked after iteration ends. + Elf_Note_Iterator notes_begin(const Elf_Shdr &Shdr, Error &Err) const { + if (Shdr.sh_type != ELF::SHT_NOTE) { + Err = createError("attempt to iterate notes of non-note section"); + return Elf_Note_Iterator(Err); + } + if (Shdr.sh_offset + Shdr.sh_size > getBufSize()) { + Err = createError("invalid section offset/size"); + return Elf_Note_Iterator(Err); + } + return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err); + } + + /// Get the end iterator for notes. + Elf_Note_Iterator notes_end() const { + return Elf_Note_Iterator(); + } + + /// Get an iterator range over notes of a program header. + /// + /// The program header must be of type \c PT_NOTE. + /// + /// \param Phdr the program header to iterate over. + /// \param Err [out] an error to support fallible iteration, which should + /// be checked after iteration ends. + iterator_range<Elf_Note_Iterator> notes(const Elf_Phdr &Phdr, + Error &Err) const { + return make_range(notes_begin(Phdr, Err), notes_end()); + } + + /// Get an iterator range over notes of a section. + /// + /// The section must be of type \c SHT_NOTE. + /// + /// \param Shdr the section to iterate over. + /// \param Err [out] an error to support fallible iteration, which should + /// be checked after iteration ends. + iterator_range<Elf_Note_Iterator> notes(const Elf_Shdr &Shdr, + Error &Err) const { + return make_range(notes_begin(Shdr, Err), notes_end()); + } + Expected<StringRef> getSectionStringTable(Elf_Shdr_Range Sections) const; Expected<uint32_t> getSectionIndex(const Elf_Sym *Sym, Elf_Sym_Range Syms, ArrayRef<Elf_Word> ShndxTable) const; @@ -165,6 +252,7 @@ public: Elf_Sym_Range Symtab, ArrayRef<Elf_Word> ShndxTable) const; Expected<const Elf_Shdr *> getSection(uint32_t Index) const; + Expected<const Elf_Shdr *> getSection(const StringRef SectionName) const; Expected<const Elf_Sym *> getSymbol(const Elf_Shdr *Sec, uint32_t Index) const; @@ -177,10 +265,10 @@ public: Expected<ArrayRef<uint8_t>> getSectionContents(const Elf_Shdr *Sec) const; }; -using ELF32LEFile = ELFFile<ELFType<support::little, false>>; -using ELF64LEFile = ELFFile<ELFType<support::little, true>>; -using ELF32BEFile = ELFFile<ELFType<support::big, false>>; -using ELF64BEFile = ELFFile<ELFType<support::big, true>>; +using ELF32LEFile = ELFFile<ELF32LE>; +using ELF64LEFile = ELFFile<ELF64LE>; +using ELF32BEFile = ELFFile<ELF32BE>; +using ELF64BEFile = ELFFile<ELF64BE>; template <class ELFT> inline Expected<const typename ELFT::Shdr *> @@ -327,6 +415,11 @@ void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type, } template <class ELFT> +uint32_t ELFFile<ELFT>::getRelrRelocationType() const { + return getELFRelrRelocationType(getHeader()->e_machine); +} + +template <class ELFT> Expected<const typename ELFT::Sym *> ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel, const Elf_Shdr *SymTab) const { @@ -429,6 +522,22 @@ ELFFile<ELFT>::getSection(uint32_t Index) const { } template <class ELFT> +Expected<const typename ELFT::Shdr *> +ELFFile<ELFT>::getSection(const StringRef SectionName) const { + auto TableOrErr = sections(); + if (!TableOrErr) + return TableOrErr.takeError(); + for (auto &Sec : *TableOrErr) { + auto SecNameOrErr = getSectionName(&Sec); + if (!SecNameOrErr) + return SecNameOrErr.takeError(); + if (*SecNameOrErr == SectionName) + return &Sec; + } + return createError("invalid section name"); +} + +template <class ELFT> Expected<StringRef> ELFFile<ELFT>::getStringTable(const Elf_Shdr *Section) const { if (Section->sh_type != ELF::SHT_STRTAB) diff --git a/contrib/llvm/include/llvm/Object/ELFObjectFile.h b/contrib/llvm/include/llvm/Object/ELFObjectFile.h index 40503cb6bb9d..2c0905d545a7 100644 --- a/contrib/llvm/include/llvm/Object/ELFObjectFile.h +++ b/contrib/llvm/include/llvm/Object/ELFObjectFile.h @@ -15,6 +15,7 @@ #define LLVM_OBJECT_ELFOBJECTFILE_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" @@ -67,6 +68,9 @@ public: virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0; + /// Returns platform-specific object flags, if any. + virtual unsigned getPlatformFlags() const = 0; + elf_symbol_iterator_range symbols() const; static bool classof(const Binary *v) { return v->isELF(); } @@ -77,7 +81,11 @@ public: SubtargetFeatures getARMFeatures() const; + SubtargetFeatures getRISCVFeatures() const; + void setARMSubArch(Triple &TheTriple) const override; + + virtual uint16_t getEType() const = 0; }; class ELFSectionRef : public SectionRef { @@ -195,19 +203,20 @@ ELFObjectFileBase::symbols() const { template <class ELFT> class ELFObjectFile : public ELFObjectFileBase { uint16_t getEMachine() const override; + uint16_t getEType() const override; uint64_t getSymbolSize(DataRefImpl Sym) const override; public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - using uintX_t = typename ELFFile<ELFT>::uintX_t; + using uintX_t = typename ELFT::uint; - using Elf_Sym = typename ELFFile<ELFT>::Elf_Sym; - using Elf_Shdr = typename ELFFile<ELFT>::Elf_Shdr; - using Elf_Ehdr = typename ELFFile<ELFT>::Elf_Ehdr; - using Elf_Rel = typename ELFFile<ELFT>::Elf_Rel; - using Elf_Rela = typename ELFFile<ELFT>::Elf_Rela; - using Elf_Dyn = typename ELFFile<ELFT>::Elf_Dyn; + using Elf_Sym = typename ELFT::Sym; + using Elf_Shdr = typename ELFT::Shdr; + using Elf_Ehdr = typename ELFT::Ehdr; + using Elf_Rel = typename ELFT::Rel; + using Elf_Rela = typename ELFT::Rela; + using Elf_Dyn = typename ELFT::Dyn; private: ELFObjectFile(MemoryBufferRef Object, ELFFile<ELFT> EF, @@ -251,6 +260,7 @@ protected: bool isSectionVirtual(DataRefImpl Sec) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; + std::vector<SectionRef> dynamic_relocation_sections() const override; section_iterator getRelocatedSection(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; @@ -265,7 +275,7 @@ protected: uint64_t getSectionOffset(DataRefImpl Sec) const override; StringRef getRelocationTypeName(uint32_t Type) const; - /// \brief Get the relocation section that contains \a Rel. + /// Get the relocation section that contains \a Rel. const Elf_Shdr *getRelSection(DataRefImpl Rel) const { auto RelSecOrErr = EF.getSection(Rel.d.a); if (!RelSecOrErr) @@ -363,11 +373,9 @@ public: uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; Triple::ArchType getArch() const override; + Expected<uint64_t> getStartAddress() const override; - std::error_code getPlatformFlags(unsigned &Result) const override { - Result = EF.getHeader()->e_flags; - return std::error_code(); - } + unsigned getPlatformFlags() const override { return EF.getHeader()->e_flags; } std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const override { auto SectionsOrErr = EF.sections(); @@ -404,10 +412,10 @@ public: bool isRelocatableObject() const override; }; -using ELF32LEObjectFile = ELFObjectFile<ELFType<support::little, false>>; -using ELF64LEObjectFile = ELFObjectFile<ELFType<support::little, true>>; -using ELF32BEObjectFile = ELFObjectFile<ELFType<support::big, false>>; -using ELF64BEObjectFile = ELFObjectFile<ELFType<support::big, true>>; +using ELF32LEObjectFile = ELFObjectFile<ELF32LE>; +using ELF64LEObjectFile = ELFObjectFile<ELF64LE>; +using ELF32BEObjectFile = ELFObjectFile<ELF32BE>; +using ELF64BEObjectFile = ELFObjectFile<ELF64BE>; template <class ELFT> void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Sym) const { @@ -505,6 +513,10 @@ uint16_t ELFObjectFile<ELFT>::getEMachine() const { return EF.getHeader()->e_machine; } +template <class ELFT> uint16_t ELFObjectFile<ELFT>::getEType() const { + return EF.getHeader()->e_type; +} + template <class ELFT> uint64_t ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Sym) const { return getSymbol(Sym)->st_size; @@ -698,8 +710,9 @@ bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const { template <class ELFT> bool ELFObjectFile<ELFT>::isSectionData(DataRefImpl Sec) const { const Elf_Shdr *EShdr = getSection(Sec); - return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && - EShdr->sh_type == ELF::SHT_PROGBITS; + return EShdr->sh_type == ELF::SHT_PROGBITS && + EShdr->sh_flags & ELF::SHF_ALLOC && + !(EShdr->sh_flags & ELF::SHF_EXECINSTR); } template <class ELFT> @@ -710,6 +723,35 @@ bool ELFObjectFile<ELFT>::isSectionBSS(DataRefImpl Sec) const { } template <class ELFT> +std::vector<SectionRef> +ELFObjectFile<ELFT>::dynamic_relocation_sections() const { + std::vector<SectionRef> Res; + std::vector<uintptr_t> Offsets; + + auto SectionsOrErr = EF.sections(); + if (!SectionsOrErr) + return Res; + + for (const Elf_Shdr &Sec : *SectionsOrErr) { + if (Sec.sh_type != ELF::SHT_DYNAMIC) + continue; + Elf_Dyn *Dynamic = + reinterpret_cast<Elf_Dyn *>((uintptr_t)base() + Sec.sh_offset); + for (; Dynamic->d_tag != ELF::DT_NULL; Dynamic++) { + if (Dynamic->d_tag == ELF::DT_REL || Dynamic->d_tag == ELF::DT_RELA || + Dynamic->d_tag == ELF::DT_JMPREL) { + Offsets.push_back(Dynamic->d_un.d_val); + } + } + } + for (const Elf_Shdr &Sec : *SectionsOrErr) { + if (is_contained(Offsets, Sec.sh_offset)) + Res.emplace_back(toDRI(&Sec), this); + } + return Res; +} + +template <class ELFT> bool ELFObjectFile<ELFT>::isSectionVirtual(DataRefImpl Sec) const { return getSection(Sec)->sh_type == ELF::SHT_NOBITS; } @@ -790,8 +832,6 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const { template <class ELFT> uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const { - assert(EF.getHeader()->e_type == ELF::ET_REL && - "Only relocatable object files have relocation offsets"); const Elf_Shdr *sec = getRelSection(Rel); if (sec->sh_type == ELF::SHT_REL) return getRel(Rel)->r_offset; @@ -986,8 +1026,6 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: return "ELF32-sparc"; - case ELF::EM_WEBASSEMBLY: - return "ELF32-wasm"; case ELF::EM_AMDGPU: return "ELF32-amdgpu"; default: @@ -1011,8 +1049,6 @@ StringRef ELFObjectFile<ELFT>::getFileFormatName() const { return "ELF64-sparc"; case ELF::EM_MIPS: return "ELF64-mips"; - case ELF::EM_WEBASSEMBLY: - return "ELF64-wasm"; case ELF::EM_AMDGPU: return "ELF64-amdgpu"; case ELF::EM_BPF: @@ -1074,26 +1110,20 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const { return IsLittleEndian ? Triple::sparcel : Triple::sparc; case ELF::EM_SPARCV9: return Triple::sparcv9; - case ELF::EM_WEBASSEMBLY: - switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { - case ELF::ELFCLASS32: return Triple::wasm32; - case ELF::ELFCLASS64: return Triple::wasm64; - default: return Triple::UnknownArch; - } case ELF::EM_AMDGPU: { if (!IsLittleEndian) return Triple::UnknownArch; - unsigned EFlags = EF.getHeader()->e_flags; - switch (EFlags & ELF::EF_AMDGPU_ARCH) { - case ELF::EF_AMDGPU_ARCH_R600: + unsigned MACH = EF.getHeader()->e_flags & ELF::EF_AMDGPU_MACH; + if (MACH >= ELF::EF_AMDGPU_MACH_R600_FIRST && + MACH <= ELF::EF_AMDGPU_MACH_R600_LAST) return Triple::r600; - case ELF::EF_AMDGPU_ARCH_GCN: + if (MACH >= ELF::EF_AMDGPU_MACH_AMDGCN_FIRST && + MACH <= ELF::EF_AMDGPU_MACH_AMDGCN_LAST) return Triple::amdgcn; - default: - return Triple::UnknownArch; - } + + return Triple::UnknownArch; } case ELF::EM_BPF: @@ -1105,6 +1135,11 @@ template <class ELFT> Triple::ArchType ELFObjectFile<ELFT>::getArch() const { } template <class ELFT> +Expected<uint64_t> ELFObjectFile<ELFT>::getStartAddress() const { + return EF.getHeader()->e_entry; +} + +template <class ELFT> ELFObjectFileBase::elf_symbol_iterator_range ELFObjectFile<ELFT>::getDynamicSymbolIterators() const { return make_range(dynamic_symbol_begin(), dynamic_symbol_end()); diff --git a/contrib/llvm/include/llvm/Object/ELFTypes.h b/contrib/llvm/include/llvm/Object/ELFTypes.h index 83b688548fdc..fb386120e34d 100644 --- a/contrib/llvm/include/llvm/Object/ELFTypes.h +++ b/contrib/llvm/include/llvm/Object/ELFTypes.h @@ -40,11 +40,15 @@ template <class ELFT> struct Elf_Versym_Impl; template <class ELFT> struct Elf_Hash_Impl; template <class ELFT> struct Elf_GnuHash_Impl; template <class ELFT> struct Elf_Chdr_Impl; +template <class ELFT> struct Elf_Nhdr_Impl; +template <class ELFT> class Elf_Note_Impl; +template <class ELFT> class Elf_Note_Iterator_Impl; +template <class ELFT> struct Elf_CGProfile_Impl; template <endianness E, bool Is64> struct ELFType { private: template <typename Ty> - using packed = support::detail::packed_endian_specific_integral<Ty, E, 2>; + using packed = support::detail::packed_endian_specific_integral<Ty, E, 1>; public: static const endianness TargetEndianness = E; @@ -58,6 +62,7 @@ public: using Phdr = Elf_Phdr_Impl<ELFType<E, Is64>>; using Rel = Elf_Rel_Impl<ELFType<E, Is64>, false>; using Rela = Elf_Rel_Impl<ELFType<E, Is64>, true>; + using Relr = packed<uint>; using Verdef = Elf_Verdef_Impl<ELFType<E, Is64>>; using Verdaux = Elf_Verdaux_Impl<ELFType<E, Is64>>; using Verneed = Elf_Verneed_Impl<ELFType<E, Is64>>; @@ -66,11 +71,16 @@ public: using Hash = Elf_Hash_Impl<ELFType<E, Is64>>; using GnuHash = Elf_GnuHash_Impl<ELFType<E, Is64>>; using Chdr = Elf_Chdr_Impl<ELFType<E, Is64>>; + using Nhdr = Elf_Nhdr_Impl<ELFType<E, Is64>>; + using Note = Elf_Note_Impl<ELFType<E, Is64>>; + using NoteIterator = Elf_Note_Iterator_Impl<ELFType<E, Is64>>; + using CGProfile = Elf_CGProfile_Impl<ELFType<E, Is64>>; using DynRange = ArrayRef<Dyn>; using ShdrRange = ArrayRef<Shdr>; using SymRange = ArrayRef<Sym>; using RelRange = ArrayRef<Rel>; using RelaRange = ArrayRef<Rela>; + using RelrRange = ArrayRef<Relr>; using PhdrRange = ArrayRef<Phdr>; using Half = packed<uint16_t>; @@ -90,46 +100,7 @@ using ELF64BE = ELFType<support::big, true>; // Use an alignment of 2 for the typedefs since that is the worst case for // ELF files in archives. -// Templates to choose Elf_Addr and Elf_Off depending on is64Bits. -template <endianness target_endianness> struct ELFDataTypeTypedefHelperCommon { - using Elf_Half = support::detail::packed_endian_specific_integral< - uint16_t, target_endianness, 2>; - using Elf_Word = support::detail::packed_endian_specific_integral< - uint32_t, target_endianness, 2>; - using Elf_Sword = support::detail::packed_endian_specific_integral< - int32_t, target_endianness, 2>; - using Elf_Xword = support::detail::packed_endian_specific_integral< - uint64_t, target_endianness, 2>; - using Elf_Sxword = support::detail::packed_endian_specific_integral< - int64_t, target_endianness, 2>; -}; - -template <class ELFT> struct ELFDataTypeTypedefHelper; - -/// ELF 32bit types. -template <endianness TargetEndianness> -struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, false>> - : ELFDataTypeTypedefHelperCommon<TargetEndianness> { - using value_type = uint32_t; - using Elf_Addr = support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, 2>; - using Elf_Off = support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, 2>; -}; - -/// ELF 64bit types. -template <endianness TargetEndianness> -struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>> - : ELFDataTypeTypedefHelperCommon<TargetEndianness> { - using value_type = uint64_t; - using Elf_Addr = support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, 2>; - using Elf_Off = support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, 2>; -}; - // I really don't like doing this, but the alternative is copypasta. - #define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ using Elf_Addr = typename ELFT::Addr; \ using Elf_Off = typename ELFT::Off; \ @@ -139,9 +110,9 @@ struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, true>> using Elf_Xword = typename ELFT::Xword; \ using Elf_Sxword = typename ELFT::Sxword; -#define LLD_ELF_COMMA , +#define LLVM_ELF_COMMA , #define LLVM_ELF_IMPORT_TYPES(E, W) \ - LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLD_ELF_COMMA W>) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFType<E LLVM_ELF_COMMA W>) // Section header. template <class ELFT> struct Elf_Shdr_Base; @@ -181,7 +152,7 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { using Elf_Shdr_Base<ELFT>::sh_entsize; using Elf_Shdr_Base<ELFT>::sh_size; - /// @brief Get the number of entities this section contains if it has any. + /// Get the number of entities this section contains if it has any. unsigned getEntityCount() const { if (sh_entsize == 0) return 0; @@ -590,6 +561,134 @@ struct Elf_Chdr_Impl<ELFType<TargetEndianness, true>> { Elf_Xword ch_addralign; }; +/// Note header +template <class ELFT> +struct Elf_Nhdr_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word n_namesz; + Elf_Word n_descsz; + Elf_Word n_type; + + /// The alignment of the name and descriptor. + /// + /// Implementations differ from the specification here: in practice all + /// variants align both the name and descriptor to 4-bytes. + static const unsigned int Align = 4; + + /// Get the size of the note, including name, descriptor, and padding. + size_t getSize() const { + return sizeof(*this) + alignTo<Align>(n_namesz) + alignTo<Align>(n_descsz); + } +}; + +/// An ELF note. +/// +/// Wraps a note header, providing methods for accessing the name and +/// descriptor safely. +template <class ELFT> +class Elf_Note_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + + const Elf_Nhdr_Impl<ELFT> &Nhdr; + + template <class NoteIteratorELFT> friend class Elf_Note_Iterator_Impl; + + Elf_Note_Impl(const Elf_Nhdr_Impl<ELFT> &Nhdr) : Nhdr(Nhdr) {} + +public: + /// Get the note's name, excluding the terminating null byte. + StringRef getName() const { + if (!Nhdr.n_namesz) + return StringRef(); + return StringRef(reinterpret_cast<const char *>(&Nhdr) + sizeof(Nhdr), + Nhdr.n_namesz - 1); + } + + /// Get the note's descriptor. + ArrayRef<Elf_Word> getDesc() const { + if (!Nhdr.n_descsz) + return ArrayRef<Elf_Word>(); + return ArrayRef<Elf_Word>( + reinterpret_cast<const Elf_Word *>( + reinterpret_cast<const uint8_t *>(&Nhdr) + sizeof(Nhdr) + + alignTo<Elf_Nhdr_Impl<ELFT>::Align>(Nhdr.n_namesz)), + Nhdr.n_descsz); + } + + /// Get the note's type. + Elf_Word getType() const { return Nhdr.n_type; } +}; + +template <class ELFT> +class Elf_Note_Iterator_Impl + : std::iterator<std::forward_iterator_tag, Elf_Note_Impl<ELFT>> { + // Nhdr being a nullptr marks the end of iteration. + const Elf_Nhdr_Impl<ELFT> *Nhdr = nullptr; + size_t RemainingSize = 0u; + Error *Err = nullptr; + + template <class ELFFileELFT> friend class ELFFile; + + // Stop iteration and indicate an overflow. + void stopWithOverflowError() { + Nhdr = nullptr; + *Err = make_error<StringError>("ELF note overflows container", + object_error::parse_failed); + } + + // Advance Nhdr by NoteSize bytes, starting from NhdrPos. + // + // Assumes NoteSize <= RemainingSize. Ensures Nhdr->getSize() <= RemainingSize + // upon returning. Handles stopping iteration when reaching the end of the + // container, either cleanly or with an overflow error. + void advanceNhdr(const uint8_t *NhdrPos, size_t NoteSize) { + RemainingSize -= NoteSize; + if (RemainingSize == 0u) + Nhdr = nullptr; + else if (sizeof(*Nhdr) > RemainingSize) + stopWithOverflowError(); + else { + Nhdr = reinterpret_cast<const Elf_Nhdr_Impl<ELFT> *>(NhdrPos + NoteSize); + if (Nhdr->getSize() > RemainingSize) + stopWithOverflowError(); + } + } + + Elf_Note_Iterator_Impl() {} + explicit Elf_Note_Iterator_Impl(Error &Err) : Err(&Err) {} + Elf_Note_Iterator_Impl(const uint8_t *Start, size_t Size, Error &Err) + : RemainingSize(Size), Err(&Err) { + assert(Start && "ELF note iterator starting at NULL"); + advanceNhdr(Start, 0u); + } + +public: + Elf_Note_Iterator_Impl &operator++() { + assert(Nhdr && "incremented ELF note end iterator"); + const uint8_t *NhdrPos = reinterpret_cast<const uint8_t *>(Nhdr); + size_t NoteSize = Nhdr->getSize(); + advanceNhdr(NhdrPos, NoteSize); + return *this; + } + bool operator==(Elf_Note_Iterator_Impl Other) const { + return Nhdr == Other.Nhdr; + } + bool operator!=(Elf_Note_Iterator_Impl Other) const { + return !(*this == Other); + } + Elf_Note_Impl<ELFT> operator*() const { + assert(Nhdr && "dereferenced ELF note end iterator"); + return Elf_Note_Impl<ELFT>(*Nhdr); + } +}; + +template <class ELFT> struct Elf_CGProfile_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word cgp_from; + Elf_Word cgp_to; + Elf_Xword cgp_weight; +}; + // MIPS .reginfo section template <class ELFT> struct Elf_Mips_RegInfo; diff --git a/contrib/llvm/include/llvm/Object/IRObjectFile.h b/contrib/llvm/include/llvm/Object/IRObjectFile.h index 6c271b1a1f44..993359b766a1 100644 --- a/contrib/llvm/include/llvm/Object/IRObjectFile.h +++ b/contrib/llvm/include/llvm/Object/IRObjectFile.h @@ -50,11 +50,22 @@ public: return v->isIR(); } - /// \brief Finds and returns bitcode embedded in the given object file, or an + using module_iterator = + pointee_iterator<std::vector<std::unique_ptr<Module>>::const_iterator, + const Module>; + + module_iterator module_begin() const { return module_iterator(Mods.begin()); } + module_iterator module_end() const { return module_iterator(Mods.end()); } + + iterator_range<module_iterator> modules() const { + return make_range(module_begin(), module_end()); + } + + /// Finds and returns bitcode embedded in the given object file, or an /// error code if not found. static Expected<MemoryBufferRef> findBitcodeInObject(const ObjectFile &Obj); - /// \brief Finds and returns bitcode in the given memory buffer (which may + /// Finds and returns bitcode in the given memory buffer (which may /// be either a bitcode file or a native object file with embedded bitcode), /// or an error code if not found. static Expected<MemoryBufferRef> diff --git a/contrib/llvm/include/llvm/Object/MachO.h b/contrib/llvm/include/llvm/Object/MachO.h index d0cc40da4293..531b3d249035 100644 --- a/contrib/llvm/include/llvm/Object/MachO.h +++ b/contrib/llvm/include/llvm/Object/MachO.h @@ -304,6 +304,8 @@ public: std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; uint64_t getSectionAlignment(DataRefImpl Sec) const override; + Expected<SectionRef> getSection(unsigned SectionIndex) const; + Expected<SectionRef> getSection(StringRef SectionName) const; bool isSectionCompressed(DataRefImpl Sec) const override; bool isSectionText(DataRefImpl Sec) const override; bool isSectionData(DataRefImpl Sec) const override; @@ -463,7 +465,7 @@ public: // In a MachO file, sections have a segment name. This is used in the .o // files. They have a single segment, but this field specifies which segment - // a section should be put in in the final object. + // a section should be put in the final object. StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; // Names are stored as 16 bytes. These returns the raw 16 bytes without diff --git a/contrib/llvm/include/llvm/Object/MachOUniversal.h b/contrib/llvm/include/llvm/Object/MachOUniversal.h index 72837d0970c4..9e70b0bc30c0 100644 --- a/contrib/llvm/include/llvm/Object/MachOUniversal.h +++ b/contrib/llvm/include/llvm/Object/MachOUniversal.h @@ -34,9 +34,9 @@ class MachOUniversalBinary : public Binary { public: class ObjectForArch { const MachOUniversalBinary *Parent; - /// \brief Index of object in the universal binary. + /// Index of object in the universal binary. uint32_t Index; - /// \brief Descriptor of the object. + /// Descriptor of the object. MachO::fat_arch Header; MachO::fat_arch_64 Header64; diff --git a/contrib/llvm/include/llvm/Object/ModuleSymbolTable.h b/contrib/llvm/include/llvm/Object/ModuleSymbolTable.h index 9e9322885388..c3cbc27998e5 100644 --- a/contrib/llvm/include/llvm/Object/ModuleSymbolTable.h +++ b/contrib/llvm/include/llvm/Object/ModuleSymbolTable.h @@ -57,6 +57,15 @@ public: static void CollectAsmSymbols( const Module &M, function_ref<void(StringRef, object::BasicSymbolRef::Flags)> AsmSymbol); + + /// Parse inline ASM and collect the symvers directives that are defined in + /// the current module. + /// + /// For each found symbol, call \p AsmSymver with the name of the symbol and + /// its alias. + static void + CollectAsmSymvers(const Module &M, + function_ref<void(StringRef, StringRef)> AsmSymver); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Object/ObjectFile.h b/contrib/llvm/include/llvm/Object/ObjectFile.h index 079a59468156..02d62e8e4879 100644 --- a/contrib/llvm/include/llvm/Object/ObjectFile.h +++ b/contrib/llvm/include/llvm/Object/ObjectFile.h @@ -65,7 +65,7 @@ public: symbol_iterator getSymbol() const; uint64_t getType() const; - /// @brief Get a string that represents the type of this relocation. + /// Get a string that represents the type of this relocation. /// /// This is for display purposes only. void getTypeName(SmallVectorImpl<char> &Result) const; @@ -100,7 +100,7 @@ public: uint64_t getSize() const; std::error_code getContents(StringRef &Result) const; - /// @brief Get the alignment of this section as the actual value (not log 2). + /// Get the alignment of this section as the actual value (not log 2). uint64_t getAlignment() const; bool isCompressed() const; @@ -154,12 +154,12 @@ public: /// offset or a virtual address. uint64_t getValue() const; - /// @brief Get the alignment of this symbol as the actual value (not log 2). + /// Get the alignment of this symbol as the actual value (not log 2). uint32_t getAlignment() const; uint64_t getCommonSize() const; Expected<SymbolRef::Type> getType() const; - /// @brief Get section this symbol is defined in reference to. Result is + /// Get section this symbol is defined in reference to. Result is /// end_sections() if it is undefined or is an absolute symbol. Expected<section_iterator> getSection() const; @@ -262,6 +262,10 @@ public: return getCommonSymbolSizeImpl(Symb); } + virtual std::vector<SectionRef> dynamic_relocation_sections() const { + return std::vector<SectionRef>(); + } + using symbol_iterator_range = iterator_range<symbol_iterator>; symbol_iterator_range symbols() const { return symbol_iterator_range(symbol_begin(), symbol_end()); @@ -275,7 +279,7 @@ public: return section_iterator_range(section_begin(), section_end()); } - /// @brief The number of bytes used to represent an address in this object + /// The number of bytes used to represent an address in this object /// file format. virtual uint8_t getBytesInAddress() const = 0; @@ -283,16 +287,13 @@ public: virtual Triple::ArchType getArch() const = 0; virtual SubtargetFeatures getFeatures() const = 0; virtual void setARMSubArch(Triple &TheTriple) const { } + virtual Expected<uint64_t> getStartAddress() const { + return errorCodeToError(object_error::parse_failed); + }; - /// @brief Create a triple from the data in this object file. + /// Create a triple from the data in this object file. Triple makeTriple() const; - /// Returns platform-specific object flags, if any. - virtual std::error_code getPlatformFlags(unsigned &Result) const { - Result = 0; - return object_error::invalid_file_type; - } - virtual std::error_code getBuildAttributes(ARMAttributeParser &Attributes) const { return std::error_code(); @@ -307,7 +308,7 @@ public: /// @returns Pointer to ObjectFile subclass to handle this type of object. /// @param ObjectPath The path to the object file. ObjectPath.isObject must /// return true. - /// @brief Create ObjectFile from path. + /// Create ObjectFile from path. static Expected<OwningBinary<ObjectFile>> createObjectFile(StringRef ObjectPath); diff --git a/contrib/llvm/include/llvm/Object/RelocVisitor.h b/contrib/llvm/include/llvm/Object/RelocVisitor.h index 2d0e938f06fd..008e109f6679 100644 --- a/contrib/llvm/include/llvm/Object/RelocVisitor.h +++ b/contrib/llvm/include/llvm/Object/RelocVisitor.h @@ -23,6 +23,7 @@ #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/Wasm.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include <cstdint> @@ -31,7 +32,7 @@ namespace llvm { namespace object { -/// @brief Base class for object file relocation visitors. +/// Base class for object file relocation visitors. class RelocVisitor { public: explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {} @@ -46,6 +47,8 @@ public: return visitCOFF(Rel, R, Value); if (isa<MachOObjectFile>(ObjToVisit)) return visitMachO(Rel, R, Value); + if (isa<WasmObjectFile>(ObjToVisit)) + return visitWasm(Rel, R, Value); HasError = true; return 0; @@ -316,6 +319,27 @@ private: HasError = true; return 0; } + + uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) { + if (ObjToVisit.getArch() == Triple::wasm32) { + switch (Rel) { + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: + case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: + case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: + // For wasm section, its offset at 0 -- ignoring Value + return 0; + } + } + HasError = true; + return 0; + } }; } // end namespace object diff --git a/contrib/llvm/include/llvm/Object/Wasm.h b/contrib/llvm/include/llvm/Object/Wasm.h index 71951d83f3cc..fd34e45feb62 100644 --- a/contrib/llvm/include/llvm/Object/Wasm.h +++ b/contrib/llvm/include/llvm/Object/Wasm.h @@ -21,6 +21,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringMap.h" #include "llvm/BinaryFormat/Wasm.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Object/Binary.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Error.h" @@ -34,61 +35,49 @@ namespace object { class WasmSymbol { public: - enum class SymbolType { - FUNCTION_IMPORT, - FUNCTION_EXPORT, - GLOBAL_IMPORT, - GLOBAL_EXPORT, - DEBUG_FUNCTION_NAME, - }; - - WasmSymbol(StringRef Name, SymbolType Type, uint32_t Section, - uint32_t ElementIndex, uint32_t FunctionType = 0) - : Name(Name), Type(Type), Section(Section), ElementIndex(ElementIndex), - FunctionType(FunctionType) {} + WasmSymbol(const wasm::WasmSymbolInfo &Info, + const wasm::WasmSignature *FunctionType, + const wasm::WasmGlobalType *GlobalType) + : Info(Info), FunctionType(FunctionType), GlobalType(GlobalType) {} - StringRef Name; - SymbolType Type; - uint32_t Section; - uint32_t Flags = 0; + const wasm::WasmSymbolInfo &Info; + const wasm::WasmSignature *FunctionType; + const wasm::WasmGlobalType *GlobalType; - // Index into either the function or global index space. - uint32_t ElementIndex; - - // For function, the type index - uint32_t FunctionType; + bool isTypeFunction() const { + return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION; + } - // Symbols can be both exported and imported (in the case of the weakly - // defined symbol). In this the import index is stored as AltIndex. - uint32_t AltIndex = 0; - bool HasAltIndex = false; + bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; } - void setAltIndex(uint32_t Index) { - HasAltIndex = true; - AltIndex = Index; + bool isTypeGlobal() const { + return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL; } - bool isFunction() const { - return Type == WasmSymbol::SymbolType::FUNCTION_IMPORT || - Type == WasmSymbol::SymbolType::FUNCTION_EXPORT || - Type == WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME; + bool isTypeSection() const { + return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION; } + bool isDefined() const { return !isUndefined(); } - bool isWeak() const { + bool isUndefined() const { + return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0; + } + + bool isBindingWeak() const { return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK; } - bool isGlobal() const { + bool isBindingGlobal() const { return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL; } - bool isLocal() const { + bool isBindingLocal() const { return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL; } unsigned getBinding() const { - return Flags & wasm::WASM_SYMBOL_BINDING_MASK; + return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK; } bool isHidden() const { @@ -96,16 +85,13 @@ public: } unsigned getVisibility() const { - return Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK; + return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK; } - void print(raw_ostream &Out) const { - Out << "Name=" << Name << ", Type=" << static_cast<int>(Type) - << ", Flags=" << Flags << " ElemIndex=" << ElementIndex; - } + void print(raw_ostream &Out) const; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - LLVM_DUMP_METHOD void dump() const { print(dbgs()); } + LLVM_DUMP_METHOD void dump() const; #endif }; @@ -144,12 +130,16 @@ public: ArrayRef<wasm::WasmLimits> memories() const { return Memories; } ArrayRef<wasm::WasmGlobal> globals() const { return Globals; } ArrayRef<wasm::WasmExport> exports() const { return Exports; } + ArrayRef<WasmSymbol> syms() const { return Symbols; } const wasm::WasmLinkingData& linkingData() const { return LinkingData; } uint32_t getNumberOfSymbols() const { return Symbols.size(); } ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; } ArrayRef<WasmSegment> dataSegments() const { return DataSegments; } ArrayRef<wasm::WasmFunction> functions() const { return Functions; } + ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; } uint32_t startFunction() const { return StartFunction; } + uint32_t getNumImportedGlobals() const { return NumImportedGlobals; } + uint32_t getNumImportedFunctions() const { return NumImportedFunctions; } void moveSymbolNext(DataRefImpl &Symb) const override; @@ -203,39 +193,50 @@ public: SubtargetFeatures getFeatures() const override; bool isRelocatableObject() const override; + struct ReadContext { + const uint8_t *Start; + const uint8_t *Ptr; + const uint8_t *End; + }; + private: bool isValidFunctionIndex(uint32_t Index) const; + bool isDefinedFunctionIndex(uint32_t Index) const; + bool isValidGlobalIndex(uint32_t Index) const; + bool isDefinedGlobalIndex(uint32_t Index) const; + bool isValidFunctionSymbol(uint32_t Index) const; + bool isValidGlobalSymbol(uint32_t Index) const; + bool isValidDataSymbol(uint32_t Index) const; + bool isValidSectionSymbol(uint32_t Index) const; + wasm::WasmFunction &getDefinedFunction(uint32_t Index); + wasm::WasmGlobal &getDefinedGlobal(uint32_t Index); + const WasmSection &getWasmSection(DataRefImpl Ref) const; const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const; - WasmSection* findCustomSectionByName(StringRef Name); - WasmSection* findSectionByType(uint32_t Type); - const uint8_t *getPtr(size_t Offset) const; Error parseSection(WasmSection &Sec); - Error parseCustomSection(WasmSection &Sec, const uint8_t *Ptr, - const uint8_t *End); + Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx); // Standard section types - Error parseTypeSection(const uint8_t *Ptr, const uint8_t *End); - Error parseImportSection(const uint8_t *Ptr, const uint8_t *End); - Error parseFunctionSection(const uint8_t *Ptr, const uint8_t *End); - Error parseTableSection(const uint8_t *Ptr, const uint8_t *End); - Error parseMemorySection(const uint8_t *Ptr, const uint8_t *End); - Error parseGlobalSection(const uint8_t *Ptr, const uint8_t *End); - Error parseExportSection(const uint8_t *Ptr, const uint8_t *End); - Error parseStartSection(const uint8_t *Ptr, const uint8_t *End); - Error parseElemSection(const uint8_t *Ptr, const uint8_t *End); - Error parseCodeSection(const uint8_t *Ptr, const uint8_t *End); - Error parseDataSection(const uint8_t *Ptr, const uint8_t *End); + Error parseTypeSection(ReadContext &Ctx); + Error parseImportSection(ReadContext &Ctx); + Error parseFunctionSection(ReadContext &Ctx); + Error parseTableSection(ReadContext &Ctx); + Error parseMemorySection(ReadContext &Ctx); + Error parseGlobalSection(ReadContext &Ctx); + Error parseExportSection(ReadContext &Ctx); + Error parseStartSection(ReadContext &Ctx); + Error parseElemSection(ReadContext &Ctx); + Error parseCodeSection(ReadContext &Ctx); + Error parseDataSection(ReadContext &Ctx); // Custom section types - Error parseNameSection(const uint8_t *Ptr, const uint8_t *End); - Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End); - Error parseRelocSection(StringRef Name, const uint8_t *Ptr, - const uint8_t *End); - - void populateSymbolTable(); + Error parseNameSection(ReadContext &Ctx); + Error parseLinkingSection(ReadContext &Ctx); + Error parseLinkingSectionSymtab(ReadContext &Ctx); + Error parseLinkingSectionComdat(ReadContext &Ctx); + Error parseRelocSection(StringRef Name, ReadContext &Ctx); wasm::WasmObjectHeader Header; std::vector<WasmSection> Sections; @@ -250,15 +251,15 @@ private: std::vector<WasmSegment> DataSegments; std::vector<wasm::WasmFunction> Functions; std::vector<WasmSymbol> Symbols; + std::vector<wasm::WasmFunctionName> DebugNames; uint32_t StartFunction = -1; bool HasLinkingSection = false; wasm::WasmLinkingData LinkingData; uint32_t NumImportedGlobals = 0; uint32_t NumImportedFunctions = 0; - uint32_t ImportSection = 0; - uint32_t ExportSection = 0; - - StringMap<uint32_t> SymbolMap; + uint32_t CodeSection = 0; + uint32_t DataSection = 0; + uint32_t GlobalSection = 0; }; } // end namespace object diff --git a/contrib/llvm/include/llvm/Object/WasmTraits.h b/contrib/llvm/include/llvm/Object/WasmTraits.h new file mode 100644 index 000000000000..ebcd00b15227 --- /dev/null +++ b/contrib/llvm/include/llvm/Object/WasmTraits.h @@ -0,0 +1,63 @@ +//===- WasmTraits.h - DenseMap traits for the Wasm structures ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides llvm::DenseMapInfo traits for the Wasm structures. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_WASMTRAITS_H +#define LLVM_OBJECT_WASMTRAITS_H + +#include "llvm/ADT/Hashing.h" +#include "llvm/BinaryFormat/Wasm.h" + +namespace llvm { + +template <typename T> struct DenseMapInfo; + +// Traits for using WasmSignature in a DenseMap. +template <> struct DenseMapInfo<wasm::WasmSignature> { + static wasm::WasmSignature getEmptyKey() { + return wasm::WasmSignature{{}, 1}; + } + static wasm::WasmSignature getTombstoneKey() { + return wasm::WasmSignature{{}, 2}; + } + static unsigned getHashValue(const wasm::WasmSignature &Sig) { + unsigned H = hash_value(Sig.ReturnType); + for (int32_t Param : Sig.ParamTypes) + H = hash_combine(H, Param); + return H; + } + static bool isEqual(const wasm::WasmSignature &LHS, + const wasm::WasmSignature &RHS) { + return LHS == RHS; + } +}; + +// Traits for using WasmGlobalType in a DenseMap +template <> struct DenseMapInfo<wasm::WasmGlobalType> { + static wasm::WasmGlobalType getEmptyKey() { + return wasm::WasmGlobalType{1, true}; + } + static wasm::WasmGlobalType getTombstoneKey() { + return wasm::WasmGlobalType{2, true}; + } + static unsigned getHashValue(const wasm::WasmGlobalType &GlobalType) { + return hash_combine(GlobalType.Type, GlobalType.Mutable); + } + static bool isEqual(const wasm::WasmGlobalType &LHS, + const wasm::WasmGlobalType &RHS) { + return LHS == RHS; + } +}; + +} // end namespace llvm + +#endif // LLVM_OBJECT_WASMTRAITS_H diff --git a/contrib/llvm/include/llvm/ObjectYAML/COFFYAML.h b/contrib/llvm/include/llvm/ObjectYAML/COFFYAML.h index 8794eaa6d59a..78f021fc0386 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/COFFYAML.h +++ b/contrib/llvm/include/llvm/ObjectYAML/COFFYAML.h @@ -67,6 +67,7 @@ struct Section { yaml::BinaryRef SectionData; std::vector<CodeViewYAML::YAMLDebugSubsection> DebugS; std::vector<CodeViewYAML::LeafRecord> DebugT; + std::vector<CodeViewYAML::LeafRecord> DebugP; Optional<CodeViewYAML::DebugHSection> DebugH; std::vector<Relocation> Relocations; StringRef Name; diff --git a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h index 4f0d9efb963b..344966fe6891 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h +++ b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypeHashing.h @@ -32,10 +32,10 @@ namespace CodeViewYAML { struct GlobalHash { GlobalHash() = default; explicit GlobalHash(StringRef S) : Hash(S) { - assert(S.size() == 20 && "Invalid hash size!"); + assert(S.size() == 8 && "Invalid hash size!"); } explicit GlobalHash(ArrayRef<uint8_t> S) : Hash(S) { - assert(S.size() == 20 && "Invalid hash size!"); + assert(S.size() == 8 && "Invalid hash size!"); } yaml::BinaryRef Hash; }; @@ -47,7 +47,7 @@ struct DebugHSection { std::vector<GlobalHash> Hashes; }; -DebugHSection fromDebugH(ArrayRef<uint8_t> DebugT); +DebugHSection fromDebugH(ArrayRef<uint8_t> DebugH); ArrayRef<uint8_t> toDebugH(const DebugHSection &DebugH, BumpPtrAllocator &Alloc); diff --git a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h index bc3b5567c2f9..1b1306df4f53 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h +++ b/contrib/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h @@ -51,8 +51,10 @@ struct LeafRecord { static Expected<LeafRecord> fromCodeViewRecord(codeview::CVType Type); }; -std::vector<LeafRecord> fromDebugT(ArrayRef<uint8_t> DebugT); -ArrayRef<uint8_t> toDebugT(ArrayRef<LeafRecord>, BumpPtrAllocator &Alloc); +std::vector<LeafRecord> fromDebugT(ArrayRef<uint8_t> DebugTorP, + StringRef SectionName); +ArrayRef<uint8_t> toDebugT(ArrayRef<LeafRecord>, BumpPtrAllocator &Alloc, + StringRef SectionName); } // end namespace CodeViewYAML diff --git a/contrib/llvm/include/llvm/ObjectYAML/DWARFEmitter.h b/contrib/llvm/include/llvm/ObjectYAML/DWARFEmitter.h index 0d7d8b4efbdf..ce3227421930 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/DWARFEmitter.h +++ b/contrib/llvm/include/llvm/ObjectYAML/DWARFEmitter.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// /// \file -/// \brief Common declarations for yaml2obj +/// Common declarations for yaml2obj //===----------------------------------------------------------------------===// #ifndef LLVM_OBJECTYAML_DWARFEMITTER_H @@ -39,11 +39,12 @@ void EmitDebugInfo(raw_ostream &OS, const Data &DI); void EmitDebugLine(raw_ostream &OS, const Data &DI); Expected<StringMap<std::unique_ptr<MemoryBuffer>>> -EmitDebugSections(StringRef YAMLString, +EmitDebugSections(StringRef YAMLString, bool ApplyFixups = false, bool IsLittleEndian = sys::IsLittleEndianHost); +StringMap<std::unique_ptr<MemoryBuffer>> +EmitDebugSections(llvm::DWARFYAML::Data &DI, bool ApplyFixups); } // end namespace DWARFYAML - } // end namespace llvm #endif // LLVM_OBJECTYAML_DWARFEMITTER_H diff --git a/contrib/llvm/include/llvm/ObjectYAML/DWARFYAML.h b/contrib/llvm/include/llvm/ObjectYAML/DWARFYAML.h index 2162f0fef852..705c88778945 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/DWARFYAML.h +++ b/contrib/llvm/include/llvm/ObjectYAML/DWARFYAML.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file declares classes for handling the YAML representation +/// This file declares classes for handling the YAML representation /// of DWARF Debug Info. /// //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/ObjectYAML/ELFYAML.h b/contrib/llvm/include/llvm/ObjectYAML/ELFYAML.h index 7ba83967330e..6fc69735f1c7 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/contrib/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file declares classes for handling the YAML representation +/// This file declares classes for handling the YAML representation /// of ELF. /// //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/ObjectYAML/MachOYAML.h b/contrib/llvm/include/llvm/ObjectYAML/MachOYAML.h index 1fa8f92e516a..cec4f86185f0 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/MachOYAML.h +++ b/contrib/llvm/include/llvm/ObjectYAML/MachOYAML.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file declares classes for handling the YAML representation +/// This file declares classes for handling the YAML representation /// of Mach-O. /// //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/ObjectYAML/WasmYAML.h b/contrib/llvm/include/llvm/ObjectYAML/WasmYAML.h index 188ce8e44491..8cd08e520560 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/WasmYAML.h +++ b/contrib/llvm/include/llvm/ObjectYAML/WasmYAML.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file declares classes for handling the YAML representation +/// This file declares classes for handling the YAML representation /// of wasm binaries. /// //===----------------------------------------------------------------------===// @@ -28,15 +28,17 @@ namespace llvm { namespace WasmYAML { LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionType) -LLVM_YAML_STRONG_TYPEDEF(int32_t, ValueType) -LLVM_YAML_STRONG_TYPEDEF(int32_t, TableType) -LLVM_YAML_STRONG_TYPEDEF(int32_t, SignatureForm) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ValueType) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, TableType) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, SignatureForm) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportKind) LLVM_YAML_STRONG_TYPEDEF(uint32_t, Opcode) LLVM_YAML_STRONG_TYPEDEF(uint32_t, RelocType) LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolFlags) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolKind) LLVM_YAML_STRONG_TYPEDEF(uint32_t, SegmentFlags) LLVM_YAML_STRONG_TYPEDEF(uint32_t, LimitFlags) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ComdatKind) struct FileHeader { yaml::Hex32 Version; @@ -66,6 +68,7 @@ struct ElemSegment { }; struct Global { + uint32_t Index; ValueType Type; bool Mutable; wasm::WasmInitExpr InitExpr; @@ -89,6 +92,7 @@ struct LocalDecl { }; struct Function { + uint32_t Index; std::vector<LocalDecl> Locals; yaml::BinaryRef Body; }; @@ -127,13 +131,29 @@ struct Signature { }; struct SymbolInfo { + uint32_t Index; StringRef Name; + SymbolKind Kind; SymbolFlags Flags; + union { + uint32_t ElementIndex; + wasm::WasmDataReference DataRef; + }; }; struct InitFunction { uint32_t Priority; - uint32_t FunctionIndex; + uint32_t Symbol; +}; + +struct ComdatEntry { + ComdatKind Kind; + uint32_t Index; +}; + +struct Comdat { + StringRef Name; + std::vector<ComdatEntry> Entries; }; struct Section { @@ -175,10 +195,11 @@ struct LinkingSection : CustomSection { return C && C->Name == "linking"; } - uint32_t DataSize; - std::vector<SymbolInfo> SymbolInfos; + uint32_t Version; + std::vector<SymbolInfo> SymbolTable; std::vector<SegmentInfo> SegmentInfos; std::vector<InitFunction> InitFunctions; + std::vector<Comdat> Comdats; }; struct TypeSection : Section { @@ -316,6 +337,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SegmentInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ComdatEntry) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Comdat) namespace llvm { namespace yaml { @@ -352,6 +375,10 @@ template <> struct ScalarBitSetTraits<WasmYAML::SymbolFlags> { static void bitset(IO &IO, WasmYAML::SymbolFlags &Value); }; +template <> struct ScalarEnumerationTraits<WasmYAML::SymbolKind> { + static void enumeration(IO &IO, WasmYAML::SymbolKind &Kind); +}; + template <> struct ScalarBitSetTraits<WasmYAML::SegmentFlags> { static void bitset(IO &IO, WasmYAML::SegmentFlags &Value); }; @@ -412,6 +439,18 @@ template <> struct MappingTraits<WasmYAML::InitFunction> { static void mapping(IO &IO, WasmYAML::InitFunction &Init); }; +template <> struct ScalarEnumerationTraits<WasmYAML::ComdatKind> { + static void enumeration(IO &IO, WasmYAML::ComdatKind &Kind); +}; + +template <> struct MappingTraits<WasmYAML::ComdatEntry> { + static void mapping(IO &IO, WasmYAML::ComdatEntry &ComdatEntry); +}; + +template <> struct MappingTraits<WasmYAML::Comdat> { + static void mapping(IO &IO, WasmYAML::Comdat &Comdat); +}; + template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> { static void enumeration(IO &IO, WasmYAML::ValueType &Type); }; diff --git a/contrib/llvm/include/llvm/ObjectYAML/YAML.h b/contrib/llvm/include/llvm/ObjectYAML/YAML.h index 93266dd67f1a..163cd8dfcf08 100644 --- a/contrib/llvm/include/llvm/ObjectYAML/YAML.h +++ b/contrib/llvm/include/llvm/ObjectYAML/YAML.h @@ -21,7 +21,7 @@ class raw_ostream; namespace yaml { -/// \brief Specialized YAMLIO scalar type for representing a binary blob. +/// Specialized YAMLIO scalar type for representing a binary blob. /// /// A typical use case would be to represent the content of a section in a /// binary file. @@ -64,11 +64,11 @@ namespace yaml { class BinaryRef { friend bool operator==(const BinaryRef &LHS, const BinaryRef &RHS); - /// \brief Either raw binary data, or a string of hex bytes (must always + /// Either raw binary data, or a string of hex bytes (must always /// be an even number of characters). ArrayRef<uint8_t> Data; - /// \brief Discriminator between the two states of the `Data` member. + /// Discriminator between the two states of the `Data` member. bool DataIsHexString = true; public: @@ -77,7 +77,7 @@ public: BinaryRef(StringRef Data) : Data(reinterpret_cast<const uint8_t *>(Data.data()), Data.size()) {} - /// \brief The number of bytes that are represented by this BinaryRef. + /// The number of bytes that are represented by this BinaryRef. /// This is the number of bytes that writeAsBinary() will write. ArrayRef<uint8_t>::size_type binary_size() const { if (DataIsHexString) @@ -85,11 +85,11 @@ public: return Data.size(); } - /// \brief Write the contents (regardless of whether it is binary or a + /// Write the contents (regardless of whether it is binary or a /// hex string) as binary to the given raw_ostream. void writeAsBinary(raw_ostream &OS) const; - /// \brief Write the contents (regardless of whether it is binary or a + /// Write the contents (regardless of whether it is binary or a /// hex string) as hex to the given raw_ostream. /// /// For example, a possible output could be `DEADBEEFCAFEBABE`. diff --git a/contrib/llvm/include/llvm/Option/Arg.h b/contrib/llvm/include/llvm/Option/Arg.h index c519a4a824c5..d0086bb6d611 100644 --- a/contrib/llvm/include/llvm/Option/Arg.h +++ b/contrib/llvm/include/llvm/Option/Arg.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the llvm::Arg class for parsed arguments. +/// Defines the llvm::Arg class for parsed arguments. /// //===----------------------------------------------------------------------===// @@ -28,35 +28,35 @@ namespace opt { class ArgList; -/// \brief A concrete instance of a particular driver option. +/// A concrete instance of a particular driver option. /// /// The Arg class encodes just enough information to be able to /// derive the argument values efficiently. class Arg { private: - /// \brief The option this argument is an instance of. + /// The option this argument is an instance of. const Option Opt; - /// \brief The argument this argument was derived from (during tool chain + /// The argument this argument was derived from (during tool chain /// argument translation), if any. const Arg *BaseArg; - /// \brief How this instance of the option was spelled. + /// How this instance of the option was spelled. StringRef Spelling; - /// \brief The index at which this argument appears in the containing + /// The index at which this argument appears in the containing /// ArgList. unsigned Index; - /// \brief Was this argument used to effect compilation? + /// Was this argument used to effect compilation? /// /// This is used for generating "argument unused" diagnostics. mutable unsigned Claimed : 1; - /// \brief Does this argument own its values? + /// Does this argument own its values? mutable unsigned OwnsValues : 1; - /// \brief The argument values, as C strings. + /// The argument values, as C strings. SmallVector<const char *, 2> Values; public: @@ -74,7 +74,7 @@ public: StringRef getSpelling() const { return Spelling; } unsigned getIndex() const { return Index; } - /// \brief Return the base argument which generated this arg. + /// Return the base argument which generated this arg. /// /// This is either the argument itself or the argument it was /// derived from during tool chain specific argument translation. @@ -88,7 +88,7 @@ public: bool isClaimed() const { return getBaseArg().Claimed; } - /// \brief Set the Arg claimed bit. + /// Set the Arg claimed bit. void claim() const { getBaseArg().Claimed = true; } unsigned getNumValues() const { return Values.size(); } @@ -107,10 +107,10 @@ public: return false; } - /// \brief Append the argument onto the given array as strings. + /// Append the argument onto the given array as strings. void render(const ArgList &Args, ArgStringList &Output) const; - /// \brief Append the argument, render as an input, onto the given + /// Append the argument, render as an input, onto the given /// array as strings. /// /// The distinction is that some options only render their values @@ -120,7 +120,7 @@ public: void print(raw_ostream &O) const; void dump() const; - /// \brief Return a formatted version of the argument and + /// Return a formatted version of the argument and /// its values, for debugging and diagnostics. std::string getAsString(const ArgList &Args) const; }; diff --git a/contrib/llvm/include/llvm/Option/ArgList.h b/contrib/llvm/include/llvm/Option/ArgList.h index aaea68bf8e27..687c8cbb02f9 100644 --- a/contrib/llvm/include/llvm/Option/ArgList.h +++ b/contrib/llvm/include/llvm/Option/ArgList.h @@ -85,9 +85,6 @@ public: SkipToNextArg(); } - // FIXME: This conversion function makes no sense. - operator const Arg*() { return *Current; } - reference operator*() const { return *Current; } pointer operator->() const { return Current; } @@ -356,7 +353,7 @@ public: return MakeArgStringRef(Str.toStringRef(Buf)); } - /// \brief Create an arg string for (\p LHS + \p RHS), reusing the + /// Create an arg string for (\p LHS + \p RHS), reusing the /// string at \p Index if possible. const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS, StringRef RHS) const; @@ -390,6 +387,8 @@ private: void releaseMemory(); public: + InputArgList() : NumInputArgStrings(0) {} + InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); InputArgList(InputArgList &&RHS) diff --git a/contrib/llvm/include/llvm/Option/OptTable.h b/contrib/llvm/include/llvm/Option/OptTable.h index 57a6954f4878..743c4772c98c 100644 --- a/contrib/llvm/include/llvm/Option/OptTable.h +++ b/contrib/llvm/include/llvm/Option/OptTable.h @@ -29,7 +29,7 @@ class ArgList; class InputArgList; class Option; -/// \brief Provide access to the Option info table. +/// Provide access to the Option info table. /// /// The OptTable class provides a layer of indirection which allows Option /// instance to be created lazily. In the common case, only a few options will @@ -38,7 +38,7 @@ class Option; /// parts of the driver still use Option instances where convenient. class OptTable { public: - /// \brief Entry for a single option instance in the option data table. + /// Entry for a single option instance in the option data table. struct Info { /// A null terminated array of prefix strings to apply to name while /// matching. @@ -57,7 +57,7 @@ public: }; private: - /// \brief The option information table. + /// The option information table. std::vector<Info> OptionInfos; bool IgnoreCase; @@ -86,36 +86,36 @@ protected: public: ~OptTable(); - /// \brief Return the total number of option classes. + /// Return the total number of option classes. unsigned getNumOptions() const { return OptionInfos.size(); } - /// \brief Get the given Opt's Option instance, lazily creating it + /// Get the given Opt's Option instance, lazily creating it /// if necessary. /// /// \return The option, or null for the INVALID option id. const Option getOption(OptSpecifier Opt) const; - /// \brief Lookup the name of the given option. + /// Lookup the name of the given option. const char *getOptionName(OptSpecifier id) const { return getInfo(id).Name; } - /// \brief Get the kind of the given option. + /// Get the kind of the given option. unsigned getOptionKind(OptSpecifier id) const { return getInfo(id).Kind; } - /// \brief Get the group id for the given option. + /// Get the group id for the given option. unsigned getOptionGroupID(OptSpecifier id) const { return getInfo(id).GroupID; } - /// \brief Get the help text to use to describe this option. + /// Get the help text to use to describe this option. const char *getOptionHelpText(OptSpecifier id) const { return getInfo(id).HelpText; } - /// \brief Get the meta-variable name to use when describing + /// Get the meta-variable name to use when describing /// this options values in the help text. const char *getOptionMetaVar(OptSpecifier id) const { return getInfo(id).MetaVar; @@ -143,6 +143,26 @@ public: std::vector<std::string> findByPrefix(StringRef Cur, unsigned short DisableFlags) const; + /// Find the OptTable option that most closely matches the given string. + /// + /// \param [in] Option - A string, such as "-stdlibs=l", that represents user + /// input of an option that may not exist in the OptTable. Note that the + /// string includes prefix dashes "-" as well as values "=l". + /// \param [out] NearestString - The nearest option string found in the + /// OptTable. + /// \param [in] FlagsToInclude - Only find options with any of these flags. + /// Zero is the default, which includes all flags. + /// \param [in] FlagsToExclude - Don't find options with this flag. Zero + /// is the default, and means exclude nothing. + /// \param [in] MinimumLength - Don't find options shorter than this length. + /// For example, a minimum length of 3 prevents "-x" from being considered + /// near to "-S". + /// + /// \return The edit distance of the nearest string found. + unsigned findNearest(StringRef Option, std::string &NearestString, + unsigned FlagsToInclude = 0, unsigned FlagsToExclude = 0, + unsigned MinimumLength = 4) const; + /// Add Values to Option's Values class /// /// \param [in] Option - Prefix + Name of the flag which Values will be @@ -154,7 +174,7 @@ public: /// \return true in success, and false in fail. bool addValues(const char *Option, const char *Values); - /// \brief Parse a single argument; returning the new argument and + /// Parse a single argument; returning the new argument and /// updating Index. /// /// \param [in,out] Index - The current parsing position in the argument @@ -172,7 +192,7 @@ public: unsigned FlagsToInclude = 0, unsigned FlagsToExclude = 0) const; - /// \brief Parse an list of arguments into an InputArgList. + /// Parse an list of arguments into an InputArgList. /// /// The resulting InputArgList will reference the strings in [\p ArgBegin, /// \p ArgEnd), and their lifetime should extend past that of the returned @@ -194,7 +214,7 @@ public: unsigned &MissingArgCount, unsigned FlagsToInclude = 0, unsigned FlagsToExclude = 0) const; - /// \brief Render the help text for an option table. + /// Render the help text for an option table. /// /// \param OS - The stream to write the help text to. /// \param Name - The name to use in the usage line. diff --git a/contrib/llvm/include/llvm/Option/Option.h b/contrib/llvm/include/llvm/Option/Option.h index d9aebd5b0757..b09f6043b7a9 100644 --- a/contrib/llvm/include/llvm/Option/Option.h +++ b/contrib/llvm/include/llvm/Option/Option.h @@ -95,7 +95,7 @@ public: return OptionClass(Info->Kind); } - /// \brief Get the name of this option without any prefix. + /// Get the name of this option without any prefix. StringRef getName() const { assert(Info && "Must have a valid info!"); return Info->Name; @@ -113,7 +113,7 @@ public: return Owner->getOption(Info->AliasID); } - /// \brief Get the alias arguments as a \0 separated list. + /// Get the alias arguments as a \0 separated list. /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0". const char *getAliasArgs() const { assert(Info && "Must have a valid info!"); @@ -123,13 +123,13 @@ public: return Info->AliasArgs; } - /// \brief Get the default prefix for this option. + /// Get the default prefix for this option. StringRef getPrefix() const { const char *Prefix = *Info->Prefixes; return Prefix ? Prefix : StringRef(); } - /// \brief Get the name of this option with the default prefix. + /// Get the name of this option with the default prefix. std::string getPrefixedName() const { std::string Ret = getPrefix(); Ret += getName(); diff --git a/contrib/llvm/include/llvm/Pass.h b/contrib/llvm/include/llvm/Pass.h index a29b3771abb4..d65347d611ea 100644 --- a/contrib/llvm/include/llvm/Pass.h +++ b/contrib/llvm/include/llvm/Pass.h @@ -353,18 +353,18 @@ protected: /// If the user specifies the -time-passes argument on an LLVM tool command line /// then the value of this boolean will be true, otherwise false. -/// @brief This is the storage for the -time-passes option. +/// This is the storage for the -time-passes option. extern bool TimePassesIsEnabled; /// isFunctionInPrintList - returns true if a function should be printed via // debugging options like -print-after-all/-print-before-all. -// @brief Tells if the function IR should be printed by PrinterPass. +// Tells if the function IR should be printed by PrinterPass. extern bool isFunctionInPrintList(StringRef FunctionName); /// forcePrintModuleIR - returns true if IR printing passes should // be printing module IR (even for local-pass printers e.g. function-pass) // to provide more context, as enabled by debugging option -print-module-scope -// @brief Tells if IR printer should be printing module IR +// Tells if IR printer should be printing module IR extern bool forcePrintModuleIR(); } // end namespace llvm diff --git a/contrib/llvm/include/llvm/PassAnalysisSupport.h b/contrib/llvm/include/llvm/PassAnalysisSupport.h index b109605355bf..118718747659 100644 --- a/contrib/llvm/include/llvm/PassAnalysisSupport.h +++ b/contrib/llvm/include/llvm/PassAnalysisSupport.h @@ -174,7 +174,7 @@ public: AnalysisImpls.push_back(pir); } - /// Clear cache that is used to connect a pass to the the analysis (PassInfo). + /// Clear cache that is used to connect a pass to the analysis (PassInfo). void clearAnalysisImpls() { AnalysisImpls.clear(); } diff --git a/contrib/llvm/include/llvm/Passes/PassBuilder.h b/contrib/llvm/include/llvm/Passes/PassBuilder.h index b69988826253..24a93bc76af5 100644 --- a/contrib/llvm/include/llvm/Passes/PassBuilder.h +++ b/contrib/llvm/include/llvm/Passes/PassBuilder.h @@ -19,6 +19,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Scalar/LoopPassManager.h" #include <vector> @@ -26,6 +27,7 @@ namespace llvm { class StringRef; class AAManager; class TargetMachine; +class ModuleSummaryIndex; /// A struct capturing PGO tunables. struct PGOOptions { @@ -47,7 +49,7 @@ struct PGOOptions { bool SamplePGOSupport; }; -/// \brief This class provides access to building LLVM's passes. +/// This class provides access to building LLVM's passes. /// /// It's members provide the baseline state available to passes during their /// construction. The \c PassRegistry.def file specifies how to construct all @@ -58,7 +60,7 @@ class PassBuilder { Optional<PGOOptions> PGOOpt; public: - /// \brief A struct to capture parsed pass pipeline names. + /// A struct to capture parsed pass pipeline names. /// /// A pipeline is defined as a series of names, each of which may in itself /// recursively contain a nested pipeline. A name is either the name of a pass @@ -71,7 +73,7 @@ public: std::vector<PipelineElement> InnerPipeline; }; - /// \brief ThinLTO phase. + /// ThinLTO phase. /// /// This enumerates the LLVM ThinLTO optimization phases. enum class ThinLTOPhase { @@ -83,7 +85,7 @@ public: PostLink }; - /// \brief LLVM-provided high-level optimization levels. + /// LLVM-provided high-level optimization levels. /// /// This enumerates the LLVM-provided high-level optimization levels. Each /// level has a specific goal and rationale. @@ -173,7 +175,7 @@ public: Optional<PGOOptions> PGOOpt = None) : TM(TM), PGOOpt(PGOOpt) {} - /// \brief Cross register the analysis managers through their proxies. + /// Cross register the analysis managers through their proxies. /// /// This is an interface that can be used to cross register each // AnalysisManager with all the others analysis managers. @@ -182,7 +184,7 @@ public: CGSCCAnalysisManager &CGAM, ModuleAnalysisManager &MAM); - /// \brief Registers all available module analysis passes. + /// Registers all available module analysis passes. /// /// This is an interface that can be used to populate a \c /// ModuleAnalysisManager with all registered module analyses. Callers can @@ -190,7 +192,7 @@ public: /// pre-register analyses and this will not override those. void registerModuleAnalyses(ModuleAnalysisManager &MAM); - /// \brief Registers all available CGSCC analysis passes. + /// Registers all available CGSCC analysis passes. /// /// This is an interface that can be used to populate a \c CGSCCAnalysisManager /// with all registered CGSCC analyses. Callers can still manually register any @@ -198,7 +200,7 @@ public: /// not override those. void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM); - /// \brief Registers all available function analysis passes. + /// Registers all available function analysis passes. /// /// This is an interface that can be used to populate a \c /// FunctionAnalysisManager with all registered function analyses. Callers can @@ -206,7 +208,7 @@ public: /// pre-register analyses and this will not override those. void registerFunctionAnalyses(FunctionAnalysisManager &FAM); - /// \brief Registers all available loop analysis passes. + /// Registers all available loop analysis passes. /// /// This is an interface that can be used to populate a \c LoopAnalysisManager /// with all registered loop analyses. Callers can still manually register any @@ -309,8 +311,9 @@ public: /// only intended for use when attempting to optimize code. If frontends /// require some transformations for semantic reasons, they should explicitly /// build them. - ModulePassManager buildThinLTODefaultPipeline(OptimizationLevel Level, - bool DebugLogging = false); + ModulePassManager + buildThinLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, + const ModuleSummaryIndex *ImportSummary); /// Build a pre-link, LTO-targeting default optimization pipeline to a pass /// manager. @@ -339,13 +342,14 @@ public: /// require some transformations for semantic reasons, they should explicitly /// build them. ModulePassManager buildLTODefaultPipeline(OptimizationLevel Level, - bool DebugLogging = false); + bool DebugLogging, + ModuleSummaryIndex *ExportSummary); /// Build the default `AAManager` with the default alias analysis pipeline /// registered. AAManager buildDefaultAAPipeline(); - /// \brief Parse a textual pass pipeline description into a \c + /// Parse a textual pass pipeline description into a \c /// ModulePassManager. /// /// The format of the textual pass pipeline description looks something like: @@ -409,7 +413,7 @@ public: /// returns false. bool parseAAPipeline(AAManager &AA, StringRef PipelineText); - /// \brief Register a callback for a default optimizer pipeline extension + /// Register a callback for a default optimizer pipeline extension /// point /// /// This extension point allows adding passes that perform peephole @@ -420,7 +424,7 @@ public: PeepholeEPCallbacks.push_back(C); } - /// \brief Register a callback for a default optimizer pipeline extension + /// Register a callback for a default optimizer pipeline extension /// point /// /// This extension point allows adding late loop canonicalization and @@ -434,7 +438,7 @@ public: LateLoopOptimizationsEPCallbacks.push_back(C); } - /// \brief Register a callback for a default optimizer pipeline extension + /// Register a callback for a default optimizer pipeline extension /// point /// /// This extension point allows adding loop passes to the end of the loop @@ -444,7 +448,7 @@ public: LoopOptimizerEndEPCallbacks.push_back(C); } - /// \brief Register a callback for a default optimizer pipeline extension + /// Register a callback for a default optimizer pipeline extension /// point /// /// This extension point allows adding optimization passes after most of the @@ -454,7 +458,7 @@ public: ScalarOptimizerLateEPCallbacks.push_back(C); } - /// \brief Register a callback for a default optimizer pipeline extension + /// Register a callback for a default optimizer pipeline extension /// point /// /// This extension point allows adding CallGraphSCC passes at the end of the @@ -465,7 +469,7 @@ public: CGSCCOptimizerLateEPCallbacks.push_back(C); } - /// \brief Register a callback for a default optimizer pipeline extension + /// Register a callback for a default optimizer pipeline extension /// point /// /// This extension point allows adding optimization passes before the @@ -476,7 +480,17 @@ public: VectorizerStartEPCallbacks.push_back(C); } - /// \brief Register a callback for parsing an AliasAnalysis Name to populate + /// Register a callback for a default optimizer pipeline extension point. + /// + /// This extension point allows adding optimization once at the start of the + /// pipeline. This does not apply to 'backend' compiles (LTO and ThinLTO + /// link-time pipelines). + void registerPipelineStartEPCallback( + const std::function<void(ModulePassManager &)> &C) { + PipelineStartEPCallbacks.push_back(C); + } + + /// Register a callback for parsing an AliasAnalysis Name to populate /// the given AAManager \p AA void registerParseAACallback( const std::function<bool(StringRef Name, AAManager &AA)> &C) { @@ -530,7 +544,7 @@ public: } /// @}} - /// \brief Register a callback for a top-level pipeline entry. + /// Register a callback for a top-level pipeline entry. /// /// If the PassManager type is not given at the top level of the pipeline /// text, this Callback should be used to determine the appropriate stack of @@ -589,6 +603,8 @@ private: SmallVector<std::function<void(FunctionPassManager &, OptimizationLevel)>, 2> VectorizerStartEPCallbacks; // Module callbacks + SmallVector<std::function<void(ModulePassManager &)>, 2> + PipelineStartEPCallbacks; SmallVector<std::function<void(ModuleAnalysisManager &)>, 2> ModuleAnalysisRegistrationCallbacks; SmallVector<std::function<bool(StringRef, ModulePassManager &, diff --git a/contrib/llvm/include/llvm/Passes/PassPlugin.h b/contrib/llvm/include/llvm/Passes/PassPlugin.h new file mode 100644 index 000000000000..af8f11a7a352 --- /dev/null +++ b/contrib/llvm/include/llvm/Passes/PassPlugin.h @@ -0,0 +1,114 @@ +//===- llvm/Passes/PassPlugin.h - Public Plugin API -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines the public entry point for new-PM pass plugins. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSES_PASSPLUGIN_H +#define LLVM_PASSES_PASSPLUGIN_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <string> + +namespace llvm { +class PassBuilder; + +/// \macro LLVM_PLUGIN_API_VERSION +/// Identifies the API version understood by this plugin. +/// +/// When a plugin is loaded, the driver will check it's supported plugin version +/// against that of the plugin. A mismatch is an error. The supported version +/// will be incremented for ABI-breaking changes to the \c PassPluginLibraryInfo +/// struct, i.e. when callbacks are added, removed, or reordered. +#define LLVM_PLUGIN_API_VERSION 1 + +extern "C" { +/// Information about the plugin required to load its passes +/// +/// This struct defines the core interface for pass plugins and is supposed to +/// be filled out by plugin implementors. LLVM-side users of a plugin are +/// expected to use the \c PassPlugin class below to interface with it. +struct PassPluginLibraryInfo { + /// The API version understood by this plugin, usually \c + /// LLVM_PLUGIN_API_VERSION + uint32_t APIVersion; + /// A meaningful name of the plugin. + const char *PluginName; + /// The version of the plugin. + const char *PluginVersion; + + /// The callback for registering plugin passes with a \c PassBuilder + /// instance + void (*RegisterPassBuilderCallbacks)(PassBuilder &); +}; +} + +/// A loaded pass plugin. +/// +/// An instance of this class wraps a loaded pass plugin and gives access to +/// its interface defined by the \c PassPluginLibraryInfo it exposes. +class PassPlugin { +public: + /// Attempts to load a pass plugin from a given file. + /// + /// \returns Returns an error if either the library cannot be found or loaded, + /// there is no public entry point, or the plugin implements the wrong API + /// version. + static Expected<PassPlugin> Load(const std::string &Filename); + + /// Get the filename of the loaded plugin. + StringRef getFilename() const { return Filename; } + + /// Get the plugin name + StringRef getPluginName() const { return Info.PluginName; } + + /// Get the plugin version + StringRef getPluginVersion() const { return Info.PluginVersion; } + + /// Get the plugin API version + uint32_t getAPIVersion() const { return Info.APIVersion; } + + /// Invoke the PassBuilder callback registration + void registerPassBuilderCallbacks(PassBuilder &PB) const { + Info.RegisterPassBuilderCallbacks(PB); + } + +private: + PassPlugin(const std::string &Filename, const sys::DynamicLibrary &Library) + : Filename(Filename), Library(Library), Info() {} + + std::string Filename; + sys::DynamicLibrary Library; + PassPluginLibraryInfo Info; +}; +} + +/// The public entry point for a pass plugin. +/// +/// When a plugin is loaded by the driver, it will call this entry point to +/// obtain information about this plugin and about how to register its passes. +/// This function needs to be implemented by the plugin, see the example below: +/// +/// ``` +/// extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +/// llvmGetPassPluginInfo() { +/// return { +/// LLVM_PLUGIN_API_VERSION, "MyPlugin", "v0.1", [](PassBuilder &PB) { ... } +/// }; +/// } +/// ``` +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo(); + +#endif /* LLVM_PASSES_PASSPLUGIN_H */ diff --git a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h index 5a4098cf666c..1ca56dcaf9c5 100644 --- a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/None.h" #include "llvm/ADT/StringRef.h" @@ -506,7 +507,7 @@ public: /// This is the main interface to get coverage information, using a profile to /// fill out execution counts. class CoverageMapping { - StringSet<> FunctionNames; + DenseMap<size_t, DenseSet<size_t>> RecordProvenance; std::vector<FunctionRecord> Functions; std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches; std::vector<std::pair<std::string, uint64_t>> FuncCounterMismatches; diff --git a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h index 633e51565cd2..c88c71a6d6f4 100644 --- a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h +++ b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h @@ -32,7 +32,7 @@ namespace coverage { class CoverageMappingReader; -/// \brief Coverage mapping information for a single function. +/// Coverage mapping information for a single function. struct CoverageMappingRecord { StringRef FunctionName; uint64_t FunctionHash; @@ -41,7 +41,7 @@ struct CoverageMappingRecord { ArrayRef<CounterMappingRegion> MappingRegions; }; -/// \brief A file format agnostic iterator over coverage mapping data. +/// A file format agnostic iterator over coverage mapping data. class CoverageMappingIterator : public std::iterator<std::input_iterator_tag, CoverageMappingRecord> { CoverageMappingReader *Reader; @@ -101,7 +101,7 @@ public: CoverageMappingIterator end() { return CoverageMappingIterator(); } }; -/// \brief Base class for the raw coverage mapping and filenames data readers. +/// Base class for the raw coverage mapping and filenames data readers. class RawCoverageReader { protected: StringRef Data; @@ -114,7 +114,7 @@ protected: Error readString(StringRef &Result); }; -/// \brief Reader for the raw coverage filenames. +/// Reader for the raw coverage filenames. class RawCoverageFilenamesReader : public RawCoverageReader { std::vector<StringRef> &Filenames; @@ -128,7 +128,7 @@ public: Error read(); }; -/// \brief Checks if the given coverage mapping data is exported for +/// Checks if the given coverage mapping data is exported for /// an unused function. class RawCoverageMappingDummyChecker : public RawCoverageReader { public: @@ -138,7 +138,7 @@ public: Expected<bool> isDummy(); }; -/// \brief Reader for the raw coverage mapping data. +/// Reader for the raw coverage mapping data. class RawCoverageMappingReader : public RawCoverageReader { ArrayRef<StringRef> TranslationUnitFilenames; std::vector<StringRef> &Filenames; @@ -169,7 +169,7 @@ private: unsigned InferredFileID, size_t NumFileIDs); }; -/// \brief Reader for the coverage mapping data that is emitted by the +/// Reader for the coverage mapping data that is emitted by the /// frontend and stored in an object file. class BinaryCoverageReader : public CoverageMappingReader { public: diff --git a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h index b6f864ab3de3..86fb1bdf1773 100644 --- a/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h +++ b/contrib/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h @@ -25,7 +25,7 @@ class raw_ostream; namespace coverage { -/// \brief Writer of the filenames section for the instrumentation +/// Writer of the filenames section for the instrumentation /// based code coverage. class CoverageFilenamesSectionWriter { ArrayRef<StringRef> Filenames; @@ -34,11 +34,11 @@ public: CoverageFilenamesSectionWriter(ArrayRef<StringRef> Filenames) : Filenames(Filenames) {} - /// \brief Write encoded filenames to the given output stream. + /// Write encoded filenames to the given output stream. void write(raw_ostream &OS); }; -/// \brief Writer for instrumentation based coverage mapping data. +/// Writer for instrumentation based coverage mapping data. class CoverageMappingWriter { ArrayRef<unsigned> VirtualFileMapping; ArrayRef<CounterExpression> Expressions; @@ -51,7 +51,7 @@ public: : VirtualFileMapping(VirtualFileMapping), Expressions(Expressions), MappingRegions(MappingRegions) {} - /// \brief Write encoded coverage mapping data to the given output stream. + /// Write encoded coverage mapping data to the given output stream. void write(raw_ostream &OS); }; diff --git a/contrib/llvm/include/llvm/ProfileData/GCOV.h b/contrib/llvm/include/llvm/ProfileData/GCOV.h index 497f80b87b26..8500401e44ad 100644 --- a/contrib/llvm/include/llvm/ProfileData/GCOV.h +++ b/contrib/llvm/include/llvm/ProfileData/GCOV.h @@ -41,7 +41,7 @@ namespace GCOV { enum GCOVVersion { V402, V404, V704 }; -/// \brief A struct for passing gcov options between functions. +/// A struct for passing gcov options between functions. struct Options { Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N) : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), @@ -376,6 +376,7 @@ private: }; class FileInfo { +protected: // It is unlikely--but possible--for multiple functions to be on the same // line. // Therefore this typedef allows LineData.Functions to store multiple @@ -428,7 +429,7 @@ public: void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile); -private: +protected: std::string getCoveragePath(StringRef Filename, StringRef MainFilename); std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath); void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const; diff --git a/contrib/llvm/include/llvm/ProfileData/InstrProf.h b/contrib/llvm/include/llvm/ProfileData/InstrProf.h index b08b78cd593c..206142b3565a 100644 --- a/contrib/llvm/include/llvm/ProfileData/InstrProf.h +++ b/contrib/llvm/include/llvm/ProfileData/InstrProf.h @@ -425,9 +425,20 @@ private: // A map from function runtime address to function name MD5 hash. // This map is only populated and used by raw instr profile reader. AddrHashMap AddrToMD5Map; + bool Sorted = false; + + static StringRef getExternalSymbol() { + return "** External Symbol **"; + } + + // If the symtab is created by a series of calls to \c addFuncName, \c + // finalizeSymtab needs to be called before looking up function names. + // This is required because the underlying map is a vector (for space + // efficiency) which needs to be sorted. + inline void finalizeSymtab(); public: - InstrProfSymtab() = default; + InstrProfSymtab() = default; /// Create InstrProfSymtab from an object file section which /// contains function PGO names. When section may contain raw @@ -456,21 +467,17 @@ public: /// \p IterRange. This interface is used by IndexedProfReader. template <typename NameIterRange> Error create(const NameIterRange &IterRange); - // If the symtab is created by a series of calls to \c addFuncName, \c - // finalizeSymtab needs to be called before looking up function names. - // This is required because the underlying map is a vector (for space - // efficiency) which needs to be sorted. - inline void finalizeSymtab(); - /// Update the symtab by adding \p FuncName to the table. This interface /// is used by the raw and text profile readers. Error addFuncName(StringRef FuncName) { if (FuncName.empty()) return make_error<InstrProfError>(instrprof_error::malformed); auto Ins = NameTab.insert(FuncName); - if (Ins.second) + if (Ins.second) { MD5NameMap.push_back(std::make_pair( IndexedInstrProf::ComputeHash(FuncName), Ins.first->getKey())); + Sorted = false; + } return Error::success(); } @@ -480,7 +487,8 @@ public: AddrToMD5Map.push_back(std::make_pair(Addr, MD5Val)); } - AddrHashMap &getAddrHashMap() { return AddrToMD5Map; } + /// Return a function's hash, or 0, if the function isn't in this SymTab. + uint64_t getFunctionHashFromAddress(uint64_t Address); /// Return function's PGO name from the function name's symbol /// address in the object file. If an error occurs, return @@ -491,6 +499,16 @@ public: /// If not found, return an empty string. inline StringRef getFuncName(uint64_t FuncMD5Hash); + /// Just like getFuncName, except that it will return a non-empty StringRef + /// if the function is external to this symbol table. All such cases + /// will be represented using the same StringRef value. + inline StringRef getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash); + + /// True if Symbol is the value used to represent external symbols. + static bool isExternalSymbol(const StringRef &Symbol) { + return Symbol == InstrProfSymtab::getExternalSymbol(); + } + /// Return function from the name's md5 hash. Return nullptr if not found. inline Function *getFunction(uint64_t FuncMD5Hash); @@ -524,14 +542,25 @@ Error InstrProfSymtab::create(const NameIterRange &IterRange) { } void InstrProfSymtab::finalizeSymtab() { - std::sort(MD5NameMap.begin(), MD5NameMap.end(), less_first()); - std::sort(MD5FuncMap.begin(), MD5FuncMap.end(), less_first()); - std::sort(AddrToMD5Map.begin(), AddrToMD5Map.end(), less_first()); + if (Sorted) + return; + llvm::sort(MD5NameMap.begin(), MD5NameMap.end(), less_first()); + llvm::sort(MD5FuncMap.begin(), MD5FuncMap.end(), less_first()); + llvm::sort(AddrToMD5Map.begin(), AddrToMD5Map.end(), less_first()); AddrToMD5Map.erase(std::unique(AddrToMD5Map.begin(), AddrToMD5Map.end()), AddrToMD5Map.end()); + Sorted = true; +} + +StringRef InstrProfSymtab::getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash) { + StringRef ret = getFuncName(FuncMD5Hash); + if (ret.empty()) + return InstrProfSymtab::getExternalSymbol(); + return ret; } StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) { + finalizeSymtab(); auto Result = std::lower_bound(MD5NameMap.begin(), MD5NameMap.end(), FuncMD5Hash, [](const std::pair<uint64_t, std::string> &LHS, @@ -542,6 +571,7 @@ StringRef InstrProfSymtab::getFuncName(uint64_t FuncMD5Hash) { } Function* InstrProfSymtab::getFunction(uint64_t FuncMD5Hash) { + finalizeSymtab(); auto Result = std::lower_bound(MD5FuncMap.begin(), MD5FuncMap.end(), FuncMD5Hash, [](const std::pair<uint64_t, Function*> &LHS, @@ -614,8 +644,6 @@ struct InstrProfRecord { return *this; } - using ValueMapType = std::vector<std::pair<uint64_t, uint64_t>>; - /// Return the number of value profile kinds with non-zero number /// of profile sites. inline uint32_t getNumValueKinds() const; @@ -649,7 +677,7 @@ struct InstrProfRecord { /// Add ValueData for ValueKind at value Site. void addValueData(uint32_t ValueKind, uint32_t Site, InstrProfValueData *VData, uint32_t N, - ValueMapType *ValueMap); + InstrProfSymtab *SymTab); /// Merge the counts in \p Other into this one. /// Optionally scale merged counts by \p Weight. @@ -723,7 +751,7 @@ private: // Map indirect call target name hash to name string. uint64_t remapValue(uint64_t Value, uint32_t ValueKind, - ValueMapType *HashKeys); + InstrProfSymtab *SymTab); // Merge Value Profile data from Src record to this record for ValueKind. // Scale merged value counts by \p Weight. @@ -993,7 +1021,7 @@ template <> inline uint64_t getMagic<uint32_t>() { // compiler-rt/lib/profile/InstrProfiling.h. // It should also match the synthesized type in // Transforms/Instrumentation/InstrProfiling.cpp:getOrCreateRegionCounters. -template <class IntPtrT> struct LLVM_ALIGNAS(8) ProfileData { +template <class IntPtrT> struct alignas(8) ProfileData { #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Type Name; #include "llvm/ProfileData/InstrProfData.inc" }; diff --git a/contrib/llvm/include/llvm/ProfileData/InstrProfData.inc b/contrib/llvm/include/llvm/ProfileData/InstrProfData.inc index 6a98dc7b9b85..454620ed997a 100644 --- a/contrib/llvm/include/llvm/ProfileData/InstrProfData.inc +++ b/contrib/llvm/include/llvm/ProfileData/InstrProfData.inc @@ -178,7 +178,7 @@ VALUE_PROF_FUNC_PARAM(uint64_t, LargeValue, Type::getInt64Ty(Ctx)) * functions are profiled by the instrumented code. The target addresses are * written in the raw profile data and converted to target function name's MD5 * hash by the profile reader during deserialization. Typically, this happens - * when the the raw profile data is read during profile merging. + * when the raw profile data is read during profile merging. * * For this remapping the ProfData is used. ProfData contains both the function * name hash and the function address. @@ -308,14 +308,14 @@ typedef struct ValueProfRecord { #ifdef __cplusplus /*! - * \brief Return the number of value sites. + * Return the number of value sites. */ uint32_t getNumValueSites() const { return NumValueSites; } /*! - * \brief Read data from this record and save it to Record. + * Read data from this record and save it to Record. */ void deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap); + InstrProfSymtab *SymTab); /* * In-place byte swap: * Do byte swap for this instance. \c Old is the original order before @@ -393,7 +393,7 @@ typedef struct ValueProfData { * Read data from this data and save it to \c Record. */ void deserializeTo(InstrProfRecord &Record, - InstrProfRecord::ValueMapType *VMap); + InstrProfSymtab *SymTab); void operator delete(void *ptr) { ::operator delete(ptr); } #endif } ValueProfData; @@ -458,7 +458,7 @@ getValueProfRecordHeaderSize(uint32_t NumValueSites); #endif /*! - * \brief Return the \c ValueProfRecord header size including the + * Return the \c ValueProfRecord header size including the * padding bytes. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE @@ -471,7 +471,7 @@ uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites) { } /*! - * \brief Return the total size of the value profile record including the + * Return the total size of the value profile record including the * header and the value data. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE @@ -482,7 +482,7 @@ uint32_t getValueProfRecordSize(uint32_t NumValueSites, } /*! - * \brief Return the pointer to the start of value data array. + * Return the pointer to the start of value data array. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) { @@ -491,7 +491,7 @@ InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *This) { } /*! - * \brief Return the total number of value data for \c This record. + * Return the total number of value data for \c This record. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) { @@ -503,7 +503,7 @@ uint32_t getValueProfRecordNumValueData(ValueProfRecord *This) { } /*! - * \brief Use this method to advance to the next \c This \c ValueProfRecord. + * Use this method to advance to the next \c This \c ValueProfRecord. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) { @@ -514,7 +514,7 @@ ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) { } /*! - * \brief Return the first \c ValueProfRecord instance. + * Return the first \c ValueProfRecord instance. */ INSTR_PROF_VISIBILITY INSTR_PROF_INLINE ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) { diff --git a/contrib/llvm/include/llvm/ProfileData/InstrProfReader.h b/contrib/llvm/include/llvm/ProfileData/InstrProfReader.h index aa58ead1eda1..efc22dcd0d9a 100644 --- a/contrib/llvm/include/llvm/ProfileData/InstrProfReader.h +++ b/contrib/llvm/include/llvm/ProfileData/InstrProfReader.h @@ -101,7 +101,7 @@ protected: return make_error<InstrProfError>(Err); } - Error error(Error E) { return error(InstrProfError::take(std::move(E))); } + Error error(Error &&E) { return error(InstrProfError::take(std::move(E))); } /// Clear the current error and return a successful one. Error success() { return error(instrprof_error::success); } @@ -199,8 +199,6 @@ private: uint32_t ValueKindLast; uint32_t CurValueDataSize; - InstrProfRecord::ValueMapType FunctionPtrToNameMap; - public: RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer) : DataBuffer(std::move(DataBuffer)) {} diff --git a/contrib/llvm/include/llvm/ProfileData/ProfileCommon.h b/contrib/llvm/include/llvm/ProfileData/ProfileCommon.h index 51b065bcdb70..087588f06340 100644 --- a/contrib/llvm/include/llvm/ProfileData/ProfileCommon.h +++ b/contrib/llvm/include/llvm/ProfileData/ProfileCommon.h @@ -61,7 +61,7 @@ protected: void computeDetailedSummary(); public: - /// \brief A vector of useful cutoff values for detailed summary. + /// A vector of useful cutoff values for detailed summary. static const ArrayRef<uint32_t> DefaultCutoffs; }; diff --git a/contrib/llvm/include/llvm/ProfileData/SampleProf.h b/contrib/llvm/include/llvm/ProfileData/SampleProf.h index 641631cc4ec9..0cd6dd2c2c0e 100644 --- a/contrib/llvm/include/llvm/ProfileData/SampleProf.h +++ b/contrib/llvm/include/llvm/ProfileData/SampleProf.h @@ -78,11 +78,29 @@ struct is_error_code_enum<llvm::sampleprof_error> : std::true_type {}; namespace llvm { namespace sampleprof { -static inline uint64_t SPMagic() { +enum SampleProfileFormat { + SPF_None = 0, + SPF_Text = 0x1, + SPF_Compact_Binary = 0x2, + SPF_GCC = 0x3, + SPF_Binary = 0xff +}; + +static inline uint64_t SPMagic(SampleProfileFormat Format = SPF_Binary) { return uint64_t('S') << (64 - 8) | uint64_t('P') << (64 - 16) | uint64_t('R') << (64 - 24) | uint64_t('O') << (64 - 32) | uint64_t('F') << (64 - 40) | uint64_t('4') << (64 - 48) | - uint64_t('2') << (64 - 56) | uint64_t(0xff); + uint64_t('2') << (64 - 56) | uint64_t(Format); +} + +// Get the proper representation of a string in the input Format. +static inline StringRef getRepInFormat(StringRef Name, + SampleProfileFormat Format, + std::string &GUIDBuf) { + if (Name.empty()) + return Name; + GUIDBuf = std::to_string(Function::getGUID(Name)); + return (Format == SPF_Compact_Binary) ? StringRef(GUIDBuf) : Name; } static inline uint64_t SPVersion() { return 103; } @@ -359,7 +377,7 @@ public: /// GUID to \p S. Also traverse the BodySamples to add hot CallTarget's GUID /// to \p S. void findInlinedFunctions(DenseSet<GlobalValue::GUID> &S, const Module *M, - uint64_t Threshold) const { + uint64_t Threshold, bool isCompact) const { if (TotalSamples <= Threshold) return; S.insert(Function::getGUID(Name)); @@ -370,11 +388,12 @@ public: if (TS.getValue() > Threshold) { Function *Callee = M->getFunction(TS.getKey()); if (!Callee || !Callee->getSubprogram()) - S.insert(Function::getGUID(TS.getKey())); + S.insert(isCompact ? std::stol(TS.getKey().data()) + : Function::getGUID(TS.getKey())); } for (const auto &CS : CallsiteSamples) for (const auto &NameFS : CS.second) - NameFS.second.findInlinedFunctions(S, M, Threshold); + NameFS.second.findInlinedFunctions(S, M, Threshold, isCompact); } /// Set the name of the function. @@ -383,6 +402,21 @@ public: /// Return the function name. const StringRef &getName() const { return Name; } + /// Returns the line offset to the start line of the subprogram. + /// We assume that a single function will not exceed 65535 LOC. + static unsigned getOffset(const DILocation *DIL); + + /// Get the FunctionSamples of the inline instance where DIL originates + /// from. + /// + /// The FunctionSamples of the instruction (Machine or IR) associated to + /// \p DIL is the inlined instance in which that instruction is coming from. + /// We traverse the inline stack of that instruction, and match it with the + /// tree nodes in the profile. + /// + /// \returns the FunctionSamples pointer to the inlined instance. + const FunctionSamples *findFunctionSamples(const DILocation *DIL) const; + private: /// Mangled name of the function. StringRef Name; diff --git a/contrib/llvm/include/llvm/ProfileData/SampleProfReader.h b/contrib/llvm/include/llvm/ProfileData/SampleProfReader.h index 0e9ab2dc60ee..0617b05e8d4f 100644 --- a/contrib/llvm/include/llvm/ProfileData/SampleProfReader.h +++ b/contrib/llvm/include/llvm/ProfileData/SampleProfReader.h @@ -235,7 +235,7 @@ class raw_ostream; namespace sampleprof { -/// \brief Sample-based profile reader. +/// Sample-based profile reader. /// /// Each profile contains sample counts for all the functions /// executed. Inside each function, statements are annotated with the @@ -264,105 +264,113 @@ namespace sampleprof { /// compact and I/O efficient. They can both be used interchangeably. class SampleProfileReader { public: - SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C) - : Profiles(0), Ctx(C), Buffer(std::move(B)) {} + SampleProfileReader(std::unique_ptr<MemoryBuffer> B, LLVMContext &C, + SampleProfileFormat Format = SPF_None) + : Profiles(0), Ctx(C), Buffer(std::move(B)), Format(Format) {} virtual ~SampleProfileReader() = default; - /// \brief Read and validate the file header. + /// Read and validate the file header. virtual std::error_code readHeader() = 0; - /// \brief Read sample profiles from the associated file. + /// Read sample profiles from the associated file. virtual std::error_code read() = 0; - /// \brief Print the profile for \p FName on stream \p OS. + /// Print the profile for \p FName on stream \p OS. void dumpFunctionProfile(StringRef FName, raw_ostream &OS = dbgs()); - /// \brief Print all the profiles on stream \p OS. + /// Print all the profiles on stream \p OS. void dump(raw_ostream &OS = dbgs()); - /// \brief Return the samples collected for function \p F. + /// Return the samples collected for function \p F. FunctionSamples *getSamplesFor(const Function &F) { // The function name may have been updated by adding suffix. In sample // profile, the function names are all stripped, so we need to strip // the function name suffix before matching with profile. - if (Profiles.count(F.getName().split('.').first)) - return &Profiles[(F.getName().split('.').first)]; + StringRef Fname = F.getName().split('.').first; + std::string FGUID; + Fname = getRepInFormat(Fname, getFormat(), FGUID); + if (Profiles.count(Fname)) + return &Profiles[Fname]; return nullptr; } - /// \brief Return all the profiles. + /// Return all the profiles. StringMap<FunctionSamples> &getProfiles() { return Profiles; } - /// \brief Report a parse error message. + /// Report a parse error message. void reportError(int64_t LineNumber, Twine Msg) const { Ctx.diagnose(DiagnosticInfoSampleProfile(Buffer->getBufferIdentifier(), LineNumber, Msg)); } - /// \brief Create a sample profile reader appropriate to the file format. + /// Create a sample profile reader appropriate to the file format. static ErrorOr<std::unique_ptr<SampleProfileReader>> create(const Twine &Filename, LLVMContext &C); - /// \brief Create a sample profile reader from the supplied memory buffer. + /// Create a sample profile reader from the supplied memory buffer. static ErrorOr<std::unique_ptr<SampleProfileReader>> create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C); - /// \brief Return the profile summary. + /// Return the profile summary. ProfileSummary &getSummary() { return *(Summary.get()); } + /// \brief Return the profile format. + SampleProfileFormat getFormat() { return Format; } + protected: - /// \brief Map every function to its associated profile. + /// Map every function to its associated profile. /// /// The profile of every function executed at runtime is collected /// in the structure FunctionSamples. This maps function objects /// to their corresponding profiles. StringMap<FunctionSamples> Profiles; - /// \brief LLVM context used to emit diagnostics. + /// LLVM context used to emit diagnostics. LLVMContext &Ctx; - /// \brief Memory buffer holding the profile file. + /// Memory buffer holding the profile file. std::unique_ptr<MemoryBuffer> Buffer; - /// \brief Profile summary information. + /// Profile summary information. std::unique_ptr<ProfileSummary> Summary; - /// \brief Compute summary for this profile. + /// Compute summary for this profile. void computeSummary(); + + /// \brief The format of sample. + SampleProfileFormat Format = SPF_None; }; class SampleProfileReaderText : public SampleProfileReader { public: SampleProfileReaderText(std::unique_ptr<MemoryBuffer> B, LLVMContext &C) - : SampleProfileReader(std::move(B), C) {} + : SampleProfileReader(std::move(B), C, SPF_Text) {} - /// \brief Read and validate the file header. + /// Read and validate the file header. std::error_code readHeader() override { return sampleprof_error::success; } - /// \brief Read sample profiles from the associated file. + /// Read sample profiles from the associated file. std::error_code read() override; - /// \brief Return true if \p Buffer is in the format supported by this class. + /// Return true if \p Buffer is in the format supported by this class. static bool hasFormat(const MemoryBuffer &Buffer); }; class SampleProfileReaderBinary : public SampleProfileReader { public: - SampleProfileReaderBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C) - : SampleProfileReader(std::move(B), C) {} + SampleProfileReaderBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C, + SampleProfileFormat Format = SPF_None) + : SampleProfileReader(std::move(B), C, Format) {} - /// \brief Read and validate the file header. + /// Read and validate the file header. std::error_code readHeader() override; - /// \brief Read sample profiles from the associated file. + /// Read sample profiles from the associated file. std::error_code read() override; - /// \brief Return true if \p Buffer is in the format supported by this class. - static bool hasFormat(const MemoryBuffer &Buffer); - protected: - /// \brief Read a numeric value of type T from the profile. + /// Read a numeric value of type T from the profile. /// /// If an error occurs during decoding, a diagnostic message is emitted and /// EC is set. @@ -370,7 +378,7 @@ protected: /// \returns the read value. template <typename T> ErrorOr<T> readNumber(); - /// \brief Read a string from the profile. + /// Read a string from the profile. /// /// If an error occurs during decoding, a diagnostic message is emitted and /// EC is set. @@ -378,29 +386,68 @@ protected: /// \returns the read value. ErrorOr<StringRef> readString(); - /// Read a string indirectly via the name table. - ErrorOr<StringRef> readStringFromTable(); + /// Read the string index and check whether it overflows the table. + template <typename T> inline ErrorOr<uint32_t> readStringIndex(T &Table); - /// \brief Return true if we've reached the end of file. + /// Return true if we've reached the end of file. bool at_eof() const { return Data >= End; } /// Read the contents of the given profile instance. std::error_code readProfile(FunctionSamples &FProfile); - /// \brief Points to the current location in the buffer. + /// Points to the current location in the buffer. const uint8_t *Data = nullptr; - /// \brief Points to the end of the buffer. + /// Points to the end of the buffer. const uint8_t *End = nullptr; +private: + std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries); + virtual std::error_code verifySPMagic(uint64_t Magic) = 0; + + /// Read profile summary. + std::error_code readSummary(); + + /// Read the whole name table. + virtual std::error_code readNameTable() = 0; + + /// Read a string indirectly via the name table. + virtual ErrorOr<StringRef> readStringFromTable() = 0; +}; + +class SampleProfileReaderRawBinary : public SampleProfileReaderBinary { +private: /// Function name table. std::vector<StringRef> NameTable; + virtual std::error_code verifySPMagic(uint64_t Magic) override; + virtual std::error_code readNameTable() override; + /// Read a string indirectly via the name table. + virtual ErrorOr<StringRef> readStringFromTable() override; + +public: + SampleProfileReaderRawBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C) + : SampleProfileReaderBinary(std::move(B), C, SPF_Binary) {} + + /// \brief Return true if \p Buffer is in the format supported by this class. + static bool hasFormat(const MemoryBuffer &Buffer); +}; +class SampleProfileReaderCompactBinary : public SampleProfileReaderBinary { private: - std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries); + /// Function name table. + std::vector<std::string> NameTable; + virtual std::error_code verifySPMagic(uint64_t Magic) override; + virtual std::error_code readNameTable() override; + /// Read a string indirectly via the name table. + virtual ErrorOr<StringRef> readStringFromTable() override; - /// \brief Read profile summary. - std::error_code readSummary(); +public: + SampleProfileReaderCompactBinary(std::unique_ptr<MemoryBuffer> B, + LLVMContext &C) + : SampleProfileReaderBinary(std::move(B), C, SPF_Compact_Binary) {} + + /// \brief Return true if \p Buffer is in the format supported by this class. + static bool hasFormat(const MemoryBuffer &Buffer); }; using InlineCallStack = SmallVector<FunctionSamples *, 10>; @@ -421,15 +468,16 @@ enum HistType { class SampleProfileReaderGCC : public SampleProfileReader { public: SampleProfileReaderGCC(std::unique_ptr<MemoryBuffer> B, LLVMContext &C) - : SampleProfileReader(std::move(B), C), GcovBuffer(Buffer.get()) {} + : SampleProfileReader(std::move(B), C, SPF_GCC), + GcovBuffer(Buffer.get()) {} - /// \brief Read and validate the file header. + /// Read and validate the file header. std::error_code readHeader() override; - /// \brief Read sample profiles from the associated file. + /// Read sample profiles from the associated file. std::error_code read() override; - /// \brief Return true if \p Buffer is in the format supported by this class. + /// Return true if \p Buffer is in the format supported by this class. static bool hasFormat(const MemoryBuffer &Buffer); protected: @@ -441,7 +489,7 @@ protected: template <typename T> ErrorOr<T> readNumber(); ErrorOr<StringRef> readString(); - /// \brief Read the section tag and check that it's the same as \p Expected. + /// Read the section tag and check that it's the same as \p Expected. std::error_code readSectionTag(uint32_t Expected); /// GCOV buffer containing the profile. diff --git a/contrib/llvm/include/llvm/ProfileData/SampleProfWriter.h b/contrib/llvm/include/llvm/ProfileData/SampleProfWriter.h index 86af1038d74e..74dc839ff049 100644 --- a/contrib/llvm/include/llvm/ProfileData/SampleProfWriter.h +++ b/contrib/llvm/include/llvm/ProfileData/SampleProfWriter.h @@ -23,14 +23,13 @@ #include <algorithm> #include <cstdint> #include <memory> +#include <set> #include <system_error> namespace llvm { namespace sampleprof { -enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC }; - -/// \brief Sample-based profile writer. Base class. +/// Sample-based profile writer. Base class. class SampleProfileWriter { public: virtual ~SampleProfileWriter() = default; @@ -62,21 +61,21 @@ protected: SampleProfileWriter(std::unique_ptr<raw_ostream> &OS) : OutputStream(std::move(OS)) {} - /// \brief Write a file header for the profile file. + /// Write a file header for the profile file. virtual std::error_code writeHeader(const StringMap<FunctionSamples> &ProfileMap) = 0; - /// \brief Output stream where to emit the profile to. + /// Output stream where to emit the profile to. std::unique_ptr<raw_ostream> OutputStream; - /// \brief Profile summary. + /// Profile summary. std::unique_ptr<ProfileSummary> Summary; - /// \brief Compute summary for this profile. + /// Compute summary for this profile. void computeSummary(const StringMap<FunctionSamples> &ProfileMap); }; -/// \brief Sample-based profile writer (text format). +/// Sample-based profile writer (text format). class SampleProfileWriterText : public SampleProfileWriter { public: std::error_code write(const FunctionSamples &S) override; @@ -101,32 +100,49 @@ private: SampleProfileFormat Format); }; -/// \brief Sample-based profile writer (binary format). +/// Sample-based profile writer (binary format). class SampleProfileWriterBinary : public SampleProfileWriter { public: std::error_code write(const FunctionSamples &S) override; - -protected: SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS) : SampleProfileWriter(OS) {} - std::error_code - writeHeader(const StringMap<FunctionSamples> &ProfileMap) override; +protected: + virtual std::error_code writeNameTable() = 0; + virtual std::error_code writeMagicIdent() = 0; + std::error_code writeHeader(const StringMap<FunctionSamples> &ProfileMap) override; std::error_code writeSummary(); std::error_code writeNameIdx(StringRef FName); std::error_code writeBody(const FunctionSamples &S); + inline void stablizeNameTable(std::set<StringRef> &V); + + MapVector<StringRef, uint32_t> NameTable; private: void addName(StringRef FName); void addNames(const FunctionSamples &S); - MapVector<StringRef, uint32_t> NameTable; - friend ErrorOr<std::unique_ptr<SampleProfileWriter>> SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS, SampleProfileFormat Format); }; +class SampleProfileWriterRawBinary : public SampleProfileWriterBinary { + using SampleProfileWriterBinary::SampleProfileWriterBinary; + +protected: + virtual std::error_code writeNameTable() override; + virtual std::error_code writeMagicIdent() override; +}; + +class SampleProfileWriterCompactBinary : public SampleProfileWriterBinary { + using SampleProfileWriterBinary::SampleProfileWriterBinary; + +protected: + virtual std::error_code writeNameTable() override; + virtual std::error_code writeMagicIdent() override; +}; + } // end namespace sampleprof } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Support/AArch64TargetParser.def b/contrib/llvm/include/llvm/Support/AArch64TargetParser.def index 30c7924ea5f1..6772e5f9b734 100644 --- a/contrib/llvm/include/llvm/Support/AArch64TargetParser.def +++ b/contrib/llvm/include/llvm/Support/AArch64TargetParser.def @@ -35,6 +35,11 @@ AARCH64_ARCH("armv8.3-a", ARMV8_3A, "8.3-A", "v8.3a", (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE | AArch64::AEK_RDM | AArch64::AEK_RCPC)) +AARCH64_ARCH("armv8.4-a", ARMV8_4A, "8.4-A", "v8.4a", + ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, + (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | + AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE | + AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD)) #undef AARCH64_ARCH #ifndef AARCH64_ARCH_EXT_NAME @@ -47,6 +52,10 @@ AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc") AARCH64_ARCH_EXT_NAME("lse", AArch64::AEK_LSE, "+lse", "-lse") AARCH64_ARCH_EXT_NAME("rdm", AArch64::AEK_RDM, "+rdm", "-rdm") AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto") +AARCH64_ARCH_EXT_NAME("sm4", AArch64::AEK_SM4, "+sm4", "-sm4") +AARCH64_ARCH_EXT_NAME("sha3", AArch64::AEK_SHA3, "+sha3", "-sha3") +AARCH64_ARCH_EXT_NAME("sha2", AArch64::AEK_SHA2, "+sha2", "-sha2") +AARCH64_ARCH_EXT_NAME("aes", AArch64::AEK_AES, "+aes", "-aes") AARCH64_ARCH_EXT_NAME("dotprod", AArch64::AEK_DOTPROD, "+dotprod","-dotprod") AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8") AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon") @@ -82,6 +91,8 @@ AARCH64_CPU_NAME("exynos-m2", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, (AArch64::AEK_CRC)) AARCH64_CPU_NAME("exynos-m3", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, (AArch64::AEK_CRC)) +AARCH64_CPU_NAME("exynos-m4", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_CRC)) AARCH64_CPU_NAME("falkor", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, (AArch64::AEK_CRC | AArch64::AEK_RDM)) AARCH64_CPU_NAME("saphira", ARMV8_3A, FK_CRYPTO_NEON_FP_ARMV8, false, diff --git a/contrib/llvm/include/llvm/Support/AMDGPUKernelDescriptor.h b/contrib/llvm/include/llvm/Support/AMDGPUKernelDescriptor.h deleted file mode 100644 index ce2c0c1c959e..000000000000 --- a/contrib/llvm/include/llvm/Support/AMDGPUKernelDescriptor.h +++ /dev/null @@ -1,139 +0,0 @@ -//===--- AMDGPUKernelDescriptor.h -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// \file -/// \brief AMDGPU kernel descriptor definitions. For more information, visit -/// https://llvm.org/docs/AMDGPUUsage.html#kernel-descriptor-for-gfx6-gfx9 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_AMDGPUKERNELDESCRIPTOR_H -#define LLVM_SUPPORT_AMDGPUKERNELDESCRIPTOR_H - -#include <cstdint> - -// Creates enumeration entries used for packing bits into integers. Enumeration -// entries include bit shift amount, bit width, and bit mask. -#define AMDGPU_BITS_ENUM_ENTRY(name, shift, width) \ - name ## _SHIFT = (shift), \ - name ## _WIDTH = (width), \ - name = (((1 << (width)) - 1) << (shift)) \ - -// Gets bits for specified bit mask from specified source. -#define AMDGPU_BITS_GET(src, mask) \ - ((src & mask) >> mask ## _SHIFT) \ - -// Sets bits for specified bit mask in specified destination. -#define AMDGPU_BITS_SET(dst, mask, val) \ - dst &= (~(1 << mask ## _SHIFT) & ~mask); \ - dst |= (((val) << mask ## _SHIFT) & mask) \ - -namespace llvm { -namespace AMDGPU { -namespace HSAKD { - -/// \brief Floating point rounding modes. -enum : uint8_t { - AMDGPU_FLOAT_ROUND_MODE_NEAR_EVEN = 0, - AMDGPU_FLOAT_ROUND_MODE_PLUS_INFINITY = 1, - AMDGPU_FLOAT_ROUND_MODE_MINUS_INFINITY = 2, - AMDGPU_FLOAT_ROUND_MODE_ZERO = 3, -}; - -/// \brief Floating point denorm modes. -enum : uint8_t { - AMDGPU_FLOAT_DENORM_MODE_FLUSH_SRC_DST = 0, - AMDGPU_FLOAT_DENORM_MODE_FLUSH_DST = 1, - AMDGPU_FLOAT_DENORM_MODE_FLUSH_SRC = 2, - AMDGPU_FLOAT_DENORM_MODE_FLUSH_NONE = 3, -}; - -/// \brief System VGPR workitem IDs. -enum : uint8_t { - AMDGPU_SYSTEM_VGPR_WORKITEM_ID_X = 0, - AMDGPU_SYSTEM_VGPR_WORKITEM_ID_X_Y = 1, - AMDGPU_SYSTEM_VGPR_WORKITEM_ID_X_Y_Z = 2, - AMDGPU_SYSTEM_VGPR_WORKITEM_ID_UNDEFINED = 3, -}; - -/// \brief Compute program resource register one layout. -enum ComputePgmRsrc1 { - AMDGPU_BITS_ENUM_ENTRY(GRANULATED_WORKITEM_VGPR_COUNT, 0, 6), - AMDGPU_BITS_ENUM_ENTRY(GRANULATED_WAVEFRONT_SGPR_COUNT, 6, 4), - AMDGPU_BITS_ENUM_ENTRY(PRIORITY, 10, 2), - AMDGPU_BITS_ENUM_ENTRY(FLOAT_ROUND_MODE_32, 12, 2), - AMDGPU_BITS_ENUM_ENTRY(FLOAT_ROUND_MODE_16_64, 14, 2), - AMDGPU_BITS_ENUM_ENTRY(FLOAT_DENORM_MODE_32, 16, 2), - AMDGPU_BITS_ENUM_ENTRY(FLOAT_DENORM_MODE_16_64, 18, 2), - AMDGPU_BITS_ENUM_ENTRY(PRIV, 20, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_DX10_CLAMP, 21, 1), - AMDGPU_BITS_ENUM_ENTRY(DEBUG_MODE, 22, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_IEEE_MODE, 23, 1), - AMDGPU_BITS_ENUM_ENTRY(BULKY, 24, 1), - AMDGPU_BITS_ENUM_ENTRY(CDBG_USER, 25, 1), - AMDGPU_BITS_ENUM_ENTRY(FP16_OVFL, 26, 1), - AMDGPU_BITS_ENUM_ENTRY(RESERVED0, 27, 5), -}; - -/// \brief Compute program resource register two layout. -enum ComputePgmRsrc2 { - AMDGPU_BITS_ENUM_ENTRY(ENABLE_SGPR_PRIVATE_SEGMENT_WAVE_OFFSET, 0, 1), - AMDGPU_BITS_ENUM_ENTRY(USER_SGPR_COUNT, 1, 5), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_TRAP_HANDLER, 6, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_SGPR_WORKGROUP_ID_X, 7, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_SGPR_WORKGROUP_ID_Y, 8, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_SGPR_WORKGROUP_ID_Z, 9, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_SGPR_WORKGROUP_INFO, 10, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_VGPR_WORKITEM_ID, 11, 2), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_ADDRESS_WATCH, 13, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_MEMORY, 14, 1), - AMDGPU_BITS_ENUM_ENTRY(GRANULATED_LDS_SIZE, 15, 9), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, 24, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, 25, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, 26, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, 27, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, 28, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, 29, 1), - AMDGPU_BITS_ENUM_ENTRY(ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, 30, 1), - AMDGPU_BITS_ENUM_ENTRY(RESERVED1, 31, 1), -}; - -/// \brief Kernel descriptor layout. This layout should be kept backwards -/// compatible as it is consumed by the command processor. -struct KernelDescriptor final { - uint32_t GroupSegmentFixedSize; - uint32_t PrivateSegmentFixedSize; - uint32_t MaxFlatWorkGroupSize; - uint64_t IsDynamicCallStack : 1; - uint64_t IsXNACKEnabled : 1; - uint64_t Reserved0 : 30; - int64_t KernelCodeEntryByteOffset; - uint64_t Reserved1[3]; - uint32_t ComputePgmRsrc1; - uint32_t ComputePgmRsrc2; - uint64_t EnableSGPRPrivateSegmentBuffer : 1; - uint64_t EnableSGPRDispatchPtr : 1; - uint64_t EnableSGPRQueuePtr : 1; - uint64_t EnableSGPRKernargSegmentPtr : 1; - uint64_t EnableSGPRDispatchID : 1; - uint64_t EnableSGPRFlatScratchInit : 1; - uint64_t EnableSGPRPrivateSegmentSize : 1; - uint64_t EnableSGPRGridWorkgroupCountX : 1; - uint64_t EnableSGPRGridWorkgroupCountY : 1; - uint64_t EnableSGPRGridWorkgroupCountZ : 1; - uint64_t Reserved2 : 54; - - KernelDescriptor() = default; -}; - -} // end namespace HSAKD -} // end namespace AMDGPU -} // end namespace llvm - -#endif // LLVM_SUPPORT_AMDGPUKERNELDESCRIPTOR_H diff --git a/contrib/llvm/include/llvm/Support/AMDGPUMetadata.h b/contrib/llvm/include/llvm/Support/AMDGPUMetadata.h index 00039a75c51d..667fb3f3da43 100644 --- a/contrib/llvm/include/llvm/Support/AMDGPUMetadata.h +++ b/contrib/llvm/include/llvm/Support/AMDGPUMetadata.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief AMDGPU metadata definitions and in-memory representations. +/// AMDGPU metadata definitions and in-memory representations. /// // //===----------------------------------------------------------------------===// @@ -29,17 +29,17 @@ namespace AMDGPU { //===----------------------------------------------------------------------===// namespace HSAMD { -/// \brief HSA metadata major version. +/// HSA metadata major version. constexpr uint32_t VersionMajor = 1; -/// \brief HSA metadata minor version. +/// HSA metadata minor version. constexpr uint32_t VersionMinor = 0; -/// \brief HSA metadata beginning assembler directive. +/// HSA metadata beginning assembler directive. constexpr char AssemblerDirectiveBegin[] = ".amd_amdgpu_hsa_metadata"; -/// \brief HSA metadata ending assembler directive. +/// HSA metadata ending assembler directive. constexpr char AssemblerDirectiveEnd[] = ".end_amd_amdgpu_hsa_metadata"; -/// \brief Access qualifiers. +/// Access qualifiers. enum class AccessQualifier : uint8_t { Default = 0, ReadOnly = 1, @@ -48,7 +48,7 @@ enum class AccessQualifier : uint8_t { Unknown = 0xff }; -/// \brief Address space qualifiers. +/// Address space qualifiers. enum class AddressSpaceQualifier : uint8_t { Private = 0, Global = 1, @@ -59,7 +59,7 @@ enum class AddressSpaceQualifier : uint8_t { Unknown = 0xff }; -/// \brief Value kinds. +/// Value kinds. enum class ValueKind : uint8_t { ByValue = 0, GlobalBuffer = 1, @@ -78,7 +78,7 @@ enum class ValueKind : uint8_t { Unknown = 0xff }; -/// \brief Value types. +/// Value types. enum class ValueType : uint8_t { Struct = 0, I8 = 1, @@ -106,29 +106,29 @@ namespace Kernel { namespace Attrs { namespace Key { -/// \brief Key for Kernel::Attr::Metadata::mReqdWorkGroupSize. +/// Key for Kernel::Attr::Metadata::mReqdWorkGroupSize. constexpr char ReqdWorkGroupSize[] = "ReqdWorkGroupSize"; -/// \brief Key for Kernel::Attr::Metadata::mWorkGroupSizeHint. +/// Key for Kernel::Attr::Metadata::mWorkGroupSizeHint. constexpr char WorkGroupSizeHint[] = "WorkGroupSizeHint"; -/// \brief Key for Kernel::Attr::Metadata::mVecTypeHint. +/// Key for Kernel::Attr::Metadata::mVecTypeHint. constexpr char VecTypeHint[] = "VecTypeHint"; -/// \brief Key for Kernel::Attr::Metadata::mRuntimeHandle. +/// Key for Kernel::Attr::Metadata::mRuntimeHandle. constexpr char RuntimeHandle[] = "RuntimeHandle"; } // end namespace Key -/// \brief In-memory representation of kernel attributes metadata. +/// In-memory representation of kernel attributes metadata. struct Metadata final { - /// \brief 'reqd_work_group_size' attribute. Optional. + /// 'reqd_work_group_size' attribute. Optional. std::vector<uint32_t> mReqdWorkGroupSize = std::vector<uint32_t>(); - /// \brief 'work_group_size_hint' attribute. Optional. + /// 'work_group_size_hint' attribute. Optional. std::vector<uint32_t> mWorkGroupSizeHint = std::vector<uint32_t>(); - /// \brief 'vec_type_hint' attribute. Optional. + /// 'vec_type_hint' attribute. Optional. std::string mVecTypeHint = std::string(); - /// \brief External symbol created by runtime to store the kernel address + /// External symbol created by runtime to store the kernel address /// for enqueued blocks. std::string mRuntimeHandle = std::string(); - /// \brief Default constructor. + /// Default constructor. Metadata() = default; /// \returns True if kernel attributes metadata is empty, false otherwise. @@ -151,68 +151,68 @@ struct Metadata final { namespace Arg { namespace Key { -/// \brief Key for Kernel::Arg::Metadata::mName. +/// Key for Kernel::Arg::Metadata::mName. constexpr char Name[] = "Name"; -/// \brief Key for Kernel::Arg::Metadata::mTypeName. +/// Key for Kernel::Arg::Metadata::mTypeName. constexpr char TypeName[] = "TypeName"; -/// \brief Key for Kernel::Arg::Metadata::mSize. +/// Key for Kernel::Arg::Metadata::mSize. constexpr char Size[] = "Size"; -/// \brief Key for Kernel::Arg::Metadata::mAlign. +/// Key for Kernel::Arg::Metadata::mAlign. constexpr char Align[] = "Align"; -/// \brief Key for Kernel::Arg::Metadata::mValueKind. +/// Key for Kernel::Arg::Metadata::mValueKind. constexpr char ValueKind[] = "ValueKind"; -/// \brief Key for Kernel::Arg::Metadata::mValueType. +/// Key for Kernel::Arg::Metadata::mValueType. constexpr char ValueType[] = "ValueType"; -/// \brief Key for Kernel::Arg::Metadata::mPointeeAlign. +/// Key for Kernel::Arg::Metadata::mPointeeAlign. constexpr char PointeeAlign[] = "PointeeAlign"; -/// \brief Key for Kernel::Arg::Metadata::mAddrSpaceQual. +/// Key for Kernel::Arg::Metadata::mAddrSpaceQual. constexpr char AddrSpaceQual[] = "AddrSpaceQual"; -/// \brief Key for Kernel::Arg::Metadata::mAccQual. +/// Key for Kernel::Arg::Metadata::mAccQual. constexpr char AccQual[] = "AccQual"; -/// \brief Key for Kernel::Arg::Metadata::mActualAccQual. +/// Key for Kernel::Arg::Metadata::mActualAccQual. constexpr char ActualAccQual[] = "ActualAccQual"; -/// \brief Key for Kernel::Arg::Metadata::mIsConst. +/// Key for Kernel::Arg::Metadata::mIsConst. constexpr char IsConst[] = "IsConst"; -/// \brief Key for Kernel::Arg::Metadata::mIsRestrict. +/// Key for Kernel::Arg::Metadata::mIsRestrict. constexpr char IsRestrict[] = "IsRestrict"; -/// \brief Key for Kernel::Arg::Metadata::mIsVolatile. +/// Key for Kernel::Arg::Metadata::mIsVolatile. constexpr char IsVolatile[] = "IsVolatile"; -/// \brief Key for Kernel::Arg::Metadata::mIsPipe. +/// Key for Kernel::Arg::Metadata::mIsPipe. constexpr char IsPipe[] = "IsPipe"; } // end namespace Key -/// \brief In-memory representation of kernel argument metadata. +/// In-memory representation of kernel argument metadata. struct Metadata final { - /// \brief Name. Optional. + /// Name. Optional. std::string mName = std::string(); - /// \brief Type name. Optional. + /// Type name. Optional. std::string mTypeName = std::string(); - /// \brief Size in bytes. Required. + /// Size in bytes. Required. uint32_t mSize = 0; - /// \brief Alignment in bytes. Required. + /// Alignment in bytes. Required. uint32_t mAlign = 0; - /// \brief Value kind. Required. + /// Value kind. Required. ValueKind mValueKind = ValueKind::Unknown; - /// \brief Value type. Required. + /// Value type. Required. ValueType mValueType = ValueType::Unknown; - /// \brief Pointee alignment in bytes. Optional. + /// Pointee alignment in bytes. Optional. uint32_t mPointeeAlign = 0; - /// \brief Address space qualifier. Optional. + /// Address space qualifier. Optional. AddressSpaceQualifier mAddrSpaceQual = AddressSpaceQualifier::Unknown; - /// \brief Access qualifier. Optional. + /// Access qualifier. Optional. AccessQualifier mAccQual = AccessQualifier::Unknown; - /// \brief Actual access qualifier. Optional. + /// Actual access qualifier. Optional. AccessQualifier mActualAccQual = AccessQualifier::Unknown; - /// \brief True if 'const' qualifier is specified. Optional. + /// True if 'const' qualifier is specified. Optional. bool mIsConst = false; - /// \brief True if 'restrict' qualifier is specified. Optional. + /// True if 'restrict' qualifier is specified. Optional. bool mIsRestrict = false; - /// \brief True if 'volatile' qualifier is specified. Optional. + /// True if 'volatile' qualifier is specified. Optional. bool mIsVolatile = false; - /// \brief True if 'pipe' qualifier is specified. Optional. + /// True if 'pipe' qualifier is specified. Optional. bool mIsPipe = false; - /// \brief Default constructor. + /// Default constructor. Metadata() = default; }; @@ -224,67 +224,67 @@ struct Metadata final { namespace CodeProps { namespace Key { -/// \brief Key for Kernel::CodeProps::Metadata::mKernargSegmentSize. +/// Key for Kernel::CodeProps::Metadata::mKernargSegmentSize. constexpr char KernargSegmentSize[] = "KernargSegmentSize"; -/// \brief Key for Kernel::CodeProps::Metadata::mGroupSegmentFixedSize. +/// Key for Kernel::CodeProps::Metadata::mGroupSegmentFixedSize. constexpr char GroupSegmentFixedSize[] = "GroupSegmentFixedSize"; -/// \brief Key for Kernel::CodeProps::Metadata::mPrivateSegmentFixedSize. +/// Key for Kernel::CodeProps::Metadata::mPrivateSegmentFixedSize. constexpr char PrivateSegmentFixedSize[] = "PrivateSegmentFixedSize"; -/// \brief Key for Kernel::CodeProps::Metadata::mKernargSegmentAlign. +/// Key for Kernel::CodeProps::Metadata::mKernargSegmentAlign. constexpr char KernargSegmentAlign[] = "KernargSegmentAlign"; -/// \brief Key for Kernel::CodeProps::Metadata::mWavefrontSize. +/// Key for Kernel::CodeProps::Metadata::mWavefrontSize. constexpr char WavefrontSize[] = "WavefrontSize"; -/// \brief Key for Kernel::CodeProps::Metadata::mNumSGPRs. +/// Key for Kernel::CodeProps::Metadata::mNumSGPRs. constexpr char NumSGPRs[] = "NumSGPRs"; -/// \brief Key for Kernel::CodeProps::Metadata::mNumVGPRs. +/// Key for Kernel::CodeProps::Metadata::mNumVGPRs. constexpr char NumVGPRs[] = "NumVGPRs"; -/// \brief Key for Kernel::CodeProps::Metadata::mMaxFlatWorkGroupSize. +/// Key for Kernel::CodeProps::Metadata::mMaxFlatWorkGroupSize. constexpr char MaxFlatWorkGroupSize[] = "MaxFlatWorkGroupSize"; -/// \brief Key for Kernel::CodeProps::Metadata::mIsDynamicCallStack. +/// Key for Kernel::CodeProps::Metadata::mIsDynamicCallStack. constexpr char IsDynamicCallStack[] = "IsDynamicCallStack"; -/// \brief Key for Kernel::CodeProps::Metadata::mIsXNACKEnabled. +/// Key for Kernel::CodeProps::Metadata::mIsXNACKEnabled. constexpr char IsXNACKEnabled[] = "IsXNACKEnabled"; -/// \brief Key for Kernel::CodeProps::Metadata::mNumSpilledSGPRs. +/// Key for Kernel::CodeProps::Metadata::mNumSpilledSGPRs. constexpr char NumSpilledSGPRs[] = "NumSpilledSGPRs"; -/// \brief Key for Kernel::CodeProps::Metadata::mNumSpilledVGPRs. +/// Key for Kernel::CodeProps::Metadata::mNumSpilledVGPRs. constexpr char NumSpilledVGPRs[] = "NumSpilledVGPRs"; } // end namespace Key -/// \brief In-memory representation of kernel code properties metadata. +/// In-memory representation of kernel code properties metadata. struct Metadata final { - /// \brief Size in bytes of the kernarg segment memory. Kernarg segment memory + /// Size in bytes of the kernarg segment memory. Kernarg segment memory /// holds the values of the arguments to the kernel. Required. uint64_t mKernargSegmentSize = 0; - /// \brief Size in bytes of the group segment memory required by a workgroup. + /// Size in bytes of the group segment memory required by a workgroup. /// This value does not include any dynamically allocated group segment memory /// that may be added when the kernel is dispatched. Required. uint32_t mGroupSegmentFixedSize = 0; - /// \brief Size in bytes of the private segment memory required by a workitem. + /// Size in bytes of the private segment memory required by a workitem. /// Private segment memory includes arg, spill and private segments. Required. uint32_t mPrivateSegmentFixedSize = 0; - /// \brief Maximum byte alignment of variables used by the kernel in the + /// Maximum byte alignment of variables used by the kernel in the /// kernarg memory segment. Required. uint32_t mKernargSegmentAlign = 0; - /// \brief Wavefront size. Required. + /// Wavefront size. Required. uint32_t mWavefrontSize = 0; - /// \brief Total number of SGPRs used by a wavefront. Optional. + /// Total number of SGPRs used by a wavefront. Optional. uint16_t mNumSGPRs = 0; - /// \brief Total number of VGPRs used by a workitem. Optional. + /// Total number of VGPRs used by a workitem. Optional. uint16_t mNumVGPRs = 0; - /// \brief Maximum flat work-group size supported by the kernel. Optional. + /// Maximum flat work-group size supported by the kernel. Optional. uint32_t mMaxFlatWorkGroupSize = 0; - /// \brief True if the generated machine code is using a dynamically sized + /// True if the generated machine code is using a dynamically sized /// call stack. Optional. bool mIsDynamicCallStack = false; - /// \brief True if the generated machine code is capable of supporting XNACK. + /// True if the generated machine code is capable of supporting XNACK. /// Optional. bool mIsXNACKEnabled = false; - /// \brief Number of SGPRs spilled by a wavefront. Optional. + /// Number of SGPRs spilled by a wavefront. Optional. uint16_t mNumSpilledSGPRs = 0; - /// \brief Number of VGPRs spilled by a workitem. Optional. + /// Number of VGPRs spilled by a workitem. Optional. uint16_t mNumSpilledVGPRs = 0; - /// \brief Default constructor. + /// Default constructor. Metadata() = default; /// \returns True if kernel code properties metadata is empty, false @@ -308,40 +308,40 @@ struct Metadata final { namespace DebugProps { namespace Key { -/// \brief Key for Kernel::DebugProps::Metadata::mDebuggerABIVersion. +/// Key for Kernel::DebugProps::Metadata::mDebuggerABIVersion. constexpr char DebuggerABIVersion[] = "DebuggerABIVersion"; -/// \brief Key for Kernel::DebugProps::Metadata::mReservedNumVGPRs. +/// Key for Kernel::DebugProps::Metadata::mReservedNumVGPRs. constexpr char ReservedNumVGPRs[] = "ReservedNumVGPRs"; -/// \brief Key for Kernel::DebugProps::Metadata::mReservedFirstVGPR. +/// Key for Kernel::DebugProps::Metadata::mReservedFirstVGPR. constexpr char ReservedFirstVGPR[] = "ReservedFirstVGPR"; -/// \brief Key for Kernel::DebugProps::Metadata::mPrivateSegmentBufferSGPR. +/// Key for Kernel::DebugProps::Metadata::mPrivateSegmentBufferSGPR. constexpr char PrivateSegmentBufferSGPR[] = "PrivateSegmentBufferSGPR"; -/// \brief Key for +/// Key for /// Kernel::DebugProps::Metadata::mWavefrontPrivateSegmentOffsetSGPR. constexpr char WavefrontPrivateSegmentOffsetSGPR[] = "WavefrontPrivateSegmentOffsetSGPR"; } // end namespace Key -/// \brief In-memory representation of kernel debug properties metadata. +/// In-memory representation of kernel debug properties metadata. struct Metadata final { - /// \brief Debugger ABI version. Optional. + /// Debugger ABI version. Optional. std::vector<uint32_t> mDebuggerABIVersion = std::vector<uint32_t>(); - /// \brief Consecutive number of VGPRs reserved for debugger use. Must be 0 if + /// Consecutive number of VGPRs reserved for debugger use. Must be 0 if /// mDebuggerABIVersion is not set. Optional. uint16_t mReservedNumVGPRs = 0; - /// \brief First fixed VGPR reserved. Must be uint16_t(-1) if + /// First fixed VGPR reserved. Must be uint16_t(-1) if /// mDebuggerABIVersion is not set or mReservedFirstVGPR is 0. Optional. uint16_t mReservedFirstVGPR = uint16_t(-1); - /// \brief Fixed SGPR of the first of 4 SGPRs used to hold the scratch V# used + /// Fixed SGPR of the first of 4 SGPRs used to hold the scratch V# used /// for the entire kernel execution. Must be uint16_t(-1) if /// mDebuggerABIVersion is not set or SGPR not used or not known. Optional. uint16_t mPrivateSegmentBufferSGPR = uint16_t(-1); - /// \brief Fixed SGPR used to hold the wave scratch offset for the entire + /// Fixed SGPR used to hold the wave scratch offset for the entire /// kernel execution. Must be uint16_t(-1) if mDebuggerABIVersion is not set /// or SGPR is not used or not known. Optional. uint16_t mWavefrontPrivateSegmentOffsetSGPR = uint16_t(-1); - /// \brief Default constructor. + /// Default constructor. Metadata() = default; /// \returns True if kernel debug properties metadata is empty, false @@ -360,75 +360,75 @@ struct Metadata final { } // end namespace DebugProps namespace Key { -/// \brief Key for Kernel::Metadata::mName. +/// Key for Kernel::Metadata::mName. constexpr char Name[] = "Name"; -/// \brief Key for Kernel::Metadata::mSymbolName. +/// Key for Kernel::Metadata::mSymbolName. constexpr char SymbolName[] = "SymbolName"; -/// \brief Key for Kernel::Metadata::mLanguage. +/// Key for Kernel::Metadata::mLanguage. constexpr char Language[] = "Language"; -/// \brief Key for Kernel::Metadata::mLanguageVersion. +/// Key for Kernel::Metadata::mLanguageVersion. constexpr char LanguageVersion[] = "LanguageVersion"; -/// \brief Key for Kernel::Metadata::mAttrs. +/// Key for Kernel::Metadata::mAttrs. constexpr char Attrs[] = "Attrs"; -/// \brief Key for Kernel::Metadata::mArgs. +/// Key for Kernel::Metadata::mArgs. constexpr char Args[] = "Args"; -/// \brief Key for Kernel::Metadata::mCodeProps. +/// Key for Kernel::Metadata::mCodeProps. constexpr char CodeProps[] = "CodeProps"; -/// \brief Key for Kernel::Metadata::mDebugProps. +/// Key for Kernel::Metadata::mDebugProps. constexpr char DebugProps[] = "DebugProps"; } // end namespace Key -/// \brief In-memory representation of kernel metadata. +/// In-memory representation of kernel metadata. struct Metadata final { - /// \brief Kernel source name. Required. + /// Kernel source name. Required. std::string mName = std::string(); - /// \brief Kernel descriptor name. Required. + /// Kernel descriptor name. Required. std::string mSymbolName = std::string(); - /// \brief Language. Optional. + /// Language. Optional. std::string mLanguage = std::string(); - /// \brief Language version. Optional. + /// Language version. Optional. std::vector<uint32_t> mLanguageVersion = std::vector<uint32_t>(); - /// \brief Attributes metadata. Optional. + /// Attributes metadata. Optional. Attrs::Metadata mAttrs = Attrs::Metadata(); - /// \brief Arguments metadata. Optional. + /// Arguments metadata. Optional. std::vector<Arg::Metadata> mArgs = std::vector<Arg::Metadata>(); - /// \brief Code properties metadata. Optional. + /// Code properties metadata. Optional. CodeProps::Metadata mCodeProps = CodeProps::Metadata(); - /// \brief Debug properties metadata. Optional. + /// Debug properties metadata. Optional. DebugProps::Metadata mDebugProps = DebugProps::Metadata(); - /// \brief Default constructor. + /// Default constructor. Metadata() = default; }; } // end namespace Kernel namespace Key { -/// \brief Key for HSA::Metadata::mVersion. +/// Key for HSA::Metadata::mVersion. constexpr char Version[] = "Version"; -/// \brief Key for HSA::Metadata::mPrintf. +/// Key for HSA::Metadata::mPrintf. constexpr char Printf[] = "Printf"; -/// \brief Key for HSA::Metadata::mKernels. +/// Key for HSA::Metadata::mKernels. constexpr char Kernels[] = "Kernels"; } // end namespace Key -/// \brief In-memory representation of HSA metadata. +/// In-memory representation of HSA metadata. struct Metadata final { - /// \brief HSA metadata version. Required. + /// HSA metadata version. Required. std::vector<uint32_t> mVersion = std::vector<uint32_t>(); - /// \brief Printf metadata. Optional. + /// Printf metadata. Optional. std::vector<std::string> mPrintf = std::vector<std::string>(); - /// \brief Kernels metadata. Required. + /// Kernels metadata. Required. std::vector<Kernel::Metadata> mKernels = std::vector<Kernel::Metadata>(); - /// \brief Default constructor. + /// Default constructor. Metadata() = default; }; -/// \brief Converts \p String to \p HSAMetadata. +/// Converts \p String to \p HSAMetadata. std::error_code fromString(std::string String, Metadata &HSAMetadata); -/// \brief Converts \p HSAMetadata to \p String. +/// Converts \p HSAMetadata to \p String. std::error_code toString(Metadata HSAMetadata, std::string &String); } // end namespace HSAMD @@ -438,10 +438,10 @@ std::error_code toString(Metadata HSAMetadata, std::string &String); //===----------------------------------------------------------------------===// namespace PALMD { -/// \brief PAL metadata assembler directive. +/// PAL metadata assembler directive. constexpr char AssemblerDirective[] = ".amd_amdgpu_pal_metadata"; -/// \brief PAL metadata keys. +/// PAL metadata keys. enum Key : uint32_t { LS_NUM_USED_VGPRS = 0x10000021, HS_NUM_USED_VGPRS = 0x10000022, @@ -468,10 +468,10 @@ enum Key : uint32_t { CS_SCRATCH_SIZE = 0x1000004a }; -/// \brief PAL metadata represented as a vector. +/// PAL metadata represented as a vector. typedef std::vector<uint32_t> Metadata; -/// \brief Converts \p PALMetadata to \p String. +/// Converts \p PALMetadata to \p String. std::error_code toString(const Metadata &PALMetadata, std::string &String); } // end namespace PALMD diff --git a/contrib/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h b/contrib/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h new file mode 100644 index 000000000000..751699e3a19f --- /dev/null +++ b/contrib/llvm/include/llvm/Support/AMDHSAKernelDescriptor.h @@ -0,0 +1,185 @@ +//===--- AMDHSAKernelDescriptor.h -----------------------------*- C++ -*---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// AMDHSA kernel descriptor definitions. For more information, visit +/// https://llvm.org/docs/AMDGPUUsage.html#kernel-descriptor +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_AMDHSAKERNELDESCRIPTOR_H +#define LLVM_SUPPORT_AMDHSAKERNELDESCRIPTOR_H + +#include <cstddef> +#include <cstdint> + +// Gets offset of specified member in specified type. +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER) +#endif // offsetof + +// Creates enumeration entries used for packing bits into integers. Enumeration +// entries include bit shift amount, bit width, and bit mask. +#ifndef AMDHSA_BITS_ENUM_ENTRY +#define AMDHSA_BITS_ENUM_ENTRY(NAME, SHIFT, WIDTH) \ + NAME ## _SHIFT = (SHIFT), \ + NAME ## _WIDTH = (WIDTH), \ + NAME = (((1 << (WIDTH)) - 1) << (SHIFT)) +#endif // AMDHSA_BITS_ENUM_ENTRY + +// Gets bits for specified bit mask from specified source. +#ifndef AMDHSA_BITS_GET +#define AMDHSA_BITS_GET(SRC, MSK) ((SRC & MSK) >> MSK ## _SHIFT) +#endif // AMDHSA_BITS_GET + +// Sets bits for specified bit mask in specified destination. +#ifndef AMDHSA_BITS_SET +#define AMDHSA_BITS_SET(DST, MSK, VAL) \ + DST &= ~MSK; \ + DST |= ((VAL << MSK ## _SHIFT) & MSK) +#endif // AMDHSA_BITS_SET + +namespace llvm { +namespace amdhsa { + +// Floating point rounding modes. Must match hardware definition. +enum : uint8_t { + FLOAT_ROUND_MODE_NEAR_EVEN = 0, + FLOAT_ROUND_MODE_PLUS_INFINITY = 1, + FLOAT_ROUND_MODE_MINUS_INFINITY = 2, + FLOAT_ROUND_MODE_ZERO = 3, +}; + +// Floating point denorm modes. Must match hardware definition. +enum : uint8_t { + FLOAT_DENORM_MODE_FLUSH_SRC_DST = 0, + FLOAT_DENORM_MODE_FLUSH_DST = 1, + FLOAT_DENORM_MODE_FLUSH_SRC = 2, + FLOAT_DENORM_MODE_FLUSH_NONE = 3, +}; + +// System VGPR workitem IDs. Must match hardware definition. +enum : uint8_t { + SYSTEM_VGPR_WORKITEM_ID_X = 0, + SYSTEM_VGPR_WORKITEM_ID_X_Y = 1, + SYSTEM_VGPR_WORKITEM_ID_X_Y_Z = 2, + SYSTEM_VGPR_WORKITEM_ID_UNDEFINED = 3, +}; + +// Compute program resource register 1. Must match hardware definition. +#define COMPUTE_PGM_RSRC1(NAME, SHIFT, WIDTH) \ + AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC1_ ## NAME, SHIFT, WIDTH) +enum : int32_t { + COMPUTE_PGM_RSRC1(GRANULATED_WORKITEM_VGPR_COUNT, 0, 6), + COMPUTE_PGM_RSRC1(GRANULATED_WAVEFRONT_SGPR_COUNT, 6, 4), + COMPUTE_PGM_RSRC1(PRIORITY, 10, 2), + COMPUTE_PGM_RSRC1(FLOAT_ROUND_MODE_32, 12, 2), + COMPUTE_PGM_RSRC1(FLOAT_ROUND_MODE_16_64, 14, 2), + COMPUTE_PGM_RSRC1(FLOAT_DENORM_MODE_32, 16, 2), + COMPUTE_PGM_RSRC1(FLOAT_DENORM_MODE_16_64, 18, 2), + COMPUTE_PGM_RSRC1(PRIV, 20, 1), + COMPUTE_PGM_RSRC1(ENABLE_DX10_CLAMP, 21, 1), + COMPUTE_PGM_RSRC1(DEBUG_MODE, 22, 1), + COMPUTE_PGM_RSRC1(ENABLE_IEEE_MODE, 23, 1), + COMPUTE_PGM_RSRC1(BULKY, 24, 1), + COMPUTE_PGM_RSRC1(CDBG_USER, 25, 1), + COMPUTE_PGM_RSRC1(FP16_OVFL, 26, 1), // GFX9+ + COMPUTE_PGM_RSRC1(RESERVED0, 27, 5), +}; +#undef COMPUTE_PGM_RSRC1 + +// Compute program resource register 2. Must match hardware definition. +#define COMPUTE_PGM_RSRC2(NAME, SHIFT, WIDTH) \ + AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC2_ ## NAME, SHIFT, WIDTH) +enum : int32_t { + COMPUTE_PGM_RSRC2(ENABLE_SGPR_PRIVATE_SEGMENT_WAVEFRONT_OFFSET, 0, 1), + COMPUTE_PGM_RSRC2(USER_SGPR_COUNT, 1, 5), + COMPUTE_PGM_RSRC2(ENABLE_TRAP_HANDLER, 6, 1), + COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_ID_X, 7, 1), + COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_ID_Y, 8, 1), + COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_ID_Z, 9, 1), + COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_INFO, 10, 1), + COMPUTE_PGM_RSRC2(ENABLE_VGPR_WORKITEM_ID, 11, 2), + COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_ADDRESS_WATCH, 13, 1), + COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_MEMORY, 14, 1), + COMPUTE_PGM_RSRC2(GRANULATED_LDS_SIZE, 15, 9), + COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, 24, 1), + COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, 25, 1), + COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, 26, 1), + COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, 27, 1), + COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, 28, 1), + COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, 29, 1), + COMPUTE_PGM_RSRC2(ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, 30, 1), + COMPUTE_PGM_RSRC2(RESERVED0, 31, 1), +}; +#undef COMPUTE_PGM_RSRC2 + +// Kernel code properties. Must be kept backwards compatible. +#define KERNEL_CODE_PROPERTY(NAME, SHIFT, WIDTH) \ + AMDHSA_BITS_ENUM_ENTRY(KERNEL_CODE_PROPERTY_ ## NAME, SHIFT, WIDTH) +enum : int32_t { + KERNEL_CODE_PROPERTY(ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER, 0, 1), + KERNEL_CODE_PROPERTY(ENABLE_SGPR_DISPATCH_PTR, 1, 1), + KERNEL_CODE_PROPERTY(ENABLE_SGPR_QUEUE_PTR, 2, 1), + KERNEL_CODE_PROPERTY(ENABLE_SGPR_KERNARG_SEGMENT_PTR, 3, 1), + KERNEL_CODE_PROPERTY(ENABLE_SGPR_DISPATCH_ID, 4, 1), + KERNEL_CODE_PROPERTY(ENABLE_SGPR_FLAT_SCRATCH_INIT, 5, 1), + KERNEL_CODE_PROPERTY(ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, 6, 1), + KERNEL_CODE_PROPERTY(RESERVED0, 7, 9), +}; +#undef KERNEL_CODE_PROPERTY + +// Kernel descriptor. Must be kept backwards compatible. +struct kernel_descriptor_t { + uint32_t group_segment_fixed_size; + uint32_t private_segment_fixed_size; + uint8_t reserved0[8]; + int64_t kernel_code_entry_byte_offset; + uint8_t reserved1[24]; + uint32_t compute_pgm_rsrc1; + uint32_t compute_pgm_rsrc2; + uint16_t kernel_code_properties; + uint8_t reserved2[6]; +}; + +static_assert( + sizeof(kernel_descriptor_t) == 64, + "invalid size for kernel_descriptor_t"); +static_assert( + offsetof(kernel_descriptor_t, group_segment_fixed_size) == 0, + "invalid offset for group_segment_fixed_size"); +static_assert( + offsetof(kernel_descriptor_t, private_segment_fixed_size) == 4, + "invalid offset for private_segment_fixed_size"); +static_assert( + offsetof(kernel_descriptor_t, reserved0) == 8, + "invalid offset for reserved0"); +static_assert( + offsetof(kernel_descriptor_t, kernel_code_entry_byte_offset) == 16, + "invalid offset for kernel_code_entry_byte_offset"); +static_assert( + offsetof(kernel_descriptor_t, reserved1) == 24, + "invalid offset for reserved1"); +static_assert( + offsetof(kernel_descriptor_t, compute_pgm_rsrc1) == 48, + "invalid offset for compute_pgm_rsrc1"); +static_assert( + offsetof(kernel_descriptor_t, compute_pgm_rsrc2) == 52, + "invalid offset for compute_pgm_rsrc2"); +static_assert( + offsetof(kernel_descriptor_t, kernel_code_properties) == 56, + "invalid offset for kernel_code_properties"); +static_assert( + offsetof(kernel_descriptor_t, reserved2) == 58, + "invalid offset for reserved2"); + +} // end namespace amdhsa +} // end namespace llvm + +#endif // LLVM_SUPPORT_AMDHSAKERNELDESCRIPTOR_H diff --git a/contrib/llvm/include/llvm/Support/ARMTargetParser.def b/contrib/llvm/include/llvm/Support/ARMTargetParser.def index 6c8eff1a8f84..78f5410fb733 100644 --- a/contrib/llvm/include/llvm/Support/ARMTargetParser.def +++ b/contrib/llvm/include/llvm/Support/ARMTargetParser.def @@ -101,6 +101,11 @@ ARM_ARCH("armv8.3-a", ARMV8_3A, "8.3-A", "v8.3a", ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS)) +ARM_ARCH("armv8.4-a", ARMV8_4A, "8.4-A", "v8.4a", + ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS | + ARM::AEK_DOTPROD)) ARM_ARCH("armv8-r", ARMV8R, "8-R", "v8r", ARMBuildAttrs::CPUArch::v8_R, FK_NEON_FP_ARMV8, (ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB | @@ -130,6 +135,8 @@ ARM_ARCH_EXT_NAME("invalid", ARM::AEK_INVALID, nullptr, nullptr) ARM_ARCH_EXT_NAME("none", ARM::AEK_NONE, nullptr, nullptr) ARM_ARCH_EXT_NAME("crc", ARM::AEK_CRC, "+crc", "-crc") ARM_ARCH_EXT_NAME("crypto", ARM::AEK_CRYPTO, "+crypto","-crypto") +ARM_ARCH_EXT_NAME("sha2", ARM::AEK_SHA2, "+sha2", "-sha2") +ARM_ARCH_EXT_NAME("aes", ARM::AEK_AES, "+aes", "-aes") ARM_ARCH_EXT_NAME("dotprod", ARM::AEK_DOTPROD, "+dotprod","-dotprod") ARM_ARCH_EXT_NAME("dsp", ARM::AEK_DSP, "+dsp", "-dsp") ARM_ARCH_EXT_NAME("fp", ARM::AEK_FP, nullptr, nullptr) @@ -253,6 +260,7 @@ ARM_CPU_NAME("cyclone", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("exynos-m1", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("exynos-m2", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("exynos-m3", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("exynos-m4", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) ARM_CPU_NAME("kryo", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) // Non-standard Arch names. ARM_CPU_NAME("iwmmxt", IWMMXT, FK_NONE, true, ARM::AEK_NONE) diff --git a/contrib/llvm/include/llvm/Support/AlignOf.h b/contrib/llvm/include/llvm/Support/AlignOf.h index abd19afa22f0..9e7a62b85e34 100644 --- a/contrib/llvm/include/llvm/Support/AlignOf.h +++ b/contrib/llvm/include/llvm/Support/AlignOf.h @@ -20,7 +20,7 @@ namespace llvm { /// \struct AlignedCharArray -/// \brief Helper for building an aligned character array type. +/// Helper for building an aligned character array type. /// /// This template is used to explicitly build up a collection of aligned /// character array types. We have to build these up using a macro and explicit @@ -34,12 +34,12 @@ namespace llvm { template<std::size_t Alignment, std::size_t Size> struct AlignedCharArray { - LLVM_ALIGNAS(Alignment) char buffer[Size]; + alignas(Alignment) char buffer[Size]; }; #else // _MSC_VER -/// \brief Create a type with an aligned char buffer. +/// Create a type with an aligned char buffer. template<std::size_t Alignment, std::size_t Size> struct AlignedCharArray; @@ -124,7 +124,7 @@ union SizerImpl { }; } // end namespace detail -/// \brief This union template exposes a suitably aligned and sized character +/// This union template exposes a suitably aligned and sized character /// array member which can hold elements of any of up to ten types. /// /// These types may be arrays, structs, or any other types. The goal is to diff --git a/contrib/llvm/include/llvm/Support/Allocator.h b/contrib/llvm/include/llvm/Support/Allocator.h index a94aa8fb1f2a..184ac491b1f1 100644 --- a/contrib/llvm/include/llvm/Support/Allocator.h +++ b/contrib/llvm/include/llvm/Support/Allocator.h @@ -23,7 +23,9 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemAlloc.h" #include <algorithm> #include <cassert> #include <cstddef> @@ -35,7 +37,7 @@ namespace llvm { -/// \brief CRTP base class providing obvious overloads for the core \c +/// CRTP base class providing obvious overloads for the core \c /// Allocate() methods of LLVM-style allocators. /// /// This base class both documents the full public interface exposed by all @@ -43,7 +45,7 @@ namespace llvm { /// set of methods which the derived class must define. template <typename DerivedT> class AllocatorBase { public: - /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method + /// Allocate \a Size bytes of \a Alignment aligned memory. This method /// must be implemented by \c DerivedT. void *Allocate(size_t Size, size_t Alignment) { #ifdef __clang__ @@ -57,7 +59,7 @@ public: return static_cast<DerivedT *>(this)->Allocate(Size, Alignment); } - /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this + /// Deallocate \a Ptr to \a Size bytes of memory allocated by this /// allocator. void Deallocate(const void *Ptr, size_t Size) { #ifdef __clang__ @@ -74,12 +76,12 @@ public: // The rest of these methods are helpers that redirect to one of the above // core methods. - /// \brief Allocate space for a sequence of objects without constructing them. + /// Allocate space for a sequence of objects without constructing them. template <typename T> T *Allocate(size_t Num = 1) { return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T))); } - /// \brief Deallocate space for a sequence of objects without constructing them. + /// Deallocate space for a sequence of objects without constructing them. template <typename T> typename std::enable_if< !std::is_same<typename std::remove_cv<T>::type, void>::value, void>::type @@ -94,7 +96,7 @@ public: LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t /*Alignment*/) { - return malloc(Size); + return safe_malloc(Size); } // Pull in base class overloads. @@ -119,7 +121,7 @@ void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, } // end namespace detail -/// \brief Allocate memory in an ever growing pool, as if by bump-pointer. +/// 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 a boundless contiguous heap. However, it has @@ -187,7 +189,7 @@ public: return *this; } - /// \brief Deallocate all but the current slab and reset the current pointer + /// Deallocate all but the current slab and reset the current pointer /// to the beginning of it, freeing all memory allocated so far. void Reset() { // Deallocate all but the first slab, and deallocate all custom-sized slabs. @@ -207,7 +209,7 @@ public: Slabs.erase(std::next(Slabs.begin()), Slabs.end()); } - /// \brief Allocate space at the specified alignment. + /// Allocate space at the specified alignment. LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * Allocate(size_t Size, size_t Alignment) { assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); @@ -302,30 +304,30 @@ public: } private: - /// \brief The current pointer into the current slab. + /// The current pointer into the current slab. /// /// This points to the next free byte in the slab. char *CurPtr = nullptr; - /// \brief The end of the current slab. + /// The end of the current slab. char *End = nullptr; - /// \brief The slabs allocated so far. + /// The slabs allocated so far. SmallVector<void *, 4> Slabs; - /// \brief Custom-sized slabs allocated for too-large allocation requests. + /// Custom-sized slabs allocated for too-large allocation requests. SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs; - /// \brief How many bytes we've allocated. + /// How many bytes we've allocated. /// /// Used so that we can compute how much space was wasted. size_t BytesAllocated = 0; - /// \brief The number of bytes to put between allocations when running under + /// The number of bytes to put between allocations when running under /// a sanitizer. size_t RedZoneSize = 1; - /// \brief The allocator instance we use to get slabs of memory. + /// The allocator instance we use to get slabs of memory. AllocatorT Allocator; static size_t computeSlabSize(unsigned SlabIdx) { @@ -336,7 +338,7 @@ private: return SlabSize * ((size_t)1 << std::min<size_t>(30, SlabIdx / 128)); } - /// \brief Allocate a new slab and move the bump pointers over into the new + /// Allocate a new slab and move the bump pointers over into the new /// slab, modifying CurPtr and End. void StartNewSlab() { size_t AllocatedSlabSize = computeSlabSize(Slabs.size()); @@ -351,7 +353,7 @@ private: End = ((char *)NewSlab) + AllocatedSlabSize; } - /// \brief Deallocate a sequence of slabs. + /// Deallocate a sequence of slabs. void DeallocateSlabs(SmallVectorImpl<void *>::iterator I, SmallVectorImpl<void *>::iterator E) { for (; I != E; ++I) { @@ -361,7 +363,7 @@ private: } } - /// \brief Deallocate all memory for custom sized slabs. + /// Deallocate all memory for custom sized slabs. void DeallocateCustomSizedSlabs() { for (auto &PtrAndSize : CustomSizedSlabs) { void *Ptr = PtrAndSize.first; @@ -373,11 +375,11 @@ private: template <typename T> friend class SpecificBumpPtrAllocator; }; -/// \brief The standard BumpPtrAllocator which just uses the default template +/// The standard BumpPtrAllocator which just uses the default template /// parameters. typedef BumpPtrAllocatorImpl<> BumpPtrAllocator; -/// \brief A BumpPtrAllocator that allows only elements of a specific type to be +/// 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 @@ -430,7 +432,7 @@ public: Allocator.Reset(); } - /// \brief Allocate space for an array of objects without constructing them. + /// Allocate space for an array of objects without constructing them. T *Allocate(size_t num = 1) { return Allocator.Allocate<T>(num); } }; diff --git a/contrib/llvm/include/llvm/Support/AtomicOrdering.h b/contrib/llvm/include/llvm/Support/AtomicOrdering.h index e93b755aa63b..a679ab30243e 100644 --- a/contrib/llvm/include/llvm/Support/AtomicOrdering.h +++ b/contrib/llvm/include/llvm/Support/AtomicOrdering.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Atomic ordering constants. +/// Atomic ordering constants. /// /// These values are used by LLVM to represent atomic ordering for C++11's /// memory model and more, as detailed in docs/Atomics.rst. diff --git a/contrib/llvm/include/llvm/Support/BinaryByteStream.h b/contrib/llvm/include/llvm/Support/BinaryByteStream.h index db1ccba1398b..9808d3b72157 100644 --- a/contrib/llvm/include/llvm/Support/BinaryByteStream.h +++ b/contrib/llvm/include/llvm/Support/BinaryByteStream.h @@ -25,7 +25,7 @@ namespace llvm { -/// \brief An implementation of BinaryStream which holds its entire data set +/// An implementation of BinaryStream which holds its entire data set /// in a single contiguous buffer. BinaryByteStream guarantees that no read /// operation will ever incur a copy. Note that BinaryByteStream does not /// own the underlying buffer. @@ -69,7 +69,7 @@ protected: ArrayRef<uint8_t> Data; }; -/// \brief An implementation of BinaryStream whose data is backed by an llvm +/// An implementation of BinaryStream whose data is backed by an llvm /// MemoryBuffer object. MemoryBufferByteStream owns the MemoryBuffer in /// question. As with BinaryByteStream, reading from a MemoryBufferByteStream /// will never cause a copy. @@ -83,7 +83,7 @@ public: std::unique_ptr<MemoryBuffer> MemBuffer; }; -/// \brief An implementation of BinaryStream which holds its entire data set +/// An implementation of BinaryStream which holds its entire data set /// in a single contiguous buffer. As with BinaryByteStream, the mutable /// version also guarantees that no read operation will ever incur a copy, /// and similarly it does not own the underlying buffer. @@ -131,7 +131,7 @@ private: BinaryByteStream ImmutableStream; }; -/// \brief An implementation of WritableBinaryStream which can write at its end +/// An implementation of WritableBinaryStream which can write at its end /// causing the underlying data to grow. This class owns the underlying data. class AppendingBinaryByteStream : public WritableBinaryStream { std::vector<uint8_t> Data; @@ -193,7 +193,7 @@ public: Error commit() override { return Error::success(); } - /// \brief Return the properties of this stream. + /// Return the properties of this stream. virtual BinaryStreamFlags getFlags() const override { return BSF_Write | BSF_Append; } @@ -201,7 +201,7 @@ public: MutableArrayRef<uint8_t> data() { return Data; } }; -/// \brief An implementation of WritableBinaryStream backed by an llvm +/// An implementation of WritableBinaryStream backed by an llvm /// FileOutputBuffer. class FileBufferByteStream : public WritableBinaryStream { private: @@ -222,6 +222,12 @@ private: return Error::success(); } + /// Returns a pointer to the start of the buffer. + uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); } + + /// Returns a pointer to the end of the buffer. + uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); } + private: std::unique_ptr<FileOutputBuffer> FileBuffer; }; @@ -253,6 +259,12 @@ public: Error commit() override { return Impl.commit(); } + /// Returns a pointer to the start of the buffer. + uint8_t *getBufferStart() const { return Impl.getBufferStart(); } + + /// Returns a pointer to the end of the buffer. + uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); } + private: StreamImpl Impl; }; diff --git a/contrib/llvm/include/llvm/Support/BinaryStream.h b/contrib/llvm/include/llvm/Support/BinaryStream.h index d69a03eccfdb..7677214e48ee 100644 --- a/contrib/llvm/include/llvm/Support/BinaryStream.h +++ b/contrib/llvm/include/llvm/Support/BinaryStream.h @@ -26,7 +26,7 @@ enum BinaryStreamFlags { LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ BSF_Append) }; -/// \brief An interface for accessing data in a stream-like format, but which +/// An interface for accessing data in a stream-like format, but which /// discourages copying. Instead of specifying a buffer in which to copy /// data on a read, the API returns an ArrayRef to data owned by the stream's /// implementation. Since implementations may not necessarily store data in a @@ -39,21 +39,21 @@ public: virtual llvm::support::endianness getEndian() const = 0; - /// \brief Given an offset into the stream and a number of bytes, attempt to + /// Given an offset into the stream and a number of bytes, attempt to /// read the bytes and set the output ArrayRef to point to data owned by the /// stream. virtual Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef<uint8_t> &Buffer) = 0; - /// \brief Given an offset into the stream, read as much as possible without + /// Given an offset into the stream, read as much as possible without /// copying any data. virtual Error readLongestContiguousChunk(uint32_t Offset, ArrayRef<uint8_t> &Buffer) = 0; - /// \brief Return the number of bytes of data in this stream. + /// Return the number of bytes of data in this stream. virtual uint32_t getLength() = 0; - /// \brief Return the properties of this stream. + /// Return the properties of this stream. virtual BinaryStreamFlags getFlags() const { return BSF_None; } protected: @@ -66,7 +66,7 @@ protected: } }; -/// \brief A BinaryStream which can be read from as well as written to. Note +/// A BinaryStream which can be read from as well as written to. Note /// that writing to a BinaryStream always necessitates copying from the input /// buffer to the stream's backing store. Streams are assumed to be buffered /// so that to be portable it is necessary to call commit() on the stream when @@ -75,15 +75,15 @@ class WritableBinaryStream : public BinaryStream { public: ~WritableBinaryStream() override = default; - /// \brief Attempt to write the given bytes into the stream at the desired + /// Attempt to write the given bytes into the stream at the desired /// offset. This will always necessitate a copy. Cannot shrink or grow the /// stream, only writes into existing allocated space. virtual Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Data) = 0; - /// \brief For buffered streams, commits changes to the backing store. + /// For buffered streams, commits changes to the backing store. virtual Error commit() = 0; - /// \brief Return the properties of this stream. + /// Return the properties of this stream. BinaryStreamFlags getFlags() const override { return BSF_Write; } protected: diff --git a/contrib/llvm/include/llvm/Support/BinaryStreamArray.h b/contrib/llvm/include/llvm/Support/BinaryStreamArray.h index 3f5562ba7519..d1571cb37fc6 100644 --- a/contrib/llvm/include/llvm/Support/BinaryStreamArray.h +++ b/contrib/llvm/include/llvm/Support/BinaryStreamArray.h @@ -111,7 +111,7 @@ public: bool empty() const { return Stream.getLength() == 0; } - /// \brief given an offset into the array's underlying stream, return an + /// given an offset into the array's underlying stream, return an /// iterator to the record at that offset. This is considered unsafe /// since the behavior is undefined if \p Offset does not refer to the /// beginning of a valid record. diff --git a/contrib/llvm/include/llvm/Support/BinaryStreamReader.h b/contrib/llvm/include/llvm/Support/BinaryStreamReader.h index ae5ebb2c3628..fe77b550c453 100644 --- a/contrib/llvm/include/llvm/Support/BinaryStreamReader.h +++ b/contrib/llvm/include/llvm/Support/BinaryStreamReader.h @@ -24,7 +24,7 @@ namespace llvm { -/// \brief Provides read only access to a subclass of `BinaryStream`. Provides +/// Provides read only access to a subclass of `BinaryStream`. Provides /// bounds checking and helpers for writing certain common data types such as /// null-terminated strings, integers in various flavors of endianness, etc. /// Can be subclassed to provide reading of custom datatypes, although no diff --git a/contrib/llvm/include/llvm/Support/BinaryStreamRef.h b/contrib/llvm/include/llvm/Support/BinaryStreamRef.h index 5cf355be6fe9..d8dc1392c01c 100644 --- a/contrib/llvm/include/llvm/Support/BinaryStreamRef.h +++ b/contrib/llvm/include/llvm/Support/BinaryStreamRef.h @@ -147,7 +147,7 @@ protected: Optional<uint32_t> Length; }; -/// \brief BinaryStreamRef is to BinaryStream what ArrayRef is to an Array. It +/// BinaryStreamRef is to BinaryStream what ArrayRef is to an Array. It /// provides copy-semantics and read only access to a "window" of the underlying /// BinaryStream. Note that BinaryStreamRef is *not* a BinaryStream. That is to /// say, it does not inherit and override the methods of BinaryStream. In @@ -266,7 +266,7 @@ public: /// Conver this WritableBinaryStreamRef to a read-only BinaryStreamRef. operator BinaryStreamRef() const; - /// \brief For buffered streams, commits changes to the backing store. + /// For buffered streams, commits changes to the backing store. Error commit(); }; diff --git a/contrib/llvm/include/llvm/Support/BinaryStreamWriter.h b/contrib/llvm/include/llvm/Support/BinaryStreamWriter.h index a4495a1ce27d..6e8a68a30474 100644 --- a/contrib/llvm/include/llvm/Support/BinaryStreamWriter.h +++ b/contrib/llvm/include/llvm/Support/BinaryStreamWriter.h @@ -24,7 +24,7 @@ namespace llvm { -/// \brief Provides write only access to a subclass of `WritableBinaryStream`. +/// Provides write only access to a subclass of `WritableBinaryStream`. /// Provides bounds checking and helpers for writing certain common data types /// such as null-terminated strings, integers in various flavors of endianness, /// etc. Can be subclassed to provide reading and writing of custom datatypes, @@ -56,7 +56,7 @@ public: /// otherwise returns an appropriate error code. Error writeBytes(ArrayRef<uint8_t> Buffer); - /// Write the the integer \p Value to the underlying stream in the + /// Write the integer \p Value to the underlying stream in the /// specified endianness. On success, updates the offset so that /// subsequent writes occur at the next unwritten position. /// @@ -80,7 +80,7 @@ public: return writeInteger<U>(static_cast<U>(Num)); } - /// Write the the string \p Str to the underlying stream followed by a null + /// Write the string \p Str to the underlying stream followed by a null /// terminator. On success, updates the offset so that subsequent writes /// occur at the next unwritten position. \p Str need not be null terminated /// on input. @@ -89,7 +89,7 @@ public: /// otherwise returns an appropriate error code. Error writeCString(StringRef Str); - /// Write the the string \p Str to the underlying stream without a null + /// Write the string \p Str to the underlying stream without a null /// terminator. On success, updates the offset so that subsequent writes /// occur at the next unwritten position. /// diff --git a/contrib/llvm/include/llvm/Support/BlockFrequency.h b/contrib/llvm/include/llvm/Support/BlockFrequency.h index 2e75cbdd29c1..4b468f7acb32 100644 --- a/contrib/llvm/include/llvm/Support/BlockFrequency.h +++ b/contrib/llvm/include/llvm/Support/BlockFrequency.h @@ -28,32 +28,32 @@ class BlockFrequency { public: BlockFrequency(uint64_t Freq = 0) : Frequency(Freq) { } - /// \brief Returns the maximum possible frequency, the saturation value. + /// Returns the maximum possible frequency, the saturation value. static uint64_t getMaxFrequency() { return -1ULL; } - /// \brief Returns the frequency as a fixpoint number scaled by the entry + /// Returns the frequency as a fixpoint number scaled by the entry /// frequency. uint64_t getFrequency() const { return Frequency; } - /// \brief Multiplies with a branch probability. The computation will never + /// Multiplies with a branch probability. The computation will never /// overflow. BlockFrequency &operator*=(BranchProbability Prob); BlockFrequency operator*(BranchProbability Prob) const; - /// \brief Divide by a non-zero branch probability using saturating + /// Divide by a non-zero branch probability using saturating /// arithmetic. BlockFrequency &operator/=(BranchProbability Prob); BlockFrequency operator/(BranchProbability Prob) const; - /// \brief Adds another block frequency using saturating arithmetic. + /// Adds another block frequency using saturating arithmetic. BlockFrequency &operator+=(BlockFrequency Freq); BlockFrequency operator+(BlockFrequency Freq) const; - /// \brief Subtracts another block frequency using saturating arithmetic. + /// Subtracts another block frequency using saturating arithmetic. BlockFrequency &operator-=(BlockFrequency Freq); BlockFrequency operator-(BlockFrequency Freq) const; - /// \brief Shift block frequency to the right by count digits saturating to 1. + /// Shift block frequency to the right by count digits saturating to 1. BlockFrequency &operator>>=(const unsigned count); bool operator<(BlockFrequency RHS) const { diff --git a/contrib/llvm/include/llvm/Support/BranchProbability.h b/contrib/llvm/include/llvm/Support/BranchProbability.h index b403d7fbf117..3a88e71c2480 100644 --- a/contrib/llvm/include/llvm/Support/BranchProbability.h +++ b/contrib/llvm/include/llvm/Support/BranchProbability.h @@ -73,7 +73,7 @@ public: void dump() const; - /// \brief Scale a large integer. + /// Scale a large integer. /// /// Scales \c Num. Guarantees full precision. Returns the floor of the /// result. @@ -81,7 +81,7 @@ public: /// \return \c Num times \c this. uint64_t scale(uint64_t Num) const; - /// \brief Scale a large integer by the inverse. + /// Scale a large integer by the inverse. /// /// Scales \c Num by the inverse of \c this. Guarantees full precision. /// Returns the floor of the result. diff --git a/contrib/llvm/include/llvm/Support/CachePruning.h b/contrib/llvm/include/llvm/Support/CachePruning.h index 327c7df4570f..cf3f8ec67a52 100644 --- a/contrib/llvm/include/llvm/Support/CachePruning.h +++ b/contrib/llvm/include/llvm/Support/CachePruning.h @@ -37,7 +37,7 @@ struct CachePruningPolicy { std::chrono::seconds Expiration = std::chrono::hours(7 * 24); // 1w /// The maximum size for the cache directory, in terms of percentage of the - /// available space on the the disk. Set to 100 to indicate no limit, 50 to + /// available space on the disk. Set to 100 to indicate no limit, 50 to /// indicate that the cache size will not be left over half the available disk /// space. A value over 100 will be reduced to 100. A value of 0 disables the /// percentage size-based pruning. @@ -52,9 +52,11 @@ struct CachePruningPolicy { /// the number of files based pruning. /// /// This defaults to 1000000 because with that many files there are - /// diminishing returns on the effectiveness of the cache, and some file - /// systems have a limit on how many files can be contained in a directory - /// (notably ext4, which is limited to around 6000000 files). + /// diminishing returns on the effectiveness of the cache. Some systems have a + /// limit on total number of files, and some also limit the number of files + /// per directory, such as Linux ext4, with the default setting (block size is + /// 4096 and large_dir disabled), there is a per-directory entry limit of + /// 508*510*floor(4096/(40+8))~=20M for average filename length of 40. uint64_t MaxSizeFiles = 1000000; }; @@ -66,7 +68,7 @@ struct CachePruningPolicy { Expected<CachePruningPolicy> parseCachePruningPolicy(StringRef PolicyStr); /// Peform pruning using the supplied policy, returns true if pruning -/// occured, i.e. if Policy.Interval was expired. +/// occurred, i.e. if Policy.Interval was expired. /// /// As a safeguard against data loss if the user specifies the wrong directory /// as their cache directory, this function will ignore files not matching the diff --git a/contrib/llvm/include/llvm/Support/Casting.h b/contrib/llvm/include/llvm/Support/Casting.h index baa2a814e9a1..3f21e0f9ebc3 100644 --- a/contrib/llvm/include/llvm/Support/Casting.h +++ b/contrib/llvm/include/llvm/Support/Casting.h @@ -60,7 +60,7 @@ struct isa_impl { } }; -/// \brief Always allow upcasts, and perform no dynamic check for them. +/// Always allow upcasts, and perform no dynamic check for them. template <typename To, typename From> struct isa_impl< To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> { diff --git a/contrib/llvm/include/llvm/Support/CheckedArithmetic.h b/contrib/llvm/include/llvm/Support/CheckedArithmetic.h new file mode 100644 index 000000000000..039c374136ff --- /dev/null +++ b/contrib/llvm/include/llvm/Support/CheckedArithmetic.h @@ -0,0 +1,104 @@ +//==-- llvm/Support/CheckedArithmetic.h - Safe arithmetical operations *- 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 generic functions for operating on integers which +// give the indication on whether the operation has overflown. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CHECKEDARITHMETIC_H +#define LLVM_SUPPORT_CHECKEDARITHMETIC_H + +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/Optional.h" + +#include <type_traits> + +namespace { + +/// Utility function to apply a given method of \c APInt \p F to \p LHS and +/// \p RHS. +/// \return Empty optional if the operation overflows, or result otherwise. +template <typename T, typename F> +typename std::enable_if<std::is_integral<T>::value && sizeof(T) * 8 <= 64, + llvm::Optional<T>>::type +checkedOp(T LHS, T RHS, F Op, bool Signed = true) { + llvm::APInt ALHS(/*BitSize=*/sizeof(T) * 8, LHS, Signed); + llvm::APInt ARHS(/*BitSize=*/sizeof(T) * 8, RHS, Signed); + bool Overflow; + llvm::APInt Out = (ALHS.*Op)(ARHS, Overflow); + if (Overflow) + return llvm::None; + return Signed ? Out.getSExtValue() : Out.getZExtValue(); +} +} + +namespace llvm { + +/// Add two signed integers \p LHS and \p RHS. +/// \return Optional of sum if no signed overflow occurred, +/// \c None otherwise. +template <typename T> +typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type +checkedAdd(T LHS, T RHS) { + return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov); +} + +/// Multiply two signed integers \p LHS and \p RHS. +/// \return Optional of product if no signed overflow occurred, +/// \c None otherwise. +template <typename T> +typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type +checkedMul(T LHS, T RHS) { + return checkedOp(LHS, RHS, &llvm::APInt::smul_ov); +} + +/// Multiply A and B, and add C to the resulting product. +/// \return Optional of result if no signed overflow occurred, +/// \c None otherwise. +template <typename T> +typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type +checkedMulAdd(T A, T B, T C) { + if (auto Product = checkedMul(A, B)) + return checkedAdd(*Product, C); + return llvm::None; +} + +/// Add two unsigned integers \p LHS and \p RHS. +/// \return Optional of sum if no unsigned overflow occurred, +/// \c None otherwise. +template <typename T> +typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type +checkedAddUnsigned(T LHS, T RHS) { + return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, /*Signed=*/false); +} + +/// Multiply two unsigned integers \p LHS and \p RHS. +/// \return Optional of product if no unsigned overflow occurred, +/// \c None otherwise. +template <typename T> +typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type +checkedMulUnsigned(T LHS, T RHS) { + return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, /*Signed=*/false); +} + +/// Multiply unsigned integers A and B, and add C to the resulting product. +/// \return Optional of result if no unsigned overflow occurred, +/// \c None otherwise. +template <typename T> +typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type +checkedMulAddUnsigned(T A, T B, T C) { + if (auto Product = checkedMulUnsigned(A, B)) + return checkedAddUnsigned(*Product, C); + return llvm::None; +} + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/include/llvm/Support/CodeGenCoverage.h b/contrib/llvm/include/llvm/Support/CodeGenCoverage.h index d5bd837bff28..c863be35b822 100644 --- a/contrib/llvm/include/llvm/Support/CodeGenCoverage.h +++ b/contrib/llvm/include/llvm/Support/CodeGenCoverage.h @@ -23,15 +23,18 @@ protected: BitVector RuleCoverage; public: + using const_covered_iterator = BitVector::const_set_bits_iterator; + CodeGenCoverage(); void setCovered(uint64_t RuleID); - bool isCovered(uint64_t RuleID); + bool isCovered(uint64_t RuleID) const; + iterator_range<const_covered_iterator> covered() const; bool parse(MemoryBuffer &Buffer, StringRef BackendName); bool emit(StringRef FilePrefix, StringRef BackendName) const; void reset(); }; -} // end namespace llvm +} // namespace llvm #endif // ifndef LLVM_SUPPORT_CODEGENCOVERAGE_H diff --git a/contrib/llvm/include/llvm/Support/CommandLine.h b/contrib/llvm/include/llvm/Support/CommandLine.h index f043c112861b..799b41fbf8b0 100644 --- a/contrib/llvm/include/llvm/Support/CommandLine.h +++ b/contrib/llvm/include/llvm/Support/CommandLine.h @@ -30,6 +30,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" #include <cassert> #include <climits> #include <cstddef> @@ -94,7 +95,7 @@ void PrintOptionValues(); // Forward declaration - AddLiteralOption needs to be up here to make gcc happy. class Option; -/// \brief Adds a new option for parsing and provides the option it refers to. +/// Adds a new option for parsing and provides the option it refers to. /// /// \param O pointer to the option /// \param Name the string name for the option to handle during parsing @@ -362,7 +363,10 @@ public: bool MultiArg = false); // Prints option name followed by message. Always returns true. - bool error(const Twine &Message, StringRef ArgName = StringRef()); + bool error(const Twine &Message, StringRef ArgName = StringRef(), raw_ostream &Errs = llvm::errs()); + bool error(const Twine &Message, raw_ostream &Errs) { + return error(Message, StringRef(), Errs); + } inline int getNumOccurrences() const { return NumOccurrences; } inline void reset() { NumOccurrences = 0; } @@ -1770,7 +1774,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false); // Public interface for accessing registered options. // -/// \brief Use this to get a StringMap to all registered named options +/// Use this to get a StringMap to all registered named options /// (e.g. -help). Note \p Map Should be an empty StringMap. /// /// \return A reference to the StringMap used by the cl APIs to parse options. @@ -1799,7 +1803,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false); /// than just handing around a global list. StringMap<Option *> &getRegisteredOptions(SubCommand &Sub = *TopLevelSubCommand); -/// \brief Use this to get all registered SubCommands from the provided parser. +/// Use this to get all registered SubCommands from the provided parser. /// /// \return A range of all SubCommand pointers registered with the parser. /// @@ -1825,7 +1829,7 @@ getRegisteredSubcommands(); // Standalone command line processing utilities. // -/// \brief Tokenizes a command line that can contain escapes and quotes. +/// Tokenizes a command line that can contain escapes and quotes. // /// The quoting rules match those used by GCC and other tools that use /// libiberty's buildargv() or expandargv() utilities, and do not match bash. @@ -1841,7 +1845,7 @@ void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver, SmallVectorImpl<const char *> &NewArgv, bool MarkEOLs = false); -/// \brief Tokenizes a Windows command line which may contain quotes and escaped +/// Tokenizes a Windows command line which may contain quotes and escaped /// quotes. /// /// See MSDN docs for CommandLineToArgvW for information on the quoting rules. @@ -1856,7 +1860,7 @@ void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver, SmallVectorImpl<const char *> &NewArgv, bool MarkEOLs = false); -/// \brief String tokenization function type. Should be compatible with either +/// String tokenization function type. Should be compatible with either /// Windows or Unix command line tokenizers. using TokenizerCallback = void (*)(StringRef Source, StringSaver &Saver, SmallVectorImpl<const char *> &NewArgv, @@ -1889,7 +1893,7 @@ void tokenizeConfigFile(StringRef Source, StringSaver &Saver, bool readConfigFile(StringRef CfgFileName, StringSaver &Saver, SmallVectorImpl<const char *> &Argv); -/// \brief Expand response files on a command line recursively using the given +/// Expand response files on a command line recursively using the given /// StringSaver and tokenization strategy. Argv should contain the command line /// before expansion and will be modified in place. If requested, Argv will /// also be populated with nullptrs indicating where each response file line @@ -1909,7 +1913,7 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl<const char *> &Argv, bool MarkEOLs = false, bool RelativeNames = false); -/// \brief Mark all options not part of this category as cl::ReallyHidden. +/// Mark all options not part of this category as cl::ReallyHidden. /// /// \param Category the category of options to keep displaying /// @@ -1919,7 +1923,7 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, void HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub = *TopLevelSubCommand); -/// \brief Mark all options not part of the categories as cl::ReallyHidden. +/// Mark all options not part of the categories as cl::ReallyHidden. /// /// \param Categories the categories of options to keep displaying. /// @@ -1929,12 +1933,12 @@ void HideUnrelatedOptions(cl::OptionCategory &Category, void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories, SubCommand &Sub = *TopLevelSubCommand); -/// \brief Reset all command line options to a state that looks as if they have +/// Reset all command line options to a state that looks as if they have /// never appeared on the command line. This is useful for being able to parse /// a command line multiple times (especially useful for writing tests). void ResetAllOptionOccurrences(); -/// \brief Reset the command line parser back to its initial state. This +/// Reset the command line parser back to its initial state. This /// removes /// all options, categories, and subcommands and returns the parser to a state /// where no options are supported. diff --git a/contrib/llvm/include/llvm/Support/Compiler.h b/contrib/llvm/include/llvm/Support/Compiler.h index b19e37235df5..4de815fe61d7 100644 --- a/contrib/llvm/include/llvm/Support/Compiler.h +++ b/contrib/llvm/include/llvm/Support/Compiler.h @@ -17,6 +17,9 @@ #include "llvm/Config/llvm-config.h" +#include <new> +#include <stddef.h> + #if defined(_MSC_VER) #include <sal.h> #endif @@ -42,7 +45,7 @@ #endif /// \macro LLVM_GNUC_PREREQ -/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't +/// Extend the default __GNUC_PREREQ even if glibc's features.h isn't /// available. #ifndef LLVM_GNUC_PREREQ # if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) @@ -58,7 +61,7 @@ #endif /// \macro LLVM_MSC_PREREQ -/// \brief Is the compiler MSVC of at least the specified version? +/// Is the compiler MSVC of at least the specified version? /// The common \param version values to check for are: /// * 1900: Microsoft Visual Studio 2015 / 14.0 #ifdef _MSC_VER @@ -73,7 +76,7 @@ #define LLVM_MSC_PREREQ(version) 0 #endif -/// \brief Does the compiler support ref-qualifiers for *this? +/// Does the compiler support ref-qualifiers for *this? /// /// Sadly, this is separate from just rvalue reference support because GCC /// and MSVC implemented this later than everything else. @@ -99,7 +102,7 @@ /// functions, making them private to any shared library they are linked into. /// On PE/COFF targets, library visibility is the default, so this isn't needed. #if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ - !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32) + !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32) #define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) #else #define LLVM_LIBRARY_VISIBILITY @@ -146,7 +149,7 @@ // FIXME: Provide this for PE/COFF targets. #if (__has_attribute(weak) || LLVM_GNUC_PREREQ(4, 0, 0)) && \ - (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)) + (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32)) #define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__)) #else #define LLVM_ATTRIBUTE_WEAK @@ -303,7 +306,7 @@ #endif /// \macro LLVM_ASSUME_ALIGNED -/// \brief Returns a pointer with an assumed alignment. +/// Returns a pointer with an assumed alignment. #if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0) # define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) #elif defined(LLVM_BUILTIN_UNREACHABLE) @@ -315,7 +318,7 @@ #endif /// \macro LLVM_ALIGNAS -/// \brief Used to specify a minimum alignment for a structure or variable. +/// Used to specify a minimum alignment for a structure or variable. #if __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 1) # define LLVM_ALIGNAS(x) __attribute__((aligned(x))) #else @@ -323,7 +326,7 @@ #endif /// \macro LLVM_PACKED -/// \brief Used to specify a packed structure. +/// Used to specify a packed structure. /// LLVM_PACKED( /// struct A { /// int i; @@ -351,7 +354,7 @@ #endif /// \macro LLVM_PTR_SIZE -/// \brief A constant integer equivalent to the value of sizeof(void*). +/// A constant integer equivalent to the value of sizeof(void*). /// Generally used in combination with LLVM_ALIGNAS or when doing computation in /// the preprocessor. #ifdef __SIZEOF_POINTER__ @@ -367,7 +370,7 @@ #endif /// \macro LLVM_MEMORY_SANITIZER_BUILD -/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. +/// Whether LLVM itself is built with MemorySanitizer instrumentation. #if __has_feature(memory_sanitizer) # define LLVM_MEMORY_SANITIZER_BUILD 1 # include <sanitizer/msan_interface.h> @@ -378,7 +381,7 @@ #endif /// \macro LLVM_ADDRESS_SANITIZER_BUILD -/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation. +/// Whether LLVM itself is built with AddressSanitizer instrumentation. #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) # define LLVM_ADDRESS_SANITIZER_BUILD 1 # include <sanitizer/asan_interface.h> @@ -389,7 +392,7 @@ #endif /// \macro LLVM_THREAD_SANITIZER_BUILD -/// \brief Whether LLVM itself is built with ThreadSanitizer instrumentation. +/// Whether LLVM itself is built with ThreadSanitizer instrumentation. #if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__) # define LLVM_THREAD_SANITIZER_BUILD 1 #else @@ -432,14 +435,14 @@ void AnnotateIgnoreWritesEnd(const char *file, int line); #endif /// \macro LLVM_NO_SANITIZE -/// \brief Disable a particular sanitizer for a function. +/// Disable a particular sanitizer for a function. #if __has_attribute(no_sanitize) #define LLVM_NO_SANITIZE(KIND) __attribute__((no_sanitize(KIND))) #else #define LLVM_NO_SANITIZE(KIND) #endif -/// \brief Mark debug helper function definitions like dump() that should not be +/// Mark debug helper function definitions like dump() that should not be /// stripped from debug builds. /// Note that you should also surround dump() functions with /// `#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)` so they do always @@ -452,7 +455,7 @@ void AnnotateIgnoreWritesEnd(const char *file, int line); #endif /// \macro LLVM_PRETTY_FUNCTION -/// \brief Gets a user-friendly looking function signature for the current scope +/// Gets a user-friendly looking function signature for the current scope /// using the best available method on each platform. The exact format of the /// resulting string is implementation specific and non-portable, so this should /// only be used, for example, for logging or diagnostics. @@ -465,7 +468,7 @@ void AnnotateIgnoreWritesEnd(const char *file, int line); #endif /// \macro LLVM_THREAD_LOCAL -/// \brief A thread-local storage specifier which can be used with globals, +/// A thread-local storage specifier which can be used with globals, /// extern globals, and static globals. /// /// This is essentially an extremely restricted analog to C++11's thread_local @@ -494,7 +497,7 @@ void AnnotateIgnoreWritesEnd(const char *file, int line); #endif /// \macro LLVM_ENABLE_EXCEPTIONS -/// \brief Whether LLVM is built with exception support. +/// Whether LLVM is built with exception support. #if __has_feature(cxx_exceptions) #define LLVM_ENABLE_EXCEPTIONS 1 #elif defined(__GNUC__) && defined(__EXCEPTIONS) @@ -503,4 +506,46 @@ void AnnotateIgnoreWritesEnd(const char *file, int line); #define LLVM_ENABLE_EXCEPTIONS 1 #endif +namespace llvm { + +/// Allocate a buffer of memory with the given size and alignment. +/// +/// When the compiler supports aligned operator new, this will use it to to +/// handle even over-aligned allocations. +/// +/// However, this doesn't make any attempt to leverage the fancier techniques +/// like posix_memalign due to portability. It is mostly intended to allow +/// compatibility with platforms that, after aligned allocation was added, use +/// reduced default alignment. +inline void *allocate_buffer(size_t Size, size_t Alignment) { + return ::operator new(Size +#if __cpp_aligned_new + , + std::align_val_t(Alignment) +#endif + ); +} + +/// Deallocate a buffer of memory with the given size and alignment. +/// +/// If supported, this will used the sized delete operator. Also if supported, +/// this will pass the alignment to the delete operator. +/// +/// The pointer must have been allocated with the corresponding new operator, +/// most likely using the above helper. +inline void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) { + ::operator delete(Ptr +#if __cpp_sized_deallocation + , + Size +#endif +#if __cpp_aligned_new + , + std::align_val_t(Alignment) +#endif + ); +} + +} // End namespace llvm + #endif diff --git a/contrib/llvm/include/llvm/Support/ConvertUTF.h b/contrib/llvm/include/llvm/Support/ConvertUTF.h index 99ae171aeabb..6ae56c2470bb 100644 --- a/contrib/llvm/include/llvm/Support/ConvertUTF.h +++ b/contrib/llvm/include/llvm/Support/ConvertUTF.h @@ -92,6 +92,7 @@ #include <cstddef> #include <string> +#include <system_error> // Wrap everything in namespace llvm so that programs can link with llvm and // their own version of the unicode libraries. @@ -286,6 +287,21 @@ bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out); bool convertUTF8ToUTF16String(StringRef SrcUTF8, SmallVectorImpl<UTF16> &DstUTF16); +#if defined(_WIN32) +namespace sys { +namespace windows { +std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16); +/// Convert to UTF16 from the current code page used in the system +std::error_code CurCPToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16); +std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len, + SmallVectorImpl<char> &utf8); +/// Convert from UTF16 to the current code page used in the system +std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len, + SmallVectorImpl<char> &utf8); +} // namespace windows +} // namespace sys +#endif + } /* end namespace llvm */ #endif diff --git a/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h b/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h index 6cbc331d2731..7b3fd4f882e4 100644 --- a/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h +++ b/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h @@ -15,7 +15,7 @@ namespace llvm { class CrashRecoveryContextCleanup; -/// \brief Crash recovery helper object. +/// Crash recovery helper object. /// /// This class implements support for running operations in a safe context so /// that crashes (memory errors, stack overflow, assertion violations) can be @@ -27,6 +27,7 @@ class CrashRecoveryContextCleanup; /// CrashRecoveryContext::Enable(), and then executing unsafe operations via a /// CrashRecoveryContext object. For example: /// +/// \code /// void actual_work(void *); /// /// void foo() { @@ -38,6 +39,11 @@ class CrashRecoveryContextCleanup; /// /// ... no crash was detected ... /// } +/// \endcode +/// +/// To assist recovery the class allows specifying set of actions that will be +/// executed in any case, whether crash occurs or not. These actions may be used +/// to reclaim resources in the case of crash. class CrashRecoveryContext { void *Impl; CrashRecoveryContextCleanup *head; @@ -46,24 +52,27 @@ public: CrashRecoveryContext() : Impl(nullptr), head(nullptr) {} ~CrashRecoveryContext(); + /// Register cleanup handler, which is used when the recovery context is + /// finished. + /// The recovery context owns the handler. void registerCleanup(CrashRecoveryContextCleanup *cleanup); + void unregisterCleanup(CrashRecoveryContextCleanup *cleanup); - /// \brief Enable crash recovery. + /// Enable crash recovery. static void Enable(); - /// \brief Disable crash recovery. + /// Disable crash recovery. static void Disable(); - /// \brief Return the active context, if the code is currently executing in a + /// Return the active context, if the code is currently executing in a /// thread which is in a protected context. static CrashRecoveryContext *GetCurrent(); - /// \brief Return true if the current thread is recovering from a - /// crash. + /// Return true if the current thread is recovering from a crash. static bool isRecoveringFromCrash(); - /// \brief Execute the provide callback function (with the given arguments) in + /// Execute the provided callback function (with the given arguments) in /// a protected context. /// /// \return True if the function completed successfully, and false if the @@ -75,7 +84,7 @@ public: return RunSafely([&]() { Fn(UserData); }); } - /// \brief Execute the provide callback function (with the given arguments) in + /// Execute the provide callback function (with the given arguments) in /// a protected context which is run in another thread (optionally with a /// requested stack size). /// @@ -89,11 +98,18 @@ public: return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize); } - /// \brief Explicitly trigger a crash recovery in the current process, and + /// Explicitly trigger a crash recovery in the current process, and /// return failure from RunSafely(). This function does not return. void HandleCrash(); }; +/// Abstract base class of cleanup handlers. +/// +/// Derived classes override method recoverResources, which makes actual work on +/// resource recovery. +/// +/// Cleanup handlers are stored in a double list, which is owned and managed by +/// a crash recovery context. class CrashRecoveryContextCleanup { protected: CrashRecoveryContext *context; @@ -115,7 +131,18 @@ private: CrashRecoveryContextCleanup *prev, *next; }; -template<typename DERIVED, typename T> +/// Base class of cleanup handler that controls recovery of resources of the +/// given type. +/// +/// \tparam Derived Class that uses this class as a base. +/// \tparam T Type of controlled resource. +/// +/// This class serves as a base for its template parameter as implied by +/// Curiously Recurring Template Pattern. +/// +/// This class factors out creation of a cleanup handler. The latter requires +/// knowledge of the current recovery context, which is provided by this class. +template<typename Derived, typename T> class CrashRecoveryContextCleanupBase : public CrashRecoveryContextCleanup { protected: T *resource; @@ -123,15 +150,20 @@ protected: : CrashRecoveryContextCleanup(context), resource(resource) {} public: - static DERIVED *create(T *x) { + /// Creates cleanup handler. + /// \param x Pointer to the resource recovered by this handler. + /// \return New handler or null if the method was called outside a recovery + /// context. + static Derived *create(T *x) { if (x) { if (CrashRecoveryContext *context = CrashRecoveryContext::GetCurrent()) - return new DERIVED(context, x); + return new Derived(context, x); } return nullptr; } }; +/// Cleanup handler that reclaims resource by calling destructor on it. template <typename T> class CrashRecoveryContextDestructorCleanup : public CrashRecoveryContextCleanupBase<CrashRecoveryContextDestructorCleanup<T>, T> { @@ -146,6 +178,7 @@ public: } }; +/// Cleanup handler that reclaims resource by calling 'delete' on it. template <typename T> class CrashRecoveryContextDeleteCleanup : public CrashRecoveryContextCleanupBase<CrashRecoveryContextDeleteCleanup<T>, T> { @@ -157,10 +190,10 @@ public: void recoverResources() override { delete this->resource; } }; +/// Cleanup handler that reclaims resource by calling its method 'Release'. template <typename T> class CrashRecoveryContextReleaseRefCleanup : public - CrashRecoveryContextCleanupBase<CrashRecoveryContextReleaseRefCleanup<T>, T> -{ + CrashRecoveryContextCleanupBase<CrashRecoveryContextReleaseRefCleanup<T>, T> { public: CrashRecoveryContextReleaseRefCleanup(CrashRecoveryContext *context, T *resource) @@ -170,6 +203,37 @@ public: void recoverResources() override { this->resource->Release(); } }; +/// Helper class for managing resource cleanups. +/// +/// \tparam T Type of resource been reclaimed. +/// \tparam Cleanup Class that defines how the resource is reclaimed. +/// +/// Clients create objects of this type in the code executed in a crash recovery +/// context to ensure that the resource will be reclaimed even in the case of +/// crash. For example: +/// +/// \code +/// void actual_work(void *) { +/// ... +/// std::unique_ptr<Resource> R(new Resource()); +/// CrashRecoveryContextCleanupRegistrar D(R.get()); +/// ... +/// } +/// +/// void foo() { +/// CrashRecoveryContext CRC; +/// +/// if (!CRC.RunSafely(actual_work, 0)) { +/// ... a crash was detected, report error to user ... +/// } +/// \endcode +/// +/// If the code of `actual_work` in the example above does not crash, the +/// destructor of CrashRecoveryContextCleanupRegistrar removes cleanup code from +/// the current CrashRecoveryContext and the resource is reclaimed by the +/// destructor of std::unique_ptr. If crash happens, destructors are not called +/// and the resource is reclaimed by cleanup object registered in the recovery +/// context by the constructor of CrashRecoveryContextCleanupRegistrar. template <typename T, typename Cleanup = CrashRecoveryContextDeleteCleanup<T> > class CrashRecoveryContextCleanupRegistrar { CrashRecoveryContextCleanup *cleanup; diff --git a/contrib/llvm/include/llvm/Support/DJB.h b/contrib/llvm/include/llvm/Support/DJB.h new file mode 100644 index 000000000000..e03111473362 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/DJB.h @@ -0,0 +1,33 @@ +//===-- llvm/Support/DJB.h ---DJB Hash --------------------------*- 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 the DJ Bernstein hash function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DJB_H +#define LLVM_SUPPORT_DJB_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +/// The Bernstein hash function used by the DWARF accelerator tables. +inline uint32_t djbHash(StringRef Buffer, uint32_t H = 5381) { + for (unsigned char C : Buffer.bytes()) + H = (H << 5) + H + C; + return H; +} + +/// Computes the Bernstein hash after folding the input according to the Dwarf 5 +/// standard case folding rules. +uint32_t caseFoldingDjbHash(StringRef Buffer, uint32_t H = 5381); +} // namespace llvm + +#endif // LLVM_SUPPORT_DJB_H diff --git a/contrib/llvm/include/llvm/Support/DataExtractor.h b/contrib/llvm/include/llvm/Support/DataExtractor.h index 31447882a919..3a6ada6c77df 100644 --- a/contrib/llvm/include/llvm/Support/DataExtractor.h +++ b/contrib/llvm/include/llvm/Support/DataExtractor.h @@ -51,13 +51,13 @@ public: DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize) : Data(Data), IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {} - /// \brief Get the data pointed to by this extractor. + /// Get the data pointed to by this extractor. StringRef getData() const { return Data; } - /// \brief Get the endianness for this extractor. + /// Get the endianness for this extractor. bool isLittleEndian() const { return IsLittleEndian; } - /// \brief Get the address size for this extractor. + /// Get the address size for this extractor. uint8_t getAddressSize() const { return AddressSize; } - /// \brief Set the address size for this extractor. + /// Set the address size for this extractor. void setAddressSize(uint8_t Size) { AddressSize = Size; } /// Extract a C string from \a *offset_ptr. diff --git a/contrib/llvm/include/llvm/Support/DataTypes.h b/contrib/llvm/include/llvm/Support/DataTypes.h new file mode 100644 index 000000000000..ad60a5b3f300 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/DataTypes.h @@ -0,0 +1,17 @@ +//===-- llvm/Support/DataTypes.h - Define fixed size types ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Due to layering constraints (Support depends on llvm-c) this is a thin +// wrapper around the implementation that lives in llvm-c, though most clients +// can/should think of this as being provided by Support for simplicity (not +// many clients are aware of their dependency on llvm-c). +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/DataTypes.h" diff --git a/contrib/llvm/include/llvm/Support/Debug.h b/contrib/llvm/include/llvm/Support/Debug.h index 48e9e1bc167d..980abfb0e8da 100644 --- a/contrib/llvm/include/llvm/Support/Debug.h +++ b/contrib/llvm/include/llvm/Support/Debug.h @@ -11,17 +11,18 @@ // code, without it being enabled all of the time, and without having to add // command line options to enable it. // -// In particular, just wrap your code with the DEBUG() macro, and it will be -// enabled automatically if you specify '-debug' on the command-line. -// DEBUG() requires the DEBUG_TYPE macro to be defined. Set it to "foo" specify -// that your debug code belongs to class "foo". Be careful that you only do -// this after including Debug.h and not around any #include of headers. Headers -// should define and undef the macro acround the code that needs to use the -// DEBUG() macro. Then, on the command line, you can specify '-debug-only=foo' -// to enable JUST the debug information for the foo class. +// In particular, just wrap your code with the LLVM_DEBUG() macro, and it will +// be enabled automatically if you specify '-debug' on the command-line. +// LLVM_DEBUG() requires the DEBUG_TYPE macro to be defined. Set it to "foo" +// specify that your debug code belongs to class "foo". Be careful that you only +// do this after including Debug.h and not around any #include of headers. +// Headers should define and undef the macro acround the code that needs to use +// the LLVM_DEBUG() macro. Then, on the command line, you can specify +// '-debug-only=foo' to enable JUST the debug information for the foo class. // // When compiling without assertions, the -debug-* options and all code in -// DEBUG() statements disappears, so it does not affect the runtime of the code. +// LLVM_DEBUG() statements disappears, so it does not affect the runtime of the +// code. // //===----------------------------------------------------------------------===// @@ -113,9 +114,9 @@ raw_ostream &dbgs(); // debug build, then the code specified as the option to the macro will be // executed. Otherwise it will not be. Example: // -// DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n"); +// LLVM_DEBUG(dbgs() << "Bitset contains: " << Bitset << "\n"); // -#define DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X) +#define LLVM_DEBUG(X) DEBUG_WITH_TYPE(DEBUG_TYPE, X) } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Support/DebugCounter.h b/contrib/llvm/include/llvm/Support/DebugCounter.h index 52e1bd71a2f2..250fc6bb1f5c 100644 --- a/contrib/llvm/include/llvm/Support/DebugCounter.h +++ b/contrib/llvm/include/llvm/Support/DebugCounter.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// /// \file -/// \brief This file provides an implementation of debug counters. Debug +/// This file provides an implementation of debug counters. Debug /// counters are a tool that let you narrow down a miscompilation to a specific /// thing happening. /// @@ -55,7 +55,7 @@ namespace llvm { class DebugCounter { public: - /// \brief Returns a reference to the singleton instance. + /// Returns a reference to the singleton instance. static DebugCounter &instance(); // Used by the command line option parser to push a new value it parsed. @@ -77,23 +77,19 @@ public: auto &Us = instance(); auto Result = Us.Counters.find(CounterName); if (Result != Us.Counters.end()) { - auto &CounterPair = Result->second; - // We only execute while the skip (first) is zero and the count (second) - // is non-zero. + auto &CounterInfo = Result->second; + ++CounterInfo.Count; + + // We only execute while the Skip is not smaller than Count, + // and the StopAfter + Skip is larger than Count. // Negative counters always execute. - if (CounterPair.first < 0) + if (CounterInfo.Skip < 0) return true; - if (CounterPair.first != 0) { - --CounterPair.first; + if (CounterInfo.Skip >= CounterInfo.Count) return false; - } - if (CounterPair.second < 0) - return true; - if (CounterPair.second != 0) { - --CounterPair.second; + if (CounterInfo.StopAfter < 0) return true; - } - return false; + return CounterInfo.StopAfter + CounterInfo.Skip >= CounterInfo.Count; } // Didn't find the counter, should we warn? return true; @@ -104,21 +100,21 @@ public: // the command line). This will return true even if those values are // currently in a state where the counter will always execute. static bool isCounterSet(unsigned ID) { - return instance().Counters.count(ID); + return instance().Counters[ID].IsSet; } - // Return the skip and count for a counter. This only works for set counters. - static std::pair<int, int> getCounterValue(unsigned ID) { + // Return the Count for a counter. This only works for set counters. + static int64_t getCounterValue(unsigned ID) { auto &Us = instance(); auto Result = Us.Counters.find(ID); assert(Result != Us.Counters.end() && "Asking about a non-set counter"); - return Result->second; + return Result->second.Count; } - // Set a registered counter to a given value. - static void setCounterValue(unsigned ID, const std::pair<int, int> &Val) { + // Set a registered counter to a given Count value. + static void setCounterValue(unsigned ID, int64_t Count) { auto &Us = instance(); - Us.Counters[ID] = Val; + Us.Counters[ID].Count = Count; } // Dump or print the current counter set into llvm::dbgs(). @@ -136,7 +132,7 @@ public: // Return the name and description of the counter with the given ID. std::pair<std::string, std::string> getCounterInfo(unsigned ID) const { - return std::make_pair(RegisteredCounters[ID], CounterDesc.lookup(ID)); + return std::make_pair(RegisteredCounters[ID], Counters.lookup(ID).Desc); } // Iterate through the registered counters @@ -149,11 +145,19 @@ public: private: unsigned addCounter(const std::string &Name, const std::string &Desc) { unsigned Result = RegisteredCounters.insert(Name); - CounterDesc[Result] = Desc; + Counters[Result] = {}; + Counters[Result].Desc = Desc; return Result; } - DenseMap<unsigned, std::pair<long, long>> Counters; - DenseMap<unsigned, std::string> CounterDesc; + // Struct to store counter info. + struct CounterInfo { + int64_t Count = 0; + int64_t Skip = 0; + int64_t StopAfter = -1; + bool IsSet = false; + std::string Desc; + }; + DenseMap<unsigned, CounterInfo> Counters; CounterVector RegisteredCounters; }; diff --git a/contrib/llvm/include/llvm/Support/DynamicLibrary.h b/contrib/llvm/include/llvm/Support/DynamicLibrary.h index 469d5dfad062..9563b483f6d5 100644 --- a/contrib/llvm/include/llvm/Support/DynamicLibrary.h +++ b/contrib/llvm/include/llvm/Support/DynamicLibrary.h @@ -64,7 +64,7 @@ namespace sys { /// if the library fails to load. /// /// It is safe to call this function multiple times for the same library. - /// @brief Open a dynamic library permanently. + /// Open a dynamic library permanently. static DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg = nullptr); @@ -110,10 +110,10 @@ namespace sys { /// search permanently loaded libraries (getPermanentLibrary()) as well /// as explicitly registered symbols (AddSymbol()). /// @throws std::string on error. - /// @brief Search through libraries for address of a symbol + /// Search through libraries for address of a symbol static void *SearchForAddressOfSymbol(const char *symbolName); - /// @brief Convenience function for C++ophiles. + /// Convenience function for C++ophiles. static void *SearchForAddressOfSymbol(const std::string &symbolName) { return SearchForAddressOfSymbol(symbolName.c_str()); } @@ -121,7 +121,7 @@ namespace sys { /// This functions permanently adds the symbol \p symbolName with the /// value \p symbolValue. These symbols are searched before any /// libraries. - /// @brief Add searchable symbol/value pair. + /// Add searchable symbol/value pair. static void AddSymbol(StringRef symbolName, void *symbolValue); class HandleSet; diff --git a/contrib/llvm/include/llvm/Support/Endian.h b/contrib/llvm/include/llvm/Support/Endian.h index f50d9b502daf..a4d3f4ff793d 100644 --- a/contrib/llvm/include/llvm/Support/Endian.h +++ b/contrib/llvm/include/llvm/Support/Endian.h @@ -34,7 +34,7 @@ enum {aligned = 0, unaligned = 1}; namespace detail { -/// \brief ::value is either alignment, or alignof(T) if alignment is 0. +/// ::value is either alignment, or alignof(T) if alignment is 0. template<class T, int alignment> struct PickAlignment { enum { value = alignment == 0 ? alignof(T) : alignment }; diff --git a/contrib/llvm/include/llvm/Support/EndianStream.h b/contrib/llvm/include/llvm/Support/EndianStream.h index 43ecd4a5c97e..9742e253ad3e 100644 --- a/contrib/llvm/include/llvm/Support/EndianStream.h +++ b/contrib/llvm/include/llvm/Support/EndianStream.h @@ -23,44 +23,44 @@ 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(ArrayRef<value_type> Vals) { - for (value_type V : Vals) - write(V); - } - template <typename value_type> void write(value_type Val) { - Val = byte_swap<value_type, endian>(Val); - OS.write((const char *)&Val, sizeof(value_type)); - } -}; -template <> -template <> -inline void Writer<little>::write<float>(float Val) { - write(FloatToBits(Val)); +template <typename value_type> +inline void write(raw_ostream &os, value_type value, endianness endian) { + value = byte_swap<value_type>(value, endian); + os.write((const char *)&value, sizeof(value_type)); } template <> -template <> -inline void Writer<little>::write<double>(double Val) { - write(DoubleToBits(Val)); +inline void write<float>(raw_ostream &os, float value, endianness endian) { + write(os, FloatToBits(value), endian); } template <> -template <> -inline void Writer<big>::write<float>(float Val) { - write(FloatToBits(Val)); +inline void write<double>(raw_ostream &os, double value, + endianness endian) { + write(os, DoubleToBits(value), endian); } -template <> -template <> -inline void Writer<big>::write<double>(double Val) { - write(DoubleToBits(Val)); +template <typename value_type> +inline void write(raw_ostream &os, ArrayRef<value_type> vals, + endianness endian) { + for (value_type v : vals) + write(os, v, endian); } +/// Adapter to write values to a stream in a particular byte order. +struct Writer { + raw_ostream &OS; + endianness Endian; + Writer(raw_ostream &OS, endianness Endian) : OS(OS), Endian(Endian) {} + template <typename value_type> void write(ArrayRef<value_type> Val) { + endian::write(OS, Val, Endian); + } + template <typename value_type> void write(value_type Val) { + endian::write(OS, Val, Endian); + } +}; + } // end namespace endian } // end namespace support diff --git a/contrib/llvm/include/llvm/Support/Errc.h b/contrib/llvm/include/llvm/Support/Errc.h index 80bfe2ac2ee5..dce42782a0d3 100644 --- a/contrib/llvm/include/llvm/Support/Errc.h +++ b/contrib/llvm/include/llvm/Support/Errc.h @@ -63,6 +63,7 @@ enum class errc { no_such_process = int(std::errc::no_such_process), not_a_directory = int(std::errc::not_a_directory), not_enough_memory = int(std::errc::not_enough_memory), + not_supported = int(std::errc::not_supported), operation_not_permitted = int(std::errc::operation_not_permitted), permission_denied = int(std::errc::permission_denied), read_only_file_system = int(std::errc::read_only_file_system), diff --git a/contrib/llvm/include/llvm/Support/Errno.h b/contrib/llvm/include/llvm/Support/Errno.h index 35dc1ea7cf84..8069c3639df3 100644 --- a/contrib/llvm/include/llvm/Support/Errno.h +++ b/contrib/llvm/include/llvm/Support/Errno.h @@ -34,9 +34,10 @@ template <typename FailT, typename Fun, typename... Args> inline auto RetryAfterSignal(const FailT &Fail, const Fun &F, const Args &... As) -> decltype(F(As...)) { decltype(F(As...)) Res; - do + do { + errno = 0; Res = F(As...); - while (Res == Fail && errno == EINTR); + } while (Res == Fail && errno == EINTR); return Res; } diff --git a/contrib/llvm/include/llvm/Support/Error.h b/contrib/llvm/include/llvm/Support/Error.h index 8567af392fb0..8015cab45a06 100644 --- a/contrib/llvm/include/llvm/Support/Error.h +++ b/contrib/llvm/include/llvm/Support/Error.h @@ -24,6 +24,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -302,6 +303,14 @@ private: return Tmp; } + friend raw_ostream &operator<<(raw_ostream &OS, const Error &E) { + if (auto P = E.getPtr()) + P->log(OS); + else + OS << "success"; + return OS; + } + ErrorInfoBase *Payload = nullptr; }; @@ -421,7 +430,7 @@ template <class T> class LLVM_NODISCARD Expected { static const bool isRef = std::is_reference<T>::value; - using wrap = ReferenceStorage<typename std::remove_reference<T>::type>; + using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>; using error_type = std::unique_ptr<ErrorInfoBase>; @@ -505,7 +514,7 @@ public: getErrorStorage()->~error_type(); } - /// \brief Return false if there is an error. + /// Return false if there is an error. explicit operator bool() { #if LLVM_ENABLE_ABI_BREAKING_CHECKS Unchecked = HasError; @@ -513,24 +522,24 @@ public: return !HasError; } - /// \brief Returns a reference to the stored T value. + /// Returns a reference to the stored T value. reference get() { assertIsChecked(); return *getStorage(); } - /// \brief Returns a const reference to the stored T value. + /// Returns a const reference to the stored T value. const_reference get() const { assertIsChecked(); return const_cast<Expected<T> *>(this)->get(); } - /// \brief Check that this Expected<T> is an error of type ErrT. + /// Check that this Expected<T> is an error of type ErrT. template <typename ErrT> bool errorIsA() const { return HasError && (*getErrorStorage())->template isA<ErrT>(); } - /// \brief Take ownership of the stored error. + /// Take ownership of the stored error. /// After calling this the Expected<T> is in an indeterminate state that can /// only be safely destructed. No further calls (beside the destructor) should /// be made on the Expected<T> vaule. @@ -541,25 +550,25 @@ public: return HasError ? Error(std::move(*getErrorStorage())) : Error::success(); } - /// \brief Returns a pointer to the stored T value. + /// Returns a pointer to the stored T value. pointer operator->() { assertIsChecked(); return toPointer(getStorage()); } - /// \brief Returns a const pointer to the stored T value. + /// Returns a const pointer to the stored T value. const_pointer operator->() const { assertIsChecked(); return toPointer(getStorage()); } - /// \brief Returns a reference to the stored T value. + /// Returns a reference to the stored T value. reference operator*() { assertIsChecked(); return *getStorage(); } - /// \brief Returns a const reference to the stored T value. + /// Returns a const reference to the stored T value. const_reference operator*() const { assertIsChecked(); return *getStorage(); @@ -882,16 +891,16 @@ Error handleErrors(Error E, HandlerTs &&... Hs) { return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...); } -/// Behaves the same as handleErrors, except that it requires that all -/// errors be handled by the given handlers. If any unhandled error remains -/// after the handlers have run, report_fatal_error() will be called. +/// Behaves the same as handleErrors, except that by contract all errors +/// *must* be handled by the given handlers (i.e. there must be no remaining +/// errors after running the handlers, or llvm_unreachable is called). template <typename... HandlerTs> void handleAllErrors(Error E, HandlerTs &&... Handlers) { cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...)); } /// Check that E is a non-error, then drop it. -/// If E is an error report_fatal_error will be called. +/// If E is an error, llvm_unreachable will be called. inline void handleAllErrors(Error E) { cantFail(std::move(E)); } @@ -963,6 +972,18 @@ inline void consumeError(Error Err) { handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); } +/// Helper for converting an Error to a bool. +/// +/// This method returns true if Err is in an error state, or false if it is +/// in a success state. Puts Err in a checked state in both cases (unlike +/// Error::operator bool(), which only does this for success states). +inline bool errorToBool(Error Err) { + bool IsError = static_cast<bool>(Err); + if (IsError) + consumeError(std::move(Err)); + return IsError; +} + /// Helper for Errors used as out-parameters. /// /// This helper is for use with the Error-as-out-parameter idiom, where an error @@ -1101,6 +1122,18 @@ private: std::error_code EC; }; +/// Create formatted StringError object. +template <typename... Ts> +Error createStringError(std::error_code EC, char const *Fmt, + const Ts &... Vals) { + std::string Buffer; + raw_string_ostream Stream(Buffer); + Stream << format(Fmt, Vals...); + return make_error<StringError>(Stream.str(), EC); +} + +Error createStringError(std::error_code EC, char const *Msg); + /// Helper for check-and-exit error handling. /// /// For tool use only. NOT FOR USE IN LIBRARY CODE. diff --git a/contrib/llvm/include/llvm/Support/ErrorHandling.h b/contrib/llvm/include/llvm/Support/ErrorHandling.h index b45f6348390e..39cbfed2436a 100644 --- a/contrib/llvm/include/llvm/Support/ErrorHandling.h +++ b/contrib/llvm/include/llvm/Support/ErrorHandling.h @@ -100,6 +100,8 @@ void install_bad_alloc_error_handler(fatal_error_handler_t handler, /// Restores default bad alloc error handling behavior. void remove_bad_alloc_error_handler(); +void install_out_of_memory_new_handler(); + /// Reports a bad alloc error, calling any user defined bad alloc /// error handler. In contrast to the generic 'report_fatal_error' /// functions, this function is expected to return, e.g. the user @@ -110,7 +112,7 @@ void remove_bad_alloc_error_handler(); /// in the unwind chain. /// /// If no error handler is installed (default), then a bad_alloc exception -/// is thrown if LLVM is compiled with exception support, otherwise an assertion +/// is thrown, if LLVM is compiled with exception support, otherwise an assertion /// is called. void report_bad_alloc_error(const char *Reason, bool GenCrashDiag = true); diff --git a/contrib/llvm/include/llvm/Support/ErrorOr.h b/contrib/llvm/include/llvm/Support/ErrorOr.h index 061fb65db465..e6ce764ad822 100644 --- a/contrib/llvm/include/llvm/Support/ErrorOr.h +++ b/contrib/llvm/include/llvm/Support/ErrorOr.h @@ -24,19 +24,7 @@ namespace llvm { -/// \brief Stores a reference that can be changed. -template <typename T> -class ReferenceStorage { - T *Storage; - -public: - ReferenceStorage(T &Ref) : Storage(&Ref) {} - - operator T &() const { return *Storage; } - T &get() const { return *Storage; } -}; - -/// \brief Represents either an error or a value T. +/// Represents either an error or a value T. /// /// ErrorOr<T> is a pointer-like class that represents the result of an /// operation. The result is either an error, or a value of type T. This is @@ -71,7 +59,7 @@ class ErrorOr { static const bool isRef = std::is_reference<T>::value; - using wrap = ReferenceStorage<typename std::remove_reference<T>::type>; + using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>; public: using storage_type = typename std::conditional<isRef, wrap, T>::type; @@ -161,7 +149,7 @@ public: getStorage()->~storage_type(); } - /// \brief Return false if there is an error. + /// Return false if there is an error. explicit operator bool() const { return !HasError; } diff --git a/contrib/llvm/include/llvm/Support/FileOutputBuffer.h b/contrib/llvm/include/llvm/Support/FileOutputBuffer.h index 6aed423a01e3..ee8cbb730878 100644 --- a/contrib/llvm/include/llvm/Support/FileOutputBuffer.h +++ b/contrib/llvm/include/llvm/Support/FileOutputBuffer.h @@ -30,13 +30,25 @@ namespace llvm { /// not committed, the file will be deleted in the FileOutputBuffer destructor. class FileOutputBuffer { public: - enum { - F_executable = 1 /// set the 'x' bit on the resulting file + enum { + /// set the 'x' bit on the resulting file + F_executable = 1, + + /// the contents of the new file are initialized from the file that exists + /// at the location (if present). This allows in-place modification of an + /// existing file. + F_modify = 2 }; /// Factory method to create an OutputBuffer object which manages a read/write /// buffer of the specified size. When committed, the buffer will be written /// to the file at the specified path. + /// + /// When F_modify is specified and \p FilePath refers to an existing on-disk + /// file \p Size may be set to -1, in which case the entire file is used. + /// Otherwise, the file shrinks or grows as necessary based on the value of + /// \p Size. It is an error to specify F_modify and Size=-1 if \p FilePath + /// does not exist. static Expected<std::unique_ptr<FileOutputBuffer>> create(StringRef FilePath, size_t Size, unsigned Flags = 0); diff --git a/contrib/llvm/include/llvm/Support/FileSystem.h b/contrib/llvm/include/llvm/Support/FileSystem.h index b1683ba5ddb3..02db4596bf1c 100644 --- a/contrib/llvm/include/llvm/Support/FileSystem.h +++ b/contrib/llvm/include/llvm/Support/FileSystem.h @@ -30,6 +30,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" @@ -53,6 +54,15 @@ namespace llvm { namespace sys { namespace fs { +#if defined(_WIN32) +// A Win32 HANDLE is a typedef of void* +using file_t = void *; +#else +using file_t = int; +#endif + +extern const file_t kInvalidFile; + /// An enumeration for the file system's view of the type. enum class file_type { status_error, @@ -153,7 +163,7 @@ protected: uid_t fs_st_uid = 0; gid_t fs_st_gid = 0; off_t fs_st_size = 0; - #elif defined (LLVM_ON_WIN32) + #elif defined (_WIN32) uint32_t LastAccessedTimeHigh = 0; uint32_t LastAccessedTimeLow = 0; uint32_t LastWriteTimeHigh = 0; @@ -174,7 +184,7 @@ public: uid_t UID, gid_t GID, off_t Size) : fs_st_atime(ATime), fs_st_mtime(MTime), fs_st_uid(UID), fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {} -#elif defined(LLVM_ON_WIN32) +#elif defined(_WIN32) basic_file_status(file_type Type, perms Perms, uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow, uint32_t FileSizeHigh, @@ -196,7 +206,7 @@ public: uint32_t getUser() const { return fs_st_uid; } uint32_t getGroup() const { return fs_st_gid; } uint64_t getSize() const { return fs_st_size; } - #elif defined (LLVM_ON_WIN32) + #elif defined (_WIN32) uint32_t getUser() const { return 9999; // Not applicable to Windows, so... } @@ -223,7 +233,7 @@ class file_status : public basic_file_status { dev_t fs_st_dev = 0; nlink_t fs_st_nlinks = 0; ino_t fs_st_ino = 0; - #elif defined (LLVM_ON_WIN32) + #elif defined (_WIN32) uint32_t NumLinks = 0; uint32_t VolumeSerialNumber = 0; uint32_t FileIndexHigh = 0; @@ -240,7 +250,7 @@ public: time_t ATime, time_t MTime, uid_t UID, gid_t GID, off_t Size) : basic_file_status(Type, Perms, ATime, MTime, UID, GID, Size), fs_st_dev(Dev), fs_st_nlinks(Links), fs_st_ino(Ino) {} - #elif defined(LLVM_ON_WIN32) + #elif defined(_WIN32) file_status(file_type Type, perms Perms, uint32_t LinkCount, uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow, @@ -262,7 +272,7 @@ public: /// @name Physical Operators /// @{ -/// @brief Make \a path an absolute path. +/// Make \a path an absolute path. /// /// Makes \a path absolute using the \a current_directory if it is not already. /// An empty \a path will result in the \a current_directory. @@ -276,7 +286,7 @@ public: std::error_code make_absolute(const Twine ¤t_directory, SmallVectorImpl<char> &path); -/// @brief Make \a path an absolute path. +/// Make \a path an absolute path. /// /// Makes \a path absolute using the current directory if it is not already. An /// empty \a path will result in the current directory. @@ -289,7 +299,7 @@ std::error_code make_absolute(const Twine ¤t_directory, /// platform-specific error_code. std::error_code make_absolute(SmallVectorImpl<char> &path); -/// @brief Create all the non-existent directories in path. +/// Create all the non-existent directories in path. /// /// @param path Directories to create. /// @returns errc::success if is_directory(path), otherwise a platform @@ -299,7 +309,7 @@ std::error_code create_directories(const Twine &path, bool IgnoreExisting = true, perms Perms = owner_all | group_all); -/// @brief Create the directory in path. +/// Create the directory in path. /// /// @param path Directory to create. /// @returns errc::success if is_directory(path), otherwise a platform @@ -308,7 +318,7 @@ std::error_code create_directories(const Twine &path, std::error_code create_directory(const Twine &path, bool IgnoreExisting = true, perms Perms = owner_all | group_all); -/// @brief Create a link from \a from to \a to. +/// 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 @@ -329,7 +339,7 @@ std::error_code create_link(const Twine &to, const Twine &from); /// specific error_code. std::error_code create_hard_link(const Twine &to, const Twine &from); -/// @brief Collapse all . and .. patterns, resolve all symlinks, and optionally +/// Collapse all . and .. patterns, resolve all symlinks, and optionally /// expand ~ expressions to the user's home directory. /// /// @param path The path to resolve. @@ -339,21 +349,21 @@ std::error_code create_hard_link(const Twine &to, const Twine &from); std::error_code real_path(const Twine &path, SmallVectorImpl<char> &output, bool expand_tilde = false); -/// @brief Get the current path. +/// Get the current path. /// /// @param result Holds the current path on return. /// @returns errc::success if the current path has been stored in result, /// otherwise a platform-specific error_code. std::error_code current_path(SmallVectorImpl<char> &result); -/// @brief Set the current path. +/// Set the current path. /// /// @param path The path to set. /// @returns errc::success if the current path was successfully set, /// otherwise a platform-specific error_code. std::error_code set_current_path(const Twine &path); -/// @brief Remove path. Equivalent to POSIX remove(). +/// Remove path. Equivalent to POSIX remove(). /// /// @param path Input path. /// @returns errc::success if path has been removed or didn't exist, otherwise a @@ -361,14 +371,14 @@ std::error_code set_current_path(const Twine &path); /// returns error if the file didn't exist. std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); -/// @brief Recursively delete a directory. +/// Recursively delete a directory. /// /// @param path Input path. /// @returns errc::success if path has been removed or didn't exist, otherwise a /// platform-specific error code. std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true); -/// @brief Rename \a from to \a to. +/// Rename \a from to \a to. /// /// Files are renamed as if by POSIX rename(), except that on Windows there may /// be a short interval of time during which the destination file does not @@ -378,13 +388,19 @@ std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true); /// @param to The path to rename to. This is created. std::error_code rename(const Twine &from, const Twine &to); -/// @brief Copy the contents of \a From to \a To. +/// Copy the contents of \a From to \a To. /// /// @param From The path to copy from. /// @param To The path to copy to. This is created. std::error_code copy_file(const Twine &From, const Twine &To); -/// @brief Resize path to size. File is resized as if by POSIX truncate(). +/// Copy the contents of \a From to \a To. +/// +/// @param From The path to copy from. +/// @param ToFD The open file descriptor of the destination file. +std::error_code copy_file(const Twine &From, int ToFD); + +/// Resize path to size. File is resized as if by POSIX truncate(). /// /// @param FD Input file descriptor. /// @param Size Size to resize to. @@ -392,21 +408,21 @@ std::error_code copy_file(const Twine &From, const Twine &To); /// platform-specific error_code. std::error_code resize_file(int FD, uint64_t Size); -/// @brief Compute an MD5 hash of a file's contents. +/// Compute an MD5 hash of a file's contents. /// /// @param FD Input file descriptor. /// @returns An MD5Result with the hash computed, if successful, otherwise a /// std::error_code. ErrorOr<MD5::MD5Result> md5_contents(int FD); -/// @brief Version of compute_md5 that doesn't require an open file descriptor. +/// Version of compute_md5 that doesn't require an open file descriptor. ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path); /// @} /// @name Physical Observers /// @{ -/// @brief Does file exist? +/// Does file exist? /// /// @param status A basic_file_status previously returned from stat. /// @returns True if the file represented by status exists, false if it does @@ -415,14 +431,14 @@ bool exists(const basic_file_status &status); enum class AccessMode { Exist, Write, Execute }; -/// @brief Can the file be accessed? +/// Can the file be accessed? /// /// @param Path Input path. /// @returns errc::success if the path can be accessed, otherwise a /// platform-specific error_code. std::error_code access(const Twine &Path, AccessMode Mode); -/// @brief Does file exist? +/// Does file exist? /// /// @param Path Input path. /// @returns True if it exists, false otherwise. @@ -430,13 +446,13 @@ inline bool exists(const Twine &Path) { return !access(Path, AccessMode::Exist); } -/// @brief Can we execute this file? +/// Can we execute this file? /// /// @param Path Input path. /// @returns True if we can execute it, false otherwise. bool can_execute(const Twine &Path); -/// @brief Can we write this file? +/// Can we write this file? /// /// @param Path Input path. /// @returns True if we can write to it, false otherwise. @@ -444,7 +460,7 @@ inline bool can_write(const Twine &Path) { return !access(Path, AccessMode::Write); } -/// @brief Do file_status's represent the same thing? +/// Do file_status's represent the same thing? /// /// @param A Input file_status. /// @param B Input file_status. @@ -455,7 +471,7 @@ inline bool can_write(const Twine &Path) { /// otherwise. bool equivalent(file_status A, file_status B); -/// @brief Do paths represent the same thing? +/// Do paths represent the same thing? /// /// assert(status_known(A) || status_known(B)); /// @@ -467,14 +483,14 @@ bool equivalent(file_status A, file_status B); /// platform-specific error_code. std::error_code equivalent(const Twine &A, const Twine &B, bool &result); -/// @brief Simpler version of equivalent for clients that don't need to +/// Simpler version of equivalent for clients that don't need to /// differentiate between an error and false. inline bool equivalent(const Twine &A, const Twine &B) { bool result; return !equivalent(A, B, result) && result; } -/// @brief Is the file mounted on a local filesystem? +/// Is the file mounted on a local filesystem? /// /// @param path Input path. /// @param result Set to true if \a path is on fixed media such as a hard disk, @@ -483,24 +499,24 @@ inline bool equivalent(const Twine &A, const Twine &B) { /// platform specific error_code. std::error_code is_local(const Twine &path, bool &result); -/// @brief Version of is_local accepting an open file descriptor. +/// Version of is_local accepting an open file descriptor. std::error_code is_local(int FD, bool &result); -/// @brief Simpler version of is_local for clients that don't need to +/// Simpler version of is_local for clients that don't need to /// differentiate between an error and false. inline bool is_local(const Twine &Path) { bool Result; return !is_local(Path, Result) && Result; } -/// @brief Simpler version of is_local accepting an open file descriptor for +/// Simpler version of is_local accepting an open file descriptor for /// clients that don't need to differentiate between an error and false. inline bool is_local(int FD) { bool Result; return !is_local(FD, Result) && Result; } -/// @brief Does status represent a directory? +/// Does status represent a directory? /// /// @param Path The path to get the type of. /// @param Follow For symbolic links, indicates whether to return the file type @@ -508,13 +524,13 @@ inline bool is_local(int FD) { /// @returns A value from the file_type enumeration indicating the type of file. file_type get_file_type(const Twine &Path, bool Follow = true); -/// @brief Does status represent a directory? +/// Does status represent a directory? /// /// @param status A basic_file_status previously returned from status. /// @returns status.type() == file_type::directory_file. bool is_directory(const basic_file_status &status); -/// @brief Is path a directory? +/// Is path a directory? /// /// @param path Input path. /// @param result Set to true if \a path is a directory (after following @@ -523,20 +539,20 @@ bool is_directory(const basic_file_status &status); /// platform-specific error_code. std::error_code is_directory(const Twine &path, bool &result); -/// @brief Simpler version of is_directory for clients that don't need to +/// Simpler version of is_directory for clients that don't need to /// differentiate between an error and false. inline bool is_directory(const Twine &Path) { bool Result; return !is_directory(Path, Result) && Result; } -/// @brief Does status represent a regular file? +/// Does status represent a regular file? /// /// @param status A basic_file_status previously returned from status. /// @returns status_known(status) && status.type() == file_type::regular_file. bool is_regular_file(const basic_file_status &status); -/// @brief Is path a regular file? +/// Is path a regular file? /// /// @param path Input path. /// @param result Set to true if \a path is a regular file (after following @@ -545,7 +561,7 @@ bool is_regular_file(const basic_file_status &status); /// platform-specific error_code. std::error_code is_regular_file(const Twine &path, bool &result); -/// @brief Simpler version of is_regular_file for clients that don't need to +/// Simpler version of is_regular_file for clients that don't need to /// differentiate between an error and false. inline bool is_regular_file(const Twine &Path) { bool Result; @@ -554,13 +570,13 @@ inline bool is_regular_file(const Twine &Path) { return Result; } -/// @brief Does status represent a symlink file? +/// Does status represent a symlink file? /// /// @param status A basic_file_status previously returned from status. /// @returns status_known(status) && status.type() == file_type::symlink_file. bool is_symlink_file(const basic_file_status &status); -/// @brief Is path a symlink file? +/// Is path a symlink file? /// /// @param path Input path. /// @param result Set to true if \a path is a symlink file, false if it is not. @@ -569,7 +585,7 @@ bool is_symlink_file(const basic_file_status &status); /// platform-specific error_code. std::error_code is_symlink_file(const Twine &path, bool &result); -/// @brief Simpler version of is_symlink_file for clients that don't need to +/// Simpler version of is_symlink_file for clients that don't need to /// differentiate between an error and false. inline bool is_symlink_file(const Twine &Path) { bool Result; @@ -578,14 +594,14 @@ inline bool is_symlink_file(const Twine &Path) { return Result; } -/// @brief Does this status represent something that exists but is not a +/// Does this status represent something that exists but is not a /// directory or regular file? /// /// @param status A basic_file_status previously returned from status. /// @returns exists(s) && !is_regular_file(s) && !is_directory(s) bool is_other(const basic_file_status &status); -/// @brief Is path something that exists but is not a directory, +/// Is path something that exists but is not a directory, /// regular file, or symlink? /// /// @param path Input path. @@ -595,7 +611,7 @@ bool is_other(const basic_file_status &status); /// platform-specific error_code. std::error_code is_other(const Twine &path, bool &result); -/// @brief Get file status as if by POSIX stat(). +/// Get file status as if by POSIX stat(). /// /// @param path Input path. /// @param result Set to the file status. @@ -606,10 +622,10 @@ std::error_code is_other(const Twine &path, bool &result); std::error_code status(const Twine &path, file_status &result, bool follow = true); -/// @brief A version for when a file descriptor is already available. +/// A version for when a file descriptor is already available. std::error_code status(int FD, file_status &Result); -/// @brief Set file permissions. +/// Set file permissions. /// /// @param Path File to set permissions on. /// @param Permissions New file permissions. @@ -620,7 +636,7 @@ std::error_code status(int FD, file_status &Result); /// Otherwise, the file will be marked as read-only. std::error_code setPermissions(const Twine &Path, perms Permissions); -/// @brief Get file permissions. +/// Get file permissions. /// /// @param Path File to get permissions from. /// @returns the permissions if they were successfully retrieved, otherwise a @@ -630,7 +646,7 @@ std::error_code setPermissions(const Twine &Path, perms Permissions); /// will be returned. ErrorOr<perms> getPermissions(const Twine &Path); -/// @brief Get file size. +/// Get file size. /// /// @param Path Input path. /// @param Result Set to the size of the file in \a Path. @@ -645,20 +661,20 @@ inline std::error_code file_size(const Twine &Path, uint64_t &Result) { return std::error_code(); } -/// @brief Set the file modification and access time. +/// Set the file modification and access time. /// /// @returns errc::success if the file times were successfully set, otherwise a /// platform-specific error_code or errc::function_not_supported on /// platforms where the functionality isn't available. std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time); -/// @brief Is status available? +/// Is status available? /// /// @param s Input file status. /// @returns True if status() != status_error. bool status_known(const basic_file_status &s); -/// @brief Is status available? +/// Is status available? /// /// @param path Input path. /// @param result Set to true if status() != status_error. @@ -666,30 +682,58 @@ bool status_known(const basic_file_status &s); /// platform-specific error_code. std::error_code status_known(const Twine &path, bool &result); -enum OpenFlags : unsigned { - F_None = 0, +enum CreationDisposition : unsigned { + /// CD_CreateAlways - When opening a file: + /// * If it already exists, truncate it. + /// * If it does not already exist, create a new file. + CD_CreateAlways = 0, + + /// CD_CreateNew - When opening a file: + /// * If it already exists, fail. + /// * If it does not already exist, create a new file. + CD_CreateNew = 1, + + /// CD_OpenAlways - When opening a file: + /// * If it already exists, open the file with the offset set to 0. + /// * If it does not already exist, fail. + CD_OpenExisting = 2, - /// F_Excl - When opening a file, this flag makes raw_fd_ostream - /// report an error if the file already exists. - F_Excl = 1, + /// CD_OpenAlways - When opening a file: + /// * If it already exists, open the file with the offset set to 0. + /// * If it does not already exist, create a new file. + CD_OpenAlways = 3, +}; - /// F_Append - When opening a file, if it already exists append to the - /// existing file instead of returning an error. This may not be specified - /// with F_Excl. - F_Append = 2, +enum FileAccess : unsigned { + FA_Read = 1, + FA_Write = 2, +}; + +enum OpenFlags : unsigned { + OF_None = 0, + F_None = 0, // For compatibility /// The file should be opened in text mode on platforms that make this /// distinction. - F_Text = 4, + OF_Text = 1, + F_Text = 1, // For compatibility - /// Open the file for read and write. - F_RW = 8, + /// The file should be opened in append mode. + OF_Append = 2, + F_Append = 2, // For compatibility /// Delete the file on close. Only makes a difference on windows. - F_Delete = 16 + OF_Delete = 4, + + /// When a child process is launched, this file should remain open in the + /// child process. + OF_ChildInherit = 8, + + /// Force files Atime to be updated on access. Only makes a difference on windows. + OF_UpdateAtime = 16, }; -/// @brief Create a uniquely named file. +/// Create a uniquely named file. /// /// Generates a unique path suitable for a temporary file and then opens it as a /// file. The name is based on \a model with '%' replaced by a random char in @@ -712,12 +756,13 @@ enum OpenFlags : unsigned { /// otherwise a platform-specific error_code. std::error_code createUniqueFile(const Twine &Model, int &ResultFD, SmallVectorImpl<char> &ResultPath, - unsigned Mode = all_read | all_write, - sys::fs::OpenFlags Flags = sys::fs::F_RW); + unsigned Mode = all_read | all_write); -/// @brief Simpler version for clients that don't want an open file. +/// Simpler version for clients that don't want an open file. An empty +/// file will still be created. std::error_code createUniqueFile(const Twine &Model, - SmallVectorImpl<char> &ResultPath); + SmallVectorImpl<char> &ResultPath, + unsigned Mode = all_read | all_write); /// Represents a temporary file. /// @@ -757,7 +802,7 @@ public: ~TempFile(); }; -/// @brief Create a file in the system temporary directory. +/// Create a file in the system temporary directory. /// /// The filename is of the form prefix-random_chars.suffix. Since the directory /// is not know to the caller, Prefix and Suffix cannot have path separators. @@ -767,16 +812,38 @@ public: /// running the assembler. std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, - SmallVectorImpl<char> &ResultPath, - sys::fs::OpenFlags Flags = sys::fs::F_RW); + SmallVectorImpl<char> &ResultPath); -/// @brief Simpler version for clients that don't want an open file. +/// Simpler version for clients that don't want an open file. An empty +/// file will still be created. std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, SmallVectorImpl<char> &ResultPath); std::error_code createUniqueDirectory(const Twine &Prefix, SmallVectorImpl<char> &ResultPath); +/// Get a unique name, not currently exisiting in the filesystem. Subject +/// to race conditions, prefer to use createUniqueFile instead. +/// +/// Similar to createUniqueFile, but instead of creating a file only +/// checks if it exists. This function is subject to race conditions, if you +/// want to use the returned name to actually create a file, use +/// createUniqueFile instead. +std::error_code getPotentiallyUniqueFileName(const Twine &Model, + SmallVectorImpl<char> &ResultPath); + +/// Get a unique temporary file name, not currently exisiting in the +/// filesystem. Subject to race conditions, prefer to use createTemporaryFile +/// instead. +/// +/// Similar to createTemporaryFile, but instead of creating a file only +/// checks if it exists. This function is subject to race conditions, if you +/// want to use the returned name to actually create a file, use +/// createTemporaryFile instead. +std::error_code +getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix, + SmallVectorImpl<char> &ResultPath); + inline OpenFlags operator|(OpenFlags A, OpenFlags B) { return OpenFlags(unsigned(A) | unsigned(B)); } @@ -786,15 +853,181 @@ inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { return A; } -std::error_code openFileForWrite(const Twine &Name, int &ResultFD, - OpenFlags Flags, unsigned Mode = 0666); +inline FileAccess operator|(FileAccess A, FileAccess B) { + return FileAccess(unsigned(A) | unsigned(B)); +} +inline FileAccess &operator|=(FileAccess &A, FileAccess B) { + A = A | B; + return A; +} + +/// @brief Opens a file with the specified creation disposition, access mode, +/// and flags and returns a file descriptor. +/// +/// The caller is responsible for closing the file descriptor once they are +/// finished with it. +/// +/// @param Name The path of the file to open, relative or absolute. +/// @param ResultFD If the file could be opened successfully, its descriptor +/// is stored in this location. Otherwise, this is set to -1. +/// @param Disp Value specifying the existing-file behavior. +/// @param Access Value specifying whether to open the file in read, write, or +/// read-write mode. +/// @param Flags Additional flags. +/// @param Mode The access permissions of the file, represented in octal. +/// @returns errc::success if \a Name has been opened, otherwise a +/// platform-specific error_code. +std::error_code openFile(const Twine &Name, int &ResultFD, + CreationDisposition Disp, FileAccess Access, + OpenFlags Flags, unsigned Mode = 0666); + +/// @brief Opens a file with the specified creation disposition, access mode, +/// and flags and returns a platform-specific file object. +/// +/// The caller is responsible for closing the file object once they are +/// finished with it. +/// +/// @param Name The path of the file to open, relative or absolute. +/// @param Disp Value specifying the existing-file behavior. +/// @param Access Value specifying whether to open the file in read, write, or +/// read-write mode. +/// @param Flags Additional flags. +/// @param Mode The access permissions of the file, represented in octal. +/// @returns errc::success if \a Name has been opened, otherwise a +/// platform-specific error_code. +Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp, + FileAccess Access, OpenFlags Flags, + unsigned Mode = 0666); + +/// @brief Opens the file with the given name in a write-only or read-write +/// mode, returning its open file descriptor. If the file does not exist, it +/// is created. +/// +/// The caller is responsible for closing the file descriptor once they are +/// finished with it. +/// +/// @param Name The path of the file to open, relative or absolute. +/// @param ResultFD If the file could be opened successfully, its descriptor +/// is stored in this location. Otherwise, this is set to -1. +/// @param Flags Additional flags used to determine whether the file should be +/// opened in, for example, read-write or in write-only mode. +/// @param Mode The access permissions of the file, represented in octal. +/// @returns errc::success if \a Name has been opened, otherwise a +/// platform-specific error_code. +inline std::error_code +openFileForWrite(const Twine &Name, int &ResultFD, + CreationDisposition Disp = CD_CreateAlways, + OpenFlags Flags = OF_None, unsigned Mode = 0666) { + return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode); +} + +/// @brief Opens the file with the given name in a write-only or read-write +/// mode, returning its open file descriptor. If the file does not exist, it +/// is created. +/// +/// The caller is responsible for closing the freeing the file once they are +/// finished with it. +/// +/// @param Name The path of the file to open, relative or absolute. +/// @param Flags Additional flags used to determine whether the file should be +/// opened in, for example, read-write or in write-only mode. +/// @param Mode The access permissions of the file, represented in octal. +/// @returns a platform-specific file descriptor if \a Name has been opened, +/// otherwise an error object. +inline Expected<file_t> openNativeFileForWrite(const Twine &Name, + CreationDisposition Disp, + OpenFlags Flags, + unsigned Mode = 0666) { + return openNativeFile(Name, Disp, FA_Write, Flags, Mode); +} + +/// @brief Opens the file with the given name in a write-only or read-write +/// mode, returning its open file descriptor. If the file does not exist, it +/// is created. +/// +/// The caller is responsible for closing the file descriptor once they are +/// finished with it. +/// +/// @param Name The path of the file to open, relative or absolute. +/// @param ResultFD If the file could be opened successfully, its descriptor +/// is stored in this location. Otherwise, this is set to -1. +/// @param Flags Additional flags used to determine whether the file should be +/// opened in, for example, read-write or in write-only mode. +/// @param Mode The access permissions of the file, represented in octal. +/// @returns errc::success if \a Name has been opened, otherwise a +/// platform-specific error_code. +inline std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD, + CreationDisposition Disp, + OpenFlags Flags, + unsigned Mode = 0666) { + return openFile(Name, ResultFD, Disp, FA_Write | FA_Read, Flags, Mode); +} + +/// @brief Opens the file with the given name in a write-only or read-write +/// mode, returning its open file descriptor. If the file does not exist, it +/// is created. +/// +/// The caller is responsible for closing the freeing the file once they are +/// finished with it. +/// +/// @param Name The path of the file to open, relative or absolute. +/// @param Flags Additional flags used to determine whether the file should be +/// opened in, for example, read-write or in write-only mode. +/// @param Mode The access permissions of the file, represented in octal. +/// @returns a platform-specific file descriptor if \a Name has been opened, +/// otherwise an error object. +inline Expected<file_t> openNativeFileForReadWrite(const Twine &Name, + CreationDisposition Disp, + OpenFlags Flags, + unsigned Mode = 0666) { + return openNativeFile(Name, Disp, FA_Write | FA_Read, Flags, Mode); +} + +/// @brief Opens the file with the given name in a read-only mode, returning +/// its open file descriptor. +/// +/// The caller is responsible for closing the file descriptor once they are +/// finished with it. +/// +/// @param Name The path of the file to open, relative or absolute. +/// @param ResultFD If the file could be opened successfully, its descriptor +/// is stored in this location. Otherwise, this is set to -1. +/// @param RealPath If nonnull, extra work is done to determine the real path +/// of the opened file, and that path is stored in this +/// location. +/// @returns errc::success if \a Name has been opened, otherwise a +/// platform-specific error_code. std::error_code openFileForRead(const Twine &Name, int &ResultFD, + OpenFlags Flags = OF_None, SmallVectorImpl<char> *RealPath = nullptr); +/// @brief Opens the file with the given name in a read-only mode, returning +/// its open file descriptor. +/// +/// The caller is responsible for closing the freeing the file once they are +/// finished with it. +/// +/// @param Name The path of the file to open, relative or absolute. +/// @param RealPath If nonnull, extra work is done to determine the real path +/// of the opened file, and that path is stored in this +/// location. +/// @returns a platform-specific file descriptor if \a Name has been opened, +/// otherwise an error object. +Expected<file_t> +openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None, + SmallVectorImpl<char> *RealPath = nullptr); + +/// @brief Close the file object. This should be used instead of ::close for +/// portability. +/// +/// @param F On input, this is the file to close. On output, the file is +/// set to kInvalidFile. +void closeFile(file_t &F); + std::error_code getUniqueID(const Twine Path, UniqueID &Result); -/// @brief Get disk space usage information. +/// Get disk space usage information. /// /// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug. /// Note: Windows reports results according to the quota allocated to the user. @@ -819,6 +1052,10 @@ private: /// Platform-specific mapping state. size_t Size; void *Mapping; +#ifdef _WIN32 + void *FileHandle; +#endif + mapmode Mode; std::error_code init(int FD, uint64_t Offset, mapmode Mode); @@ -924,14 +1161,16 @@ public: SmallString<128> path_storage; ec = detail::directory_iterator_construct( *State, path.toStringRef(path_storage), FollowSymlinks); + update_error_code_for_current_entry(ec); } explicit directory_iterator(const directory_entry &de, std::error_code &ec, bool follow_symlinks = true) : FollowSymlinks(follow_symlinks) { State = std::make_shared<detail::DirIterState>(); - ec = - detail::directory_iterator_construct(*State, de.path(), FollowSymlinks); + ec = detail::directory_iterator_construct( + *State, de.path(), FollowSymlinks); + update_error_code_for_current_entry(ec); } /// Construct end iterator. @@ -940,6 +1179,7 @@ public: // No operator++ because we need error_code. directory_iterator &increment(std::error_code &ec) { ec = directory_iterator_increment(*State); + update_error_code_for_current_entry(ec); return *this; } @@ -961,6 +1201,24 @@ public: } // Other members as required by // C++ Std, 24.1.1 Input iterators [input.iterators] + +private: + // Checks if current entry is valid and populates error code. For example, + // current entry may not exist due to broken symbol links. + void update_error_code_for_current_entry(std::error_code &ec) { + // Bail out if error has already occured earlier to avoid overwriting it. + if (ec) + return; + + // Empty directory entry is used to mark the end of an interation, it's not + // an error. + if (State->CurrentEntry == directory_entry()) + return; + + ErrorOr<basic_file_status> status = State->CurrentEntry.status(); + if (!status) + ec = status.getError(); + } }; namespace detail { @@ -998,11 +1256,9 @@ public: if (State->HasNoPushRequest) State->HasNoPushRequest = false; else { - ErrorOr<basic_file_status> st = State->Stack.top()->status(); - if (!st) return *this; - if (is_directory(*st)) { + ErrorOr<basic_file_status> status = State->Stack.top()->status(); + if (status && is_directory(*status)) { State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow)); - if (ec) return *this; if (State->Stack.top() != end_itr) { ++State->Level; return *this; diff --git a/contrib/llvm/include/llvm/Support/FormatAdapters.h b/contrib/llvm/include/llvm/Support/FormatAdapters.h index 197beb7363df..8320eaad39a9 100644 --- a/contrib/llvm/include/llvm/Support/FormatAdapters.h +++ b/contrib/llvm/include/llvm/Support/FormatAdapters.h @@ -12,6 +12,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" #include "llvm/Support/FormatCommon.h" #include "llvm/Support/FormatVariadicDetails.h" #include "llvm/Support/raw_ostream.h" @@ -19,7 +20,7 @@ namespace llvm { template <typename T> class FormatAdapter : public detail::format_adapter { protected: - explicit FormatAdapter(T &&Item) : Item(Item) {} + explicit FormatAdapter(T &&Item) : Item(std::forward<T>(Item)) {} T Item; }; @@ -71,6 +72,14 @@ public: } } }; + +class ErrorAdapter : public FormatAdapter<Error> { +public: + ErrorAdapter(Error &&Item) : FormatAdapter(std::move(Item)) {} + ErrorAdapter(ErrorAdapter &&) = default; + ~ErrorAdapter() { consumeError(std::move(Item)); } + void format(llvm::raw_ostream &Stream, StringRef Style) { Stream << Item; } +}; } template <typename T> @@ -88,6 +97,13 @@ template <typename T> detail::RepeatAdapter<T> fmt_repeat(T &&Item, size_t Count) { return detail::RepeatAdapter<T>(std::forward<T>(Item), Count); } + +// llvm::Error values must be consumed before being destroyed. +// Wrapping an error in fmt_consume explicitly indicates that the formatv_object +// should take ownership and consume it. +inline detail::ErrorAdapter fmt_consume(Error &&Item) { + return detail::ErrorAdapter(std::move(Item)); +} } #endif diff --git a/contrib/llvm/include/llvm/Support/FormatVariadic.h b/contrib/llvm/include/llvm/Support/FormatVariadic.h index 8c08a7d9488f..b0f582513e07 100644 --- a/contrib/llvm/include/llvm/Support/FormatVariadic.h +++ b/contrib/llvm/include/llvm/Support/FormatVariadic.h @@ -118,7 +118,7 @@ public: auto W = Adapters[R.Index]; - FmtAlign Align(*W, R.Where, R.Align); + FmtAlign Align(*W, R.Where, R.Align, R.Pad); Align.format(S, R.Options); } } @@ -168,7 +168,7 @@ public: } }; -// \brief Format text given a format string and replacement parameters. +// Format text given a format string and replacement parameters. // // ===General Description=== // @@ -237,6 +237,8 @@ public: // for type T containing a method whose signature is: // void format(const T &Obj, raw_ostream &Stream, StringRef Options) // Then this method is invoked as described in Step 1. +// 3. If an appropriate operator<< for raw_ostream exists, it will be used. +// For this to work, (raw_ostream& << const T&) must return raw_ostream&. // // If a match cannot be found through either of the above methods, a compiler // error is generated. @@ -258,13 +260,6 @@ inline auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object<decltype( std::make_tuple(detail::build_format_adapter(std::forward<Ts>(Vals))...)); } -// Allow a formatv_object to be formatted (no options supported). -template <typename T> struct format_provider<formatv_object<T>> { - static void format(const formatv_object<T> &V, raw_ostream &OS, StringRef) { - OS << V; - } -}; - } // end namespace llvm #endif // LLVM_SUPPORT_FORMATVARIADIC_H diff --git a/contrib/llvm/include/llvm/Support/FormatVariadicDetails.h b/contrib/llvm/include/llvm/Support/FormatVariadicDetails.h index 9b60462209dc..56dda430efda 100644 --- a/contrib/llvm/include/llvm/Support/FormatVariadicDetails.h +++ b/contrib/llvm/include/llvm/Support/FormatVariadicDetails.h @@ -17,6 +17,7 @@ namespace llvm { template <typename T, typename Enable = void> struct format_provider {}; +class Error; namespace detail { class format_adapter { @@ -38,6 +39,17 @@ public: } }; +template <typename T> +class stream_operator_format_adapter : public format_adapter { + T Item; + +public: + explicit stream_operator_format_adapter(T &&Item) + : Item(std::forward<T>(Item)) {} + + void format(llvm::raw_ostream &S, StringRef Options) override { S << Item; } +}; + template <typename T> class missing_format_adapter; // Test if format_provider<T> is defined on T and contains a member function @@ -59,6 +71,23 @@ public: (sizeof(test<llvm::format_provider<Decayed>>(nullptr)) == 1); }; +// Test if raw_ostream& << T -> raw_ostream& is findable via ADL. +template <class T> class has_StreamOperator { +public: + using ConstRefT = const typename std::decay<T>::type &; + + template <typename U> + static char test(typename std::enable_if< + std::is_same<decltype(std::declval<llvm::raw_ostream &>() + << std::declval<U>()), + llvm::raw_ostream &>::value, + int *>::type); + + template <typename U> static double test(...); + + static bool const value = (sizeof(test<ConstRefT>(nullptr)) == 1); +}; + // Simple template that decides whether a type T should use the member-function // based format() invocation. template <typename T> @@ -77,15 +106,24 @@ struct uses_format_provider bool, !uses_format_member<T>::value && has_FormatProvider<T>::value> { }; +// Simple template that decides whether a type T should use the operator<< +// based format() invocation. This takes last priority. +template <typename T> +struct uses_stream_operator + : public std::integral_constant<bool, !uses_format_member<T>::value && + !uses_format_provider<T>::value && + has_StreamOperator<T>::value> {}; + // Simple template that decides whether a type T has neither a member-function // nor format_provider based implementation that it can use. Mostly used so // that the compiler spits out a nice diagnostic when a type with no format // implementation can be located. template <typename T> struct uses_missing_provider - : public std::integral_constant<bool, - !uses_format_member<T>::value && - !uses_format_provider<T>::value> {}; + : public std::integral_constant<bool, !uses_format_member<T>::value && + !uses_format_provider<T>::value && + !uses_stream_operator<T>::value> { +}; template <typename T> typename std::enable_if<uses_format_member<T>::value, T>::type @@ -101,6 +139,19 @@ build_format_adapter(T &&Item) { } template <typename T> +typename std::enable_if<uses_stream_operator<T>::value, + stream_operator_format_adapter<T>>::type +build_format_adapter(T &&Item) { + // If the caller passed an Error by value, then stream_operator_format_adapter + // would be responsible for consuming it. + // Make the caller opt into this by calling fmt_consume(). + static_assert( + !std::is_same<llvm::Error, typename std::remove_cv<T>::type>::value, + "llvm::Error-by-value must be wrapped in fmt_consume() for formatv"); + return stream_operator_format_adapter<T>(std::forward<T>(Item)); +} + +template <typename T> typename std::enable_if<uses_missing_provider<T>::value, missing_format_adapter<T>>::type build_format_adapter(T &&Item) { diff --git a/contrib/llvm/include/llvm/Support/GenericDomTree.h b/contrib/llvm/include/llvm/Support/GenericDomTree.h index 635c87a106f0..115abc23e2c6 100644 --- a/contrib/llvm/include/llvm/Support/GenericDomTree.h +++ b/contrib/llvm/include/llvm/Support/GenericDomTree.h @@ -50,9 +50,9 @@ template <typename DomTreeT> struct SemiNCAInfo; } // namespace DomTreeBuilder -/// \brief Base class for the actual dominator tree node. +/// Base class for the actual dominator tree node. template <class NodeT> class DomTreeNodeBase { - friend struct PostDominatorTree; + friend class PostDominatorTree; friend class DominatorTreeBase<NodeT, false>; friend class DominatorTreeBase<NodeT, true>; friend struct DomTreeBuilder::SemiNCAInfo<DominatorTreeBase<NodeT, false>>; @@ -234,10 +234,10 @@ void ApplyUpdates(DomTreeT &DT, ArrayRef<typename DomTreeT::UpdateType> Updates); template <typename DomTreeT> -bool Verify(const DomTreeT &DT); +bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL); } // namespace DomTreeBuilder -/// \brief Core dominator tree base class. +/// Core dominator tree base class. /// /// This class is a generic template over graph nodes. It is instantiated for /// various graphs in the LLVM IR or in the code generator. @@ -259,7 +259,9 @@ class DominatorTreeBase { static constexpr UpdateKind Insert = UpdateKind::Insert; static constexpr UpdateKind Delete = UpdateKind::Delete; - protected: + enum class VerificationLevel { Fast, Basic, Full }; + +protected: // Dominators always have a single root, postdominators can have more. SmallVector<NodeT *, IsPostDom ? 4 : 1> Roots; @@ -316,6 +318,12 @@ class DominatorTreeBase { bool compare(const DominatorTreeBase &Other) const { if (Parent != Other.Parent) return true; + if (Roots.size() != Other.Roots.size()) + return true; + + if (!std::is_permutation(Roots.begin(), Roots.end(), Other.Roots.begin())) + return true; + const DomTreeNodeMapType &OtherDomTreeNodes = Other.DomTreeNodes; if (DomTreeNodes.size() != OtherDomTreeNodes.size()) return true; @@ -343,7 +351,7 @@ class DominatorTreeBase { /// block. This is the same as using operator[] on this class. The result /// may (but is not required to) be null for a forward (backwards) /// statically unreachable block. - DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const { + DomTreeNodeBase<NodeT> *getNode(const NodeT *BB) const { auto I = DomTreeNodes.find(BB); if (I != DomTreeNodes.end()) return I->second.get(); @@ -351,7 +359,9 @@ class DominatorTreeBase { } /// See getNode. - DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { return getNode(BB); } + DomTreeNodeBase<NodeT> *operator[](const NodeT *BB) const { + return getNode(BB); + } /// getRootNode - This returns the entry node for the CFG of the function. If /// this tree represents the post-dominance relations for a function, however, @@ -750,10 +760,25 @@ public: DomTreeBuilder::Calculate(*this); } - /// verify - check parent and sibling property - bool verify() const { return DomTreeBuilder::Verify(*this); } + /// verify - checks if the tree is correct. There are 3 level of verification: + /// - Full -- verifies if the tree is correct by making sure all the + /// properties (including the parent and the sibling property) + /// hold. + /// Takes O(N^3) time. + /// + /// - Basic -- checks if the tree is correct, but compares it to a freshly + /// constructed tree instead of checking the sibling property. + /// Takes O(N^2) time. + /// + /// - Fast -- checks basic tree structure and compares it with a freshly + /// constructed tree. + /// Takes O(N^2) time worst case, but is faster in practise (same + /// as tree construction). + bool verify(VerificationLevel VL = VerificationLevel::Full) const { + return DomTreeBuilder::Verify(*this, VL); + } - protected: +protected: void addRoot(NodeT *BB) { this->Roots.push_back(BB); } void reset() { @@ -835,7 +860,7 @@ public: return IDom != nullptr; } - /// \brief Wipe this tree's state without releasing any resources. + /// Wipe this tree's state without releasing any resources. /// /// This is essentially a post-move helper only. It leaves the object in an /// assignable and destroyable state, but otherwise invalid. diff --git a/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h b/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h index 9438c9e08850..103ff8ca476a 100644 --- a/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h +++ b/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h @@ -82,8 +82,8 @@ struct SemiNCAInfo { // Note that these children are from the future relative to what the // DominatorTree knows about -- using them to gets us some snapshot of the // CFG from the past (relative to the state of the CFG). - DenseMap<NodePtr, SmallDenseSet<NodePtrAndKind, 4>> FutureSuccessors; - DenseMap<NodePtr, SmallDenseSet<NodePtrAndKind, 4>> FuturePredecessors; + DenseMap<NodePtr, SmallVector<NodePtrAndKind, 4>> FutureSuccessors; + DenseMap<NodePtr, SmallVector<NodePtrAndKind, 4>> FuturePredecessors; // Remembers if the whole tree was recalculated at some point during the // current batch update. bool IsRecalculated = false; @@ -146,15 +146,15 @@ struct SemiNCAInfo { assert(llvm::find(Res, Child) != Res.end() && "Expected child not found in the CFG"); Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); - DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " - << BlockNamePrinter(Child) << "\n"); + LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " + << BlockNamePrinter(Child) << "\n"); } else { // If there's an deletion in the future, it means that the edge cannot // exist in the current CFG, but existed in it before. assert(llvm::find(Res, Child) == Res.end() && "Unexpected child found in the CFG"); - DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) - << " -> " << BlockNamePrinter(Child) << "\n"); + LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) + << " -> " << BlockNamePrinter(Child) << "\n"); Res.push_back(Child); } } @@ -387,7 +387,7 @@ struct SemiNCAInfo { SNCA.addVirtualRoot(); unsigned Num = 1; - DEBUG(dbgs() << "\t\tLooking for trivial roots\n"); + LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n"); // Step #1: Find all the trivial roots that are going to will definitely // remain tree roots. @@ -404,14 +404,14 @@ struct SemiNCAInfo { Roots.push_back(N); // Run DFS not to walk this part of CFG later. Num = SNCA.runDFS(N, Num, AlwaysDescend, 1); - DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N) - << "\n"); - DEBUG(dbgs() << "Last visited node: " - << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n"); + LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N) + << "\n"); + LLVM_DEBUG(dbgs() << "Last visited node: " + << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n"); } } - DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n"); + LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n"); // Step #2: Find all non-trivial root candidates. Those are CFG nodes that // are reverse-unreachable were not visited by previous DFS walks (i.e. CFG @@ -431,8 +431,8 @@ struct SemiNCAInfo { SmallPtrSet<NodePtr, 4> ConnectToExitBlock; for (const NodePtr I : nodes(DT.Parent)) { if (SNCA.NodeToInfo.count(I) == 0) { - DEBUG(dbgs() << "\t\t\tVisiting node " << BlockNamePrinter(I) - << "\n"); + LLVM_DEBUG(dbgs() + << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n"); // Find the furthest away we can get by following successors, then // follow them in reverse. This gives us some reasonable answer about // the post-dom tree inside any infinite loop. In particular, it @@ -443,47 +443,49 @@ struct SemiNCAInfo { // the lowest and highest points in the infinite loop. In theory, it // would be nice to give the canonical backedge for the loop, but it's // expensive and does not always lead to a minimal set of roots. - DEBUG(dbgs() << "\t\t\tRunning forward DFS\n"); + LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n"); const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num); const NodePtr FurthestAway = SNCA.NumToNode[NewNum]; - DEBUG(dbgs() << "\t\t\tFound a new furthest away node " - << "(non-trivial root): " - << BlockNamePrinter(FurthestAway) << "\n"); + LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node " + << "(non-trivial root): " + << BlockNamePrinter(FurthestAway) << "\n"); ConnectToExitBlock.insert(FurthestAway); Roots.push_back(FurthestAway); - DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: " - << NewNum << "\n\t\t\tRemoving DFS info\n"); + LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: " + << NewNum << "\n\t\t\tRemoving DFS info\n"); for (unsigned i = NewNum; i > Num; --i) { const NodePtr N = SNCA.NumToNode[i]; - DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for " - << BlockNamePrinter(N) << "\n"); + LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for " + << BlockNamePrinter(N) << "\n"); SNCA.NodeToInfo.erase(N); SNCA.NumToNode.pop_back(); } const unsigned PrevNum = Num; - DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n"); + LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n"); Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1); for (unsigned i = PrevNum + 1; i <= Num; ++i) - DEBUG(dbgs() << "\t\t\t\tfound node " - << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); + LLVM_DEBUG(dbgs() << "\t\t\t\tfound node " + << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); } } } - DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n"); - DEBUG(dbgs() << "Discovered CFG nodes:\n"); - DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs() - << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); + LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n"); + LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n"); + LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs() + << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); assert((Total + 1 == Num) && "Everything should have been visited"); // Step #3: If we found some non-trivial roots, make them non-redundant. if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots); - DEBUG(dbgs() << "Found roots: "); - DEBUG(for (auto *Root : Roots) dbgs() << BlockNamePrinter(Root) << " "); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "Found roots: "); + LLVM_DEBUG(for (auto *Root + : Roots) dbgs() + << BlockNamePrinter(Root) << " "); + LLVM_DEBUG(dbgs() << "\n"); return Roots; } @@ -499,7 +501,7 @@ struct SemiNCAInfo { static void RemoveRedundantRoots(const DomTreeT &DT, BatchUpdatePtr BUI, RootsT &Roots) { assert(IsPostDom && "This function is for postdominators only"); - DEBUG(dbgs() << "Removing redundant roots\n"); + LLVM_DEBUG(dbgs() << "Removing redundant roots\n"); SemiNCAInfo SNCA(BUI); @@ -507,8 +509,8 @@ struct SemiNCAInfo { auto &Root = Roots[i]; // Trivial roots are always non-redundant. if (!HasForwardSuccessors(Root, BUI)) continue; - DEBUG(dbgs() << "\tChecking if " << BlockNamePrinter(Root) - << " remains a root\n"); + LLVM_DEBUG(dbgs() << "\tChecking if " << BlockNamePrinter(Root) + << " remains a root\n"); SNCA.clear(); // Do a forward walk looking for the other roots. const unsigned Num = SNCA.runDFS<true>(Root, 0, AlwaysDescend, 0); @@ -520,9 +522,9 @@ struct SemiNCAInfo { // root from the set of roots, as it is reverse-reachable from the other // one. if (llvm::find(Roots, N) != Roots.end()) { - DEBUG(dbgs() << "\tForward DFS walk found another root " - << BlockNamePrinter(N) << "\n\tRemoving root " - << BlockNamePrinter(Root) << "\n"); + LLVM_DEBUG(dbgs() << "\tForward DFS walk found another root " + << BlockNamePrinter(N) << "\n\tRemoving root " + << BlockNamePrinter(Root) << "\n"); std::swap(Root, Roots.back()); Roots.pop_back(); @@ -563,7 +565,8 @@ struct SemiNCAInfo { SNCA.runSemiNCA(DT); if (BUI) { BUI->IsRecalculated = true; - DEBUG(dbgs() << "DomTree recalculated, skipping future batch updates\n"); + LLVM_DEBUG( + dbgs() << "DomTree recalculated, skipping future batch updates\n"); } if (DT.Roots.empty()) return; @@ -585,8 +588,8 @@ struct SemiNCAInfo { // Loop over all of the discovered blocks in the function... for (size_t i = 1, e = NumToNode.size(); i != e; ++i) { NodePtr W = NumToNode[i]; - DEBUG(dbgs() << "\tdiscovered a new reachable node " - << BlockNamePrinter(W) << "\n"); + LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node " + << BlockNamePrinter(W) << "\n"); // Don't replace this with 'count', the insertion side effect is important if (DT.DomTreeNodes[W]) continue; // Haven't calculated this node yet? @@ -638,8 +641,8 @@ struct SemiNCAInfo { assert((From || IsPostDom) && "From has to be a valid CFG node or a virtual root"); assert(To && "Cannot be a nullptr"); - DEBUG(dbgs() << "Inserting edge " << BlockNamePrinter(From) << " -> " - << BlockNamePrinter(To) << "\n"); + LLVM_DEBUG(dbgs() << "Inserting edge " << BlockNamePrinter(From) << " -> " + << BlockNamePrinter(To) << "\n"); TreeNodePtr FromTN = DT.getNode(From); if (!FromTN) { @@ -678,8 +681,8 @@ struct SemiNCAInfo { if (RIt == DT.Roots.end()) return false; // To is not a root, nothing to update. - DEBUG(dbgs() << "\t\tAfter the insertion, " << BlockNamePrinter(To) - << " is no longer a root\n\t\tRebuilding the tree!!!\n"); + LLVM_DEBUG(dbgs() << "\t\tAfter the insertion, " << BlockNamePrinter(To) + << " is no longer a root\n\t\tRebuilding the tree!!!\n"); CalculateFromScratch(DT, BUI); return true; @@ -706,8 +709,8 @@ struct SemiNCAInfo { // can make a different (implicit) decision about which node within an // infinite loop becomes a root. - DEBUG(dbgs() << "Roots are different in updated trees\n" - << "The entire tree needs to be rebuilt\n"); + LLVM_DEBUG(dbgs() << "Roots are different in updated trees\n" + << "The entire tree needs to be rebuilt\n"); // It may be possible to update the tree without recalculating it, but // we do not know yet how to do it, and it happens rarely in practise. CalculateFromScratch(DT, BUI); @@ -718,8 +721,8 @@ struct SemiNCAInfo { // Handles insertion to a node already in the dominator tree. static void InsertReachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr From, const TreeNodePtr To) { - DEBUG(dbgs() << "\tReachable " << BlockNamePrinter(From->getBlock()) - << " -> " << BlockNamePrinter(To->getBlock()) << "\n"); + LLVM_DEBUG(dbgs() << "\tReachable " << BlockNamePrinter(From->getBlock()) + << " -> " << BlockNamePrinter(To->getBlock()) << "\n"); if (IsPostDom && UpdateRootsBeforeInsertion(DT, BUI, From, To)) return; // DT.findNCD expects both pointers to be valid. When From is a virtual // root, then its CFG block pointer is a nullptr, so we have to 'compute' @@ -732,7 +735,7 @@ struct SemiNCAInfo { const TreeNodePtr NCD = DT.getNode(NCDBlock); assert(NCD); - DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n"); + LLVM_DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n"); const TreeNodePtr ToIDom = To->getIDom(); // Nothing affected -- NCA property holds. @@ -741,18 +744,20 @@ struct SemiNCAInfo { // Identify and collect affected nodes. InsertionInfo II; - DEBUG(dbgs() << "Marking " << BlockNamePrinter(To) << " as affected\n"); + LLVM_DEBUG(dbgs() << "Marking " << BlockNamePrinter(To) + << " as affected\n"); II.Affected.insert(To); const unsigned ToLevel = To->getLevel(); - DEBUG(dbgs() << "Putting " << BlockNamePrinter(To) << " into a Bucket\n"); + LLVM_DEBUG(dbgs() << "Putting " << BlockNamePrinter(To) + << " into a Bucket\n"); II.Bucket.push({ToLevel, To}); while (!II.Bucket.empty()) { const TreeNodePtr CurrentNode = II.Bucket.top().second; const unsigned CurrentLevel = CurrentNode->getLevel(); II.Bucket.pop(); - DEBUG(dbgs() << "\tAdding to Visited and AffectedQueue: " - << BlockNamePrinter(CurrentNode) << "\n"); + LLVM_DEBUG(dbgs() << "\tAdding to Visited and AffectedQueue: " + << BlockNamePrinter(CurrentNode) << "\n"); II.Visited.insert({CurrentNode, CurrentLevel}); II.AffectedQueue.push_back(CurrentNode); @@ -770,8 +775,8 @@ struct SemiNCAInfo { const TreeNodePtr TN, const unsigned RootLevel, const TreeNodePtr NCD, InsertionInfo &II) { const unsigned NCDLevel = NCD->getLevel(); - DEBUG(dbgs() << "Visiting " << BlockNamePrinter(TN) << ", RootLevel " - << RootLevel << "\n"); + LLVM_DEBUG(dbgs() << "Visiting " << BlockNamePrinter(TN) << ", RootLevel " + << RootLevel << "\n"); SmallVector<TreeNodePtr, 8> Stack = {TN}; assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!"); @@ -780,7 +785,7 @@ struct SemiNCAInfo { do { TreeNodePtr Next = Stack.pop_back_val(); - DEBUG(dbgs() << " Next: " << BlockNamePrinter(Next) << "\n"); + LLVM_DEBUG(dbgs() << " Next: " << BlockNamePrinter(Next) << "\n"); for (const NodePtr Succ : ChildrenGetter<IsPostDom>::Get(Next->getBlock(), BUI)) { @@ -788,8 +793,8 @@ struct SemiNCAInfo { assert(SuccTN && "Unreachable successor found at reachable insertion"); const unsigned SuccLevel = SuccTN->getLevel(); - DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ) << ", level = " - << SuccLevel << "\n"); + LLVM_DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ) + << ", level = " << SuccLevel << "\n"); // Do not process the same node multiple times. if (Processed.count(Next) > 0) @@ -798,11 +803,11 @@ struct SemiNCAInfo { // Succ dominated by subtree From -- not affected. // (Based on the lemma 2.5 from the second paper.) if (SuccLevel > RootLevel) { - DEBUG(dbgs() << "\t\tDominated by subtree From\n"); + LLVM_DEBUG(dbgs() << "\t\tDominated by subtree From\n"); if (II.Visited.count(SuccTN) != 0) { - DEBUG(dbgs() << "\t\t\talready visited at level " - << II.Visited[SuccTN] << "\n\t\t\tcurrent level " - << RootLevel << ")\n"); + LLVM_DEBUG(dbgs() << "\t\t\talready visited at level " + << II.Visited[SuccTN] << "\n\t\t\tcurrent level " + << RootLevel << ")\n"); // A node can be necessary to visit again if we see it again at // a lower level than before. @@ -810,15 +815,15 @@ struct SemiNCAInfo { continue; } - DEBUG(dbgs() << "\t\tMarking visited not affected " - << BlockNamePrinter(Succ) << "\n"); + LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected " + << BlockNamePrinter(Succ) << "\n"); II.Visited.insert({SuccTN, RootLevel}); II.VisitedNotAffectedQueue.push_back(SuccTN); Stack.push_back(SuccTN); } else if ((SuccLevel > NCDLevel + 1) && II.Affected.count(SuccTN) == 0) { - DEBUG(dbgs() << "\t\tMarking affected and adding " - << BlockNamePrinter(Succ) << " to a Bucket\n"); + LLVM_DEBUG(dbgs() << "\t\tMarking affected and adding " + << BlockNamePrinter(Succ) << " to a Bucket\n"); II.Affected.insert(SuccTN); II.Bucket.push({SuccLevel, SuccTN}); } @@ -831,11 +836,11 @@ struct SemiNCAInfo { // Updates immediate dominators and levels after insertion. static void UpdateInsertion(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr NCD, InsertionInfo &II) { - DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n"); + LLVM_DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n"); for (const TreeNodePtr TN : II.AffectedQueue) { - DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN) - << ") = " << BlockNamePrinter(NCD) << "\n"); + LLVM_DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN) + << ") = " << BlockNamePrinter(NCD) << "\n"); TN->setIDom(NCD); } @@ -844,12 +849,13 @@ struct SemiNCAInfo { } static void UpdateLevelsAfterInsertion(InsertionInfo &II) { - DEBUG(dbgs() << "Updating levels for visited but not affected nodes\n"); + LLVM_DEBUG( + dbgs() << "Updating levels for visited but not affected nodes\n"); for (const TreeNodePtr TN : II.VisitedNotAffectedQueue) { - DEBUG(dbgs() << "\tlevel(" << BlockNamePrinter(TN) << ") = (" - << BlockNamePrinter(TN->getIDom()) << ") " - << TN->getIDom()->getLevel() << " + 1\n"); + LLVM_DEBUG(dbgs() << "\tlevel(" << BlockNamePrinter(TN) << ") = (" + << BlockNamePrinter(TN->getIDom()) << ") " + << TN->getIDom()->getLevel() << " + 1\n"); TN->UpdateLevel(); } } @@ -857,23 +863,24 @@ struct SemiNCAInfo { // Handles insertion to previously unreachable nodes. static void InsertUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr From, const NodePtr To) { - DEBUG(dbgs() << "Inserting " << BlockNamePrinter(From) - << " -> (unreachable) " << BlockNamePrinter(To) << "\n"); + LLVM_DEBUG(dbgs() << "Inserting " << BlockNamePrinter(From) + << " -> (unreachable) " << BlockNamePrinter(To) << "\n"); // Collect discovered edges to already reachable nodes. SmallVector<std::pair<NodePtr, TreeNodePtr>, 8> DiscoveredEdgesToReachable; // Discover and connect nodes that became reachable with the insertion. ComputeUnreachableDominators(DT, BUI, To, From, DiscoveredEdgesToReachable); - DEBUG(dbgs() << "Inserted " << BlockNamePrinter(From) - << " -> (prev unreachable) " << BlockNamePrinter(To) << "\n"); + LLVM_DEBUG(dbgs() << "Inserted " << BlockNamePrinter(From) + << " -> (prev unreachable) " << BlockNamePrinter(To) + << "\n"); // Used the discovered edges and inset discovered connecting (incoming) // edges. for (const auto &Edge : DiscoveredEdgesToReachable) { - DEBUG(dbgs() << "\tInserting discovered connecting edge " - << BlockNamePrinter(Edge.first) << " -> " - << BlockNamePrinter(Edge.second) << "\n"); + LLVM_DEBUG(dbgs() << "\tInserting discovered connecting edge " + << BlockNamePrinter(Edge.first) << " -> " + << BlockNamePrinter(Edge.second) << "\n"); InsertReachable(DT, BUI, DT.getNode(Edge.first), Edge.second); } } @@ -901,14 +908,14 @@ struct SemiNCAInfo { SNCA.runSemiNCA(DT); SNCA.attachNewSubtree(DT, Incoming); - DEBUG(dbgs() << "After adding unreachable nodes\n"); + LLVM_DEBUG(dbgs() << "After adding unreachable nodes\n"); } static void DeleteEdge(DomTreeT &DT, const BatchUpdatePtr BUI, const NodePtr From, const NodePtr To) { assert(From && To && "Cannot disconnect nullptrs"); - DEBUG(dbgs() << "Deleting edge " << BlockNamePrinter(From) << " -> " - << BlockNamePrinter(To) << "\n"); + LLVM_DEBUG(dbgs() << "Deleting edge " << BlockNamePrinter(From) << " -> " + << BlockNamePrinter(To) << "\n"); #ifndef NDEBUG // Ensure that the edge was in fact deleted from the CFG before informing @@ -928,8 +935,9 @@ struct SemiNCAInfo { const TreeNodePtr ToTN = DT.getNode(To); if (!ToTN) { - DEBUG(dbgs() << "\tTo (" << BlockNamePrinter(To) - << ") already unreachable -- there is no edge to delete\n"); + LLVM_DEBUG( + dbgs() << "\tTo (" << BlockNamePrinter(To) + << ") already unreachable -- there is no edge to delete\n"); return; } @@ -941,8 +949,8 @@ struct SemiNCAInfo { DT.DFSInfoValid = false; const TreeNodePtr ToIDom = ToTN->getIDom(); - DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom " - << BlockNamePrinter(ToIDom) << "\n"); + LLVM_DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom " + << BlockNamePrinter(ToIDom) << "\n"); // To remains reachable after deletion. // (Based on the caption under Figure 4. from the second paper.) @@ -959,9 +967,9 @@ struct SemiNCAInfo { static void DeleteReachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr FromTN, const TreeNodePtr ToTN) { - DEBUG(dbgs() << "Deleting reachable " << BlockNamePrinter(FromTN) << " -> " - << BlockNamePrinter(ToTN) << "\n"); - DEBUG(dbgs() << "\tRebuilding subtree\n"); + LLVM_DEBUG(dbgs() << "Deleting reachable " << BlockNamePrinter(FromTN) + << " -> " << BlockNamePrinter(ToTN) << "\n"); + LLVM_DEBUG(dbgs() << "\tRebuilding subtree\n"); // Find the top of the subtree that needs to be rebuilt. // (Based on the lemma 2.6 from the second paper.) @@ -974,7 +982,7 @@ struct SemiNCAInfo { // Top of the subtree to rebuild is the root node. Rebuild the tree from // scratch. if (!PrevIDomSubTree) { - DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); + LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); CalculateFromScratch(DT, BUI); return; } @@ -985,11 +993,12 @@ struct SemiNCAInfo { return DT.getNode(To)->getLevel() > Level; }; - DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN) << "\n"); + LLVM_DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN) + << "\n"); SemiNCAInfo SNCA(BUI); SNCA.runDFS(ToIDom, 0, DescendBelow, 0); - DEBUG(dbgs() << "\tRunning Semi-NCA\n"); + LLVM_DEBUG(dbgs() << "\tRunning Semi-NCA\n"); SNCA.runSemiNCA(DT, Level); SNCA.reattachExistingSubtree(DT, PrevIDomSubTree); } @@ -998,19 +1007,20 @@ struct SemiNCAInfo { // explained on the page 7 of the second paper. static bool HasProperSupport(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr TN) { - DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN) << "\n"); + LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN) + << "\n"); for (const NodePtr Pred : ChildrenGetter<!IsPostDom>::Get(TN->getBlock(), BUI)) { - DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n"); + LLVM_DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n"); if (!DT.getNode(Pred)) continue; const NodePtr Support = DT.findNearestCommonDominator(TN->getBlock(), Pred); - DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n"); + LLVM_DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n"); if (Support != TN->getBlock()) { - DEBUG(dbgs() << "\t" << BlockNamePrinter(TN) - << " is reachable from support " - << BlockNamePrinter(Support) << "\n"); + LLVM_DEBUG(dbgs() << "\t" << BlockNamePrinter(TN) + << " is reachable from support " + << BlockNamePrinter(Support) << "\n"); return true; } } @@ -1022,8 +1032,8 @@ struct SemiNCAInfo { // (Based on the lemma 2.7 from the second paper.) static void DeleteUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr ToTN) { - DEBUG(dbgs() << "Deleting unreachable subtree " << BlockNamePrinter(ToTN) - << "\n"); + LLVM_DEBUG(dbgs() << "Deleting unreachable subtree " + << BlockNamePrinter(ToTN) << "\n"); assert(ToTN); assert(ToTN->getBlock()); @@ -1031,8 +1041,9 @@ struct SemiNCAInfo { // Deletion makes a region reverse-unreachable and creates a new root. // Simulate that by inserting an edge from the virtual root to ToTN and // adding it as a new root. - DEBUG(dbgs() << "\tDeletion made a region reverse-unreachable\n"); - DEBUG(dbgs() << "\tAdding new root " << BlockNamePrinter(ToTN) << "\n"); + LLVM_DEBUG(dbgs() << "\tDeletion made a region reverse-unreachable\n"); + LLVM_DEBUG(dbgs() << "\tAdding new root " << BlockNamePrinter(ToTN) + << "\n"); DT.Roots.push_back(ToTN->getBlock()); InsertReachable(DT, BUI, DT.getNode(nullptr), ToTN); return; @@ -1069,15 +1080,15 @@ struct SemiNCAInfo { const TreeNodePtr NCD = DT.getNode(NCDBlock); assert(NCD); - DEBUG(dbgs() << "Processing affected node " << BlockNamePrinter(TN) - << " with NCD = " << BlockNamePrinter(NCD) - << ", MinNode =" << BlockNamePrinter(MinNode) << "\n"); + LLVM_DEBUG(dbgs() << "Processing affected node " << BlockNamePrinter(TN) + << " with NCD = " << BlockNamePrinter(NCD) + << ", MinNode =" << BlockNamePrinter(MinNode) << "\n"); if (NCD != TN && NCD->getLevel() < MinNode->getLevel()) MinNode = NCD; } // Root reached, rebuild the whole tree from scratch. if (!MinNode->getIDom()) { - DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); + LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); CalculateFromScratch(DT, BUI); return; } @@ -1087,7 +1098,7 @@ struct SemiNCAInfo { for (unsigned i = LastDFSNum; i > 0; --i) { const NodePtr N = SNCA.NumToNode[i]; const TreeNodePtr TN = DT.getNode(N); - DEBUG(dbgs() << "Erasing node " << BlockNamePrinter(TN) << "\n"); + LLVM_DEBUG(dbgs() << "Erasing node " << BlockNamePrinter(TN) << "\n"); EraseNode(DT, TN); } @@ -1095,8 +1106,8 @@ struct SemiNCAInfo { // The affected subtree start at the To node -- there's no extra work to do. if (MinNode == ToTN) return; - DEBUG(dbgs() << "DeleteUnreachable: running DFS with MinNode = " - << BlockNamePrinter(MinNode) << "\n"); + LLVM_DEBUG(dbgs() << "DeleteUnreachable: running DFS with MinNode = " + << BlockNamePrinter(MinNode) << "\n"); const unsigned MinLevel = MinNode->getLevel(); const TreeNodePtr PrevIDom = MinNode->getIDom(); assert(PrevIDom); @@ -1109,8 +1120,8 @@ struct SemiNCAInfo { }; SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0); - DEBUG(dbgs() << "Previous IDom(MinNode) = " << BlockNamePrinter(PrevIDom) - << "\nRunning Semi-NCA\n"); + LLVM_DEBUG(dbgs() << "Previous IDom(MinNode) = " + << BlockNamePrinter(PrevIDom) << "\nRunning Semi-NCA\n"); // Rebuild the remaining part of affected subtree. SNCA.runSemiNCA(DT, MinLevel); @@ -1165,15 +1176,15 @@ struct SemiNCAInfo { // predecessors. Note that these sets will only decrease size over time, as // the next CFG snapshots slowly approach the actual (current) CFG. for (UpdateT &U : BUI.Updates) { - BUI.FutureSuccessors[U.getFrom()].insert({U.getTo(), U.getKind()}); - BUI.FuturePredecessors[U.getTo()].insert({U.getFrom(), U.getKind()}); + BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()}); + BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()}); } - DEBUG(dbgs() << "About to apply " << NumLegalized << " updates\n"); - DEBUG(if (NumLegalized < 32) for (const auto &U - : reverse(BUI.Updates)) dbgs() - << '\t' << U << "\n"); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "About to apply " << NumLegalized << " updates\n"); + LLVM_DEBUG(if (NumLegalized < 32) for (const auto &U + : reverse(BUI.Updates)) dbgs() + << '\t' << U << "\n"); + LLVM_DEBUG(dbgs() << "\n"); // If the DominatorTree was recalculated at some point, stop the batch // updates. Full recalculations ignore batch updates and look at the actual @@ -1201,7 +1212,7 @@ struct SemiNCAInfo { // minimizes the amount of work needed done during incremental updates. static void LegalizeUpdates(ArrayRef<UpdateT> AllUpdates, SmallVectorImpl<UpdateT> &Result) { - DEBUG(dbgs() << "Legalizing " << AllUpdates.size() << " updates\n"); + LLVM_DEBUG(dbgs() << "Legalizing " << AllUpdates.size() << " updates\n"); // Count the total number of inserions of each edge. // Each insertion adds 1 and deletion subtracts 1. The end number should be // one of {-1 (deletion), 0 (NOP), +1 (insertion)}. Otherwise, the sequence @@ -1241,26 +1252,31 @@ struct SemiNCAInfo { Operations[{U.getTo(), U.getFrom()}] = int(i); } - std::sort(Result.begin(), Result.end(), - [&Operations](const UpdateT &A, const UpdateT &B) { - return Operations[{A.getFrom(), A.getTo()}] > - Operations[{B.getFrom(), B.getTo()}]; - }); + llvm::sort(Result.begin(), Result.end(), + [&Operations](const UpdateT &A, const UpdateT &B) { + return Operations[{A.getFrom(), A.getTo()}] > + Operations[{B.getFrom(), B.getTo()}]; + }); } static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI) { assert(!BUI.Updates.empty() && "No updates to apply!"); UpdateT CurrentUpdate = BUI.Updates.pop_back_val(); - DEBUG(dbgs() << "Applying update: " << CurrentUpdate << "\n"); + LLVM_DEBUG(dbgs() << "Applying update: " << CurrentUpdate << "\n"); // Move to the next snapshot of the CFG by removing the reverse-applied - // current update. + // current update. Since updates are performed in the same order they are + // legalized it's sufficient to pop the last item here. auto &FS = BUI.FutureSuccessors[CurrentUpdate.getFrom()]; - FS.erase({CurrentUpdate.getTo(), CurrentUpdate.getKind()}); + assert(FS.back().getPointer() == CurrentUpdate.getTo() && + FS.back().getInt() == CurrentUpdate.getKind()); + FS.pop_back(); if (FS.empty()) BUI.FutureSuccessors.erase(CurrentUpdate.getFrom()); auto &FP = BUI.FuturePredecessors[CurrentUpdate.getTo()]; - FP.erase({CurrentUpdate.getFrom(), CurrentUpdate.getKind()}); + assert(FP.back().getPointer() == CurrentUpdate.getFrom() && + FP.back().getInt() == CurrentUpdate.getKind()); + FP.pop_back(); if (FP.empty()) BUI.FuturePredecessors.erase(CurrentUpdate.getTo()); if (CurrentUpdate.getKind() == UpdateKind::Insert) @@ -1277,6 +1293,7 @@ struct SemiNCAInfo { // root which is the function's entry node. A PostDominatorTree can have // multiple roots - one for each node with no successors and for infinite // loops. + // Running time: O(N). bool verifyRoots(const DomTreeT &DT) { if (!DT.Parent && !DT.Roots.empty()) { errs() << "Tree has no parent but has roots!\n"; @@ -1317,6 +1334,7 @@ struct SemiNCAInfo { } // Checks if the tree contains all reachable nodes in the input graph. + // Running time: O(N). bool verifyReachability(const DomTreeT &DT) { clear(); doFullDFSWalk(DT, AlwaysDescend); @@ -1352,6 +1370,7 @@ struct SemiNCAInfo { // Check if for every parent with a level L in the tree all of its children // have level L + 1. + // Running time: O(N). static bool VerifyLevels(const DomTreeT &DT) { for (auto &NodeToTN : DT.DomTreeNodes) { const TreeNodePtr TN = NodeToTN.second.get(); @@ -1383,6 +1402,7 @@ struct SemiNCAInfo { // Check if the computed DFS numbers are correct. Note that DFS info may not // be valid, and when that is the case, we don't verify the numbers. + // Running time: O(N log(N)). static bool VerifyDFSNumbers(const DomTreeT &DT) { if (!DT.DFSInfoValid || !DT.Parent) return true; @@ -1426,10 +1446,10 @@ struct SemiNCAInfo { // Make a copy and sort it such that it is possible to check if there are // no gaps between DFS numbers of adjacent children. SmallVector<TreeNodePtr, 8> Children(Node->begin(), Node->end()); - std::sort(Children.begin(), Children.end(), - [](const TreeNodePtr Ch1, const TreeNodePtr Ch2) { - return Ch1->getDFSNumIn() < Ch2->getDFSNumIn(); - }); + llvm::sort(Children.begin(), Children.end(), + [](const TreeNodePtr Ch1, const TreeNodePtr Ch2) { + return Ch1->getDFSNumIn() < Ch2->getDFSNumIn(); + }); auto PrintChildrenError = [Node, &Children, PrintNodeAndDFSNums]( const TreeNodePtr FirstCh, const TreeNodePtr SecondCh) { @@ -1513,10 +1533,10 @@ struct SemiNCAInfo { // linear time, but the algorithms are complex. Instead, we do it in a // straightforward N^2 and N^3 way below, using direct path reachability. - // Checks if the tree has the parent property: if for all edges from V to W in // the input graph, such that V is reachable, the parent of W in the tree is // an ancestor of V in the tree. + // Running time: O(N^2). // // This means that if a node gets disconnected from the graph, then all of // the nodes it dominated previously will now become unreachable. @@ -1526,8 +1546,8 @@ struct SemiNCAInfo { const NodePtr BB = TN->getBlock(); if (!BB || TN->getChildren().empty()) continue; - DEBUG(dbgs() << "Verifying parent property of node " - << BlockNamePrinter(TN) << "\n"); + LLVM_DEBUG(dbgs() << "Verifying parent property of node " + << BlockNamePrinter(TN) << "\n"); clear(); doFullDFSWalk(DT, [BB](NodePtr From, NodePtr To) { return From != BB && To != BB; @@ -1549,6 +1569,7 @@ struct SemiNCAInfo { // Check if the tree has sibling property: if a node V does not dominate a // node W for all siblings V and W in the tree. + // Running time: O(N^3). // // This means that if a node gets disconnected from the graph, then all of its // siblings will now still be reachable. @@ -1583,6 +1604,31 @@ struct SemiNCAInfo { return true; } + + // Check if the given tree is the same as a freshly computed one for the same + // Parent. + // Running time: O(N^2), but faster in practise (same as tree construction). + // + // Note that this does not check if that the tree construction algorithm is + // correct and should be only used for fast (but possibly unsound) + // verification. + static bool IsSameAsFreshTree(const DomTreeT &DT) { + DomTreeT FreshTree; + FreshTree.recalculate(*DT.Parent); + const bool Different = DT.compare(FreshTree); + + if (Different) { + errs() << (DT.isPostDominator() ? "Post" : "") + << "DominatorTree is different than a freshly computed one!\n" + << "\tCurrent:\n"; + DT.print(errs()); + errs() << "\n\tFreshly computed tree:\n"; + FreshTree.print(errs()); + errs().flush(); + } + + return !Different; + } }; template <class DomTreeT> @@ -1611,11 +1657,29 @@ void ApplyUpdates(DomTreeT &DT, } template <class DomTreeT> -bool Verify(const DomTreeT &DT) { +bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL) { SemiNCAInfo<DomTreeT> SNCA(nullptr); - return SNCA.verifyRoots(DT) && SNCA.verifyReachability(DT) && - SNCA.VerifyLevels(DT) && SNCA.verifyParentProperty(DT) && - SNCA.verifySiblingProperty(DT) && SNCA.VerifyDFSNumbers(DT); + + // Simplist check is to compare against a new tree. This will also + // usefully print the old and new trees, if they are different. + if (!SNCA.IsSameAsFreshTree(DT)) + return false; + + // Common checks to verify the properties of the tree. O(N log N) at worst + if (!SNCA.verifyRoots(DT) || !SNCA.verifyReachability(DT) || + !SNCA.VerifyLevels(DT) || !SNCA.VerifyDFSNumbers(DT)) + return false; + + // Extra checks depending on VerificationLevel. Up to O(N^3) + if (VL == DomTreeT::VerificationLevel::Basic || + VL == DomTreeT::VerificationLevel::Full) + if (!SNCA.verifyParentProperty(DT)) + return false; + if (VL == DomTreeT::VerificationLevel::Full) + if (!SNCA.verifySiblingProperty(DT)) + return false; + + return true; } } // namespace DomTreeBuilder diff --git a/contrib/llvm/include/llvm/Support/GraphWriter.h b/contrib/llvm/include/llvm/Support/GraphWriter.h index 3df5c867f7d3..c9a9f409c522 100644 --- a/contrib/llvm/include/llvm/Support/GraphWriter.h +++ b/contrib/llvm/include/llvm/Support/GraphWriter.h @@ -41,7 +41,7 @@ namespace DOT { // Private functions... std::string EscapeString(const std::string &Label); -/// \brief Get a color string for this node number. Simply round-robin selects +/// Get a color string for this node number. Simply round-robin selects /// from a reasonable number of colors. StringRef getColorString(unsigned NodeNumber); diff --git a/contrib/llvm/include/llvm/Support/Host.h b/contrib/llvm/include/llvm/Support/Host.h index a4b0a340c568..57c79c0b9fdf 100644 --- a/contrib/llvm/include/llvm/Support/Host.h +++ b/contrib/llvm/include/llvm/Support/Host.h @@ -31,7 +31,7 @@ #define BYTE_ORDER LITTLE_ENDIAN #endif #else -#if !defined(BYTE_ORDER) && !defined(LLVM_ON_WIN32) +#if !defined(BYTE_ORDER) && !defined(_WIN32) #include <machine/endian.h> #endif #endif @@ -88,9 +88,9 @@ constexpr bool IsBigEndianHost = false; namespace detail { /// Helper functions to extract HostCPUName from /proc/cpuinfo on linux. - StringRef getHostCPUNameForPowerPC(const StringRef &ProcCpuinfoContent); - StringRef getHostCPUNameForARM(const StringRef &ProcCpuinfoContent); - StringRef getHostCPUNameForS390x(const StringRef &ProcCpuinfoContent); + StringRef getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent); + StringRef getHostCPUNameForARM(StringRef ProcCpuinfoContent); + StringRef getHostCPUNameForS390x(StringRef ProcCpuinfoContent); StringRef getHostCPUNameForBPF(); } } diff --git a/contrib/llvm/include/llvm/Support/InitLLVM.h b/contrib/llvm/include/llvm/Support/InitLLVM.h new file mode 100644 index 000000000000..0f629c9ac92d --- /dev/null +++ b/contrib/llvm/include/llvm/Support/InitLLVM.h @@ -0,0 +1,46 @@ +//===- InitLLVM.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_LLVM_H +#define LLVM_SUPPORT_LLVM_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/PrettyStackTrace.h" + +// The main() functions in typical LLVM tools start with InitLLVM which does +// the following one-time initializations: +// +// 1. Setting up a signal handler so that pretty stack trace is printed out +// if a process crashes. +// +// 2. If running on Windows, obtain command line arguments using a +// multibyte character-aware API and convert arguments into UTF-8 +// encoding, so that you can assume that command line arguments are +// always encoded in UTF-8 on any platform. +// +// InitLLVM calls llvm_shutdown() on destruction, which cleans up +// ManagedStatic objects. +namespace llvm { +class InitLLVM { +public: + InitLLVM(int &Argc, const char **&Argv); + InitLLVM(int &Argc, char **&Argv) + : InitLLVM(Argc, const_cast<const char **&>(Argv)) {} + + ~InitLLVM(); + +private: + BumpPtrAllocator Alloc; + SmallVector<const char *, 0> Args; + PrettyStackTraceProgram StackPrinter; +}; +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Support/JSON.h b/contrib/llvm/include/llvm/Support/JSON.h new file mode 100644 index 000000000000..da3c5ea0b25d --- /dev/null +++ b/contrib/llvm/include/llvm/Support/JSON.h @@ -0,0 +1,704 @@ +//===--- JSON.h - JSON values, parsing and serialization -------*- 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 supports working with JSON data. +/// +/// It comprises: +/// +/// - classes which hold dynamically-typed parsed JSON structures +/// These are value types that can be composed, inspected, and modified. +/// See json::Value, and the related types json::Object and json::Array. +/// +/// - functions to parse JSON text into Values, and to serialize Values to text. +/// See parse(), operator<<, and format_provider. +/// +/// - a convention and helpers for mapping between json::Value and user-defined +/// types. See fromJSON(), ObjectMapper, and the class comment on Value. +/// +/// Typically, JSON data would be read from an external source, parsed into +/// a Value, and then converted into some native data structure before doing +/// real work on it. (And vice versa when writing). +/// +/// Other serialization mechanisms you may consider: +/// +/// - YAML is also text-based, and more human-readable than JSON. It's a more +/// complex format and data model, and YAML parsers aren't ubiquitous. +/// YAMLParser.h is a streaming parser suitable for parsing large documents +/// (including JSON, as YAML is a superset). It can be awkward to use +/// directly. YAML I/O (YAMLTraits.h) provides data mapping that is more +/// declarative than the toJSON/fromJSON conventions here. +/// +/// - LLVM bitstream is a space- and CPU- efficient binary format. Typically it +/// encodes LLVM IR ("bitcode"), but it can be a container for other data. +/// Low-level reader/writer libraries are in Bitcode/Bitstream*.h +/// +//===---------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_JSON_H +#define LLVM_SUPPORT_JSON_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/raw_ostream.h" +#include <map> + +namespace llvm { +namespace json { + +// === String encodings === +// +// JSON strings are character sequences (not byte sequences like std::string). +// We need to know the encoding, and for simplicity only support UTF-8. +// +// - When parsing, invalid UTF-8 is a syntax error like any other +// +// - When creating Values from strings, callers must ensure they are UTF-8. +// with asserts on, invalid UTF-8 will crash the program +// with asserts off, we'll substitute the replacement character (U+FFFD) +// Callers can use json::isUTF8() and json::fixUTF8() for validation. +// +// - When retrieving strings from Values (e.g. asString()), the result will +// always be valid UTF-8. + +/// Returns true if \p S is valid UTF-8, which is required for use as JSON. +/// If it returns false, \p Offset is set to a byte offset near the first error. +bool isUTF8(llvm::StringRef S, size_t *ErrOffset = nullptr); +/// Replaces invalid UTF-8 sequences in \p S with the replacement character +/// (U+FFFD). The returned string is valid UTF-8. +/// This is much slower than isUTF8, so test that first. +std::string fixUTF8(llvm::StringRef S); + +class Array; +class ObjectKey; +class Value; +template <typename T> Value toJSON(const llvm::Optional<T> &Opt); + +/// An Object is a JSON object, which maps strings to heterogenous JSON values. +/// It simulates DenseMap<ObjectKey, Value>. ObjectKey is a maybe-owned string. +class Object { + using Storage = DenseMap<ObjectKey, Value, llvm::DenseMapInfo<StringRef>>; + Storage M; + +public: + using key_type = ObjectKey; + using mapped_type = Value; + using value_type = Storage::value_type; + using iterator = Storage::iterator; + using const_iterator = Storage::const_iterator; + + explicit Object() = default; + // KV is a trivial key-value struct for list-initialization. + // (using std::pair forces extra copies). + struct KV; + explicit Object(std::initializer_list<KV> Properties); + + iterator begin() { return M.begin(); } + const_iterator begin() const { return M.begin(); } + iterator end() { return M.end(); } + const_iterator end() const { return M.end(); } + + bool empty() const { return M.empty(); } + size_t size() const { return M.size(); } + + void clear() { M.clear(); } + std::pair<iterator, bool> insert(KV E); + template <typename... Ts> + std::pair<iterator, bool> try_emplace(const ObjectKey &K, Ts &&... Args) { + return M.try_emplace(K, std::forward<Ts>(Args)...); + } + template <typename... Ts> + std::pair<iterator, bool> try_emplace(ObjectKey &&K, Ts &&... Args) { + return M.try_emplace(std::move(K), std::forward<Ts>(Args)...); + } + + iterator find(StringRef K) { return M.find_as(K); } + const_iterator find(StringRef K) const { return M.find_as(K); } + // operator[] acts as if Value was default-constructible as null. + Value &operator[](const ObjectKey &K); + Value &operator[](ObjectKey &&K); + // Look up a property, returning nullptr if it doesn't exist. + Value *get(StringRef K); + const Value *get(StringRef K) const; + // Typed accessors return None/nullptr if + // - the property doesn't exist + // - or it has the wrong type + llvm::Optional<std::nullptr_t> getNull(StringRef K) const; + llvm::Optional<bool> getBoolean(StringRef K) const; + llvm::Optional<double> getNumber(StringRef K) const; + llvm::Optional<int64_t> getInteger(StringRef K) const; + llvm::Optional<llvm::StringRef> getString(StringRef K) const; + const json::Object *getObject(StringRef K) const; + json::Object *getObject(StringRef K); + const json::Array *getArray(StringRef K) const; + json::Array *getArray(StringRef K); +}; +bool operator==(const Object &LHS, const Object &RHS); +inline bool operator!=(const Object &LHS, const Object &RHS) { + return !(LHS == RHS); +} + +/// An Array is a JSON array, which contains heterogeneous JSON values. +/// It simulates std::vector<Value>. +class Array { + std::vector<Value> V; + +public: + using value_type = Value; + using iterator = std::vector<Value>::iterator; + using const_iterator = std::vector<Value>::const_iterator; + + explicit Array() = default; + explicit Array(std::initializer_list<Value> Elements); + template <typename Collection> explicit Array(const Collection &C) { + for (const auto &V : C) + emplace_back(V); + } + + Value &operator[](size_t I) { return V[I]; } + const Value &operator[](size_t I) const { return V[I]; } + Value &front() { return V.front(); } + const Value &front() const { return V.front(); } + Value &back() { return V.back(); } + const Value &back() const { return V.back(); } + Value *data() { return V.data(); } + const Value *data() const { return V.data(); } + + iterator begin() { return V.begin(); } + const_iterator begin() const { return V.begin(); } + iterator end() { return V.end(); } + const_iterator end() const { return V.end(); } + + bool empty() const { return V.empty(); } + size_t size() const { return V.size(); } + + void clear() { V.clear(); } + void push_back(const Value &E) { V.push_back(E); } + void push_back(Value &&E) { V.push_back(std::move(E)); } + template <typename... Args> void emplace_back(Args &&... A) { + V.emplace_back(std::forward<Args>(A)...); + } + void pop_back() { V.pop_back(); } + // FIXME: insert() takes const_iterator since C++11, old libstdc++ disagrees. + iterator insert(iterator P, const Value &E) { return V.insert(P, E); } + iterator insert(iterator P, Value &&E) { + return V.insert(P, std::move(E)); + } + template <typename It> iterator insert(iterator P, It A, It Z) { + return V.insert(P, A, Z); + } + template <typename... Args> iterator emplace(const_iterator P, Args &&... A) { + return V.emplace(P, std::forward<Args>(A)...); + } + + friend bool operator==(const Array &L, const Array &R) { return L.V == R.V; } +}; +inline bool operator!=(const Array &L, const Array &R) { return !(L == R); } + +/// A Value is an JSON value of unknown type. +/// They can be copied, but should generally be moved. +/// +/// === Composing values === +/// +/// You can implicitly construct Values from: +/// - strings: std::string, SmallString, formatv, StringRef, char* +/// (char*, and StringRef are references, not copies!) +/// - numbers +/// - booleans +/// - null: nullptr +/// - arrays: {"foo", 42.0, false} +/// - serializable things: types with toJSON(const T&)->Value, found by ADL +/// +/// They can also be constructed from object/array helpers: +/// - json::Object is a type like map<ObjectKey, Value> +/// - json::Array is a type like vector<Value> +/// These can be list-initialized, or used to build up collections in a loop. +/// json::ary(Collection) converts all items in a collection to Values. +/// +/// === Inspecting values === +/// +/// Each Value is one of the JSON kinds: +/// null (nullptr_t) +/// boolean (bool) +/// number (double or int64) +/// string (StringRef) +/// array (json::Array) +/// object (json::Object) +/// +/// The kind can be queried directly, or implicitly via the typed accessors: +/// if (Optional<StringRef> S = E.getAsString() +/// assert(E.kind() == Value::String); +/// +/// Array and Object also have typed indexing accessors for easy traversal: +/// Expected<Value> E = parse(R"( {"options": {"font": "sans-serif"}} )"); +/// if (Object* O = E->getAsObject()) +/// if (Object* Opts = O->getObject("options")) +/// if (Optional<StringRef> Font = Opts->getString("font")) +/// assert(Opts->at("font").kind() == Value::String); +/// +/// === Converting JSON values to C++ types === +/// +/// The convention is to have a deserializer function findable via ADL: +/// fromJSON(const json::Value&, T&)->bool +/// Deserializers are provided for: +/// - bool +/// - int and int64_t +/// - double +/// - std::string +/// - vector<T>, where T is deserializable +/// - map<string, T>, where T is deserializable +/// - Optional<T>, where T is deserializable +/// ObjectMapper can help writing fromJSON() functions for object types. +/// +/// For conversion in the other direction, the serializer function is: +/// toJSON(const T&) -> json::Value +/// If this exists, then it also allows constructing Value from T, and can +/// be used to serialize vector<T>, map<string, T>, and Optional<T>. +/// +/// === Serialization === +/// +/// Values can be serialized to JSON: +/// 1) raw_ostream << Value // Basic formatting. +/// 2) raw_ostream << formatv("{0}", Value) // Basic formatting. +/// 3) raw_ostream << formatv("{0:2}", Value) // Pretty-print with indent 2. +/// +/// And parsed: +/// Expected<Value> E = json::parse("[1, 2, null]"); +/// assert(E && E->kind() == Value::Array); +class Value { +public: + enum Kind { + Null, + Boolean, + /// Number values can store both int64s and doubles at full precision, + /// depending on what they were constructed/parsed from. + Number, + String, + Array, + Object, + }; + + // It would be nice to have Value() be null. But that would make {} null too. + Value(const Value &M) { copyFrom(M); } + Value(Value &&M) { moveFrom(std::move(M)); } + Value(std::initializer_list<Value> Elements); + Value(json::Array &&Elements) : Type(T_Array) { + create<json::Array>(std::move(Elements)); + } + Value(json::Object &&Properties) : Type(T_Object) { + create<json::Object>(std::move(Properties)); + } + // Strings: types with value semantics. Must be valid UTF-8. + Value(std::string V) : Type(T_String) { + if (LLVM_UNLIKELY(!isUTF8(V))) { + assert(false && "Invalid UTF-8 in value used as JSON"); + V = fixUTF8(std::move(V)); + } + create<std::string>(std::move(V)); + } + Value(const llvm::SmallVectorImpl<char> &V) + : Value(std::string(V.begin(), V.end())){}; + Value(const llvm::formatv_object_base &V) : Value(V.str()){}; + // Strings: types with reference semantics. Must be valid UTF-8. + Value(StringRef V) : Type(T_StringRef) { + create<llvm::StringRef>(V); + if (LLVM_UNLIKELY(!isUTF8(V))) { + assert(false && "Invalid UTF-8 in value used as JSON"); + *this = Value(fixUTF8(V)); + } + } + Value(const char *V) : Value(StringRef(V)) {} + Value(std::nullptr_t) : Type(T_Null) {} + // Boolean (disallow implicit conversions). + // (The last template parameter is a dummy to keep templates distinct.) + template < + typename T, + typename = typename std::enable_if<std::is_same<T, bool>::value>::type, + bool = false> + Value(T B) : Type(T_Boolean) { + create<bool>(B); + } + // Integers (except boolean). Must be non-narrowing convertible to int64_t. + template < + typename T, + typename = typename std::enable_if<std::is_integral<T>::value>::type, + typename = typename std::enable_if<!std::is_same<T, bool>::value>::type> + Value(T I) : Type(T_Integer) { + create<int64_t>(int64_t{I}); + } + // Floating point. Must be non-narrowing convertible to double. + template <typename T, + typename = + typename std::enable_if<std::is_floating_point<T>::value>::type, + double * = nullptr> + Value(T D) : Type(T_Double) { + create<double>(double{D}); + } + // Serializable types: with a toJSON(const T&)->Value function, found by ADL. + template <typename T, + typename = typename std::enable_if<std::is_same< + Value, decltype(toJSON(*(const T *)nullptr))>::value>, + Value * = nullptr> + Value(const T &V) : Value(toJSON(V)) {} + + Value &operator=(const Value &M) { + destroy(); + copyFrom(M); + return *this; + } + Value &operator=(Value &&M) { + destroy(); + moveFrom(std::move(M)); + return *this; + } + ~Value() { destroy(); } + + Kind kind() const { + switch (Type) { + case T_Null: + return Null; + case T_Boolean: + return Boolean; + case T_Double: + case T_Integer: + return Number; + case T_String: + case T_StringRef: + return String; + case T_Object: + return Object; + case T_Array: + return Array; + } + llvm_unreachable("Unknown kind"); + } + + // Typed accessors return None/nullptr if the Value is not of this type. + llvm::Optional<std::nullptr_t> getAsNull() const { + if (LLVM_LIKELY(Type == T_Null)) + return nullptr; + return llvm::None; + } + llvm::Optional<bool> getAsBoolean() const { + if (LLVM_LIKELY(Type == T_Boolean)) + return as<bool>(); + return llvm::None; + } + llvm::Optional<double> getAsNumber() const { + if (LLVM_LIKELY(Type == T_Double)) + return as<double>(); + if (LLVM_LIKELY(Type == T_Integer)) + return as<int64_t>(); + return llvm::None; + } + // Succeeds if the Value is a Number, and exactly representable as int64_t. + llvm::Optional<int64_t> getAsInteger() const { + if (LLVM_LIKELY(Type == T_Integer)) + return as<int64_t>(); + if (LLVM_LIKELY(Type == T_Double)) { + double D = as<double>(); + if (LLVM_LIKELY(std::modf(D, &D) == 0.0 && + D >= double(std::numeric_limits<int64_t>::min()) && + D <= double(std::numeric_limits<int64_t>::max()))) + return D; + } + return llvm::None; + } + llvm::Optional<llvm::StringRef> getAsString() const { + if (Type == T_String) + return llvm::StringRef(as<std::string>()); + if (LLVM_LIKELY(Type == T_StringRef)) + return as<llvm::StringRef>(); + return llvm::None; + } + const json::Object *getAsObject() const { + return LLVM_LIKELY(Type == T_Object) ? &as<json::Object>() : nullptr; + } + json::Object *getAsObject() { + return LLVM_LIKELY(Type == T_Object) ? &as<json::Object>() : nullptr; + } + const json::Array *getAsArray() const { + return LLVM_LIKELY(Type == T_Array) ? &as<json::Array>() : nullptr; + } + json::Array *getAsArray() { + return LLVM_LIKELY(Type == T_Array) ? &as<json::Array>() : nullptr; + } + + /// Serializes this Value to JSON, writing it to the provided stream. + /// The formatting is compact (no extra whitespace) and deterministic. + /// For pretty-printing, use the formatv() format_provider below. + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Value &); + +private: + void destroy(); + void copyFrom(const Value &M); + // We allow moving from *const* Values, by marking all members as mutable! + // This hack is needed to support initializer-list syntax efficiently. + // (std::initializer_list<T> is a container of const T). + void moveFrom(const Value &&M); + friend class Array; + friend class Object; + + template <typename T, typename... U> void create(U &&... V) { + new (reinterpret_cast<T *>(Union.buffer)) T(std::forward<U>(V)...); + } + template <typename T> T &as() const { + return *reinterpret_cast<T *>(Union.buffer); + } + + template <typename Indenter> + void print(llvm::raw_ostream &, const Indenter &) const; + friend struct llvm::format_provider<llvm::json::Value>; + + enum ValueType : char { + T_Null, + T_Boolean, + T_Double, + T_Integer, + T_StringRef, + T_String, + T_Object, + T_Array, + }; + // All members mutable, see moveFrom(). + mutable ValueType Type; + mutable llvm::AlignedCharArrayUnion<bool, double, int64_t, llvm::StringRef, + std::string, json::Array, json::Object> + Union; +}; + +bool operator==(const Value &, const Value &); +inline bool operator!=(const Value &L, const Value &R) { return !(L == R); } +llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Value &); + +/// ObjectKey is a used to capture keys in Object. Like Value but: +/// - only strings are allowed +/// - it's optimized for the string literal case (Owned == nullptr) +/// Like Value, strings must be UTF-8. See isUTF8 documentation for details. +class ObjectKey { +public: + ObjectKey(const char *S) : ObjectKey(StringRef(S)) {} + ObjectKey(std::string S) : Owned(new std::string(std::move(S))) { + if (LLVM_UNLIKELY(!isUTF8(*Owned))) { + assert(false && "Invalid UTF-8 in value used as JSON"); + *Owned = fixUTF8(std::move(*Owned)); + } + Data = *Owned; + } + ObjectKey(llvm::StringRef S) : Data(S) { + if (LLVM_UNLIKELY(!isUTF8(Data))) { + assert(false && "Invalid UTF-8 in value used as JSON"); + *this = ObjectKey(fixUTF8(S)); + } + } + ObjectKey(const llvm::SmallVectorImpl<char> &V) + : ObjectKey(std::string(V.begin(), V.end())) {} + ObjectKey(const llvm::formatv_object_base &V) : ObjectKey(V.str()) {} + + ObjectKey(const ObjectKey &C) { *this = C; } + ObjectKey(ObjectKey &&C) : ObjectKey(static_cast<const ObjectKey &&>(C)) {} + ObjectKey &operator=(const ObjectKey &C) { + if (C.Owned) { + Owned.reset(new std::string(*C.Owned)); + Data = *Owned; + } else { + Data = C.Data; + } + return *this; + } + ObjectKey &operator=(ObjectKey &&) = default; + + operator llvm::StringRef() const { return Data; } + std::string str() const { return Data.str(); } + +private: + // FIXME: this is unneccesarily large (3 pointers). Pointer + length + owned + // could be 2 pointers at most. + std::unique_ptr<std::string> Owned; + llvm::StringRef Data; +}; + +inline bool operator==(const ObjectKey &L, const ObjectKey &R) { + return llvm::StringRef(L) == llvm::StringRef(R); +} +inline bool operator!=(const ObjectKey &L, const ObjectKey &R) { + return !(L == R); +} +inline bool operator<(const ObjectKey &L, const ObjectKey &R) { + return StringRef(L) < StringRef(R); +} + +struct Object::KV { + ObjectKey K; + Value V; +}; + +inline Object::Object(std::initializer_list<KV> Properties) { + for (const auto &P : Properties) { + auto R = try_emplace(P.K, nullptr); + if (R.second) + R.first->getSecond().moveFrom(std::move(P.V)); + } +} +inline std::pair<Object::iterator, bool> Object::insert(KV E) { + return try_emplace(std::move(E.K), std::move(E.V)); +} + +// Standard deserializers are provided for primitive types. +// See comments on Value. +inline bool fromJSON(const Value &E, std::string &Out) { + if (auto S = E.getAsString()) { + Out = *S; + return true; + } + return false; +} +inline bool fromJSON(const Value &E, int &Out) { + if (auto S = E.getAsInteger()) { + Out = *S; + return true; + } + return false; +} +inline bool fromJSON(const Value &E, int64_t &Out) { + if (auto S = E.getAsInteger()) { + Out = *S; + return true; + } + return false; +} +inline bool fromJSON(const Value &E, double &Out) { + if (auto S = E.getAsNumber()) { + Out = *S; + return true; + } + return false; +} +inline bool fromJSON(const Value &E, bool &Out) { + if (auto S = E.getAsBoolean()) { + Out = *S; + return true; + } + return false; +} +template <typename T> bool fromJSON(const Value &E, llvm::Optional<T> &Out) { + if (E.getAsNull()) { + Out = llvm::None; + return true; + } + T Result; + if (!fromJSON(E, Result)) + return false; + Out = std::move(Result); + return true; +} +template <typename T> bool fromJSON(const Value &E, std::vector<T> &Out) { + if (auto *A = E.getAsArray()) { + Out.clear(); + Out.resize(A->size()); + for (size_t I = 0; I < A->size(); ++I) + if (!fromJSON((*A)[I], Out[I])) + return false; + return true; + } + return false; +} +template <typename T> +bool fromJSON(const Value &E, std::map<std::string, T> &Out) { + if (auto *O = E.getAsObject()) { + Out.clear(); + for (const auto &KV : *O) + if (!fromJSON(KV.second, Out[llvm::StringRef(KV.first)])) + return false; + return true; + } + return false; +} + +// Allow serialization of Optional<T> for supported T. +template <typename T> Value toJSON(const llvm::Optional<T> &Opt) { + return Opt ? Value(*Opt) : Value(nullptr); +} + +/// Helper for mapping JSON objects onto protocol structs. +/// +/// Example: +/// \code +/// bool fromJSON(const Value &E, MyStruct &R) { +/// ObjectMapper O(E); +/// if (!O || !O.map("mandatory_field", R.MandatoryField)) +/// return false; +/// O.map("optional_field", R.OptionalField); +/// return true; +/// } +/// \endcode +class ObjectMapper { +public: + ObjectMapper(const Value &E) : O(E.getAsObject()) {} + + /// True if the expression is an object. + /// Must be checked before calling map(). + operator bool() { return O; } + + /// Maps a property to a field, if it exists. + template <typename T> bool map(StringRef Prop, T &Out) { + assert(*this && "Must check this is an object before calling map()"); + if (const Value *E = O->get(Prop)) + return fromJSON(*E, Out); + return false; + } + + /// Maps a property to a field, if it exists. + /// (Optional requires special handling, because missing keys are OK). + template <typename T> bool map(StringRef Prop, llvm::Optional<T> &Out) { + assert(*this && "Must check this is an object before calling map()"); + if (const Value *E = O->get(Prop)) + return fromJSON(*E, Out); + Out = llvm::None; + return true; + } + +private: + const Object *O; +}; + +/// Parses the provided JSON source, or returns a ParseError. +/// The returned Value is self-contained and owns its strings (they do not refer +/// to the original source). +llvm::Expected<Value> parse(llvm::StringRef JSON); + +class ParseError : public llvm::ErrorInfo<ParseError> { + const char *Msg; + unsigned Line, Column, Offset; + +public: + static char ID; + ParseError(const char *Msg, unsigned Line, unsigned Column, unsigned Offset) + : Msg(Msg), Line(Line), Column(Column), Offset(Offset) {} + void log(llvm::raw_ostream &OS) const override { + OS << llvm::formatv("[{0}:{1}, byte={2}]: {3}", Line, Column, Offset, Msg); + } + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } +}; +} // namespace json + +/// Allow printing json::Value with formatv(). +/// The default style is basic/compact formatting, like operator<<. +/// A format string like formatv("{0:2}", Value) pretty-prints with indent 2. +template <> struct format_provider<llvm::json::Value> { + static void format(const llvm::json::Value &, raw_ostream &, StringRef); +}; +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Support/JamCRC.h b/contrib/llvm/include/llvm/Support/JamCRC.h index 5268bbd9ba1e..846d6cea9828 100644 --- a/contrib/llvm/include/llvm/Support/JamCRC.h +++ b/contrib/llvm/include/llvm/Support/JamCRC.h @@ -36,7 +36,7 @@ class JamCRC { public: JamCRC(uint32_t Init = 0xFFFFFFFFU) : CRC(Init) {} - // \brief Update the CRC calculation with Data. + // Update the CRC calculation with Data. void update(ArrayRef<char> Data); uint32_t getCRC() const { return CRC; } diff --git a/contrib/llvm/include/llvm/Support/KnownBits.h b/contrib/llvm/include/llvm/Support/KnownBits.h index 97e73b13fca3..259df9546c57 100644 --- a/contrib/llvm/include/llvm/Support/KnownBits.h +++ b/contrib/llvm/include/llvm/Support/KnownBits.h @@ -103,7 +103,7 @@ public: One.setSignBit(); } - /// Make this value negative. + /// Make this value non-negative. void makeNonNegative() { Zero.setSignBit(); } diff --git a/contrib/llvm/include/llvm/Support/LEB128.h b/contrib/llvm/include/llvm/Support/LEB128.h index 6af6e9f34474..9feb07229225 100644 --- a/contrib/llvm/include/llvm/Support/LEB128.h +++ b/contrib/llvm/include/llvm/Support/LEB128.h @@ -19,9 +19,10 @@ namespace llvm { -/// Utility function to encode a SLEB128 value to an output stream. -inline void encodeSLEB128(int64_t Value, raw_ostream &OS, - unsigned PadTo = 0) { +/// Utility function to encode a SLEB128 value to an output stream. Returns +/// the length in bytes of the encoded value. +inline unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, + unsigned PadTo = 0) { bool More; unsigned Count = 0; do { @@ -42,7 +43,9 @@ inline void encodeSLEB128(int64_t Value, raw_ostream &OS, for (; Count < PadTo - 1; ++Count) OS << char(PadValue | 0x80); OS << char(PadValue); + Count++; } + return Count; } /// Utility function to encode a SLEB128 value to a buffer. Returns @@ -73,9 +76,10 @@ inline unsigned encodeSLEB128(int64_t Value, uint8_t *p, unsigned PadTo = 0) { return (unsigned)(p - orig_p); } -/// Utility function to encode a ULEB128 value to an output stream. -inline void encodeULEB128(uint64_t Value, raw_ostream &OS, - unsigned PadTo = 0) { +/// Utility function to encode a ULEB128 value to an output stream. Returns +/// the length in bytes of the encoded value. +inline unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, + unsigned PadTo = 0) { unsigned Count = 0; do { uint8_t Byte = Value & 0x7f; @@ -93,6 +97,7 @@ inline void encodeULEB128(uint64_t Value, raw_ostream &OS, OS << '\x00'; Count++; } + return Count; } /// Utility function to encode a ULEB128 value to a buffer. Returns diff --git a/contrib/llvm/include/llvm/Support/LineIterator.h b/contrib/llvm/include/llvm/Support/LineIterator.h index 9d4cd3bd4c6d..892d289976cb 100644 --- a/contrib/llvm/include/llvm/Support/LineIterator.h +++ b/contrib/llvm/include/llvm/Support/LineIterator.h @@ -18,7 +18,7 @@ namespace llvm { class MemoryBuffer; -/// \brief A forward iterator which reads text lines from a buffer. +/// A forward iterator which reads text lines from a buffer. /// /// This class provides a forward iterator interface for reading one line at /// a time from a buffer. When default constructed the iterator will be the @@ -39,23 +39,23 @@ class line_iterator StringRef CurrentLine; public: - /// \brief Default construct an "end" iterator. + /// Default construct an "end" iterator. line_iterator() : Buffer(nullptr) {} - /// \brief Construct a new iterator around some memory buffer. + /// Construct a new iterator around some memory buffer. explicit line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks = true, char CommentMarker = '\0'); - /// \brief Return true if we've reached EOF or are an "end" iterator. + /// 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. + /// 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. + /// 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. + /// Advance to the next (non-empty, non-comment) line. line_iterator &operator++() { advance(); return *this; @@ -66,7 +66,7 @@ public: return tmp; } - /// \brief Get the current line as a \c StringRef. + /// Get the current line as a \c StringRef. StringRef operator*() const { return CurrentLine; } const StringRef *operator->() const { return &CurrentLine; } @@ -80,7 +80,7 @@ public: } private: - /// \brief Advance the iterator to the next line. + /// Advance the iterator to the next line. void advance(); }; } diff --git a/contrib/llvm/include/llvm/Support/LockFileManager.h b/contrib/llvm/include/llvm/Support/LockFileManager.h index 1e417bdd5b25..86db0b2b1020 100644 --- a/contrib/llvm/include/llvm/Support/LockFileManager.h +++ b/contrib/llvm/include/llvm/Support/LockFileManager.h @@ -11,14 +11,13 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" -#include "llvm/Support/FileSystem.h" #include <system_error> #include <utility> // for std::pair namespace llvm { class StringRef; -/// \brief Class that manages the creation of a lock file to aid +/// Class that manages the creation of a lock file to aid /// implicit coordination between different processes. /// /// The implicit coordination works by creating a ".lock" file alongside @@ -28,33 +27,33 @@ class StringRef; /// operation. class LockFileManager { public: - /// \brief Describes the state of a lock file. + /// Describes the state of a lock file. enum LockFileState { - /// \brief The lock file has been created and is owned by this instance + /// The lock file has been created and is owned by this instance /// of the object. LFS_Owned, - /// \brief The lock file already exists and is owned by some other + /// The lock file already exists and is owned by some other /// instance. LFS_Shared, - /// \brief An error occurred while trying to create or find the lock + /// An error occurred while trying to create or find the lock /// file. LFS_Error }; - /// \brief Describes the result of waiting for the owner to release the lock. + /// Describes the result of waiting for the owner to release the lock. enum WaitForUnlockResult { - /// \brief The lock was released successfully. + /// The lock was released successfully. Res_Success, - /// \brief Owner died while holding the lock. + /// Owner died while holding the lock. Res_OwnerDied, - /// \brief Reached timeout while waiting for the owner to release the lock. + /// Reached timeout while waiting for the owner to release the lock. Res_Timeout }; private: SmallString<128> FileName; SmallString<128> LockFileName; - Optional<sys::fs::TempFile> UniqueLockFile; + SmallString<128> UniqueLockFileName; Optional<std::pair<std::string, int> > Owner; std::error_code ErrorCode; @@ -73,22 +72,22 @@ public: LockFileManager(StringRef FileName); ~LockFileManager(); - /// \brief Determine the state of the lock file. + /// Determine the state of the lock file. LockFileState getState() const; operator LockFileState() const { return getState(); } - /// \brief For a shared lock, wait until the owner releases the lock. + /// For a shared lock, wait until the owner releases the lock. WaitForUnlockResult waitForUnlock(); - /// \brief Remove the lock file. This may delete a different lock file than + /// Remove the lock file. This may delete a different lock file than /// the one previously read if there is a race. std::error_code unsafeRemoveLockFile(); - /// \brief Get error message, or "" if there is no error. + /// Get error message, or "" if there is no error. std::string getErrorMessage() const; - /// \brief Set error and error message + /// Set error and error message void setError(const std::error_code &EC, StringRef ErrorMsg = "") { ErrorCode = EC; ErrorDiagMsg = ErrorMsg.str(); diff --git a/contrib/llvm/include/llvm/Support/LowLevelTypeImpl.h b/contrib/llvm/include/llvm/Support/LowLevelTypeImpl.h index 099fa4618997..a0a5a52d206e 100644 --- a/contrib/llvm/include/llvm/Support/LowLevelTypeImpl.h +++ b/contrib/llvm/include/llvm/Support/LowLevelTypeImpl.h @@ -28,7 +28,7 @@ #define LLVM_SUPPORT_LOWLEVELTYPEIMPL_H #include "llvm/ADT/DenseMapInfo.h" -#include "llvm/CodeGen/MachineValueType.h" +#include "llvm/Support/MachineValueType.h" #include <cassert> namespace llvm { diff --git a/contrib/llvm/include/llvm/Support/MD5.h b/contrib/llvm/include/llvm/Support/MD5.h index 2c0dc76485f8..bb2bdbf1bed2 100644 --- a/contrib/llvm/include/llvm/Support/MD5.h +++ b/contrib/llvm/include/llvm/Support/MD5.h @@ -81,20 +81,20 @@ public: MD5(); - /// \brief Updates the hash for the byte stream provided. + /// Updates the hash for the byte stream provided. void update(ArrayRef<uint8_t> Data); - /// \brief Updates the hash for the StringRef provided. + /// Updates the hash for the StringRef provided. void update(StringRef Str); - /// \brief Finishes off the hash and puts the result in result. + /// Finishes off the hash and puts the result in result. void final(MD5Result &Result); - /// \brief Translates the bytes in \p Res to a hex string that is + /// Translates the bytes in \p Res to a hex string that is /// deposited into \p Str. The result will be of length 32. static void stringifyResult(MD5Result &Result, SmallString<32> &Str); - /// \brief Computes the hash for a given bytes. + /// Computes the hash for a given bytes. static std::array<uint8_t, 16> hash(ArrayRef<uint8_t> Data); private: diff --git a/contrib/llvm/include/llvm/CodeGen/MachineValueType.h b/contrib/llvm/include/llvm/Support/MachineValueType.h index b452684757f6..552dea05029c 100644 --- a/contrib/llvm/include/llvm/CodeGen/MachineValueType.h +++ b/contrib/llvm/include/llvm/Support/MachineValueType.h @@ -1,4 +1,4 @@ -//===- CodeGen/MachineValueType.h - Machine-Level types ---------*- C++ -*-===// +//===- Support/MachineValueType.h - Machine-Level types ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHINEVALUETYPE_H -#define LLVM_CODEGEN_MACHINEVALUETYPE_H +#ifndef LLVM_SUPPORT_MACHINEVALUETYPE_H +#define LLVM_SUPPORT_MACHINEVALUETYPE_H #include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" @@ -191,8 +191,10 @@ namespace llvm { // unspecified type. The register class // will be determined by the opcode. + ExceptRef = 113, // WebAssembly's except_ref type + FIRST_VALUETYPE = 1, // This is always the beginning of the list. - LAST_VALUETYPE = 113, // This always remains at the end of the list. + LAST_VALUETYPE = 114, // 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 @@ -376,7 +378,7 @@ namespace llvm { SimpleTy == MVT::v16i64); } - /// Return true if this is a 1024-bit vector type. + /// Return true if this is a 2048-bit vector type. bool is2048BitVector() const { return (SimpleTy == MVT::v256i8 || SimpleTy == MVT::v128i16 || SimpleTy == MVT::v64i32 || SimpleTy == MVT::v32i64); @@ -746,6 +748,7 @@ namespace llvm { case v64i32: case v32i64: case nxv32i64: return 2048; + case ExceptRef: return 0; // opaque type } } diff --git a/contrib/llvm/include/llvm/Support/MathExtras.h b/contrib/llvm/include/llvm/Support/MathExtras.h index a37a16784e2a..b59f21b4998e 100644 --- a/contrib/llvm/include/llvm/Support/MathExtras.h +++ b/contrib/llvm/include/llvm/Support/MathExtras.h @@ -23,22 +23,30 @@ #include <limits> #include <type_traits> -#ifdef _MSC_VER -#include <intrin.h> -#endif - #ifdef __ANDROID_NDK__ #include <android/api-level.h> #endif +#ifdef _MSC_VER +// Declare these intrinsics manually rather including intrin.h. It's very +// expensive, and MathExtras.h is popular. +// #include <intrin.h> +extern "C" { +unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask); +unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask); +unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask); +unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask); +} +#endif + namespace llvm { -/// \brief The behavior an operation has on an input of 0. +/// The behavior an operation has on an input of 0. enum ZeroBehavior { - /// \brief The returned value is undefined. + /// The returned value is undefined. ZB_Undefined, - /// \brief The returned value is numeric_limits<T>::max() + /// The returned value is numeric_limits<T>::max() ZB_Max, - /// \brief The returned value is numeric_limits<T>::digits + /// The returned value is numeric_limits<T>::digits ZB_Width }; @@ -101,7 +109,7 @@ template <typename T> struct TrailingZerosCounter<T, 8> { #endif } // namespace detail -/// \brief Count number of 0's from the least significant bit to the most +/// Count number of 0's from the least significant bit to the most /// stopping at the first 1. /// /// Only unsigned integral types are allowed. @@ -170,7 +178,7 @@ template <typename T> struct LeadingZerosCounter<T, 8> { #endif } // namespace detail -/// \brief Count number of 0's from the most significant bit to the least +/// Count number of 0's from the most significant bit to the least /// stopping at the first 1. /// /// Only unsigned integral types are allowed. @@ -185,7 +193,7 @@ std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { return llvm::detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB); } -/// \brief Get the index of the first set bit starting from the least +/// Get the index of the first set bit starting from the least /// significant bit. /// /// Only unsigned integral types are allowed. @@ -199,7 +207,7 @@ template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { return countTrailingZeros(Val, ZB_Undefined); } -/// \brief Create a bitmask with the N right-most bits set to 1, and all other +/// Create a bitmask with the N right-most bits set to 1, and all other /// bits set to 0. Only unsigned types are allowed. template <typename T> T maskTrailingOnes(unsigned N) { static_assert(std::is_unsigned<T>::value, "Invalid type!"); @@ -208,25 +216,25 @@ template <typename T> T maskTrailingOnes(unsigned N) { return N == 0 ? 0 : (T(-1) >> (Bits - N)); } -/// \brief Create a bitmask with the N left-most bits set to 1, and all other +/// Create a bitmask with the N left-most bits set to 1, and all other /// bits set to 0. Only unsigned types are allowed. template <typename T> T maskLeadingOnes(unsigned N) { return ~maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N); } -/// \brief Create a bitmask with the N right-most bits set to 0, and all other +/// Create a bitmask with the N right-most bits set to 0, and all other /// bits set to 1. Only unsigned types are allowed. template <typename T> T maskTrailingZeros(unsigned N) { return maskLeadingOnes<T>(CHAR_BIT * sizeof(T) - N); } -/// \brief Create a bitmask with the N left-most bits set to 0, and all other +/// Create a bitmask with the N left-most bits set to 0, and all other /// bits set to 1. Only unsigned types are allowed. template <typename T> T maskLeadingZeros(unsigned N) { return maskTrailingOnes<T>(CHAR_BIT * sizeof(T) - N); } -/// \brief Get the index of the last set bit starting from the least +/// Get the index of the last set bit starting from the least /// significant bit. /// /// Only unsigned integral types are allowed. @@ -243,7 +251,7 @@ template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { (std::numeric_limits<T>::digits - 1); } -/// \brief Macro compressed bit reversal table for 256 bits. +/// Macro compressed bit reversal table for 256 bits. /// /// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable static const unsigned char BitReverseTable256[256] = { @@ -256,7 +264,7 @@ static const unsigned char BitReverseTable256[256] = { #undef R6 }; -/// \brief Reverse the bits in \p Val. +/// Reverse the bits in \p Val. template <typename T> T reverseBits(T Val) { unsigned char in[sizeof(Val)]; @@ -442,7 +450,7 @@ inline uint64_t ByteSwap_64(uint64_t Value) { return sys::SwapByteOrder_64(Value); } -/// \brief Count the number of ones from the most significant bit to the first +/// Count the number of ones from the most significant bit to the first /// zero bit. /// /// Ex. countLeadingOnes(0xFF0FFF00) == 8. @@ -455,10 +463,10 @@ std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, "Only unsigned integral types are allowed."); - return countLeadingZeros(~Value, ZB); + return countLeadingZeros<T>(~Value, ZB); } -/// \brief Count the number of ones from the least significant bit to the first +/// Count the number of ones from the least significant bit to the first /// zero bit. /// /// Ex. countTrailingOnes(0x00FF00FF) == 8. @@ -471,7 +479,7 @@ std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, "Only unsigned integral types are allowed."); - return countTrailingZeros(~Value, ZB); + return countTrailingZeros<T>(~Value, ZB); } namespace detail { @@ -505,7 +513,7 @@ template <typename T> struct PopulationCounter<T, 8> { }; } // namespace detail -/// \brief Count the number of set bits in a value. +/// Count the number of set bits in a value. /// Ex. countPopulation(0xF000F000) = 8 /// Returns 0 if the word is zero. template <typename T> @@ -608,7 +616,7 @@ constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) { return (A | B) & (1 + ~(A | B)); } -/// \brief Aligns \c Addr to \c Alignment bytes, rounding up. +/// Aligns \c Addr to \c Alignment bytes, rounding up. /// /// Alignment should be a power of two. This method rounds up, so /// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8. @@ -621,7 +629,7 @@ inline uintptr_t alignAddr(const void *Addr, size_t Alignment) { return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1)); } -/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment +/// Returns the necessary adjustment for aligning \c Ptr to \c Alignment /// bytes, rounding up. inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) { return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr; diff --git a/contrib/llvm/include/llvm/Support/MemAlloc.h b/contrib/llvm/include/llvm/Support/MemAlloc.h new file mode 100644 index 000000000000..d06c659cfba6 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/MemAlloc.h @@ -0,0 +1,49 @@ +//===- MemAlloc.h - Memory allocation functions -----------------*- 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 counterparts of C library allocation functions defined in +/// the namespace 'std'. The new allocation functions crash on allocation +/// failure instead of returning null pointer. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MEMALLOC_H +#define LLVM_SUPPORT_MEMALLOC_H + +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include <cstdlib> + +namespace llvm { + +LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_malloc(size_t Sz) { + void *Result = std::malloc(Sz); + if (Result == nullptr) + report_bad_alloc_error("Allocation failed"); + return Result; +} + +LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_calloc(size_t Count, + size_t Sz) { + void *Result = std::calloc(Count, Sz); + if (Result == nullptr) + report_bad_alloc_error("Allocation failed"); + return Result; +} + +LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) { + void *Result = std::realloc(Ptr, Sz); + if (Result == nullptr) + report_bad_alloc_error("Allocation failed"); + return Result; +} + +} +#endif diff --git a/contrib/llvm/include/llvm/Support/Memory.h b/contrib/llvm/include/llvm/Support/Memory.h index 3140dc6eef42..fa026d49a61b 100644 --- a/contrib/llvm/include/llvm/Support/Memory.h +++ b/contrib/llvm/include/llvm/Support/Memory.h @@ -25,7 +25,7 @@ namespace sys { /// and a size. It is used by the Memory class (a friend) as the result of /// various memory allocation operations. /// @see Memory - /// @brief Memory block abstraction. + /// Memory block abstraction. class MemoryBlock { public: MemoryBlock() : Address(nullptr), Size(0) { } @@ -42,7 +42,7 @@ namespace sys { /// This class provides various memory handling functions that manipulate /// MemoryBlock instances. /// @since 1.4 - /// @brief An abstraction for memory operations. + /// An abstraction for memory operations. class Memory { public: enum ProtectionFlags { @@ -74,7 +74,7 @@ namespace sys { /// \r a non-null MemoryBlock if the function was successful, /// otherwise a null MemoryBlock is with \p EC describing the error. /// - /// @brief Allocate mapped memory. + /// Allocate mapped memory. static MemoryBlock allocateMappedMemory(size_t NumBytes, const MemoryBlock *const NearBlock, unsigned Flags, @@ -88,7 +88,7 @@ namespace sys { /// \r error_success if the function was successful, or an error_code /// describing the failure if an error occurred. /// - /// @brief Release mapped memory. + /// Release mapped memory. static std::error_code releaseMappedMemory(MemoryBlock &Block); /// This method sets the protection flags for a block of memory to the @@ -105,7 +105,7 @@ namespace sys { /// \r error_success if the function was successful, or an error_code /// describing the failure if an error occurred. /// - /// @brief Set memory protection state. + /// Set memory protection state. static std::error_code protectMappedMemory(const MemoryBlock &Block, unsigned Flags); diff --git a/contrib/llvm/include/llvm/Support/MemoryBuffer.h b/contrib/llvm/include/llvm/Support/MemoryBuffer.h index 7b849fdb8670..535579ecff53 100644 --- a/contrib/llvm/include/llvm/Support/MemoryBuffer.h +++ b/contrib/llvm/include/llvm/Support/MemoryBuffer.h @@ -20,6 +20,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" #include <cstddef> #include <cstdint> #include <memory> @@ -49,7 +50,8 @@ protected: void init(const char *BufStart, const char *BufEnd, bool RequiresNullTerminator); - static constexpr bool Writable = false; + static constexpr sys::fs::mapped_file_region::mapmode Mapmode = + sys::fs::mapped_file_region::readonly; public: MemoryBuffer(const MemoryBuffer &) = delete; @@ -117,12 +119,6 @@ public: static std::unique_ptr<MemoryBuffer> getMemBufferCopy(StringRef InputData, const Twine &BufferName = ""); - /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note - /// that the caller need not initialize the memory allocated by this method. - /// The memory is owned by the MemoryBuffer object. - static std::unique_ptr<MemoryBuffer> - getNewMemBuffer(size_t Size, StringRef BufferName = ""); - /// Read all of stdin into a file buffer, and return it. static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN(); @@ -152,17 +148,21 @@ public: virtual BufferKind getBufferKind() const = 0; MemoryBufferRef getMemBufferRef() const; + +private: + virtual void anchor(); }; -/// This class is an extension of MemoryBuffer, which allows writing to the -/// underlying contents. It only supports creation methods that are guaranteed -/// to produce a writable buffer. For example, mapping a file read-only is not -/// supported. +/// This class is an extension of MemoryBuffer, which allows copy-on-write +/// access to the underlying contents. It only supports creation methods that +/// are guaranteed to produce a writable buffer. For example, mapping a file +/// read-only is not supported. class WritableMemoryBuffer : public MemoryBuffer { protected: WritableMemoryBuffer() = default; - static constexpr bool Writable = true; + static constexpr sys::fs::mapped_file_region::mapmode Mapmode = + sys::fs::mapped_file_region::priv; public: using MemoryBuffer::getBuffer; @@ -196,6 +196,60 @@ public: static std::unique_ptr<WritableMemoryBuffer> getNewUninitMemBuffer(size_t Size, const Twine &BufferName = ""); + /// Allocate a new zero-initialized MemoryBuffer of the specified size. Note + /// that the caller need not initialize the memory allocated by this method. + /// The memory is owned by the MemoryBuffer object. + static std::unique_ptr<WritableMemoryBuffer> + getNewMemBuffer(size_t Size, const Twine &BufferName = ""); + +private: + // Hide these base class factory function so one can't write + // WritableMemoryBuffer::getXXX() + // and be surprised that he got a read-only Buffer. + using MemoryBuffer::getFileAsStream; + using MemoryBuffer::getFileOrSTDIN; + using MemoryBuffer::getMemBuffer; + using MemoryBuffer::getMemBufferCopy; + using MemoryBuffer::getOpenFile; + using MemoryBuffer::getOpenFileSlice; + using MemoryBuffer::getSTDIN; +}; + +/// This class is an extension of MemoryBuffer, which allows write access to +/// the underlying contents and committing those changes to the original source. +/// It only supports creation methods that are guaranteed to produce a writable +/// buffer. For example, mapping a file read-only is not supported. +class WriteThroughMemoryBuffer : public MemoryBuffer { +protected: + WriteThroughMemoryBuffer() = default; + + static constexpr sys::fs::mapped_file_region::mapmode Mapmode = + sys::fs::mapped_file_region::readwrite; + +public: + using MemoryBuffer::getBuffer; + using MemoryBuffer::getBufferEnd; + using MemoryBuffer::getBufferStart; + + // const_cast is well-defined here, because the underlying buffer is + // guaranteed to have been initialized with a mutable buffer. + char *getBufferStart() { + return const_cast<char *>(MemoryBuffer::getBufferStart()); + } + char *getBufferEnd() { + return const_cast<char *>(MemoryBuffer::getBufferEnd()); + } + MutableArrayRef<char> getBuffer() { + return {getBufferStart(), getBufferEnd()}; + } + + static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> + getFile(const Twine &Filename, int64_t FileSize = -1); + + /// Map a subrange of the specified file as a ReadWriteMemoryBuffer. + static ErrorOr<std::unique_ptr<WriteThroughMemoryBuffer>> + getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset); + private: // Hide these base class factory function so one can't write // WritableMemoryBuffer::getXXX() @@ -204,7 +258,6 @@ private: using MemoryBuffer::getFileOrSTDIN; using MemoryBuffer::getMemBuffer; using MemoryBuffer::getMemBufferCopy; - using MemoryBuffer::getNewMemBuffer; using MemoryBuffer::getOpenFile; using MemoryBuffer::getOpenFileSlice; using MemoryBuffer::getSTDIN; diff --git a/contrib/llvm/include/llvm/Support/MipsABIFlags.h b/contrib/llvm/include/llvm/Support/MipsABIFlags.h index 93f6b416ba88..12c350015b21 100644 --- a/contrib/llvm/include/llvm/Support/MipsABIFlags.h +++ b/contrib/llvm/include/llvm/Support/MipsABIFlags.h @@ -42,7 +42,9 @@ enum AFL_ASE { AFL_ASE_MSA = 0x00000200, // MSA ASE AFL_ASE_MIPS16 = 0x00000400, // MIPS16 ASE AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE - AFL_ASE_XPA = 0x00001000 // XPA ASE + AFL_ASE_XPA = 0x00001000, // XPA ASE + AFL_ASE_CRC = 0x00008000, // CRC ASE + AFL_ASE_GINV = 0x00020000 // GINV ASE }; // Values for the isa_ext word of an ABI flags structure. diff --git a/contrib/llvm/include/llvm/Support/Mutex.h b/contrib/llvm/include/llvm/Support/Mutex.h index 0f4e61af4439..680d94b24ef5 100644 --- a/contrib/llvm/include/llvm/Support/Mutex.h +++ b/contrib/llvm/include/llvm/Support/Mutex.h @@ -14,6 +14,7 @@ #ifndef LLVM_SUPPORT_MUTEX_H #define LLVM_SUPPORT_MUTEX_H +#include "llvm/Config/llvm-config.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Threading.h" #include <cassert> @@ -22,7 +23,7 @@ namespace llvm { namespace sys { - /// @brief Platform agnostic Mutex class. + /// Platform agnostic Mutex class. class MutexImpl { /// @name Constructors @@ -33,11 +34,11 @@ namespace llvm /// to false, the lock will not be recursive which makes it cheaper but /// also more likely to deadlock (same thread can't acquire more than /// once). - /// @brief Default Constructor. + /// Default Constructor. explicit MutexImpl(bool recursive = true); /// Releases and removes the lock - /// @brief Destructor + /// Destructor ~MutexImpl(); /// @} @@ -48,14 +49,14 @@ namespace llvm /// Attempts to unconditionally acquire the lock. If the lock is held by /// another thread, this method will wait until it can acquire the lock. /// @returns false if any kind of error occurs, true otherwise. - /// @brief Unconditionally acquire the lock. + /// Unconditionally acquire the lock. bool acquire(); /// Attempts to release the lock. If the lock is held by the current /// thread, the lock is released allowing other threads to acquire the /// lock. /// @returns false if any kind of error occurs, true otherwise. - /// @brief Unconditionally release the lock. + /// Unconditionally release the lock. bool release(); /// Attempts to acquire the lock without blocking. If the lock is not @@ -63,7 +64,7 @@ namespace llvm /// the lock is available, it is acquired. /// @returns false if any kind of error occurs or the lock is not /// available, true otherwise. - /// @brief Try to acquire the lock. + /// Try to acquire the lock. bool tryacquire(); //@} diff --git a/contrib/llvm/include/llvm/Support/MutexGuard.h b/contrib/llvm/include/llvm/Support/MutexGuard.h index 07b64b611960..641d64d94988 100644 --- a/contrib/llvm/include/llvm/Support/MutexGuard.h +++ b/contrib/llvm/include/llvm/Support/MutexGuard.h @@ -23,7 +23,7 @@ namespace llvm { /// these on the stack at the top of some scope to be assured that C++ /// destruction of the object will always release the Mutex and thus avoid /// a host of nasty multi-threading problems in the face of exceptions, etc. - /// @brief Guard a section of code with a Mutex. + /// Guard a section of code with a Mutex. class MutexGuard { sys::Mutex &M; MutexGuard(const MutexGuard &) = delete; diff --git a/contrib/llvm/include/llvm/Support/OnDiskHashTable.h b/contrib/llvm/include/llvm/Support/OnDiskHashTable.h index e9c28daf03b9..912e2700d1a0 100644 --- a/contrib/llvm/include/llvm/Support/OnDiskHashTable.h +++ b/contrib/llvm/include/llvm/Support/OnDiskHashTable.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines facilities for reading and writing on-disk hash tables. +/// Defines facilities for reading and writing on-disk hash tables. /// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_ONDISKHASHTABLE_H @@ -25,7 +25,7 @@ namespace llvm { -/// \brief Generates an on disk hash table. +/// Generates an on disk hash table. /// /// This needs an \c Info that handles storing values into the hash table's /// payload and computes the hash for a given key. This should provide the @@ -57,7 +57,7 @@ namespace llvm { /// }; /// \endcode template <typename Info> class OnDiskChainedHashTableGenerator { - /// \brief A single item in the hash table. + /// A single item in the hash table. class Item { public: typename Info::key_type Key; @@ -75,7 +75,7 @@ template <typename Info> class OnDiskChainedHashTableGenerator { offset_type NumEntries; llvm::SpecificBumpPtrAllocator<Item> BA; - /// \brief A linked list of values in a particular hash bucket. + /// A linked list of values in a particular hash bucket. struct Bucket { offset_type Off; unsigned Length; @@ -85,7 +85,7 @@ template <typename Info> class OnDiskChainedHashTableGenerator { Bucket *Buckets; private: - /// \brief Insert an item into the appropriate hash bucket. + /// Insert an item into the appropriate hash bucket. void insert(Bucket *Buckets, size_t Size, Item *E) { Bucket &B = Buckets[E->Hash & (Size - 1)]; E->Next = B.Head; @@ -93,9 +93,10 @@ private: B.Head = E; } - /// \brief Resize the hash table, moving the old entries into the new buckets. + /// Resize the hash table, moving the old entries into the new buckets. void resize(size_t NewSize) { - Bucket *NewBuckets = (Bucket *)std::calloc(NewSize, sizeof(Bucket)); + Bucket *NewBuckets = static_cast<Bucket *>( + safe_calloc(NewSize, sizeof(Bucket))); // Populate NewBuckets with the old entries. for (size_t I = 0; I < NumBuckets; ++I) for (Item *E = Buckets[I].Head; E;) { @@ -111,14 +112,14 @@ private: } public: - /// \brief Insert an entry into the table. + /// Insert an entry into the table. void insert(typename Info::key_type_ref Key, typename Info::data_type_ref Data) { Info InfoObj; insert(Key, Data, InfoObj); } - /// \brief Insert an entry into the table. + /// Insert an entry into the table. /// /// Uses the provided Info instead of a stack allocated one. void insert(typename Info::key_type_ref Key, @@ -129,7 +130,7 @@ public: insert(Buckets, NumBuckets, new (BA.Allocate()) Item(Key, Data, InfoObj)); } - /// \brief Determine whether an entry has been inserted. + /// Determine whether an entry has been inserted. bool contains(typename Info::key_type_ref Key, Info &InfoObj) { unsigned Hash = InfoObj.ComputeHash(Key); for (Item *I = Buckets[Hash & (NumBuckets - 1)].Head; I; I = I->Next) @@ -138,18 +139,18 @@ public: return false; } - /// \brief Emit the table to Out, which must not be at offset 0. + /// Emit the table to Out, which must not be at offset 0. offset_type Emit(raw_ostream &Out) { Info InfoObj; return Emit(Out, InfoObj); } - /// \brief Emit the table to Out, which must not be at offset 0. + /// Emit the table to Out, which must not be at offset 0. /// /// Uses the provided Info instead of a stack allocated one. offset_type Emit(raw_ostream &Out, Info &InfoObj) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); // Now we're done adding entries, resize the bucket list if it's // significantly too large. (This only happens if the number of @@ -226,13 +227,13 @@ public: NumBuckets = 64; // Note that we do not need to run the constructors of the individual // Bucket objects since 'calloc' returns bytes that are all 0. - Buckets = (Bucket *)std::calloc(NumBuckets, sizeof(Bucket)); + Buckets = static_cast<Bucket *>(safe_calloc(NumBuckets, sizeof(Bucket))); } ~OnDiskChainedHashTableGenerator() { std::free(Buckets); } }; -/// \brief Provides lookup on an on disk hash table. +/// Provides lookup on an on disk hash table. /// /// This needs an \c Info that handles reading values from the hash table's /// payload and computes the hash for a given key. This should provide the @@ -338,14 +339,14 @@ public: bool operator!=(const iterator &X) const { return X.Data != Data; } }; - /// \brief Look up the stored data for a particular key. + /// Look up the stored data for a particular key. iterator find(const external_key_type &EKey, Info *InfoPtr = nullptr) { const internal_key_type &IKey = InfoObj.GetInternalKey(EKey); hash_value_type KeyHash = InfoObj.ComputeHash(IKey); return find_hashed(IKey, KeyHash, InfoPtr); } - /// \brief Look up the stored data for a particular key with a known hash. + /// Look up the stored data for a particular key with a known hash. iterator find_hashed(const internal_key_type &IKey, hash_value_type KeyHash, Info *InfoPtr = nullptr) { using namespace llvm::support; @@ -403,7 +404,7 @@ public: Info &getInfoObj() { return InfoObj; } - /// \brief Create the hash table. + /// Create the hash table. /// /// \param Buckets is the beginning of the hash table itself, which follows /// the payload of entire structure. This is the value returned by @@ -423,7 +424,7 @@ public: } }; -/// \brief Provides lookup and iteration over an on disk hash table. +/// Provides lookup and iteration over an on disk hash table. /// /// \copydetails llvm::OnDiskChainedHashTable template <typename Info> @@ -439,7 +440,7 @@ public: typedef typename base_type::offset_type offset_type; private: - /// \brief Iterates over all of the keys in the table. + /// Iterates over all of the keys in the table. class iterator_base { const unsigned char *Ptr; offset_type NumItemsInBucketLeft; @@ -496,7 +497,7 @@ public: : base_type(NumBuckets, NumEntries, Buckets, Base, InfoObj), Payload(Payload) {} - /// \brief Iterates over all of the keys in the table. + /// Iterates over all of the keys in the table. class key_iterator : public iterator_base { Info *InfoObj; @@ -542,7 +543,7 @@ public: return make_range(key_begin(), key_end()); } - /// \brief Iterates over all the entries in the table, returning the data. + /// Iterates over all the entries in the table, returning the data. class data_iterator : public iterator_base { Info *InfoObj; @@ -585,7 +586,7 @@ public: return make_range(data_begin(), data_end()); } - /// \brief Create the hash table. + /// Create the hash table. /// /// \param Buckets is the beginning of the hash table itself, which follows /// the payload of entire structure. This is the value returned by diff --git a/contrib/llvm/include/llvm/Support/Options.h b/contrib/llvm/include/llvm/Support/Options.h index 9019804d24e0..dd321c6a1984 100644 --- a/contrib/llvm/include/llvm/Support/Options.h +++ b/contrib/llvm/include/llvm/Support/Options.h @@ -56,7 +56,7 @@ char OptionKey<ValT, Base, Mem>::ID = 0; } // namespace detail -/// \brief Singleton class used to register debug options. +/// Singleton class used to register debug options. /// /// The OptionRegistry is responsible for managing lifetimes of the options and /// provides interfaces for option registration and reading values from options. @@ -66,7 +66,7 @@ class OptionRegistry { private: DenseMap<void *, cl::Option *> Options; - /// \brief Adds a cl::Option to the registry. + /// Adds a cl::Option to the registry. /// /// \param Key unique key for option /// \param O option to map to \p Key @@ -79,10 +79,10 @@ public: ~OptionRegistry(); OptionRegistry() {} - /// \brief Returns a reference to the singleton instance. + /// Returns a reference to the singleton instance. static OptionRegistry &instance(); - /// \brief Registers an option with the OptionRegistry singleton. + /// Registers an option with the OptionRegistry singleton. /// /// \tparam ValT type of the option's data /// \tparam Base class used to key the option @@ -100,7 +100,7 @@ public: instance().addOption(&detail::OptionKey<ValT, Base, Mem>::ID, Option); } - /// \brief Returns the value of the option. + /// Returns the value of the option. /// /// \tparam ValT type of the option's data /// \tparam Base class used to key the option diff --git a/contrib/llvm/include/llvm/Support/Parallel.h b/contrib/llvm/include/llvm/Support/Parallel.h index 6bc0a6bbaf2b..1462265343be 100644 --- a/contrib/llvm/include/llvm/Support/Parallel.h +++ b/contrib/llvm/include/llvm/Support/Parallel.h @@ -56,12 +56,12 @@ public: ~Latch() { sync(); } void inc() { - std::unique_lock<std::mutex> lock(Mutex); + std::lock_guard<std::mutex> lock(Mutex); ++Count; } void dec() { - std::unique_lock<std::mutex> lock(Mutex); + std::lock_guard<std::mutex> lock(Mutex); if (--Count == 0) Cond.notify_all(); } @@ -100,7 +100,7 @@ void parallel_for_each_n(IndexTy Begin, IndexTy End, FuncTy Fn) { #else const ptrdiff_t MinParallelSize = 1024; -/// \brief Inclusive median. +/// Inclusive median. template <class RandomAccessIterator, class Comparator> RandomAccessIterator medianOf3(RandomAccessIterator Start, RandomAccessIterator End, @@ -118,7 +118,7 @@ void parallel_quick_sort(RandomAccessIterator Start, RandomAccessIterator End, const Comparator &Comp, TaskGroup &TG, size_t Depth) { // Do a sequential sort for small inputs. if (std::distance(Start, End) < detail::MinParallelSize || Depth == 0) { - std::sort(Start, End, Comp); + llvm::sort(Start, End, Comp); return; } @@ -200,7 +200,7 @@ void sort(Policy policy, RandomAccessIterator Start, RandomAccessIterator End, const Comparator &Comp = Comparator()) { static_assert(is_execution_policy<Policy>::value, "Invalid execution policy!"); - std::sort(Start, End, Comp); + llvm::sort(Start, End, Comp); } template <class Policy, class IterTy, class FuncTy> diff --git a/contrib/llvm/include/llvm/Support/Path.h b/contrib/llvm/include/llvm/Support/Path.h index e5979674cf1c..c4cc93721d7e 100644 --- a/contrib/llvm/include/llvm/Support/Path.h +++ b/contrib/llvm/include/llvm/Support/Path.h @@ -20,6 +20,7 @@ #include "llvm/ADT/iterator.h" #include "llvm/Support/DataTypes.h" #include <iterator> +#include <system_error> namespace llvm { namespace sys { @@ -30,7 +31,7 @@ enum class Style { windows, posix, native }; /// @name Lexical Component Iterator /// @{ -/// @brief Path iterator. +/// Path iterator. /// /// This is an input iterator that iterates over the individual components in /// \a path. The traversal order is as follows: @@ -66,11 +67,11 @@ public: const_iterator &operator++(); // preincrement bool operator==(const const_iterator &RHS) const; - /// @brief Difference in bytes between this and RHS. + /// Difference in bytes between this and RHS. ptrdiff_t operator-(const const_iterator &RHS) const; }; -/// @brief Reverse path iterator. +/// Reverse path iterator. /// /// This is an input iterator that iterates over the individual components in /// \a path in reverse order. The traversal order is exactly reversed from that @@ -91,26 +92,26 @@ public: reverse_iterator &operator++(); // preincrement bool operator==(const reverse_iterator &RHS) const; - /// @brief Difference in bytes between this and RHS. + /// Difference in bytes between this and RHS. ptrdiff_t operator-(const reverse_iterator &RHS) const; }; -/// @brief Get begin iterator over \a path. +/// Get begin iterator over \a path. /// @param path Input path. /// @returns Iterator initialized with the first component of \a path. const_iterator begin(StringRef path, Style style = Style::native); -/// @brief Get end iterator over \a path. +/// Get end iterator over \a path. /// @param path Input path. /// @returns Iterator initialized to the end of \a path. const_iterator end(StringRef path); -/// @brief Get reverse begin iterator over \a path. +/// Get reverse begin iterator over \a path. /// @param path Input path. /// @returns Iterator initialized with the first reverse component of \a path. reverse_iterator rbegin(StringRef path, Style style = Style::native); -/// @brief Get reverse end iterator over \a path. +/// Get reverse end iterator over \a path. /// @param path Input path. /// @returns Iterator initialized to the reverse end of \a path. reverse_iterator rend(StringRef path); @@ -119,7 +120,7 @@ reverse_iterator rend(StringRef path); /// @name Lexical Modifiers /// @{ -/// @brief Remove the last component from \a path unless it is the root dir. +/// Remove the last component from \a path unless it is the root dir. /// /// @code /// directory/filename.cpp => directory/ @@ -131,7 +132,7 @@ reverse_iterator rend(StringRef path); /// @param path A path that is modified to not have a file component. void remove_filename(SmallVectorImpl<char> &path, Style style = Style::native); -/// @brief Replace the file extension of \a path with \a extension. +/// Replace the file extension of \a path with \a extension. /// /// @code /// ./filename.cpp => ./filename.extension @@ -146,7 +147,7 @@ void remove_filename(SmallVectorImpl<char> &path, Style style = Style::native); void replace_extension(SmallVectorImpl<char> &path, const Twine &extension, Style style = Style::native); -/// @brief Replace matching path prefix with another path. +/// Replace matching path prefix with another path. /// /// @code /// /foo, /old, /new => /foo @@ -163,7 +164,7 @@ void replace_path_prefix(SmallVectorImpl<char> &Path, const StringRef &OldPrefix, const StringRef &NewPrefix, Style style = Style::native); -/// @brief Append to path. +/// Append to path. /// /// @code /// /foo + bar/f => /foo/bar/f @@ -181,7 +182,7 @@ void append(SmallVectorImpl<char> &path, const Twine &a, void append(SmallVectorImpl<char> &path, Style style, const Twine &a, const Twine &b = "", const Twine &c = "", const Twine &d = ""); -/// @brief Append to path. +/// Append to path. /// /// @code /// /foo + [bar,f] => /foo/bar/f @@ -215,7 +216,7 @@ void native(const Twine &path, SmallVectorImpl<char> &result, /// @param path A path that is transformed to native format. void native(SmallVectorImpl<char> &path, Style style = Style::native); -/// @brief Replaces backslashes with slashes if Windows. +/// Replaces backslashes with slashes if Windows. /// /// @param path processed path /// @result The result of replacing backslashes with forward slashes if Windows. @@ -227,7 +228,7 @@ std::string convert_to_slash(StringRef path, Style style = Style::native); /// @name Lexical Observers /// @{ -/// @brief Get root name. +/// Get root name. /// /// @code /// //net/hello => //net @@ -239,7 +240,7 @@ std::string convert_to_slash(StringRef path, Style style = Style::native); /// @result The root name of \a path if it has one, otherwise "". StringRef root_name(StringRef path, Style style = Style::native); -/// @brief Get root directory. +/// Get root directory. /// /// @code /// /goo/hello => / @@ -252,7 +253,7 @@ StringRef root_name(StringRef path, Style style = Style::native); /// "". StringRef root_directory(StringRef path, Style style = Style::native); -/// @brief Get root path. +/// Get root path. /// /// Equivalent to root_name + root_directory. /// @@ -260,7 +261,7 @@ StringRef root_directory(StringRef path, Style style = Style::native); /// @result The root path of \a path if it has one, otherwise "". StringRef root_path(StringRef path, Style style = Style::native); -/// @brief Get relative path. +/// Get relative path. /// /// @code /// C:\hello\world => hello\world @@ -272,7 +273,7 @@ StringRef root_path(StringRef path, Style style = Style::native); /// @result The path starting after root_path if one exists, otherwise "". StringRef relative_path(StringRef path, Style style = Style::native); -/// @brief Get parent path. +/// Get parent path. /// /// @code /// / => <empty> @@ -284,7 +285,7 @@ StringRef relative_path(StringRef path, Style style = Style::native); /// @result The parent path of \a path if one exists, otherwise "". StringRef parent_path(StringRef path, Style style = Style::native); -/// @brief Get filename. +/// Get filename. /// /// @code /// /foo.txt => foo.txt @@ -298,7 +299,7 @@ StringRef parent_path(StringRef path, Style style = Style::native); /// of \a path. StringRef filename(StringRef path, Style style = Style::native); -/// @brief Get stem. +/// Get stem. /// /// If filename contains a dot but not solely one or two dots, result is the /// substring of filename ending at (but not including) the last dot. Otherwise @@ -316,7 +317,7 @@ StringRef filename(StringRef path, Style style = Style::native); /// @result The stem of \a path. StringRef stem(StringRef path, Style style = Style::native); -/// @brief Get extension. +/// Get extension. /// /// If filename contains a dot but not solely one or two dots, result is the /// substring of filename starting at (and including) the last dot, and ending @@ -332,18 +333,18 @@ StringRef stem(StringRef path, Style style = Style::native); /// @result The extension of \a path. StringRef extension(StringRef path, Style style = Style::native); -/// @brief Check whether the given char is a path separator on the host OS. +/// Check whether the given char is a path separator on the host OS. /// /// @param value a character /// @result true if \a value is a path separator character on the host OS bool is_separator(char value, Style style = Style::native); -/// @brief Return the preferred separator for this platform. +/// Return the preferred separator for this platform. /// /// @result StringRef of the preferred separator, null-terminated. StringRef get_separator(Style style = Style::native); -/// @brief Get the typical temporary directory for the system, e.g., +/// Get the typical temporary directory for the system, e.g., /// "/var/tmp" or "C:/TEMP" /// /// @param erasedOnReboot Whether to favor a path that is erased on reboot @@ -354,13 +355,13 @@ StringRef get_separator(Style style = Style::native); /// @param result Holds the resulting path name. void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result); -/// @brief Get the user's home directory. +/// 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 Get the user's cache directory. +/// Get the user's cache directory. /// /// Expect the resulting path to be a directory shared with other /// applications/services used by the user. Params \p Path1 to \p Path3 can be @@ -376,7 +377,7 @@ bool home_directory(SmallVectorImpl<char> &result); bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1, const Twine &Path2 = "", const Twine &Path3 = ""); -/// @brief Has root name? +/// Has root name? /// /// root_name != "" /// @@ -384,7 +385,7 @@ bool user_cache_directory(SmallVectorImpl<char> &Result, const Twine &Path1, /// @result True if the path has a root name, false otherwise. bool has_root_name(const Twine &path, Style style = Style::native); -/// @brief Has root directory? +/// Has root directory? /// /// root_directory != "" /// @@ -392,7 +393,7 @@ bool has_root_name(const Twine &path, Style style = Style::native); /// @result True if the path has a root directory, false otherwise. bool has_root_directory(const Twine &path, Style style = Style::native); -/// @brief Has root path? +/// Has root path? /// /// root_path != "" /// @@ -400,7 +401,7 @@ bool has_root_directory(const Twine &path, Style style = Style::native); /// @result True if the path has a root path, false otherwise. bool has_root_path(const Twine &path, Style style = Style::native); -/// @brief Has relative path? +/// Has relative path? /// /// relative_path != "" /// @@ -408,7 +409,7 @@ bool has_root_path(const Twine &path, Style style = Style::native); /// @result True if the path has a relative path, false otherwise. bool has_relative_path(const Twine &path, Style style = Style::native); -/// @brief Has parent path? +/// Has parent path? /// /// parent_path != "" /// @@ -416,7 +417,7 @@ bool has_relative_path(const Twine &path, Style style = Style::native); /// @result True if the path has a parent path, false otherwise. bool has_parent_path(const Twine &path, Style style = Style::native); -/// @brief Has filename? +/// Has filename? /// /// filename != "" /// @@ -424,7 +425,7 @@ bool has_parent_path(const Twine &path, Style style = Style::native); /// @result True if the path has a filename, false otherwise. bool has_filename(const Twine &path, Style style = Style::native); -/// @brief Has stem? +/// Has stem? /// /// stem != "" /// @@ -432,7 +433,7 @@ bool has_filename(const Twine &path, Style style = Style::native); /// @result True if the path has a stem, false otherwise. bool has_stem(const Twine &path, Style style = Style::native); -/// @brief Has extension? +/// Has extension? /// /// extension != "" /// @@ -440,25 +441,25 @@ bool has_stem(const Twine &path, Style style = Style::native); /// @result True if the path has a extension, false otherwise. bool has_extension(const Twine &path, Style style = Style::native); -/// @brief Is path absolute? +/// Is path absolute? /// /// @param path Input path. /// @result True if the path is absolute, false if it is not. bool is_absolute(const Twine &path, Style style = Style::native); -/// @brief Is path relative? +/// Is path relative? /// /// @param path Input path. /// @result True if the path is relative, false if it is not. bool is_relative(const Twine &path, Style style = Style::native); -/// @brief Remove redundant leading "./" pieces and consecutive separators. +/// Remove redundant leading "./" pieces and consecutive separators. /// /// @param path Input path. /// @result The cleaned-up \a path. StringRef remove_leading_dotslash(StringRef path, Style style = Style::native); -/// @brief In-place remove any './' and optionally '../' components from a path. +/// In-place remove any './' and optionally '../' components from a path. /// /// @param path processed path /// @param remove_dot_dot specify if '../' (except for leading "../") should be @@ -467,6 +468,10 @@ StringRef remove_leading_dotslash(StringRef path, Style style = Style::native); bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot = false, Style style = Style::native); +#if defined(_WIN32) +std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16); +#endif + } // end namespace path } // end namespace sys } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h b/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h index 794230d606a4..1710b57131d1 100644 --- a/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h +++ b/contrib/llvm/include/llvm/Support/PointerLikeTypeTraits.h @@ -16,6 +16,7 @@ #define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H #include "llvm/Support/DataTypes.h" +#include <assert.h> #include <type_traits> namespace llvm { @@ -111,6 +112,39 @@ template <> struct PointerLikeTypeTraits<uintptr_t> { enum { NumLowBitsAvailable = 0 }; }; +/// Provide suitable custom traits struct for function pointers. +/// +/// Function pointers can't be directly given these traits as functions can't +/// have their alignment computed with `alignof` and we need different casting. +/// +/// To rely on higher alignment for a specialized use, you can provide a +/// customized form of this template explicitly with higher alignment, and +/// potentially use alignment attributes on functions to satisfy that. +template <int Alignment, typename FunctionPointerT> +struct FunctionPointerLikeTypeTraits { + enum { NumLowBitsAvailable = detail::ConstantLog2<Alignment>::value }; + static inline void *getAsVoidPointer(FunctionPointerT P) { + assert((reinterpret_cast<uintptr_t>(P) & + ~((uintptr_t)-1 << NumLowBitsAvailable)) == 0 && + "Alignment not satisfied for an actual function pointer!"); + return reinterpret_cast<void *>(P); + } + static inline FunctionPointerT getFromVoidPointer(void *P) { + return reinterpret_cast<FunctionPointerT>(P); + } +}; + +/// Provide a default specialization for function pointers that assumes 4-byte +/// alignment. +/// +/// We assume here that functions used with this are always at least 4-byte +/// aligned. This means that, for example, thumb functions won't work or systems +/// with weird unaligned function pointers won't work. But all practical systems +/// we support satisfy this requirement. +template <typename ReturnT, typename... ParamTs> +struct PointerLikeTypeTraits<ReturnT (*)(ParamTs...)> + : FunctionPointerLikeTypeTraits<4, ReturnT (*)(ParamTs...)> {}; + } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Support/Process.h b/contrib/llvm/include/llvm/Support/Process.h index 82b0d9f6ba28..f9f1cac86278 100644 --- a/contrib/llvm/include/llvm/Support/Process.h +++ b/contrib/llvm/include/llvm/Support/Process.h @@ -26,7 +26,6 @@ #define LLVM_SUPPORT_PROCESS_H #include "llvm/ADT/Optional.h" -#include "llvm/Config/llvm-config.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/DataTypes.h" @@ -39,13 +38,13 @@ class StringRef; namespace sys { -/// \brief A collection of legacy interfaces for querying information about the +/// A collection of legacy interfaces for querying information about the /// current executing process. class Process { public: static unsigned getPageSize(); - /// \brief Return process memory usage. + /// Return process memory usage. /// This static function will return the total amount of memory allocated /// by the process. This only counts the memory allocated via the malloc, /// calloc and realloc functions and includes any "free" holes in the @@ -67,10 +66,10 @@ public: /// This function makes the necessary calls to the operating system to /// prevent core files or any other kind of large memory dumps that can /// occur when a program fails. - /// @brief Prevent core file generation. + /// Prevent core file generation. static void PreventCoreFiles(); - /// \brief true if PreventCoreFiles has been called, false otherwise. + /// true if PreventCoreFiles has been called, false otherwise. static bool AreCoreFilesPrevented(); // This function returns the environment variable \arg name's value as a UTF-8 @@ -90,14 +89,6 @@ public: static Optional<std::string> FindInEnvPath(StringRef EnvName, StringRef FileName); - /// This function returns a SmallVector containing the arguments passed from - /// the operating system to the program. This function expects to be handed - /// the vector passed in from main. - static std::error_code - GetArgumentVector(SmallVectorImpl<const char *> &Args, - ArrayRef<const char *> ArgsFromMain, - SpecificBumpPtrAllocator<char> &ArgAllocator); - // This functions ensures that the standard file descriptors (input, output, // and error) are properly mapped to a file descriptor before we use any of // them. This should only be called by standalone programs, library diff --git a/contrib/llvm/include/llvm/Support/Program.h b/contrib/llvm/include/llvm/Support/Program.h index 06fd35078145..1f4dbdce3323 100644 --- a/contrib/llvm/include/llvm/Support/Program.h +++ b/contrib/llvm/include/llvm/Support/Program.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/ErrorOr.h" #include <system_error> @@ -27,35 +28,32 @@ namespace sys { // a colon on Unix or a semicolon on Windows. #if defined(LLVM_ON_UNIX) const char EnvPathSeparator = ':'; -#elif defined (LLVM_ON_WIN32) +#elif defined (_WIN32) const char EnvPathSeparator = ';'; #endif -/// @brief This struct encapsulates information about a process. -struct ProcessInfo { -#if defined(LLVM_ON_UNIX) - typedef pid_t ProcessId; -#elif defined(LLVM_ON_WIN32) - typedef unsigned long ProcessId; // Must match the type of DWORD on Windows. - typedef void * HANDLE; // Must match the type of HANDLE on Windows. - /// The handle to the process (available on Windows only). - HANDLE ProcessHandle; +#if defined(_WIN32) + typedef unsigned long procid_t; // Must match the type of DWORD on Windows. + typedef void *process_t; // Must match the type of HANDLE on Windows. #else -#error "ProcessInfo is not defined for this platform!" + typedef pid_t procid_t; + typedef procid_t process_t; #endif - enum : ProcessId { InvalidPid = 0 }; + /// This struct encapsulates information about a process. + struct ProcessInfo { + enum : procid_t { InvalidPid = 0 }; - /// The process identifier. - ProcessId Pid; + procid_t Pid; /// The process identifier. + process_t Process; /// Platform-dependent process object. - /// The return code, set after execution. - int ReturnCode; + /// The return code, set after execution. + int ReturnCode; - ProcessInfo(); -}; + ProcessInfo(); + }; - /// \brief Find the first executable file \p Name in \p Paths. + /// Find the first executable file \p Name in \p Paths. /// /// This does not perform hashing as a shell would but instead stats each PATH /// entry individually so should generally be avoided. Core LLVM library @@ -91,12 +89,13 @@ struct ProcessInfo { int ExecuteAndWait( StringRef Program, ///< Path of the program to be executed. It is ///< presumed this is the result of the findProgramByName method. - const char **Args, ///< A vector of strings that are passed to the + ArrayRef<StringRef> Args, ///< An array of strings that are passed to the ///< program. The first element should be the name of the program. - ///< The list *must* be terminated by a null char* entry. - const char **Env = nullptr, ///< An optional vector of strings to use for - ///< the program's environment. If not provided, the current program's - ///< environment will be used. + ///< The array should **not** be terminated by an empty StringRef. + Optional<ArrayRef<StringRef>> Env = None, ///< An optional vector of + ///< strings to use for the program's environment. If not provided, the + ///< current program's environment will be used. If specified, the + ///< vector should **not** be terminated by an empty StringRef. ArrayRef<Optional<StringRef>> Redirects = {}, ///< ///< An array of optional paths. Should have a size of zero or three. ///< If the array is empty, no redirections are performed. @@ -125,8 +124,8 @@ struct ProcessInfo { /// \note On Microsoft Windows systems, users will need to either call /// \see Wait until the process finished execution or win32 CloseHandle() API /// on ProcessInfo.ProcessHandle to avoid memory leaks. - ProcessInfo ExecuteNoWait(StringRef Program, const char **Args, - const char **Env = nullptr, + ProcessInfo ExecuteNoWait(StringRef Program, ArrayRef<StringRef> Args, + Optional<ArrayRef<StringRef>> Env, ArrayRef<Optional<StringRef>> Redirects = {}, unsigned MemoryLimit = 0, std::string *ErrMsg = nullptr, @@ -135,6 +134,11 @@ struct ProcessInfo { /// Return true if the given arguments fit within system-specific /// argument length limits. bool commandLineFitsWithinSystemLimits(StringRef Program, + ArrayRef<StringRef> Args); + + /// Return true if the given arguments fit within system-specific + /// argument length limits. + bool commandLineFitsWithinSystemLimits(StringRef Program, ArrayRef<const char *> Args); /// File encoding options when writing contents that a non-UTF8 tool will @@ -191,6 +195,14 @@ struct ProcessInfo { ///< string is non-empty upon return an error occurred while invoking the ///< program. ); + +#if defined(_WIN32) + /// Given a list of command line arguments, quote and escape them as necessary + /// to build a single flat command line appropriate for calling CreateProcess + /// on + /// Windows. + std::string flattenWindowsCommandLine(ArrayRef<StringRef> Args); +#endif } } diff --git a/contrib/llvm/include/llvm/Support/RWMutex.h b/contrib/llvm/include/llvm/Support/RWMutex.h index 85f4fc09fb87..5ac3e558999b 100644 --- a/contrib/llvm/include/llvm/Support/RWMutex.h +++ b/contrib/llvm/include/llvm/Support/RWMutex.h @@ -21,7 +21,7 @@ namespace llvm { namespace sys { - /// @brief Platform agnostic RWMutex class. + /// Platform agnostic RWMutex class. class RWMutexImpl { /// @name Constructors @@ -29,7 +29,7 @@ namespace sys { public: /// Initializes the lock but doesn't acquire it. - /// @brief Default Constructor. + /// Default Constructor. explicit RWMutexImpl(); /// @} @@ -40,7 +40,7 @@ namespace sys { /// @} /// Releases and removes the lock - /// @brief Destructor + /// Destructor ~RWMutexImpl(); /// @} @@ -52,24 +52,24 @@ namespace sys { /// lock is held by a writer, this method will wait until it can acquire /// the lock. /// @returns false if any kind of error occurs, true otherwise. - /// @brief Unconditionally acquire the lock in reader mode. + /// Unconditionally acquire the lock in reader mode. bool reader_acquire(); /// Attempts to release the lock in reader mode. /// @returns false if any kind of error occurs, true otherwise. - /// @brief Unconditionally release the lock in reader mode. + /// Unconditionally release the lock in reader mode. bool reader_release(); /// Attempts to unconditionally acquire the lock in reader mode. If the /// lock is held by any readers, this method will wait until it can /// acquire the lock. /// @returns false if any kind of error occurs, true otherwise. - /// @brief Unconditionally acquire the lock in writer mode. + /// Unconditionally acquire the lock in writer mode. bool writer_acquire(); /// Attempts to release the lock in writer mode. /// @returns false if any kind of error occurs, true otherwise. - /// @brief Unconditionally release the lock in write mode. + /// Unconditionally release the lock in write mode. bool writer_release(); //@} diff --git a/contrib/llvm/include/llvm/Support/Regex.h b/contrib/llvm/include/llvm/Support/Regex.h index f498835bcb58..d901eb1e3ffb 100644 --- a/contrib/llvm/include/llvm/Support/Regex.h +++ b/contrib/llvm/include/llvm/Support/Regex.h @@ -86,11 +86,11 @@ namespace llvm { std::string sub(StringRef Repl, StringRef String, std::string *Error = nullptr); - /// \brief If this function returns true, ^Str$ is an extended regular + /// If this function returns true, ^Str$ is an extended regular /// expression that matches Str and only Str. static bool isLiteralERE(StringRef Str); - /// \brief Turn String into a regex by escaping its special characters. + /// Turn String into a regex by escaping its special characters. static std::string escape(StringRef String); private: diff --git a/contrib/llvm/include/llvm/Support/SMLoc.h b/contrib/llvm/include/llvm/Support/SMLoc.h index 5b8be5505540..c74feff378d6 100644 --- a/contrib/llvm/include/llvm/Support/SMLoc.h +++ b/contrib/llvm/include/llvm/Support/SMLoc.h @@ -44,8 +44,8 @@ public: /// Represents a range in source code. /// /// SMRange is implemented using a half-open range, as is the convention in C++. -/// In the string "abc", the range (1,3] represents the substring "bc", and the -/// range (2,2] represents an empty range between the characters "b" and "c". +/// In the string "abc", the range [1,3) represents the substring "bc", and the +/// range [2,2) represents an empty range between the characters "b" and "c". class SMRange { public: SMLoc Start, End; @@ -54,7 +54,7 @@ public: SMRange(NoneType) {} SMRange(SMLoc St, SMLoc En) : Start(St), End(En) { assert(Start.isValid() == End.isValid() && - "Start and end should either both be valid or both be invalid!"); + "Start and End should either both be valid or both be invalid!"); } bool isValid() const { return Start.isValid(); } diff --git a/contrib/llvm/include/llvm/Support/SaveAndRestore.h b/contrib/llvm/include/llvm/Support/SaveAndRestore.h index ef154ac9c913..8e11789907ad 100644 --- a/contrib/llvm/include/llvm/Support/SaveAndRestore.h +++ b/contrib/llvm/include/llvm/Support/SaveAndRestore.h @@ -32,18 +32,6 @@ private: T OldValue; }; -/// Similar to \c SaveAndRestore. Operates only on bools; the old value of a -/// variable is saved, and during the dstor the old value is or'ed with the new -/// value. -struct SaveOr { - SaveOr(bool &X) : X(X), OldValue(X) { X = false; } - ~SaveOr() { X |= OldValue; } - -private: - bool &X; - const bool OldValue; -}; - } // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Support/ScaledNumber.h b/contrib/llvm/include/llvm/Support/ScaledNumber.h index cfbdbc751617..3bd3ccedc42c 100644 --- a/contrib/llvm/include/llvm/Support/ScaledNumber.h +++ b/contrib/llvm/include/llvm/Support/ScaledNumber.h @@ -33,16 +33,16 @@ namespace llvm { namespace ScaledNumbers { -/// \brief Maximum scale; same as APFloat for easy debug printing. +/// Maximum scale; same as APFloat for easy debug printing. const int32_t MaxScale = 16383; -/// \brief Maximum scale; same as APFloat for easy debug printing. +/// Maximum scale; same as APFloat for easy debug printing. const int32_t MinScale = -16382; -/// \brief Get the width of a number. +/// Get the width of a number. template <class DigitsT> inline int getWidth() { return sizeof(DigitsT) * 8; } -/// \brief Conditionally round up a scaled number. +/// Conditionally round up a scaled number. /// /// Given \c Digits and \c Scale, round up iff \c ShouldRound is \c true. /// Always returns \c Scale unless there's an overflow, in which case it @@ -61,19 +61,19 @@ inline std::pair<DigitsT, int16_t> getRounded(DigitsT Digits, int16_t Scale, return std::make_pair(Digits, Scale); } -/// \brief Convenience helper for 32-bit rounding. +/// Convenience helper for 32-bit rounding. inline std::pair<uint32_t, int16_t> getRounded32(uint32_t Digits, int16_t Scale, bool ShouldRound) { return getRounded(Digits, Scale, ShouldRound); } -/// \brief Convenience helper for 64-bit rounding. +/// Convenience helper for 64-bit rounding. inline std::pair<uint64_t, int16_t> getRounded64(uint64_t Digits, int16_t Scale, bool ShouldRound) { return getRounded(Digits, Scale, ShouldRound); } -/// \brief Adjust a 64-bit scaled number down to the appropriate width. +/// Adjust a 64-bit scaled number down to the appropriate width. /// /// \pre Adding 64 to \c Scale will not overflow INT16_MAX. template <class DigitsT> @@ -91,24 +91,24 @@ inline std::pair<DigitsT, int16_t> getAdjusted(uint64_t Digits, Digits & (UINT64_C(1) << (Shift - 1))); } -/// \brief Convenience helper for adjusting to 32 bits. +/// Convenience helper for adjusting to 32 bits. inline std::pair<uint32_t, int16_t> getAdjusted32(uint64_t Digits, int16_t Scale = 0) { return getAdjusted<uint32_t>(Digits, Scale); } -/// \brief Convenience helper for adjusting to 64 bits. +/// Convenience helper for adjusting to 64 bits. inline std::pair<uint64_t, int16_t> getAdjusted64(uint64_t Digits, int16_t Scale = 0) { return getAdjusted<uint64_t>(Digits, Scale); } -/// \brief Multiply two 64-bit integers to create a 64-bit scaled number. +/// Multiply two 64-bit integers to create a 64-bit scaled number. /// /// Implemented with four 64-bit integer multiplies. std::pair<uint64_t, int16_t> multiply64(uint64_t LHS, uint64_t RHS); -/// \brief Multiply two 32-bit integers to create a 32-bit scaled number. +/// Multiply two 32-bit integers to create a 32-bit scaled number. /// /// Implemented with one 64-bit integer multiply. template <class DigitsT> @@ -121,31 +121,31 @@ inline std::pair<DigitsT, int16_t> getProduct(DigitsT LHS, DigitsT RHS) { return multiply64(LHS, RHS); } -/// \brief Convenience helper for 32-bit product. +/// Convenience helper for 32-bit product. inline std::pair<uint32_t, int16_t> getProduct32(uint32_t LHS, uint32_t RHS) { return getProduct(LHS, RHS); } -/// \brief Convenience helper for 64-bit product. +/// Convenience helper for 64-bit product. inline std::pair<uint64_t, int16_t> getProduct64(uint64_t LHS, uint64_t RHS) { return getProduct(LHS, RHS); } -/// \brief Divide two 64-bit integers to create a 64-bit scaled number. +/// Divide two 64-bit integers to create a 64-bit scaled number. /// /// Implemented with long division. /// /// \pre \c Dividend and \c Divisor are non-zero. std::pair<uint64_t, int16_t> divide64(uint64_t Dividend, uint64_t Divisor); -/// \brief Divide two 32-bit integers to create a 32-bit scaled number. +/// Divide two 32-bit integers to create a 32-bit scaled number. /// /// Implemented with one 64-bit integer divide/remainder pair. /// /// \pre \c Dividend and \c Divisor are non-zero. std::pair<uint32_t, int16_t> divide32(uint32_t Dividend, uint32_t Divisor); -/// \brief Divide two 32-bit numbers to create a 32-bit scaled number. +/// Divide two 32-bit numbers to create a 32-bit scaled number. /// /// Implemented with one 64-bit integer divide/remainder pair. /// @@ -167,19 +167,19 @@ std::pair<DigitsT, int16_t> getQuotient(DigitsT Dividend, DigitsT Divisor) { return divide32(Dividend, Divisor); } -/// \brief Convenience helper for 32-bit quotient. +/// Convenience helper for 32-bit quotient. inline std::pair<uint32_t, int16_t> getQuotient32(uint32_t Dividend, uint32_t Divisor) { return getQuotient(Dividend, Divisor); } -/// \brief Convenience helper for 64-bit quotient. +/// Convenience helper for 64-bit quotient. inline std::pair<uint64_t, int16_t> getQuotient64(uint64_t Dividend, uint64_t Divisor) { return getQuotient(Dividend, Divisor); } -/// \brief Implementation of getLg() and friends. +/// Implementation of getLg() and friends. /// /// Returns the rounded lg of \c Digits*2^Scale and an int specifying whether /// this was rounded up (1), down (-1), or exact (0). @@ -206,7 +206,7 @@ inline std::pair<int32_t, int> getLgImpl(DigitsT Digits, int16_t Scale) { return std::make_pair(Floor + Round, Round ? 1 : -1); } -/// \brief Get the lg (rounded) of a scaled number. +/// Get the lg (rounded) of a scaled number. /// /// Get the lg of \c Digits*2^Scale. /// @@ -215,7 +215,7 @@ template <class DigitsT> int32_t getLg(DigitsT Digits, int16_t Scale) { return getLgImpl(Digits, Scale).first; } -/// \brief Get the lg floor of a scaled number. +/// Get the lg floor of a scaled number. /// /// Get the floor of the lg of \c Digits*2^Scale. /// @@ -225,7 +225,7 @@ template <class DigitsT> int32_t getLgFloor(DigitsT Digits, int16_t Scale) { return Lg.first - (Lg.second > 0); } -/// \brief Get the lg ceiling of a scaled number. +/// Get the lg ceiling of a scaled number. /// /// Get the ceiling of the lg of \c Digits*2^Scale. /// @@ -235,7 +235,7 @@ template <class DigitsT> int32_t getLgCeiling(DigitsT Digits, int16_t Scale) { return Lg.first + (Lg.second < 0); } -/// \brief Implementation for comparing scaled numbers. +/// Implementation for comparing scaled numbers. /// /// Compare two 64-bit numbers with different scales. Given that the scale of /// \c L is higher than that of \c R by \c ScaleDiff, compare them. Return -1, @@ -244,7 +244,7 @@ template <class DigitsT> int32_t getLgCeiling(DigitsT Digits, int16_t Scale) { /// \pre 0 <= ScaleDiff < 64. int compareImpl(uint64_t L, uint64_t R, int ScaleDiff); -/// \brief Compare two scaled numbers. +/// Compare two scaled numbers. /// /// Compare two scaled numbers. Returns 0 for equal, -1 for less than, and 1 /// for greater than. @@ -271,7 +271,7 @@ int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale) { return -compareImpl(RDigits, LDigits, LScale - RScale); } -/// \brief Match scales of two numbers. +/// Match scales of two numbers. /// /// Given two scaled numbers, match up their scales. Change the digits and /// scales in place. Shift the digits as necessary to form equivalent numbers, @@ -324,7 +324,7 @@ int16_t matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits, return LScale; } -/// \brief Get the sum of two scaled numbers. +/// Get the sum of two scaled numbers. /// /// Get the sum of two scaled numbers with as much precision as possible. /// @@ -352,19 +352,19 @@ std::pair<DigitsT, int16_t> getSum(DigitsT LDigits, int16_t LScale, return std::make_pair(HighBit | Sum >> 1, Scale + 1); } -/// \brief Convenience helper for 32-bit sum. +/// Convenience helper for 32-bit sum. inline std::pair<uint32_t, int16_t> getSum32(uint32_t LDigits, int16_t LScale, uint32_t RDigits, int16_t RScale) { return getSum(LDigits, LScale, RDigits, RScale); } -/// \brief Convenience helper for 64-bit sum. +/// Convenience helper for 64-bit sum. inline std::pair<uint64_t, int16_t> getSum64(uint64_t LDigits, int16_t LScale, uint64_t RDigits, int16_t RScale) { return getSum(LDigits, LScale, RDigits, RScale); } -/// \brief Get the difference of two scaled numbers. +/// Get the difference of two scaled numbers. /// /// Get LHS minus RHS with as much precision as possible. /// @@ -395,7 +395,7 @@ std::pair<DigitsT, int16_t> getDifference(DigitsT LDigits, int16_t LScale, return std::make_pair(LDigits, LScale); } -/// \brief Convenience helper for 32-bit difference. +/// Convenience helper for 32-bit difference. inline std::pair<uint32_t, int16_t> getDifference32(uint32_t LDigits, int16_t LScale, uint32_t RDigits, @@ -403,7 +403,7 @@ inline std::pair<uint32_t, int16_t> getDifference32(uint32_t LDigits, return getDifference(LDigits, LScale, RDigits, RScale); } -/// \brief Convenience helper for 64-bit difference. +/// Convenience helper for 64-bit difference. inline std::pair<uint64_t, int16_t> getDifference64(uint64_t LDigits, int16_t LScale, uint64_t RDigits, @@ -443,7 +443,7 @@ public: } }; -/// \brief Simple representation of a scaled number. +/// Simple representation of a scaled number. /// /// ScaledNumber is a number represented by digits and a scale. It uses simple /// saturation arithmetic and every operation is well-defined for every value. @@ -534,7 +534,7 @@ public: int16_t getScale() const { return Scale; } DigitsType getDigits() const { return Digits; } - /// \brief Convert to the given integer type. + /// Convert to the given integer type. /// /// Convert to \c IntT using simple saturating arithmetic, truncating if /// necessary. @@ -548,17 +548,17 @@ public: return Digits == DigitsType(1) << -Scale; } - /// \brief The log base 2, rounded. + /// The log base 2, rounded. /// /// Get the lg of the scalar. lg 0 is defined to be INT32_MIN. int32_t lg() const { return ScaledNumbers::getLg(Digits, Scale); } - /// \brief The log base 2, rounded towards INT32_MIN. + /// The log base 2, rounded towards INT32_MIN. /// /// Get the lg floor. lg 0 is defined to be INT32_MIN. int32_t lgFloor() const { return ScaledNumbers::getLgFloor(Digits, Scale); } - /// \brief The log base 2, rounded towards INT32_MAX. + /// The log base 2, rounded towards INT32_MAX. /// /// Get the lg ceiling. lg 0 is defined to be INT32_MIN. int32_t lgCeiling() const { @@ -574,7 +574,7 @@ public: bool operator!() const { return isZero(); } - /// \brief Convert to a decimal representation in a string. + /// Convert to a decimal representation in a string. /// /// Convert to a string. Uses scientific notation for very large/small /// numbers. Scientific notation is used roughly for numbers outside of the @@ -597,7 +597,7 @@ public: return ScaledNumberBase::toString(Digits, Scale, Width, Precision); } - /// \brief Print a decimal representation. + /// Print a decimal representation. /// /// Print a string. See toString for documentation. raw_ostream &print(raw_ostream &OS, @@ -634,7 +634,7 @@ private: void shiftLeft(int32_t Shift); void shiftRight(int32_t Shift); - /// \brief Adjust two floats to have matching exponents. + /// Adjust two floats to have matching exponents. /// /// Adjust \c this and \c X to have matching exponents. Returns the new \c X /// by value. Does nothing if \a isZero() for either. @@ -647,7 +647,7 @@ private: } public: - /// \brief Scale a large number accurately. + /// Scale a large number accurately. /// /// Scale N (multiply it by this). Uses full precision multiplication, even /// if Width is smaller than 64, so information is not lost. @@ -693,7 +693,7 @@ private: return countLeadingZeros32(Digits) + Width - 32; } - /// \brief Adjust a number to width, rounding up if necessary. + /// Adjust a number to width, rounding up if necessary. /// /// Should only be called for \c Shift close to zero. /// diff --git a/contrib/llvm/include/llvm/Support/ScopedPrinter.h b/contrib/llvm/include/llvm/Support/ScopedPrinter.h index 1b6651932212..062439b4f7db 100644 --- a/contrib/llvm/include/llvm/Support/ScopedPrinter.h +++ b/contrib/llvm/include/llvm/Support/ScopedPrinter.h @@ -80,6 +80,8 @@ public: void resetIndent() { IndentLevel = 0; } + int getIndentLevel() { return IndentLevel; } + void setPrefix(StringRef P) { Prefix = P; } void printIndent() { @@ -136,7 +138,7 @@ public: } } - std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); + llvm::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); startLine() << Label << " [ (" << hex(Value) << ")\n"; for (const auto &Flag : SetFlags) { @@ -261,7 +263,11 @@ public: } void printString(StringRef Label, const std::string &Value) { - startLine() << Label << ": " << Value << "\n"; + printString(Label, StringRef(Value)); + } + + void printString(StringRef Label, const char* Value) { + printString(Label, StringRef(Value)); } template <typename T> diff --git a/contrib/llvm/include/llvm/Support/Signals.h b/contrib/llvm/include/llvm/Support/Signals.h index cbd6f686a778..f25a04969904 100644 --- a/contrib/llvm/include/llvm/Support/Signals.h +++ b/contrib/llvm/include/llvm/Support/Signals.h @@ -29,16 +29,16 @@ namespace sys { /// This function registers signal handlers to ensure that if a signal gets /// delivered that the named file is removed. - /// @brief Remove a file if a fatal signal occurs. + /// Remove a file if a fatal signal occurs. bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = nullptr); /// This function removes a file from the list of files to be removed on /// signal delivery. void DontRemoveFileOnSignal(StringRef Filename); - /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the + /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the /// process, print a stack trace and then exit. - /// \brief Print a stack trace if a fatal signal occurs. + /// Print a stack trace if a fatal signal occurs. /// \param Argv0 the current binary name, used to find the symbolizer /// relative to the current binary before searching $PATH; can be /// StringRef(), in which case we will only search $PATH. @@ -50,16 +50,18 @@ namespace sys { /// Disable all system dialog boxes that appear when the process crashes. void DisableSystemDialogsOnCrash(); - /// \brief Print the stack trace using the given \c raw_ostream object. + /// Print the stack trace using the given \c raw_ostream object. void PrintStackTrace(raw_ostream &OS); // Run all registered signal handlers. void RunSignalHandlers(); - /// AddSignalHandler - Add a function to be called when an abort/kill signal - /// is delivered to the process. The handler can have a cookie passed to it - /// to identify what instance of the handler it is. - void AddSignalHandler(void (*FnPtr)(void *), void *Cookie); + using SignalHandlerCallback = void (*)(void *); + + /// Add a function to be called when an abort/kill signal is delivered to the + /// process. The handler can have a cookie passed to it to identify what + /// instance of the handler it is. + void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie); /// This function registers a function to be called when the user "interrupts" /// the program (typically by pressing ctrl-c). When the user interrupts the @@ -69,7 +71,7 @@ namespace sys { /// functions. An null interrupt function pointer disables the current /// installed function. Note also that the handler may be executed on a /// different thread on some platforms. - /// @brief Register a function to be called when ctrl-c is pressed. + /// Register a function to be called when ctrl-c is pressed. void SetInterruptFunction(void (*IF)()); } // End sys namespace } // End llvm namespace diff --git a/contrib/llvm/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h b/contrib/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h index 0f00ad006a7d..f43c2fb8f826 100644 --- a/contrib/llvm/include/llvm/ExecutionEngine/ObjectMemoryBuffer.h +++ b/contrib/llvm/include/llvm/Support/SmallVectorMemoryBuffer.h @@ -1,4 +1,4 @@ -//===- ObjectMemoryBuffer.h - SmallVector-backed MemoryBuffrer -*- C++ -*-===// +//===- SmallVectorMemoryBuffer.h --------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,31 +21,31 @@ namespace llvm { -/// \brief SmallVector-backed MemoryBuffer instance. +/// SmallVector-backed MemoryBuffer instance. /// /// This class enables efficient construction of MemoryBuffers from SmallVector /// instances. This is useful for MCJIT and Orc, where object files are streamed /// into SmallVectors, then inspected using ObjectFile (which takes a /// MemoryBuffer). -class ObjectMemoryBuffer : public MemoryBuffer { +class SmallVectorMemoryBuffer : public MemoryBuffer { public: - - /// \brief Construct an ObjectMemoryBuffer from the given SmallVector r-value. + /// Construct an SmallVectorMemoryBuffer from the given SmallVector + /// r-value. /// /// FIXME: It'd be nice for this to be a non-templated constructor taking a /// SmallVectorImpl here instead of a templated one taking a SmallVector<N>, /// but SmallVector's move-construction/assignment currently only take /// SmallVectors. If/when that is fixed we can simplify this constructor and /// the following one. - ObjectMemoryBuffer(SmallVectorImpl<char> &&SV) - : SV(std::move(SV)), BufferName("<in-memory object>") { + SmallVectorMemoryBuffer(SmallVectorImpl<char> &&SV) + : SV(std::move(SV)), BufferName("<in-memory object>") { init(this->SV.begin(), this->SV.end(), false); } - /// \brief Construct a named ObjectMemoryBuffer from the given SmallVector - /// r-value and StringRef. - ObjectMemoryBuffer(SmallVectorImpl<char> &&SV, StringRef Name) - : SV(std::move(SV)), BufferName(Name) { + /// Construct a named SmallVectorMemoryBuffer from the given + /// SmallVector r-value and StringRef. + SmallVectorMemoryBuffer(SmallVectorImpl<char> &&SV, StringRef Name) + : SV(std::move(SV)), BufferName(Name) { init(this->SV.begin(), this->SV.end(), false); } @@ -56,6 +56,7 @@ public: private: SmallVector<char, 0> SV; std::string BufferName; + void anchor() override; }; } // namespace llvm diff --git a/contrib/llvm/include/llvm/Support/SourceMgr.h b/contrib/llvm/include/llvm/Support/SourceMgr.h index c08bf858760a..63ac893239d1 100644 --- a/contrib/llvm/include/llvm/Support/SourceMgr.h +++ b/contrib/llvm/include/llvm/Support/SourceMgr.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" @@ -57,8 +58,38 @@ private: /// The memory buffer for the file. std::unique_ptr<MemoryBuffer> Buffer; + /// Helper type for OffsetCache below: since we're storing many offsets + /// into relatively small files (often smaller than 2^8 or 2^16 bytes), + /// we select the offset vector element type dynamically based on the + /// size of Buffer. + using VariableSizeOffsets = PointerUnion4<std::vector<uint8_t> *, + std::vector<uint16_t> *, + std::vector<uint32_t> *, + std::vector<uint64_t> *>; + + /// Vector of offsets into Buffer at which there are line-endings + /// (lazily populated). Once populated, the '\n' that marks the end of + /// line number N from [1..] is at Buffer[OffsetCache[N-1]]. Since + /// these offsets are in sorted (ascending) order, they can be + /// binary-searched for the first one after any given offset (eg. an + /// offset corresponding to a particular SMLoc). + mutable VariableSizeOffsets OffsetCache; + + /// Populate \c OffsetCache and look up a given \p Ptr in it, assuming + /// it points somewhere into \c Buffer. The static type parameter \p T + /// must be an unsigned integer type from uint{8,16,32,64}_t large + /// enough to store offsets inside \c Buffer. + template<typename T> + unsigned getLineNumber(const char *Ptr) const; + /// This is the location of the parent include, or null if at the top level. SMLoc IncludeLoc; + + SrcBuffer() = default; + SrcBuffer(SrcBuffer &&); + SrcBuffer(const SrcBuffer &) = delete; + SrcBuffer &operator=(const SrcBuffer &) = delete; + ~SrcBuffer(); }; /// This is all of the buffers that we are reading from. @@ -67,10 +98,6 @@ private: // This is the list of directories we should search for include files in. std::vector<std::string> IncludeDirectories; - /// This is a cache for line number queries, its implementation is really - /// private to SourceMgr.cpp. - mutable void *LineNoCache = nullptr; - DiagHandlerTy DiagHandler = nullptr; void *DiagContext = nullptr; @@ -80,7 +107,7 @@ public: SourceMgr() = default; SourceMgr(const SourceMgr &) = delete; SourceMgr &operator=(const SourceMgr &) = delete; - ~SourceMgr(); + ~SourceMgr() = default; void setIncludeDirs(const std::vector<std::string> &Dirs) { IncludeDirectories = Dirs; diff --git a/contrib/llvm/include/llvm/Support/StringSaver.h b/contrib/llvm/include/llvm/Support/StringSaver.h index e85b2895ce51..6b77d487333b 100644 --- a/contrib/llvm/include/llvm/Support/StringSaver.h +++ b/contrib/llvm/include/llvm/Support/StringSaver.h @@ -10,23 +10,49 @@ #ifndef LLVM_SUPPORT_STRINGSAVER_H #define LLVM_SUPPORT_STRINGSAVER_H +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Allocator.h" namespace llvm { -/// \brief Saves strings in the inheritor's stable storage and returns a +/// Saves strings in the provided stable storage and returns a /// StringRef with a stable character pointer. class StringSaver final { BumpPtrAllocator &Alloc; public: StringSaver(BumpPtrAllocator &Alloc) : Alloc(Alloc) {} + + // All returned strings are null-terminated: *save(S).end() == 0. StringRef save(const char *S) { return save(StringRef(S)); } StringRef save(StringRef S); StringRef save(const Twine &S) { return save(StringRef(S.str())); } StringRef save(const std::string &S) { return save(StringRef(S)); } }; + +/// Saves strings in the provided stable storage and returns a StringRef with a +/// stable character pointer. Saving the same string yields the same StringRef. +/// +/// Compared to StringSaver, it does more work but avoids saving the same string +/// multiple times. +/// +/// Compared to StringPool, it performs fewer allocations but doesn't support +/// refcounting/deletion. +class UniqueStringSaver final { + StringSaver Strings; + llvm::DenseSet<llvm::StringRef> Unique; + +public: + UniqueStringSaver(BumpPtrAllocator &Alloc) : Strings(Alloc) {} + + // All returned strings are null-terminated: *save(S).end() == 0. + StringRef save(const char *S) { return save(StringRef(S)); } + StringRef save(StringRef S); + StringRef save(const Twine &S) { return save(StringRef(S.str())); } + StringRef save(const std::string &S) { return save(StringRef(S)); } +}; + } #endif diff --git a/contrib/llvm/include/llvm/Support/SystemUtils.h b/contrib/llvm/include/llvm/Support/SystemUtils.h index 2997b1b0c9cf..bd60793d1554 100644 --- a/contrib/llvm/include/llvm/Support/SystemUtils.h +++ b/contrib/llvm/include/llvm/Support/SystemUtils.h @@ -21,7 +21,7 @@ namespace llvm { /// Determine if the raw_ostream provided is connected to a terminal. If so, /// generate a warning message to errs() advising against display of bitcode /// and return true. Otherwise just return false. -/// @brief Check for output written to a console +/// Check for output written to a console bool CheckBitcodeOutputToConsole( raw_ostream &stream_to_check, ///< The stream to be checked bool print_warning = true ///< Control whether warnings are printed diff --git a/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.def b/contrib/llvm/include/llvm/Support/TargetOpcodes.def index d3e8483798a7..21f5c7e709b8 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetOpcodes.def +++ b/contrib/llvm/include/llvm/Support/TargetOpcodes.def @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/TargetOpcodes.def - Target Indep Opcodes ---*- C++ -*-===// +//===-- llvm/Support/TargetOpcodes.def - Target Indep Opcodes ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -77,6 +77,9 @@ HANDLE_TARGET_OPCODE(SUBREG_TO_REG) /// DBG_VALUE - a mapping of the llvm.dbg.value intrinsic HANDLE_TARGET_OPCODE(DBG_VALUE) +/// DBG_LABEL - a mapping of the llvm.dbg.label intrinsic +HANDLE_TARGET_OPCODE(DBG_LABEL) + /// 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 @@ -183,10 +186,16 @@ HANDLE_TARGET_OPCODE(PATCHABLE_FUNCTION_EXIT) /// PATCHABLE_RET which specifically only works for return instructions. HANDLE_TARGET_OPCODE(PATCHABLE_TAIL_CALL) -/// Wraps a logging call and its arguments with nop sleds. At runtime, this can be -/// patched to insert instrumentation instructions. +/// Wraps a logging call and its arguments with nop sleds. At runtime, this can +/// be patched to insert instrumentation instructions. HANDLE_TARGET_OPCODE(PATCHABLE_EVENT_CALL) +/// Wraps a typed logging call and its argument with nop sleds. At runtime, this +/// can be patched to insert instrumentation instructions. +HANDLE_TARGET_OPCODE(PATCHABLE_TYPED_EVENT_CALL) + +HANDLE_TARGET_OPCODE(ICALL_BRANCH_FUNNEL) + /// The following generic opcodes are not supposed to appear after ISel. /// This is something we might want to relax, but for now, this is convenient /// to produce diagnostics. @@ -259,9 +268,15 @@ HANDLE_TARGET_OPCODE(G_INTTOPTR) /// COPY is the relevant instruction. HANDLE_TARGET_OPCODE(G_BITCAST) -/// Generic load. +/// Generic load (including anyext load) HANDLE_TARGET_OPCODE(G_LOAD) +/// Generic signext load +HANDLE_TARGET_OPCODE(G_SEXTLOAD) + +/// Generic zeroext load +HANDLE_TARGET_OPCODE(G_ZEXTLOAD) + /// Generic store. HANDLE_TARGET_OPCODE(G_STORE) @@ -427,6 +442,9 @@ HANDLE_TARGET_OPCODE(G_SITOFP) /// Generic unsigned-int to float conversion HANDLE_TARGET_OPCODE(G_UITOFP) +/// Generic FP absolute value. +HANDLE_TARGET_OPCODE(G_FABS) + /// Generic pointer offset HANDLE_TARGET_OPCODE(G_GEP) @@ -449,12 +467,15 @@ HANDLE_TARGET_OPCODE(G_SHUFFLE_VECTOR) /// Generic byte swap. HANDLE_TARGET_OPCODE(G_BSWAP) +/// Generic AddressSpaceCast. +HANDLE_TARGET_OPCODE(G_ADDRSPACE_CAST) + // TODO: Add more generic opcodes as we move along. /// Marker for the end of the generic opcode. /// This is used to check if an opcode is in the range of the /// generic opcodes. -HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_BSWAP) +HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_ADDRSPACE_CAST) /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific post-isel opcode values start here. diff --git a/contrib/llvm/include/llvm/Support/TargetParser.h b/contrib/llvm/include/llvm/Support/TargetParser.h index 13b7befb8ce4..08ad42dda3eb 100644 --- a/contrib/llvm/include/llvm/Support/TargetParser.h +++ b/contrib/llvm/include/llvm/Support/TargetParser.h @@ -86,6 +86,8 @@ enum ArchExtKind : unsigned { AEK_RAS = 1 << 12, AEK_SVE = 1 << 13, AEK_DOTPROD = 1 << 14, + AEK_SHA2 = 1 << 15, + AEK_AES = 1 << 16, // Unsupported extensions. AEK_OS = 0x8000000, AEK_IWMMXT = 0x10000000, @@ -137,6 +139,7 @@ unsigned parseFPU(StringRef FPU); ArchKind parseArch(StringRef Arch); unsigned parseArchExt(StringRef ArchExt); ArchKind parseCPUArch(StringRef CPU); +void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values); ISAKind parseArchISA(StringRef Arch); EndianKind parseArchEndian(StringRef Arch); ProfileKind parseArchProfile(StringRef Arch); @@ -170,7 +173,11 @@ enum ArchExtKind : unsigned { AEK_SVE = 1 << 9, AEK_DOTPROD = 1 << 10, AEK_RCPC = 1 << 11, - AEK_RDM = 1 << 12 + AEK_RDM = 1 << 12, + AEK_SM4 = 1 << 13, + AEK_SHA3 = 1 << 14, + AEK_SHA2 = 1 << 15, + AEK_AES = 1 << 16, }; StringRef getCanonicalArchName(StringRef Arch); @@ -199,17 +206,21 @@ unsigned checkArchVersion(StringRef Arch); unsigned getDefaultFPU(StringRef CPU, ArchKind AK); unsigned getDefaultExtensions(StringRef CPU, ArchKind AK); StringRef getDefaultCPU(StringRef Arch); +AArch64::ArchKind getCPUArchKind(StringRef CPU); // Parser unsigned parseFPU(StringRef FPU); AArch64::ArchKind parseArch(StringRef Arch); -unsigned parseArchExt(StringRef ArchExt); +ArchExtKind parseArchExt(StringRef ArchExt); ArchKind parseCPUArch(StringRef CPU); +void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values); ARM::ISAKind parseArchISA(StringRef Arch); ARM::EndianKind parseArchEndian(StringRef Arch); ARM::ProfileKind parseArchProfile(StringRef Arch); unsigned parseArchVersion(StringRef Arch); +bool isX18ReservedByDefault(const Triple &TT); + } // namespace AArch64 namespace X86 { diff --git a/contrib/llvm/include/llvm/Support/TargetRegistry.h b/contrib/llvm/include/llvm/Support/TargetRegistry.h index 8a429ab728ed..1bafc4e687da 100644 --- a/contrib/llvm/include/llvm/Support/TargetRegistry.h +++ b/contrib/llvm/include/llvm/Support/TargetRegistry.h @@ -19,7 +19,7 @@ #ifndef LLVM_SUPPORT_TARGETREGISTRY_H #define LLVM_SUPPORT_TARGETREGISTRY_H -#include "llvm-c/Disassembler.h" +#include "llvm-c/DisassemblerTypes.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" @@ -46,6 +46,7 @@ class MCDisassembler; class MCInstPrinter; class MCInstrAnalysis; class MCInstrInfo; +class MCObjectWriter; class MCRegisterInfo; class MCRelocationInfo; class MCStreamer; @@ -60,27 +61,44 @@ class TargetMachine; class TargetOptions; MCStreamer *createNullStreamer(MCContext &Ctx); -MCStreamer *createAsmStreamer(MCContext &Ctx, - std::unique_ptr<formatted_raw_ostream> OS, - bool isVerboseAsm, bool useDwarfDirectory, - MCInstPrinter *InstPrint, MCCodeEmitter *CE, - MCAsmBackend *TAB, bool ShowInst); +// Takes ownership of \p TAB and \p CE. + +/// Create a machine code streamer which will print out assembly for the native +/// target, suitable for compiling with a native assembler. +/// +/// \param InstPrint - If given, the instruction printer to use. If not given +/// the MCInst representation will be printed. This method takes ownership of +/// InstPrint. +/// +/// \param CE - If given, a code emitter to use to show the instruction +/// encoding inline with the assembly. This method takes ownership of \p CE. +/// +/// \param TAB - If given, a target asm backend to use to show the fixup +/// information in conjunction with encoding information. This method takes +/// ownership of \p TAB. +/// +/// \param ShowInst - Whether to show the MCInst representation inline with +/// the assembly. +MCStreamer * +createAsmStreamer(MCContext &Ctx, std::unique_ptr<formatted_raw_ostream> OS, + bool isVerboseAsm, bool useDwarfDirectory, + MCInstPrinter *InstPrint, std::unique_ptr<MCCodeEmitter> &&CE, + std::unique_ptr<MCAsmBackend> &&TAB, bool ShowInst); -/// Takes ownership of \p TAB and \p CE. MCStreamer *createELFStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&CE, bool RelaxAll); MCStreamer *createMachOStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&CE, bool RelaxAll, bool DWARFMustBeAtTheEnd, bool LabelSections = false); MCStreamer *createWasmStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&CE, bool RelaxAll); @@ -143,22 +161,22 @@ public: using ELFStreamerCtorTy = MCStreamer *(*)(const Triple &T, MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll); using MachOStreamerCtorTy = MCStreamer *(*)(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll, bool DWARFMustBeAtTheEnd); using COFFStreamerCtorTy = MCStreamer *(*)(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll, bool IncrementalLinkerCompatible); using WasmStreamerCtorTy = MCStreamer *(*)(const Triple &T, MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll); using NullTargetStreamerCtorTy = MCTargetStreamer *(*)(MCStreamer &S); using AsmTargetStreamerCtorTy = MCTargetStreamer *(*)( @@ -441,12 +459,12 @@ public: /// \param T The target triple. /// \param Ctx The target context. /// \param TAB The target assembler backend object. Takes ownership. - /// \param OS The stream object. + /// \param OW The stream object. /// \param Emitter The target independent assembler object.Takes ownership. /// \param RelaxAll Relax all fixups? MCStreamer *createMCObjectStreamer(const Triple &T, MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&Emitter, const MCSubtargetInfo &STI, bool RelaxAll, bool IncrementalLinkerCompatible, @@ -457,32 +475,35 @@ public: llvm_unreachable("Unknown object format"); case Triple::COFF: assert(T.isOSWindows() && "only Windows COFF is supported"); - S = COFFStreamerCtorFn(Ctx, std::move(TAB), OS, std::move(Emitter), - RelaxAll, IncrementalLinkerCompatible); + S = COFFStreamerCtorFn(Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll, + IncrementalLinkerCompatible); break; case Triple::MachO: if (MachOStreamerCtorFn) - S = MachOStreamerCtorFn(Ctx, std::move(TAB), OS, std::move(Emitter), - RelaxAll, DWARFMustBeAtTheEnd); + S = MachOStreamerCtorFn(Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll, + DWARFMustBeAtTheEnd); else - S = createMachOStreamer(Ctx, std::move(TAB), OS, std::move(Emitter), - RelaxAll, DWARFMustBeAtTheEnd); + S = createMachOStreamer(Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll, + DWARFMustBeAtTheEnd); break; case Triple::ELF: if (ELFStreamerCtorFn) - S = ELFStreamerCtorFn(T, Ctx, std::move(TAB), OS, std::move(Emitter), - RelaxAll); + S = ELFStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll); else - S = createELFStreamer(Ctx, std::move(TAB), OS, std::move(Emitter), - RelaxAll); + S = createELFStreamer(Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll); break; case Triple::Wasm: if (WasmStreamerCtorFn) - S = WasmStreamerCtorFn(T, Ctx, std::move(TAB), OS, std::move(Emitter), - RelaxAll); + S = WasmStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll); else - S = createWasmStreamer(Ctx, std::move(TAB), OS, std::move(Emitter), - RelaxAll); + S = createWasmStreamer(Ctx, std::move(TAB), std::move(OW), + std::move(Emitter), RelaxAll); break; } if (ObjectTargetStreamerCtorFn) @@ -493,12 +514,14 @@ public: MCStreamer *createAsmStreamer(MCContext &Ctx, std::unique_ptr<formatted_raw_ostream> OS, bool IsVerboseAsm, bool UseDwarfDirectory, - MCInstPrinter *InstPrint, MCCodeEmitter *CE, - MCAsmBackend *TAB, bool ShowInst) const { + MCInstPrinter *InstPrint, + std::unique_ptr<MCCodeEmitter> &&CE, + std::unique_ptr<MCAsmBackend> &&TAB, + bool ShowInst) const { formatted_raw_ostream &OSRef = *OS; - MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IsVerboseAsm, - UseDwarfDirectory, InstPrint, CE, - TAB, ShowInst); + MCStreamer *S = llvm::createAsmStreamer( + Ctx, std::move(OS), IsVerboseAsm, UseDwarfDirectory, InstPrint, + std::move(CE), std::move(TAB), ShowInst); createAsmTargetStreamer(*S, OSRef, InstPrint, IsVerboseAsm); return S; } diff --git a/contrib/llvm/include/llvm/Support/TaskQueue.h b/contrib/llvm/include/llvm/Support/TaskQueue.h new file mode 100644 index 000000000000..49981adb763d --- /dev/null +++ b/contrib/llvm/include/llvm/Support/TaskQueue.h @@ -0,0 +1,139 @@ +//===-- llvm/Support/TaskQueue.h - A TaskQueue 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 defines a crude C++11 based task queue. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TASK_QUEUE_H +#define LLVM_SUPPORT_TASK_QUEUE_H + +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/ThreadPool.h" +#include "llvm/Support/thread.h" + +#include <atomic> +#include <cassert> +#include <condition_variable> +#include <deque> +#include <functional> +#include <future> +#include <memory> +#include <mutex> +#include <utility> + +namespace llvm { +/// TaskQueue executes serialized work on a user-defined Thread Pool. It +/// guarantees that if task B is enqueued after task A, task B begins after +/// task A completes and there is no overlap between the two. +class TaskQueue { + // Because we don't have init capture to use move-only local variables that + // are captured into a lambda, we create the promise inside an explicit + // callable struct. We want to do as much of the wrapping in the + // type-specialized domain (before type erasure) and then erase this into a + // std::function. + template <typename Callable> struct Task { + using ResultTy = typename std::result_of<Callable()>::type; + explicit Task(Callable C, TaskQueue &Parent) + : C(std::move(C)), P(std::make_shared<std::promise<ResultTy>>()), + Parent(&Parent) {} + + template<typename T> + void invokeCallbackAndSetPromise(T*) { + P->set_value(C()); + } + + void invokeCallbackAndSetPromise(void*) { + C(); + P->set_value(); + } + + void operator()() noexcept { + ResultTy *Dummy = nullptr; + invokeCallbackAndSetPromise(Dummy); + Parent->completeTask(); + } + + Callable C; + std::shared_ptr<std::promise<ResultTy>> P; + TaskQueue *Parent; + }; + +public: + /// Construct a task queue with no work. + TaskQueue(ThreadPool &Scheduler) : Scheduler(Scheduler) { (void)Scheduler; } + + /// Blocking destructor: the queue will wait for all work to complete. + ~TaskQueue() { + Scheduler.wait(); + assert(Tasks.empty()); + } + + /// Asynchronous submission of a task to the queue. The returned future can be + /// used to wait for the task (and all previous tasks that have not yet + /// completed) to finish. + template <typename Callable> + std::future<typename std::result_of<Callable()>::type> async(Callable &&C) { +#if !LLVM_ENABLE_THREADS + static_assert(false, + "TaskQueue requires building with LLVM_ENABLE_THREADS!"); +#endif + Task<Callable> T{std::move(C), *this}; + using ResultTy = typename std::result_of<Callable()>::type; + std::future<ResultTy> F = T.P->get_future(); + { + std::lock_guard<std::mutex> Lock(QueueLock); + // If there's already a task in flight, just queue this one up. If + // there is not a task in flight, bypass the queue and schedule this + // task immediately. + if (IsTaskInFlight) + Tasks.push_back(std::move(T)); + else { + Scheduler.async(std::move(T)); + IsTaskInFlight = true; + } + } + return std::move(F); + } + +private: + void completeTask() { + // We just completed a task. If there are no more tasks in the queue, + // update IsTaskInFlight to false and stop doing work. Otherwise + // schedule the next task (while not holding the lock). + std::function<void()> Continuation; + { + std::lock_guard<std::mutex> Lock(QueueLock); + if (Tasks.empty()) { + IsTaskInFlight = false; + return; + } + + Continuation = std::move(Tasks.front()); + Tasks.pop_front(); + } + Scheduler.async(std::move(Continuation)); + } + + /// The thread pool on which to run the work. + ThreadPool &Scheduler; + + /// State which indicates whether the queue currently is currently processing + /// any work. + bool IsTaskInFlight = false; + + /// Mutex for synchronizing access to the Tasks array. + std::mutex QueueLock; + + /// Tasks waiting for execution in the queue. + std::deque<std::function<void()>> Tasks; +}; +} // namespace llvm + +#endif // LLVM_SUPPORT_TASK_QUEUE_H diff --git a/contrib/llvm/include/llvm/Support/ThreadLocal.h b/contrib/llvm/include/llvm/Support/ThreadLocal.h index 427a67e2a96d..885bd18e8356 100644 --- a/contrib/llvm/include/llvm/Support/ThreadLocal.h +++ b/contrib/llvm/include/llvm/Support/ThreadLocal.h @@ -24,7 +24,7 @@ namespace llvm { // YOU SHOULD NEVER USE THIS DIRECTLY. class ThreadLocalImpl { typedef uint64_t ThreadLocalDataTy; - /// \brief Platform-specific thread local data. + /// Platform-specific thread local data. /// /// This is embedded in the class and we avoid malloc'ing/free'ing it, /// to make this class more safe for use along with CrashRecoveryContext. diff --git a/contrib/llvm/include/llvm/Support/ThreadPool.h b/contrib/llvm/include/llvm/Support/ThreadPool.h index fb8255900510..4fdbd528b212 100644 --- a/contrib/llvm/include/llvm/Support/ThreadPool.h +++ b/contrib/llvm/include/llvm/Support/ThreadPool.h @@ -14,6 +14,7 @@ #ifndef LLVM_SUPPORT_THREAD_POOL_H #define LLVM_SUPPORT_THREAD_POOL_H +#include "llvm/Config/llvm-config.h" #include "llvm/Support/thread.h" #include <future> diff --git a/contrib/llvm/include/llvm/Support/Threading.h b/contrib/llvm/include/llvm/Support/Threading.h index 6d813bccb93f..e8021f648b0d 100644 --- a/contrib/llvm/include/llvm/Support/Threading.h +++ b/contrib/llvm/include/llvm/Support/Threading.h @@ -72,7 +72,7 @@ void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData, enum InitStatus { Uninitialized = 0, Wait = 1, Done = 2 }; - /// \brief The llvm::once_flag structure + /// The llvm::once_flag structure /// /// This type is modeled after std::once_flag to use with llvm::call_once. /// This structure must be used as an opaque object. It is a struct to force @@ -83,7 +83,7 @@ void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData, #endif - /// \brief Execute the function specified as a parameter once. + /// Execute the function specified as a parameter once. /// /// Typical usage: /// \code @@ -139,17 +139,17 @@ void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData, /// not available. unsigned hardware_concurrency(); - /// \brief Return the current thread id, as used in various OS system calls. + /// Return the current thread id, as used in various OS system calls. /// Note that not all platforms guarantee that the value returned will be /// unique across the entire system, so portable code should not assume /// this. uint64_t get_threadid(); - /// \brief Get the maximum length of a thread name on this platform. + /// Get the maximum length of a thread name on this platform. /// A value of 0 means there is no limit. uint32_t get_max_thread_name_length(); - /// \brief Set the name of the current thread. Setting a thread's name can + /// Set the name of the current thread. Setting a thread's name can /// be helpful for enabling useful diagnostics under a debugger or when /// logging. The level of support for setting a thread's name varies /// wildly across operating systems, and we only make a best effort to @@ -157,7 +157,7 @@ void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData, /// or failure is returned. void set_thread_name(const Twine &Name); - /// \brief Get the name of the current thread. The level of support for + /// Get the name of the current thread. The level of support for /// getting a thread's name varies wildly across operating systems, and it /// is not even guaranteed that if you can successfully set a thread's name /// that you can later get it back. This function is intended for diagnostic diff --git a/contrib/llvm/include/llvm/Support/Timer.h b/contrib/llvm/include/llvm/Support/Timer.h index 198855ae0377..bfffbc3157b1 100644 --- a/contrib/llvm/include/llvm/Support/Timer.h +++ b/contrib/llvm/include/llvm/Support/Timer.h @@ -10,6 +10,7 @@ #ifndef LLVM_SUPPORT_TIMER_H #define LLVM_SUPPORT_TIMER_H +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include <cassert> @@ -194,6 +195,10 @@ class TimerGroup { public: explicit TimerGroup(StringRef Name, StringRef Description); + + explicit TimerGroup(StringRef Name, StringRef Description, + const StringMap<TimeRecord> &Records); + ~TimerGroup(); void setName(StringRef NewName, StringRef NewDescription) { @@ -207,6 +212,8 @@ public: /// This static method prints all timers and clears them all out. static void printAll(raw_ostream &OS); + const char *printJSONValues(raw_ostream &OS, const char *delim); + /// Prints all timers as JSON key/value pairs, and clears them all out. static const char *printAllJSONValues(raw_ostream &OS, const char *delim); @@ -223,7 +230,6 @@ private: void PrintQueuedTimers(raw_ostream &OS); void printJSONValue(raw_ostream &OS, const PrintRecord &R, const char *suffix, double Value); - const char *printJSONValues(raw_ostream &OS, const char *delim); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Support/ToolOutputFile.h b/contrib/llvm/include/llvm/Support/ToolOutputFile.h index b41ca5a6edaa..cf3bc2fb0171 100644 --- a/contrib/llvm/include/llvm/Support/ToolOutputFile.h +++ b/contrib/llvm/include/llvm/Support/ToolOutputFile.h @@ -35,7 +35,7 @@ class ToolOutputFile { /// The flag which indicates whether we should not delete the file. bool Keep; - explicit CleanupInstaller(StringRef ilename); + explicit CleanupInstaller(StringRef Filename); ~CleanupInstaller(); } Installer; @@ -43,7 +43,7 @@ class ToolOutputFile { raw_fd_ostream OS; public: - /// This constructor's arguments are passed to to raw_fd_ostream's + /// This constructor's arguments are passed to raw_fd_ostream's /// constructor. ToolOutputFile(StringRef Filename, std::error_code &EC, sys::fs::OpenFlags Flags); diff --git a/contrib/llvm/include/llvm/Support/TrailingObjects.h b/contrib/llvm/include/llvm/Support/TrailingObjects.h index cb5a52b0d861..490bd94f4cd5 100644 --- a/contrib/llvm/include/llvm/Support/TrailingObjects.h +++ b/contrib/llvm/include/llvm/Support/TrailingObjects.h @@ -89,25 +89,25 @@ protected: }; /// This helper template works-around MSVC 2013's lack of useful -/// alignas() support. The argument to LLVM_ALIGNAS(), in MSVC, is +/// alignas() support. The argument to alignas(), in MSVC, is /// required to be a literal integer. But, you *can* use template -/// specialization to select between a bunch of different LLVM_ALIGNAS +/// specialization to select between a bunch of different alignas() /// expressions... template <int Align> class TrailingObjectsAligner : public TrailingObjectsBase {}; template <> -class LLVM_ALIGNAS(1) TrailingObjectsAligner<1> : public TrailingObjectsBase {}; +class alignas(1) TrailingObjectsAligner<1> : public TrailingObjectsBase {}; template <> -class LLVM_ALIGNAS(2) TrailingObjectsAligner<2> : public TrailingObjectsBase {}; +class alignas(2) TrailingObjectsAligner<2> : public TrailingObjectsBase {}; template <> -class LLVM_ALIGNAS(4) TrailingObjectsAligner<4> : public TrailingObjectsBase {}; +class alignas(4) TrailingObjectsAligner<4> : public TrailingObjectsBase {}; template <> -class LLVM_ALIGNAS(8) TrailingObjectsAligner<8> : public TrailingObjectsBase {}; +class alignas(8) TrailingObjectsAligner<8> : public TrailingObjectsBase {}; template <> -class LLVM_ALIGNAS(16) TrailingObjectsAligner<16> : public TrailingObjectsBase { +class alignas(16) TrailingObjectsAligner<16> : public TrailingObjectsBase { }; template <> -class LLVM_ALIGNAS(32) TrailingObjectsAligner<32> : public TrailingObjectsBase { +class alignas(32) TrailingObjectsAligner<32> : public TrailingObjectsBase { }; // Just a little helper for transforming a type pack into the same diff --git a/contrib/llvm/include/llvm/Support/Unicode.h b/contrib/llvm/include/llvm/Support/Unicode.h index adedb1ed83a6..983acaf03635 100644 --- a/contrib/llvm/include/llvm/Support/Unicode.h +++ b/contrib/llvm/include/llvm/Support/Unicode.h @@ -60,6 +60,10 @@ bool isPrintable(int UCS); /// * 1 for each of the remaining characters. int columnWidthUTF8(StringRef Text); +/// Fold input unicode character according the Simple unicode case folding +/// rules. +int foldCharSimple(int C); + } // namespace unicode } // namespace sys } // namespace llvm diff --git a/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h b/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h index 4c655833b396..3cf4a6d96602 100644 --- a/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h +++ b/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h @@ -23,7 +23,7 @@ namespace llvm { namespace sys { -/// \brief Represents a closed range of Unicode code points [Lower, Upper]. +/// Represents a closed range of Unicode code points [Lower, Upper]. struct UnicodeCharRange { uint32_t Lower; uint32_t Upper; @@ -36,14 +36,14 @@ inline bool operator<(UnicodeCharRange Range, uint32_t Value) { return Range.Upper < Value; } -/// \brief Holds a reference to an ordered array of UnicodeCharRange and allows +/// Holds a reference to an ordered array of UnicodeCharRange and allows /// to quickly check if a code point is contained in the set represented by this /// array. class UnicodeCharSet { public: typedef ArrayRef<UnicodeCharRange> CharRanges; - /// \brief Constructs a UnicodeCharSet instance from an array of + /// Constructs a UnicodeCharSet instance from an array of /// UnicodeCharRanges. /// /// Array pointed by \p Ranges should have the lifetime at least as long as @@ -63,31 +63,31 @@ public: } #endif - /// \brief Returns true if the character set contains the Unicode code point + /// Returns true if the character set contains the Unicode code point /// \p C. bool contains(uint32_t C) const { return std::binary_search(Ranges.begin(), Ranges.end(), C); } private: - /// \brief Returns true if each of the ranges is a proper closed range + /// Returns true if each of the ranges is a proper closed range /// [min, max], and if the ranges themselves are ordered and non-overlapping. bool rangesAreValid() const { uint32_t Prev = 0; for (CharRanges::const_iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { if (I != Ranges.begin() && Prev >= I->Lower) { - 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"); + LLVM_DEBUG(dbgs() << "Upper bound 0x"); + LLVM_DEBUG(dbgs().write_hex(Prev)); + LLVM_DEBUG(dbgs() << " should be less than succeeding lower bound 0x"); + LLVM_DEBUG(dbgs().write_hex(I->Lower) << "\n"); return false; } if (I->Upper < I->Lower) { - 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"); + LLVM_DEBUG(dbgs() << "Upper bound 0x"); + LLVM_DEBUG(dbgs().write_hex(I->Lower)); + LLVM_DEBUG(dbgs() << " should not be less than lower bound 0x"); + LLVM_DEBUG(dbgs().write_hex(I->Upper) << "\n"); return false; } Prev = I->Upper; diff --git a/contrib/llvm/include/llvm/Support/UniqueLock.h b/contrib/llvm/include/llvm/Support/UniqueLock.h index b4675f4b43ae..91dc911036d5 100644 --- a/contrib/llvm/include/llvm/Support/UniqueLock.h +++ b/contrib/llvm/include/llvm/Support/UniqueLock.h @@ -24,7 +24,7 @@ namespace llvm { /// an associated mutex, which is guaranteed to be locked upon creation /// and unlocked after destruction. unique_lock can also unlock the mutex /// and re-lock it freely during its lifetime. - /// @brief Guard a section of code with a mutex. + /// Guard a section of code with a mutex. template<typename MutexT> class unique_lock { MutexT *M = nullptr; diff --git a/contrib/llvm/include/llvm/Support/VersionTuple.h b/contrib/llvm/include/llvm/Support/VersionTuple.h new file mode 100644 index 000000000000..e85a188e54b4 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/VersionTuple.h @@ -0,0 +1,154 @@ +//===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Defines the llvm::VersionTuple class, which represents a version in +/// the form major[.minor[.subminor]]. +/// +//===----------------------------------------------------------------------===// +#ifndef LLVM_SUPPORT_VERSIONTUPLE_H +#define LLVM_SUPPORT_VERSIONTUPLE_H + +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" +#include <string> +#include <tuple> + +namespace llvm { + +/// Represents a version number in the form major[.minor[.subminor[.build]]]. +class VersionTuple { + unsigned Major : 32; + + unsigned Minor : 31; + unsigned HasMinor : 1; + + unsigned Subminor : 31; + unsigned HasSubminor : 1; + + unsigned Build : 31; + unsigned HasBuild : 1; + +public: + VersionTuple() + : Major(0), Minor(0), HasMinor(false), Subminor(0), HasSubminor(false), + Build(0), HasBuild(false) {} + + explicit VersionTuple(unsigned Major) + : Major(Major), Minor(0), HasMinor(false), Subminor(0), + HasSubminor(false), Build(0), HasBuild(false) {} + + explicit VersionTuple(unsigned Major, unsigned Minor) + : Major(Major), Minor(Minor), HasMinor(true), Subminor(0), + HasSubminor(false), Build(0), HasBuild(false) {} + + explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor) + : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor), + HasSubminor(true), Build(0), HasBuild(false) {} + + explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor, + unsigned Build) + : Major(Major), Minor(Minor), HasMinor(true), Subminor(Subminor), + HasSubminor(true), Build(Build), HasBuild(true) {} + + /// Determine whether this version information is empty + /// (e.g., all version components are zero). + bool empty() const { + return Major == 0 && Minor == 0 && Subminor == 0 && Build == 0; + } + + /// Retrieve the major version number. + unsigned getMajor() const { return Major; } + + /// Retrieve the minor version number, if provided. + Optional<unsigned> getMinor() const { + if (!HasMinor) + return None; + return Minor; + } + + /// Retrieve the subminor version number, if provided. + Optional<unsigned> getSubminor() const { + if (!HasSubminor) + return None; + return Subminor; + } + + /// Retrieve the build version number, if provided. + Optional<unsigned> getBuild() const { + if (!HasBuild) + return None; + return Build; + } + + /// Determine if two version numbers are equivalent. If not + /// provided, minor and subminor version numbers are considered to be zero. + friend bool operator==(const VersionTuple &X, const VersionTuple &Y) { + return X.Major == Y.Major && X.Minor == Y.Minor && + X.Subminor == Y.Subminor && X.Build == Y.Build; + } + + /// Determine if two version numbers are not equivalent. + /// + /// If not provided, minor and subminor version numbers are considered to be + /// zero. + friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) { + return !(X == Y); + } + + /// Determine whether one version number precedes another. + /// + /// If not provided, minor and subminor version numbers are considered to be + /// zero. + friend bool operator<(const VersionTuple &X, const VersionTuple &Y) { + return std::tie(X.Major, X.Minor, X.Subminor, X.Build) < + std::tie(Y.Major, Y.Minor, Y.Subminor, Y.Build); + } + + /// Determine whether one version number follows another. + /// + /// If not provided, minor and subminor version numbers are considered to be + /// zero. + friend bool operator>(const VersionTuple &X, const VersionTuple &Y) { + return Y < X; + } + + /// Determine whether one version number precedes or is + /// equivalent to another. + /// + /// If not provided, minor and subminor version numbers are considered to be + /// zero. + friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) { + return !(Y < X); + } + + /// Determine whether one version number follows or is + /// equivalent to another. + /// + /// If not provided, minor and subminor version numbers are considered to be + /// zero. + friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) { + return !(X < Y); + } + + /// Retrieve a string representation of the version number. + std::string getAsString() const; + + /// Try to parse the given string as a version number. + /// \returns \c true if the string does not match the regular expression + /// [0-9]+(\.[0-9]+){0,3} + bool tryParse(StringRef string); +}; + +/// Print a version number. +raw_ostream &operator<<(raw_ostream &Out, const VersionTuple &V); + +} // end namespace llvm +#endif // LLVM_SUPPORT_VERSIONTUPLE_H diff --git a/contrib/llvm/include/llvm/Support/Win64EH.h b/contrib/llvm/include/llvm/Support/Win64EH.h index f6c492794875..928eb906de0c 100644 --- a/contrib/llvm/include/llvm/Support/Win64EH.h +++ b/contrib/llvm/include/llvm/Support/Win64EH.h @@ -101,40 +101,40 @@ struct UnwindInfo { // For more information please see MSDN at: // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx - /// \brief Return pointer to language specific data part of UnwindInfo. + /// Return pointer to language specific data part of UnwindInfo. void *getLanguageSpecificData() { return reinterpret_cast<void *>(&UnwindCodes[(NumCodes+1) & ~1]); } - /// \brief Return pointer to language specific data part of UnwindInfo. + /// Return pointer to language specific data part of UnwindInfo. const void *getLanguageSpecificData() const { return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes + 1) & ~1]); } - /// \brief Return image-relative offset of language-specific exception handler. + /// Return image-relative offset of language-specific exception handler. uint32_t getLanguageSpecificHandlerOffset() const { return *reinterpret_cast<const support::ulittle32_t *>( getLanguageSpecificData()); } - /// \brief Set image-relative offset of language-specific exception handler. + /// Set image-relative offset of language-specific exception handler. void setLanguageSpecificHandlerOffset(uint32_t offset) { *reinterpret_cast<support::ulittle32_t *>(getLanguageSpecificData()) = offset; } - /// \brief Return pointer to exception-specific data. + /// Return pointer to exception-specific data. void *getExceptionData() { return reinterpret_cast<void *>(reinterpret_cast<uint32_t *>( getLanguageSpecificData())+1); } - /// \brief Return pointer to chained unwind info. + /// Return pointer to chained unwind info. RuntimeFunction *getChainedFunctionEntry() { return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData()); } - /// \brief Return pointer to chained unwind info. + /// Return pointer to chained unwind info. const RuntimeFunction *getChainedFunctionEntry() const { return reinterpret_cast<const RuntimeFunction *>(getLanguageSpecificData()); } diff --git a/contrib/llvm/include/llvm/Support/WithColor.h b/contrib/llvm/include/llvm/Support/WithColor.h new file mode 100644 index 000000000000..85fc5fa0cf14 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/WithColor.h @@ -0,0 +1,67 @@ +//===- WithColor.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WITHCOLOR_H +#define LLVM_SUPPORT_WITHCOLOR_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/CommandLine.h" + +namespace llvm { + +extern cl::OptionCategory ColorCategory; + +class raw_ostream; + +// Symbolic names for various syntax elements. +enum class HighlightColor { + Address, + String, + Tag, + Attribute, + Enumerator, + Macro, + Error, + Warning, + Note +}; + +/// An RAII object that temporarily switches an output stream to a specific +/// color. +class WithColor { + raw_ostream &OS; + /// Determine whether colors should be displayed. + bool colorsEnabled(raw_ostream &OS); + +public: + /// To be used like this: WithColor(OS, HighlightColor::String) << "text"; + WithColor(raw_ostream &OS, HighlightColor S); + ~WithColor(); + + raw_ostream &get() { return OS; } + operator raw_ostream &() { return OS; } + + /// Convenience method for printing "error: " to stderr. + static raw_ostream &error(); + /// Convenience method for printing "warning: " to stderr. + static raw_ostream &warning(); + /// Convenience method for printing "note: " to stderr. + static raw_ostream ¬e(); + + /// Convenience method for printing "error: " to the given stream. + static raw_ostream &error(raw_ostream &OS, StringRef Prefix = ""); + /// Convenience method for printing "warning: " to the given stream. + static raw_ostream &warning(raw_ostream &OS, StringRef Prefix = ""); + /// Convenience method for printing "note: " to the given stream. + static raw_ostream ¬e(raw_ostream &OS, StringRef Prefix = ""); +}; + +} // end namespace llvm + +#endif // LLVM_LIB_DEBUGINFO_WITHCOLOR_H diff --git a/contrib/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h b/contrib/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h new file mode 100644 index 000000000000..185b357efef5 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h @@ -0,0 +1,475 @@ +//===-- X86DisassemblerDecoderCommon.h - Disassembler decoder ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is part of the X86 Disassembler. +// It contains common definitions used by both the disassembler and the table +// generator. +// Documentation for the disassembler can be found in X86Disassembler.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_X86_DISASSEMBLER_X86DISASSEMBLERDECODERCOMMON_H +#define LLVM_LIB_TARGET_X86_DISASSEMBLER_X86DISASSEMBLERDECODERCOMMON_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { +namespace X86Disassembler { + +#define INSTRUCTIONS_SYM x86DisassemblerInstrSpecifiers +#define CONTEXTS_SYM x86DisassemblerContexts +#define ONEBYTE_SYM x86DisassemblerOneByteOpcodes +#define TWOBYTE_SYM x86DisassemblerTwoByteOpcodes +#define THREEBYTE38_SYM x86DisassemblerThreeByte38Opcodes +#define THREEBYTE3A_SYM x86DisassemblerThreeByte3AOpcodes +#define XOP8_MAP_SYM x86DisassemblerXOP8Opcodes +#define XOP9_MAP_SYM x86DisassemblerXOP9Opcodes +#define XOPA_MAP_SYM x86DisassemblerXOPAOpcodes +#define THREEDNOW_MAP_SYM x86Disassembler3DNowOpcodes + +#define INSTRUCTIONS_STR "x86DisassemblerInstrSpecifiers" +#define CONTEXTS_STR "x86DisassemblerContexts" +#define ONEBYTE_STR "x86DisassemblerOneByteOpcodes" +#define TWOBYTE_STR "x86DisassemblerTwoByteOpcodes" +#define THREEBYTE38_STR "x86DisassemblerThreeByte38Opcodes" +#define THREEBYTE3A_STR "x86DisassemblerThreeByte3AOpcodes" +#define XOP8_MAP_STR "x86DisassemblerXOP8Opcodes" +#define XOP9_MAP_STR "x86DisassemblerXOP9Opcodes" +#define XOPA_MAP_STR "x86DisassemblerXOPAOpcodes" +#define THREEDNOW_MAP_STR "x86Disassembler3DNowOpcodes" + +// Attributes of an instruction that must be known before the opcode can be +// processed correctly. Most of these indicate the presence of particular +// prefixes, but ATTR_64BIT is simply an attribute of the decoding context. +#define ATTRIBUTE_BITS \ + ENUM_ENTRY(ATTR_NONE, 0x00) \ + ENUM_ENTRY(ATTR_64BIT, (0x1 << 0)) \ + ENUM_ENTRY(ATTR_XS, (0x1 << 1)) \ + ENUM_ENTRY(ATTR_XD, (0x1 << 2)) \ + ENUM_ENTRY(ATTR_REXW, (0x1 << 3)) \ + ENUM_ENTRY(ATTR_OPSIZE, (0x1 << 4)) \ + ENUM_ENTRY(ATTR_ADSIZE, (0x1 << 5)) \ + ENUM_ENTRY(ATTR_VEX, (0x1 << 6)) \ + ENUM_ENTRY(ATTR_VEXL, (0x1 << 7)) \ + ENUM_ENTRY(ATTR_EVEX, (0x1 << 8)) \ + ENUM_ENTRY(ATTR_EVEXL, (0x1 << 9)) \ + ENUM_ENTRY(ATTR_EVEXL2, (0x1 << 10)) \ + ENUM_ENTRY(ATTR_EVEXK, (0x1 << 11)) \ + ENUM_ENTRY(ATTR_EVEXKZ, (0x1 << 12)) \ + ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13)) + +#define ENUM_ENTRY(n, v) n = v, +enum attributeBits { + ATTRIBUTE_BITS + ATTR_max +}; +#undef ENUM_ENTRY + +// Combinations of the above attributes that are relevant to instruction +// decode. Although other combinations are possible, they can be reduced to +// these without affecting the ultimately decoded instruction. + +// Class name Rank Rationale for rank assignment +#define INSTRUCTION_CONTEXTS \ + ENUM_ENTRY(IC, 0, "says nothing about the instruction") \ + ENUM_ENTRY(IC_64BIT, 1, "says the instruction applies in " \ + "64-bit mode but no more") \ + ENUM_ENTRY(IC_OPSIZE, 3, "requires an OPSIZE prefix, so " \ + "operands change width") \ + ENUM_ENTRY(IC_ADSIZE, 3, "requires an ADSIZE prefix, so " \ + "operands change width") \ + ENUM_ENTRY(IC_OPSIZE_ADSIZE, 4, "requires ADSIZE and OPSIZE prefixes") \ + ENUM_ENTRY(IC_XD, 2, "may say something about the opcode " \ + "but not the operands") \ + ENUM_ENTRY(IC_XS, 2, "may say something about the opcode " \ + "but not the operands") \ + ENUM_ENTRY(IC_XD_OPSIZE, 3, "requires an OPSIZE prefix, so " \ + "operands change width") \ + ENUM_ENTRY(IC_XS_OPSIZE, 3, "requires an OPSIZE prefix, so " \ + "operands change width") \ + ENUM_ENTRY(IC_XD_ADSIZE, 3, "requires an ADSIZE prefix, so " \ + "operands change width") \ + ENUM_ENTRY(IC_XS_ADSIZE, 3, "requires an ADSIZE prefix, so " \ + "operands change width") \ + ENUM_ENTRY(IC_64BIT_REXW, 5, "requires a REX.W prefix, so operands "\ + "change width; overrides IC_OPSIZE") \ + ENUM_ENTRY(IC_64BIT_REXW_ADSIZE, 6, "requires a REX.W prefix and 0x67 " \ + "prefix") \ + ENUM_ENTRY(IC_64BIT_OPSIZE, 3, "Just as meaningful as IC_OPSIZE") \ + ENUM_ENTRY(IC_64BIT_ADSIZE, 3, "Just as meaningful as IC_ADSIZE") \ + ENUM_ENTRY(IC_64BIT_OPSIZE_ADSIZE, 4, "Just as meaningful as IC_OPSIZE/" \ + "IC_ADSIZE") \ + ENUM_ENTRY(IC_64BIT_XD, 6, "XD instructions are SSE; REX.W is " \ + "secondary") \ + ENUM_ENTRY(IC_64BIT_XS, 6, "Just as meaningful as IC_64BIT_XD") \ + ENUM_ENTRY(IC_64BIT_XD_OPSIZE, 3, "Just as meaningful as IC_XD_OPSIZE") \ + ENUM_ENTRY(IC_64BIT_XS_OPSIZE, 3, "Just as meaningful as IC_XS_OPSIZE") \ + ENUM_ENTRY(IC_64BIT_XD_ADSIZE, 3, "Just as meaningful as IC_XD_ADSIZE") \ + ENUM_ENTRY(IC_64BIT_XS_ADSIZE, 3, "Just as meaningful as IC_XS_ADSIZE") \ + ENUM_ENTRY(IC_64BIT_REXW_XS, 7, "OPSIZE could mean a different " \ + "opcode") \ + ENUM_ENTRY(IC_64BIT_REXW_XD, 7, "Just as meaningful as " \ + "IC_64BIT_REXW_XS") \ + ENUM_ENTRY(IC_64BIT_REXW_OPSIZE, 8, "The Dynamic Duo! Prefer over all " \ + "else because this changes most " \ + "operands' meaning") \ + ENUM_ENTRY(IC_VEX, 1, "requires a VEX prefix") \ + ENUM_ENTRY(IC_VEX_XS, 2, "requires VEX and the XS prefix") \ + ENUM_ENTRY(IC_VEX_XD, 2, "requires VEX and the XD prefix") \ + ENUM_ENTRY(IC_VEX_OPSIZE, 2, "requires VEX and the OpSize prefix") \ + ENUM_ENTRY(IC_VEX_W, 3, "requires VEX and the W prefix") \ + ENUM_ENTRY(IC_VEX_W_XS, 4, "requires VEX, W, and XS prefix") \ + ENUM_ENTRY(IC_VEX_W_XD, 4, "requires VEX, W, and XD prefix") \ + ENUM_ENTRY(IC_VEX_W_OPSIZE, 4, "requires VEX, W, and OpSize") \ + ENUM_ENTRY(IC_VEX_L, 3, "requires VEX and the L prefix") \ + ENUM_ENTRY(IC_VEX_L_XS, 4, "requires VEX and the L and XS prefix")\ + ENUM_ENTRY(IC_VEX_L_XD, 4, "requires VEX and the L and XD prefix")\ + ENUM_ENTRY(IC_VEX_L_OPSIZE, 4, "requires VEX, L, and OpSize") \ + ENUM_ENTRY(IC_VEX_L_W, 4, "requires VEX, L and W") \ + ENUM_ENTRY(IC_VEX_L_W_XS, 5, "requires VEX, L, W and XS prefix") \ + ENUM_ENTRY(IC_VEX_L_W_XD, 5, "requires VEX, L, W and XD prefix") \ + ENUM_ENTRY(IC_VEX_L_W_OPSIZE, 5, "requires VEX, L, W and OpSize") \ + ENUM_ENTRY(IC_EVEX, 1, "requires an EVEX prefix") \ + ENUM_ENTRY(IC_EVEX_XS, 2, "requires EVEX and the XS prefix") \ + ENUM_ENTRY(IC_EVEX_XD, 2, "requires EVEX and the XD prefix") \ + ENUM_ENTRY(IC_EVEX_OPSIZE, 2, "requires EVEX and the OpSize prefix") \ + ENUM_ENTRY(IC_EVEX_W, 3, "requires EVEX and the W prefix") \ + ENUM_ENTRY(IC_EVEX_W_XS, 4, "requires EVEX, W, and XS prefix") \ + ENUM_ENTRY(IC_EVEX_W_XD, 4, "requires EVEX, W, and XD prefix") \ + ENUM_ENTRY(IC_EVEX_W_OPSIZE, 4, "requires EVEX, W, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L, 3, "requires EVEX and the L prefix") \ + ENUM_ENTRY(IC_EVEX_L_XS, 4, "requires EVEX and the L and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L_XD, 4, "requires EVEX and the L and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L_OPSIZE, 4, "requires EVEX, L, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_W, 3, "requires EVEX, L and W") \ + ENUM_ENTRY(IC_EVEX_L_W_XS, 4, "requires EVEX, L, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_XD, 4, "requires EVEX, L, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_OPSIZE, 4, "requires EVEX, L, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2, 3, "requires EVEX and the L2 prefix") \ + ENUM_ENTRY(IC_EVEX_L2_XS, 4, "requires EVEX and the L2 and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L2_XD, 4, "requires EVEX and the L2 and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L2_OPSIZE, 4, "requires EVEX, L2, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_W, 3, "requires EVEX, L2 and W") \ + ENUM_ENTRY(IC_EVEX_L2_W_XS, 4, "requires EVEX, L2, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_XD, 4, "requires EVEX, L2, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE, 4, "requires EVEX, L2, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_K, 1, "requires an EVEX_K prefix") \ + ENUM_ENTRY(IC_EVEX_XS_K, 2, "requires EVEX_K and the XS prefix") \ + ENUM_ENTRY(IC_EVEX_XD_K, 2, "requires EVEX_K and the XD prefix") \ + ENUM_ENTRY(IC_EVEX_OPSIZE_K, 2, "requires EVEX_K and the OpSize prefix") \ + ENUM_ENTRY(IC_EVEX_W_K, 3, "requires EVEX_K and the W prefix") \ + ENUM_ENTRY(IC_EVEX_W_XS_K, 4, "requires EVEX_K, W, and XS prefix") \ + ENUM_ENTRY(IC_EVEX_W_XD_K, 4, "requires EVEX_K, W, and XD prefix") \ + ENUM_ENTRY(IC_EVEX_W_OPSIZE_K, 4, "requires EVEX_K, W, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_K, 3, "requires EVEX_K and the L prefix") \ + ENUM_ENTRY(IC_EVEX_L_XS_K, 4, "requires EVEX_K and the L and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L_XD_K, 4, "requires EVEX_K and the L and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L_OPSIZE_K, 4, "requires EVEX_K, L, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_W_K, 3, "requires EVEX_K, L and W") \ + ENUM_ENTRY(IC_EVEX_L_W_XS_K, 4, "requires EVEX_K, L, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_XD_K, 4, "requires EVEX_K, L, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_K, 4, "requires EVEX_K, L, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_K, 3, "requires EVEX_K and the L2 prefix") \ + ENUM_ENTRY(IC_EVEX_L2_XS_K, 4, "requires EVEX_K and the L2 and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L2_XD_K, 4, "requires EVEX_K and the L2 and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L2_OPSIZE_K, 4, "requires EVEX_K, L2, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_W_K, 3, "requires EVEX_K, L2 and W") \ + ENUM_ENTRY(IC_EVEX_L2_W_XS_K, 4, "requires EVEX_K, L2, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_XD_K, 4, "requires EVEX_K, L2, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_K, 4, "requires EVEX_K, L2, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_B, 1, "requires an EVEX_B prefix") \ + ENUM_ENTRY(IC_EVEX_XS_B, 2, "requires EVEX_B and the XS prefix") \ + ENUM_ENTRY(IC_EVEX_XD_B, 2, "requires EVEX_B and the XD prefix") \ + ENUM_ENTRY(IC_EVEX_OPSIZE_B, 2, "requires EVEX_B and the OpSize prefix") \ + ENUM_ENTRY(IC_EVEX_W_B, 3, "requires EVEX_B and the W prefix") \ + ENUM_ENTRY(IC_EVEX_W_XS_B, 4, "requires EVEX_B, W, and XS prefix") \ + ENUM_ENTRY(IC_EVEX_W_XD_B, 4, "requires EVEX_B, W, and XD prefix") \ + ENUM_ENTRY(IC_EVEX_W_OPSIZE_B, 4, "requires EVEX_B, W, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_B, 3, "requires EVEX_B and the L prefix") \ + ENUM_ENTRY(IC_EVEX_L_XS_B, 4, "requires EVEX_B and the L and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L_XD_B, 4, "requires EVEX_B and the L and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L_OPSIZE_B, 4, "requires EVEX_B, L, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_W_B, 3, "requires EVEX_B, L and W") \ + ENUM_ENTRY(IC_EVEX_L_W_XS_B, 4, "requires EVEX_B, L, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_XD_B, 4, "requires EVEX_B, L, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_B, 4, "requires EVEX_B, L, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_B, 3, "requires EVEX_B and the L2 prefix") \ + ENUM_ENTRY(IC_EVEX_L2_XS_B, 4, "requires EVEX_B and the L2 and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L2_XD_B, 4, "requires EVEX_B and the L2 and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L2_OPSIZE_B, 4, "requires EVEX_B, L2, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_W_B, 3, "requires EVEX_B, L2 and W") \ + ENUM_ENTRY(IC_EVEX_L2_W_XS_B, 4, "requires EVEX_B, L2, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_XD_B, 4, "requires EVEX_B, L2, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_B, 4, "requires EVEX_B, L2, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_K_B, 1, "requires EVEX_B and EVEX_K prefix") \ + ENUM_ENTRY(IC_EVEX_XS_K_B, 2, "requires EVEX_B, EVEX_K and the XS prefix") \ + ENUM_ENTRY(IC_EVEX_XD_K_B, 2, "requires EVEX_B, EVEX_K and the XD prefix") \ + ENUM_ENTRY(IC_EVEX_OPSIZE_K_B, 2, "requires EVEX_B, EVEX_K and the OpSize prefix") \ + ENUM_ENTRY(IC_EVEX_W_K_B, 3, "requires EVEX_B, EVEX_K and the W prefix") \ + ENUM_ENTRY(IC_EVEX_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, W, and XS prefix") \ + ENUM_ENTRY(IC_EVEX_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, W, and XD prefix") \ + ENUM_ENTRY(IC_EVEX_W_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, W, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_K_B, 3, "requires EVEX_B, EVEX_K and the L prefix") \ + ENUM_ENTRY(IC_EVEX_L_XS_K_B, 4, "requires EVEX_B, EVEX_K and the L and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L_XD_K_B, 4, "requires EVEX_B, EVEX_K and the L and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, L, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_W_K_B, 3, "requires EVEX_B, EVEX_K, L and W") \ + ENUM_ENTRY(IC_EVEX_L_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, L, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, L, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_K_B,4, "requires EVEX_B, EVEX_K, L, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_K_B, 3, "requires EVEX_B, EVEX_K and the L2 prefix") \ + ENUM_ENTRY(IC_EVEX_L2_XS_K_B, 4, "requires EVEX_B, EVEX_K and the L2 and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L2_XD_K_B, 4, "requires EVEX_B, EVEX_K and the L2 and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L2_OPSIZE_K_B, 4, "requires EVEX_B, EVEX_K, L2, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_W_K_B, 3, "requires EVEX_B, EVEX_K, L2 and W") \ + ENUM_ENTRY(IC_EVEX_L2_W_XS_K_B, 4, "requires EVEX_B, EVEX_K, L2, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_XD_K_B, 4, "requires EVEX_B, EVEX_K, L2, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_K_B,4, "requires EVEX_B, EVEX_K, L2, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_KZ_B, 1, "requires EVEX_B and EVEX_KZ prefix") \ + ENUM_ENTRY(IC_EVEX_XS_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the XS prefix") \ + ENUM_ENTRY(IC_EVEX_XD_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the XD prefix") \ + ENUM_ENTRY(IC_EVEX_OPSIZE_KZ_B, 2, "requires EVEX_B, EVEX_KZ and the OpSize prefix") \ + ENUM_ENTRY(IC_EVEX_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the W prefix") \ + ENUM_ENTRY(IC_EVEX_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and XS prefix") \ + ENUM_ENTRY(IC_EVEX_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and XD prefix") \ + ENUM_ENTRY(IC_EVEX_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, W, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the L prefix") \ + ENUM_ENTRY(IC_EVEX_L_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ, L and W") \ + ENUM_ENTRY(IC_EVEX_L_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_KZ_B, 3, "requires EVEX_B, EVEX_KZ and the L2 prefix") \ + ENUM_ENTRY(IC_EVEX_L2_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L2 and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L2_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ and the L2 and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L2_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_W_KZ_B, 3, "requires EVEX_B, EVEX_KZ, L2 and W") \ + ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ_B, 4, "requires EVEX_B, EVEX_KZ, L2, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_KZ, 1, "requires an EVEX_KZ prefix") \ + ENUM_ENTRY(IC_EVEX_XS_KZ, 2, "requires EVEX_KZ and the XS prefix") \ + ENUM_ENTRY(IC_EVEX_XD_KZ, 2, "requires EVEX_KZ and the XD prefix") \ + ENUM_ENTRY(IC_EVEX_OPSIZE_KZ, 2, "requires EVEX_KZ and the OpSize prefix") \ + ENUM_ENTRY(IC_EVEX_W_KZ, 3, "requires EVEX_KZ and the W prefix") \ + ENUM_ENTRY(IC_EVEX_W_XS_KZ, 4, "requires EVEX_KZ, W, and XS prefix") \ + ENUM_ENTRY(IC_EVEX_W_XD_KZ, 4, "requires EVEX_KZ, W, and XD prefix") \ + ENUM_ENTRY(IC_EVEX_W_OPSIZE_KZ, 4, "requires EVEX_KZ, W, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_KZ, 3, "requires EVEX_KZ and the L prefix") \ + ENUM_ENTRY(IC_EVEX_L_XS_KZ, 4, "requires EVEX_KZ and the L and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L_XD_KZ, 4, "requires EVEX_KZ and the L and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L_OPSIZE_KZ, 4, "requires EVEX_KZ, L, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L_W_KZ, 3, "requires EVEX_KZ, L and W") \ + ENUM_ENTRY(IC_EVEX_L_W_XS_KZ, 4, "requires EVEX_KZ, L, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_XD_KZ, 4, "requires EVEX_KZ, L, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L, W and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_KZ, 3, "requires EVEX_KZ and the L2 prefix") \ + ENUM_ENTRY(IC_EVEX_L2_XS_KZ, 4, "requires EVEX_KZ and the L2 and XS prefix")\ + ENUM_ENTRY(IC_EVEX_L2_XD_KZ, 4, "requires EVEX_KZ and the L2 and XD prefix")\ + ENUM_ENTRY(IC_EVEX_L2_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, and OpSize") \ + ENUM_ENTRY(IC_EVEX_L2_W_KZ, 3, "requires EVEX_KZ, L2 and W") \ + ENUM_ENTRY(IC_EVEX_L2_W_XS_KZ, 4, "requires EVEX_KZ, L2, W and XS prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_XD_KZ, 4, "requires EVEX_KZ, L2, W and XD prefix") \ + ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_KZ, 4, "requires EVEX_KZ, L2, W and OpSize") + +#define ENUM_ENTRY(n, r, d) n, +enum InstructionContext { + INSTRUCTION_CONTEXTS + IC_max +}; +#undef ENUM_ENTRY + +// Opcode types, which determine which decode table to use, both in the Intel +// manual and also for the decoder. +enum OpcodeType { + ONEBYTE = 0, + TWOBYTE = 1, + THREEBYTE_38 = 2, + THREEBYTE_3A = 3, + XOP8_MAP = 4, + XOP9_MAP = 5, + XOPA_MAP = 6, + THREEDNOW_MAP = 7 +}; + +// The following structs are used for the hierarchical decode table. After +// determining the instruction's class (i.e., which IC_* constant applies to +// it), the decoder reads the opcode. Some instructions require specific +// values of the ModR/M byte, so the ModR/M byte indexes into the final table. +// +// If a ModR/M byte is not required, "required" is left unset, and the values +// for each instructionID are identical. +typedef uint16_t InstrUID; + +// ModRMDecisionType - describes the type of ModR/M decision, allowing the +// consumer to determine the number of entries in it. +// +// MODRM_ONEENTRY - No matter what the value of the ModR/M byte is, the decoded +// instruction is the same. +// MODRM_SPLITRM - If the ModR/M byte is between 0x00 and 0xbf, the opcode +// corresponds to one instruction; otherwise, it corresponds to +// a different instruction. +// MODRM_SPLITMISC- If the ModR/M byte is between 0x00 and 0xbf, ModR/M byte +// divided by 8 is used to select instruction; otherwise, each +// value of the ModR/M byte could correspond to a different +// instruction. +// MODRM_SPLITREG - ModR/M byte divided by 8 is used to select instruction. This +// corresponds to instructions that use reg field as opcode +// MODRM_FULL - Potentially, each value of the ModR/M byte could correspond +// to a different instruction. +#define MODRMTYPES \ + ENUM_ENTRY(MODRM_ONEENTRY) \ + ENUM_ENTRY(MODRM_SPLITRM) \ + ENUM_ENTRY(MODRM_SPLITMISC) \ + ENUM_ENTRY(MODRM_SPLITREG) \ + ENUM_ENTRY(MODRM_FULL) + +#define ENUM_ENTRY(n) n, +enum ModRMDecisionType { + MODRMTYPES + MODRM_max +}; +#undef ENUM_ENTRY + +#define CASE_ENCODING_RM \ + case ENCODING_RM: \ + case ENCODING_RM_CD2: \ + case ENCODING_RM_CD4: \ + case ENCODING_RM_CD8: \ + case ENCODING_RM_CD16: \ + case ENCODING_RM_CD32: \ + case ENCODING_RM_CD64 + +#define CASE_ENCODING_VSIB \ + case ENCODING_VSIB: \ + case ENCODING_VSIB_CD2: \ + case ENCODING_VSIB_CD4: \ + case ENCODING_VSIB_CD8: \ + case ENCODING_VSIB_CD16: \ + case ENCODING_VSIB_CD32: \ + case ENCODING_VSIB_CD64 + +// Physical encodings of instruction operands. +#define ENCODINGS \ + ENUM_ENTRY(ENCODING_NONE, "") \ + ENUM_ENTRY(ENCODING_REG, "Register operand in ModR/M byte.") \ + ENUM_ENTRY(ENCODING_RM, "R/M operand in ModR/M byte.") \ + ENUM_ENTRY(ENCODING_RM_CD2, "R/M operand with CDisp scaling of 2") \ + ENUM_ENTRY(ENCODING_RM_CD4, "R/M operand with CDisp scaling of 4") \ + ENUM_ENTRY(ENCODING_RM_CD8, "R/M operand with CDisp scaling of 8") \ + ENUM_ENTRY(ENCODING_RM_CD16,"R/M operand with CDisp scaling of 16") \ + ENUM_ENTRY(ENCODING_RM_CD32,"R/M operand with CDisp scaling of 32") \ + ENUM_ENTRY(ENCODING_RM_CD64,"R/M operand with CDisp scaling of 64") \ + ENUM_ENTRY(ENCODING_VSIB, "VSIB operand in ModR/M byte.") \ + ENUM_ENTRY(ENCODING_VSIB_CD2, "VSIB operand with CDisp scaling of 2") \ + ENUM_ENTRY(ENCODING_VSIB_CD4, "VSIB operand with CDisp scaling of 4") \ + ENUM_ENTRY(ENCODING_VSIB_CD8, "VSIB operand with CDisp scaling of 8") \ + ENUM_ENTRY(ENCODING_VSIB_CD16,"VSIB operand with CDisp scaling of 16") \ + ENUM_ENTRY(ENCODING_VSIB_CD32,"VSIB operand with CDisp scaling of 32") \ + ENUM_ENTRY(ENCODING_VSIB_CD64,"VSIB operand with CDisp scaling of 64") \ + ENUM_ENTRY(ENCODING_VVVV, "Register operand in VEX.vvvv byte.") \ + ENUM_ENTRY(ENCODING_WRITEMASK, "Register operand in EVEX.aaa byte.") \ + ENUM_ENTRY(ENCODING_IB, "1-byte immediate") \ + ENUM_ENTRY(ENCODING_IW, "2-byte") \ + ENUM_ENTRY(ENCODING_ID, "4-byte") \ + ENUM_ENTRY(ENCODING_IO, "8-byte") \ + ENUM_ENTRY(ENCODING_RB, "(AL..DIL, R8L..R15L) Register code added to " \ + "the opcode byte") \ + ENUM_ENTRY(ENCODING_RW, "(AX..DI, R8W..R15W)") \ + ENUM_ENTRY(ENCODING_RD, "(EAX..EDI, R8D..R15D)") \ + ENUM_ENTRY(ENCODING_RO, "(RAX..RDI, R8..R15)") \ + ENUM_ENTRY(ENCODING_FP, "Position on floating-point stack in ModR/M " \ + "byte.") \ + \ + ENUM_ENTRY(ENCODING_Iv, "Immediate of operand size") \ + ENUM_ENTRY(ENCODING_Ia, "Immediate of address size") \ + ENUM_ENTRY(ENCODING_IRC, "Immediate for static rounding control") \ + ENUM_ENTRY(ENCODING_Rv, "Register code of operand size added to the " \ + "opcode byte") \ + ENUM_ENTRY(ENCODING_DUP, "Duplicate of another operand; ID is encoded " \ + "in type") \ + ENUM_ENTRY(ENCODING_SI, "Source index; encoded in OpSize/Adsize prefix") \ + ENUM_ENTRY(ENCODING_DI, "Destination index; encoded in prefixes") + +#define ENUM_ENTRY(n, d) n, +enum OperandEncoding { + ENCODINGS + ENCODING_max +}; +#undef ENUM_ENTRY + +// Semantic interpretations of instruction operands. +#define TYPES \ + ENUM_ENTRY(TYPE_NONE, "") \ + ENUM_ENTRY(TYPE_REL, "immediate address") \ + ENUM_ENTRY(TYPE_R8, "1-byte register operand") \ + ENUM_ENTRY(TYPE_R16, "2-byte") \ + ENUM_ENTRY(TYPE_R32, "4-byte") \ + ENUM_ENTRY(TYPE_R64, "8-byte") \ + ENUM_ENTRY(TYPE_IMM, "immediate operand") \ + ENUM_ENTRY(TYPE_IMM3, "1-byte immediate operand between 0 and 7") \ + ENUM_ENTRY(TYPE_IMM5, "1-byte immediate operand between 0 and 31") \ + ENUM_ENTRY(TYPE_AVX512ICC, "1-byte immediate operand for AVX512 icmp") \ + ENUM_ENTRY(TYPE_UIMM8, "1-byte unsigned immediate operand") \ + ENUM_ENTRY(TYPE_M, "Memory operand") \ + ENUM_ENTRY(TYPE_MVSIBX, "Memory operand using XMM index") \ + ENUM_ENTRY(TYPE_MVSIBY, "Memory operand using YMM index") \ + ENUM_ENTRY(TYPE_MVSIBZ, "Memory operand using ZMM index") \ + ENUM_ENTRY(TYPE_SRCIDX, "memory at source index") \ + ENUM_ENTRY(TYPE_DSTIDX, "memory at destination index") \ + ENUM_ENTRY(TYPE_MOFFS, "memory offset (relative to segment base)") \ + ENUM_ENTRY(TYPE_ST, "Position on the floating-point stack") \ + ENUM_ENTRY(TYPE_MM64, "8-byte MMX register") \ + ENUM_ENTRY(TYPE_XMM, "16-byte") \ + ENUM_ENTRY(TYPE_YMM, "32-byte") \ + ENUM_ENTRY(TYPE_ZMM, "64-byte") \ + ENUM_ENTRY(TYPE_VK, "mask register") \ + ENUM_ENTRY(TYPE_SEGMENTREG, "Segment register operand") \ + ENUM_ENTRY(TYPE_DEBUGREG, "Debug register operand") \ + ENUM_ENTRY(TYPE_CONTROLREG, "Control register operand") \ + ENUM_ENTRY(TYPE_BNDR, "MPX bounds register") \ + \ + ENUM_ENTRY(TYPE_Rv, "Register operand of operand size") \ + ENUM_ENTRY(TYPE_RELv, "Immediate address of operand size") \ + ENUM_ENTRY(TYPE_DUP0, "Duplicate of operand 0") \ + ENUM_ENTRY(TYPE_DUP1, "operand 1") \ + ENUM_ENTRY(TYPE_DUP2, "operand 2") \ + ENUM_ENTRY(TYPE_DUP3, "operand 3") \ + ENUM_ENTRY(TYPE_DUP4, "operand 4") \ + +#define ENUM_ENTRY(n, d) n, +enum OperandType { + TYPES + TYPE_max +}; +#undef ENUM_ENTRY + +/// The specification for how to extract and interpret one operand. +struct OperandSpecifier { + uint8_t encoding; + uint8_t type; +}; + +static const unsigned X86_MAX_OPERANDS = 6; + +/// Decoding mode for the Intel disassembler. 16-bit, 32-bit, and 64-bit mode +/// are supported, and represent real mode, IA-32e, and IA-32e in 64-bit mode, +/// respectively. +enum DisassemblerMode { + MODE_16BIT, + MODE_32BIT, + MODE_64BIT +}; + +} // namespace X86Disassembler +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Support/X86TargetParser.def b/contrib/llvm/include/llvm/Support/X86TargetParser.def index 5c8c576b1027..e4af0657a350 100644 --- a/contrib/llvm/include/llvm/Support/X86TargetParser.def +++ b/contrib/llvm/include/llvm/Support/X86TargetParser.def @@ -65,6 +65,8 @@ X86_CPU_TYPE ("athlon-xp", AMD_ATHLON_XP) X86_CPU_TYPE ("k8", AMD_K8) X86_CPU_TYPE ("k8-sse3", AMD_K8SSE3) X86_CPU_TYPE ("goldmont", INTEL_GOLDMONT) +X86_CPU_TYPE ("goldmont-plus", INTEL_GOLDMONT_PLUS) +X86_CPU_TYPE ("tremont", INTEL_TREMONT) #undef X86_CPU_TYPE_COMPAT_WITH_ALIAS #undef X86_CPU_TYPE_COMPAT #undef X86_CPU_TYPE diff --git a/contrib/llvm/include/llvm/Support/YAMLParser.h b/contrib/llvm/include/llvm/Support/YAMLParser.h index c907a99ddb59..5b031a9a4270 100644 --- a/contrib/llvm/include/llvm/Support/YAMLParser.h +++ b/contrib/llvm/include/llvm/Support/YAMLParser.h @@ -64,23 +64,26 @@ class Node; class Scanner; struct Token; -/// \brief Dump all the tokens in this stream to OS. +/// Dump all the tokens in this stream to OS. /// \returns true if there was an error, false otherwise. bool dumpTokens(StringRef Input, raw_ostream &); -/// \brief Scans all tokens in input without outputting anything. This is used +/// Scans all tokens in input without outputting anything. This is used /// for benchmarking the tokenizer. /// \returns true if there was an error, false otherwise. bool scanTokens(StringRef Input); -/// \brief Escape \a Input for a double quoted scalar. -std::string escape(StringRef Input); +/// Escape \a Input for a double quoted scalar; if \p EscapePrintable +/// is true, all UTF8 sequences will be escaped, if \p EscapePrintable is +/// false, those UTF8 sequences encoding printable unicode scalars will not be +/// escaped, but emitted verbatim. +std::string escape(StringRef Input, bool EscapePrintable = true); -/// \brief This class represents a YAML stream potentially containing multiple +/// This class represents a YAML stream potentially containing multiple /// documents. class Stream { public: - /// \brief This keeps a reference to the string referenced by \p Input. + /// This keeps a reference to the string referenced by \p Input. Stream(StringRef Input, SourceMgr &, bool ShowColors = true, std::error_code *EC = nullptr); @@ -107,7 +110,7 @@ private: std::unique_ptr<Document> CurrentDoc; }; -/// \brief Abstract base class for all Nodes. +/// Abstract base class for all Nodes. class Node { virtual void anchor(); @@ -125,6 +128,11 @@ public: Node(unsigned int Type, std::unique_ptr<Document> &, StringRef Anchor, StringRef Tag); + // It's not safe to copy YAML nodes; the document is streamed and the position + // is part of the state. + Node(const Node &) = delete; + void operator=(const Node &) = delete; + void *operator new(size_t Size, BumpPtrAllocator &Alloc, size_t Alignment = 16) noexcept { return Alloc.Allocate(Size, Alignment); @@ -137,15 +145,15 @@ public: void operator delete(void *) noexcept = delete; - /// \brief Get the value of the anchor attached to this node. If it does not + /// Get the value of the anchor attached to this node. If it does not /// have one, getAnchor().size() will be 0. StringRef getAnchor() const { return Anchor; } - /// \brief Get the tag as it was written in the document. This does not + /// Get the tag as it was written in the document. This does not /// perform tag resolution. StringRef getRawTag() const { return Tag; } - /// \brief Get the verbatium tag for a given Node. This performs tag resoluton + /// Get the verbatium tag for a given Node. This performs tag resoluton /// and substitution. std::string getVerbatimTag() const; @@ -173,11 +181,11 @@ protected: private: unsigned int TypeID; StringRef Anchor; - /// \brief The tag as typed in the document. + /// The tag as typed in the document. StringRef Tag; }; -/// \brief A null value. +/// A null value. /// /// Example: /// !!null null @@ -191,7 +199,7 @@ public: static bool classof(const Node *N) { return N->getType() == NK_Null; } }; -/// \brief A scalar node is an opaque datum that can be presented as a +/// A scalar node is an opaque datum that can be presented as a /// series of zero or more Unicode scalar values. /// /// Example: @@ -213,7 +221,7 @@ public: // utf8). StringRef getRawValue() const { return Value; } - /// \brief Gets the value of this node as a StringRef. + /// Gets the value of this node as a StringRef. /// /// \param Storage is used to store the content of the returned StringRef iff /// it requires any modification from how it appeared in the source. @@ -232,7 +240,7 @@ private: SmallVectorImpl<char> &Storage) const; }; -/// \brief A block scalar node is an opaque datum that can be presented as a +/// A block scalar node is an opaque datum that can be presented as a /// series of zero or more Unicode scalar values. /// /// Example: @@ -251,7 +259,7 @@ public: SourceRange = SMRange(Start, End); } - /// \brief Gets the value of this node as a StringRef. + /// Gets the value of this node as a StringRef. StringRef getValue() const { return Value; } static bool classof(const Node *N) { @@ -262,7 +270,7 @@ private: StringRef Value; }; -/// \brief A key and value pair. While not technically a Node under the YAML +/// A key and value pair. While not technically a Node under the YAML /// representation graph, it is easier to treat them this way. /// /// TODO: Consider making this not a child of Node. @@ -276,14 +284,14 @@ public: KeyValueNode(std::unique_ptr<Document> &D) : Node(NK_KeyValue, D, StringRef(), StringRef()) {} - /// \brief Parse and return the key. + /// Parse and return the key. /// /// This may be called multiple times. /// /// \returns The key, or nullptr if failed() == true. Node *getKey(); - /// \brief Parse and return the value. + /// Parse and return the value. /// /// This may be called multiple times. /// @@ -307,7 +315,7 @@ private: Node *Value = nullptr; }; -/// \brief This is an iterator abstraction over YAML collections shared by both +/// This is an iterator abstraction over YAML collections shared by both /// sequences and maps. /// /// BaseT must have a ValueT* member named CurrentEntry and a member function @@ -387,7 +395,7 @@ template <class CollectionType> void skip(CollectionType &C) { i->skip(); } -/// \brief Represents a YAML map created from either a block map for a flow map. +/// Represents a YAML map created from either a block map for a flow map. /// /// This parses the YAML stream as increment() is called. /// @@ -434,7 +442,7 @@ private: void increment(); }; -/// \brief Represents a YAML sequence created from either a block sequence for a +/// Represents a YAML sequence created from either a block sequence for a /// flow sequence. /// /// This parses the YAML stream as increment() is called. @@ -490,7 +498,7 @@ private: Node *CurrentEntry = nullptr; }; -/// \brief Represents an alias to a Node with an anchor. +/// Represents an alias to a Node with an anchor. /// /// Example: /// *AnchorName @@ -510,20 +518,20 @@ private: StringRef Name; }; -/// \brief A YAML Stream is a sequence of Documents. A document contains a root +/// A YAML Stream is a sequence of Documents. A document contains a root /// node. class Document { public: Document(Stream &ParentStream); - /// \brief Root for parsing a node. Returns a single node. + /// Root for parsing a node. Returns a single node. Node *parseBlockNode(); - /// \brief Finish parsing the current document and return true if there are + /// Finish parsing the current document and return true if there are /// more. Return false otherwise. bool skip(); - /// \brief Parse and return the root level node. + /// Parse and return the root level node. Node *getRoot() { if (Root) return Root; @@ -536,18 +544,18 @@ private: friend class Node; friend class document_iterator; - /// \brief Stream to read tokens from. + /// Stream to read tokens from. Stream &stream; - /// \brief Used to allocate nodes to. All are destroyed without calling their + /// Used to allocate nodes to. All are destroyed without calling their /// destructor when the document is destroyed. BumpPtrAllocator NodeAllocator; - /// \brief The root node. Used to support skipping a partially parsed + /// The root node. Used to support skipping a partially parsed /// document. Node *Root; - /// \brief Maps tag prefixes to their expansion. + /// Maps tag prefixes to their expansion. std::map<StringRef, StringRef> TagMap; Token &peekNext(); @@ -555,20 +563,20 @@ private: void setError(const Twine &Message, Token &Location) const; bool failed() const; - /// \brief Parse %BLAH directives and return true if any were encountered. + /// Parse %BLAH directives and return true if any were encountered. bool parseDirectives(); - /// \brief Parse %YAML + /// Parse %YAML void parseYAMLDirective(); - /// \brief Parse %TAG + /// Parse %TAG void parseTAGDirective(); - /// \brief Consume the next token and error if it is not \a TK. + /// Consume the next token and error if it is not \a TK. bool expectToken(int TK); }; -/// \brief Iterator abstraction for Documents over a Stream. +/// Iterator abstraction for Documents over a Stream. class document_iterator { public: document_iterator() = default; diff --git a/contrib/llvm/include/llvm/Support/YAMLTraits.h b/contrib/llvm/include/llvm/Support/YAMLTraits.h index 674c78a11695..4b8c4e958288 100644 --- a/contrib/llvm/include/llvm/Support/YAMLTraits.h +++ b/contrib/llvm/include/llvm/Support/YAMLTraits.h @@ -511,8 +511,6 @@ inline QuotingType needsQuotes(StringRef S) { return QuotingType::Single; if (isspace(S.front()) || isspace(S.back())) return QuotingType::Single; - if (S.front() == ',') - return QuotingType::Single; if (isNull(S)) return QuotingType::Single; if (isBool(S)) @@ -520,6 +518,13 @@ inline QuotingType needsQuotes(StringRef S) { if (isNumeric(S)) return QuotingType::Single; + // 7.3.3 Plain Style + // Plain scalars must not begin with most indicators, as this would cause + // ambiguity with other YAML constructs. + static constexpr char Indicators[] = R"(-?:\,[]{}#&*!|>'"%@`)"; + if (S.find_first_of(Indicators) == 0) + return QuotingType::Single; + QuotingType MaxQuotingNeeded = QuotingType::None; for (unsigned char C : S) { // Alphanum is safe. @@ -535,11 +540,14 @@ inline QuotingType needsQuotes(StringRef S) { case '.': case ',': case ' ': - // TAB (0x9), LF (0xA), CR (0xD) and NEL (0x85) are allowed. + // TAB (0x9) is allowed in unquoted strings. case 0x9: + continue; + // LF(0xA) and CR(0xD) may delimit values and so require at least single + // quotes. case 0xA: case 0xD: - case 0x85: + MaxQuotingNeeded = QuotingType::Single; continue; // DEL (0x7F) are excluded from the allowed character range. case 0x7F: @@ -1306,7 +1314,7 @@ public: Output(raw_ostream &, void *Ctxt = nullptr, int WrapColumn = 70); ~Output() override; - /// \brief Set whether or not to output optional values which are equal + /// Set whether or not to output optional values which are equal /// to the default value. By default, when outputting if you attempt /// to write a value that is equal to the default, the value gets ignored. /// Sometimes, it is useful to be able to see these in the resulting YAML diff --git a/contrib/llvm/include/llvm/Support/raw_ostream.h b/contrib/llvm/include/llvm/Support/raw_ostream.h index d11f5a837796..b9ea9b5817f2 100644 --- a/contrib/llvm/include/llvm/Support/raw_ostream.h +++ b/contrib/llvm/include/llvm/Support/raw_ostream.h @@ -33,7 +33,9 @@ class FormattedBytes; namespace sys { namespace fs { +enum FileAccess : unsigned; enum OpenFlags : unsigned; +enum CreationDisposition : unsigned; } // end namespace fs } // end namespace sys @@ -218,7 +220,7 @@ public: raw_ostream &write_uuid(const uuid_t UUID); /// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't - /// satisfy std::isprint into an escape sequence. + /// satisfy llvm::isPrint into an escape sequence. raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); raw_ostream &write(unsigned char C); @@ -242,6 +244,9 @@ public: /// indent - Insert 'NumSpaces' spaces. raw_ostream &indent(unsigned NumSpaces); + /// write_zeros - Insert 'NumZeros' nulls. + raw_ostream &write_zeros(unsigned NumZeros); + /// Changes the foreground color of text that will be output from this point /// forward. /// @param Color ANSI color to use, the special SAVEDCOLOR can be used to @@ -293,9 +298,6 @@ private: /// \invariant { Size > 0 } virtual void write_impl(const char *Ptr, size_t Size) = 0; - // An out of line virtual method to provide a home for the class vtable. - virtual void handle(); - /// Return the current position within the stream, not counting the bytes /// currently in the buffer. virtual uint64_t current_pos() const = 0; @@ -329,6 +331,8 @@ private: /// Copy data into the buffer. Size must not be greater than the number of /// unused bytes in the buffer. void copy_to_buffer(const char *Ptr, size_t Size); + + virtual void anchor(); }; /// An abstract base class for streams implementations that also support a @@ -336,6 +340,7 @@ private: /// but needs to patch in a header that needs to know the output size. class raw_pwrite_stream : public raw_ostream { virtual void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) = 0; + void anchor() override; public: explicit raw_pwrite_stream(bool Unbuffered = false) @@ -383,6 +388,8 @@ class raw_fd_ostream : public raw_pwrite_stream { /// Set the flag indicating that an output error has been encountered. void error_detected(std::error_code EC) { this->EC = EC; } + void anchor() override; + public: /// Open the specified file for writing. If an error occurs, information /// about the error is put into EC, and the stream should be immediately @@ -392,7 +399,15 @@ public: /// As a special case, if Filename is "-", then the stream will use /// STDOUT_FILENO instead of opening a file. This will not close the stdout /// descriptor. + raw_fd_ostream(StringRef Filename, std::error_code &EC); + raw_fd_ostream(StringRef Filename, std::error_code &EC, + sys::fs::CreationDisposition Disp); + raw_fd_ostream(StringRef Filename, std::error_code &EC, + sys::fs::FileAccess Access); + raw_fd_ostream(StringRef Filename, std::error_code &EC, + sys::fs::OpenFlags Flags); raw_fd_ostream(StringRef Filename, std::error_code &EC, + sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access, sys::fs::OpenFlags Flags); /// FD is the file descriptor that this writes to. If ShouldClose is true, diff --git a/contrib/llvm/include/llvm/Support/type_traits.h b/contrib/llvm/include/llvm/Support/type_traits.h index cc0878358800..55d84f138f07 100644 --- a/contrib/llvm/include/llvm/Support/type_traits.h +++ b/contrib/llvm/include/llvm/Support/type_traits.h @@ -54,7 +54,7 @@ struct isPodLike<std::pair<T, U>> { static const bool value = isPodLike<T>::value && isPodLike<U>::value; }; -/// \brief Metafunction that determines whether the given type is either an +/// Metafunction that determines whether the given type is either an /// integral type or an enumeration type, including enum classes. /// /// Note that this accepts potentially more integral types than is_integral @@ -73,7 +73,7 @@ public: std::is_convertible<UnderlyingT, unsigned long long>::value); }; -/// \brief If T is a pointer, just return it. If it is not, return T&. +/// 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 { using type = T &; }; @@ -83,7 +83,7 @@ struct add_lvalue_reference_if_not_pointer< using type = T; }; -/// \brief If T is a pointer to X, return a pointer to const X. If it is not, +/// 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 { using type = const T; }; @@ -104,12 +104,51 @@ struct const_pointer_or_const_ref< using type = typename add_const_past_pointer<T>::type; }; +namespace detail { +/// Internal utility to detect trivial copy construction. +template<typename T> union copy_construction_triviality_helper { + T t; + copy_construction_triviality_helper() = default; + copy_construction_triviality_helper(const copy_construction_triviality_helper&) = default; + ~copy_construction_triviality_helper() = default; +}; +/// Internal utility to detect trivial move construction. +template<typename T> union move_construction_triviality_helper { + T t; + move_construction_triviality_helper() = default; + move_construction_triviality_helper(move_construction_triviality_helper&&) = default; + ~move_construction_triviality_helper() = default; +}; +} // end namespace detail + +/// An implementation of `std::is_trivially_copy_constructible` since we have +/// users with STLs that don't yet include it. +template <typename T> +struct is_trivially_copy_constructible + : std::is_copy_constructible< + ::llvm::detail::copy_construction_triviality_helper<T>> {}; +template <typename T> +struct is_trivially_copy_constructible<T &> : std::true_type {}; +template <typename T> +struct is_trivially_copy_constructible<T &&> : std::false_type {}; + +/// An implementation of `std::is_trivially_move_constructible` since we have +/// users with STLs that don't yet include it. +template <typename T> +struct is_trivially_move_constructible + : std::is_move_constructible< + ::llvm::detail::move_construction_triviality_helper<T>> {}; +template <typename T> +struct is_trivially_move_constructible<T &> : std::true_type {}; +template <typename T> +struct is_trivially_move_constructible<T &&> : std::true_type {}; + } // end namespace llvm // If the compiler supports detecting whether a class is final, define // an LLVM_IS_FINAL macro. If it cannot be defined properly, this // macro will be left undefined. -#if __cplusplus >= 201402L +#if __cplusplus >= 201402L || defined(_MSC_VER) #define LLVM_IS_FINAL(Ty) std::is_final<Ty>() #elif __has_feature(is_final) || LLVM_GNUC_PREREQ(4, 7, 0) #define LLVM_IS_FINAL(Ty) __is_final(Ty) diff --git a/contrib/llvm/include/llvm/TableGen/Record.h b/contrib/llvm/include/llvm/TableGen/Record.h index 55b4dfe2fa2f..e022bc82b4e4 100644 --- a/contrib/llvm/include/llvm/TableGen/Record.h +++ b/contrib/llvm/include/llvm/TableGen/Record.h @@ -16,6 +16,8 @@ #define LLVM_TABLEGEN_RECORD_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" @@ -42,7 +44,9 @@ struct MultiClass; class Record; class RecordKeeper; class RecordVal; +class Resolver; class StringInit; +class TypedInit; //===----------------------------------------------------------------------===// // Type Classes @@ -50,7 +54,7 @@ class StringInit; class RecTy { public: - /// \brief Subclass discriminator (for dyn_cast<> et al.) + /// Subclass discriminator (for dyn_cast<> et al.) enum RecTyKind { BitRecTyKind, BitsRecTyKind, @@ -80,6 +84,10 @@ public: /// type. virtual bool typeIsConvertibleTo(const RecTy *RHS) const; + /// Return true if 'this' type is equal to or a subtype of RHS. For example, + /// a bit set is not an int, but they are convertible. + virtual bool typeIsA(const RecTy *RHS) const; + /// Returns the type representing list<this>. ListRecTy *getListTy(); }; @@ -125,6 +133,8 @@ public: std::string getAsString() const override; bool typeIsConvertibleTo(const RecTy *RHS) const override; + + bool typeIsA(const RecTy *RHS) const override; }; /// 'code' - Represent a code fragment @@ -141,6 +151,8 @@ public: static CodeRecTy *get() { return &Shared; } std::string getAsString() const override { return "code"; } + + bool typeIsConvertibleTo(const RecTy *RHS) const override; }; /// 'int' - Represent an integer value of no particular size @@ -169,13 +181,14 @@ class StringRecTy : public RecTy { public: static bool classof(const RecTy *RT) { - return RT->getRecTyKind() == StringRecTyKind || - RT->getRecTyKind() == CodeRecTyKind; + return RT->getRecTyKind() == StringRecTyKind; } static StringRecTy *get() { return &Shared; } std::string getAsString() const override; + + bool typeIsConvertibleTo(const RecTy *RHS) const override; }; /// 'list<Ty>' - Represent a list of values, all of which must be of @@ -198,6 +211,8 @@ public: std::string getAsString() const override; bool typeIsConvertibleTo(const RecTy *RHS) const override; + + bool typeIsA(const RecTy *RHS) const override; }; /// 'dag' - Represent a dag fragment @@ -216,27 +231,50 @@ public: std::string getAsString() const override; }; -/// '[classname]' - Represent an instance of a class, such as: -/// (R32 X = EAX). -class RecordRecTy : public RecTy { +/// '[classname]' - Type of record values that have zero or more superclasses. +/// +/// The list of superclasses is non-redundant, i.e. only contains classes that +/// are not the superclass of some other listed class. +class RecordRecTy final : public RecTy, public FoldingSetNode, + public TrailingObjects<RecordRecTy, Record *> { friend class Record; - Record *Rec; + unsigned NumClasses; - explicit RecordRecTy(Record *R) : RecTy(RecordRecTyKind), Rec(R) {} + explicit RecordRecTy(unsigned Num) + : RecTy(RecordRecTyKind), NumClasses(Num) {} public: + RecordRecTy(const RecordRecTy &) = delete; + RecordRecTy &operator=(const RecordRecTy &) = delete; + + // Do not use sized deallocation due to trailing objects. + void operator delete(void *p) { ::operator delete(p); } + static bool classof(const RecTy *RT) { return RT->getRecTyKind() == RecordRecTyKind; } - static RecordRecTy *get(Record *R); + /// Get the record type with the given non-redundant list of superclasses. + static RecordRecTy *get(ArrayRef<Record *> Classes); + + void Profile(FoldingSetNodeID &ID) const; + + ArrayRef<Record *> getClasses() const { + return makeArrayRef(getTrailingObjects<Record *>(), NumClasses); + } + + using const_record_iterator = Record * const *; - Record *getRecord() const { return Rec; } + const_record_iterator classes_begin() const { return getClasses().begin(); } + const_record_iterator classes_end() const { return getClasses().end(); } std::string getAsString() const override; + bool isSubClassOf(Record *Class) const; bool typeIsConvertibleTo(const RecTy *RHS) const override; + + bool typeIsA(const RecTy *RHS) const override; }; /// Find a common type that T1 and T2 convert to. @@ -249,7 +287,7 @@ RecTy *resolveTypes(RecTy *T1, RecTy *T2); class Init { protected: - /// \brief Discriminator enum (for isa<>, dyn_cast<>, et al.) + /// Discriminator enum (for isa<>, dyn_cast<>, et al.) /// /// This enum is laid out by a preorder traversal of the inheritance /// hierarchy, and does not contain an entry for abstract classes, as per @@ -263,8 +301,9 @@ protected: /// and IK_LastXXXInit be their own values, but that would degrade /// readability for really no benefit. enum InitKind : uint8_t { - IK_BitInit, + IK_First, // unused; silence a spurious warning IK_FirstTypedInit, + IK_BitInit, IK_BitsInit, IK_CodeInit, IK_DagInit, @@ -277,12 +316,15 @@ protected: IK_TernOpInit, IK_UnOpInit, IK_LastOpInit, + IK_FoldOpInit, + IK_IsAOpInit, IK_StringInit, IK_VarInit, IK_VarListElementInit, + IK_VarBitInit, + IK_VarDefInit, IK_LastTypedInit, - IK_UnsetInit, - IK_VarBitInit + IK_UnsetInit }; private: @@ -309,6 +351,10 @@ public: /// not be completely specified yet. virtual bool isComplete() const { return true; } + /// Is this a concrete and fully resolved value without any references or + /// stuck operations? Unset values are concrete. + virtual bool isConcrete() const { return false; } + /// Print out this value. void print(raw_ostream &OS) const { OS << getAsString(); } @@ -324,8 +370,14 @@ public: /// invokes print on stderr. void dump() const; - /// This virtual function converts to the appropriate - /// Init based on the passed in type. + /// If this initializer is convertible to Ty, return an initializer whose + /// type is-a Ty, generating a !cast operation if required. Otherwise, return + /// nullptr. + virtual Init *getCastTo(RecTy *Ty) const = 0; + + /// Convert to an initializer whose type is-a Ty, or return nullptr if this + /// is not possible (this can happen if the initializer's type is convertible + /// to Ty, but there are unresolved references). virtual Init *convertInitializerTo(RecTy *Ty) const = 0; /// This method is used to implement the bitrange @@ -351,33 +403,17 @@ public: return nullptr; } - /// This method complements getFieldType to return the - /// initializer for the specified field. If getFieldType returns non-null - /// this method should return non-null, otherwise it returns null. - virtual Init *getFieldInit(Record &R, const RecordVal *RV, - StringInit *FieldName) const { - return nullptr; - } - /// This method is used by classes that refer to other /// variables which may not be defined at the time the 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 { + virtual Init *resolveReferences(Resolver &R) const { return const_cast<Init *>(this); } /// This method is used to return the initializer for the specified /// bit. virtual Init *getBit(unsigned Bit) const = 0; - - /// This method is used to retrieve the initializer for bit - /// reference. For non-VarBitInit, it simply returns itself. - virtual Init *getBitVar() const { return const_cast<Init*>(this); } - - /// This method is used to retrieve the bit number of a bit - /// reference. For non-VarBitInit, it simply returns 0. - virtual unsigned getBitNum() const { return 0; } }; inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) { @@ -404,6 +440,7 @@ public: RecTy *getType() const { return Ty; } + Init *getCastTo(RecTy *Ty) const override; Init *convertInitializerTo(RecTy *Ty) const override; Init *convertInitializerBitRange(ArrayRef<unsigned> Bits) const override; @@ -414,12 +451,6 @@ public: /// they are of record type. /// RecTy *getFieldType(StringInit *FieldName) const override; - - /// 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 = 0; }; /// '?' - Represents an uninitialized value @@ -436,6 +467,7 @@ public: static UnsetInit *get(); + Init *getCastTo(RecTy *Ty) const override; Init *convertInitializerTo(RecTy *Ty) const override; Init *getBit(unsigned Bit) const override { @@ -443,14 +475,15 @@ public: } bool isComplete() const override { return false; } + bool isConcrete() const override { return true; } std::string getAsString() const override { return "?"; } }; /// 'true'/'false' - Represent a concrete initializer for a bit. -class BitInit : public Init { +class BitInit final : public TypedInit { bool Value; - explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {} + explicit BitInit(bool V) : TypedInit(IK_BitInit, BitRecTy::get()), Value(V) {} public: BitInit(const BitInit &) = delete; @@ -471,6 +504,7 @@ public: return const_cast<BitInit*>(this); } + bool isConcrete() const override { return true; } std::string getAsString() const override { return Value ? "1" : "0"; } }; @@ -515,17 +549,10 @@ public: return true; } + bool isConcrete() const override; std::string getAsString() const override; - /// This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override { - llvm_unreachable("Illegal element reference off bits<n>"); - } - - Init *resolveReferences(Record &R, const RecordVal *RV) const override; + Init *resolveReferences(Resolver &R) const override; Init *getBit(unsigned Bit) const override { assert(Bit < NumBits && "Bit index out of range!"); @@ -555,16 +582,9 @@ public: Init *convertInitializerTo(RecTy *Ty) const override; Init *convertInitializerBitRange(ArrayRef<unsigned> Bits) const override; + bool isConcrete() const override { return true; } std::string getAsString() const override; - /// This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override { - llvm_unreachable("Illegal element reference off int"); - } - Init *getBit(unsigned Bit) const override { return BitInit::get((Value & (1ULL << Bit)) != 0); } @@ -591,18 +611,11 @@ public: Init *convertInitializerTo(RecTy *Ty) const override; + bool isConcrete() const override { return true; } std::string getAsString() const override { return "\"" + Value.str() + "\""; } 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. - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override { - llvm_unreachable("Illegal element reference off string"); - } - Init *getBit(unsigned Bit) const override { llvm_unreachable("Illegal bit reference off string"); } @@ -629,20 +642,13 @@ public: Init *convertInitializerTo(RecTy *Ty) const override; + bool isConcrete() const override { return true; } std::string getAsString() const override { return "[{" + Value.str() + "}]"; } std::string getAsUnquotedString() const override { return Value; } - /// This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override { - llvm_unreachable("Illegal element reference off string"); - } - Init *getBit(unsigned Bit) const override { llvm_unreachable("Illegal bit reference off string"); } @@ -679,6 +685,9 @@ public: assert(i < NumValues && "List element index out of range!"); return getTrailingObjects<Init *>()[i]; } + RecTy *getElementType() const { + return cast<ListRecTy>(getType())->getElementType(); + } Record *getElementAsRecord(unsigned i) const; @@ -691,8 +700,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. /// - Init *resolveReferences(Record &R, const RecordVal *RV) const override; + Init *resolveReferences(Resolver &R) const override; + bool isConcrete() const override; std::string getAsString() const override; ArrayRef<Init*> getValues() const { @@ -705,12 +715,6 @@ public: size_t size () const { return NumValues; } bool empty() const { return NumValues == 0; } - /// This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override; - Init *getBit(unsigned Bit) const override { llvm_unreachable("Illegal bit reference off list"); } @@ -738,13 +742,6 @@ public: virtual unsigned getNumOperands() const = 0; virtual Init *getOperand(unsigned i) const = 0; - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0; - - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override; - Init *getBit(unsigned Bit) const override; }; @@ -752,7 +749,7 @@ public: /// class UnOpInit : public OpInit, public FoldingSetNode { public: - enum UnaryOp : uint8_t { CAST, HEAD, TAIL, EMPTY }; + enum UnaryOp : uint8_t { CAST, HEAD, TAIL, SIZE, EMPTY }; private: Init *LHS; @@ -791,9 +788,9 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override; + Init *Fold(Record *CurRec, bool IsFinal = false) const; - Init *resolveReferences(Record &R, const RecordVal *RV) const override; + Init *resolveReferences(Resolver &R) const override; std::string getAsString() const override; }; @@ -802,7 +799,7 @@ public: class BinOpInit : public OpInit, public FoldingSetNode { public: enum BinaryOp : uint8_t { ADD, AND, OR, SHL, SRA, SRL, LISTCONCAT, - STRCONCAT, CONCAT, EQ }; + STRCONCAT, CONCAT, EQ, NE, LE, LT, GE, GT }; private: Init *LHS, *RHS; @@ -820,6 +817,7 @@ public: static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type); + static Init *getStrConcat(Init *lhs, Init *rhs); void Profile(FoldingSetNodeID &ID) const; @@ -845,9 +843,9 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override; + Init *Fold(Record *CurRec) const; - Init *resolveReferences(Record &R, const RecordVal *RV) const override; + Init *resolveReferences(Resolver &R) const override; std::string getAsString() const override; }; @@ -855,7 +853,7 @@ public: /// !op (X, Y, Z) - Combine two inits. class TernOpInit : public OpInit, public FoldingSetNode { public: - enum TernaryOp : uint8_t { SUBST, FOREACH, IF }; + enum TernaryOp : uint8_t { SUBST, FOREACH, IF, DAG }; private: Init *LHS, *MHS, *RHS; @@ -903,11 +901,83 @@ public: // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const override; + Init *Fold(Record *CurRec) const; + + bool isComplete() const override { + return LHS->isComplete() && MHS->isComplete() && RHS->isComplete(); + } + + Init *resolveReferences(Resolver &R) const override; + + std::string getAsString() const override; +}; + +/// !foldl (a, b, expr, start, lst) - Fold over a list. +class FoldOpInit : public TypedInit, public FoldingSetNode { +private: + Init *Start; + Init *List; + Init *A; + Init *B; + Init *Expr; + + FoldOpInit(Init *Start, Init *List, Init *A, Init *B, Init *Expr, RecTy *Type) + : TypedInit(IK_FoldOpInit, Type), Start(Start), List(List), A(A), B(B), + Expr(Expr) {} + +public: + FoldOpInit(const FoldOpInit &) = delete; + FoldOpInit &operator=(const FoldOpInit &) = delete; + + static bool classof(const Init *I) { return I->getKind() == IK_FoldOpInit; } + + static FoldOpInit *get(Init *Start, Init *List, Init *A, Init *B, Init *Expr, + RecTy *Type); + + void Profile(FoldingSetNodeID &ID) const; + + // Fold - If possible, fold this to a simpler init. Return this if not + // possible to fold. + Init *Fold(Record *CurRec) const; + + bool isComplete() const override { return false; } + + Init *resolveReferences(Resolver &R) const override; + + Init *getBit(unsigned Bit) const override; + + std::string getAsString() const override; +}; + +/// !isa<type>(expr) - Dynamically determine the type of an expression. +class IsAOpInit : public TypedInit, public FoldingSetNode { +private: + RecTy *CheckType; + Init *Expr; + + IsAOpInit(RecTy *CheckType, Init *Expr) + : TypedInit(IK_IsAOpInit, IntRecTy::get()), CheckType(CheckType), + Expr(Expr) {} + +public: + IsAOpInit(const IsAOpInit &) = delete; + IsAOpInit &operator=(const IsAOpInit &) = delete; + + static bool classof(const Init *I) { return I->getKind() == IK_IsAOpInit; } + + static IsAOpInit *get(RecTy *CheckType, Init *Expr); + + void Profile(FoldingSetNodeID &ID) const; + + // Fold - If possible, fold this to a simpler init. Return this if not + // possible to fold. + Init *Fold() const; bool isComplete() const override { return false; } - Init *resolveReferences(Record &R, const RecordVal *RV) const override; + Init *resolveReferences(Resolver &R) const override; + + Init *getBit(unsigned Bit) const override; std::string getAsString() const override; }; @@ -937,19 +1007,12 @@ public: return getNameInit()->getAsUnquotedString(); } - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override; - - RecTy *getFieldType(StringInit *FieldName) const override; - Init *getFieldInit(Record &R, const RecordVal *RV, - StringInit *FieldName) const override; - /// 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. /// - Init *resolveReferences(Record &R, const RecordVal *RV) const override; + Init *resolveReferences(Resolver &R) const override; Init *getBit(unsigned Bit) const override; @@ -957,11 +1020,12 @@ public: }; /// Opcode{0} - Represent access to one bit of a variable or field. -class VarBitInit : public Init { +class VarBitInit final : public TypedInit { TypedInit *TI; unsigned Bit; - VarBitInit(TypedInit *T, unsigned B) : Init(IK_VarBitInit), TI(T), Bit(B) { + VarBitInit(TypedInit *T, unsigned B) + : TypedInit(IK_VarBitInit, BitRecTy::get()), TI(T), Bit(B) { assert(T->getType() && (isa<IntRecTy>(T->getType()) || (isa<BitsRecTy>(T->getType()) && @@ -979,13 +1043,11 @@ public: static VarBitInit *get(TypedInit *T, unsigned B); - Init *convertInitializerTo(RecTy *Ty) const override; - - Init *getBitVar() const override { return TI; } - unsigned getBitNum() const override { return Bit; } + Init *getBitVar() const { return TI; } + unsigned getBitNum() const { return Bit; } std::string getAsString() const override; - Init *resolveReferences(Record &R, const RecordVal *RV) const override; + Init *resolveReferences(Resolver &R) const override; Init *getBit(unsigned B) const override { assert(B < 1 && "Bit index out of range!"); @@ -1020,14 +1082,8 @@ public: TypedInit *getVariable() const { return TI; } unsigned getElementNum() const { return Element; } - /// This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override; - std::string getAsString() const override; - Init *resolveReferences(Record &R, const RecordVal *RV) const override; + Init *resolveReferences(Resolver &R) const override; Init *getBit(unsigned Bit) const override; }; @@ -1038,7 +1094,7 @@ class DefInit : public TypedInit { Record *Def; - DefInit(Record *D, RecordRecTy *T) : TypedInit(IK_DefInit, T), Def(D) {} + explicit DefInit(Record *D); public: DefInit(const DefInit &) = delete; @@ -1057,21 +1113,64 @@ public: //virtual Init *convertInitializerBitRange(ArrayRef<unsigned> Bits); RecTy *getFieldType(StringInit *FieldName) const override; - Init *getFieldInit(Record &R, const RecordVal *RV, - StringInit *FieldName) const override; + bool isConcrete() const override { return true; } std::string getAsString() const override; Init *getBit(unsigned Bit) const override { llvm_unreachable("Illegal bit reference off def"); } +}; - /// This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override { - llvm_unreachable("Illegal element reference off def"); +/// classname<targs...> - Represent an uninstantiated anonymous class +/// instantiation. +class VarDefInit final : public TypedInit, public FoldingSetNode, + public TrailingObjects<VarDefInit, Init *> { + Record *Class; + DefInit *Def = nullptr; // after instantiation + unsigned NumArgs; + + explicit VarDefInit(Record *Class, unsigned N) + : TypedInit(IK_VarDefInit, RecordRecTy::get(Class)), Class(Class), NumArgs(N) {} + + DefInit *instantiate(); + +public: + VarDefInit(const VarDefInit &) = delete; + VarDefInit &operator=(const VarDefInit &) = delete; + + // Do not use sized deallocation due to trailing objects. + void operator delete(void *p) { ::operator delete(p); } + + static bool classof(const Init *I) { + return I->getKind() == IK_VarDefInit; + } + static VarDefInit *get(Record *Class, ArrayRef<Init *> Args); + + void Profile(FoldingSetNodeID &ID) const; + + Init *resolveReferences(Resolver &R) const override; + Init *Fold() const; + + std::string getAsString() const override; + + Init *getArg(unsigned i) const { + assert(i < NumArgs && "Argument index out of range!"); + return getTrailingObjects<Init *>()[i]; + } + + using const_iterator = Init *const *; + + const_iterator args_begin() const { return getTrailingObjects<Init *>(); } + const_iterator args_end () const { return args_begin() + NumArgs; } + + size_t args_size () const { return NumArgs; } + bool args_empty() const { return NumArgs == 0; } + + ArrayRef<Init *> args() const { return makeArrayRef(args_begin(), NumArgs); } + + Init *getBit(unsigned Bit) const override { + llvm_unreachable("Illegal bit reference off anonymous def"); } }; @@ -1095,12 +1194,13 @@ public: static FieldInit *get(Init *R, StringInit *FN); - Init *getBit(unsigned Bit) const override; + Init *getRecord() const { return Rec; } + StringInit *getFieldName() const { return FieldName; } - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override; + Init *getBit(unsigned Bit) const override; - Init *resolveReferences(Record &R, const RecordVal *RV) const override; + Init *resolveReferences(Resolver &R) const override; + Init *Fold(Record *CurRec) const; std::string getAsString() const override { return Rec->getAsString() + "." + FieldName->getValue().str(); @@ -1140,8 +1240,6 @@ public: void Profile(FoldingSetNodeID &ID) const; - Init *convertInitializerTo(RecTy *Ty) const override; - Init *getOperator() const { return Val; } StringInit *getName() const { return ValName; } @@ -1175,8 +1273,9 @@ public: return makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames); } - Init *resolveReferences(Record &R, const RecordVal *RV) const override; + Init *resolveReferences(Resolver &R) const override; + bool isConcrete() const override; std::string getAsString() const override; using const_arg_iterator = SmallVectorImpl<Init*>::const_iterator; @@ -1197,11 +1296,6 @@ public: Init *getBit(unsigned Bit) const override { llvm_unreachable("Illegal bit reference off dag"); } - - Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const override { - llvm_unreachable("Illegal element reference off dag"); - } }; //===----------------------------------------------------------------------===// @@ -1229,14 +1323,7 @@ public: RecTy *getType() const { return TyAndPrefix.getPointer(); } Init *getValue() const { return Value; } - bool setValue(Init *V) { - if (V) { - Value = V->convertInitializerTo(getType()); - return Value == nullptr; - } - Value = nullptr; - return false; - } + bool setValue(Init *V); void dump() const; void print(raw_ostream &OS, bool PrintSem = true) const; @@ -1256,6 +1343,9 @@ class Record { SmallVector<SMLoc, 4> Locs; SmallVector<Init *, 0> TemplateArgs; SmallVector<RecordVal, 0> Values; + + // All superclasses in the inheritance forest in reverse preorder (yes, it + // must be a forest; diamond-shaped inheritance is not allowed). SmallVector<std::pair<Record *, SMRange>, 0> SuperClasses; // Tracks Record instances. Not owned by Record. @@ -1267,49 +1357,37 @@ class Record { unsigned ID; bool IsAnonymous; + bool IsClass; - // Class-instance values can be used by other defs. For example, Struct<i> - // is used here as a template argument to another class: - // - // multiclass MultiClass<int i> { - // def Def : Class<Struct<i>>; - // - // These need to get fully resolved before instantiating any other - // definitions that use them (e.g. Def). However, inside a multiclass they - // can't be immediately resolved so we mark them ResolveFirst to fully - // resolve them later as soon as the multiclass is instantiated. - bool ResolveFirst = false; - - void init(); void checkName(); public: // Constructs a record. explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records, - bool Anonymous = false) : - Name(N), Locs(locs.begin(), locs.end()), TrackedRecords(records), - ID(LastID++), IsAnonymous(Anonymous) { - init(); + bool Anonymous = false, bool Class = false) + : Name(N), Locs(locs.begin(), locs.end()), TrackedRecords(records), + ID(LastID++), IsAnonymous(Anonymous), IsClass(Class) { + checkName(); } explicit Record(StringRef N, ArrayRef<SMLoc> locs, RecordKeeper &records, - bool Anonymous = false) - : Record(StringInit::get(N), locs, records, Anonymous) {} + bool Class = false) + : Record(StringInit::get(N), locs, records, false, Class) {} // When copy-constructing a Record, we must still guarantee a globally unique // ID number. Don't copy TheInit either since it's owned by the original // record. All other fields can be copied normally. - Record(const Record &O) : - Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs), - Values(O.Values), SuperClasses(O.SuperClasses), - TrackedRecords(O.TrackedRecords), ID(LastID++), - IsAnonymous(O.IsAnonymous), ResolveFirst(O.ResolveFirst) { } + Record(const Record &O) + : Name(O.Name), Locs(O.Locs), TemplateArgs(O.TemplateArgs), + Values(O.Values), SuperClasses(O.SuperClasses), + TrackedRecords(O.TrackedRecords), ID(LastID++), + IsAnonymous(O.IsAnonymous), IsClass(O.IsClass) { } static unsigned getNewUID() { return LastID++; } unsigned getID() const { return ID; } - StringRef getName() const; + StringRef getName() const { return cast<StringInit>(Name)->getValue(); } Init *getNameInit() const { return Name; @@ -1322,10 +1400,16 @@ public: void setName(Init *Name); // Also updates RecordKeeper. ArrayRef<SMLoc> getLoc() const { return Locs; } + void appendLoc(SMLoc Loc) { Locs.push_back(Loc); } + + // Make the type that this record should have based on its superclasses. + RecordRecTy *getType(); /// get the corresponding DefInit. DefInit *getDefInit(); + bool isClass() const { return IsClass; } + ArrayRef<Init *> getTemplateArgs() const { return TemplateArgs; } @@ -1336,6 +1420,9 @@ public: return SuperClasses; } + /// Append the direct super classes of this record to Classes. + void getDirectSuperClasses(SmallVectorImpl<Record *> &Classes) const; + bool isTemplateArg(Init *Name) const { for (Init *TA : TemplateArgs) if (TA == Name) return true; @@ -1368,13 +1455,6 @@ public: void addValue(const RecordVal &RV) { assert(getValue(RV.getNameInit()) == nullptr && "Value already added!"); Values.push_back(RV); - if (Values.size() > 1) - // Keep NAME at the end of the list. It makes record dumps a - // bit prettier and allows TableGen tests to be written more - // naturally. Tests can use CHECK-NEXT to look for Record - // fields they expect to see after a def. They can't do that if - // NAME is the first Record field. - std::swap(Values[Values.size() - 2], Values[Values.size() - 1]); } void removeValue(Init *Name) { @@ -1410,13 +1490,24 @@ public: } void addSuperClass(Record *R, SMRange Range) { + assert(!TheInit && "changing type of record after it has been referenced"); assert(!isSubClassOf(R) && "Already subclassing record!"); SuperClasses.push_back(std::make_pair(R, Range)); } /// If there are any field references that refer to fields /// that have been filled in, we can propagate the values now. - void resolveReferences() { resolveReferencesTo(nullptr); } + /// + /// This is a final resolve: any error messages, e.g. due to undefined + /// !cast references, are generated now. + void resolveReferences(); + + /// Apply the resolver to the name of the record as well as to the + /// initializers of all fields of the record except SkipVal. + /// + /// The resolver should not resolve any of the fields itself, to avoid + /// recursion / infinite loops. + void resolveReferences(Resolver &R, const RecordVal *SkipVal = nullptr); /// If anything in this record refers to RV, replace the /// reference to RV with the RHS of RV. If RV is null, we resolve all @@ -1431,14 +1522,6 @@ public: return IsAnonymous; } - bool isResolveFirst() const { - return ResolveFirst; - } - - void setResolveFirst(bool b) { - ResolveFirst = b; - } - void print(raw_ostream &OS) const; void dump() const; @@ -1513,20 +1596,13 @@ public: raw_ostream &operator<<(raw_ostream &OS, const Record &R); -struct MultiClass { - Record Rec; // Placeholder for template args and Name. - using RecordVector = std::vector<std::unique_ptr<Record>>; - RecordVector DefPrototypes; - - void dump() const; - - MultiClass(StringRef Name, SMLoc Loc, RecordKeeper &Records) : - Rec(Name, Loc, Records) {} -}; - class RecordKeeper { + friend class RecordRecTy; using RecordMap = std::map<std::string, std::unique_ptr<Record>>; RecordMap Classes, Defs; + FoldingSet<RecordRecTy> RecordTypePool; + std::map<std::string, Init *> ExtraGlobals; + unsigned AnonCounter = 0; public: const RecordMap &getClasses() const { return Classes; } @@ -1542,6 +1618,13 @@ public: return I == Defs.end() ? nullptr : I->second.get(); } + Init *getGlobal(StringRef Name) const { + if (Record *R = getDef(Name)) + return R->getDefInit(); + auto It = ExtraGlobals.find(Name); + return It == ExtraGlobals.end() ? nullptr : It->second; + } + void addClass(std::unique_ptr<Record> R) { bool Ins = Classes.insert(std::make_pair(R->getName(), std::move(R))).second; @@ -1556,6 +1639,15 @@ public: assert(Ins && "Record already exists"); } + void addExtraGlobal(StringRef Name, Init *I) { + bool Ins = ExtraGlobals.insert(std::make_pair(Name, I)).second; + (void)Ins; + assert(!getDef(Name)); + assert(Ins && "Global already exists"); + } + + Init *getNewAnonymousName(); + //===--------------------------------------------------------------------===// // High-level helper methods, useful for tablegen backends... @@ -1673,10 +1765,142 @@ struct LessRecordRegister { raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK); -/// Return an Init with a qualifier prefix referring -/// to CurRec's name. -Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass, - Init *Name, StringRef Scoper); +//===----------------------------------------------------------------------===// +// Resolvers +//===----------------------------------------------------------------------===// + +/// Interface for looking up the initializer for a variable name, used by +/// Init::resolveReferences. +class Resolver { + Record *CurRec; + bool IsFinal = false; + +public: + explicit Resolver(Record *CurRec) : CurRec(CurRec) {} + virtual ~Resolver() {} + + Record *getCurrentRecord() const { return CurRec; } + + /// Return the initializer for the given variable name (should normally be a + /// StringInit), or nullptr if the name could not be resolved. + virtual Init *resolve(Init *VarName) = 0; + + // Whether bits in a BitsInit should stay unresolved if resolving them would + // result in a ? (UnsetInit). This behavior is used to represent instruction + // encodings by keeping references to unset variables within a record. + virtual bool keepUnsetBits() const { return false; } + + // Whether this is the final resolve step before adding a record to the + // RecordKeeper. Error reporting during resolve and related constant folding + // should only happen when this is true. + bool isFinal() const { return IsFinal; } + + void setFinal(bool Final) { IsFinal = Final; } +}; + +/// Resolve arbitrary mappings. +class MapResolver final : public Resolver { + struct MappedValue { + Init *V; + bool Resolved; + + MappedValue() : V(nullptr), Resolved(false) {} + MappedValue(Init *V, bool Resolved) : V(V), Resolved(Resolved) {} + }; + + DenseMap<Init *, MappedValue> Map; + +public: + explicit MapResolver(Record *CurRec = nullptr) : Resolver(CurRec) {} + + void set(Init *Key, Init *Value) { Map[Key] = {Value, false}; } + + Init *resolve(Init *VarName) override; +}; + +/// Resolve all variables from a record except for unset variables. +class RecordResolver final : public Resolver { + DenseMap<Init *, Init *> Cache; + SmallVector<Init *, 4> Stack; + +public: + explicit RecordResolver(Record &R) : Resolver(&R) {} + + Init *resolve(Init *VarName) override; + + bool keepUnsetBits() const override { return true; } +}; + +/// Resolve all references to a specific RecordVal. +// +// TODO: This is used for resolving references to template arguments, in a +// rather inefficient way. Change those uses to resolve all template +// arguments simultaneously and get rid of this class. +class RecordValResolver final : public Resolver { + const RecordVal *RV; + +public: + explicit RecordValResolver(Record &R, const RecordVal *RV) + : Resolver(&R), RV(RV) {} + + Init *resolve(Init *VarName) override { + if (VarName == RV->getNameInit()) + return RV->getValue(); + return nullptr; + } +}; + +/// Delegate resolving to a sub-resolver, but shadow some variable names. +class ShadowResolver final : public Resolver { + Resolver &R; + DenseSet<Init *> Shadowed; + +public: + explicit ShadowResolver(Resolver &R) + : Resolver(R.getCurrentRecord()), R(R) { + setFinal(R.isFinal()); + } + + void addShadow(Init *Key) { Shadowed.insert(Key); } + + Init *resolve(Init *VarName) override { + if (Shadowed.count(VarName)) + return nullptr; + return R.resolve(VarName); + } +}; + +/// (Optionally) delegate resolving to a sub-resolver, and keep track whether +/// there were unresolved references. +class TrackUnresolvedResolver final : public Resolver { + Resolver *R; + bool FoundUnresolved = false; + +public: + explicit TrackUnresolvedResolver(Resolver *R = nullptr) + : Resolver(R ? R->getCurrentRecord() : nullptr), R(R) {} + + bool foundUnresolved() const { return FoundUnresolved; } + + Init *resolve(Init *VarName) override; +}; + +/// Do not resolve anything, but keep track of whether a given variable was +/// referenced. +class HasReferenceResolver final : public Resolver { + Init *VarNameToTrack; + bool Found = false; + +public: + explicit HasReferenceResolver(Init *VarNameToTrack) + : Resolver(nullptr), VarNameToTrack(VarNameToTrack) {} + + bool found() const { return Found; } + + Init *resolve(Init *VarName) override; +}; + +void EmitJSON(RecordKeeper &RK, raw_ostream &OS); } // end namespace llvm diff --git a/contrib/llvm/include/llvm/TableGen/SearchableTable.td b/contrib/llvm/include/llvm/TableGen/SearchableTable.td index 12aaf6000c31..1089d363eb6f 100644 --- a/contrib/llvm/include/llvm/TableGen/SearchableTable.td +++ b/contrib/llvm/include/llvm/TableGen/SearchableTable.td @@ -8,32 +8,127 @@ //===----------------------------------------------------------------------===// // // This file defines the key top-level classes needed to produce a reasonably -// generic table that can be binary-searched via int and string entries. +// generic table that can be binary-searched. Three types of objects can be +// defined using the classes in this file: // -// Each table must instantiate "Mappingkind", listing the fields that should be -// included and fields that shoould be searchable. Only two kinds of fields are -// searchable at the moment: "strings" (which are compared case-insensitively), -// and "bits". +// 1. (Generic) Enums. By instantiating the GenericEnum class once, an enum with +// the name of the def is generated. It is guarded by the preprocessor define +// GET_name_DECL, where name is the name of the def. // -// For each "MappingKind" the generated header will create GET_MAPPINGKIND_DECL -// and GET_MAPPINGKIND_IMPL guards. +// 2. (Generic) Tables and search indices. By instantiating the GenericTable +// class once, a table with the name of the instantiating def is generated and +// guarded by the GET_name_IMPL preprocessor guard. // -// Inside the DECL guard will be a set of function declarations: -// "lookup{InstanceClass}By{SearchableField}", returning "const {InstanceClass} -// *" and accepting either a StringRef or a uintN_t. Additionally, if -// EnumNameField is still defined, there will be an "enum {InstanceClass}Values" -// allowing C++ code to reference either the primary data table's entries (if -// EnumValueField is not defined) or some other field (e.g. encoding) if it is. -// -// Inside the IMPL guard will be a primary data table "{InstanceClass}sList" and -// as many searchable indexes as requested -// ("{InstanceClass}sBy{SearchableField}"). Additionally implementations of the -// lookup function will be provided. +// Both a primary key and additional secondary keys / search indices can also +// be defined, which result in the generation of lookup functions. Their +// declarations and definitions are all guarded by GET_name_DECL and +// GET_name_IMPL, respectively, where name is the name of the underlying table. // // See AArch64SystemOperands.td and its generated header for example uses. // //===----------------------------------------------------------------------===// +// Define a record derived from this class to generate a generic enum. +// +// The name of the record is used as the type name of the C++ enum. +class GenericEnum { + // Name of a TableGen class. The enum will have one entry for each record + // that derives from that class. + string FilterClass; + + // (Optional) Name of a field that is present in all collected records and + // contains the name of enum entries. + // + // If NameField is not set, the record names will be used instead. + string NameField; + + // (Optional) Name of a field that is present in all collected records and + // contains the numerical value of enum entries. + // + // If ValueField is not set, enum values will be assigned automatically, + // starting at 0, according to a lexicographical sort of the entry names. + string ValueField; +} + +// Define a record derived from this class to generate a generic table. This +// table can have a searchable primary key, and it can also be referenced by +// external search indices. +// +// The name of the record is used as the name of the global primary array of +// entries of the table in C++. +class GenericTable { + // Name of a class. The table will have one entry for each record that + // derives from that class. + string FilterClass; + + // Name of the C++ struct/class type that holds table entries. The + // declaration of this type is not generated automatically. + string CppTypeName = FilterClass; + + // List of the names of fields of collected records that contain the data for + // table entries, in the order that is used for initialization in C++. + // + // For each field of the table named XXX, TableGen will look for a value + // called TypeOf_XXX and use that as a more detailed description of the + // type of the field if present. This is required for fields whose type + // cannot be deduced automatically, such as enum fields. For example: + // + // def MyEnum : GenericEnum { + // let FilterClass = "MyEnum"; + // ... + // } + // + // class MyTableEntry { + // MyEnum V; + // ... + // } + // + // def MyTable : GenericTable { + // let FilterClass = "MyTableEntry"; + // let Fields = ["V", ...]; + // GenericEnum TypeOf_V = MyEnum; + // } + // + // Fields of type bit, bits<N>, string, Intrinsic, and Instruction (or + // derived classes of those) are supported natively. + // + // Additionally, fields of type `code` can appear, where the value is used + // verbatim as an initializer. However, these fields cannot be used as + // search keys. + list<string> Fields; + + // (Optional) List of fields that make up the primary key. + list<string> PrimaryKey; + + // (Optional) Name of the primary key search function. + string PrimaryKeyName; + + // See SearchIndex.EarlyOut + bit PrimaryKeyEarlyOut = 0; +} + +// Define a record derived from this class to generate an additional search +// index for a generic table that has been defined earlier. +// +// The name of the record will be used as the name of the C++ lookup function. +class SearchIndex { + // Table that this search index refers to. + GenericTable Table; + + // List of fields that make up the key. + list<string> Key; + + // If true, the lookup function will check the first field of the key against + // the minimum and maximum values in the index before entering the binary + // search. This is convenient for tables that add extended data for a subset + // of a larger enum-based space, e.g. extended data about a subset of + // instructions. + // + // Can only be used when the first field is an integral (non-string) type. + bit EarlyOut = 0; +} + +// Legacy table type with integrated enum. class SearchableTable { list<string> SearchableFields; string EnumNameField = "Name"; diff --git a/contrib/llvm/include/llvm/Support/CodeGenCWrappers.h b/contrib/llvm/include/llvm/Target/CodeGenCWrappers.h index 47971e80cefb..e9a990569d36 100644 --- a/contrib/llvm/include/llvm/Support/CodeGenCWrappers.h +++ b/contrib/llvm/include/llvm/Target/CodeGenCWrappers.h @@ -1,4 +1,4 @@ -//===- llvm/Support/CodeGenCWrappers.h - CodeGen C Wrappers -----*- C++ -*-===// +//===- llvm/Target/CodeGenCWrappers.h - CodeGen C Wrappers ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_CODEGENCWRAPPERS_H -#define LLVM_SUPPORT_CODEGENCWRAPPERS_H +#ifndef LLVM_TARGET_CODEGENCWRAPPERS_H +#define LLVM_TARGET_CODEGENCWRAPPERS_H #include "llvm-c/TargetMachine.h" #include "llvm/ADT/Optional.h" @@ -56,7 +56,6 @@ inline LLVMCodeModel wrap(CodeModel::Model Model) { } llvm_unreachable("Bad CodeModel!"); } - -} // end llvm namespace +} // namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Target/GenericOpcodes.td b/contrib/llvm/include/llvm/Target/GenericOpcodes.td index 28c90bf22767..d72746a0838a 100644 --- a/contrib/llvm/include/llvm/Target/GenericOpcodes.td +++ b/contrib/llvm/include/llvm/Target/GenericOpcodes.td @@ -126,6 +126,11 @@ def G_BSWAP : GenericInstruction { let hasSideEffects = 0; } +def G_ADDRSPACE_CAST : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = 0; +} //------------------------------------------------------------------------------ // Binary ops. //------------------------------------------------------------------------------ @@ -378,6 +383,12 @@ def G_UITOFP : GenericInstruction { let hasSideEffects = 0; } +def G_FABS : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type0:$src); + let hasSideEffects = 0; +} + //------------------------------------------------------------------------------ // Floating Point Binary ops. //------------------------------------------------------------------------------ @@ -476,6 +487,22 @@ def G_LOAD : GenericInstruction { let mayLoad = 1; } +// Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands. +def G_SEXTLOAD : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins ptype1:$addr); + let hasSideEffects = 0; + let mayLoad = 1; +} + +// Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands. +def G_ZEXTLOAD : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins ptype1:$addr); + let hasSideEffects = 0; + let mayLoad = 1; +} + // Generic store. Expects a MachineMemOperand in addition to explicit operands. def G_STORE : GenericInstruction { let OutOperandList = (outs); diff --git a/contrib/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/contrib/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td index 575f228cd773..d487759a4852 100644 --- a/contrib/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ b/contrib/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -28,6 +28,13 @@ class GINodeEquiv<Instruction i, SDNode node> { // (ISD::LOAD, ISD::ATOMIC_LOAD, ISD::STORE, ISD::ATOMIC_STORE) but GlobalISel // stores this information in the MachineMemoryOperand. bit CheckMMOIsNonAtomic = 0; + + // SelectionDAG has one node for all loads and uses predicates to + // differentiate them. GlobalISel on the other hand uses separate opcodes. + // When this is true, the resulting opcode is G_LOAD/G_SEXTLOAD/G_ZEXTLOAD + // depending on the predicates on the node. + Instruction IfSignExtend = ?; + Instruction IfZeroExtend = ?; } // These are defined in the same order as the G_* instructions. @@ -80,11 +87,15 @@ def : GINodeEquiv<G_BSWAP, bswap>; // Broadly speaking G_LOAD is equivalent to ISD::LOAD but there are some // complications that tablegen must take care of. For example, Predicates such // as isSignExtLoad require that this is not a perfect 1:1 mapping since a -// sign-extending load is (G_SEXT (G_LOAD x)) in GlobalISel. Additionally, +// sign-extending load is (G_SEXTLOAD x) in GlobalISel. Additionally, // G_LOAD handles both atomic and non-atomic loads where as SelectionDAG had // separate nodes for them. This GINodeEquiv maps the non-atomic loads to // G_LOAD with a non-atomic MachineMemOperand. -def : GINodeEquiv<G_LOAD, ld> { let CheckMMOIsNonAtomic = 1; } +def : GINodeEquiv<G_LOAD, ld> { + let CheckMMOIsNonAtomic = 1; + let IfSignExtend = G_SEXTLOAD; + let IfZeroExtend = G_ZEXTLOAD; +} // Broadly speaking G_STORE is equivalent to ISD::STORE but there are some // complications that tablegen must take care of. For example, predicates such // as isTruncStore require that this is not a perfect 1:1 mapping since a @@ -112,3 +123,9 @@ def : GINodeEquiv<G_ATOMICRMW_UMAX, atomic_load_umax>; class GIComplexPatternEquiv<ComplexPattern seldag> { ComplexPattern SelDAGEquivalent = seldag; } + +// Specifies the GlobalISel equivalents for SelectionDAG's SDNodeXForm. +// Should be used on defs that subclass GICustomOperandRenderer<>. +class GISDNodeXFormEquiv<SDNodeXForm seldag> { + SDNodeXForm SelDAGEquivalent = seldag; +} diff --git a/contrib/llvm/include/llvm/Target/GlobalISel/Target.td b/contrib/llvm/include/llvm/Target/GlobalISel/Target.td index fd2ebca86d60..6740f404a9d3 100644 --- a/contrib/llvm/include/llvm/Target/GlobalISel/Target.td +++ b/contrib/llvm/include/llvm/Target/GlobalISel/Target.td @@ -46,3 +46,16 @@ class GIComplexOperandMatcher<LLT type, string matcherfn> { // overwritten. string MatcherFn = matcherfn; } + +// Defines a custom renderer. This is analogous to SDNodeXForm from +// SelectionDAG. Unlike SDNodeXForm, this matches a MachineInstr and +// renders directly to the result instruction without an intermediate node. +// +// Definitions that inherit from this may also inherit from GISDNodeXFormEquiv +// to enable the import of SelectionDAG patterns involving those SDNodeXForms. +class GICustomOperandRenderer<string rendererfn> { + // The function renders the operand(s) of the matched instruction to + // the specified instruction. It should be of the form: + // void render(MachineInstrBuilder &MIB, const MachineInstr &MI) + string RendererFn = rendererfn; +} diff --git a/contrib/llvm/include/llvm/Target/Target.td b/contrib/llvm/include/llvm/Target/Target.td index 82a3be5e63d4..b746505d2a45 100644 --- a/contrib/llvm/include/llvm/Target/Target.td +++ b/contrib/llvm/include/llvm/Target/Target.td @@ -175,6 +175,8 @@ class Register<string n, list<string> altNames = []> { // HWEncoding - The target specific hardware encoding for this register. bits<16> HWEncoding = 0; + + bit isArtificial = 0; } // RegisterWithSubRegs - This can be used to define instances of Register which @@ -382,6 +384,11 @@ class DwarfRegAlias<Register reg> { } //===----------------------------------------------------------------------===// +// Pull in the common support for MCPredicate (portable scheduling predicates). +// +include "llvm/Target/TargetInstrPredicate.td" + +//===----------------------------------------------------------------------===// // Pull in the common support for scheduling // include "llvm/Target/TargetSchedule.td" @@ -435,11 +442,13 @@ class Instruction { bit isIndirectBranch = 0; // Is this instruction an indirect branch? bit isCompare = 0; // Is this instruction a comparison instruction? bit isMoveImm = 0; // Is this instruction a move immediate instruction? + bit isMoveReg = 0; // Is this instruction a move register instruction? bit isBitcast = 0; // Is this instruction a bitcast instruction? bit isSelect = 0; // Is this instruction a select instruction? bit isBarrier = 0; // Can control flow fall through this instruction? bit isCall = 0; // Is this instruction a call instruction? bit isAdd = 0; // Is this instruction an add instruction? + bit isTrap = 0; // Is this instruction a trap instruction? bit canFoldAsLoad = 0; // Can this be folded as a simple memory operand? bit mayLoad = ?; // Is it possible for this inst to read memory? bit mayStore = ?; // Is it possible for this inst to write memory? @@ -566,6 +575,12 @@ class Instruction { /// can be queried via the getNamedOperandIdx() function which is generated /// by TableGen. bit UseNamedOperandTable = 0; + + /// Should FastISel ignore this instruction. For certain ISAs, they have + /// instructions which map to the same ISD Opcode, value type operands and + /// instruction selection predicates. FastISel cannot handle such cases, but + /// SelectionDAG can. + bit FastISelShouldIgnore = 0; } /// PseudoInstExpansion - Expansion information for a pseudo-instruction. @@ -995,6 +1010,12 @@ def DBG_VALUE : StandardPseudoInstruction { let AsmString = "DBG_VALUE"; let hasSideEffects = 0; } +def DBG_LABEL : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins unknown:$label); + let AsmString = "DBG_LABEL"; + let hasSideEffects = 0; +} def REG_SEQUENCE : StandardPseudoInstruction { let OutOperandList = (outs unknown:$dst); let InOperandList = (ins unknown:$supersrc, variable_ops); @@ -1097,7 +1118,7 @@ def PATCHABLE_FUNCTION_ENTER : StandardPseudoInstruction { let hasSideEffects = 0; } def PATCHABLE_RET : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); + let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = "# XRay Function Patchable RET."; let usesCustomInserter = 1; @@ -1114,7 +1135,7 @@ def PATCHABLE_FUNCTION_EXIT : StandardPseudoInstruction { let isReturn = 0; // Original return instruction will follow } def PATCHABLE_TAIL_CALL : StandardPseudoInstruction { - let OutOperandList = (outs unknown:$dst); + let OutOperandList = (outs); let InOperandList = (ins variable_ops); let AsmString = "# XRay Tail Call Exit."; let usesCustomInserter = 1; @@ -1131,6 +1152,16 @@ def PATCHABLE_EVENT_CALL : StandardPseudoInstruction { let mayStore = 1; let hasSideEffects = 1; } +def PATCHABLE_TYPED_EVENT_CALL : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins i16imm:$type, ptr_rc:$event, i32imm:$size); + let AsmString = "# XRay Typed Event Log."; + let usesCustomInserter = 1; + let isCall = 1; + let mayLoad = 1; + let mayStore = 1; + let hasSideEffects = 1; +} def FENTRY_CALL : StandardPseudoInstruction { let OutOperandList = (outs unknown:$dst); let InOperandList = (ins variable_ops); @@ -1140,6 +1171,12 @@ def FENTRY_CALL : StandardPseudoInstruction { let mayStore = 1; let hasSideEffects = 1; } +def ICALL_BRANCH_FUNNEL : StandardPseudoInstruction { + let OutOperandList = (outs unknown:$dst); + let InOperandList = (ins variable_ops); + let AsmString = ""; + let hasSideEffects = 1; +} // Generic opcodes used in GlobalISel. include "llvm/Target/GenericOpcodes.td" @@ -1290,7 +1327,7 @@ class MnemonicAlias<string From, string To, string VariantName = ""> { /// InstAlias - This defines an alternate assembly syntax that is allowed to /// match an instruction that has a different (more canonical) assembly /// representation. -class InstAlias<string Asm, dag Result, int Emit = 1> { +class InstAlias<string Asm, dag Result, int Emit = 1, string VariantName = ""> { string AsmString = Asm; // The .s format to match the instruction with. dag ResultInst = Result; // The MCInst to generate. @@ -1314,7 +1351,7 @@ class InstAlias<string Asm, dag Result, int Emit = 1> { // Assembler variant name to use for this alias. If not specified then // assembler variants will be determined based on AsmString - string AsmVariantName = ""; + string AsmVariantName = VariantName; } //===----------------------------------------------------------------------===// @@ -1362,6 +1399,12 @@ class Target { // AssemblyWriters - The AsmWriter instances available for this target. list<AsmWriter> AssemblyWriters = [DefaultAsmWriter]; + + // AllowRegisterRenaming - Controls whether this target allows + // post-register-allocation renaming of registers. This is done by + // setting hasExtraDefRegAllocReq and hasExtraSrcRegAllocReq to 1 + // for all opcodes if this flag is set to 0. + int AllowRegisterRenaming = 0; } //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/include/llvm/Target/TargetInstrPredicate.td b/contrib/llvm/include/llvm/Target/TargetInstrPredicate.td new file mode 100644 index 000000000000..d38279b0d65e --- /dev/null +++ b/contrib/llvm/include/llvm/Target/TargetInstrPredicate.td @@ -0,0 +1,197 @@ +//===- TargetInstrPredicate.td - ---------------------------*- 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 MCInstPredicate classes and its subclasses. +// +// MCInstPredicate is used to describe constraints on the opcode/operand(s) of +// an instruction. Each MCInstPredicate class has a well-known semantic, and it +// is used by a PredicateExpander to generate code for MachineInstr and/or +// MCInst. +// +// MCInstPredicate definitions can be used to construct MCSchedPredicate +// definitions. An MCSchedPredicate can be used in place of a SchedPredicate +// when defining SchedReadVariant and SchedWriteVariant used by a processor +// scheduling model. +// +// Here is an example of MCInstPredicate definition: +// +// def MCInstPredicateExample : CheckAll<[ +// CheckOpcode<[BLR]>, +// CheckIsRegOperand<0>, +// CheckNot<CheckRegOperand<0, LR>>]>; +// +// Predicate `MCInstPredicateExample` checks that the machine instruction in +// input is a BLR, and that operand at index 0 is register `LR`. +// +// That predicate could be used to rewrite the following definition (from +// AArch64SchedExynosM3.td): +// +// def M3BranchLinkFastPred : SchedPredicate<[{ +// MI->getOpcode() == AArch64::BLR && +// MI->getOperand(0).isReg() && +// MI->getOperand(0).getReg() != AArch64::LR}]>; +// +// MCInstPredicate definitions are used to construct MCSchedPredicate (see the +// definition of class MCSchedPredicate in llvm/Target/TargetSchedule.td). An +// MCSchedPredicate can be used by a `SchedVar` to associate a predicate with a +// list of SchedReadWrites. Note that `SchedVar` are used to create SchedVariant +// definitions. +// +// Each MCInstPredicate class has a well known semantic. For example, +// `CheckOpcode` is only used to check the instruction opcode value. +// +// MCInstPredicate classes allow the definition of predicates in a declarative +// way. These predicates don't require a custom block of C++, and can be used +// to define conditions on instructions without being bound to a particular +// representation (i.e. MachineInstr vs MCInst). +// +// It also means that tablegen backends must know how to parse and expand them +// into code that works on MCInst (or MachineInst). +// +// Instances of class PredicateExpander (see utils/Tablegen/PredicateExpander.h) +// know how to expand a predicate. For each MCInstPredicate class, there must be +// an "expand" method available in the PredicateExpander interface. +// +// For example, a `CheckOpcode` predicate is expanded using method +// `PredicateExpander::expandCheckOpcode()`. +// +// New MCInstPredicate classes must be added to this file. For each new class +// XYZ, an "expandXYZ" method must be added to the PredicateExpander. +// +//===----------------------------------------------------------------------===// + +// Forward declarations. +class Instruction; + +// A generic machine instruction predicate. +class MCInstPredicate; + +class MCTrue : MCInstPredicate; // A predicate that always evaluates to True. +class MCFalse : MCInstPredicate; // A predicate that always evaluates to False. +def TruePred : MCTrue; +def FalsePred : MCFalse; + +// A predicate used to negate the outcome of another predicate. +// It allows to easily express "set difference" operations. For example, it +// makes it easy to describe a check that tests if an opcode is not part of a +// set of opcodes. +class CheckNot<MCInstPredicate P> : MCInstPredicate { + MCInstPredicate Pred = P; +} + +// This class is used as a building block to define predicates on instruction +// operands. It is used to reference a specific machine operand. +class MCOperandPredicate<int Index> : MCInstPredicate { + int OpIndex = Index; +} + +// Return true if machine operand at position `Index` is a register operand. +class CheckIsRegOperand<int Index> : MCOperandPredicate<Index>; + +// Return true if machine operand at position `Index` is an immediate operand. +class CheckIsImmOperand<int Index> : MCOperandPredicate<Index>; + +// Check if machine operands at index `First` and index `Second` both reference +// the same register. +class CheckSameRegOperand<int First, int Second> : MCInstPredicate { + int FirstIndex = First; + int SecondIndex = Second; +} + +// Check that the machine register operand at position `Index` references +// register R. This predicate assumes that we already checked that the machine +// operand at position `Index` is a register operand. +class CheckRegOperand<int Index, Register R> : MCOperandPredicate<Index> { + Register Reg = R; +} + +// Check if register operand at index `Index` is the invalid register. +class CheckInvalidRegOperand<int Index> : MCOperandPredicate<Index>; + +// Check that the operand at position `Index` is immediate `Imm`. +class CheckImmOperand<int Index, int Imm> : MCOperandPredicate<Index> { + int ImmVal = Imm; +} + +// Similar to CheckImmOperand, however the immediate is not a literal number. +// This is useful when we want to compare the value of an operand against an +// enum value, and we know the actual integer value of that enum. +class CheckImmOperand_s<int Index, string Value> : MCOperandPredicate<Index> { + string ImmVal = Value; +} + +// Check that the operand at position `Index` is immediate value zero. +class CheckZeroOperand<int Index> : CheckImmOperand<Index, 0>; + +// Check that the instruction has exactly `Num` operands. +class CheckNumOperands<int Num> : MCInstPredicate { + int NumOps = Num; +} + +// Check that the instruction opcode is one of the opcodes in set `Opcodes`. +// This is a simple set membership query. The easier way to check if an opcode +// is not a member of the set is by using a `CheckNot<CheckOpcode<[...]>>` +// sequence. +class CheckOpcode<list<Instruction> Opcodes> : MCInstPredicate { + list<Instruction> ValidOpcodes = Opcodes; +} + +// Check that the instruction opcode is a pseudo opcode member of the set +// `Opcodes`. This check is always expanded to "false" if we are generating +// code for MCInst. +class CheckPseudo<list<Instruction> Opcodes> : CheckOpcode<Opcodes>; + +// A non-portable predicate. Only to use as a last resort when a block of code +// cannot possibly be converted in a declarative way using other MCInstPredicate +// classes. This check is always expanded to "false" when generating code for +// MCInst. +class CheckNonPortable<string Code> : MCInstPredicate { + string CodeBlock = Code; +} + +// A sequence of predicates. It is used as the base class for CheckAll, and +// CheckAny. It allows to describe compositions of predicates. +class CheckPredicateSequence<list<MCInstPredicate> Preds> : MCInstPredicate { + list<MCInstPredicate> Predicates = Preds; +} + +// Check that all of the predicates in `Preds` evaluate to true. +class CheckAll<list<MCInstPredicate> Sequence> + : CheckPredicateSequence<Sequence>; + +// Check that at least one of the predicates in `Preds` evaluates to true. +class CheckAny<list<MCInstPredicate> Sequence> + : CheckPredicateSequence<Sequence>; + +// Check that a call to method `Name` in class "XXXGenInstrInfo" (where XXX is +// the `Target` name) returns true. +// +// TIIPredicate definitions are used to model calls to the target-specific +// InstrInfo. A TIIPredicate is treated specially by the InstrInfoEmitter +// tablegen backend, which will use it to automatically generate a definition in +// the target specific `GenInstrInfo` class. +class TIIPredicate<string Target, string Name, MCInstPredicate P> : MCInstPredicate { + string TargetName = Target; + string FunctionName = Name; + MCInstPredicate Pred = P; +} + +// A function predicate that takes as input a machine instruction, and returns +// a boolean value. +// +// This predicate is expanded into a function call by the PredicateExpander. +// In particular, the PredicateExpander would either expand this predicate into +// a call to `MCInstFn`, or into a call to`MachineInstrFn` depending on whether +// it is lowering predicates for MCInst or MachineInstr. +// +// In this context, `MCInstFn` and `MachineInstrFn` are both function names. +class CheckFunctionPredicate<string MCInstFn, string MachineInstrFn> : MCInstPredicate { + string MCInstFnName = MCInstFn; + string MachineInstrFnName = MachineInstrFn; +} diff --git a/contrib/llvm/include/llvm/Target/TargetItinerary.td b/contrib/llvm/include/llvm/Target/TargetItinerary.td index 3b1998dfb1ff..182054d8444e 100644 --- a/contrib/llvm/include/llvm/Target/TargetItinerary.td +++ b/contrib/llvm/include/llvm/Target/TargetItinerary.td @@ -44,9 +44,9 @@ def Reserved : ReservationKind<1>; // the execution of an instruction. Cycles represents the number of // discrete time slots needed to complete the stage. Units represent // the choice of functional units that can be used to complete the -// stage. Eg. IntUnit1, IntUnit2. NextCycles indicates how many -// cycles should elapse from the start of this stage to the start of -// the next stage in the itinerary. For example: +// stage. Eg. IntUnit1, IntUnit2. TimeInc indicates how many cycles +// should elapse from the start of this stage to the start of the next +// stage in the itinerary. For example: // // A stage is specified in one of two ways: // diff --git a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFile.h b/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h index fe77c2954129..dbdfd4139a0f 100644 --- a/contrib/llvm/include/llvm/CodeGen/TargetLoweringObjectFile.h +++ b/contrib/llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/TargetLoweringObjectFile.h - Object Info ---*- C++ -*-===// +//===-- llvm/Target/TargetLoweringObjectFile.h - Object Info ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -71,8 +71,7 @@ public: const MCSymbol *Sym) const; /// Emit the module-level metadata that the platform cares about. - virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M, - const TargetMachine &TM) const {} + virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {} /// Given a constant with the SectionKind, return a section that it should be /// placed in. @@ -149,7 +148,7 @@ public: return StaticDtorSection; } - /// \brief Create a symbol reference to describe the given TLS variable when + /// Create a symbol reference to describe the given TLS variable when /// emitting the address in debug info. virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const; @@ -159,19 +158,19 @@ public: return nullptr; } - /// \brief Target supports replacing a data "PC"-relative access to a symbol + /// Target supports replacing a data "PC"-relative access to a symbol /// through another symbol, by accessing the later via a GOT entry instead? bool supportIndirectSymViaGOTPCRel() const { return SupportIndirectSymViaGOTPCRel; } - /// \brief Target GOT "PC"-relative relocation supports encoding an additional + /// Target GOT "PC"-relative relocation supports encoding an additional /// binary expression with an offset? bool supportGOTPCRelWithOffset() const { return SupportGOTPCRelWithOffset; } - /// \brief Get the target specific PC relative GOT entry relocation + /// Get the target specific PC relative GOT entry relocation virtual const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym, const MCValue &MV, int64_t Offset, @@ -183,6 +182,9 @@ public: virtual void emitLinkerFlagsForGlobal(raw_ostream &OS, const GlobalValue *GV) const {} + virtual void emitLinkerFlagsForUsed(raw_ostream &OS, + const GlobalValue *GV) const {} + protected: virtual MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, diff --git a/contrib/llvm/include/llvm/Target/TargetMachine.h b/contrib/llvm/include/llvm/Target/TargetMachine.h index 97442f9a7849..1ca68c8df63a 100644 --- a/contrib/llvm/include/llvm/Target/TargetMachine.h +++ b/contrib/llvm/include/llvm/Target/TargetMachine.h @@ -138,9 +138,23 @@ public: /// Get the pointer size for this target. /// /// This is the only time the DataLayout in the TargetMachine is used. - unsigned getPointerSize() const { return DL.getPointerSize(); } + unsigned getPointerSize(unsigned AS) const { + return DL.getPointerSize(AS); + } + + unsigned getPointerSizeInBits(unsigned AS) const { + return DL.getPointerSizeInBits(AS); + } + + unsigned getProgramPointerSize() const { + return DL.getPointerSize(DL.getProgramAddressSpace()); + } - /// \brief Reset the target options based on the function's attributes. + unsigned getAllocaPointerSize() const { + return DL.getPointerSize(DL.getAllocaAddrSpace()); + } + + /// Reset the target options based on the function's attributes. // FIXME: Remove TargetOptions that affect per-function code generation // from TargetMachine. void resetTargetOptions(const Function &F) const; @@ -172,18 +186,28 @@ public: bool shouldAssumeDSOLocal(const Module &M, const GlobalValue *GV) const; + /// Returns true if this target uses emulated TLS. + bool useEmulatedTLS() const; + /// Returns the TLS model which should be used for the given global variable. TLSModel::Model getTLSModel(const GlobalValue *GV) const; /// Returns the optimization level: None, Less, Default, or Aggressive. CodeGenOpt::Level getOptLevel() const; - /// \brief Overrides the optimization level. + /// Overrides the optimization level. void setOptLevel(CodeGenOpt::Level Level); void setFastISel(bool Enable) { Options.EnableFastISel = Enable; } bool getO0WantsFastISel() { return O0WantsFastISel; } void setO0WantsFastISel(bool Enable) { O0WantsFastISel = Enable; } + void setGlobalISel(bool Enable) { Options.EnableGlobalISel = Enable; } + void setMachineOutliner(bool Enable) { + Options.EnableMachineOutliner = Enable; + } + void setSupportsDefaultOutlining(bool Enable) { + Options.SupportsDefaultOutlining = Enable; + } bool shouldPrintMachineCode() const { return Options.PrintMachineCode; } @@ -201,14 +225,14 @@ public: return Options.FunctionSections; } - /// \brief Get a \c TargetIRAnalysis appropriate for the target. + /// Get a \c TargetIRAnalysis appropriate for the target. /// /// This is used to construct the new pass manager's target IR analysis pass, /// set up appropriately for this target machine. Even the old pass manager /// uses this to answer queries about the IR. TargetIRAnalysis getTargetIRAnalysis(); - /// \brief Return a TargetTransformInfo for a given function. + /// Return a TargetTransformInfo for a given function. /// /// The returned TargetTransformInfo is specialized to the subtarget /// corresponding to \p F. @@ -234,7 +258,7 @@ public: /// \p MMI is an optional parameter that, if set to non-nullptr, /// will be used to set the MachineModuloInfo for this PM. virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &, - CodeGenFileType, + raw_pwrite_stream *, CodeGenFileType, bool /*DisableVerify*/ = true, MachineModuleInfo *MMI = nullptr) { return true; @@ -281,14 +305,14 @@ public: class LLVMTargetMachine : public TargetMachine { protected: // Can only create subclasses. LLVMTargetMachine(const Target &T, StringRef DataLayoutString, - const Triple &TargetTriple, StringRef CPU, StringRef FS, + const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); void initAsmInfo(); public: - /// \brief Get a TargetTransformInfo implementation for the target. + /// Get a TargetTransformInfo implementation for the target. /// /// The TTI returned uses the common code generator to answer queries about /// the IR. @@ -303,7 +327,8 @@ public: /// \p MMI is an optional parameter that, if set to non-nullptr, /// will be used to set the MachineModuloInfofor this PM. bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out, - CodeGenFileType FileType, bool DisableVerify = true, + raw_pwrite_stream *DwoOut, CodeGenFileType FileType, + bool DisableVerify = true, MachineModuleInfo *MMI = nullptr) override; /// Add passes to the specified pass manager to get machine code emitted with @@ -311,7 +336,7 @@ public: /// fills the MCContext Ctx pointer which can be used to build custom /// MCStreamer. bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, - raw_pwrite_stream &OS, + raw_pwrite_stream &Out, bool DisableVerify = true) override; /// Returns true if the target is expected to pass all machine verifier @@ -320,10 +345,11 @@ public: /// EXPENSIVE_CHECKS is enabled. virtual bool isMachineVerifierClean() const { return true; } - /// \brief Adds an AsmPrinter pass to the pipeline that prints assembly or + /// Adds an AsmPrinter pass to the pipeline that prints assembly or /// machine code from the MI representation. bool addAsmPrinter(PassManagerBase &PM, raw_pwrite_stream &Out, - CodeGenFileType FileTYpe, MCContext &Context); + raw_pwrite_stream *DwoOut, CodeGenFileType FileTYpe, + MCContext &Context); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Target/TargetOptions.h b/contrib/llvm/include/llvm/Target/TargetOptions.h index 70fac7833f32..07ed773de55e 100644 --- a/contrib/llvm/include/llvm/Target/TargetOptions.h +++ b/contrib/llvm/include/llvm/Target/TargetOptions.h @@ -104,11 +104,14 @@ namespace llvm { NoSignedZerosFPMath(false), HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false), GuaranteedTailCallOpt(false), StackSymbolOrdering(true), - EnableFastISel(false), UseInitArray(false), + EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false), DisableIntegratedAS(false), RelaxELFRelocations(false), FunctionSections(false), DataSections(false), - UniqueSectionNames(true), TrapUnreachable(false), EmulatedTLS(false), - EnableIPRA(false), EmitStackSizeSection(false) {} + UniqueSectionNames(true), TrapUnreachable(false), + NoTrapAfterNoreturn(false), EmulatedTLS(false), + ExplicitEmulatedTLS(false), EnableIPRA(false), + EmitStackSizeSection(false), EnableMachineOutliner(false), + SupportsDefaultOutlining(false), EmitAddrsig(false) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// option is specified on the command line, and should enable debugging @@ -186,6 +189,9 @@ namespace llvm { /// compile time. unsigned EnableFastISel : 1; + /// EnableGlobalISel - This flag enables global instruction selection. + unsigned EnableGlobalISel : 1; + /// UseInitArray - Use .init_array instead of .ctors for static /// constructors. unsigned UseInitArray : 1; @@ -209,16 +215,32 @@ namespace llvm { /// Emit target-specific trap instruction for 'unreachable' IR instructions. unsigned TrapUnreachable : 1; + /// Do not emit a trap instruction for 'unreachable' IR instructions behind + /// noreturn calls, even if TrapUnreachable is true. + unsigned NoTrapAfterNoreturn : 1; + /// EmulatedTLS - This flag enables emulated TLS model, using emutls /// function in the runtime library.. unsigned EmulatedTLS : 1; + /// Whether -emulated-tls or -no-emulated-tls is set. + unsigned ExplicitEmulatedTLS : 1; + /// This flag enables InterProcedural Register Allocation (IPRA). unsigned EnableIPRA : 1; /// Emit section containing metadata on function stack sizes. unsigned EmitStackSizeSection : 1; + /// Enables the MachineOutliner pass. + unsigned EnableMachineOutliner : 1; + + /// Set if the target supports default outlining behaviour. + unsigned SupportsDefaultOutlining : 1; + + /// Emit address-significance table. + unsigned EmitAddrsig : 1; + /// FloatABIType - This setting is set by -float-abi=xxx option is specfied /// on the command line. This setting may either be Default, Soft, or Hard. /// Default selects the target's default behavior. Soft selects the ABI for diff --git a/contrib/llvm/include/llvm/Target/TargetSchedule.td b/contrib/llvm/include/llvm/Target/TargetSchedule.td index 7b00c9420e35..6fd2d5b78e54 100644 --- a/contrib/llvm/include/llvm/Target/TargetSchedule.td +++ b/contrib/llvm/include/llvm/Target/TargetSchedule.td @@ -99,6 +99,12 @@ class SchedMachineModel { // resulting from changes to the instruction definitions. bit CompleteModel = 1; + // Indicates that we should do full overlap checking for multiple InstrRWs + // definining the same instructions within the same SchedMachineModel. + // FIXME: Remove when all in tree targets are clean with the full check + // enabled. + bit FullInstRWOverlapCheck = 1; + // A processor may only implement part of published ISA, due to either new ISA // extensions, (e.g. Pentium 4 doesn't have AVX) or implementation // (ARM/MIPS/PowerPC/SPARC soft float cores). @@ -175,9 +181,9 @@ class ProcResourceKind; // BufferSize=1. // // SchedModel ties these units to a processor for any stand-alone defs -// of this class. Instances of subclass ProcResource will be automatically -// attached to a processor, so SchedModel is not needed. -class ProcResourceUnits<ProcResourceKind kind, int num> { +// of this class. +class ProcResourceUnits<ProcResourceKind kind, int num, + list<string> pfmCounters> { ProcResourceKind Kind = kind; int NumUnits = num; ProcResourceKind Super = ?; @@ -192,8 +198,8 @@ def EponymousProcResourceKind : ProcResourceKind; // Subtargets typically define processor resource kind and number of // units in one place. -class ProcResource<int num> : ProcResourceKind, - ProcResourceUnits<EponymousProcResourceKind, num>; +class ProcResource<int num, list<string> pfmCounters = []> : ProcResourceKind, + ProcResourceUnits<EponymousProcResourceKind, num, pfmCounters>; class ProcResGroup<list<ProcResource> resources> : ProcResourceKind { list<ProcResource> Resources = resources; @@ -275,10 +281,9 @@ class ProcWriteResources<list<ProcResourceKind> resources> { // ProcResources indicates the set of resources consumed by the write. // Optionally, ResourceCycles indicates the number of cycles the // resource is consumed. Each ResourceCycles item is paired with the -// ProcResource item at the same position in its list. Since -// ResourceCycles are rarely specialized, the list may be -// incomplete. By default, resources are consumed for a single cycle, -// regardless of latency, which models a fully pipelined processing +// ProcResource item at the same position in its list. ResourceCycles +// can be `[]`: in that case, all resources are consumed for a single +// cycle, regardless of latency, which models a fully pipelined processing // unit. A value of 0 for ResourceCycles means that the resource must // be available but is not consumed, which is only relevant for // unbuffered resources. @@ -349,13 +354,23 @@ class PredicateProlog<code c> { code Code = c; } +// Base class for scheduling predicates. +class SchedPredicateBase; + +// A scheduling predicate whose logic is defined by a MCInstPredicate. +// This can directly be used by SchedWriteVariant definitions. +class MCSchedPredicate<MCInstPredicate P> : SchedPredicateBase { + MCInstPredicate Pred = P; + SchedMachineModel SchedModel = ?; +} + // Define a predicate to determine which SchedVariant applies to a // particular MachineInstr. The code snippet is used as an // if-statement's expression. Available variables are MI, SchedModel, // and anything defined in a PredicateProlog. // // SchedModel silences warnings but is ignored. -class SchedPredicate<code pred> { +class SchedPredicate<code pred> : SchedPredicateBase { SchedMachineModel SchedModel = ?; code Predicate = pred; } @@ -370,8 +385,8 @@ def NoSchedPred : SchedPredicate<[{true}]>; // operands. In this case, latency is not additive. If the current Variant // is already part of a Sequence, then that entire chain leading up to // the Variant is distributed over the variadic operands. -class SchedVar<SchedPredicate pred, list<SchedReadWrite> selected> { - SchedPredicate Predicate = pred; +class SchedVar<SchedPredicateBase pred, list<SchedReadWrite> selected> { + SchedPredicateBase Predicate = pred; list<SchedReadWrite> Selected = selected; } @@ -437,3 +452,102 @@ class SchedAlias<SchedReadWrite match, SchedReadWrite alias> { SchedReadWrite AliasRW = alias; SchedMachineModel SchedModel = ?; } + +// Allow the definition of processor register files for register renaming +// purposes. +// +// Each processor register file declares: +// - The set of registers that can be renamed. +// - The number of physical registers which can be used for register renaming +// purpose. +// - The cost of a register rename. +// +// The cost of a rename is the number of physical registers allocated by the +// register alias table to map the new definition. By default, register can be +// renamed at the cost of a single physical register. Note that register costs +// are defined at register class granularity (see field `Costs`). +// +// The set of registers that are subject to register renaming is declared using +// a list of register classes (see field `RegClasses`). An empty list of +// register classes means: all the logical registers defined by the target can +// be fully renamed. +// +// A register R can be renamed if its register class appears in the `RegClasses` +// set. When R is written, a new alias is allocated at the cost of one or more +// physical registers; as a result, false dependencies on R are removed. +// +// A sub-register V of register R is implicitly part of the same register file. +// However, V is only renamed if its register class is part of `RegClasses`. +// Otherwise, the processor keeps it (as well as any other different part +// of R) together with R, and a write of V always causes a compulsory read of R. +// +// This is what happens for example on AMD processors (at least from Bulldozer +// onwards), where AL and AH are not treated as independent from AX, and AX is +// not treated as independent from EAX. A write to AL has an implicity false +// dependency on the last write to EAX (or a portion of EAX). As a consequence, +// a write to AL cannot go in parallel with a write to AH. +// +// There is no false dependency if the partial register write belongs to a +// register class that is in `RegClasses`. +// There is also no penalty for writes that "clear the content a super-register" +// (see MC/MCInstrAnalysis.h - method MCInstrAnalysis::clearsSuperRegisters()). +// On x86-64, 32-bit GPR writes implicitly zero the upper half of the underlying +// physical register, effectively removing any false dependencies with the +// previous register definition. +// +// TODO: This implementation assumes that there is no limit in the number of +// renames per cycle, which might not be true for all hardware or register +// classes. Also, there is no limit to how many times the same logical register +// can be renamed during the same cycle. +// +// TODO: we don't currently model merge penalties for the case where a write to +// a part of a register is followed by a read from a larger part of the same +// register. On some Intel chips, different parts of a GPR can be stored in +// different physical registers. However, there is a cost to pay for when the +// partial write is combined with the previous super-register definition. We +// should add support for these cases, and correctly model merge problems with +// partial register accesses. +class RegisterFile<int numPhysRegs, list<RegisterClass> Classes = [], + list<int> Costs = []> { + list<RegisterClass> RegClasses = Classes; + list<int> RegCosts = Costs; + int NumPhysRegs = numPhysRegs; + SchedMachineModel SchedModel = ?; +} + +// Describe the retire control unit. +// A retire control unit specifies the size of the reorder buffer, as well as +// the maximum number of opcodes that can be retired every cycle. +// A value less-than-or-equal-to zero for field 'ReorderBufferSize' means: "the +// size is unknown". The idea is that external tools can fall-back to using +// field MicroOpBufferSize in SchedModel if the reorder buffer size is unknown. +// A zero or negative value for field 'MaxRetirePerCycle' means "no +// restrictions on the number of instructions retired per cycle". +// Models can optionally specify up to one instance of RetireControlUnit per +// scheduling model. +class RetireControlUnit<int bufferSize, int retirePerCycle> { + int ReorderBufferSize = bufferSize; + int MaxRetirePerCycle = retirePerCycle; + SchedMachineModel SchedModel = ?; +} + +// Allow the definition of hardware counters. +class PfmCounter { + SchedMachineModel SchedModel = ?; +} + +// Each processor can define how to measure cycles by defining a +// PfmCycleCounter. +class PfmCycleCounter<string counter> : PfmCounter { + string Counter = counter; +} + +// Each ProcResourceUnits can define how to measure issued uops by defining +// a PfmIssueCounter. +class PfmIssueCounter<ProcResourceUnits resource, list<string> counters> + : PfmCounter{ + // The resource units on which uops are issued. + ProcResourceUnits Resource = resource; + // The list of counters that measure issue events. + list<string> Counters = counters; +} diff --git a/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td b/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td index f6162377b8b7..4ba4d821225d 100644 --- a/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td +++ b/contrib/llvm/include/llvm/Target/TargetSelectionDAG.td @@ -485,6 +485,8 @@ def atomic_load_sub : SDNode<"ISD::ATOMIC_LOAD_SUB" , SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; def atomic_load_and : SDNode<"ISD::ATOMIC_LOAD_AND" , SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; +def atomic_load_clr : SDNode<"ISD::ATOMIC_LOAD_CLR" , SDTAtomic2, + [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; def atomic_load_or : SDNode<"ISD::ATOMIC_LOAD_OR" , SDTAtomic2, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; def atomic_load_xor : SDNode<"ISD::ATOMIC_LOAD_XOR" , SDTAtomic2, @@ -613,14 +615,18 @@ class CodePatPred<code predicate> : PatPred { // compact and readable. // -/// PatFrag - Represents a pattern fragment. This can match something on the -/// DAG, from a single node to multiple nested other fragments. +/// PatFrags - Represents a set of pattern fragments. Each single fragment +/// can match something on the DAG, from a single node to multiple nested other +/// fragments. The whole set of fragments matches if any of the single +/// fragemnts match. This allows e.g. matching and "add with overflow" and +/// a regular "add" with the same fragment set. /// -class PatFrag<dag ops, dag frag, code pred = [{}], - SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator { +class PatFrags<dag ops, list<dag> frags, code pred = [{}], + SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator { dag Operands = ops; - dag Fragment = frag; + list<dag> Fragments = frags; code PredicateCode = pred; + code GISelPredicateCode = [{}]; code ImmediateCode = [{}]; SDNodeXForm OperandTransform = xform; @@ -679,6 +685,11 @@ class PatFrag<dag ops, dag frag, code pred = [{}], ValueType ScalarMemoryVT = ?; } +// PatFrag - A version of PatFrags matching only a single fragment. +class PatFrag<dag ops, dag frag, code pred = [{}], + SDNodeXForm xform = NOOP_SDNodeXForm> + : PatFrags<ops, [frag], pred, 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. @@ -1130,27 +1141,27 @@ def setne : PatFrag<(ops node:$lhs, node:$rhs), multiclass binary_atomic_op_ord<SDNode atomic_op> { def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$val)> { + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { let IsAtomic = 1; let IsAtomicOrderingMonotonic = 1; } def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$val)> { + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { let IsAtomic = 1; let IsAtomicOrderingAcquire = 1; } def #NAME#_release : PatFrag<(ops node:$ptr, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$val)> { + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { let IsAtomic = 1; let IsAtomicOrderingRelease = 1; } def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$val)> { + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { let IsAtomic = 1; let IsAtomicOrderingAcquireRelease = 1; } def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$val)> { + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> { let IsAtomic = 1; let IsAtomicOrderingSequentiallyConsistent = 1; } @@ -1158,27 +1169,27 @@ multiclass binary_atomic_op_ord<SDNode atomic_op> { multiclass ternary_atomic_op_ord<SDNode atomic_op> { def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> { + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { let IsAtomic = 1; let IsAtomicOrderingMonotonic = 1; } def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> { + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { let IsAtomic = 1; let IsAtomicOrderingAcquire = 1; } def #NAME#_release : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> { + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { let IsAtomic = 1; let IsAtomicOrderingRelease = 1; } def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> { + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { let IsAtomic = 1; let IsAtomicOrderingAcquireRelease = 1; } def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$cmp, node:$val), - (!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> { + (!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> { let IsAtomic = 1; let IsAtomicOrderingSequentiallyConsistent = 1; } @@ -1244,6 +1255,7 @@ defm atomic_load_add : binary_atomic_op<atomic_load_add>; defm atomic_swap : binary_atomic_op<atomic_swap>; defm atomic_load_sub : binary_atomic_op<atomic_load_sub>; defm atomic_load_and : binary_atomic_op<atomic_load_and>; +defm atomic_load_clr : binary_atomic_op<atomic_load_clr>; defm atomic_load_or : binary_atomic_op<atomic_load_or>; defm atomic_load_xor : binary_atomic_op<atomic_load_xor>; defm atomic_load_nand : binary_atomic_op<atomic_load_nand>; diff --git a/contrib/llvm/include/llvm/Testing/Support/Error.h b/contrib/llvm/include/llvm/Testing/Support/Error.h index 50889b9c66f5..0e5b5403ce87 100644 --- a/contrib/llvm/include/llvm/Testing/Support/Error.h +++ b/contrib/llvm/include/llvm/Testing/Support/Error.h @@ -38,7 +38,7 @@ public: bool MatchAndExplain(const ExpectedHolder<T> &Holder, testing::MatchResultListener *listener) const override { - if (!Holder.Success) + if (!Holder.Success()) return false; bool result = Matcher.MatchAndExplain(*Holder.Exp, listener); @@ -82,6 +82,53 @@ private: M Matcher; }; +template <typename InfoT> +class ErrorMatchesMono : public testing::MatcherInterface<const ErrorHolder &> { +public: + explicit ErrorMatchesMono(Optional<testing::Matcher<InfoT &>> Matcher) + : Matcher(std::move(Matcher)) {} + + bool MatchAndExplain(const ErrorHolder &Holder, + testing::MatchResultListener *listener) const override { + if (Holder.Success()) + return false; + + if (Holder.Infos.size() > 1) { + *listener << "multiple errors"; + return false; + } + + auto &Info = *Holder.Infos[0]; + if (!Info.isA<InfoT>()) { + *listener << "Error was not of given type"; + return false; + } + + if (!Matcher) + return true; + + return Matcher->MatchAndExplain(static_cast<InfoT &>(Info), listener); + } + + void DescribeTo(std::ostream *OS) const override { + *OS << "failed with Error of given type"; + if (Matcher) { + *OS << " and the error "; + Matcher->DescribeTo(OS); + } + } + + void DescribeNegationTo(std::ostream *OS) const override { + *OS << "succeeded or did not fail with the error of given type"; + if (Matcher) { + *OS << " or the error "; + Matcher->DescribeNegationTo(OS); + } + } + +private: + Optional<testing::Matcher<InfoT &>> Matcher; +}; } // namespace detail #define EXPECT_THAT_ERROR(Err, Matcher) \ @@ -94,8 +141,19 @@ private: #define ASSERT_THAT_EXPECTED(Err, Matcher) \ ASSERT_THAT(llvm::detail::TakeExpected(Err), Matcher) -MATCHER(Succeeded, "") { return arg.Success; } -MATCHER(Failed, "") { return !arg.Success; } +MATCHER(Succeeded, "") { return arg.Success(); } +MATCHER(Failed, "") { return !arg.Success(); } + +template <typename InfoT> +testing::Matcher<const detail::ErrorHolder &> Failed() { + return MakeMatcher(new detail::ErrorMatchesMono<InfoT>(None)); +} + +template <typename InfoT, typename M> +testing::Matcher<const detail::ErrorHolder &> Failed(M Matcher) { + return MakeMatcher(new detail::ErrorMatchesMono<InfoT>( + testing::SafeMatcherCast<InfoT &>(Matcher))); +} template <typename M> detail::ValueMatchesPoly<M> HasValue(M Matcher) { diff --git a/contrib/llvm/include/llvm/Testing/Support/SupportHelpers.h b/contrib/llvm/include/llvm/Testing/Support/SupportHelpers.h index d7f0c7142b2c..96264ac81dc4 100644 --- a/contrib/llvm/include/llvm/Testing/Support/SupportHelpers.h +++ b/contrib/llvm/include/llvm/Testing/Support/SupportHelpers.h @@ -17,8 +17,9 @@ namespace llvm { namespace detail { struct ErrorHolder { - bool Success; - std::string Message; + std::vector<std::shared_ptr<ErrorInfoBase>> Infos; + + bool Success() const { return Infos.empty(); } }; template <typename T> struct ExpectedHolder : public ErrorHolder { @@ -29,15 +30,22 @@ template <typename T> struct ExpectedHolder : public ErrorHolder { }; inline void PrintTo(const ErrorHolder &Err, std::ostream *Out) { - *Out << (Err.Success ? "succeeded" : "failed"); - if (!Err.Success) { - *Out << " (" << StringRef(Err.Message).trim().str() << ")"; + raw_os_ostream OS(*Out); + OS << (Err.Success() ? "succeeded" : "failed"); + if (!Err.Success()) { + const char *Delim = " ("; + for (const auto &Info : Err.Infos) { + OS << Delim; + Delim = "; "; + Info->log(OS); + } + OS << ")"; } } template <typename T> void PrintTo(const ExpectedHolder<T> &Item, std::ostream *Out) { - if (Item.Success) { + if (Item.Success()) { *Out << "succeeded with value " << ::testing::PrintToString(*Item.Exp); } else { PrintTo(static_cast<const ErrorHolder &>(Item), Out); diff --git a/contrib/llvm/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h b/contrib/llvm/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h new file mode 100644 index 000000000000..f970acdc741f --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h @@ -0,0 +1,41 @@ +//===- AggressiveInstCombine.h - AggressiveInstCombine 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 the primary interface to the aggressive instcombine pass. +/// This pass is suitable for use in the new pass manager. For a pass that works +/// with the legacy pass manager, please use +/// \c createAggressiveInstCombinerPass(). +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_AGGRESSIVE_INSTCOMBINE_INSTCOMBINE_H +#define LLVM_TRANSFORMS_AGGRESSIVE_INSTCOMBINE_INSTCOMBINE_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class AggressiveInstCombinePass + : public PassInfoMixin<AggressiveInstCombinePass> { + +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +//===----------------------------------------------------------------------===// +// +// AggressiveInstCombiner - Combine expression patterns to form expressions with +// fewer, simple instructions. This pass does not modify the CFG. +// +FunctionPass *createAggressiveInstCombinerPass(); +} + +#endif diff --git a/contrib/llvm/include/llvm/Transforms/IPO.h b/contrib/llvm/include/llvm/Transforms/IPO.h index ce20a726b783..ebc76bf82118 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO.h +++ b/contrib/llvm/include/llvm/Transforms/IPO.h @@ -15,6 +15,7 @@ #ifndef LLVM_TRANSFORMS_IPO_H #define LLVM_TRANSFORMS_IPO_H +#include "llvm/ADT/SmallVector.h" #include <functional> #include <vector> @@ -44,10 +45,6 @@ ModulePass *createStripSymbolsPass(bool OnlyDebugInfo = false); // ModulePass *createStripNonDebugSymbolsPass(); -/// This function returns a new pass that downgrades the debug info in the -/// module to line tables only. -ModulePass *createStripNonLineTableDebugInfoPass(); - //===----------------------------------------------------------------------===// // // This pass removes llvm.dbg.declare intrinsics. @@ -179,10 +176,13 @@ Pass *createLoopExtractorPass(); /// Pass *createSingleLoopExtractorPass(); -/// createBlockExtractorPass - This pass extracts all blocks (except those -/// specified in the argument list) from the functions in the module. +/// createBlockExtractorPass - This pass extracts all the specified blocks +/// from the functions in the module. /// ModulePass *createBlockExtractorPass(); +ModulePass * +createBlockExtractorPass(const SmallVectorImpl<BasicBlock *> &BlocksToExtract, + bool EraseFunctions); /// createStripDeadPrototypesPass - This pass removes any function declarations /// (prototypes) that are not used. @@ -207,11 +207,6 @@ ModulePass *createMergeFunctionsPass(); ModulePass *createPartialInliningPass(); //===----------------------------------------------------------------------===// -// createMetaRenamerPass - Rename everything with metasyntatic names. -// -ModulePass *createMetaRenamerPass(); - -//===----------------------------------------------------------------------===// /// createBarrierNoopPass - This pass is purely a module pass barrier in a pass /// manager. ModulePass *createBarrierNoopPass(); @@ -227,7 +222,7 @@ enum class PassSummaryAction { Export, ///< Export information to summary. }; -/// \brief This pass lowers type metadata and the llvm.type.test intrinsic to +/// This pass lowers type metadata and the llvm.type.test intrinsic to /// bitsets. /// /// The behavior depends on the summary arguments: @@ -240,10 +235,10 @@ enum class PassSummaryAction { ModulePass *createLowerTypeTestsPass(ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary); -/// \brief This pass export CFI checks for use by external modules. +/// This pass export CFI checks for use by external modules. ModulePass *createCrossDSOCFIPass(); -/// \brief This pass implements whole-program devirtualization using type +/// This pass implements whole-program devirtualization using type /// metadata. /// /// The behavior depends on the summary arguments: diff --git a/contrib/llvm/include/llvm/Transforms/IPO/AlwaysInliner.h b/contrib/llvm/include/llvm/Transforms/IPO/AlwaysInliner.h index 15c80357e4a8..b52c0fdbd2c9 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO/AlwaysInliner.h +++ b/contrib/llvm/include/llvm/Transforms/IPO/AlwaysInliner.h @@ -27,7 +27,13 @@ namespace llvm { /// be the simplest possible pass to remove always_inline function definitions' /// uses by inlining them. The \c GlobalDCE pass can be used to remove these /// functions once all users are gone. -struct AlwaysInlinerPass : PassInfoMixin<AlwaysInlinerPass> { +class AlwaysInlinerPass : public PassInfoMixin<AlwaysInlinerPass> { + bool InsertLifetime; + +public: + AlwaysInlinerPass(bool InsertLifetime = true) + : InsertLifetime(InsertLifetime) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &); }; diff --git a/contrib/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h b/contrib/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h index 82ffc69a166e..49ca6cc73393 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h +++ b/contrib/llvm/include/llvm/Transforms/IPO/ArgumentPromotion.h @@ -22,7 +22,11 @@ namespace llvm { /// transform it and all of its callers to replace indirect arguments with /// direct (by-value) arguments. class ArgumentPromotionPass : public PassInfoMixin<ArgumentPromotionPass> { + unsigned MaxElements; + public: + ArgumentPromotionPass(unsigned MaxElements = 3u) : MaxElements(MaxElements) {} + PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR); }; diff --git a/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h b/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h index 39e5b5c8ae6f..120a34e15933 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h +++ b/contrib/llvm/include/llvm/Transforms/IPO/FunctionImport.h @@ -33,11 +33,17 @@ class Module; /// based on the provided summary informations. class FunctionImporter { public: - /// Set of functions to import from a source module. Each entry is a map - /// containing all the functions to import for a source module. - /// The keys is the GUID identifying a function to import, and the value - /// is the threshold applied when deciding to import it. - using FunctionsToImportTy = std::map<GlobalValue::GUID, unsigned>; + /// Set of functions to import from a source module. Each entry is a set + /// containing all the GUIDs of all functions to import for a source module. + using FunctionsToImportTy = std::unordered_set<GlobalValue::GUID>; + + /// Map of callee GUID considered for import into a given module to a pair + /// consisting of the largest threshold applied when deciding whether to + /// import it and, if we decided to import, a pointer to the summary instance + /// imported. If we decided not to import, the summary will be nullptr. + using ImportThresholdsTy = + DenseMap<GlobalValue::GUID, + std::pair<unsigned, const GlobalValueSummary *>>; /// The map contains an entry for every module to import from, the key being /// the module identifier to pass to the ModuleLoader. The value is the set of @@ -107,12 +113,24 @@ void ComputeCrossModuleImportForModuleFromIndex( StringRef ModulePath, const ModuleSummaryIndex &Index, FunctionImporter::ImportMapTy &ImportList); +/// PrevailingType enum used as a return type of callback passed +/// to computeDeadSymbols. Yes and No values used when status explicitly +/// set by symbols resolution, otherwise status is Unknown. +enum class PrevailingType { Yes, No, Unknown }; + /// Compute all the symbols that are "dead": i.e these that can't be reached /// in the graph from any of the given symbols listed in -/// \p GUIDPreservedSymbols. +/// \p GUIDPreservedSymbols. Non-prevailing symbols are symbols without a +/// prevailing copy anywhere in IR and are normally dead, \p isPrevailing +/// predicate returns status of symbol. void computeDeadSymbols( ModuleSummaryIndex &Index, - const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols); + const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols, + function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing); + +/// Converts value \p GV to declaration, or replaces with a declaration if +/// it is an alias. Returns true if converted, false if replaced. +bool convertToDeclaration(GlobalValue &GV); /// Compute the set of summaries needed for a ThinLTO backend compilation of /// \p ModulePath. @@ -131,9 +149,9 @@ void gatherImportedSummariesForModule( std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex); /// Emit into \p OutputFilename the files module \p ModulePath will import from. -std::error_code -EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename, - const FunctionImporter::ImportMapTy &ModuleImports); +std::error_code EmitImportsFiles( + StringRef ModulePath, StringRef OutputFilename, + const std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex); /// Resolve WeakForLinker values in \p TheModule based on the information /// recorded in the summaries during global summary-based analysis. diff --git a/contrib/llvm/include/llvm/Transforms/IPO/Inliner.h b/contrib/llvm/include/llvm/Transforms/IPO/Inliner.h index eda8cf462b50..610e4500e4b1 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO/Inliner.h +++ b/contrib/llvm/include/llvm/Transforms/IPO/Inliner.h @@ -96,12 +96,17 @@ class InlinerPass : public PassInfoMixin<InlinerPass> { public: InlinerPass(InlineParams Params = getInlineParams()) : Params(std::move(Params)) {} + ~InlinerPass(); + InlinerPass(InlinerPass &&Arg) + : Params(std::move(Arg.Params)), + ImportedFunctionsStats(std::move(Arg.ImportedFunctionsStats)) {} PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR); private: InlineParams Params; + std::unique_ptr<ImportedFunctionsInliningStatistics> ImportedFunctionsStats; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h b/contrib/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h index 3bcfe65df550..bc448386b63d 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h +++ b/contrib/llvm/include/llvm/Transforms/IPO/LowerTypeTests.h @@ -26,6 +26,7 @@ namespace llvm { class Module; +class ModuleSummaryIndex; class raw_ostream; namespace lowertypetests { @@ -197,6 +198,11 @@ struct ByteArrayBuilder { class LowerTypeTestsPass : public PassInfoMixin<LowerTypeTestsPass> { public: + ModuleSummaryIndex *ExportSummary; + const ModuleSummaryIndex *ImportSummary; + LowerTypeTestsPass(ModuleSummaryIndex *ExportSummary, + const ModuleSummaryIndex *ImportSummary) + : ExportSummary(ExportSummary), ImportSummary(ImportSummary) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; diff --git a/contrib/llvm/include/llvm/Transforms/SampleProfile.h b/contrib/llvm/include/llvm/Transforms/IPO/SampleProfile.h index f5a8590e14a1..cd5a0563898e 100644 --- a/contrib/llvm/include/llvm/Transforms/SampleProfile.h +++ b/contrib/llvm/include/llvm/Transforms/IPO/SampleProfile.h @@ -1,4 +1,4 @@ -//===- Transforms/SampleProfile.h - SamplePGO pass --------------*- C++ -*-===// +//===- SampleProfile.h - SamplePGO pass ---------- --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_SAMPLEPROFILE_H -#define LLVM_TRANSFORMS_SAMPLEPROFILE_H +#ifndef LLVM_TRANSFORMS_IPO_SAMPLEPROFILE_H +#define LLVM_TRANSFORMS_IPO_SAMPLEPROFILE_H #include "llvm/IR/PassManager.h" #include <string> diff --git a/contrib/llvm/include/llvm/Transforms/IPO/SyntheticCountsPropagation.h b/contrib/llvm/include/llvm/Transforms/IPO/SyntheticCountsPropagation.h new file mode 100644 index 000000000000..0b3ba86bc9e4 --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/IPO/SyntheticCountsPropagation.h @@ -0,0 +1,19 @@ +#ifndef LLVM_TRANSFORMS_IPO_SYNTHETIC_COUNTS_PROPAGATION_H +#define LLVM_TRANSFORMS_IPO_SYNTHETIC_COUNTS_PROPAGATION_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Support/ScaledNumber.h" + +namespace llvm { +class Function; +class Module; + +class SyntheticCountsPropagation + : public PassInfoMixin<SyntheticCountsPropagation> { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +}; +} // namespace llvm +#endif diff --git a/contrib/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h b/contrib/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h index 1aa4c6f4f559..bf2c79b0751e 100644 --- a/contrib/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h +++ b/contrib/llvm/include/llvm/Transforms/IPO/WholeProgramDevirt.h @@ -28,6 +28,7 @@ template <typename T> class ArrayRef; template <typename T> class MutableArrayRef; class Function; class GlobalVariable; +class ModuleSummaryIndex; namespace wholeprogramdevirt { @@ -218,6 +219,13 @@ void setAfterReturnValues(MutableArrayRef<VirtualCallTarget> Targets, } // end namespace wholeprogramdevirt struct WholeProgramDevirtPass : public PassInfoMixin<WholeProgramDevirtPass> { + ModuleSummaryIndex *ExportSummary; + const ModuleSummaryIndex *ImportSummary; + WholeProgramDevirtPass(ModuleSummaryIndex *ExportSummary, + const ModuleSummaryIndex *ImportSummary) + : ExportSummary(ExportSummary), ImportSummary(ImportSummary) { + assert(!(ExportSummary && ImportSummary)); + } PreservedAnalyses run(Module &M, ModuleAnalysisManager &); }; diff --git a/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombine.h b/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombine.h index 6bd22dc46255..ab25fe08553a 100644 --- a/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombine.h +++ b/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombine.h @@ -10,8 +10,7 @@ /// /// This file provides the primary interface to the instcombine pass. This pass /// is suitable for use in the new pass manager. For a pass that works with the -/// legacy pass manager, please look for \c createInstructionCombiningPass() in -/// Scalar.h. +/// legacy pass manager, use \c createInstructionCombiningPass(). /// //===----------------------------------------------------------------------===// @@ -37,7 +36,7 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief The legacy pass manager's instcombine pass. +/// The legacy pass manager's instcombine pass. /// /// This is a basic whole-function wrapper around the instcombine utility. It /// will try to combine all instructions in the function. @@ -56,6 +55,20 @@ public: void getAnalysisUsage(AnalysisUsage &AU) const override; bool runOnFunction(Function &F) override; }; + +//===----------------------------------------------------------------------===// +// +// InstructionCombining - Combine instructions to form fewer, simple +// instructions. This pass does not modify the CFG, and has a tendency to make +// instructions dead, so a subsequent DCE pass is useful. +// +// This pass combines things like: +// %Y = add int 1, %X +// %Z = add int 1, %Y +// into: +// %Z = add int 2, %X +// +FunctionPass *createInstructionCombiningPass(bool ExpensiveCombines = true); } #endif diff --git a/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombineWorklist.h b/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombineWorklist.h index 271e891bb45e..f860b4b86555 100644 --- a/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombineWorklist.h +++ b/contrib/llvm/include/llvm/Transforms/InstCombine/InstCombineWorklist.h @@ -40,7 +40,7 @@ public: /// in it. void Add(Instruction *I) { if (WorklistMap.insert(std::make_pair(I, Worklist.size())).second) { - DEBUG(dbgs() << "IC: ADD: " << *I << '\n'); + LLVM_DEBUG(dbgs() << "IC: ADD: " << *I << '\n'); Worklist.push_back(I); } } @@ -57,7 +57,8 @@ public: assert(Worklist.empty() && "Worklist must be empty to add initial group"); Worklist.reserve(List.size()+16); WorklistMap.reserve(List.size()); - DEBUG(dbgs() << "IC: ADDING: " << List.size() << " instrs to worklist\n"); + LLVM_DEBUG(dbgs() << "IC: ADDING: " << List.size() + << " instrs to worklist\n"); unsigned Idx = 0; for (Instruction *I : reverse(List)) { WorklistMap.insert(std::make_pair(I, Idx++)); diff --git a/contrib/llvm/include/llvm/Transforms/Instrumentation.h b/contrib/llvm/include/llvm/Transforms/Instrumentation.h index b1e13f17aef1..4a346c8d7450 100644 --- a/contrib/llvm/include/llvm/Transforms/Instrumentation.h +++ b/contrib/llvm/include/llvm/Transforms/Instrumentation.h @@ -133,7 +133,8 @@ ModulePass *createAddressSanitizerModulePass(bool CompileKernel = false, FunctionPass *createMemorySanitizerPass(int TrackOrigins = 0, bool Recover = false); -FunctionPass *createHWAddressSanitizerPass(bool Recover = false); +FunctionPass *createHWAddressSanitizerPass(bool CompileKernel = false, + bool Recover = false); // Insert ThreadSanitizer (race detection) instrumentation FunctionPass *createThreadSanitizerPass(); @@ -186,7 +187,7 @@ struct SanitizerCoverageOptions { ModulePass *createSanitizerCoverageModulePass( const SanitizerCoverageOptions &Options = SanitizerCoverageOptions()); -/// \brief Calculate what to divide by to scale counts. +/// Calculate what to divide by to scale counts. /// /// Given the maximum count, calculate a divisor that will scale all the /// weights to strictly less than std::numeric_limits<uint32_t>::max(). @@ -196,7 +197,7 @@ static inline uint64_t calculateCountScale(uint64_t MaxCount) { : MaxCount / std::numeric_limits<uint32_t>::max() + 1; } -/// \brief Scale an individual branch count. +/// Scale an individual branch count. /// /// Scale a 64-bit weight down to 32-bits using \c Scale. /// diff --git a/contrib/llvm/include/llvm/Transforms/Instrumentation/CGProfile.h b/contrib/llvm/include/llvm/Transforms/Instrumentation/CGProfile.h new file mode 100644 index 000000000000..c06c1a28715e --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/Instrumentation/CGProfile.h @@ -0,0 +1,31 @@ +//===- Transforms/Instrumentation/CGProfile.h -------------------*- 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 the interface for LLVM's Call Graph Profile pass. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_CGPROFILE_H +#define LLVM_TRANSFORMS_CGPROFILE_H + +#include "llvm/ADT/MapVector.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { +class CGProfilePass : public PassInfoMixin<CGProfilePass> { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + +private: + void addModuleFlags( + Module &M, + MapVector<std::pair<Function *, Function *>, uint64_t> &Counts) const; +}; +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_CGPROFILE_H diff --git a/contrib/llvm/include/llvm/Transforms/GCOVProfiler.h b/contrib/llvm/include/llvm/Transforms/Instrumentation/GCOVProfiler.h index 66bd75c88e24..dd55fbe29eed 100644 --- a/contrib/llvm/include/llvm/Transforms/GCOVProfiler.h +++ b/contrib/llvm/include/llvm/Transforms/Instrumentation/GCOVProfiler.h @@ -1,4 +1,4 @@ -//===- Transforms/GCOVProfiler.h - GCOVProfiler pass ----------*- C++ -*-===// +//===- Transforms/Instrumentation/GCOVProfiler.h ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/Transforms/InstrProfiling.h b/contrib/llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h index 0fe6ad5eeac7..13fb3db4ae6f 100644 --- a/contrib/llvm/include/llvm/Transforms/InstrProfiling.h +++ b/contrib/llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h @@ -1,4 +1,4 @@ -//===- Transforms/InstrProfiling.h - Instrumentation passes -----*- C++ -*-===// +//===- Transforms/Instrumentation/InstrProfiling.h --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -109,7 +109,8 @@ private: void emitRegistration(); /// Emit the necessary plumbing to pull in the runtime initialization. - void emitRuntimeHook(); + /// Returns true if a change was made. + bool emitRuntimeHook(); /// Add uses of our data variables and runtime hook. void emitUses(); diff --git a/contrib/llvm/include/llvm/Transforms/PGOInstrumentation.h b/contrib/llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h index c2cc76c422da..c0b37c470b74 100644 --- a/contrib/llvm/include/llvm/Transforms/PGOInstrumentation.h +++ b/contrib/llvm/include/llvm/Transforms/Instrumentation/PGOInstrumentation.h @@ -1,4 +1,4 @@ -//===- Transforms/PGOInstrumentation.h - PGO gen/use passes -----*- C++ -*-===// +//===- Transforms/Instrumentation/PGOInstrumentation.h ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/contrib/llvm/include/llvm/Transforms/Scalar.h b/contrib/llvm/include/llvm/Transforms/Scalar.h index 49186bc5cd66..9491e1bbac93 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar.h @@ -80,7 +80,6 @@ FunctionPass *createDeadStoreEliminationPass(); // values. FunctionPass *createCallSiteSplittingPass(); - //===----------------------------------------------------------------------===// // // AggressiveDCE - This pass uses the SSA based Aggressive DCE algorithm. This @@ -89,7 +88,6 @@ FunctionPass *createCallSiteSplittingPass(); // FunctionPass *createAggressiveDCEPass(); - //===----------------------------------------------------------------------===// // // GuardWidening - An optimization over the @llvm.experimental.guard intrinsic @@ -101,6 +99,16 @@ FunctionPass *createGuardWideningPass(); //===----------------------------------------------------------------------===// // +// LoopGuardWidening - Analogous to the GuardWidening pass, but restricted to a +// single loop at a time for use within a LoopPassManager. Desired effect is +// to widen guards into preheader or a single guard within loop if that's not +// possible. +// +Pass *createLoopGuardWideningPass(); + + +//===----------------------------------------------------------------------===// +// // BitTrackingDCE - This pass uses a bit-tracking DCE algorithm in order to // remove computations of dead bits. // @@ -128,20 +136,6 @@ Pass *createIndVarSimplifyPass(); //===----------------------------------------------------------------------===// // -// InstructionCombining - Combine instructions to form fewer, simple -// instructions. This pass does not modify the CFG, and has a tendency to make -// instructions dead, so a subsequent DCE pass is useful. -// -// This pass combines things like: -// %Y = add int 1, %X -// %Z = add int 1, %Y -// into: -// %Z = add int 2, %X -// -FunctionPass *createInstructionCombiningPass(bool ExpensiveCombines = true); - -//===----------------------------------------------------------------------===// -// // LICM - This pass is a loop invariant code motion and memory promotion pass. // Pass *createLICMPass(); @@ -198,6 +192,12 @@ Pass *createSimpleLoopUnrollPass(int OptLevel = 2); //===----------------------------------------------------------------------===// // +// LoopUnrollAndJam - This pass is a simple loop unroll and jam pass. +// +Pass *createLoopUnrollAndJamPass(int OptLevel = 2); + +//===----------------------------------------------------------------------===// +// // LoopReroll - This pass is a simple loop rerolling pass. // Pass *createLoopRerollPass(); @@ -222,20 +222,6 @@ Pass *createLoopVersioningLICMPass(); //===----------------------------------------------------------------------===// // -// PromoteMemoryToRegister - This pass is used to promote memory references to -// be register references. A simple example of the transformation performed by -// this pass is: -// -// FROM CODE TO CODE -// %X = alloca i32, i32 1 ret i32 42 -// store i32 42, i32 *%X -// %Y = load i32* %X -// ret i32 %Y -// -FunctionPass *createPromoteMemoryToRegisterPass(); - -//===----------------------------------------------------------------------===// -// // DemoteRegisterToMemoryPass - This pass is used to demote registers to memory // references. In basically undoes the PromoteMemoryToRegister pass to make cfg // hacking easier. @@ -288,31 +274,6 @@ Pass *createStructurizeCFGPass(bool SkipUniformRegions = false); //===----------------------------------------------------------------------===// // -// BreakCriticalEdges - Break all of the critical edges in the CFG by inserting -// a dummy basic block. This pass may be "required" by passes that cannot deal -// with critical edges. For this usage, a pass must call: -// -// AU.addRequiredID(BreakCriticalEdgesID); -// -// This pass obviously invalidates the CFG, but can update forward dominator -// (set, immediate dominators, tree, and frontier) information. -// -FunctionPass *createBreakCriticalEdgesPass(); -extern char &BreakCriticalEdgesID; - -//===----------------------------------------------------------------------===// -// -// LoopSimplify - Insert Pre-header blocks into the CFG for every function in -// the module. This pass updates dominator information, loop information, and -// does not add critical edges to the CFG. -// -// AU.addRequiredID(LoopSimplifyID); -// -Pass *createLoopSimplifyPass(); -extern char &LoopSimplifyID; - -//===----------------------------------------------------------------------===// -// // TailCallElimination - This pass eliminates call instructions to the current // function which occur immediately before return instructions. // @@ -320,30 +281,6 @@ FunctionPass *createTailCallEliminationPass(); //===----------------------------------------------------------------------===// // -// LowerSwitch - This pass converts SwitchInst instructions into a sequence of -// chained binary branch instructions. -// -FunctionPass *createLowerSwitchPass(); -extern char &LowerSwitchID; - -//===----------------------------------------------------------------------===// -// -// LowerInvoke - This pass removes invoke instructions, converting them to call -// instructions. -// -FunctionPass *createLowerInvokePass(); -extern char &LowerInvokePassID; - -//===----------------------------------------------------------------------===// -// -// LCSSA - This pass inserts phi nodes at loop boundaries to simplify other loop -// optimizations. -// -Pass *createLCSSAPass(); -extern char &LCSSAID; - -//===----------------------------------------------------------------------===// -// // EarlyCSE - This pass performs a simple and fast CSE pass over the dominator // tree. // @@ -405,13 +342,6 @@ FunctionPass *createConstantHoistingPass(); //===----------------------------------------------------------------------===// // -// InstructionNamer - Give any unnamed non-void instructions "tmp" names. -// -FunctionPass *createInstructionNamerPass(); -extern char &InstructionNamerID; - -//===----------------------------------------------------------------------===// -// // Sink - Code Sinking // FunctionPass *createSinkingPass(); @@ -451,13 +381,6 @@ extern char &InferAddressSpacesID; //===----------------------------------------------------------------------===// // -// InstructionSimplifier - Remove redundant instructions. -// -FunctionPass *createInstructionSimplifierPass(); -extern char &InstructionSimplifierID; - -//===----------------------------------------------------------------------===// -// // LowerExpectIntrinsics - Removes llvm.expect intrinsics and creates // "block_weights" metadata. FunctionPass *createLowerExpectIntrinsicPass(); @@ -477,16 +400,9 @@ FunctionPass *createScalarizerPass(); //===----------------------------------------------------------------------===// // -// AddDiscriminators - Add DWARF path discriminators to the IR. -FunctionPass *createAddDiscriminatorsPass(); - -//===----------------------------------------------------------------------===// -// // SeparateConstOffsetFromGEP - Split GEPs for better CSE // -FunctionPass * -createSeparateConstOffsetFromGEPPass(const TargetMachine *TM = nullptr, - bool LowerGEP = false); +FunctionPass *createSeparateConstOffsetFromGEPPass(bool LowerGEP = false); //===----------------------------------------------------------------------===// // @@ -525,13 +441,6 @@ ModulePass *createRewriteStatepointsForGCLegacyPass(); //===----------------------------------------------------------------------===// // -// StripGCRelocates - Remove GC relocates that have been inserted by -// RewriteStatepointsForGC. The resulting IR is incorrect, but this is useful -// for manual inspection. -FunctionPass *createStripGCRelocatesPass(); - -//===----------------------------------------------------------------------===// -// // Float2Int - Demote floats to ints where possible. // FunctionPass *createFloat2IntPass(); @@ -556,13 +465,6 @@ FunctionPass *createLoopLoadEliminationPass(); //===----------------------------------------------------------------------===// // -// LoopSimplifyCFG - This pass performs basic CFG simplification on loops, -// primarily to help other loop passes. -// -Pass *createLoopSimplifyCFGPass(); - -//===----------------------------------------------------------------------===// -// // LoopVersioning - Perform loop multi-versioning. // FunctionPass *createLoopVersioningPass(); @@ -585,13 +487,10 @@ FunctionPass *createLibCallsShrinkWrapPass(); //===----------------------------------------------------------------------===// // -// EntryExitInstrumenter pass - Instrument function entry/exit with calls to -// mcount(), @__cyg_profile_func_{enter,exit} and the like. There are two -// variants, intended to run pre- and post-inlining, respectively. +// LoopSimplifyCFG - This pass performs basic CFG simplification on loops, +// primarily to help other loop passes. // -FunctionPass *createEntryExitInstrumenterPass(); -FunctionPass *createPostInlineEntryExitInstrumenterPass(); - +Pass *createLoopSimplifyCFGPass(); } // End llvm namespace #endif diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h b/contrib/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h index f75dc4dc331d..61975036e9ff 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h @@ -33,12 +33,6 @@ struct AlignmentFromAssumptionsPass bool runImpl(Function &F, AssumptionCache &AC, ScalarEvolution *SE_, DominatorTree *DT_); - // For memory transfers, we need a common alignment for both the source and - // destination. If we have a new alignment for only one operand of a transfer - // instruction, save it in these maps. If we reach the other operand through - // another assumption later, then we may change the alignment at that point. - DenseMap<MemTransferInst *, unsigned> NewDestAlignments, NewSrcAlignments; - ScalarEvolution *SE = nullptr; DominatorTree *DT = nullptr; diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h b/contrib/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h index 5ab951a49f2c..b2ca2a1c09ae 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/CallSiteSplitting.h @@ -21,7 +21,7 @@ namespace llvm { struct CallSiteSplittingPass : PassInfoMixin<CallSiteSplittingPass> { - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h b/contrib/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h index d3322dc1c414..84589bf4db99 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h @@ -60,7 +60,7 @@ class TargetTransformInfo; /// clients. namespace consthoist { -/// \brief Keeps track of the user of a constant and the operand index where the +/// Keeps track of the user of a constant and the operand index where the /// constant is used. struct ConstantUser { Instruction *Inst; @@ -71,7 +71,7 @@ struct ConstantUser { using ConstantUseListType = SmallVector<ConstantUser, 8>; -/// \brief Keeps track of a constant candidate and its uses. +/// Keeps track of a constant candidate and its uses. struct ConstantCandidate { ConstantUseListType Uses; ConstantInt *ConstInt; @@ -79,14 +79,14 @@ struct ConstantCandidate { ConstantCandidate(ConstantInt *ConstInt) : ConstInt(ConstInt) {} - /// \brief Add the user to the use list and update the cost. + /// Add the user to the use list and update the cost. void addUser(Instruction *Inst, unsigned Idx, unsigned Cost) { CumulativeCost += Cost; Uses.push_back(ConstantUser(Inst, Idx)); } }; -/// \brief This represents a constant that has been rebased with respect to a +/// This represents a constant that has been rebased with respect to a /// base constant. The difference to the base constant is recorded in Offset. struct RebasedConstantInfo { ConstantUseListType Uses; @@ -98,7 +98,7 @@ struct RebasedConstantInfo { using RebasedConstantListType = SmallVector<RebasedConstantInfo, 4>; -/// \brief A base constant and all its rebased constants. +/// A base constant and all its rebased constants. struct ConstantInfo { ConstantInt *BaseConstant; RebasedConstantListType RebasedConstants; diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/EarlyCSE.h b/contrib/llvm/include/llvm/Transforms/Scalar/EarlyCSE.h index dca3b2dbf04f..faf03a4ec489 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/EarlyCSE.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/EarlyCSE.h @@ -21,7 +21,7 @@ namespace llvm { class Function; -/// \brief A simple and fast domtree-based CSE pass. +/// A simple and fast domtree-based CSE pass. /// /// This pass does a simple depth-first walk over the dominator tree, /// eliminating trivially redundant instructions and using instsimplify to @@ -31,7 +31,7 @@ class Function; struct EarlyCSEPass : PassInfoMixin<EarlyCSEPass> { EarlyCSEPass(bool UseMemorySSA = false) : UseMemorySSA(UseMemorySSA) {} - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); bool UseMemorySSA; diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/GVN.h b/contrib/llvm/include/llvm/Transforms/Scalar/GVN.h index 440d3f67c35a..b9de07ec9279 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/GVN.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/GVN.h @@ -69,7 +69,7 @@ class GVN : public PassInfoMixin<GVN> { public: struct Expression; - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); /// This removes the specified instruction from @@ -291,17 +291,17 @@ private: /// loads are eliminated by the pass. FunctionPass *createGVNPass(bool NoLoads = false); -/// \brief A simple and fast domtree-based GVN pass to hoist common expressions +/// A simple and fast domtree-based GVN pass to hoist common expressions /// from sibling branches. struct GVNHoistPass : PassInfoMixin<GVNHoistPass> { - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Uses an "inverted" value numbering to decide the similarity of +/// Uses an "inverted" value numbering to decide the similarity of /// expressions and sinks similar expressions into successors. struct GVNSinkPass : PassInfoMixin<GVNSinkPass> { - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h b/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h index 99dae15a3ac0..8b346969b1e9 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/GVNExpression.h @@ -159,7 +159,7 @@ public: return ET > ET_BasicStart && ET < ET_BasicEnd; } - /// \brief Swap two operands. Used during GVN to put commutative operands in + /// Swap two operands. Used during GVN to put commutative operands in /// order. void swapOperands(unsigned First, unsigned Second) { std::swap(Operands[First], Operands[Second]); diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h b/contrib/llvm/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h new file mode 100644 index 000000000000..311c549b8326 --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/Scalar/InductiveRangeCheckElimination.h @@ -0,0 +1,31 @@ +//===- InductiveRangeCheckElimination.h - IRCE ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides the interface for the Inductive Range Check Elimination +// loop pass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_INDUCTIVERANGECHECKELIMINATION_H +#define LLVM_TRANSFORMS_SCALAR_INDUCTIVERANGECHECKELIMINATION_H + +#include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" + +namespace llvm { + +class IRCEPass : public PassInfoMixin<IRCEPass> { +public: + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_SCALAR_INDUCTIVERANGECHECKELIMINATION_H diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/InstSimplifyPass.h b/contrib/llvm/include/llvm/Transforms/Scalar/InstSimplifyPass.h new file mode 100644 index 000000000000..da79a13eb7cf --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/Scalar/InstSimplifyPass.h @@ -0,0 +1,46 @@ +//===- InstSimplifyPass.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Defines passes for running instruction simplification across chunks of IR. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_INSTSIMPLIFYPASS_H +#define LLVM_TRANSFORMS_UTILS_INSTSIMPLIFYPASS_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class FunctionPass; + +/// Run instruction simplification across each instruction in the function. +/// +/// Instruction simplification has useful constraints in some contexts: +/// - It will never introduce *new* instructions. +/// - There is no need to iterate to a fixed point. +/// +/// Many passes use instruction simplification as a library facility, but it may +/// also be useful (in tests and other contexts) to have access to this very +/// restricted transform at a pass granularity. However, for a much more +/// powerful and comprehensive peephole optimization engine, see the +/// `instcombine` pass instead. +class InstSimplifyPass : public PassInfoMixin<InstSimplifyPass> { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +/// Create a legacy pass that does instruction simplification on each +/// instruction in a function. +FunctionPass *createInstSimplifyLegacyPass(); + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_UTILS_INSTSIMPLIFYPASS_H diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/JumpThreading.h b/contrib/llvm/include/llvm/Transforms/Scalar/JumpThreading.h index a9466713b8e6..b3493a292498 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/JumpThreading.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/JumpThreading.h @@ -34,6 +34,7 @@ class BinaryOperator; class BranchInst; class CmpInst; class Constant; +class DeferredDominance; class Function; class Instruction; class IntrinsicInst; @@ -77,6 +78,7 @@ class JumpThreadingPass : public PassInfoMixin<JumpThreadingPass> { TargetLibraryInfo *TLI; LazyValueInfo *LVI; AliasAnalysis *AA; + DeferredDominance *DDT; std::unique_ptr<BlockFrequencyInfo> BFI; std::unique_ptr<BranchProbabilityInfo> BPI; bool HasProfileData = false; @@ -107,8 +109,8 @@ public: // Glue for old PM. bool runImpl(Function &F, TargetLibraryInfo *TLI_, LazyValueInfo *LVI_, - AliasAnalysis *AA_, bool HasProfileData_, - std::unique_ptr<BlockFrequencyInfo> BFI_, + AliasAnalysis *AA_, DeferredDominance *DDT_, + bool HasProfileData_, std::unique_ptr<BlockFrequencyInfo> BFI_, std::unique_ptr<BranchProbabilityInfo> BPI_); PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h b/contrib/llvm/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h index 5eddd5fdc7e7..e1b33799578b 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h @@ -15,7 +15,7 @@ namespace llvm { -/// \brief Printer pass for the \c LoopAccessInfo results. +/// Printer pass for the \c LoopAccessInfo results. class LoopAccessInfoPrinterPass : public PassInfoMixin<LoopAccessInfoPrinterPass> { raw_ostream &OS; diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/LoopDataPrefetch.h b/contrib/llvm/include/llvm/Transforms/Scalar/LoopDataPrefetch.h index 12c7a030ff8b..e1ad67ac6fff 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/LoopDataPrefetch.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/LoopDataPrefetch.h @@ -24,7 +24,7 @@ class LoopDataPrefetchPass : public PassInfoMixin<LoopDataPrefetchPass> { public: LoopDataPrefetchPass() = default; - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/contrib/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h index 56a45ed34178..5f61c39b5530 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -71,7 +71,7 @@ PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &, extern template class PassManager<Loop, LoopAnalysisManager, LoopStandardAnalysisResults &, LPMUpdater &>; -/// \brief The Loop pass manager. +/// The Loop pass manager. /// /// See the documentation for the PassManager template for details. It runs /// a sequence of Loop passes over each Loop that the manager is run over. This @@ -253,7 +253,7 @@ private: : Worklist(Worklist), LAM(LAM) {} }; -/// \brief Adaptor that maps from a function to its loops. +/// Adaptor that maps from a function to its loops. /// /// Designed to allow composition of a LoopPass(Manager) and a /// FunctionPassManager. Note that if this pass is constructed with a \c @@ -270,7 +270,7 @@ public: LoopCanonicalizationFPM.addPass(LCSSAPass()); } - /// \brief Runs the loop passes across every loop in the function. + /// Runs the loop passes across every loop in the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { // Before we even compute any loop analyses, first run a miniature function // pass pipeline to put loops into their canonical form. Note that we can @@ -381,7 +381,7 @@ private: FunctionPassManager LoopCanonicalizationFPM; }; -/// \brief A function to deduce a loop pass type and wrap it in the templated +/// A function to deduce a loop pass type and wrap it in the templated /// adaptor. template <typename LoopPassT> FunctionToLoopPassAdaptor<LoopPassT> @@ -389,7 +389,7 @@ createFunctionToLoopPassAdaptor(LoopPassT Pass, bool DebugLogging = false) { return FunctionToLoopPassAdaptor<LoopPassT>(std::move(Pass), DebugLogging); } -/// \brief Pass for printing a loop's contents as textual IR. +/// Pass for printing a loop's contents as textual IR. class PrintLoopPass : public PassInfoMixin<PrintLoopPass> { raw_ostream &OS; std::string Banner; diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h b/contrib/llvm/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h new file mode 100644 index 000000000000..fc69aa361059 --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/Scalar/LoopUnrollAndJamPass.h @@ -0,0 +1,35 @@ +//===- LoopUnrollAndJamPass.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_LOOPUNROLLANDJAMPASS_H +#define LLVM_TRANSFORMS_SCALAR_LOOPUNROLLANDJAMPASS_H + +#include "llvm/Analysis/LoopAnalysisManager.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class Loop; +struct LoopStandardAnalysisResults; +class LPMUpdater; + +/// A simple loop rotation transformation. +class LoopUnrollAndJamPass : public PassInfoMixin<LoopUnrollAndJamPass> { + const int OptLevel; + +public: + explicit LoopUnrollAndJamPass(int OptLevel = 2) : OptLevel(OptLevel) {} + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_SCALAR_LOOPUNROLLANDJAMPASS_H diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h b/contrib/llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h index ab9dec0311b2..b6ee6523697c 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/LowerExpectIntrinsic.h @@ -22,7 +22,7 @@ namespace llvm { struct LowerExpectIntrinsicPass : PassInfoMixin<LowerExpectIntrinsicPass> { - /// \brief Run the pass over the function. + /// Run the pass over the function. /// /// This will lower all of the expect intrinsic calls in this function into /// branch weight metadata. That metadata will subsequently feed the analysis diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h b/contrib/llvm/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h index 3cad7bb070d0..48df09cdec9e 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/MergedLoadStoreMotion.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // //! \file -//! \brief This pass performs merges of loads and stores on both sides of a +//! This pass performs merges of loads and stores on both sides of a // diamond (hammock). It hoists the loads and sinks the stores. // // The algorithm iteratively hoists two loads to the same address out of a diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/NewGVN.h b/contrib/llvm/include/llvm/Transforms/Scalar/NewGVN.h index 05db25502dc3..3f7541863a19 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/NewGVN.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/NewGVN.h @@ -23,7 +23,7 @@ class Function; class NewGVNPass : public PassInfoMixin<NewGVNPass> { public: - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, AnalysisManager<Function> &AM); }; diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/Reassociate.h b/contrib/llvm/include/llvm/Transforms/Scalar/Reassociate.h index 9997dfa5b6f3..ba7586dffd9d 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/Reassociate.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/Reassociate.h @@ -29,6 +29,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/ValueHandle.h" +#include <deque> namespace llvm { @@ -54,7 +55,7 @@ inline bool operator<(const ValueEntry &LHS, const ValueEntry &RHS) { return LHS.Rank > RHS.Rank; // Sort so that highest rank goes to start. } -/// \brief Utility class representing a base and exponent pair which form one +/// Utility class representing a base and exponent pair which form one /// factor of some product. struct Factor { Value *Base; @@ -69,9 +70,14 @@ class XorOpnd; /// Reassociate commutative expressions. class ReassociatePass : public PassInfoMixin<ReassociatePass> { +public: + using OrderedSet = + SetVector<AssertingVH<Instruction>, std::deque<AssertingVH<Instruction>>>; + +protected: DenseMap<BasicBlock *, unsigned> RankMap; DenseMap<AssertingVH<Value>, unsigned> ValueRankMap; - SetVector<AssertingVH<Instruction>> RedoInsts; + OrderedSet RedoInsts; // Arbitrary, but prevents quadratic behavior. static const unsigned GlobalReassociateLimit = 10; @@ -108,8 +114,7 @@ private: SmallVectorImpl<reassociate::ValueEntry> &Ops); Value *RemoveFactorFromExpression(Value *V, Value *Factor); void EraseInst(Instruction *I); - void RecursivelyEraseDeadInsts(Instruction *I, - SetVector<AssertingVH<Instruction>> &Insts); + void RecursivelyEraseDeadInsts(Instruction *I, OrderedSet &Insts); void OptimizeInst(Instruction *I); Instruction *canonicalizeNegConstExpr(Instruction *I); void BuildPairMap(ReversePostOrderTraversal<Function *> &RPOT); diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/SCCP.h b/contrib/llvm/include/llvm/Transforms/Scalar/SCCP.h index b93287fff907..2a294c95a17b 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/SCCP.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/SCCP.h @@ -21,6 +21,10 @@ #ifndef LLVM_TRANSFORMS_SCALAR_SCCP_H #define LLVM_TRANSFORMS_SCALAR_SCCP_H +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" namespace llvm { @@ -33,6 +37,7 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; +bool runIPSCCP(Module &M, const DataLayout &DL, const TargetLibraryInfo *TLI); } // end namespace llvm #endif // LLVM_TRANSFORMS_SCALAR_SCCP_H diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/SROA.h b/contrib/llvm/include/llvm/Transforms/Scalar/SROA.h index 4a321e75c68b..b36c6f492be1 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/SROA.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/SROA.h @@ -45,7 +45,7 @@ class SROALegacyPass; } // end namespace sroa -/// \brief An optimization pass providing Scalar Replacement of Aggregates. +/// An optimization pass providing Scalar Replacement of Aggregates. /// /// This pass takes allocations which can be completely analyzed (that is, they /// don't escape) and tries to turn them into scalar SSA values. There are @@ -68,7 +68,7 @@ class SROA : public PassInfoMixin<SROA> { DominatorTree *DT = nullptr; AssumptionCache *AC = nullptr; - /// \brief Worklist of alloca instructions to simplify. + /// Worklist of alloca instructions to simplify. /// /// Each alloca in the function is added to this. Each new alloca formed gets /// added to it as well to recursively simplify unless that alloca can be @@ -77,12 +77,12 @@ class SROA : public PassInfoMixin<SROA> { /// already present to ensure it is re-visited. SetVector<AllocaInst *, SmallVector<AllocaInst *, 16>> Worklist; - /// \brief A collection of instructions to delete. + /// A collection of instructions to delete. /// We try to batch deletions to simplify code and make things a bit more /// efficient. SetVector<Instruction *, SmallVector<Instruction *, 8>> DeadInsts; - /// \brief Post-promotion worklist. + /// Post-promotion worklist. /// /// Sometimes we discover an alloca which has a high probability of becoming /// viable for SROA after a round of promotion takes place. In those cases, @@ -92,17 +92,17 @@ class SROA : public PassInfoMixin<SROA> { /// the event they are deleted. SetVector<AllocaInst *, SmallVector<AllocaInst *, 16>> PostPromotionWorklist; - /// \brief A collection of alloca instructions we can directly promote. + /// A collection of alloca instructions we can directly promote. std::vector<AllocaInst *> PromotableAllocas; - /// \brief A worklist of PHIs to speculate prior to promoting allocas. + /// A worklist of PHIs to speculate prior to promoting allocas. /// /// All of these PHIs have been checked for the safety of speculation and by /// being speculated will allow promoting allocas currently in the promotable /// queue. SetVector<PHINode *, SmallVector<PHINode *, 2>> SpeculatablePHIs; - /// \brief A worklist of select instructions to speculate prior to promoting + /// A worklist of select instructions to speculate prior to promoting /// allocas. /// /// All of these select instructions have been checked for the safety of @@ -113,7 +113,7 @@ class SROA : public PassInfoMixin<SROA> { public: SROA() = default; - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); private: diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h b/contrib/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h index 63bfe6373d04..eed50ec96161 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h @@ -17,9 +17,9 @@ namespace llvm { -/// This pass transforms loops that contain branches on loop-invariant -/// conditions to have multiple loops. For example, it turns the left into the -/// right code: +/// This pass transforms loops that contain branches or switches on loop- +/// invariant conditions to have multiple loops. For example, it turns the left +/// into the right code: /// /// for (...) if (lic) /// A for (...) @@ -35,6 +35,31 @@ namespace llvm { /// This pass expects LICM to be run before it to hoist invariant conditions out /// of the loop, to make the unswitching opportunity obvious. /// +/// There is a taxonomy of unswitching that we use to classify different forms +/// of this transformaiton: +/// +/// - Trival unswitching: this is when the condition can be unswitched without +/// cloning any code from inside the loop. A non-trivial unswitch requires +/// code duplication. +/// +/// - Full unswitching: this is when the branch or switch is completely moved +/// from inside the loop to outside the loop. Partial unswitching removes the +/// branch from the clone of the loop but must leave a (somewhat simplified) +/// branch in the original loop. While theoretically partial unswitching can +/// be done for switches, the requirements are extreme - we need the loop +/// invariant input to the switch to be sufficient to collapse to a single +/// successor in each clone. +/// +/// This pass always does trivial, full unswitching for both branches and +/// switches. For branches, it also always does trivial, partial unswitching. +/// +/// If enabled (via the constructor's `NonTrivial` parameter), this pass will +/// additionally do non-trivial, full unswitching for branches and switches, and +/// will do non-trivial, partial unswitching for branches. +/// +/// Because partial unswitching of switches is extremely unlikely to be possible +/// in practice and significantly complicates the implementation, this pass does +/// not currently implement that in any mode. class SimpleLoopUnswitchPass : public PassInfoMixin<SimpleLoopUnswitchPass> { bool NonTrivial; diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h b/contrib/llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h index 1afb9c7f954f..ce0a35fc06bd 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/SimplifyCFG.h @@ -15,9 +15,9 @@ #ifndef LLVM_TRANSFORMS_SCALAR_SIMPLIFYCFG_H #define LLVM_TRANSFORMS_SCALAR_SIMPLIFYCFG_H +#include "llvm/Transforms/Utils/Local.h" #include "llvm/IR/Function.h" #include "llvm/IR/PassManager.h" -#include "llvm/Transforms/Utils/Local.h" namespace llvm { @@ -46,7 +46,7 @@ public: /// Construct a pass with optional optimizations. SimplifyCFGPass(const SimplifyCFGOptions &PassOptions); - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; diff --git a/contrib/llvm/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h b/contrib/llvm/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h index f39e03d22d65..4a0bfd754723 100644 --- a/contrib/llvm/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h +++ b/contrib/llvm/include/llvm/Transforms/Scalar/SpeculateAroundPHIs.h @@ -102,7 +102,7 @@ namespace llvm { /// here are relatively simple ones around execution and codesize cost, without /// any need to consider simplifications or other transformations. struct SpeculateAroundPHIsPass : PassInfoMixin<SpeculateAroundPHIsPass> { - /// \brief Run the pass over the function. + /// Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; diff --git a/contrib/llvm/include/llvm/Transforms/Utils.h b/contrib/llvm/include/llvm/Transforms/Utils.h new file mode 100644 index 000000000000..0d997ce17b83 --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/Utils.h @@ -0,0 +1,118 @@ +//===- llvm/Transforms/Utils.h - Utility Transformations --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the Utils transformations library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_H +#define LLVM_TRANSFORMS_UTILS_H + +namespace llvm { + +class ModulePass; +class FunctionPass; +class Pass; + +//===----------------------------------------------------------------------===// +// createMetaRenamerPass - Rename everything with metasyntatic names. +// +ModulePass *createMetaRenamerPass(); + +//===----------------------------------------------------------------------===// +// +// LowerInvoke - This pass removes invoke instructions, converting them to call +// instructions. +// +FunctionPass *createLowerInvokePass(); +extern char &LowerInvokePassID; + +//===----------------------------------------------------------------------===// +// +// InstructionNamer - Give any unnamed non-void instructions "tmp" names. +// +FunctionPass *createInstructionNamerPass(); +extern char &InstructionNamerID; + +//===----------------------------------------------------------------------===// +// +// LowerSwitch - This pass converts SwitchInst instructions into a sequence of +// chained binary branch instructions. +// +FunctionPass *createLowerSwitchPass(); +extern char &LowerSwitchID; + +//===----------------------------------------------------------------------===// +// +// EntryExitInstrumenter pass - Instrument function entry/exit with calls to +// mcount(), @__cyg_profile_func_{enter,exit} and the like. There are two +// variants, intended to run pre- and post-inlining, respectively. +// +FunctionPass *createEntryExitInstrumenterPass(); +FunctionPass *createPostInlineEntryExitInstrumenterPass(); + +//===----------------------------------------------------------------------===// +// +// BreakCriticalEdges - Break all of the critical edges in the CFG by inserting +// a dummy basic block. This pass may be "required" by passes that cannot deal +// with critical edges. For this usage, a pass must call: +// +// AU.addRequiredID(BreakCriticalEdgesID); +// +// This pass obviously invalidates the CFG, but can update forward dominator +// (set, immediate dominators, tree, and frontier) information. +// +FunctionPass *createBreakCriticalEdgesPass(); +extern char &BreakCriticalEdgesID; + +//===----------------------------------------------------------------------===// +// +// LCSSA - This pass inserts phi nodes at loop boundaries to simplify other loop +// optimizations. +// +Pass *createLCSSAPass(); +extern char &LCSSAID; + +//===----------------------------------------------------------------------===// +// +// AddDiscriminators - Add DWARF path discriminators to the IR. +FunctionPass *createAddDiscriminatorsPass(); + +//===----------------------------------------------------------------------===// +// +// PromoteMemoryToRegister - This pass is used to promote memory references to +// be register references. A simple example of the transformation performed by +// this pass is: +// +// FROM CODE TO CODE +// %X = alloca i32, i32 1 ret i32 42 +// store i32 42, i32 *%X +// %Y = load i32* %X +// ret i32 %Y +// +FunctionPass *createPromoteMemoryToRegisterPass(); + +//===----------------------------------------------------------------------===// +// +// LoopSimplify - Insert Pre-header blocks into the CFG for every function in +// the module. This pass updates dominator information, loop information, and +// does not add critical edges to the CFG. +// +// AU.addRequiredID(LoopSimplifyID); +// +Pass *createLoopSimplifyPass(); +extern char &LoopSimplifyID; + +/// This function returns a new pass that downgrades the debug info in the +/// module to line tables only. +ModulePass *createStripNonLineTableDebugInfoPass(); +} + +#endif diff --git a/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h index 74f75509f550..3dfc73b64842 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -27,6 +27,7 @@ namespace llvm { class BlockFrequencyInfo; class BranchProbabilityInfo; +class DeferredDominance; class DominatorTree; class Function; class Instruction; @@ -38,7 +39,7 @@ class TargetLibraryInfo; class Value; /// Delete the specified block, which must have no predecessors. -void DeleteDeadBlock(BasicBlock *BB); +void DeleteDeadBlock(BasicBlock *BB, DeferredDominance *DDT = nullptr); /// We know that BB has one predecessor. If there are any single-entry PHI nodes /// in it, fold them away. This handles the case when all entries to the PHI @@ -57,7 +58,8 @@ bool DeleteDeadPHIs(BasicBlock *BB, const TargetLibraryInfo *TLI = nullptr); /// value indicates success or failure. bool MergeBlockIntoPredecessor(BasicBlock *BB, DominatorTree *DT = nullptr, LoopInfo *LI = nullptr, - MemoryDependenceResults *MemDep = nullptr); + MemoryDependenceResults *MemDep = nullptr, + DeferredDominance *DDT = nullptr); /// Replace all uses of an instruction (specified by BI) with a value, then /// remove and delete the original instruction. diff --git a/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h b/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h index a067a685b837..bdcdf6f361f2 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -15,6 +15,7 @@ #ifndef LLVM_TRANSFORMS_UTILS_BUILDLIBCALLS_H #define LLVM_TRANSFORMS_UTILS_BUILDLIBCALLS_H +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/IRBuilder.h" namespace llvm { @@ -29,6 +30,12 @@ namespace llvm { /// Returns true if any attributes were set and false otherwise. bool inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI); + /// Check whether the overloaded unary floating point function + /// corresponding to \a Ty is available. + bool hasUnaryFloatFn(const TargetLibraryInfo *TLI, Type *Ty, + LibFunc DoubleFn, LibFunc FloatFn, + LibFunc LongDoubleFn); + /// Return V if it is an i8*, otherwise cast it to i8*. Value *castToCStr(Value *V, IRBuilder<> &B); @@ -104,15 +111,54 @@ namespace llvm { Value *emitFPutC(Value *Char, Value *File, IRBuilder<> &B, const TargetLibraryInfo *TLI); - /// Emit a call to the puts function. Str is required to be a pointer and + /// Emit a call to the fputc_unlocked function. This assumes that Char is an + /// i32, and File is a pointer to FILE. + Value *emitFPutCUnlocked(Value *Char, Value *File, IRBuilder<> &B, + const TargetLibraryInfo *TLI); + + /// Emit a call to the fputs function. Str is required to be a pointer and /// File is a pointer to FILE. Value *emitFPutS(Value *Str, Value *File, IRBuilder<> &B, const TargetLibraryInfo *TLI); + /// Emit a call to the fputs_unlocked function. Str is required to be a + /// pointer and File is a pointer to FILE. + Value *emitFPutSUnlocked(Value *Str, Value *File, IRBuilder<> &B, + const TargetLibraryInfo *TLI); + /// Emit a call to the fwrite function. This assumes that Ptr is a pointer, /// Size is an 'intptr_t', and File is a pointer to FILE. Value *emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, const DataLayout &DL, const TargetLibraryInfo *TLI); + + /// Emit a call to the malloc function. + Value *emitMalloc(Value *Num, IRBuilder<> &B, const DataLayout &DL, + const TargetLibraryInfo *TLI); + + /// Emit a call to the calloc function. + Value *emitCalloc(Value *Num, Value *Size, const AttributeList &Attrs, + IRBuilder<> &B, const TargetLibraryInfo &TLI); + + /// Emit a call to the fwrite_unlocked function. This assumes that Ptr is a + /// pointer, Size is an 'intptr_t', N is nmemb and File is a pointer to FILE. + Value *emitFWriteUnlocked(Value *Ptr, Value *Size, Value *N, Value *File, + IRBuilder<> &B, const DataLayout &DL, + const TargetLibraryInfo *TLI); + + /// Emit a call to the fgetc_unlocked function. File is a pointer to FILE. + Value *emitFGetCUnlocked(Value *File, IRBuilder<> &B, + const TargetLibraryInfo *TLI); + + /// Emit a call to the fgets_unlocked function. Str is required to be a + /// pointer, Size is an i32 and File is a pointer to FILE. + Value *emitFGetSUnlocked(Value *Str, Value *Size, Value *File, IRBuilder<> &B, + const TargetLibraryInfo *TLI); + + /// Emit a call to the fread_unlocked function. This assumes that Ptr is a + /// pointer, Size is an 'intptr_t', N is nmemb and File is a pointer to FILE. + Value *emitFReadUnlocked(Value *Ptr, Value *Size, Value *N, Value *File, + IRBuilder<> &B, const DataLayout &DL, + const TargetLibraryInfo *TLI); } #endif diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h b/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h index 178bae76cef6..7531fb2d69b3 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/Cloning.h @@ -49,15 +49,15 @@ class ReturnInst; /// Return an exact copy of the specified module /// -std::unique_ptr<Module> CloneModule(const Module *M); -std::unique_ptr<Module> CloneModule(const Module *M, ValueToValueMapTy &VMap); +std::unique_ptr<Module> CloneModule(const Module &M); +std::unique_ptr<Module> CloneModule(const Module &M, ValueToValueMapTy &VMap); /// Return a copy of the specified module. The ShouldCloneDefinition function /// controls whether a specific GlobalValue's definition is cloned. If the /// function returns false, the module copy will contain an external reference /// in place of the global definition. std::unique_ptr<Module> -CloneModule(const Module *M, ValueToValueMapTy &VMap, +CloneModule(const Module &M, ValueToValueMapTy &VMap, function_ref<bool(const GlobalValue *)> ShouldCloneDefinition); /// ClonedCodeInfo - This struct can be used to capture information about code @@ -240,7 +240,7 @@ bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI, AAResults *CalleeAAR = nullptr, bool InsertLifetime = true, Function *ForwardVarArgsTo = nullptr); -/// \brief Clones a loop \p OrigLoop. Returns the loop and the blocks in \p +/// Clones a loop \p OrigLoop. Returns the loop and the blocks in \p /// Blocks. /// /// Updates LoopInfo and DominatorTree assuming the loop is dominated by block @@ -252,7 +252,7 @@ Loop *cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB, DominatorTree *DT, SmallVectorImpl<BasicBlock *> &Blocks); -/// \brief Remaps instructions in \p Blocks using the mapping in \p VMap. +/// Remaps instructions in \p Blocks using the mapping in \p VMap. void remapInstructionsInBlocks(const SmallVectorImpl<BasicBlock *> &Blocks, ValueToValueMapTy &VMap); @@ -265,7 +265,8 @@ void remapInstructionsInBlocks(const SmallVectorImpl<BasicBlock *> &Blocks, BasicBlock * DuplicateInstructionsInSplitBetween(BasicBlock *BB, BasicBlock *PredBB, Instruction *StopAt, - ValueToValueMapTy &ValueMapping); + ValueToValueMapTy &ValueMapping, + DominatorTree *DT = nullptr); } // end namespace llvm #endif // LLVM_TRANSFORMS_UTILS_CLONING_H diff --git a/contrib/llvm/include/llvm/Transforms/Utils/CodeExtractor.h b/contrib/llvm/include/llvm/Transforms/Utils/CodeExtractor.h index 63d34511102d..fab8334d4c66 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/CodeExtractor.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/CodeExtractor.h @@ -34,7 +34,7 @@ class Module; class Type; class Value; - /// \brief Utility class for extracting code into a new function. + /// Utility class for extracting code into a new function. /// /// This utility provides a simple interface for extracting some sequence of /// code into its own function, replacing it with a call to that function. It @@ -65,20 +65,22 @@ class Value; Type *RetTy; public: - /// \brief Create a code extractor for a sequence of blocks. + /// Create a code extractor for a sequence of blocks. /// /// Given a sequence of basic blocks where the first block in the sequence /// dominates the rest, prepare a code extractor object for pulling this /// sequence out into its new function. When a DominatorTree is also given, /// extra checking and transformations are enabled. If AllowVarArgs is true, /// vararg functions can be extracted. This is safe, if all vararg handling - /// code is extracted, including vastart. + /// code is extracted, including vastart. If AllowAlloca is true, then + /// extraction of blocks containing alloca instructions would be possible, + /// however code extractor won't validate whether extraction is legal. CodeExtractor(ArrayRef<BasicBlock *> BBs, DominatorTree *DT = nullptr, bool AggregateArgs = false, BlockFrequencyInfo *BFI = nullptr, BranchProbabilityInfo *BPI = nullptr, - bool AllowVarArgs = false); + bool AllowVarArgs = false, bool AllowAlloca = false); - /// \brief Create a code extractor for a loop body. + /// Create a code extractor for a loop body. /// /// Behaves just like the generic code sequence constructor, but uses the /// block sequence of the loop. @@ -86,27 +88,19 @@ class Value; BlockFrequencyInfo *BFI = nullptr, BranchProbabilityInfo *BPI = nullptr); - /// \brief Check to see if a block is valid for extraction. - /// - /// Blocks containing EHPads, allocas and invokes are not valid. If - /// AllowVarArgs is true, blocks with vastart can be extracted. This is - /// safe, if all vararg handling code is extracted, including vastart. - static bool isBlockValidForExtraction(const BasicBlock &BB, - bool AllowVarArgs); - - /// \brief Perform the extraction, returning the new function. + /// Perform the extraction, returning the new function. /// /// Returns zero when called on a CodeExtractor instance where isEligible /// returns false. Function *extractCodeRegion(); - /// \brief Test whether this code extractor is eligible. + /// Test whether this code extractor is eligible. /// /// Based on the blocks used when constructing the code extractor, /// determine whether it is eligible for extraction. bool isEligible() const { return !Blocks.empty(); } - /// \brief Compute the set of input values and output values for the code. + /// Compute the set of input values and output values for the code. /// /// These can be used either when performing the extraction or to evaluate /// the expected size of a call to the extracted function. Note that this diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Evaluator.h b/contrib/llvm/include/llvm/Transforms/Utils/Evaluator.h index 0e987b93177a..9908ae6fd393 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/Evaluator.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/Evaluator.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" @@ -73,6 +74,18 @@ public: ValueStack.back()[V] = C; } + /// Given call site return callee and list of its formal arguments + Function *getCalleeWithFormalArgs(CallSite &CS, + SmallVector<Constant *, 8> &Formals); + + /// Given call site and callee returns list of callee formal argument + /// values converting them when necessary + bool getFormalParams(CallSite &CS, Function *F, + SmallVector<Constant *, 8> &Formals); + + /// Casts call result to a type of bitcast call expression + Constant *castCallResultIfNeeded(Value *CallExpr, Constant *RV); + const DenseMap<Constant*, Constant*> &getMutatedMemory() const { return MutatedMemory; } diff --git a/contrib/llvm/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h b/contrib/llvm/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h index b7a3d130aa11..b55a9893bcf7 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h @@ -22,7 +22,7 @@ namespace llvm { class Module; class Function; -/// \brief Calculate and dump ThinLTO specific inliner stats. +/// Calculate and dump ThinLTO specific inliner stats. /// The main statistics are: /// (1) Number of inlined imported functions, /// (2) Number of imported functions inlined into importing module (indirect), diff --git a/contrib/llvm/include/llvm/Transforms/Utils/IntegerDivision.h b/contrib/llvm/include/llvm/Transforms/Utils/IntegerDivision.h index 0ec3321b9cf8..5d9927eb51b2 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/IntegerDivision.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/IntegerDivision.h @@ -29,7 +29,7 @@ namespace llvm { /// e.g. when more information about the operands are known. Implements both /// 32bit and 64bit scalar division. /// - /// @brief Replace Rem with generated code. + /// Replace Rem with generated code. bool expandRemainder(BinaryOperator *Rem); /// Generate code to divide two integers, replacing Div with the generated @@ -38,7 +38,7 @@ namespace llvm { /// when more information about the operands are known. Implements both /// 32bit and 64bit scalar division. /// - /// @brief Replace Div with generated code. + /// Replace Div with generated code. bool expandDivision(BinaryOperator* Div); /// Generate code to calculate the remainder of two integers, replacing Rem @@ -46,26 +46,26 @@ namespace llvm { /// makes it useful for targets with little or no support for less than /// 32 bit arithmetic. /// - /// @brief Replace Rem with generated code. + /// 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. + /// Replace Rem with generated code. bool expandRemainderUpTo64Bits(BinaryOperator *Rem); /// Generate code to divide two integers, replacing Div with the generated /// code. Uses ExpandDivision with a 32bit Div which makes it useful for /// targets with little or no support for less than 32 bit arithmetic. /// - /// @brief Replace Rem with generated code. + /// 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. + /// Replace Rem with generated code. bool expandDivisionUpTo64Bits(BinaryOperator *Div); } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Transforms/Utils/Local.h b/contrib/llvm/include/llvm/Transforms/Utils/Local.h index 01db88bc15c2..b8df32565723 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/Local.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/Local.h @@ -16,10 +16,12 @@ #define LLVM_TRANSFORMS_UTILS_LOCAL_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/Utils/Local.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" @@ -117,7 +119,8 @@ struct SimplifyCFGOptions { /// conditions and indirectbr addresses this might make dead if /// DeleteDeadConditions is true. bool ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions = false, - const TargetLibraryInfo *TLI = nullptr); + const TargetLibraryInfo *TLI = nullptr, + DeferredDominance *DDT = nullptr); //===----------------------------------------------------------------------===// // Local dead code elimination. @@ -140,6 +143,18 @@ bool wouldInstructionBeTriviallyDead(Instruction *I, bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI = nullptr); +/// Delete all of the instructions in `DeadInsts`, and all other instructions +/// that deleting these in turn causes to be trivially dead. +/// +/// The initial instructions in the provided vector must all have empty use +/// lists and satisfy `isInstructionTriviallyDead`. +/// +/// `DeadInsts` will be used as scratch storage for this routine and will be +/// empty afterward. +void RecursivelyDeleteTriviallyDeadInstructions( + SmallVectorImpl<Instruction *> &DeadInsts, + const TargetLibraryInfo *TLI = nullptr); + /// If the specified value is an effectively dead PHI node, due to being a /// def-use chain of single-use nodes that either forms a cycle or is terminated /// by a trivially dead instruction, delete it. If that makes any of its @@ -171,18 +186,21 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB, /// /// .. and delete the predecessor corresponding to the '1', this will attempt to /// recursively fold the 'and' to 0. -void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred); +void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, + DeferredDominance *DDT = nullptr); /// BB is a block with one predecessor and its predecessor is known to have one /// successor (BB!). Eliminate the edge between them, moving the instructions in /// the predecessor into BB. This deletes the predecessor block. -void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr); +void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, DominatorTree *DT = nullptr, + DeferredDominance *DDT = nullptr); /// BB is known to contain an unconditional branch, and contains no instructions /// other than PHI nodes, potential debug intrinsics and the branch. If /// possible, eliminate BB by rewriting all the predecessors to branch to the /// successor block and return true. If we can't transform, return false. -bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB); +bool TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB, + DeferredDominance *DDT = nullptr); /// Check for and eliminate duplicate PHI nodes in this block. This doesn't try /// to be clever about PHI nodes which differ only in the order of the incoming @@ -246,72 +264,6 @@ inline unsigned getKnownAlignment(Value *V, const DataLayout &DL, return getOrEnforceKnownAlignment(V, 0, DL, CxtI, AC, DT); } -/// Given a getelementptr instruction/constantexpr, emit the code necessary to -/// compute the offset from the base pointer (without adding in the base -/// pointer). Return the result as a signed integer of intptr size. -/// When NoAssumptions is true, no assumptions about index computation not -/// overflowing is made. -template <typename IRBuilderTy> -Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP, - bool NoAssumptions = false) { - GEPOperator *GEPOp = cast<GEPOperator>(GEP); - Type *IntPtrTy = DL.getIntPtrType(GEP->getType()); - Value *Result = Constant::getNullValue(IntPtrTy); - - // If the GEP is inbounds, we know that none of the addressing operations will - // overflow in an unsigned sense. - bool isInBounds = GEPOp->isInBounds() && !NoAssumptions; - - // Build a mask for high order bits. - unsigned IntPtrWidth = IntPtrTy->getScalarType()->getIntegerBitWidth(); - uint64_t PtrSizeMask = - std::numeric_limits<uint64_t>::max() >> (64 - IntPtrWidth); - - gep_type_iterator GTI = gep_type_begin(GEP); - for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; - ++i, ++GTI) { - Value *Op = *i; - uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType()) & PtrSizeMask; - if (Constant *OpC = dyn_cast<Constant>(Op)) { - if (OpC->isZeroValue()) - continue; - - // Handle a struct index, which adds its field offset to the pointer. - if (StructType *STy = GTI.getStructTypeOrNull()) { - if (OpC->getType()->isVectorTy()) - OpC = OpC->getSplatValue(); - - uint64_t OpValue = cast<ConstantInt>(OpC)->getZExtValue(); - Size = DL.getStructLayout(STy)->getElementOffset(OpValue); - - if (Size) - Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size), - GEP->getName()+".offs"); - continue; - } - - Constant *Scale = ConstantInt::get(IntPtrTy, Size); - Constant *OC = ConstantExpr::getIntegerCast(OpC, IntPtrTy, true /*SExt*/); - Scale = ConstantExpr::getMul(OC, Scale, isInBounds/*NUW*/); - // Emit an add instruction. - Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs"); - continue; - } - // Convert to correct type. - if (Op->getType() != IntPtrTy) - Op = Builder->CreateIntCast(Op, IntPtrTy, true, Op->getName()+".c"); - if (Size != 1) { - // We'll let instcombine(mul) convert this to a shl if possible. - Op = Builder->CreateMul(Op, ConstantInt::get(IntPtrTy, Size), - GEP->getName()+".idx", isInBounds /*NUW*/); - } - - // Emit an add instruction. - Result = Builder->CreateAdd(Op, Result, GEP->getName()+".offs"); - } - return Result; -} - ///===---------------------------------------------------------------------===// /// Dbg Intrinsic utilities /// @@ -335,6 +287,10 @@ void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII, /// llvm.dbg.value intrinsics. bool LowerDbgDeclare(Function &F); +/// Propagate dbg.value intrinsics through the newly inserted PHIs. +void insertDebugValuesForPHIs(BasicBlock *BB, + SmallVectorImpl<PHINode *> &InsertedPHIs); + /// Finds all intrinsics declaring local variables as living in the memory that /// 'V' points to. This may include a mix of dbg.declare and /// dbg.addr intrinsics. @@ -343,6 +299,9 @@ TinyPtrVector<DbgInfoIntrinsic *> FindDbgAddrUses(Value *V); /// Finds the llvm.dbg.value intrinsics describing a value. void findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V); +/// Finds the debug info intrinsics describing a value. +void findDbgUsers(SmallVectorImpl<DbgInfoIntrinsic *> &DbgInsts, Value *V); + /// Replaces llvm.dbg.declare instruction when the address it /// describes is replaced with a new value. If Deref is true, an /// additional DW_OP_deref is prepended to the expression. If Offset @@ -357,7 +316,7 @@ bool replaceDbgDeclare(Value *Address, Value *NewAddress, /// DW_OP_deref is prepended to the expression. If Offset is non-zero, /// a constant displacement is added to the expression (between the /// optional Deref operations). Offset can be negative. The new -/// llvm.dbg.declare is inserted immediately before AI. +/// llvm.dbg.declare is inserted immediately after AI. bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, DIBuilder &Builder, bool DerefBefore, int Offset, bool DerefAfter); @@ -370,10 +329,27 @@ bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, void replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress, DIBuilder &Builder, int Offset = 0); -/// Assuming the instruction \p I is going to be deleted, attempt to salvage any -/// dbg.value intrinsics referring to \p I by rewriting its effect into a -/// DIExpression. -void salvageDebugInfo(Instruction &I); +/// Assuming the instruction \p I is going to be deleted, attempt to salvage +/// debug users of \p I by writing the effect of \p I in a DIExpression. +/// Returns true if any debug users were updated. +bool salvageDebugInfo(Instruction &I); + +/// Point debug users of \p From to \p To or salvage them. Use this function +/// only when replacing all uses of \p From with \p To, with a guarantee that +/// \p From is going to be deleted. +/// +/// Follow these rules to prevent use-before-def of \p To: +/// . If \p To is a linked Instruction, set \p DomPoint to \p To. +/// . If \p To is an unlinked Instruction, set \p DomPoint to the Instruction +/// \p To will be inserted after. +/// . If \p To is not an Instruction (e.g a Constant), the choice of +/// \p DomPoint is arbitrary. Pick \p From for simplicity. +/// +/// If a debug user cannot be preserved without reordering variable updates or +/// introducing a use-before-def, it is either salvaged (\ref salvageDebugInfo) +/// or deleted. Returns true if any debug users were updated. +bool replaceAllDbgUsesWith(Instruction &From, Value &To, Instruction &DomPoint, + DominatorTree &DT); /// Remove all instructions from a basic block other than it's terminator /// and any present EH pad instructions. @@ -382,7 +358,8 @@ unsigned removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB); /// Insert an unreachable instruction before the specified /// instruction, making it and the rest of the code in the block dead. unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap, - bool PreserveLCSSA = false); + bool PreserveLCSSA = false, + DeferredDominance *DDT = nullptr); /// Convert the CallInst to InvokeInst with the specified unwind edge basic /// block. This also splits the basic block where CI is located, because @@ -397,12 +374,13 @@ BasicBlock *changeToInvokeAndSplitBasicBlock(CallInst *CI, /// /// \param BB Block whose terminator will be replaced. Its terminator must /// have an unwind successor. -void removeUnwindEdge(BasicBlock *BB); +void removeUnwindEdge(BasicBlock *BB, DeferredDominance *DDT = nullptr); /// Remove all blocks that can not be reached from the function's entry. /// /// Returns true if any basic block was removed. -bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr); +bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI = nullptr, + DeferredDominance *DDT = nullptr); /// Combine the metadata of two instructions so that K can replace J /// diff --git a/contrib/llvm/include/llvm/Transforms/Utils/LoopRotationUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/LoopRotationUtils.h new file mode 100644 index 000000000000..231e5bbb6dee --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/Utils/LoopRotationUtils.h @@ -0,0 +1,40 @@ +//===- LoopRotationUtils.h - Utilities to perform loop rotation -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides utilities to convert a loop into a loop with bottom test. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_LOOPROTATIONUTILS_H +#define LLVM_TRANSFORMS_UTILS_LOOPROTATIONUTILS_H + +namespace llvm { + +class AssumptionCache; +class DominatorTree; +class Loop; +class LoopInfo; +class ScalarEvolution; +struct SimplifyQuery; +class TargetTransformInfo; + +/// Convert a loop into a loop with bottom test. It may +/// perform loop latch simplication as well if the flag RotationOnly +/// is false. The flag Threshold represents the size threshold of the loop +/// header. If the loop header's size exceeds the threshold, the loop rotation +/// will give up. The flag IsUtilMode controls the heuristic used in the +/// LoopRotation. If it is true, the profitability heuristic will be ignored. +bool LoopRotation(Loop *L, LoopInfo *LI, const TargetTransformInfo *TTI, + AssumptionCache *AC, DominatorTree *DT, ScalarEvolution *SE, + const SimplifyQuery &SQ, bool RotationOnly, + unsigned Threshold, bool IsUtilMode); + +} // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Transforms/Utils/LoopSimplify.h b/contrib/llvm/include/llvm/Transforms/Utils/LoopSimplify.h index f3828bc16e2f..166da2738ffd 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/LoopSimplify.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/LoopSimplify.h @@ -52,7 +52,7 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Simplify each loop in a loop nest recursively. +/// 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 diff --git a/contrib/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/LoopUtils.h index fb53647112f9..eb4c99102a63 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/LoopUtils.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/LoopUtils.h @@ -23,6 +23,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/DemandedBits.h" #include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/MustExecute.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IRBuilder.h" @@ -47,17 +48,6 @@ class SCEV; class TargetLibraryInfo; class TargetTransformInfo; -/// \brief Captures loop safety information. -/// It keep information for loop & its header may throw exception. -struct LoopSafetyInfo { - bool MayThrow = false; // The current loop contains an instruction which - // may throw. - bool HeaderMayThrow = false; // Same as previous, but specific to loop header - // Used to update funclet bundle operands. - DenseMap<BasicBlock *, ColorVector> BlockColors; - - LoopSafetyInfo() = default; -}; /// The RecurrenceDescriptor is used to identify recurrences variables in a /// loop. Reduction is a special case of recurrence that has uses of the @@ -299,16 +289,16 @@ public: /// induction, the induction descriptor \p D will contain the data describing /// this induction. If by some other means the caller has a better SCEV /// expression for \p Phi than the one returned by the ScalarEvolution - /// analysis, it can be passed through \p Expr. If the def-use chain + /// analysis, it can be passed through \p Expr. If the def-use chain /// associated with the phi includes casts (that we know we can ignore /// under proper runtime checks), they are passed through \p CastsToIgnore. - static bool + static bool isInductionPHI(PHINode *Phi, const Loop* L, ScalarEvolution *SE, InductionDescriptor &D, const SCEV *Expr = nullptr, SmallVectorImpl<Instruction *> *CastsToIgnore = nullptr); /// Returns true if \p Phi is a floating point induction in the loop \p L. - /// If \p Phi is an induction, the induction descriptor \p D will contain + /// If \p Phi is an induction, the induction descriptor \p D will contain /// the data describing this induction. static bool isFPInductionPHI(PHINode *Phi, const Loop* L, ScalarEvolution *SE, InductionDescriptor &D); @@ -344,11 +334,11 @@ public: Instruction::BinaryOpsEnd; } - /// Returns a reference to the type cast instructions in the induction + /// Returns a reference to the type cast instructions in the induction /// update chain, that are redundant when guarded with a runtime /// SCEV overflow check. - const SmallVectorImpl<Instruction *> &getCastInsts() const { - return RedundantCasts; + const SmallVectorImpl<Instruction *> &getCastInsts() const { + return RedundantCasts; } private: @@ -395,7 +385,7 @@ bool formDedicatedExitBlocks(Loop *L, DominatorTree *DT, LoopInfo *LI, bool formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist, DominatorTree &DT, LoopInfo &LI); -/// \brief Put loop into LCSSA form. +/// 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 @@ -408,7 +398,7 @@ bool formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist, /// Returns true if any modifications are made to the loop. bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE); -/// \brief Put a loop nest into LCSSA form. +/// Put a loop nest into LCSSA form. /// /// This recursively forms LCSSA for a loop nest. /// @@ -420,7 +410,7 @@ bool formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE); bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI, ScalarEvolution *SE); -/// \brief Walk the specified region of the CFG (defined by all blocks +/// Walk the specified region of the CFG (defined by all blocks /// dominated by the specified block, and that are in the current loop) in /// reverse depth first order w.r.t the DominatorTree. This allows us to visit /// uses before definitions, allowing us to sink a loop body in one pass without @@ -433,7 +423,7 @@ bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, AliasSetTracker *, LoopSafetyInfo *, OptimizationRemarkEmitter *ORE); -/// \brief Walk the specified region of the CFG (defined by all blocks +/// Walk the specified region of the CFG (defined by all blocks /// dominated by the specified block, and that are in the current loop) in depth /// first order w.r.t the DominatorTree. This allows us to visit definitions /// before uses, allowing us to hoist a loop body in one pass without iteration. @@ -459,7 +449,7 @@ bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *, void deleteDeadLoop(Loop *L, DominatorTree *DT, ScalarEvolution *SE, LoopInfo *LI); -/// \brief Try to promote memory values to scalars by sinking stores out of +/// Try to promote memory values to scalars by sinking stores out of /// the loop and moving loads to before the loop. We do this by looping over /// the stores in the loop, looking for stores to Must pointers which are /// loop invariant. It takes a set of must-alias values, Loop exit blocks @@ -480,22 +470,10 @@ bool promoteLoopAccessesToScalars(const SmallSetVector<Value *, 8> &, SmallVector<DomTreeNode *, 16> collectChildrenInLoop(DomTreeNode *N, const Loop *CurLoop); -/// \brief Computes safety information for a loop -/// checks loop body & header for the possibility of may throw -/// exception, it takes LoopSafetyInfo and loop as argument. -/// Updates safety information in LoopSafetyInfo argument. -void computeLoopSafetyInfo(LoopSafetyInfo *, Loop *); - -/// Returns true if the instruction in a loop is guaranteed to execute at least -/// once. -bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, - const Loop *CurLoop, - const LoopSafetyInfo *SafetyInfo); - -/// \brief Returns the instructions that use values defined in the loop. +/// Returns the instructions that use values defined in the loop. SmallVector<Instruction *, 8> findDefsUsedOutsideOfLoop(Loop *L); -/// \brief Find string metadata for loop +/// Find string metadata for loop /// /// If it has a value (e.g. {"llvm.distribute", 1} return the value as an /// operand or null otherwise. If the string metadata is not found return @@ -503,11 +481,11 @@ SmallVector<Instruction *, 8> findDefsUsedOutsideOfLoop(Loop *L); Optional<const MDOperand *> findStringMetadataForLoop(Loop *TheLoop, StringRef Name); -/// \brief Set input string into loop metadata by keeping other values intact. +/// Set input string into loop metadata by keeping other values intact. void addStringMetadataToLoop(Loop *TheLoop, const char *MDString, unsigned V = 0); -/// \brief Get a loop's estimated trip count based on branch weight metadata. +/// Get a loop's estimated trip count based on branch weight metadata. /// Returns 0 when the count is estimated to be 0, or None when a meaningful /// estimate can not be made. Optional<unsigned> getLoopEstimatedTripCount(Loop *L); @@ -531,11 +509,18 @@ bool canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, LoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE = nullptr); +/// Generates an ordered vector reduction using extracts to reduce the value. +Value * +getOrderedReduction(IRBuilder<> &Builder, Value *Acc, Value *Src, unsigned Op, + RecurrenceDescriptor::MinMaxRecurrenceKind MinMaxKind = + RecurrenceDescriptor::MRK_Invalid, + ArrayRef<Value *> RedOps = None); + /// Generates a vector reduction using shufflevectors to reduce the value. Value *getShuffleReduction(IRBuilder<> &Builder, Value *Src, unsigned Op, RecurrenceDescriptor::MinMaxRecurrenceKind MinMaxKind = RecurrenceDescriptor::MRK_Invalid, - ArrayRef<Value *> RedOps = ArrayRef<Value *>()); + ArrayRef<Value *> RedOps = None); /// Create a target reduction of the given vector. The reduction operation /// is described by the \p Opcode parameter. min/max reductions require @@ -547,7 +532,7 @@ createSimpleTargetReduction(IRBuilder<> &B, const TargetTransformInfo *TTI, unsigned Opcode, Value *Src, TargetTransformInfo::ReductionFlags Flags = TargetTransformInfo::ReductionFlags(), - ArrayRef<Value *> RedOps = ArrayRef<Value *>()); + ArrayRef<Value *> RedOps = None); /// Create a generic target reduction using a recurrence descriptor \p Desc /// The target is queried to determine if intrinsics or shuffle sequences are diff --git a/contrib/llvm/include/llvm/Transforms/Utils/LoopVersioning.h b/contrib/llvm/include/llvm/Transforms/Utils/LoopVersioning.h index fa5d7845d080..fcd734b37a1f 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/LoopVersioning.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/LoopVersioning.h @@ -28,14 +28,14 @@ class LoopAccessInfo; class LoopInfo; class ScalarEvolution; -/// \brief This class emits a version of the loop where run-time checks ensure +/// This class emits a version of the loop where run-time checks ensure /// that may-alias pointers can't overlap. /// /// It currently only supports single-exit loops and assumes that the loop /// already has a preheader. class LoopVersioning { public: - /// \brief Expects LoopAccessInfo, Loop, LoopInfo, DominatorTree as input. + /// Expects LoopAccessInfo, Loop, LoopInfo, DominatorTree as input. /// It uses runtime check provided by the user. If \p UseLAIChecks is true, /// we will retain the default checks made by LAI. Otherwise, construct an /// object having no checks and we expect the user to add them. @@ -43,7 +43,7 @@ public: DominatorTree *DT, ScalarEvolution *SE, bool UseLAIChecks = true); - /// \brief Performs the CFG manipulation part of versioning the loop including + /// Performs the CFG manipulation part of versioning the loop including /// the DominatorTree and LoopInfo updates. /// /// The loop that was used to construct the class will be the "versioned" loop @@ -58,38 +58,38 @@ public: /// transform L void versionLoop() { versionLoop(findDefsUsedOutsideOfLoop(VersionedLoop)); } - /// \brief Same but if the client has already precomputed the set of values + /// Same but if the client has already precomputed the set of values /// used outside the loop, this API will allows passing that. void versionLoop(const SmallVectorImpl<Instruction *> &DefsUsedOutside); - /// \brief Returns the versioned loop. Control flows here if pointers in the + /// Returns the versioned loop. Control flows here if pointers in the /// loop don't alias (i.e. all memchecks passed). (This loop is actually the /// same as the original loop that we got constructed with.) Loop *getVersionedLoop() { return VersionedLoop; } - /// \brief Returns the fall-back loop. Control flows here if pointers in the + /// Returns the fall-back loop. Control flows here if pointers in the /// loop may alias (i.e. one of the memchecks failed). Loop *getNonVersionedLoop() { return NonVersionedLoop; } - /// \brief Sets the runtime alias checks for versioning the loop. + /// Sets the runtime alias checks for versioning the loop. void setAliasChecks( SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks); - /// \brief Sets the runtime SCEV checks for versioning the loop. + /// Sets the runtime SCEV checks for versioning the loop. void setSCEVChecks(SCEVUnionPredicate Check); - /// \brief Annotate memory instructions in the versioned loop with no-alias + /// Annotate memory instructions in the versioned loop with no-alias /// metadata based on the memchecks issued. /// /// This is just wrapper that calls prepareNoAliasMetadata and /// annotateInstWithNoAlias on the instructions of the versioned loop. void annotateLoopWithNoAlias(); - /// \brief Set up the aliasing scopes based on the memchecks. This needs to + /// Set up the aliasing scopes based on the memchecks. This needs to /// be called before the first call to annotateInstWithNoAlias. void prepareNoAliasMetadata(); - /// \brief Add the noalias annotations to \p VersionedInst. + /// Add the noalias annotations to \p VersionedInst. /// /// \p OrigInst is the instruction corresponding to \p VersionedInst in the /// original loop. Initialize the aliasing scopes with @@ -98,50 +98,50 @@ public: const Instruction *OrigInst); private: - /// \brief Adds the necessary PHI nodes for the versioned loops based on the + /// Adds the necessary PHI nodes for the versioned loops based on the /// loop-defined values used outside of the loop. /// /// This needs to be called after versionLoop if there are defs in the loop /// that are used outside the loop. void addPHINodes(const SmallVectorImpl<Instruction *> &DefsUsedOutside); - /// \brief Add the noalias annotations to \p I. Initialize the aliasing + /// Add the noalias annotations to \p I. Initialize the aliasing /// scopes with prepareNoAliasMetadata once before this can be called. void annotateInstWithNoAlias(Instruction *I) { annotateInstWithNoAlias(I, I); } - /// \brief The original loop. This becomes the "versioned" one. I.e., + /// The original loop. This becomes the "versioned" one. I.e., /// control flows here if pointers in the loop don't alias. Loop *VersionedLoop; - /// \brief The fall-back loop. I.e. control flows here if pointers in the + /// The fall-back loop. I.e. control flows here if pointers in the /// loop may alias (memchecks failed). Loop *NonVersionedLoop; - /// \brief This maps the instructions from VersionedLoop to their counterpart + /// This maps the instructions from VersionedLoop to their counterpart /// in NonVersionedLoop. ValueToValueMapTy VMap; - /// \brief The set of alias checks that we are versioning for. + /// The set of alias checks that we are versioning for. SmallVector<RuntimePointerChecking::PointerCheck, 4> AliasChecks; - /// \brief The set of SCEV checks that we are versioning for. + /// The set of SCEV checks that we are versioning for. SCEVUnionPredicate Preds; - /// \brief Maps a pointer to the pointer checking group that the pointer + /// Maps a pointer to the pointer checking group that the pointer /// belongs to. DenseMap<const Value *, const RuntimePointerChecking::CheckingPtrGroup *> PtrToGroup; - /// \brief The alias scope corresponding to a pointer checking group. + /// The alias scope corresponding to a pointer checking group. DenseMap<const RuntimePointerChecking::CheckingPtrGroup *, MDNode *> GroupToScope; - /// \brief The list of alias scopes that a pointer checking group can't alias. + /// The list of alias scopes that a pointer checking group can't alias. DenseMap<const RuntimePointerChecking::CheckingPtrGroup *, MDNode *> GroupToNonAliasingScopeList; - /// \brief Analyses used. + /// Analyses used. const LoopAccessInfo &LAI; LoopInfo *LI; DominatorTree *DT; diff --git a/contrib/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/contrib/llvm/include/llvm/Transforms/Utils/ModuleUtils.h index 4b9bc8293810..14615c25d093 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/ModuleUtils.h @@ -49,7 +49,7 @@ Function *checkSanitizerInterfaceFunction(Constant *FuncOrBitcast); Function *declareSanitizerInitFunction(Module &M, StringRef InitName, ArrayRef<Type *> InitArgTypes); -/// \brief Creates sanitizer constructor function, and calls sanitizer's init +/// Creates sanitizer constructor function, and calls sanitizer's init /// function from it. /// \return Returns pair of pointers to constructor, and init functions /// respectively. @@ -62,10 +62,10 @@ std::pair<Function *, Function *> createSanitizerCtorAndInitFunctions( /// the list of public globals in the module. bool nameUnamedGlobals(Module &M); -/// \brief Adds global values to the llvm.used list. +/// Adds global values to the llvm.used list. void appendToUsed(Module &M, ArrayRef<GlobalValue *> Values); -/// \brief Adds global values to the llvm.compiler.used list. +/// Adds global values to the llvm.compiler.used list. void appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values); /// Filter out potentially dead comdat functions where other entries keep the @@ -84,7 +84,7 @@ void appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values); void filterDeadComdatFunctions( Module &M, SmallVectorImpl<Function *> &DeadComdatFunctions); -/// \brief Produce a unique identifier for this module by taking the MD5 sum of +/// Produce a unique identifier for this module by taking the MD5 sum of /// the names of the module's strong external symbols that are not comdat /// members. /// diff --git a/contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h b/contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h index 165d4bdaa6d4..7f57fde638b8 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h @@ -35,6 +35,11 @@ class OrderedInstructions { /// The dominator tree of the parent function. DominatorTree *DT; + /// Return true if the first instruction comes before the second in the + /// same basic block. It will create an ordered basic block, if it does + /// not yet exist in OBBMap. + bool localDominates(const Instruction *, const Instruction *) const; + public: /// Constructor. OrderedInstructions(DominatorTree *DT) : DT(DT) {} @@ -42,6 +47,12 @@ public: /// Return true if first instruction dominates the second. bool dominates(const Instruction *, const Instruction *) const; + /// Return true if the first instruction comes before the second in the + /// dominator tree DFS traversal if they are in different basic blocks, + /// or if the first instruction comes before the second in the same basic + /// block. + bool dfsBefore(const Instruction *, const Instruction *) const; + /// Invalidate the OrderedBasicBlock cache when its basic block changes. /// i.e. If an instruction is deleted or added to the basic block, the user /// should call this function to invalidate the OrderedBasicBlock cache for diff --git a/contrib/llvm/include/llvm/Transforms/Utils/PredicateInfo.h b/contrib/llvm/include/llvm/Transforms/Utils/PredicateInfo.h index 8150f1528397..b53eda7e5a42 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/PredicateInfo.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/PredicateInfo.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file implements the PredicateInfo analysis, which creates an Extended +/// This file implements the PredicateInfo analysis, which creates an Extended /// SSA form for operations used in branch comparisons and llvm.assume /// comparisons. /// @@ -31,7 +31,7 @@ /// %cmp = icmp eq i32, %x, 50 /// br i1 %cmp, label %true, label %false /// true: -/// %x.0 = call @llvm.ssa_copy.i32(i32 %x) +/// %x.0 = call \@llvm.ssa_copy.i32(i32 %x) /// ret i32 %x.0 /// false: /// ret i32 1 @@ -54,6 +54,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" @@ -69,6 +70,7 @@ #include "llvm/IR/Use.h" #include "llvm/IR/User.h" #include "llvm/IR/Value.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include "llvm/PassAnalysisSupport.h" #include "llvm/Support/Casting.h" @@ -193,7 +195,7 @@ namespace PredicateInfoClasses { struct ValueDFS; } -/// \brief Encapsulates PredicateInfo, including all data associated with memory +/// Encapsulates PredicateInfo, including all data associated with memory /// accesses. class PredicateInfo { private: @@ -261,6 +263,8 @@ private: // The set of edges along which we can only handle phi uses, due to critical // edges. DenseSet<std::pair<BasicBlock *, BasicBlock *>> EdgeUsesOnly; + // The set of ssa_copy declarations we created with our custom mangling. + SmallSet<AssertingVH<Function>, 20> CreatedDeclarations; }; // This pass does eager building and then printing of PredicateInfo. It is used @@ -275,7 +279,7 @@ public: void getAnalysisUsage(AnalysisUsage &AU) const override; }; -/// \brief Printer pass for \c PredicateInfo. +/// Printer pass for \c PredicateInfo. class PredicateInfoPrinterPass : public PassInfoMixin<PredicateInfoPrinterPass> { raw_ostream &OS; @@ -285,7 +289,7 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -/// \brief Verifier pass for \c PredicateInfo. +/// Verifier pass for \c PredicateInfo. struct PredicateInfoVerifierPass : PassInfoMixin<PredicateInfoVerifierPass> { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; diff --git a/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h b/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h index bb8a61a474f2..5ddfbe2bf058 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -23,7 +23,7 @@ class DominatorTree; class AliasSetTracker; class AssumptionCache; -/// \brief Return true if this alloca is legal for promotion. +/// Return true if this alloca is legal for promotion. /// /// This is true if there are only loads, stores, and lifetime markers /// (transitively) using this alloca. This also enforces that there is only @@ -31,7 +31,7 @@ class AssumptionCache; /// markers. bool isAllocaPromotable(const AllocaInst *AI); -/// \brief Promote the specified list of alloca instructions into scalar +/// Promote the specified list of alloca instructions into scalar /// registers, inserting PHI nodes as appropriate. /// /// This function makes use of DominanceFrontier information. This function diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h index 6cd9f1539b0b..4a7911662990 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdater.h @@ -30,7 +30,7 @@ class Type; class Use; class Value; -/// \brief Helper class for SSA formation on a set of values defined in +/// Helper class for SSA formation on a set of values defined in /// multiple blocks. /// /// This is used when code duplication or another unstructured @@ -62,25 +62,25 @@ public: SSAUpdater &operator=(const SSAUpdater &) = delete; ~SSAUpdater(); - /// \brief Reset this object to get ready for a new set of SSA updates with + /// Reset this object to get ready for a new set of SSA updates with /// type 'Ty'. /// /// PHI nodes get a name based on 'Name'. void Initialize(Type *Ty, StringRef Name); - /// \brief Indicate that a rewritten value is available in the specified block + /// Indicate that a rewritten value is available in the specified block /// with the specified value. void AddAvailableValue(BasicBlock *BB, Value *V); - /// \brief Return true if the SSAUpdater already has a value for the specified + /// Return true if the SSAUpdater already has a value for the specified /// block. bool HasValueForBlock(BasicBlock *BB) const; - /// \brief Construct SSA form, materializing a value that is live at the end + /// Construct SSA form, materializing a value that is live at the end /// of the specified block. Value *GetValueAtEndOfBlock(BasicBlock *BB); - /// \brief Construct SSA form, materializing a value that is live in the + /// Construct SSA form, materializing a value that is live in the /// middle of the specified block. /// /// \c GetValueInMiddleOfBlock is the same as \c GetValueAtEndOfBlock except @@ -102,7 +102,7 @@ public: /// merge the appropriate values, and this value isn't live out of the block. Value *GetValueInMiddleOfBlock(BasicBlock *BB); - /// \brief Rewrite a use of the symbolic value. + /// Rewrite a use of the symbolic value. /// /// This handles PHI nodes, which use their value in the corresponding /// predecessor. Note that this will not work if the use is supposed to be @@ -111,7 +111,7 @@ public: /// be below it. void RewriteUse(Use &U); - /// \brief Rewrite a use like \c RewriteUse but handling in-block definitions. + /// Rewrite a use like \c RewriteUse but handling in-block definitions. /// /// This version of the method can rewrite uses in the same block as /// a definition, because it assumes that all uses of a value are below any @@ -122,7 +122,7 @@ private: Value *GetValueAtEndOfBlockInternal(BasicBlock *BB); }; -/// \brief Helper class for promoting a collection of loads and stores into SSA +/// Helper class for promoting a collection of loads and stores into SSA /// Form using the SSAUpdater. /// /// This handles complexities that SSAUpdater doesn't, such as multiple loads @@ -139,32 +139,32 @@ public: SSAUpdater &S, StringRef Name = StringRef()); virtual ~LoadAndStorePromoter() = default; - /// \brief This does the promotion. + /// This does the promotion. /// /// Insts is a list of loads and stores to promote, and Name is the basename /// for the PHIs to insert. After this is complete, the loads and stores are /// removed from the code. void run(const SmallVectorImpl<Instruction *> &Insts) const; - /// \brief Return true if the specified instruction is in the Inst list. + /// Return true if the specified instruction is in the Inst list. /// /// The Insts list is the one passed into the constructor. Clients should /// implement this with a more efficient version if possible. virtual bool isInstInList(Instruction *I, const SmallVectorImpl<Instruction *> &Insts) const; - /// \brief This hook is invoked after all the stores are found and inserted as + /// This hook is invoked after all the stores are found and inserted as /// available values. virtual void doExtraRewritesBeforeFinalDeletion() const {} - /// \brief Clients can choose to implement this to get notified right before + /// Clients can choose to implement this to get notified right before /// a load is RAUW'd another value. virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const {} - /// \brief Called before each instruction is deleted. + /// Called before each instruction is deleted. virtual void instructionDeleted(Instruction *I) const {} - /// \brief Called to update debug info associated with the instruction. + /// Called to update debug info associated with the instruction. virtual void updateDebugInfo(Instruction *I) const {} }; diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterBulk.h b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterBulk.h new file mode 100644 index 000000000000..53a608f01804 --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterBulk.h @@ -0,0 +1,92 @@ +//===- SSAUpdaterBulk.h - Unstructured SSA Update Tool ----------*- 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 SSAUpdaterBulk class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATERBULK_H +#define LLVM_TRANSFORMS_UTILS_SSAUPDATERBULK_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/PredIteratorCache.h" + +namespace llvm { + +class BasicBlock; +class PHINode; +template <typename T> class SmallVectorImpl; +class Type; +class Use; +class Value; +class DominatorTree; + +/// Helper class for SSA formation on a set of values defined in multiple +/// blocks. +/// +/// This is used when code duplication or another unstructured transformation +/// wants to rewrite a set of uses of one value with uses of a set of values. +/// The update is done only when RewriteAllUses is called, all other methods are +/// used for book-keeping. That helps to share some common computations between +/// updates of different uses (which is not the case when traditional SSAUpdater +/// is used). +class SSAUpdaterBulk { + struct RewriteInfo { + DenseMap<BasicBlock *, Value *> Defines; + SmallVector<Use *, 4> Uses; + StringRef Name; + Type *Ty; + RewriteInfo(){}; + RewriteInfo(StringRef &N, Type *T) : Name(N), Ty(T){}; + }; + SmallVector<RewriteInfo, 4> Rewrites; + + PredIteratorCache PredCache; + + Value *computeValueAt(BasicBlock *BB, RewriteInfo &R, DominatorTree *DT); + +public: + explicit SSAUpdaterBulk(){}; + SSAUpdaterBulk(const SSAUpdaterBulk &) = delete; + SSAUpdaterBulk &operator=(const SSAUpdaterBulk &) = delete; + ~SSAUpdaterBulk(){}; + + /// Add a new variable to the SSA rewriter. This needs to be called before + /// AddAvailableValue or AddUse calls. The return value is the variable ID, + /// which needs to be passed to AddAvailableValue and AddUse. + unsigned AddVariable(StringRef Name, Type *Ty); + + /// Indicate that a rewritten value is available in the specified block with + /// the specified value. + void AddAvailableValue(unsigned Var, BasicBlock *BB, Value *V); + + /// Record a use of the symbolic value. This use will be updated with a + /// rewritten value when RewriteAllUses is called. + void AddUse(unsigned Var, Use *U); + + /// Return true if the SSAUpdater already has a value for the specified + /// variable in the specified block. + bool HasValueForBlock(unsigned Var, BasicBlock *BB); + + /// Perform all the necessary updates, including new PHI-nodes insertion and + /// the requested uses update. + /// + /// The function requires dominator tree DT, which is used for computing + /// locations for new phi-nodes insertions. If a nonnull pointer to a vector + /// InsertedPHIs is passed, all the new phi-nodes will be added to this + /// vector. + void RewriteAllUses(DominatorTree *DT, + SmallVectorImpl<PHINode *> *InsertedPHIs = nullptr); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_UTILS_SSAUPDATERBULK_H diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterImpl.h b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterImpl.h index b1611d49a456..b7649ba88334 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterImpl.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/SSAUpdaterImpl.h @@ -379,7 +379,7 @@ public: Traits::AddPHIOperand(PHI, PredInfo->AvailableVal, Pred); } - DEBUG(dbgs() << " Inserted PHI: " << *PHI << "\n"); + LLVM_DEBUG(dbgs() << " Inserted PHI: " << *PHI << "\n"); // If the client wants to know about all new instructions, tell it. if (InsertedPHIs) InsertedPHIs->push_back(PHI); @@ -389,12 +389,8 @@ public: /// FindExistingPHI - Look through the PHI nodes in a block to see if any of /// them match what is needed. void FindExistingPHI(BlkT *BB, BlockListTy *BlockList) { - for (typename BlkT::iterator BBI = BB->begin(), BBE = BB->end(); - BBI != BBE; ++BBI) { - PhiT *SomePHI = Traits::InstrIsPHI(&*BBI); - if (!SomePHI) - break; - if (CheckIfPHIMatches(SomePHI)) { + for (auto &SomePHI : BB->phis()) { + if (CheckIfPHIMatches(&SomePHI)) { RecordMatchingPHIs(BlockList); break; } diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SimplifyInstructions.h b/contrib/llvm/include/llvm/Transforms/Utils/SimplifyInstructions.h deleted file mode 100644 index 3f838611626f..000000000000 --- a/contrib/llvm/include/llvm/Transforms/Utils/SimplifyInstructions.h +++ /dev/null @@ -1,31 +0,0 @@ -//===- SimplifyInstructions.h - Remove redundant instructions ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This is a utility pass used for testing the InstructionSimplify analysis. -// The analysis is applied to every instruction, and if it simplifies then the -// instruction is replaced by the simplification. If you are looking for a pass -// that performs serious instruction folding, use the instcombine pass instead. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYINSTRUCTIONS_H -#define LLVM_TRANSFORMS_UTILS_SIMPLIFYINSTRUCTIONS_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { - -/// This pass removes redundant instructions. -class InstSimplifierPass : public PassInfoMixin<InstSimplifierPass> { -public: - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); -}; -} // end namespace llvm - -#endif // LLVM_TRANSFORMS_UTILS_SIMPLIFYINSTRUCTIONS_H diff --git a/contrib/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/contrib/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h index 73a62f59203b..d007f909c6a4 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -30,7 +30,7 @@ class BasicBlock; class Function; class OptimizationRemarkEmitter; -/// \brief This class implements simplifications for calls to fortified library +/// This class implements simplifications for calls to fortified library /// functions (__st*cpy_chk, __memcpy_chk, __memmove_chk, __memset_chk), to, /// when possible, replace them with their non-checking counterparts. /// Other optimizations can also be done, but it's possible to disable them and @@ -45,7 +45,7 @@ public: FortifiedLibCallSimplifier(const TargetLibraryInfo *TLI, bool OnlyLowerUnknownSize = false); - /// \brief Take the given call instruction and return a more + /// Take the given call instruction and return a more /// optimal value to replace the instruction with or 0 if a more /// optimal form can't be found. /// The call must not be an indirect call. @@ -60,7 +60,7 @@ private: Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func); Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func); - /// \brief Checks whether the call \p CI to a fortified libcall is foldable + /// Checks whether the call \p CI to a fortified libcall is foldable /// to the non-fortified version. bool isFortifiedCallFoldable(CallInst *CI, unsigned ObjSizeOp, unsigned SizeOp, bool isString); @@ -78,13 +78,13 @@ private: bool UnsafeFPShrink; function_ref<void(Instruction *, Value *)> Replacer; - /// \brief Internal wrapper for RAUW that is the default implementation. + /// Internal wrapper for RAUW that is the default implementation. /// /// Other users may provide an alternate function with this signature instead /// of this one. static void replaceAllUsesWithDefault(Instruction *I, Value *With); - /// \brief Replace an instruction's uses with a value using our replacer. + /// Replace an instruction's uses with a value using our replacer. void replaceAllUsesWith(Instruction *I, Value *With); public: @@ -124,6 +124,7 @@ private: Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B); Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B); Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B); + Value *optimizeRealloc(CallInst *CI, IRBuilder<> &B); Value *optimizeWcslen(CallInst *CI, IRBuilder<> &B); // Wrapper for all String/Memory Library Call Optimizations Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B); @@ -150,15 +151,22 @@ private: Value *optimizeIsDigit(CallInst *CI, IRBuilder<> &B); Value *optimizeIsAscii(CallInst *CI, IRBuilder<> &B); Value *optimizeToAscii(CallInst *CI, IRBuilder<> &B); + Value *optimizeAtoi(CallInst *CI, IRBuilder<> &B); + Value *optimizeStrtol(CallInst *CI, IRBuilder<> &B); // Formatting and IO Library Call Optimizations Value *optimizeErrorReporting(CallInst *CI, IRBuilder<> &B, int StreamArg = -1); Value *optimizePrintF(CallInst *CI, IRBuilder<> &B); Value *optimizeSPrintF(CallInst *CI, IRBuilder<> &B); + Value *optimizeSnPrintF(CallInst *CI, IRBuilder<> &B); Value *optimizeFPrintF(CallInst *CI, IRBuilder<> &B); Value *optimizeFWrite(CallInst *CI, IRBuilder<> &B); + Value *optimizeFRead(CallInst *CI, IRBuilder<> &B); Value *optimizeFPuts(CallInst *CI, IRBuilder<> &B); + Value *optimizeFGets(CallInst *CI, IRBuilder<> &B); + Value *optimizeFPutc(CallInst *CI, IRBuilder<> &B); + Value *optimizeFGetc(CallInst *CI, IRBuilder<> &B); Value *optimizePuts(CallInst *CI, IRBuilder<> &B); // Helper methods @@ -169,6 +177,7 @@ private: SmallVectorImpl<CallInst *> &SinCosCalls); Value *optimizePrintFString(CallInst *CI, IRBuilder<> &B); Value *optimizeSPrintFString(CallInst *CI, IRBuilder<> &B); + Value *optimizeSnPrintFString(CallInst *CI, IRBuilder<> &B); Value *optimizeFPrintFString(CallInst *CI, IRBuilder<> &B); /// hasFloatVersion - Checks if there is a float version of the specified diff --git a/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h b/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h index 12aa3bc6e770..a6b84af068a5 100644 --- a/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/contrib/llvm/include/llvm/Transforms/Utils/UnrollLoop.h @@ -19,11 +19,13 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/Transforms/Utils/ValueMapper.h" namespace llvm { class AssumptionCache; class BasicBlock; +class DependenceInfo; class DominatorTree; class Loop; class LoopInfo; @@ -71,13 +73,54 @@ bool UnrollRuntimeLoopRemainder(Loop *L, unsigned Count, void computePeelCount(Loop *L, unsigned LoopSize, TargetTransformInfo::UnrollingPreferences &UP, - unsigned &TripCount); + unsigned &TripCount, ScalarEvolution &SE); + +bool canPeel(Loop *L); bool peelLoop(Loop *L, unsigned PeelCount, LoopInfo *LI, ScalarEvolution *SE, DominatorTree *DT, AssumptionCache *AC, bool PreserveLCSSA); +LoopUnrollResult UnrollAndJamLoop(Loop *L, unsigned Count, unsigned TripCount, + unsigned TripMultiple, bool UnrollRemainder, + LoopInfo *LI, ScalarEvolution *SE, + DominatorTree *DT, AssumptionCache *AC, + OptimizationRemarkEmitter *ORE); + +bool isSafeToUnrollAndJam(Loop *L, ScalarEvolution &SE, DominatorTree &DT, + DependenceInfo &DI); + +bool computeUnrollCount(Loop *L, const TargetTransformInfo &TTI, + DominatorTree &DT, LoopInfo *LI, ScalarEvolution &SE, + const SmallPtrSetImpl<const Value *> &EphValues, + OptimizationRemarkEmitter *ORE, unsigned &TripCount, + unsigned MaxTripCount, unsigned &TripMultiple, + unsigned LoopSize, + TargetTransformInfo::UnrollingPreferences &UP, + bool &UseUpperBound); + +BasicBlock *foldBlockIntoPredecessor(BasicBlock *BB, LoopInfo *LI, + ScalarEvolution *SE, DominatorTree *DT); + +void remapInstruction(Instruction *I, ValueToValueMapTy &VMap); + +void simplifyLoopAfterUnroll(Loop *L, bool SimplifyIVs, LoopInfo *LI, + ScalarEvolution *SE, DominatorTree *DT, + AssumptionCache *AC); + MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name); +TargetTransformInfo::UnrollingPreferences gatherUnrollingPreferences( + Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, int OptLevel, + Optional<unsigned> UserThreshold, Optional<unsigned> UserCount, + Optional<bool> UserAllowPartial, Optional<bool> UserRuntime, + Optional<bool> UserUpperBound, Optional<bool> UserAllowPeeling); + +unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls, + bool &NotDuplicatable, bool &Convergent, + const TargetTransformInfo &TTI, + const SmallPtrSetImpl<const Value *> &EphValues, + unsigned BEInsns); + } // end namespace llvm #endif // LLVM_TRANSFORMS_UTILS_UNROLLLOOP_H diff --git a/contrib/llvm/include/llvm/Transforms/Vectorize.h b/contrib/llvm/include/llvm/Transforms/Vectorize.h index 19845e471e48..950af7ffe05f 100644 --- a/contrib/llvm/include/llvm/Transforms/Vectorize.h +++ b/contrib/llvm/include/llvm/Transforms/Vectorize.h @@ -21,88 +21,88 @@ class BasicBlockPass; class Pass; //===----------------------------------------------------------------------===// -/// @brief Vectorize configuration. +/// Vectorize configuration. struct VectorizeConfig { //===--------------------------------------------------------------------===// // Target architecture related parameters - /// @brief The size of the native vector registers. + /// The size of the native vector registers. unsigned VectorBits; - /// @brief Vectorize boolean values. + /// Vectorize boolean values. bool VectorizeBools; - /// @brief Vectorize integer values. + /// Vectorize integer values. bool VectorizeInts; - /// @brief Vectorize floating-point values. + /// Vectorize floating-point values. bool VectorizeFloats; - /// @brief Vectorize pointer values. + /// Vectorize pointer values. bool VectorizePointers; - /// @brief Vectorize casting (conversion) operations. + /// Vectorize casting (conversion) operations. bool VectorizeCasts; - /// @brief Vectorize floating-point math intrinsics. + /// Vectorize floating-point math intrinsics. bool VectorizeMath; - /// @brief Vectorize bit intrinsics. + /// Vectorize bit intrinsics. bool VectorizeBitManipulations; - /// @brief Vectorize the fused-multiply-add intrinsic. + /// Vectorize the fused-multiply-add intrinsic. bool VectorizeFMA; - /// @brief Vectorize select instructions. + /// Vectorize select instructions. bool VectorizeSelect; - /// @brief Vectorize comparison instructions. + /// Vectorize comparison instructions. bool VectorizeCmp; - /// @brief Vectorize getelementptr instructions. + /// Vectorize getelementptr instructions. bool VectorizeGEP; - /// @brief Vectorize loads and stores. + /// Vectorize loads and stores. bool VectorizeMemOps; - /// @brief Only generate aligned loads and stores. + /// Only generate aligned loads and stores. bool AlignedOnly; //===--------------------------------------------------------------------===// // Misc parameters - /// @brief The required chain depth for vectorization. + /// The required chain depth for vectorization. unsigned ReqChainDepth; - /// @brief The maximum search distance for instruction pairs. + /// The maximum search distance for instruction pairs. unsigned SearchLimit; - /// @brief The maximum number of candidate pairs with which to use a full + /// The maximum number of candidate pairs with which to use a full /// cycle check. unsigned MaxCandPairsForCycleCheck; - /// @brief Replicating one element to a pair breaks the chain. + /// Replicating one element to a pair breaks the chain. bool SplatBreaksChain; - /// @brief The maximum number of pairable instructions per group. + /// The maximum number of pairable instructions per group. unsigned MaxInsts; - /// @brief The maximum number of candidate instruction pairs per group. + /// The maximum number of candidate instruction pairs per group. unsigned MaxPairs; - /// @brief The maximum number of pairing iterations. + /// The maximum number of pairing iterations. unsigned MaxIter; - /// @brief Don't try to form odd-length vectors. + /// Don't try to form odd-length vectors. bool Pow2LenOnly; - /// @brief Don't boost the chain-depth contribution of loads and stores. + /// Don't boost the chain-depth contribution of loads and stores. bool NoMemOpBoost; - /// @brief Use a fast instruction dependency analysis. + /// Use a fast instruction dependency analysis. bool FastDep; - /// @brief Initialize the VectorizeConfig from command line options. + /// Initialize the VectorizeConfig from command line options. VectorizeConfig(); }; @@ -120,7 +120,7 @@ Pass *createLoopVectorizePass(bool NoUnrolling = false, Pass *createSLPVectorizerPass(); //===----------------------------------------------------------------------===// -/// @brief Vectorize the BasicBlock. +/// Vectorize the BasicBlock. /// /// @param BB The BasicBlock to be vectorized /// @param P The current running pass, should require AliasAnalysis and diff --git a/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h new file mode 100644 index 000000000000..224879cdba52 --- /dev/null +++ b/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h @@ -0,0 +1,482 @@ +//===- llvm/Transforms/Vectorize/LoopVectorizationLegality.h ----*- 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 the LoopVectorizationLegality class. Original code +/// in Loop Vectorizer has been moved out to its own file for modularity +/// and reusability. +/// +/// Currently, it works for innermost loop vectorization. Extending this to +/// outer loop vectorization is a TODO item. +/// +/// Also provides: +/// 1) LoopVectorizeHints class which keeps a number of loop annotations +/// locally for easy look up. It has the ability to write them back as +/// loop metadata, upon request. +/// 2) LoopVectorizationRequirements class for lazy bail out for the purpose +/// of reporting useful failure to vectorize message. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONLEGALITY_H +#define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONLEGALITY_H + +#include "llvm/ADT/MapVector.h" +#include "llvm/Analysis/LoopAccessAnalysis.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h" +#include "llvm/Transforms/Utils/LoopUtils.h" + +namespace llvm { + +/// Create an analysis remark that explains why vectorization failed +/// +/// \p PassName is the name of the pass (e.g. can be AlwaysPrint). \p +/// RemarkName is the identifier for the remark. If \p I is passed it is an +/// instruction that prevents vectorization. Otherwise \p TheLoop is used for +/// the location of the remark. \return the remark object that can be +/// streamed to. +OptimizationRemarkAnalysis createLVMissedAnalysis(const char *PassName, + StringRef RemarkName, + Loop *TheLoop, + Instruction *I = nullptr); + +/// Utility class for getting and setting loop vectorizer hints in the form +/// of loop metadata. +/// This class keeps a number of loop annotations locally (as member variables) +/// and can, upon request, write them back as metadata on the loop. It will +/// initially scan the loop for existing metadata, and will update the local +/// values based on information in the loop. +/// We cannot write all values to metadata, as the mere presence of some info, +/// for example 'force', means a decision has been made. So, we need to be +/// careful NOT to add them if the user hasn't specifically asked so. +class LoopVectorizeHints { + enum HintKind { HK_WIDTH, HK_UNROLL, HK_FORCE, HK_ISVECTORIZED }; + + /// Hint - associates name and validation with the hint value. + struct Hint { + const char *Name; + unsigned Value; // This may have to change for non-numeric values. + HintKind Kind; + + Hint(const char *Name, unsigned Value, HintKind Kind) + : Name(Name), Value(Value), Kind(Kind) {} + + bool validate(unsigned Val); + }; + + /// Vectorization width. + Hint Width; + + /// Vectorization interleave factor. + Hint Interleave; + + /// Vectorization forced + Hint Force; + + /// Already Vectorized + Hint IsVectorized; + + /// Return the loop metadata prefix. + static StringRef Prefix() { return "llvm.loop."; } + + /// True if there is any unsafe math in the loop. + bool PotentiallyUnsafe = false; + +public: + enum ForceKind { + FK_Undefined = -1, ///< Not selected. + FK_Disabled = 0, ///< Forcing disabled. + FK_Enabled = 1, ///< Forcing enabled. + }; + + LoopVectorizeHints(const Loop *L, bool DisableInterleaving, + OptimizationRemarkEmitter &ORE); + + /// Mark the loop L as already vectorized by setting the width to 1. + void setAlreadyVectorized() { + IsVectorized.Value = 1; + Hint Hints[] = {IsVectorized}; + writeHintsToMetadata(Hints); + } + + bool allowVectorization(Function *F, Loop *L, bool AlwaysVectorize) const; + + /// Dumps all the hint information. + void emitRemarkWithHints() const; + + unsigned getWidth() const { return Width.Value; } + unsigned getInterleave() const { return Interleave.Value; } + unsigned getIsVectorized() const { return IsVectorized.Value; } + enum ForceKind getForce() const { return (ForceKind)Force.Value; } + + /// If hints are provided that force vectorization, use the AlwaysPrint + /// pass name to force the frontend to print the diagnostic. + const char *vectorizeAnalysisPassName() const; + + bool allowReordering() const { + // When enabling loop hints are provided we allow the vectorizer to change + // the order of operations that is given by the scalar loop. This is not + // enabled by default because can be unsafe or inefficient. For example, + // reordering floating-point operations will change the way round-off + // error accumulates in the loop. + return getForce() == LoopVectorizeHints::FK_Enabled || getWidth() > 1; + } + + bool isPotentiallyUnsafe() const { + // Avoid FP vectorization if the target is unsure about proper support. + // This may be related to the SIMD unit in the target not handling + // IEEE 754 FP ops properly, or bad single-to-double promotions. + // Otherwise, a sequence of vectorized loops, even without reduction, + // could lead to different end results on the destination vectors. + return getForce() != LoopVectorizeHints::FK_Enabled && PotentiallyUnsafe; + } + + void setPotentiallyUnsafe() { PotentiallyUnsafe = true; } + +private: + /// Find hints specified in the loop metadata and update local values. + void getHintsFromMetadata(); + + /// Checks string hint with one operand and set value if valid. + void setHint(StringRef Name, Metadata *Arg); + + /// Create a new hint from name / value pair. + MDNode *createHintMetadata(StringRef Name, unsigned V) const; + + /// Matches metadata with hint name. + bool matchesHintMetadataName(MDNode *Node, ArrayRef<Hint> HintTypes); + + /// Sets current hints into loop metadata, keeping other values intact. + void writeHintsToMetadata(ArrayRef<Hint> HintTypes); + + /// The loop these hints belong to. + const Loop *TheLoop; + + /// Interface to emit optimization remarks. + OptimizationRemarkEmitter &ORE; +}; + +/// This holds vectorization requirements that must be verified late in +/// the process. The requirements are set by legalize and costmodel. Once +/// vectorization has been determined to be possible and profitable the +/// requirements can be verified by looking for metadata or compiler options. +/// For example, some loops require FP commutativity which is only allowed if +/// vectorization is explicitly specified or if the fast-math compiler option +/// has been provided. +/// Late evaluation of these requirements allows helpful diagnostics to be +/// composed that tells the user what need to be done to vectorize the loop. For +/// example, by specifying #pragma clang loop vectorize or -ffast-math. Late +/// evaluation should be used only when diagnostics can generated that can be +/// followed by a non-expert user. +class LoopVectorizationRequirements { +public: + LoopVectorizationRequirements(OptimizationRemarkEmitter &ORE) : ORE(ORE) {} + + void addUnsafeAlgebraInst(Instruction *I) { + // First unsafe algebra instruction. + if (!UnsafeAlgebraInst) + UnsafeAlgebraInst = I; + } + + void addRuntimePointerChecks(unsigned Num) { NumRuntimePointerChecks = Num; } + + bool doesNotMeet(Function *F, Loop *L, const LoopVectorizeHints &Hints); + +private: + unsigned NumRuntimePointerChecks = 0; + Instruction *UnsafeAlgebraInst = nullptr; + + /// Interface to emit optimization remarks. + OptimizationRemarkEmitter &ORE; +}; + +/// LoopVectorizationLegality checks if it is legal to vectorize a loop, and +/// to what vectorization factor. +/// This class does not look at the profitability of vectorization, only the +/// legality. This class has two main kinds of checks: +/// * Memory checks - The code in canVectorizeMemory checks if vectorization +/// will change the order of memory accesses in a way that will change the +/// correctness of the program. +/// * Scalars checks - The code in canVectorizeInstrs and canVectorizeMemory +/// checks for a number of different conditions, such as the availability of a +/// single induction variable, that all types are supported and vectorize-able, +/// etc. This code reflects the capabilities of InnerLoopVectorizer. +/// This class is also used by InnerLoopVectorizer for identifying +/// induction variable and the different reduction variables. +class LoopVectorizationLegality { +public: + LoopVectorizationLegality( + Loop *L, PredicatedScalarEvolution &PSE, DominatorTree *DT, + TargetLibraryInfo *TLI, AliasAnalysis *AA, Function *F, + std::function<const LoopAccessInfo &(Loop &)> *GetLAA, LoopInfo *LI, + OptimizationRemarkEmitter *ORE, LoopVectorizationRequirements *R, + LoopVectorizeHints *H, DemandedBits *DB, AssumptionCache *AC) + : TheLoop(L), LI(LI), PSE(PSE), TLI(TLI), DT(DT), GetLAA(GetLAA), + ORE(ORE), Requirements(R), Hints(H), DB(DB), AC(AC) {} + + /// ReductionList contains the reduction descriptors for all + /// of the reductions that were found in the loop. + using ReductionList = DenseMap<PHINode *, RecurrenceDescriptor>; + + /// InductionList saves induction variables and maps them to the + /// induction descriptor. + using InductionList = MapVector<PHINode *, InductionDescriptor>; + + /// RecurrenceSet contains the phi nodes that are recurrences other than + /// inductions and reductions. + using RecurrenceSet = SmallPtrSet<const PHINode *, 8>; + + /// Returns true if it is legal to vectorize this loop. + /// This does not mean that it is profitable to vectorize this + /// loop, only that it is legal to do so. + /// Temporarily taking UseVPlanNativePath parameter. If true, take + /// the new code path being implemented for outer loop vectorization + /// (should be functional for inner loop vectorization) based on VPlan. + /// If false, good old LV code. + bool canVectorize(bool UseVPlanNativePath); + + /// Returns the primary induction variable. + PHINode *getPrimaryInduction() { return PrimaryInduction; } + + /// Returns the reduction variables found in the loop. + ReductionList *getReductionVars() { return &Reductions; } + + /// Returns the induction variables found in the loop. + InductionList *getInductionVars() { return &Inductions; } + + /// Return the first-order recurrences found in the loop. + RecurrenceSet *getFirstOrderRecurrences() { return &FirstOrderRecurrences; } + + /// Return the set of instructions to sink to handle first-order recurrences. + DenseMap<Instruction *, Instruction *> &getSinkAfter() { return SinkAfter; } + + /// Returns the widest induction type. + Type *getWidestInductionType() { return WidestIndTy; } + + /// Returns True if V is a Phi node of an induction variable in this loop. + bool isInductionPhi(const Value *V); + + /// Returns True if V is a cast that is part of an induction def-use chain, + /// and had been proven to be redundant under a runtime guard (in other + /// words, the cast has the same SCEV expression as the induction phi). + bool isCastedInductionVariable(const Value *V); + + /// Returns True if V can be considered as an induction variable in this + /// loop. V can be the induction phi, or some redundant cast in the def-use + /// chain of the inducion phi. + bool isInductionVariable(const Value *V); + + /// Returns True if PN is a reduction variable in this loop. + bool isReductionVariable(PHINode *PN) { return Reductions.count(PN); } + + /// Returns True if Phi is a first-order recurrence in this loop. + bool isFirstOrderRecurrence(const PHINode *Phi); + + /// Return true if the block BB needs to be predicated in order for the loop + /// to be vectorized. + bool blockNeedsPredication(BasicBlock *BB); + + /// Check if this pointer is consecutive when vectorizing. This happens + /// when the last index of the GEP is the induction variable, or that the + /// pointer itself is an induction variable. + /// This check allows us to vectorize A[idx] into a wide load/store. + /// Returns: + /// 0 - Stride is unknown or non-consecutive. + /// 1 - Address is consecutive. + /// -1 - Address is consecutive, and decreasing. + /// NOTE: This method must only be used before modifying the original scalar + /// loop. Do not use after invoking 'createVectorizedLoopSkeleton' (PR34965). + int isConsecutivePtr(Value *Ptr); + + /// Returns true if the value V is uniform within the loop. + bool isUniform(Value *V); + + /// Returns the information that we collected about runtime memory check. + const RuntimePointerChecking *getRuntimePointerChecking() const { + return LAI->getRuntimePointerChecking(); + } + + const LoopAccessInfo *getLAI() const { return LAI; } + + unsigned getMaxSafeDepDistBytes() { return LAI->getMaxSafeDepDistBytes(); } + + uint64_t getMaxSafeRegisterWidth() const { + return LAI->getDepChecker().getMaxSafeRegisterWidth(); + } + + bool hasStride(Value *V) { return LAI->hasStride(V); } + + /// Returns true if vector representation of the instruction \p I + /// requires mask. + bool isMaskRequired(const Instruction *I) { return (MaskedOp.count(I) != 0); } + + unsigned getNumStores() const { return LAI->getNumStores(); } + unsigned getNumLoads() const { return LAI->getNumLoads(); } + + // Returns true if the NoNaN attribute is set on the function. + bool hasFunNoNaNAttr() const { return HasFunNoNaNAttr; } + +private: + /// Return true if the pre-header, exiting and latch blocks of \p Lp and all + /// its nested loops are considered legal for vectorization. These legal + /// checks are common for inner and outer loop vectorization. + /// Temporarily taking UseVPlanNativePath parameter. If true, take + /// the new code path being implemented for outer loop vectorization + /// (should be functional for inner loop vectorization) based on VPlan. + /// If false, good old LV code. + bool canVectorizeLoopNestCFG(Loop *Lp, bool UseVPlanNativePath); + + /// Return true if the pre-header, exiting and latch blocks of \p Lp + /// (non-recursive) are considered legal for vectorization. + /// Temporarily taking UseVPlanNativePath parameter. If true, take + /// the new code path being implemented for outer loop vectorization + /// (should be functional for inner loop vectorization) based on VPlan. + /// If false, good old LV code. + bool canVectorizeLoopCFG(Loop *Lp, bool UseVPlanNativePath); + + /// Check if a single basic block loop is vectorizable. + /// At this point we know that this is a loop with a constant trip count + /// and we only need to check individual instructions. + bool canVectorizeInstrs(); + + /// When we vectorize loops we may change the order in which + /// we read and write from memory. This method checks if it is + /// legal to vectorize the code, considering only memory constrains. + /// Returns true if the loop is vectorizable + bool canVectorizeMemory(); + + /// Return true if we can vectorize this loop using the IF-conversion + /// transformation. + bool canVectorizeWithIfConvert(); + + /// Return true if we can vectorize this outer loop. The method performs + /// specific checks for outer loop vectorization. + bool canVectorizeOuterLoop(); + + /// Return true if all of the instructions in the block can be speculatively + /// executed. \p SafePtrs is a list of addresses that are known to be legal + /// and we know that we can read from them without segfault. + bool blockCanBePredicated(BasicBlock *BB, SmallPtrSetImpl<Value *> &SafePtrs); + + /// Updates the vectorization state by adding \p Phi to the inductions list. + /// This can set \p Phi as the main induction of the loop if \p Phi is a + /// better choice for the main induction than the existing one. + void addInductionPhi(PHINode *Phi, const InductionDescriptor &ID, + SmallPtrSetImpl<Value *> &AllowedExit); + + /// Create an analysis remark that explains why vectorization failed + /// + /// \p RemarkName is the identifier for the remark. If \p I is passed it is + /// an instruction that prevents vectorization. Otherwise the loop is used + /// for the location of the remark. \return the remark object that can be + /// streamed to. + OptimizationRemarkAnalysis + createMissedAnalysis(StringRef RemarkName, Instruction *I = nullptr) const { + return createLVMissedAnalysis(Hints->vectorizeAnalysisPassName(), + RemarkName, TheLoop, I); + } + + /// If an access has a symbolic strides, this maps the pointer value to + /// the stride symbol. + const ValueToValueMap *getSymbolicStrides() { + // FIXME: Currently, the set of symbolic strides is sometimes queried before + // it's collected. This happens from canVectorizeWithIfConvert, when the + // pointer is checked to reference consecutive elements suitable for a + // masked access. + return LAI ? &LAI->getSymbolicStrides() : nullptr; + } + + /// The loop that we evaluate. + Loop *TheLoop; + + /// Loop Info analysis. + LoopInfo *LI; + + /// A wrapper around ScalarEvolution used to add runtime SCEV checks. + /// Applies dynamic knowledge to simplify SCEV expressions in the context + /// of existing SCEV assumptions. The analysis will also add a minimal set + /// of new predicates if this is required to enable vectorization and + /// unrolling. + PredicatedScalarEvolution &PSE; + + /// Target Library Info. + TargetLibraryInfo *TLI; + + /// Dominator Tree. + DominatorTree *DT; + + // LoopAccess analysis. + std::function<const LoopAccessInfo &(Loop &)> *GetLAA; + + // And the loop-accesses info corresponding to this loop. This pointer is + // null until canVectorizeMemory sets it up. + const LoopAccessInfo *LAI = nullptr; + + /// Interface to emit optimization remarks. + OptimizationRemarkEmitter *ORE; + + // --- vectorization state --- // + + /// Holds the primary induction variable. This is the counter of the + /// loop. + PHINode *PrimaryInduction = nullptr; + + /// Holds the reduction variables. + ReductionList Reductions; + + /// Holds all of the induction variables that we found in the loop. + /// Notice that inductions don't need to start at zero and that induction + /// variables can be pointers. + InductionList Inductions; + + /// Holds all the casts that participate in the update chain of the induction + /// variables, and that have been proven to be redundant (possibly under a + /// runtime guard). These casts can be ignored when creating the vectorized + /// loop body. + SmallPtrSet<Instruction *, 4> InductionCastsToIgnore; + + /// Holds the phi nodes that are first-order recurrences. + RecurrenceSet FirstOrderRecurrences; + + /// Holds instructions that need to sink past other instructions to handle + /// first-order recurrences. + DenseMap<Instruction *, Instruction *> SinkAfter; + + /// Holds the widest induction type encountered. + Type *WidestIndTy = nullptr; + + /// Allowed outside users. This holds the induction and reduction + /// vars which can be accessed from outside the loop. + SmallPtrSet<Value *, 4> AllowedExit; + + /// Can we assume the absence of NaNs. + bool HasFunNoNaNAttr = false; + + /// Vectorization requirements that will go through late-evaluation. + LoopVectorizationRequirements *Requirements; + + /// Used to emit an analysis of any legality issues. + LoopVectorizeHints *Hints; + + /// The demanded bits analsyis is used to compute the minimum type size in + /// which a reduction can be computed. + DemandedBits *DB; + + /// The assumption cache analysis is used to compute the minimum type size in + /// which a reduction can be computed. + AssumptionCache *AC; + + /// While vectorizing these instructions we have to generate a + /// call to the appropriate masked intrinsic + SmallPtrSet<const Instruction *, 8> MaskedOp; +}; + +} // namespace llvm + +#endif // LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONLEGALITY_H diff --git a/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h b/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h index 32b56d372ea1..d79d84691803 100644 --- a/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h +++ b/contrib/llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h @@ -26,6 +26,14 @@ // of vectorization. It decides on the optimal vector width, which // can be one, if vectorization is not profitable. // +// There is a development effort going on to migrate loop vectorizer to the +// VPlan infrastructure and to introduce outer loop vectorization support (see +// docs/Proposal/VectorizationPlan.rst and +// http://lists.llvm.org/pipermail/llvm-dev/2017-December/119523.html). For this +// purpose, we temporarily introduced the VPlan-native vectorization path: an +// alternative vectorization path that is natively implemented on top of the +// VPlan infrastructure. See EnableVPlanNativePath for enabling. +// //===----------------------------------------------------------------------===// // // The reduction-variable vectorization is based on the paper: diff --git a/contrib/llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h b/contrib/llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h index 781a628a0974..3152e8192fc5 100644 --- a/contrib/llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h +++ b/contrib/llvm/include/llvm/Transforms/Vectorize/SLPVectorizer.h @@ -82,7 +82,7 @@ public: OptimizationRemarkEmitter *ORE_); private: - /// \brief Collect store and getelementptr instructions and organize them + /// Collect store and getelementptr instructions and organize them /// according to the underlying object of their pointer operands. We sort the /// instructions by their underlying objects to reduce the cost of /// consecutive access queries. @@ -91,21 +91,23 @@ private: /// every time we run into a memory barrier. void collectSeedInstructions(BasicBlock *BB); - /// \brief Try to vectorize a chain that starts at two arithmetic instrs. + /// Try to vectorize a chain that starts at two arithmetic instrs. bool tryToVectorizePair(Value *A, Value *B, slpvectorizer::BoUpSLP &R); - /// \brief Try to vectorize a list of operands. + /// Try to vectorize a list of operands. + /// \param UserCost Cost of the user operations of \p VL if they may affect + /// the cost of the vectorization. /// \returns true if a value was vectorized. bool tryToVectorizeList(ArrayRef<Value *> VL, slpvectorizer::BoUpSLP &R, - bool AllowReorder = false); + int UserCost = 0, bool AllowReorder = false); - /// \brief Try to vectorize a chain that may start at the operands of \p I. + /// Try to vectorize a chain that may start at the operands of \p I. bool tryToVectorize(Instruction *I, slpvectorizer::BoUpSLP &R); - /// \brief Vectorize the store instructions collected in Stores. + /// Vectorize the store instructions collected in Stores. bool vectorizeStoreChains(slpvectorizer::BoUpSLP &R); - /// \brief Vectorize the index computations of the getelementptr instructions + /// Vectorize the index computations of the getelementptr instructions /// collected in GEPs. bool vectorizeGEPIndices(BasicBlock *BB, slpvectorizer::BoUpSLP &R); @@ -131,7 +133,7 @@ private: bool vectorizeSimpleInstructions(SmallVectorImpl<WeakVH> &Instructions, BasicBlock *BB, slpvectorizer::BoUpSLP &R); - /// \brief Scan the basic block and look for patterns that are likely to start + /// Scan the basic block and look for patterns that are likely to start /// a vectorization chain. bool vectorizeChainsInBlock(BasicBlock *BB, slpvectorizer::BoUpSLP &R); diff --git a/contrib/llvm/include/llvm/XRay/XRayRecord.h b/contrib/llvm/include/llvm/XRay/XRayRecord.h index 5c5e9f436f4a..76873447f170 100644 --- a/contrib/llvm/include/llvm/XRay/XRayRecord.h +++ b/contrib/llvm/include/llvm/XRay/XRayRecord.h @@ -75,6 +75,9 @@ struct XRayRecord { /// The thread ID for the currently running thread. uint32_t TId; + /// The process ID for the currently running process. + uint32_t PId; + /// The function call arguments. std::vector<uint64_t> CallArgs; }; diff --git a/contrib/llvm/include/llvm/XRay/YAMLXRayRecord.h b/contrib/llvm/include/llvm/XRay/YAMLXRayRecord.h index b436aefb1e8f..0de9ea0968e6 100644 --- a/contrib/llvm/include/llvm/XRay/YAMLXRayRecord.h +++ b/contrib/llvm/include/llvm/XRay/YAMLXRayRecord.h @@ -37,6 +37,7 @@ struct YAMLXRayRecord { std::string Function; uint64_t TSC; uint32_t TId; + uint32_t PId; std::vector<uint64_t> CallArgs; }; @@ -79,6 +80,7 @@ template <> struct MappingTraits<xray::YAMLXRayRecord> { IO.mapOptional("args", Record.CallArgs); IO.mapRequired("cpu", Record.CPU); IO.mapRequired("thread", Record.TId); + IO.mapOptional("process", Record.PId, 0U); IO.mapRequired("kind", Record.Type); IO.mapRequired("tsc", Record.TSC); } diff --git a/contrib/llvm/include/llvm/module.modulemap b/contrib/llvm/include/llvm/module.modulemap index d8b07c4f54da..649cdf3b0a89 100644 --- a/contrib/llvm/include/llvm/module.modulemap +++ b/contrib/llvm/include/llvm/module.modulemap @@ -20,15 +20,12 @@ module LLVM_Backend { // Exclude these; they're intended to be included into only a single // translation unit (or none) and aren't part of this module. - exclude header "CodeGen/CommandFlags.h" exclude header "CodeGen/LinkAllAsmWriterComponents.h" exclude header "CodeGen/LinkAllCodegenComponents.h" // These are intended for (repeated) textual inclusion. - textual header "CodeGen/CommandFlags.def" + textual header "CodeGen/CommandFlags.inc" textual header "CodeGen/DIEValue.def" - textual header "CodeGen/RuntimeLibcalls.def" - textual header "CodeGen/TargetOpcodes.def" } module Target { @@ -43,6 +40,7 @@ module LLVM_BinaryFormat { requires cplusplus umbrella "BinaryFormat" module * { export * } textual header "BinaryFormat/Dwarf.def" + textual header "BinaryFormat/DynamicTags.def" textual header "BinaryFormat/MachO.def" textual header "BinaryFormat/ELFRelocs/AArch64.def" textual header "BinaryFormat/ELFRelocs/AMDGPU.def" @@ -60,7 +58,6 @@ module LLVM_BinaryFormat { textual header "BinaryFormat/ELFRelocs/Sparc.def" textual header "BinaryFormat/ELFRelocs/SystemZ.def" textual header "BinaryFormat/ELFRelocs/x86_64.def" - textual header "BinaryFormat/ELFRelocs/WebAssembly.def" textual header "BinaryFormat/WasmRelocs.def" } @@ -90,16 +87,21 @@ module LLVM_DebugInfo_PDB { // FIXME: There should be a better way to specify this. exclude header "DebugInfo/PDB/DIA/DIADataStream.h" exclude header "DebugInfo/PDB/DIA/DIAEnumDebugStreams.h" + exclude header "DebugInfo/PDB/DIA/DIAEnumInjectedSources.h" exclude header "DebugInfo/PDB/DIA/DIAEnumLineNumbers.h" + exclude header "DebugInfo/PDB/DIA/DIAEnumSectionContribs.h" exclude header "DebugInfo/PDB/DIA/DIAEnumSourceFiles.h" exclude header "DebugInfo/PDB/DIA/DIAEnumSymbols.h" exclude header "DebugInfo/PDB/DIA/DIAEnumTables.h" + exclude header "DebugInfo/PDB/DIA/DIAInjectedSource.h" exclude header "DebugInfo/PDB/DIA/DIALineNumber.h" exclude header "DebugInfo/PDB/DIA/DIARawSymbol.h" + exclude header "DebugInfo/PDB/DIA/DIASectionContrib.h" exclude header "DebugInfo/PDB/DIA/DIASession.h" exclude header "DebugInfo/PDB/DIA/DIASourceFile.h" exclude header "DebugInfo/PDB/DIA/DIASupport.h" exclude header "DebugInfo/PDB/DIA/DIATable.h" + exclude header "DebugInfo/PDB/DIA/DIAUtils.h" } module LLVM_DebugInfo_PDB_DIA { @@ -192,6 +194,8 @@ module LLVM_intrinsic_gen { module IR_CFG { header "IR/CFG.h" export * } module IR_ConstantRange { header "IR/ConstantRange.h" export * } module IR_Dominators { header "IR/Dominators.h" export * } + module Analysis_PostDominators { header "Analysis/PostDominators.h" export * } + module IR_DomTreeUpdater { header "IR/DomTreeUpdater.h" export * } module IR_IRBuilder { header "IR/IRBuilder.h" export * } module IR_PassManager { header "IR/PassManager.h" export * } module IR_PredIteratorCache { header "IR/PredIteratorCache.h" export * } @@ -217,6 +221,7 @@ module LLVM_IR { textual header "IR/Instruction.def" textual header "IR/Metadata.def" textual header "IR/Value.def" + textual header "IR/RuntimeLibcalls.def" } module LLVM_IRReader { requires cplusplus umbrella "IRReader" module * { export * } } @@ -229,7 +234,7 @@ module LLVM_MC { umbrella "MC" module * { export * } - textual header "MC/MCTargetOptionsCommandFlags.def" + textual header "MC/MCTargetOptionsCommandFlags.inc" } // Used by llvm-tblgen @@ -297,6 +302,7 @@ module LLVM_Utils { // These are intended for textual inclusion. textual header "Support/ARMTargetParser.def" textual header "Support/AArch64TargetParser.def" + textual header "Support/TargetOpcodes.def" textual header "Support/X86TargetParser.def" } @@ -305,12 +311,6 @@ module LLVM_Utils { header "Support/ConvertUTF.h" export * } - - module LLVM_CodeGen_MachineValueType { - requires cplusplus - header "CodeGen/MachineValueType.h" - export * - } } // This is used for a $src == $build compilation. Otherwise we use |
