mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Upgrade our copy of llvm/clang to trunk r154661, in preparation of the
upcoming 3.1 release (expected in a few weeks). Preliminary release notes can be found at: <http://llvm.org/docs/ReleaseNotes.html> MFC after: 2 weeks
This commit is contained in:
commit
dff0c46c97
2267 changed files with 249615 additions and 121903 deletions
|
|
@ -38,6 +38,22 @@
|
|||
# xargs -n1 | sort | uniq -d;
|
||||
# done
|
||||
|
||||
# 20120415: new clang import which bumps version from 3.0 to 3.1
|
||||
OLD_FILES+=usr/include/clang/3.0/altivec.h
|
||||
OLD_FILES+=usr/include/clang/3.0/avxintrin.h
|
||||
OLD_FILES+=usr/include/clang/3.0/emmintrin.h
|
||||
OLD_FILES+=usr/include/clang/3.0/immintrin.h
|
||||
OLD_FILES+=usr/include/clang/3.0/mm3dnow.h
|
||||
OLD_FILES+=usr/include/clang/3.0/mm_malloc.h
|
||||
OLD_FILES+=usr/include/clang/3.0/mmintrin.h
|
||||
OLD_FILES+=usr/include/clang/3.0/nmmintrin.h
|
||||
OLD_FILES+=usr/include/clang/3.0/pmmintrin.h
|
||||
OLD_FILES+=usr/include/clang/3.0/smmintrin.h
|
||||
OLD_FILES+=usr/include/clang/3.0/tmmintrin.h
|
||||
OLD_FILES+=usr/include/clang/3.0/wmmintrin.h
|
||||
OLD_FILES+=usr/include/clang/3.0/x86intrin.h
|
||||
OLD_FILES+=usr/include/clang/3.0/xmmintrin.h
|
||||
OLD_DIRS+=usr/include/clang/3.0
|
||||
# 20120322: Update heimdal to 1.5.1.
|
||||
OLD_FILES+=usr/include/krb5-v4compat.h \
|
||||
usr/include/krb_err.h \
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ LLVM Release License
|
|||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign.
|
||||
Copyright (c) 2003-2012 University of Illinois at Urbana-Champaign.
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
|
|
@ -67,3 +67,4 @@ Autoconf llvm/autoconf
|
|||
CellSPU backend llvm/lib/Target/CellSPU/README.txt
|
||||
Google Test llvm/utils/unittest/googletest
|
||||
OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
|
||||
pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCAnalysis Analysis
|
||||
* @ingroup LLVMC
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
LLVMAbortProcessAction, /* verifier will print to stderr and abort() */
|
||||
|
|
@ -48,6 +54,10 @@ LLVMBool LLVMVerifyFunction(LLVMValueRef Fn, LLVMVerifierFailureAction Action);
|
|||
void LLVMViewFunctionCFG(LLVMValueRef Fn);
|
||||
void LLVMViewFunctionCFGOnly(LLVMValueRef Fn);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCBitReader Bit Reader
|
||||
* @ingroup LLVMC
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Builds a module from the bitcode in the specified memory buffer, returning a
|
||||
reference to the module via the OutModule parameter. Returns 0 on success.
|
||||
|
|
@ -59,6 +65,10 @@ LLVMBool LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf,
|
|||
LLVMModuleProviderRef *OutMP,
|
||||
char **OutMessage);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCBitWriter Bit Writer
|
||||
* @ingroup LLVMC
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*===-- Operations on modules ---------------------------------------------===*/
|
||||
|
||||
|
|
@ -39,6 +45,10 @@ int LLVMWriteBitcodeToFD(LLVMModuleRef M, int FD, int ShouldClose,
|
|||
descriptor. Returns 0 on success. Closes the Handle. */
|
||||
int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int Handle);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -18,6 +18,13 @@
|
|||
#include "llvm/Support/DataTypes.h"
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCDisassembler Disassembler
|
||||
* @ingroup LLVMC
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* An opaque reference to a disassembler context.
|
||||
*/
|
||||
|
|
@ -157,6 +164,10 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DC, uint8_t *Bytes,
|
|||
uint64_t BytesSize, uint64_t PC,
|
||||
char *OutString, size_t OutStringSize);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* !defined(__cplusplus) */
|
||||
|
|
|
|||
|
|
@ -25,6 +25,19 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCEnhancedDisassembly Enhanced Disassembly
|
||||
* @ingroup LLVMC
|
||||
* @deprecated
|
||||
*
|
||||
* This module contains an interface to the Enhanced Disassembly (edis)
|
||||
* library. The edis library is deprecated and will likely disappear in
|
||||
* the near future. You should use the @ref LLVMCDisassembler interface
|
||||
* instead.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
@typedef EDByteReaderCallback
|
||||
Interface to memory from which instructions may be read.
|
||||
|
|
@ -504,6 +517,10 @@ int EDBlockEvaluateOperand(uint64_t *result,
|
|||
int EDBlockVisitTokens(EDInstRef inst,
|
||||
EDTokenVisitor_t visitor);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -26,6 +26,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCExecutionEngine Execution Engine
|
||||
* @ingroup LLVMC
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
void LLVMLinkInJIT(void);
|
||||
void LLVMLinkInInterpreter(void);
|
||||
|
||||
|
|
@ -125,6 +132,10 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
|
|||
|
||||
void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,9 +22,19 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCInitialization Initialization Routines
|
||||
* @ingroup LLVMC
|
||||
*
|
||||
* This module contains routines used to initialize the LLVM system.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
void LLVMInitializeCore(LLVMPassRegistryRef R);
|
||||
void LLVMInitializeTransformUtils(LLVMPassRegistryRef R);
|
||||
void LLVMInitializeScalarOpts(LLVMPassRegistryRef R);
|
||||
void LLVMInitializeVectorization(LLVMPassRegistryRef R);
|
||||
void LLVMInitializeInstCombine(LLVMPassRegistryRef R);
|
||||
void LLVMInitializeIPO(LLVMPassRegistryRef R);
|
||||
void LLVMInitializeInstrumentation(LLVMPassRegistryRef R);
|
||||
|
|
@ -33,6 +43,10 @@ void LLVMInitializeIPA(LLVMPassRegistryRef R);
|
|||
void LLVMInitializeCodeGen(LLVMPassRegistryRef R);
|
||||
void LLVMInitializeTarget(LLVMPassRegistryRef R);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCLinkTimeOptimizer Link Time Optimization
|
||||
* @ingroup LLVMC
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/// This provides a dummy type for pointers to the LTO object.
|
||||
typedef void* llvm_lto_t;
|
||||
|
||||
|
|
@ -51,6 +58,10 @@ extern "C" {
|
|||
extern llvm_lto_status_t llvm_optimize_modules
|
||||
(llvm_lto_t lto, const char* output_filename);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,23 +28,74 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCObject Object file reading and writing
|
||||
* @ingroup LLVMC
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
// Opaque type wrappers
|
||||
typedef struct LLVMOpaqueObjectFile *LLVMObjectFileRef;
|
||||
|
||||
typedef struct LLVMOpaqueSectionIterator *LLVMSectionIteratorRef;
|
||||
typedef struct LLVMOpaqueSymbolIterator *LLVMSymbolIteratorRef;
|
||||
typedef struct LLVMOpaqueRelocationIterator *LLVMRelocationIteratorRef;
|
||||
|
||||
// ObjectFile creation
|
||||
LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf);
|
||||
void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile);
|
||||
|
||||
// ObjectFile Section iterators
|
||||
LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile);
|
||||
void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI);
|
||||
LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile,
|
||||
LLVMSectionIteratorRef SI);
|
||||
void LLVMMoveToNextSection(LLVMSectionIteratorRef SI);
|
||||
void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect,
|
||||
LLVMSymbolIteratorRef Sym);
|
||||
|
||||
// ObjectFile Symbol iterators
|
||||
LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef ObjectFile);
|
||||
void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI);
|
||||
LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef ObjectFile,
|
||||
LLVMSymbolIteratorRef SI);
|
||||
void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI);
|
||||
|
||||
// SectionRef accessors
|
||||
const char *LLVMGetSectionName(LLVMSectionIteratorRef SI);
|
||||
uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI);
|
||||
const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI);
|
||||
uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI);
|
||||
LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI,
|
||||
LLVMSymbolIteratorRef Sym);
|
||||
|
||||
// Section Relocation iterators
|
||||
LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section);
|
||||
void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef RI);
|
||||
LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section,
|
||||
LLVMRelocationIteratorRef RI);
|
||||
void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef RI);
|
||||
|
||||
|
||||
// SymbolRef accessors
|
||||
const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI);
|
||||
uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI);
|
||||
uint64_t LLVMGetSymbolFileOffset(LLVMSymbolIteratorRef SI);
|
||||
uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI);
|
||||
|
||||
// RelocationRef accessors
|
||||
uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI);
|
||||
uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI);
|
||||
LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI);
|
||||
uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI);
|
||||
// NOTE: Caller takes ownership of returned string of the two
|
||||
// following functions.
|
||||
const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI);
|
||||
const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
@ -68,6 +119,27 @@ namespace llvm {
|
|||
return reinterpret_cast<LLVMSectionIteratorRef>
|
||||
(const_cast<section_iterator*>(SI));
|
||||
}
|
||||
|
||||
inline symbol_iterator *unwrap(LLVMSymbolIteratorRef SI) {
|
||||
return reinterpret_cast<symbol_iterator*>(SI);
|
||||
}
|
||||
|
||||
inline LLVMSymbolIteratorRef
|
||||
wrap(const symbol_iterator *SI) {
|
||||
return reinterpret_cast<LLVMSymbolIteratorRef>
|
||||
(const_cast<symbol_iterator*>(SI));
|
||||
}
|
||||
|
||||
inline relocation_iterator *unwrap(LLVMRelocationIteratorRef SI) {
|
||||
return reinterpret_cast<relocation_iterator*>(SI);
|
||||
}
|
||||
|
||||
inline LLVMRelocationIteratorRef
|
||||
wrap(const relocation_iterator *SI) {
|
||||
return reinterpret_cast<LLVMRelocationIteratorRef>
|
||||
(const_cast<relocation_iterator*>(SI));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCTarget Target information
|
||||
* @ingroup LLVMC
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
enum LLVMByteOrdering { LLVMBigEndian, LLVMLittleEndian };
|
||||
|
||||
typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef;
|
||||
|
|
@ -47,6 +54,24 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef;
|
|||
#include "llvm/Config/Targets.def"
|
||||
#undef LLVM_TARGET /* Explicit undef to make SWIG happier */
|
||||
|
||||
/* Declare all of the available assembly printer initialization functions. */
|
||||
#define LLVM_ASM_PRINTER(TargetName) \
|
||||
void LLVMInitialize##TargetName##AsmPrinter();
|
||||
#include "llvm/Config/AsmPrinters.def"
|
||||
#undef LLVM_ASM_PRINTER /* Explicit undef to make SWIG happier */
|
||||
|
||||
/* Declare all of the available assembly parser initialization functions. */
|
||||
#define LLVM_ASM_PARSER(TargetName) \
|
||||
void LLVMInitialize##TargetName##AsmParser();
|
||||
#include "llvm/Config/AsmParsers.def"
|
||||
#undef LLVM_ASM_PARSER /* Explicit undef to make SWIG happier */
|
||||
|
||||
/* Declare all of the available disassembler initialization functions. */
|
||||
#define LLVM_DISASSEMBLER(TargetName) \
|
||||
void LLVMInitialize##TargetName##Disassembler();
|
||||
#include "llvm/Config/Disassemblers.def"
|
||||
#undef LLVM_DISASSEMBLER /* Explicit undef to make SWIG happier */
|
||||
|
||||
/** LLVMInitializeAllTargetInfos - The main program should call this function if
|
||||
it wants access to all available targets that LLVM is configured to
|
||||
support. */
|
||||
|
|
@ -64,6 +89,43 @@ static inline void LLVMInitializeAllTargets(void) {
|
|||
#include "llvm/Config/Targets.def"
|
||||
#undef LLVM_TARGET /* Explicit undef to make SWIG happier */
|
||||
}
|
||||
|
||||
/** LLVMInitializeAllTargetMCs - The main program should call this function if
|
||||
it wants access to all available target MC that LLVM is configured to
|
||||
support. */
|
||||
static inline void LLVMInitializeAllTargetMCs(void) {
|
||||
#define LLVM_TARGET(TargetName) LLVMInitialize##TargetName##TargetMC();
|
||||
#include "llvm/Config/Targets.def"
|
||||
#undef LLVM_TARGET /* Explicit undef to make SWIG happier */
|
||||
}
|
||||
|
||||
/** LLVMInitializeAllAsmPrinters - The main program should call this function if
|
||||
it wants all asm printers that LLVM is configured to support, to make them
|
||||
available via the TargetRegistry. */
|
||||
static inline void LLVMInitializeAllAsmPrinters() {
|
||||
#define LLVM_ASM_PRINTER(TargetName) LLVMInitialize##TargetName##AsmPrinter();
|
||||
#include "llvm/Config/AsmPrinters.def"
|
||||
#undef LLVM_ASM_PRINTER /* Explicit undef to make SWIG happier */
|
||||
}
|
||||
|
||||
/** LLVMInitializeAllAsmParsers - The main program should call this function if
|
||||
it wants all asm parsers that LLVM is configured to support, to make them
|
||||
available via the TargetRegistry. */
|
||||
static inline void LLVMInitializeAllAsmParsers() {
|
||||
#define LLVM_ASM_PARSER(TargetName) LLVMInitialize##TargetName##AsmParser();
|
||||
#include "llvm/Config/AsmParsers.def"
|
||||
#undef LLVM_ASM_PARSER /* Explicit undef to make SWIG happier */
|
||||
}
|
||||
|
||||
/** LLVMInitializeAllDisassemblers - The main program should call this function
|
||||
if it wants all disassemblers that LLVM is configured to support, to make
|
||||
them available via the TargetRegistry. */
|
||||
static inline void LLVMInitializeAllDisassemblers() {
|
||||
#define LLVM_DISASSEMBLER(TargetName) \
|
||||
LLVMInitialize##TargetName##Disassembler();
|
||||
#include "llvm/Config/Disassemblers.def"
|
||||
#undef LLVM_DISASSEMBLER /* Explicit undef to make SWIG happier */
|
||||
}
|
||||
|
||||
/** LLVMInitializeNativeTarget - The main program should call this function to
|
||||
initialize the native target corresponding to the host. This is useful
|
||||
|
|
@ -157,6 +219,9 @@ unsigned long long LLVMOffsetOfElement(LLVMTargetDataRef, LLVMTypeRef StructTy,
|
|||
See the destructor llvm::TargetData::~TargetData. */
|
||||
void LLVMDisposeTargetData(LLVMTargetDataRef);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
142
contrib/llvm/include/llvm-c/TargetMachine.h
Normal file
142
contrib/llvm/include/llvm-c/TargetMachine.h
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*===-- llvm-c/TargetMachine.h - Target Machine 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 the Target and TargetMachine *|
|
||||
|* classes, which can be used to generate assembly or object files. *|
|
||||
|* *|
|
||||
|* 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_TARGETMACHINE_H
|
||||
#define LLVM_C_TARGETMACHINE_H
|
||||
|
||||
#include "llvm-c/Core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
typedef struct LLVMTargetMachine *LLVMTargetMachineRef;
|
||||
typedef struct LLVMTarget *LLVMTargetRef;
|
||||
|
||||
typedef enum {
|
||||
LLVMCodeGenLevelNone,
|
||||
LLVMCodeGenLevelLess,
|
||||
LLVMCodeGenLevelDefault,
|
||||
LLVMCodeGenLevelAggressive
|
||||
} LLVMCodeGenOptLevel;
|
||||
|
||||
typedef enum {
|
||||
LLVMRelocDefault,
|
||||
LLVMRelocStatic,
|
||||
LLVMRelocPIC,
|
||||
LLVMRelocDynamicNoPic
|
||||
} LLVMRelocMode;
|
||||
|
||||
typedef enum {
|
||||
LLVMCodeModelDefault,
|
||||
LLVMCodeModelJITDefault,
|
||||
LLVMCodeModelSmall,
|
||||
LLVMCodeModelKernel,
|
||||
LLVMCodeModelMedium,
|
||||
LLVMCodeModelLarge
|
||||
} LLVMCodeModel;
|
||||
|
||||
typedef enum {
|
||||
LLVMAssemblyFile,
|
||||
LLVMObjectFile
|
||||
} LLVMCodeGenFileType;
|
||||
|
||||
/** Returns the first llvm::Target in the registered targets list. */
|
||||
LLVMTargetRef LLVMGetFirstTarget();
|
||||
/** Returns the next llvm::Target given a previous one (or null if there's none) */
|
||||
LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T);
|
||||
|
||||
/*===-- Target ------------------------------------------------------------===*/
|
||||
/** Returns the name of a target. See llvm::Target::getName */
|
||||
const char *LLVMGetTargetName(LLVMTargetRef T);
|
||||
|
||||
/** Returns the description of a target. See llvm::Target::getDescription */
|
||||
const char *LLVMGetTargetDescription(LLVMTargetRef T);
|
||||
|
||||
/** Returns if the target has a JIT */
|
||||
LLVMBool LLVMTargetHasJIT(LLVMTargetRef T);
|
||||
|
||||
/** Returns if the target has a TargetMachine associated */
|
||||
LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T);
|
||||
|
||||
/** Returns if the target as an ASM backend (required for emitting output) */
|
||||
LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T);
|
||||
|
||||
/*===-- Target Machine ----------------------------------------------------===*/
|
||||
/** Creates a new llvm::TargetMachine. See llvm::Target::createTargetMachine */
|
||||
LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T, char *Triple,
|
||||
char *CPU, char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
|
||||
LLVMCodeModel CodeModel);
|
||||
|
||||
/** Dispose the LLVMTargetMachineRef instance generated by
|
||||
LLVMCreateTargetMachine. */
|
||||
void LLVMDisposeTargetMachine(LLVMTargetMachineRef T);
|
||||
|
||||
/** Returns the Target used in a TargetMachine */
|
||||
LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T);
|
||||
|
||||
/** Returns the triple used creating this target machine. See
|
||||
llvm::TargetMachine::getTriple. The result needs to be disposed with
|
||||
LLVMDisposeMessage. */
|
||||
char *LLVMGetTargetMachineTriple(LLVMTargetMachineRef T);
|
||||
|
||||
/** Returns the cpu used creating this target machine. See
|
||||
llvm::TargetMachine::getCPU. The result needs to be disposed with
|
||||
LLVMDisposeMessage. */
|
||||
char *LLVMGetTargetMachineCPU(LLVMTargetMachineRef T);
|
||||
|
||||
/** Returns the feature string used creating this target machine. See
|
||||
llvm::TargetMachine::getFeatureString. The result needs to be disposed with
|
||||
LLVMDisposeMessage. */
|
||||
char *LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T);
|
||||
|
||||
/** Returns the llvm::TargetData used for this llvm:TargetMachine. */
|
||||
LLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T);
|
||||
|
||||
/** Emits an asm or object file for the given module to the filename. This
|
||||
wraps several c++ only classes (among them a file stream). Returns any
|
||||
error in ErrorMessage. Use LLVMDisposeMessage to dispose the message. */
|
||||
LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
|
||||
char *Filename, LLVMCodeGenFileType codegen, char **ErrorMessage);
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
class TargetMachine;
|
||||
class Target;
|
||||
|
||||
inline TargetMachine *unwrap(LLVMTargetMachineRef P) {
|
||||
return reinterpret_cast<TargetMachine*>(P);
|
||||
}
|
||||
inline Target *unwrap(LLVMTargetRef P) {
|
||||
return reinterpret_cast<Target*>(P);
|
||||
}
|
||||
inline LLVMTargetMachineRef wrap(const TargetMachine *P) {
|
||||
return reinterpret_cast<LLVMTargetMachineRef>(
|
||||
const_cast<TargetMachine*>(P));
|
||||
}
|
||||
inline LLVMTargetRef wrap(const Target * P) {
|
||||
return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -21,6 +21,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCTransformsIPO Interprocedural transformations
|
||||
* @ingroup LLVMCTransforms
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** See llvm::createArgumentPromotionPass function. */
|
||||
void LLVMAddArgumentPromotionPass(LLVMPassManagerRef PM);
|
||||
|
||||
|
|
@ -63,6 +70,10 @@ void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM);
|
|||
/** See llvm::createStripSymbolsPass function. */
|
||||
void LLVMAddStripSymbolsPass(LLVMPassManagerRef PM);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
|
|
|||
|
|
@ -23,6 +23,13 @@ typedef struct LLVMOpaquePassManagerBuilder *LLVMPassManagerBuilderRef;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCTransformsPassManagerBuilder Pass manager builder
|
||||
* @ingroup LLVMCTransforms
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** See llvm::PassManagerBuilder. */
|
||||
LLVMPassManagerBuilderRef LLVMPassManagerBuilderCreate(void);
|
||||
void LLVMPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB);
|
||||
|
|
@ -73,6 +80,10 @@ void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB,
|
|||
bool Internalize,
|
||||
bool RunInliner);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCTransformsScalar Scalar transformations
|
||||
* @ingroup LLVMCTransforms
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** See llvm::createAggressiveDCEPass function. */
|
||||
void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM);
|
||||
|
||||
|
|
@ -116,6 +123,9 @@ void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM);
|
|||
/** See llvm::createBasicAliasAnalysisPass function */
|
||||
void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
48
contrib/llvm/include/llvm-c/Transforms/Vectorize.h
Normal file
48
contrib/llvm/include/llvm-c/Transforms/Vectorize.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*===---------------------------Vectorize.h --------------------- -*- C -*-===*\
|
||||
|*===----------- Vectorization Transformation Library C Interface ---------===*|
|
||||
|* *|
|
||||
|* 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 libLLVMVectorize.a, which *|
|
||||
|* implements various vectorization transformations 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_VECTORIZE_H
|
||||
#define LLVM_C_TRANSFORMS_VECTORIZE_H
|
||||
|
||||
#include "llvm-c/Core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCTransformsVectorize Vectorization transformations
|
||||
* @ingroup LLVMCTransforms
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** See llvm::createBBVectorizePass function. */
|
||||
void LLVMAddBBVectorizePass(LLVMPassManagerRef PM);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -20,24 +20,31 @@
|
|||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCLTO LTO
|
||||
* @ingroup LLVMC
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define LTO_API_VERSION 4
|
||||
|
||||
typedef enum {
|
||||
LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */
|
||||
LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0,
|
||||
LTO_SYMBOL_PERMISSIONS_CODE = 0x000000A0,
|
||||
LTO_SYMBOL_PERMISSIONS_DATA = 0x000000C0,
|
||||
LTO_SYMBOL_PERMISSIONS_RODATA = 0x00000080,
|
||||
LTO_SYMBOL_DEFINITION_MASK = 0x00000700,
|
||||
LTO_SYMBOL_DEFINITION_REGULAR = 0x00000100,
|
||||
LTO_SYMBOL_DEFINITION_TENTATIVE = 0x00000200,
|
||||
LTO_SYMBOL_DEFINITION_WEAK = 0x00000300,
|
||||
LTO_SYMBOL_DEFINITION_UNDEFINED = 0x00000400,
|
||||
LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0,
|
||||
LTO_SYMBOL_PERMISSIONS_CODE = 0x000000A0,
|
||||
LTO_SYMBOL_PERMISSIONS_DATA = 0x000000C0,
|
||||
LTO_SYMBOL_PERMISSIONS_RODATA = 0x00000080,
|
||||
LTO_SYMBOL_DEFINITION_MASK = 0x00000700,
|
||||
LTO_SYMBOL_DEFINITION_REGULAR = 0x00000100,
|
||||
LTO_SYMBOL_DEFINITION_TENTATIVE = 0x00000200,
|
||||
LTO_SYMBOL_DEFINITION_WEAK = 0x00000300,
|
||||
LTO_SYMBOL_DEFINITION_UNDEFINED = 0x00000400,
|
||||
LTO_SYMBOL_DEFINITION_WEAKUNDEF = 0x00000500,
|
||||
LTO_SYMBOL_SCOPE_MASK = 0x00003800,
|
||||
LTO_SYMBOL_SCOPE_INTERNAL = 0x00000800,
|
||||
LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000,
|
||||
LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000,
|
||||
LTO_SYMBOL_SCOPE_MASK = 0x00003800,
|
||||
LTO_SYMBOL_SCOPE_INTERNAL = 0x00000800,
|
||||
LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000,
|
||||
LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000,
|
||||
LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800,
|
||||
LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800
|
||||
} lto_symbol_attributes;
|
||||
|
|
@ -88,7 +95,7 @@ lto_module_is_object_file(const char* path);
|
|||
* Checks if a file is a loadable object compiled for requested target.
|
||||
*/
|
||||
extern bool
|
||||
lto_module_is_object_file_for_target(const char* path,
|
||||
lto_module_is_object_file_for_target(const char* path,
|
||||
const char* target_triple_prefix);
|
||||
|
||||
|
||||
|
|
@ -103,7 +110,7 @@ lto_module_is_object_file_in_memory(const void* mem, size_t length);
|
|||
* Checks if a buffer is a loadable object compiled for requested target.
|
||||
*/
|
||||
extern bool
|
||||
lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length,
|
||||
lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length,
|
||||
const char* target_triple_prefix);
|
||||
|
||||
|
||||
|
|
@ -243,6 +250,12 @@ extern void
|
|||
lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
|
||||
int nargs);
|
||||
|
||||
/**
|
||||
* Enables the internalize pass during LTO optimizations.
|
||||
*/
|
||||
extern void
|
||||
lto_codegen_set_whole_program_optimization(lto_code_gen_t cg);
|
||||
|
||||
/**
|
||||
* Adds to a list of all global symbols that must exist in the final
|
||||
* generated code. If a function is not listed, it might be
|
||||
|
|
@ -251,7 +264,6 @@ lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
|
|||
extern void
|
||||
lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol);
|
||||
|
||||
|
||||
/**
|
||||
* Writes a new object file at the specified path that contains the
|
||||
* merged contents of all modules added so far.
|
||||
|
|
@ -260,11 +272,10 @@ lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char* symbol);
|
|||
extern bool
|
||||
lto_codegen_write_merged_modules(lto_code_gen_t cg, const char* path);
|
||||
|
||||
|
||||
/**
|
||||
* Generates code for all added modules into one native object file.
|
||||
* On success returns a pointer to a generated mach-o/ELF buffer and
|
||||
* length set to the buffer size. The buffer is owned by the
|
||||
* length set to the buffer size. The buffer is owned by the
|
||||
* lto_code_gen_t and will be freed when lto_codegen_dispose()
|
||||
* is called, or lto_codegen_compile() is called again.
|
||||
* On failure, returns NULL (check lto_get_error_message() for details).
|
||||
|
|
@ -285,9 +296,13 @@ lto_codegen_compile_to_file(lto_code_gen_t cg, const char** name);
|
|||
*/
|
||||
extern void
|
||||
lto_codegen_debug_options(lto_code_gen_t cg, const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ namespace llvm {
|
|||
const fltSemantics &getSemantics() const { return *semantics; }
|
||||
bool isZero() const { return category == fcZero; }
|
||||
bool isNonZero() const { return category != fcZero; }
|
||||
bool isNormal() const { return category == fcNormal; }
|
||||
bool isNaN() const { return category == fcNaN; }
|
||||
bool isInfinity() const { return category == fcInfinity; }
|
||||
bool isNegative() const { return sign; }
|
||||
|
|
@ -328,8 +329,16 @@ namespace llvm {
|
|||
|
||||
APFloat& operator=(const APFloat &);
|
||||
|
||||
/* Return an arbitrary integer value usable for hashing. */
|
||||
uint32_t getHashValue() const;
|
||||
/// \brief Overload to compute a hash code for an APFloat value.
|
||||
///
|
||||
/// Note that the use of hash codes for floating point values is in general
|
||||
/// frought with peril. Equality is hard to define for these values. For
|
||||
/// example, should negative and positive zero hash to different codes? Are
|
||||
/// they equal or not? This hash value implementation specifically
|
||||
/// emphasizes producing different codes for different inputs in order to
|
||||
/// be used in canonicalization and memoization. As such, equality is
|
||||
/// bitwiseIsEqual, and 0 != -0.
|
||||
friend hash_code hash_value(const APFloat &Arg);
|
||||
|
||||
/// Converts this value into a decimal string.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -23,11 +23,12 @@
|
|||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class Serializer;
|
||||
class Deserializer;
|
||||
class FoldingSetNodeID;
|
||||
class raw_ostream;
|
||||
class Serializer;
|
||||
class StringRef;
|
||||
class hash_code;
|
||||
class raw_ostream;
|
||||
|
||||
template<typename T>
|
||||
class SmallVectorImpl;
|
||||
|
|
@ -497,15 +498,13 @@ public:
|
|||
if (loBitsSet == APINT_BITS_PER_WORD)
|
||||
return APInt(numBits, -1ULL);
|
||||
// For small values, return quickly.
|
||||
if (numBits < APINT_BITS_PER_WORD)
|
||||
return APInt(numBits, (1ULL << loBitsSet) - 1);
|
||||
if (loBitsSet <= APINT_BITS_PER_WORD)
|
||||
return APInt(numBits, -1ULL >> (APINT_BITS_PER_WORD - loBitsSet));
|
||||
return getAllOnesValue(numBits).lshr(numBits - loBitsSet);
|
||||
}
|
||||
|
||||
/// The hash value is computed as the sum of the words and the bit width.
|
||||
/// @returns A hash value computed from the sum of the APInt words.
|
||||
/// @brief Get a hash value based on this APInt
|
||||
uint64_t getHashValue() const;
|
||||
/// \brief 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.
|
||||
/// This is useful for writing out the APInt in binary form without any
|
||||
|
|
@ -562,7 +561,15 @@ public:
|
|||
/// Performs logical negation operation on this APInt.
|
||||
/// @returns true if *this is zero, false otherwise.
|
||||
/// @brief Logical negation operator.
|
||||
bool operator!() const;
|
||||
bool operator!() const {
|
||||
if (isSingleWord())
|
||||
return !VAL;
|
||||
|
||||
for (unsigned i = 0; i != getNumWords(); ++i)
|
||||
if (pVal[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Assignment Operators
|
||||
|
|
@ -835,7 +842,11 @@ public:
|
|||
|
||||
/// @returns the bit value at bitPosition
|
||||
/// @brief Array-indexing support.
|
||||
bool operator[](unsigned bitPosition) const;
|
||||
bool operator[](unsigned bitPosition) const {
|
||||
assert(bitPosition < getBitWidth() && "Bit position out of bounds!");
|
||||
return (maskBit(bitPosition) &
|
||||
(isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != 0;
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Comparison Operators
|
||||
|
|
@ -1056,6 +1067,16 @@ public:
|
|||
/// @brief Zero extend or truncate to width
|
||||
APInt zextOrTrunc(unsigned width) const;
|
||||
|
||||
/// Make this APInt have the bit width given by \p width. The value is sign
|
||||
/// extended, or left alone to make it that width.
|
||||
/// @brief Sign extend or truncate to width
|
||||
APInt sextOrSelf(unsigned width) const;
|
||||
|
||||
/// Make this APInt have the bit width given by \p width. The value is zero
|
||||
/// extended, or left alone to make it that width.
|
||||
/// @brief Zero extend or truncate to width
|
||||
APInt zextOrSelf(unsigned width) const;
|
||||
|
||||
/// @}
|
||||
/// @name Bit Manipulation Operators
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@
|
|||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class APInt;
|
||||
|
||||
|
||||
/// ArrayRef - Represent a constant reference to an array (0 or more elements
|
||||
/// consecutively in memory), i.e. a start pointer and a length. It allows
|
||||
/// various APIs to take consecutive elements easily and conveniently.
|
||||
|
|
@ -33,33 +32,33 @@ namespace llvm {
|
|||
typedef const T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
typedef size_t size_type;
|
||||
|
||||
|
||||
private:
|
||||
/// The start of the array, in an external buffer.
|
||||
const T *Data;
|
||||
|
||||
|
||||
/// The number of elements.
|
||||
size_type Length;
|
||||
|
||||
|
||||
public:
|
||||
/// @name Constructors
|
||||
/// @{
|
||||
|
||||
|
||||
/// Construct an empty ArrayRef.
|
||||
/*implicit*/ ArrayRef() : Data(0), Length(0) {}
|
||||
|
||||
|
||||
/// Construct an ArrayRef from a single element.
|
||||
/*implicit*/ ArrayRef(const T &OneElt)
|
||||
: Data(&OneElt), Length(1) {}
|
||||
|
||||
|
||||
/// Construct an ArrayRef from a pointer and length.
|
||||
/*implicit*/ ArrayRef(const T *data, size_t length)
|
||||
: Data(data), Length(length) {}
|
||||
|
||||
|
||||
/// Construct an ArrayRef from a range.
|
||||
ArrayRef(const T *begin, const T *end)
|
||||
: Data(begin), Length(end - begin) {}
|
||||
|
||||
|
||||
/// Construct an ArrayRef from a SmallVector.
|
||||
/*implicit*/ ArrayRef(const SmallVectorImpl<T> &Vec)
|
||||
: Data(Vec.data()), Length(Vec.size()) {}
|
||||
|
|
@ -67,39 +66,39 @@ namespace llvm {
|
|||
/// Construct an ArrayRef from a std::vector.
|
||||
/*implicit*/ ArrayRef(const std::vector<T> &Vec)
|
||||
: Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {}
|
||||
|
||||
|
||||
/// Construct an ArrayRef from a C array.
|
||||
template <size_t N>
|
||||
/*implicit*/ ArrayRef(const T (&Arr)[N])
|
||||
: Data(Arr), Length(N) {}
|
||||
|
||||
|
||||
/// @}
|
||||
/// @name Simple Operations
|
||||
/// @{
|
||||
|
||||
iterator begin() const { return Data; }
|
||||
iterator end() const { return Data + Length; }
|
||||
|
||||
|
||||
/// empty - Check if the array is empty.
|
||||
bool empty() const { return Length == 0; }
|
||||
|
||||
|
||||
const T *data() const { return Data; }
|
||||
|
||||
|
||||
/// size - Get the array size.
|
||||
size_t size() const { return Length; }
|
||||
|
||||
|
||||
/// front - Get the first element.
|
||||
const T &front() const {
|
||||
assert(!empty());
|
||||
return Data[0];
|
||||
}
|
||||
|
||||
|
||||
/// back - Get the last element.
|
||||
const T &back() const {
|
||||
assert(!empty());
|
||||
return Data[Length-1];
|
||||
}
|
||||
|
||||
|
||||
/// equals - Check for element-wise equality.
|
||||
bool equals(ArrayRef RHS) const {
|
||||
if (Length != RHS.Length)
|
||||
|
|
@ -111,18 +110,18 @@ namespace llvm {
|
|||
}
|
||||
|
||||
/// slice(n) - Chop off the first N elements of the array.
|
||||
ArrayRef<T> slice(unsigned N) {
|
||||
ArrayRef<T> slice(unsigned N) const {
|
||||
assert(N <= size() && "Invalid specifier");
|
||||
return ArrayRef<T>(data()+N, size()-N);
|
||||
}
|
||||
|
||||
/// slice(n, m) - Chop off the first N elements of the array, and keep M
|
||||
/// elements in the array.
|
||||
ArrayRef<T> slice(unsigned N, unsigned M) {
|
||||
ArrayRef<T> slice(unsigned N, unsigned M) const {
|
||||
assert(N+M <= size() && "Invalid specifier");
|
||||
return ArrayRef<T>(data()+N, M);
|
||||
}
|
||||
|
||||
|
||||
/// @}
|
||||
/// @name Operator Overloads
|
||||
/// @{
|
||||
|
|
@ -130,22 +129,104 @@ namespace llvm {
|
|||
assert(Index < Length && "Invalid index!");
|
||||
return Data[Index];
|
||||
}
|
||||
|
||||
|
||||
/// @}
|
||||
/// @name Expensive Operations
|
||||
/// @{
|
||||
std::vector<T> vec() const {
|
||||
return std::vector<T>(Data, Data+Length);
|
||||
}
|
||||
|
||||
|
||||
/// @}
|
||||
/// @name Conversion operators
|
||||
/// @{
|
||||
operator std::vector<T>() const {
|
||||
return std::vector<T>(Data, Data+Length);
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
/// MutableArrayRef - Represent a mutable reference to an array (0 or more
|
||||
/// elements consecutively in memory), i.e. a start pointer and a length. It
|
||||
/// allows various APIs to take and modify consecutive elements easily and
|
||||
/// conveniently.
|
||||
///
|
||||
/// This class does not own the underlying data, it is expected to be used in
|
||||
/// situations where the data resides in some other buffer, whose lifetime
|
||||
/// extends past that of the MutableArrayRef. For this reason, it is not in
|
||||
/// general safe to store a MutableArrayRef.
|
||||
///
|
||||
/// This is intended to be trivially copyable, so it should be passed by
|
||||
/// value.
|
||||
template<typename T>
|
||||
class MutableArrayRef : public ArrayRef<T> {
|
||||
public:
|
||||
typedef T *iterator;
|
||||
|
||||
/// Construct an empty ArrayRef.
|
||||
/*implicit*/ MutableArrayRef() : ArrayRef<T>() {}
|
||||
|
||||
/// Construct an MutableArrayRef from a single element.
|
||||
/*implicit*/ MutableArrayRef(T &OneElt) : ArrayRef<T>(OneElt) {}
|
||||
|
||||
/// Construct an MutableArrayRef from a pointer and length.
|
||||
/*implicit*/ MutableArrayRef(T *data, size_t length)
|
||||
: ArrayRef<T>(data, length) {}
|
||||
|
||||
/// Construct an MutableArrayRef from a range.
|
||||
MutableArrayRef(T *begin, T *end) : ArrayRef<T>(begin, end) {}
|
||||
|
||||
/// Construct an MutableArrayRef from a SmallVector.
|
||||
/*implicit*/ MutableArrayRef(SmallVectorImpl<T> &Vec)
|
||||
: ArrayRef<T>(Vec) {}
|
||||
|
||||
/// Construct a MutableArrayRef from a std::vector.
|
||||
/*implicit*/ MutableArrayRef(std::vector<T> &Vec)
|
||||
: ArrayRef<T>(Vec) {}
|
||||
|
||||
/// Construct an MutableArrayRef from a C array.
|
||||
template <size_t N>
|
||||
/*implicit*/ MutableArrayRef(T (&Arr)[N])
|
||||
: ArrayRef<T>(Arr) {}
|
||||
|
||||
T *data() const { return const_cast<T*>(ArrayRef<T>::data()); }
|
||||
|
||||
iterator begin() const { return data(); }
|
||||
iterator end() const { return data() + this->size(); }
|
||||
|
||||
/// front - Get the first element.
|
||||
T &front() const {
|
||||
assert(!this->empty());
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
/// back - Get the last element.
|
||||
T &back() const {
|
||||
assert(!this->empty());
|
||||
return data()[this->size()-1];
|
||||
}
|
||||
|
||||
/// slice(n) - Chop off the first N elements of the array.
|
||||
MutableArrayRef<T> slice(unsigned N) const {
|
||||
assert(N <= this->size() && "Invalid specifier");
|
||||
return MutableArrayRef<T>(data()+N, this->size()-N);
|
||||
}
|
||||
|
||||
/// slice(n, m) - Chop off the first N elements of the array, and keep M
|
||||
/// elements in the array.
|
||||
MutableArrayRef<T> slice(unsigned N, unsigned M) const {
|
||||
assert(N+M <= this->size() && "Invalid specifier");
|
||||
return MutableArrayRef<T>(data()+N, M);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Operator Overloads
|
||||
/// @{
|
||||
T &operator[](size_t Index) const {
|
||||
assert(Index < this->size() && "Invalid index!");
|
||||
return data()[Index];
|
||||
}
|
||||
};
|
||||
|
||||
/// @name ArrayRef Convenience constructors
|
||||
|
|
@ -215,5 +296,5 @@ namespace llvm {
|
|||
static const bool value = true;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@
|
|||
#ifndef LLVM_ADT_BITVECTOR_H
|
||||
#define LLVM_ADT_BITVECTOR_H
|
||||
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ public:
|
|||
else if (sizeof(BitWord) == 8)
|
||||
NumBits += CountPopulation_64(Bits[i]);
|
||||
else
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
return NumBits;
|
||||
}
|
||||
|
||||
|
|
@ -146,10 +146,9 @@ public:
|
|||
if (Bits[i] != 0) {
|
||||
if (sizeof(BitWord) == 4)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]);
|
||||
else if (sizeof(BitWord) == 8)
|
||||
if (sizeof(BitWord) == 8)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
|
||||
else
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -170,10 +169,9 @@ public:
|
|||
if (Copy != 0) {
|
||||
if (sizeof(BitWord) == 4)
|
||||
return WordPos * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Copy);
|
||||
else if (sizeof(BitWord) == 8)
|
||||
if (sizeof(BitWord) == 8)
|
||||
return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy);
|
||||
else
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
|
||||
// Check subsequent words.
|
||||
|
|
@ -181,10 +179,9 @@ public:
|
|||
if (Bits[i] != 0) {
|
||||
if (sizeof(BitWord) == 4)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_32((uint32_t)Bits[i]);
|
||||
else if (sizeof(BitWord) == 8)
|
||||
if (sizeof(BitWord) == 8)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
|
||||
else
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -318,6 +315,16 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
// reset - Reset bits that are set in RHS. Same as *this &= ~RHS.
|
||||
BitVector &reset(const BitVector &RHS) {
|
||||
unsigned ThisWords = NumBitWords(size());
|
||||
unsigned RHSWords = NumBitWords(RHS.size());
|
||||
unsigned i;
|
||||
for (i = 0; i != std::min(ThisWords, RHSWords); ++i)
|
||||
Bits[i] &= ~RHS.Bits[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
BitVector &operator|=(const BitVector &RHS) {
|
||||
if (size() < RHS.size())
|
||||
resize(RHS.size());
|
||||
|
|
@ -365,6 +372,42 @@ public:
|
|||
std::swap(Capacity, RHS.Capacity);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Portable bit mask operations.
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// These methods all operate on arrays of uint32_t, each holding 32 bits. The
|
||||
// fixed word size makes it easier to work with literal bit vector constants
|
||||
// in portable code.
|
||||
//
|
||||
// The LSB in each word is the lowest numbered bit. The size of a portable
|
||||
// bit mask is always a whole multiple of 32 bits. If no bit mask size is
|
||||
// given, the bit mask is assumed to cover the entire BitVector.
|
||||
|
||||
/// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize.
|
||||
/// This computes "*this |= Mask".
|
||||
void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
applyMask<true, false>(Mask, MaskWords);
|
||||
}
|
||||
|
||||
/// clearBitsInMask - Clear any bits in this vector that are set in Mask.
|
||||
/// Don't resize. This computes "*this &= ~Mask".
|
||||
void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
applyMask<false, false>(Mask, MaskWords);
|
||||
}
|
||||
|
||||
/// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask.
|
||||
/// Don't resize. This computes "*this |= ~Mask".
|
||||
void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
applyMask<true, true>(Mask, MaskWords);
|
||||
}
|
||||
|
||||
/// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask.
|
||||
/// Don't resize. This computes "*this &= Mask".
|
||||
void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
|
||||
applyMask<false, true>(Mask, MaskWords);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned NumBitWords(unsigned S) const {
|
||||
return (S + BITWORD_SIZE-1) / BITWORD_SIZE;
|
||||
|
|
@ -400,6 +443,33 @@ private:
|
|||
void init_words(BitWord *B, unsigned NumWords, bool t) {
|
||||
memset(B, 0 - (int)t, NumWords*sizeof(BitWord));
|
||||
}
|
||||
|
||||
template<bool AddBits, bool InvertMask>
|
||||
void applyMask(const uint32_t *Mask, unsigned MaskWords) {
|
||||
assert(BITWORD_SIZE % 32 == 0 && "Unsupported BitWord size.");
|
||||
MaskWords = std::min(MaskWords, (size() + 31) / 32);
|
||||
const unsigned Scale = BITWORD_SIZE / 32;
|
||||
unsigned i;
|
||||
for (i = 0; MaskWords >= Scale; ++i, MaskWords -= Scale) {
|
||||
BitWord BW = Bits[i];
|
||||
// This inner loop should unroll completely when BITWORD_SIZE > 32.
|
||||
for (unsigned b = 0; b != BITWORD_SIZE; b += 32) {
|
||||
uint32_t M = *Mask++;
|
||||
if (InvertMask) M = ~M;
|
||||
if (AddBits) BW |= BitWord(M) << b;
|
||||
else BW &= ~(BitWord(M) << b);
|
||||
}
|
||||
Bits[i] = BW;
|
||||
}
|
||||
for (unsigned b = 0; MaskWords; b += 32, --MaskWords) {
|
||||
uint32_t M = *Mask++;
|
||||
if (InvertMask) M = ~M;
|
||||
if (AddBits) Bits[i] |= BitWord(M) << b;
|
||||
else Bits[i] &= ~(BitWord(M) << b);
|
||||
}
|
||||
if (AddBits)
|
||||
clear_unused_bits();
|
||||
}
|
||||
};
|
||||
|
||||
inline BitVector operator&(const BitVector &LHS, const BitVector &RHS) {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ namespace llvm {
|
|||
/// for more information on the properties which the predicate function itself
|
||||
/// should satisfy.
|
||||
class DAGDeltaAlgorithm {
|
||||
virtual void anchor();
|
||||
public:
|
||||
typedef unsigned change_ty;
|
||||
typedef std::pair<change_ty, change_ty> edge_ty;
|
||||
|
|
|
|||
|
|
@ -30,12 +30,11 @@ namespace llvm {
|
|||
|
||||
template<typename KeyT, typename ValueT,
|
||||
typename KeyInfoT = DenseMapInfo<KeyT>,
|
||||
typename ValueInfoT = DenseMapInfo<ValueT>, bool IsConst = false>
|
||||
bool IsConst = false>
|
||||
class DenseMapIterator;
|
||||
|
||||
template<typename KeyT, typename ValueT,
|
||||
typename KeyInfoT = DenseMapInfo<KeyT>,
|
||||
typename ValueInfoT = DenseMapInfo<ValueT> >
|
||||
typename KeyInfoT = DenseMapInfo<KeyT> >
|
||||
class DenseMap {
|
||||
typedef std::pair<KeyT, ValueT> BucketT;
|
||||
unsigned NumBuckets;
|
||||
|
|
@ -80,19 +79,19 @@ public:
|
|||
|
||||
typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator;
|
||||
typedef DenseMapIterator<KeyT, ValueT,
|
||||
KeyInfoT, ValueInfoT, true> const_iterator;
|
||||
KeyInfoT, true> const_iterator;
|
||||
inline iterator begin() {
|
||||
// When the map is empty, avoid the overhead of AdvancePastEmptyBuckets().
|
||||
return empty() ? end() : iterator(Buckets, Buckets+NumBuckets);
|
||||
}
|
||||
inline iterator end() {
|
||||
return iterator(Buckets+NumBuckets, Buckets+NumBuckets);
|
||||
return iterator(Buckets+NumBuckets, Buckets+NumBuckets, true);
|
||||
}
|
||||
inline const_iterator begin() const {
|
||||
return empty() ? end() : const_iterator(Buckets, Buckets+NumBuckets);
|
||||
}
|
||||
inline const_iterator end() const {
|
||||
return const_iterator(Buckets+NumBuckets, Buckets+NumBuckets);
|
||||
return const_iterator(Buckets+NumBuckets, Buckets+NumBuckets, true);
|
||||
}
|
||||
|
||||
bool empty() const { return NumEntries == 0; }
|
||||
|
|
@ -137,13 +136,33 @@ public:
|
|||
iterator find(const KeyT &Val) {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(Val, TheBucket))
|
||||
return iterator(TheBucket, Buckets+NumBuckets);
|
||||
return iterator(TheBucket, Buckets+NumBuckets, true);
|
||||
return end();
|
||||
}
|
||||
const_iterator find(const KeyT &Val) const {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(Val, TheBucket))
|
||||
return const_iterator(TheBucket, Buckets+NumBuckets);
|
||||
return const_iterator(TheBucket, Buckets+NumBuckets, true);
|
||||
return end();
|
||||
}
|
||||
|
||||
/// Alternate version of find() which allows a different, and possibly
|
||||
/// less expensive, key type.
|
||||
/// The DenseMapInfo is responsible for supplying methods
|
||||
/// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key
|
||||
/// type used.
|
||||
template<class LookupKeyT>
|
||||
iterator find_as(const LookupKeyT &Val) {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(Val, TheBucket))
|
||||
return iterator(TheBucket, Buckets+NumBuckets, true);
|
||||
return end();
|
||||
}
|
||||
template<class LookupKeyT>
|
||||
const_iterator find_as(const LookupKeyT &Val) const {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(Val, TheBucket))
|
||||
return const_iterator(TheBucket, Buckets+NumBuckets, true);
|
||||
return end();
|
||||
}
|
||||
|
||||
|
|
@ -162,13 +181,12 @@ public:
|
|||
std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(KV.first, TheBucket))
|
||||
return std::make_pair(iterator(TheBucket, Buckets+NumBuckets),
|
||||
return std::make_pair(iterator(TheBucket, Buckets+NumBuckets, true),
|
||||
false); // Already in map.
|
||||
|
||||
// Otherwise, insert the new element.
|
||||
TheBucket = InsertIntoBucket(KV.first, KV.second, TheBucket);
|
||||
return std::make_pair(iterator(TheBucket, Buckets+NumBuckets),
|
||||
true);
|
||||
return std::make_pair(iterator(TheBucket, Buckets+NumBuckets, true), true);
|
||||
}
|
||||
|
||||
/// insert - Range insertion of pairs.
|
||||
|
|
@ -237,7 +255,7 @@ public:
|
|||
private:
|
||||
void CopyFrom(const DenseMap& other) {
|
||||
if (NumBuckets != 0 &&
|
||||
(!isPodLike<KeyInfoT>::value || !isPodLike<ValueInfoT>::value)) {
|
||||
(!isPodLike<KeyT>::value || !isPodLike<ValueT>::value)) {
|
||||
const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
|
||||
for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) {
|
||||
if (!KeyInfoT::isEqual(P->first, EmptyKey) &&
|
||||
|
|
@ -266,7 +284,7 @@ private:
|
|||
|
||||
Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) * NumBuckets));
|
||||
|
||||
if (isPodLike<KeyInfoT>::value && isPodLike<ValueInfoT>::value)
|
||||
if (isPodLike<KeyT>::value && isPodLike<ValueT>::value)
|
||||
memcpy(Buckets, other.Buckets, NumBuckets * sizeof(BucketT));
|
||||
else
|
||||
for (size_t i = 0; i < NumBuckets; ++i) {
|
||||
|
|
@ -310,6 +328,10 @@ private:
|
|||
static unsigned getHashValue(const KeyT &Val) {
|
||||
return KeyInfoT::getHashValue(Val);
|
||||
}
|
||||
template<typename LookupKeyT>
|
||||
static unsigned getHashValue(const LookupKeyT &Val) {
|
||||
return KeyInfoT::getHashValue(Val);
|
||||
}
|
||||
static const KeyT getEmptyKey() {
|
||||
return KeyInfoT::getEmptyKey();
|
||||
}
|
||||
|
|
@ -321,7 +343,8 @@ private:
|
|||
/// FoundBucket. If the bucket contains the key and a value, this returns
|
||||
/// true, otherwise it returns a bucket with an empty marker or tombstone and
|
||||
/// returns false.
|
||||
bool LookupBucketFor(const KeyT &Val, BucketT *&FoundBucket) const {
|
||||
template<typename LookupKeyT>
|
||||
bool LookupBucketFor(const LookupKeyT &Val, BucketT *&FoundBucket) const {
|
||||
unsigned BucketNo = getHashValue(Val);
|
||||
unsigned ProbeAmt = 1;
|
||||
BucketT *BucketsPtr = Buckets;
|
||||
|
|
@ -342,7 +365,7 @@ private:
|
|||
while (1) {
|
||||
BucketT *ThisBucket = BucketsPtr + (BucketNo & (NumBuckets-1));
|
||||
// Found Val's bucket? If so, return it.
|
||||
if (KeyInfoT::isEqual(ThisBucket->first, Val)) {
|
||||
if (KeyInfoT::isEqual(Val, ThisBucket->first)) {
|
||||
FoundBucket = ThisBucket;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -478,12 +501,12 @@ public:
|
|||
};
|
||||
|
||||
template<typename KeyT, typename ValueT,
|
||||
typename KeyInfoT, typename ValueInfoT, bool IsConst>
|
||||
typename KeyInfoT, bool IsConst>
|
||||
class DenseMapIterator {
|
||||
typedef std::pair<KeyT, ValueT> Bucket;
|
||||
typedef DenseMapIterator<KeyT, ValueT,
|
||||
KeyInfoT, ValueInfoT, true> ConstIterator;
|
||||
friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, ValueInfoT, true>;
|
||||
KeyInfoT, true> ConstIterator;
|
||||
friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, true>;
|
||||
public:
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef typename conditional<IsConst, const Bucket, Bucket>::type value_type;
|
||||
|
|
@ -495,15 +518,16 @@ private:
|
|||
public:
|
||||
DenseMapIterator() : Ptr(0), End(0) {}
|
||||
|
||||
DenseMapIterator(pointer Pos, pointer E) : Ptr(Pos), End(E) {
|
||||
AdvancePastEmptyBuckets();
|
||||
DenseMapIterator(pointer Pos, pointer E, bool NoAdvance = false)
|
||||
: Ptr(Pos), End(E) {
|
||||
if (!NoAdvance) AdvancePastEmptyBuckets();
|
||||
}
|
||||
|
||||
// If IsConst is true this is a converting constructor from iterator to
|
||||
// const_iterator and the default copy constructor is used.
|
||||
// Otherwise this is a copy constructor for iterator.
|
||||
DenseMapIterator(const DenseMapIterator<KeyT, ValueT,
|
||||
KeyInfoT, ValueInfoT, false>& I)
|
||||
KeyInfoT, false>& I)
|
||||
: Ptr(I.Ptr), End(I.End) {}
|
||||
|
||||
reference operator*() const {
|
||||
|
|
@ -541,9 +565,9 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
template<typename KeyT, typename ValueT, typename KeyInfoT, typename ValueInfoT>
|
||||
template<typename KeyT, typename ValueT, typename KeyInfoT>
|
||||
static inline size_t
|
||||
capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT, ValueInfoT> &X) {
|
||||
capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) {
|
||||
return X.getMemorySize();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ template<> struct DenseMapInfo<char> {
|
|||
|
||||
// Provide DenseMapInfo for unsigned ints.
|
||||
template<> struct DenseMapInfo<unsigned> {
|
||||
static inline unsigned getEmptyKey() { return ~0; }
|
||||
static inline unsigned getEmptyKey() { return ~0U; }
|
||||
static inline unsigned getTombstoneKey() { return ~0U - 1; }
|
||||
static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
|
||||
static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
|
||||
|
|
|
|||
|
|
@ -193,12 +193,11 @@ protected:
|
|||
virtual void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const = 0;
|
||||
/// NodeEquals - Instantiations of the FoldingSet template implement
|
||||
/// this function to compare the given node with the given ID.
|
||||
virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID,
|
||||
virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
|
||||
FoldingSetNodeID &TempID) const=0;
|
||||
/// NodeEquals - Instantiations of the FoldingSet template implement
|
||||
/// ComputeNodeHash - Instantiations of the FoldingSet template implement
|
||||
/// this function to compute a hash value for the given node.
|
||||
virtual unsigned ComputeNodeHash(Node *N,
|
||||
FoldingSetNodeID &TempID) const = 0;
|
||||
virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0;
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -220,7 +219,7 @@ template<typename T> struct DefaultFoldingSetTrait {
|
|||
// to compute a temporary ID if necessary. The default implementation
|
||||
// just calls Profile and does a regular comparison. Implementations
|
||||
// can override this to provide more efficient implementations.
|
||||
static inline bool Equals(T &X, const FoldingSetNodeID &ID,
|
||||
static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
|
||||
FoldingSetNodeID &TempID);
|
||||
|
||||
// ComputeHash - Compute a hash value for X, using TempID to
|
||||
|
|
@ -249,7 +248,7 @@ struct DefaultContextualFoldingSetTrait {
|
|||
static void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
|
||||
X.Profile(ID, Context);
|
||||
}
|
||||
static inline bool Equals(T &X, const FoldingSetNodeID &ID,
|
||||
static inline bool Equals(T &X, const FoldingSetNodeID &ID, unsigned IDHash,
|
||||
FoldingSetNodeID &TempID, Ctx Context);
|
||||
static inline unsigned ComputeHash(T &X, FoldingSetNodeID &TempID,
|
||||
Ctx Context);
|
||||
|
|
@ -344,7 +343,7 @@ template<class T> class FoldingSetBucketIterator;
|
|||
template<typename T>
|
||||
inline bool
|
||||
DefaultFoldingSetTrait<T>::Equals(T &X, const FoldingSetNodeID &ID,
|
||||
FoldingSetNodeID &TempID) {
|
||||
unsigned IDHash, FoldingSetNodeID &TempID) {
|
||||
FoldingSetTrait<T>::Profile(X, TempID);
|
||||
return TempID == ID;
|
||||
}
|
||||
|
|
@ -358,6 +357,7 @@ template<typename T, typename Ctx>
|
|||
inline bool
|
||||
DefaultContextualFoldingSetTrait<T, Ctx>::Equals(T &X,
|
||||
const FoldingSetNodeID &ID,
|
||||
unsigned IDHash,
|
||||
FoldingSetNodeID &TempID,
|
||||
Ctx Context) {
|
||||
ContextualFoldingSetTrait<T, Ctx>::Profile(X, TempID, Context);
|
||||
|
|
@ -387,15 +387,14 @@ private:
|
|||
}
|
||||
/// NodeEquals - Instantiations may optionally provide a way to compare a
|
||||
/// node with a specified ID.
|
||||
virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID,
|
||||
virtual bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
|
||||
FoldingSetNodeID &TempID) const {
|
||||
T *TN = static_cast<T *>(N);
|
||||
return FoldingSetTrait<T>::Equals(*TN, ID, TempID);
|
||||
return FoldingSetTrait<T>::Equals(*TN, ID, IDHash, TempID);
|
||||
}
|
||||
/// NodeEquals - Instantiations may optionally provide a way to compute a
|
||||
/// ComputeNodeHash - Instantiations may optionally provide a way to compute a
|
||||
/// hash value directly from a node.
|
||||
virtual unsigned ComputeNodeHash(Node *N,
|
||||
FoldingSetNodeID &TempID) const {
|
||||
virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const {
|
||||
T *TN = static_cast<T *>(N);
|
||||
return FoldingSetTrait<T>::ComputeHash(*TN, TempID);
|
||||
}
|
||||
|
|
@ -465,10 +464,11 @@ private:
|
|||
ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context);
|
||||
}
|
||||
virtual bool NodeEquals(FoldingSetImpl::Node *N,
|
||||
const FoldingSetNodeID &ID,
|
||||
const FoldingSetNodeID &ID, unsigned IDHash,
|
||||
FoldingSetNodeID &TempID) const {
|
||||
T *TN = static_cast<T *>(N);
|
||||
return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, TempID, Context);
|
||||
return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID,
|
||||
Context);
|
||||
}
|
||||
virtual unsigned ComputeNodeHash(FoldingSetImpl::Node *N,
|
||||
FoldingSetNodeID &TempID) const {
|
||||
|
|
|
|||
|
|
@ -43,9 +43,12 @@ struct GraphTraits {
|
|||
// typedef ...iterator nodes_iterator;
|
||||
// static nodes_iterator nodes_begin(GraphType *G)
|
||||
// static nodes_iterator nodes_end (GraphType *G)
|
||||
//
|
||||
// nodes_iterator/begin/end - Allow iteration over all nodes in the graph
|
||||
|
||||
// static unsigned size (GraphType *G)
|
||||
// Return total number of nodes in the graph
|
||||
//
|
||||
|
||||
|
||||
// If anyone tries to use this class without having an appropriate
|
||||
// specialization, make an error. If you get this error, it's because you
|
||||
|
|
|
|||
770
contrib/llvm/include/llvm/ADT/Hashing.h
Normal file
770
contrib/llvm/include/llvm/ADT/Hashing.h
Normal file
|
|
@ -0,0 +1,770 @@
|
|||
//===-- llvm/ADT/Hashing.h - Utilities for hashing --------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the newly proposed standard C++ interfaces for hashing
|
||||
// arbitrary data and building hash functions for user-defined types. This
|
||||
// interface was originally proposed in N3333[1] and is currently under review
|
||||
// for inclusion in a future TR and/or standard.
|
||||
//
|
||||
// The primary interfaces provide are comprised of one type and three functions:
|
||||
//
|
||||
// -- 'hash_code' class is an opaque type representing the hash code for some
|
||||
// data. It is the intended product of hashing, and can be used to implement
|
||||
// hash tables, checksumming, and other common uses of hashes. It is not an
|
||||
// integer type (although it can be converted to one) because it is risky
|
||||
// to assume much about the internals of a hash_code. In particular, each
|
||||
// execution of the program has a high probability of producing a different
|
||||
// hash_code for a given input. Thus their values are not stable to save or
|
||||
// persist, and should only be used during the execution for the
|
||||
// construction of hashing datastructures.
|
||||
//
|
||||
// -- 'hash_value' is a function designed to be overloaded for each
|
||||
// user-defined type which wishes to be used within a hashing context. It
|
||||
// should be overloaded within the user-defined type's namespace and found
|
||||
// via ADL. Overloads for primitive types are provided by this library.
|
||||
//
|
||||
// -- 'hash_combine' and 'hash_combine_range' are functions designed to aid
|
||||
// programmers in easily and intuitively combining a set of data into
|
||||
// a single hash_code for their object. They should only logically be used
|
||||
// within the implementation of a 'hash_value' routine or similar context.
|
||||
//
|
||||
// Note that 'hash_combine_range' contains very special logic for hashing
|
||||
// a contiguous array of integers or pointers. This logic is *extremely* fast,
|
||||
// on a modern Intel "Gainestown" Xeon (Nehalem uarch) @2.2 GHz, these were
|
||||
// benchmarked at over 6.5 GiB/s for large keys, and <20 cycles/hash for keys
|
||||
// under 32-bytes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_HASHING_H
|
||||
#define LLVM_ADT_HASHING_H
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/SwapByteOrder.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
// Allow detecting C++11 feature availability when building with Clang without
|
||||
// breaking other compilers.
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief 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.
|
||||
/// While it wraps and exposes a numeric value, this value should not be
|
||||
/// trusted to be stable or predictable across processes or executions.
|
||||
///
|
||||
/// In order to obtain the hash_code for an object 'x':
|
||||
/// \code
|
||||
/// using llvm::hash_value;
|
||||
/// llvm::hash_code code = hash_value(x);
|
||||
/// \endcode
|
||||
///
|
||||
/// Also note that there are two numerical values which are reserved, and the
|
||||
/// implementation ensures will never be produced for real hash_codes. These
|
||||
/// can be used as sentinels within hashing data structures.
|
||||
class hash_code {
|
||||
size_t value;
|
||||
|
||||
public:
|
||||
/// \brief Default construct a hash_code.
|
||||
/// Note that this leaves the value uninitialized.
|
||||
hash_code() {}
|
||||
|
||||
/// \brief 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.
|
||||
/*explicit*/ operator size_t() const { return value; }
|
||||
|
||||
friend bool operator==(const hash_code &lhs, const hash_code &rhs) {
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
friend bool operator!=(const hash_code &lhs, const hash_code &rhs) {
|
||||
return lhs.value != rhs.value;
|
||||
}
|
||||
|
||||
/// \brief 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.
|
||||
///
|
||||
/// 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
|
||||
/// contrast to hash_combine which may produce different hash_codes for
|
||||
/// differing argument types even if they would implicit promote to a common
|
||||
/// type without changing the value.
|
||||
template <typename T>
|
||||
typename enable_if<is_integral_or_enum<T>, hash_code>::type hash_value(T value);
|
||||
|
||||
/// \brief 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.
|
||||
template <typename T, typename U>
|
||||
hash_code hash_value(const std::pair<T, U> &arg);
|
||||
|
||||
/// \brief 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.
|
||||
///
|
||||
/// 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
|
||||
/// attackable and to ensure that output which is intended to be stable does
|
||||
/// not rely on the particulars of the hash codes produced.
|
||||
///
|
||||
/// That said, there are use cases where it is important to be able to
|
||||
/// reproduce *exactly* a specific behavior. To that end, we provide a function
|
||||
/// which will forcibly set the seed to a fixed value. This must be done at the
|
||||
/// start of the program, before any hashes are computed. Also, it cannot be
|
||||
/// undone. This makes it thread-hostile and very hard to use outside of
|
||||
/// immediately on start of a simple program designed for reproducible
|
||||
/// behavior.
|
||||
void set_fixed_execution_hash_seed(size_t fixed_value);
|
||||
|
||||
|
||||
// All of the implementation details of actually computing the various hash
|
||||
// code values are held within this namespace. These routines are included in
|
||||
// the header file mainly to allow inlining and constant propagation.
|
||||
namespace hashing {
|
||||
namespace detail {
|
||||
|
||||
inline uint64_t fetch64(const char *p) {
|
||||
uint64_t result;
|
||||
memcpy(&result, p, sizeof(result));
|
||||
if (sys::isBigEndianHost())
|
||||
return sys::SwapByteOrder(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline uint32_t fetch32(const char *p) {
|
||||
uint32_t result;
|
||||
memcpy(&result, p, sizeof(result));
|
||||
if (sys::isBigEndianHost())
|
||||
return sys::SwapByteOrder(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Some primes between 2^63 and 2^64 for various uses.
|
||||
static const uint64_t k0 = 0xc3a5c85c97cb3127ULL;
|
||||
static const uint64_t k1 = 0xb492b66fbe98f273ULL;
|
||||
static const uint64_t k2 = 0x9ae16a3b2f90404fULL;
|
||||
static const uint64_t k3 = 0xc949d7c7509e6557ULL;
|
||||
|
||||
/// \brief 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) {
|
||||
// Avoid shifting by 64: doing so yields an undefined result.
|
||||
return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
|
||||
}
|
||||
|
||||
inline uint64_t shift_mix(uint64_t val) {
|
||||
return val ^ (val >> 47);
|
||||
}
|
||||
|
||||
inline uint64_t hash_16_bytes(uint64_t low, uint64_t high) {
|
||||
// Murmur-inspired hashing.
|
||||
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
|
||||
uint64_t a = (low ^ high) * kMul;
|
||||
a ^= (a >> 47);
|
||||
uint64_t b = (high ^ a) * kMul;
|
||||
b ^= (b >> 47);
|
||||
b *= kMul;
|
||||
return b;
|
||||
}
|
||||
|
||||
inline uint64_t hash_1to3_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint8_t a = s[0];
|
||||
uint8_t b = s[len >> 1];
|
||||
uint8_t c = s[len - 1];
|
||||
uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
|
||||
uint32_t z = len + (static_cast<uint32_t>(c) << 2);
|
||||
return shift_mix(y * k2 ^ z * k3 ^ seed) * k2;
|
||||
}
|
||||
|
||||
inline uint64_t hash_4to8_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint64_t a = fetch32(s);
|
||||
return hash_16_bytes(len + (a << 3), seed ^ fetch32(s + len - 4));
|
||||
}
|
||||
|
||||
inline uint64_t hash_9to16_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint64_t a = fetch64(s);
|
||||
uint64_t b = fetch64(s + len - 8);
|
||||
return hash_16_bytes(seed ^ a, rotate(b + len, len)) ^ b;
|
||||
}
|
||||
|
||||
inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint64_t a = fetch64(s) * k1;
|
||||
uint64_t b = fetch64(s + 8);
|
||||
uint64_t c = fetch64(s + len - 8) * k2;
|
||||
uint64_t d = fetch64(s + len - 16) * k0;
|
||||
return hash_16_bytes(rotate(a - b, 43) + rotate(c ^ seed, 30) + d,
|
||||
a + rotate(b ^ k3, 20) - c + len + seed);
|
||||
}
|
||||
|
||||
inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) {
|
||||
uint64_t z = fetch64(s + 24);
|
||||
uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0;
|
||||
uint64_t b = rotate(a + z, 52);
|
||||
uint64_t c = rotate(a, 37);
|
||||
a += fetch64(s + 8);
|
||||
c += rotate(a, 7);
|
||||
a += fetch64(s + 16);
|
||||
uint64_t vf = a + z;
|
||||
uint64_t vs = b + rotate(a, 31) + c;
|
||||
a = fetch64(s + 16) + fetch64(s + len - 32);
|
||||
z = fetch64(s + len - 8);
|
||||
b = rotate(a + z, 52);
|
||||
c = rotate(a, 37);
|
||||
a += fetch64(s + len - 24);
|
||||
c += rotate(a, 7);
|
||||
a += fetch64(s + len - 16);
|
||||
uint64_t wf = a + z;
|
||||
uint64_t ws = b + rotate(a, 31) + c;
|
||||
uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0);
|
||||
return shift_mix((seed ^ (r * k0)) + vs) * k2;
|
||||
}
|
||||
|
||||
inline uint64_t hash_short(const char *s, size_t length, uint64_t seed) {
|
||||
if (length >= 4 && length <= 8)
|
||||
return hash_4to8_bytes(s, length, seed);
|
||||
if (length > 8 && length <= 16)
|
||||
return hash_9to16_bytes(s, length, seed);
|
||||
if (length > 16 && length <= 32)
|
||||
return hash_17to32_bytes(s, length, seed);
|
||||
if (length > 32)
|
||||
return hash_33to64_bytes(s, length, seed);
|
||||
if (length != 0)
|
||||
return hash_1to3_bytes(s, length, seed);
|
||||
|
||||
return k2 ^ seed;
|
||||
}
|
||||
|
||||
/// \brief 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;
|
||||
uint64_t seed;
|
||||
|
||||
/// \brief 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) {
|
||||
hash_state state = {
|
||||
0, seed, hash_16_bytes(seed, k1), rotate(seed ^ k1, 49),
|
||||
seed * k1, shift_mix(seed), 0, seed };
|
||||
state.h6 = hash_16_bytes(state.h4, state.h5);
|
||||
state.mix(s);
|
||||
return state;
|
||||
}
|
||||
|
||||
/// \brief 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);
|
||||
uint64_t c = fetch64(s + 24);
|
||||
b = rotate(b + a + c, 21);
|
||||
uint64_t d = a;
|
||||
a += fetch64(s + 8) + fetch64(s + 16);
|
||||
b += rotate(a, 44) + d;
|
||||
a += c;
|
||||
}
|
||||
|
||||
/// \brief 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) {
|
||||
h0 = rotate(h0 + h1 + h3 + fetch64(s + 8), 37) * k1;
|
||||
h1 = rotate(h1 + h4 + fetch64(s + 48), 42) * k1;
|
||||
h0 ^= h6;
|
||||
h1 += h3 + fetch64(s + 40);
|
||||
h2 = rotate(h2 + h5, 33) * k1;
|
||||
h3 = h4 * k1;
|
||||
h4 = h0 + h5;
|
||||
mix_32_bytes(s, h3, h4);
|
||||
h5 = h2 + h6;
|
||||
h6 = h1 + fetch64(s + 16);
|
||||
mix_32_bytes(s + 32, h5, h6);
|
||||
std::swap(h2, h0);
|
||||
}
|
||||
|
||||
/// \brief 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,
|
||||
hash_16_bytes(h4, h6) + shift_mix(length) * k1 + h0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// \brief 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,
|
||||
/// set or read this variable.
|
||||
extern size_t fixed_seed_override;
|
||||
|
||||
inline size_t get_execution_seed() {
|
||||
// FIXME: This needs to be a per-execution seed. This is just a placeholder
|
||||
// implementation. Switching to a per-execution seed is likely to flush out
|
||||
// instability bugs and so will happen as its own commit.
|
||||
//
|
||||
// However, if there is a fixed seed override set the first time this is
|
||||
// called, return that instead of the per-execution seed.
|
||||
const uint64_t seed_prime = 0xff51afd7ed558ccdULL;
|
||||
static size_t seed = fixed_seed_override ? fixed_seed_override
|
||||
: (size_t)seed_prime;
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
/// \brief 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
|
||||
/// first be passed to hash_value, and the resulting hash_codes combined.
|
||||
//
|
||||
// FIXME: We want to replace is_integral_or_enum and is_pointer here with
|
||||
// a predicate which asserts that comparing the underlying storage of two
|
||||
// values of the type for equality is equivalent to comparing the two values
|
||||
// for equality. For all the platforms we care about, this holds for integers
|
||||
// and pointers, but there are platforms where it doesn't and we would like to
|
||||
// support user-defined types which happen to satisfy this property.
|
||||
template <typename T> struct is_hashable_data
|
||||
: integral_constant<bool, ((is_integral_or_enum<T>::value ||
|
||||
is_pointer<T>::value) &&
|
||||
64 % sizeof(T) == 0)> {};
|
||||
|
||||
// Special case std::pair to detect when both types are viable and when there
|
||||
// is no alignment-derived padding in the pair. This is a bit of a lie because
|
||||
// std::pair isn't truly POD, but it's close enough in all reasonable
|
||||
// implementations for our use case of hashing the underlying data.
|
||||
template <typename T, typename U> struct is_hashable_data<std::pair<T, U> >
|
||||
: integral_constant<bool, (is_hashable_data<T>::value &&
|
||||
is_hashable_data<U>::value &&
|
||||
(sizeof(T) + sizeof(U)) ==
|
||||
sizeof(std::pair<T, U>))> {};
|
||||
|
||||
/// \brief Helper to get the hashable data representation for a type.
|
||||
/// This variant is enabled when the type itself can be used.
|
||||
template <typename T>
|
||||
typename enable_if<is_hashable_data<T>, T>::type
|
||||
get_hashable_data(const T &value) {
|
||||
return value;
|
||||
}
|
||||
/// \brief 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>
|
||||
typename enable_if_c<!is_hashable_data<T>::value, size_t>::type
|
||||
get_hashable_data(const T &value) {
|
||||
using ::llvm::hash_value;
|
||||
return hash_value(value);
|
||||
}
|
||||
|
||||
/// \brief 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
|
||||
/// buffer, and if not immediately returns false. If there is space, it
|
||||
/// copies the underlying bytes of value into the buffer, advances the
|
||||
/// buffer_ptr past the copied bytes, and returns true.
|
||||
template <typename T>
|
||||
bool store_and_advance(char *&buffer_ptr, char *buffer_end, const T& value,
|
||||
size_t offset = 0) {
|
||||
size_t store_size = sizeof(value) - offset;
|
||||
if (buffer_ptr + store_size > buffer_end)
|
||||
return false;
|
||||
const char *value_data = reinterpret_cast<const char *>(&value);
|
||||
memcpy(buffer_ptr, value_data + offset, store_size);
|
||||
buffer_ptr += store_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \brief 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
|
||||
/// combining them, this (as an optimization) directly combines the integers.
|
||||
template <typename InputIteratorT>
|
||||
hash_code hash_combine_range_impl(InputIteratorT first, InputIteratorT last) {
|
||||
typedef typename std::iterator_traits<InputIteratorT>::value_type ValueT;
|
||||
const size_t seed = get_execution_seed();
|
||||
char buffer[64], *buffer_ptr = buffer;
|
||||
char *const buffer_end = buffer_ptr + array_lengthof(buffer);
|
||||
while (first != last && store_and_advance(buffer_ptr, buffer_end,
|
||||
get_hashable_data(*first)))
|
||||
++first;
|
||||
if (first == last)
|
||||
return hash_short(buffer, buffer_ptr - buffer, seed);
|
||||
assert(buffer_ptr == buffer_end);
|
||||
|
||||
hash_state state = state.create(buffer, seed);
|
||||
size_t length = 64;
|
||||
while (first != last) {
|
||||
// Fill up the buffer. We don't clear it, which re-mixes the last round
|
||||
// when only a partial 64-byte chunk is left.
|
||||
buffer_ptr = buffer;
|
||||
while (first != last && store_and_advance(buffer_ptr, buffer_end,
|
||||
get_hashable_data(*first)))
|
||||
++first;
|
||||
|
||||
// Rotate the buffer if we did a partial fill in order to simulate doing
|
||||
// a mix of the last 64-bytes. That is how the algorithm works when we
|
||||
// have a contiguous byte sequence, and we want to emulate that here.
|
||||
std::rotate(buffer, buffer_ptr, buffer_end);
|
||||
|
||||
// Mix this chunk into the current state.
|
||||
state.mix(buffer);
|
||||
length += buffer_ptr - buffer;
|
||||
};
|
||||
|
||||
return state.finalize(length);
|
||||
}
|
||||
|
||||
/// \brief 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
|
||||
/// a hash_code for each object and then combining them, this (as an
|
||||
/// optimization) directly combines the integers. Also, because the integers
|
||||
/// are stored in contiguous memory, this routine avoids copying each value
|
||||
/// and directly reads from the underlying memory.
|
||||
template <typename ValueT>
|
||||
typename enable_if<is_hashable_data<ValueT>, hash_code>::type
|
||||
hash_combine_range_impl(ValueT *first, ValueT *last) {
|
||||
const size_t seed = get_execution_seed();
|
||||
const char *s_begin = reinterpret_cast<const char *>(first);
|
||||
const char *s_end = reinterpret_cast<const char *>(last);
|
||||
const size_t length = std::distance(s_begin, s_end);
|
||||
if (length <= 64)
|
||||
return hash_short(s_begin, length, seed);
|
||||
|
||||
const char *s_aligned_end = s_begin + (length & ~63);
|
||||
hash_state state = state.create(s_begin, seed);
|
||||
s_begin += 64;
|
||||
while (s_begin != s_aligned_end) {
|
||||
state.mix(s_begin);
|
||||
s_begin += 64;
|
||||
}
|
||||
if (length & 63)
|
||||
state.mix(s_end - 64);
|
||||
|
||||
return state.finalize(length);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace hashing
|
||||
|
||||
|
||||
/// \brief 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
|
||||
/// and is significantly faster given pointers and types which can be hashed as
|
||||
/// a sequence of bytes.
|
||||
template <typename InputIteratorT>
|
||||
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last) {
|
||||
return ::llvm::hashing::detail::hash_combine_range_impl(first, last);
|
||||
}
|
||||
|
||||
|
||||
// Implementation details for hash_combine.
|
||||
namespace hashing {
|
||||
namespace detail {
|
||||
|
||||
/// \brief Helper class to manage the recursive combining of hash_combine
|
||||
/// arguments.
|
||||
///
|
||||
/// This class exists to manage the state and various calls involved in the
|
||||
/// recursive combining of arguments used in hash_combine. It is particularly
|
||||
/// useful at minimizing the code in the recursive calls to ease the pain
|
||||
/// caused by a lack of variadic functions.
|
||||
struct hash_combine_recursive_helper {
|
||||
char buffer[64];
|
||||
hash_state state;
|
||||
const size_t seed;
|
||||
|
||||
public:
|
||||
/// \brief 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.
|
||||
///
|
||||
/// 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
|
||||
/// hash_state, empties it, and then merges the new chunk in. This also
|
||||
/// handles cases where the data straddles the end of the buffer.
|
||||
template <typename T>
|
||||
char *combine_data(size_t &length, char *buffer_ptr, char *buffer_end, T data) {
|
||||
if (!store_and_advance(buffer_ptr, buffer_end, data)) {
|
||||
// Check for skew which prevents the buffer from being packed, and do
|
||||
// a partial store into the buffer to fill it. This is only a concern
|
||||
// with the variadic combine because that formation can have varying
|
||||
// argument types.
|
||||
size_t partial_store_size = buffer_end - buffer_ptr;
|
||||
memcpy(buffer_ptr, &data, partial_store_size);
|
||||
|
||||
// If the store fails, our buffer is full and ready to hash. We have to
|
||||
// either initialize the hash state (on the first full buffer) or mix
|
||||
// this buffer into the existing hash state. Length tracks the *hashed*
|
||||
// length, not the buffered length.
|
||||
if (length == 0) {
|
||||
state = state.create(buffer, seed);
|
||||
length = 64;
|
||||
} else {
|
||||
// Mix this chunk into the current state and bump length up by 64.
|
||||
state.mix(buffer);
|
||||
length += 64;
|
||||
}
|
||||
// Reset the buffer_ptr to the head of the buffer for the next chunk of
|
||||
// data.
|
||||
buffer_ptr = buffer;
|
||||
|
||||
// Try again to store into the buffer -- this cannot fail as we only
|
||||
// store types smaller than the buffer.
|
||||
if (!store_and_advance(buffer_ptr, buffer_end, data,
|
||||
partial_store_size))
|
||||
abort();
|
||||
}
|
||||
return buffer_ptr;
|
||||
}
|
||||
|
||||
#if defined(__has_feature) && __has_feature(__cxx_variadic_templates__)
|
||||
|
||||
/// \brief Recursive, variadic combining method.
|
||||
///
|
||||
/// This function recurses through each argument, combining that argument
|
||||
/// into a single hash.
|
||||
template <typename T, typename ...Ts>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T &arg, const Ts &...args) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg));
|
||||
|
||||
// Recurse to the next argument.
|
||||
return combine(length, buffer_ptr, buffer_end, args...);
|
||||
}
|
||||
|
||||
#else
|
||||
// Manually expanded recursive combining methods. See variadic above for
|
||||
// documentation.
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4, const T5 &arg5, const T6 &arg6) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4, const T5 &arg5) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end, arg2, arg3, arg4);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1, const T2 &arg2, const T3 &arg3) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end, arg2, arg3);
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1, const T2 &arg2) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end, arg2);
|
||||
}
|
||||
template <typename T1>
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end,
|
||||
const T1 &arg1) {
|
||||
buffer_ptr = combine_data(length, buffer_ptr, buffer_end, get_hashable_data(arg1));
|
||||
return combine(length, buffer_ptr, buffer_end);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// \brief 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
|
||||
/// constructs a hash_code.
|
||||
hash_code combine(size_t length, char *buffer_ptr, char *buffer_end) {
|
||||
// Check whether the entire set of values fit in the buffer. If so, we'll
|
||||
// use the optimized short hashing routine and skip state entirely.
|
||||
if (length == 0)
|
||||
return hash_short(buffer, buffer_ptr - buffer, seed);
|
||||
|
||||
// Mix the final buffer, rotating it if we did a partial fill in order to
|
||||
// simulate doing a mix of the last 64-bytes. That is how the algorithm
|
||||
// works when we have a contiguous byte sequence, and we want to emulate
|
||||
// that here.
|
||||
std::rotate(buffer, buffer_ptr, buffer_end);
|
||||
|
||||
// Mix this chunk into the current state.
|
||||
state.mix(buffer);
|
||||
length += buffer_ptr - buffer;
|
||||
|
||||
return state.finalize(length);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace hashing
|
||||
|
||||
|
||||
#if __has_feature(__cxx_variadic_templates__)
|
||||
|
||||
/// \brief 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
|
||||
/// attempts to call a \see hash_value overload (via ADL) for the type. For
|
||||
/// integer and pointer types it directly combines their data into the
|
||||
/// resulting hash_code.
|
||||
///
|
||||
/// The result is suitable for returning from a user's hash_value
|
||||
/// *implementation* for their user-defined type. Consumers of a type should
|
||||
/// *not* call this routine, they should instead call 'hash_value'.
|
||||
template <typename ...Ts> hash_code hash_combine(const Ts &...args) {
|
||||
// Recursively hash each argument using a helper class.
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64, args...);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// What follows are manually exploded overloads for each argument width. See
|
||||
// the above variadic definition for documentation and specification.
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6>
|
||||
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4, const T5 &arg5, const T6 &arg6) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64,
|
||||
arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4, const T5 &arg5) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64,
|
||||
arg1, arg2, arg3, arg4, arg5);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3,
|
||||
const T4 &arg4) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64,
|
||||
arg1, arg2, arg3, arg4);
|
||||
}
|
||||
template <typename T1, typename T2, typename T3>
|
||||
hash_code hash_combine(const T1 &arg1, const T2 &arg2, const T3 &arg3) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2, arg3);
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
hash_code hash_combine(const T1 &arg1, const T2 &arg2) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64, arg1, arg2);
|
||||
}
|
||||
template <typename T1>
|
||||
hash_code hash_combine(const T1 &arg1) {
|
||||
::llvm::hashing::detail::hash_combine_recursive_helper helper;
|
||||
return helper.combine(0, helper.buffer, helper.buffer + 64, arg1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Implementation details for implementatinos of hash_value overloads provided
|
||||
// here.
|
||||
namespace hashing {
|
||||
namespace detail {
|
||||
|
||||
/// \brief 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,
|
||||
/// "hash_value('4')" and "hash_value('0' + 4)" should be the same.
|
||||
inline hash_code hash_integer_value(uint64_t value) {
|
||||
// Similar to hash_4to8_bytes but using a seed instead of length.
|
||||
const uint64_t seed = get_execution_seed();
|
||||
const char *s = reinterpret_cast<const char *>(&value);
|
||||
const uint64_t a = fetch32(s);
|
||||
return hash_16_bytes(seed + (a << 3), fetch32(s + 4));
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace hashing
|
||||
|
||||
// Declared and documented above, but defined here so that any of the hashing
|
||||
// infrastructure is available.
|
||||
template <typename T>
|
||||
typename enable_if<is_integral_or_enum<T>, hash_code>::type
|
||||
hash_value(T value) {
|
||||
return ::llvm::hashing::detail::hash_integer_value(value);
|
||||
}
|
||||
|
||||
// Declared and documented above, but defined here so that any of the hashing
|
||||
// infrastructure is available.
|
||||
template <typename T> hash_code hash_value(const T *ptr) {
|
||||
return ::llvm::hashing::detail::hash_integer_value(
|
||||
reinterpret_cast<uintptr_t>(ptr));
|
||||
}
|
||||
|
||||
// Declared and documented above, but defined here so that any of the hashing
|
||||
// infrastructure is available.
|
||||
template <typename T, typename U>
|
||||
hash_code hash_value(const std::pair<T, U> &arg) {
|
||||
return hash_combine(arg.first, arg.second);
|
||||
}
|
||||
|
||||
// Declared and documented above, but defined here so that any of the hashing
|
||||
// infrastructure is available.
|
||||
template <typename T>
|
||||
hash_code hash_value(const std::basic_string<T> &arg) {
|
||||
return hash_combine_range(arg.begin(), arg.end());
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
|
@ -346,7 +347,7 @@ public:
|
|||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
factory->Cache[computeDigest()] = next;
|
||||
factory->Cache[factory->maskCacheIndex(computeDigest())] = next;
|
||||
}
|
||||
|
||||
// We need to clear the mutability bit in case we are
|
||||
|
|
@ -428,6 +429,11 @@ protected:
|
|||
TreeTy* getRight(TreeTy* T) const { return T->getRight(); }
|
||||
value_type_ref getValue(TreeTy* T) const { return T->value; }
|
||||
|
||||
// Make sure the index is not the Tombstone or Entry key of the DenseMap.
|
||||
static inline unsigned maskCacheIndex(unsigned I) {
|
||||
return (I & ~0x02);
|
||||
}
|
||||
|
||||
unsigned incrementHeight(TreeTy* L, TreeTy* R) const {
|
||||
unsigned hl = getHeight(L);
|
||||
unsigned hr = getHeight(R);
|
||||
|
|
@ -610,7 +616,7 @@ public:
|
|||
// Search the hashtable for another tree with the same digest, and
|
||||
// if find a collision compare those trees by their contents.
|
||||
unsigned digest = TNew->computeDigest();
|
||||
TreeTy *&entry = Cache[digest];
|
||||
TreeTy *&entry = Cache[maskCacheIndex(digest)];
|
||||
do {
|
||||
if (!entry)
|
||||
break;
|
||||
|
|
@ -686,7 +692,7 @@ public:
|
|||
stack.back() |= VisitedRight;
|
||||
break;
|
||||
default:
|
||||
assert(false && "Unreachable.");
|
||||
llvm_unreachable("Unreachable.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -722,7 +728,7 @@ public:
|
|||
skipToParent();
|
||||
break;
|
||||
default:
|
||||
assert(false && "Unreachable.");
|
||||
llvm_unreachable("Unreachable.");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
@ -747,7 +753,7 @@ public:
|
|||
stack.push_back(reinterpret_cast<uintptr_t>(R) | VisitedRight);
|
||||
break;
|
||||
default:
|
||||
assert(false && "Unreachable.");
|
||||
llvm_unreachable("Unreachable.");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -739,7 +739,7 @@ public:
|
|||
// A Path is used by iterators to represent a position in a B+-tree, and the
|
||||
// path to get there from the root.
|
||||
//
|
||||
// The Path class also constains the tree navigation code that doesn't have to
|
||||
// The Path class also contains the tree navigation code that doesn't have to
|
||||
// be templatized.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -1977,7 +1977,7 @@ iterator::overflow(unsigned Level) {
|
|||
CurSize[Nodes] = CurSize[NewNode];
|
||||
Node[Nodes] = Node[NewNode];
|
||||
CurSize[NewNode] = 0;
|
||||
Node[NewNode] = this->map->newNode<NodeT>();
|
||||
Node[NewNode] = this->map->template newNode<NodeT>();
|
||||
++Nodes;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ namespace llvm {
|
|||
|
||||
public:
|
||||
RefCountedBase() : ref_cnt(0) {}
|
||||
RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
|
||||
|
||||
void Retain() const { ++ref_cnt; }
|
||||
void Release() const {
|
||||
|
|
@ -64,9 +65,12 @@ namespace llvm {
|
|||
//===----------------------------------------------------------------------===//
|
||||
class RefCountedBaseVPTR {
|
||||
mutable unsigned ref_cnt;
|
||||
virtual void anchor();
|
||||
|
||||
protected:
|
||||
RefCountedBaseVPTR() : ref_cnt(0) {}
|
||||
RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
|
||||
|
||||
virtual ~RefCountedBaseVPTR() {}
|
||||
|
||||
void Retain() const { ++ref_cnt; }
|
||||
|
|
@ -76,9 +80,15 @@ namespace llvm {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
friend class IntrusiveRefCntPtr;
|
||||
friend struct IntrusiveRefCntPtrInfo;
|
||||
};
|
||||
|
||||
|
||||
template <typename T> struct IntrusiveRefCntPtrInfo {
|
||||
static void retain(T *obj) { obj->Retain(); }
|
||||
static void release(T *obj) { obj->Release(); }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
|
||||
/// that assumes the wrapped object has a reference count associated
|
||||
|
|
@ -105,7 +115,7 @@ namespace llvm {
|
|||
|
||||
explicit IntrusiveRefCntPtr() : Obj(0) {}
|
||||
|
||||
explicit IntrusiveRefCntPtr(T* obj) : Obj(obj) {
|
||||
IntrusiveRefCntPtr(T* obj) : Obj(obj) {
|
||||
retain();
|
||||
}
|
||||
|
||||
|
|
@ -153,14 +163,19 @@ namespace llvm {
|
|||
other.Obj = Obj;
|
||||
Obj = tmp;
|
||||
}
|
||||
|
||||
|
||||
void reset() {
|
||||
release();
|
||||
Obj = 0;
|
||||
}
|
||||
|
||||
void resetWithoutRelease() {
|
||||
Obj = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void retain() { if (Obj) Obj->Retain(); }
|
||||
void release() { if (Obj) Obj->Release(); }
|
||||
void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
|
||||
void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
|
||||
|
||||
void replace(T* S) {
|
||||
this_type(S).swap(*this);
|
||||
|
|
|
|||
|
|
@ -92,10 +92,14 @@ public:
|
|||
}
|
||||
|
||||
PointerTy const *getAddrOfPointer() const {
|
||||
return const_cast<PointerIntPair *>(this)->getAddrOfPointer();
|
||||
}
|
||||
|
||||
PointerTy *getAddrOfPointer() {
|
||||
assert(Value == reinterpret_cast<intptr_t>(getPointer()) &&
|
||||
"Can only return the address if IntBits is cleared and "
|
||||
"PtrTraits doesn't change the pointer");
|
||||
return reinterpret_cast<PointerTy const *>(&Value);
|
||||
return reinterpret_cast<PointerTy *>(&Value);
|
||||
}
|
||||
|
||||
void *getOpaqueValue() const { return reinterpret_cast<void*>(Value); }
|
||||
|
|
|
|||
|
|
@ -142,16 +142,19 @@ namespace llvm {
|
|||
return T();
|
||||
}
|
||||
|
||||
/// \brief If the union is set to the first pointer type we can get an
|
||||
/// address pointing to it.
|
||||
template <typename T>
|
||||
PT1 const *getAddrOf() const {
|
||||
/// \brief If the union is set to the first pointer type get an address
|
||||
/// pointing to it.
|
||||
PT1 const *getAddrOfPtr1() const {
|
||||
return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
|
||||
}
|
||||
|
||||
/// \brief If the union is set to the first pointer type get an address
|
||||
/// pointing to it.
|
||||
PT1 *getAddrOfPtr1() {
|
||||
assert(is<PT1>() && "Val is not the first pointer");
|
||||
assert(get<PT1>() == Val.getPointer() &&
|
||||
"Can't get the address because PointerLikeTypeTraits changes the ptr");
|
||||
T const *can_only_get_address_of_first_pointer_type
|
||||
= reinterpret_cast<PT1 const *>(Val.getAddrOfPointer());
|
||||
return can_only_get_address_of_first_pointer_type;
|
||||
return (PT1 *)Val.getAddrOfPointer();
|
||||
}
|
||||
|
||||
/// Assignment operators - Allow assigning into this union from either
|
||||
|
|
@ -263,7 +266,7 @@ namespace llvm {
|
|||
::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
|
||||
::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
|
||||
>::Return Ty;
|
||||
return Ty(Val).is<T>();
|
||||
return Ty(Val).template is<T>();
|
||||
}
|
||||
|
||||
/// get<T>() - Return the value of the specified pointer type. If the
|
||||
|
|
@ -276,7 +279,7 @@ namespace llvm {
|
|||
::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
|
||||
::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
|
||||
>::Return Ty;
|
||||
return Ty(Val).get<T>();
|
||||
return Ty(Val).template get<T>();
|
||||
}
|
||||
|
||||
/// dyn_cast<T>() - If the current value is of the specified pointer type,
|
||||
|
|
|
|||
|
|
@ -144,6 +144,12 @@ public:
|
|||
set_.erase(back());
|
||||
vector_.pop_back();
|
||||
}
|
||||
|
||||
T pop_back_val() {
|
||||
T Ret = back();
|
||||
pop_back();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
bool operator==(const SetVector &that) const {
|
||||
return vector_ == that.vector_;
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ public:
|
|||
return CountPopulation_32(Bits);
|
||||
if (sizeof(uintptr_t) * CHAR_BIT == 64)
|
||||
return CountPopulation_64(Bits);
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
return getPointer()->count();
|
||||
}
|
||||
|
|
@ -212,7 +212,7 @@ public:
|
|||
return CountTrailingZeros_32(Bits);
|
||||
if (sizeof(uintptr_t) * CHAR_BIT == 64)
|
||||
return CountTrailingZeros_64(Bits);
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
return getPointer()->find_first();
|
||||
}
|
||||
|
|
@ -230,7 +230,7 @@ public:
|
|||
return CountTrailingZeros_32(Bits);
|
||||
if (sizeof(uintptr_t) * CHAR_BIT == 64)
|
||||
return CountTrailingZeros_64(Bits);
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
return getPointer()->find_next(Prev);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,6 +137,10 @@ private:
|
|||
|
||||
void operator=(const SmallPtrSetImpl &RHS); // DO NOT IMPLEMENT.
|
||||
protected:
|
||||
/// swap - Swaps the elements of two sets.
|
||||
/// Note: This method assumes that both sets have the same small size.
|
||||
void swap(SmallPtrSetImpl &RHS);
|
||||
|
||||
void CopyFrom(const SmallPtrSetImpl &RHS);
|
||||
};
|
||||
|
||||
|
|
@ -287,8 +291,20 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
/// swap - Swaps the elements of two sets.
|
||||
void swap(SmallPtrSet<PtrType, SmallSize> &RHS) {
|
||||
SmallPtrSetImpl::swap(RHS);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
/// Implement std::swap in terms of SmallPtrSet swap.
|
||||
template<class T, unsigned N>
|
||||
inline void swap(llvm::SmallPtrSet<T, N> &LHS, llvm::SmallPtrSet<T, N> &RHS) {
|
||||
LHS.swap(RHS);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@ namespace llvm {
|
|||
///
|
||||
/// Note that this set does not provide a way to iterate over members in the
|
||||
/// set.
|
||||
template <typename T, unsigned N>
|
||||
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
|
||||
/// reach its 'large' stage) to avoid calling the default ctors of elements
|
||||
/// we will never use.
|
||||
SmallVector<T, N> Vector;
|
||||
std::set<T> Set;
|
||||
std::set<T, C> Set;
|
||||
typedef typename SmallVector<T, N>::const_iterator VIterator;
|
||||
typedef typename SmallVector<T, N>::iterator mutable_iterator;
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -24,21 +24,244 @@ namespace llvm {
|
|||
template<unsigned InternalLen>
|
||||
class SmallString : public SmallVector<char, InternalLen> {
|
||||
public:
|
||||
// Default ctor - Initialize to empty.
|
||||
/// Default ctor - Initialize to empty.
|
||||
SmallString() {}
|
||||
|
||||
// Initialize from a StringRef.
|
||||
/// Initialize from a StringRef.
|
||||
SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {}
|
||||
|
||||
// Initialize with a range.
|
||||
/// Initialize with a range.
|
||||
template<typename ItTy>
|
||||
SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {}
|
||||
|
||||
// Copy ctor.
|
||||
/// Copy ctor.
|
||||
SmallString(const SmallString &RHS) : SmallVector<char, InternalLen>(RHS) {}
|
||||
|
||||
// Note that in order to add new overloads for append & assign, we have to
|
||||
// duplicate the inherited versions so as not to inadvertently hide them.
|
||||
|
||||
/// @}
|
||||
/// @name String Assignment
|
||||
/// @{
|
||||
|
||||
/// Assign from a repeated element
|
||||
void assign(unsigned NumElts, char Elt) {
|
||||
this->SmallVectorImpl<char>::assign(NumElts, Elt);
|
||||
}
|
||||
|
||||
/// Assign from an iterator pair
|
||||
template<typename in_iter>
|
||||
void assign(in_iter S, in_iter E) {
|
||||
this->clear();
|
||||
SmallVectorImpl<char>::append(S, E);
|
||||
}
|
||||
|
||||
/// Assign from a StringRef
|
||||
void assign(StringRef RHS) {
|
||||
this->clear();
|
||||
SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
/// Assign from a SmallVector
|
||||
void assign(const SmallVectorImpl<char> &RHS) {
|
||||
this->clear();
|
||||
SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Concatenation
|
||||
/// @{
|
||||
|
||||
/// Append from an iterator pair
|
||||
template<typename in_iter>
|
||||
void append(in_iter S, in_iter E) {
|
||||
SmallVectorImpl<char>::append(S, E);
|
||||
}
|
||||
|
||||
/// Append from a StringRef
|
||||
void append(StringRef RHS) {
|
||||
SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
/// Append from a SmallVector
|
||||
void append(const SmallVectorImpl<char> &RHS) {
|
||||
SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Comparison
|
||||
/// @{
|
||||
|
||||
/// equals - Check for string equality, this is more efficient than
|
||||
/// compare() when the relative ordering of inequal strings isn't needed.
|
||||
bool equals(StringRef RHS) const {
|
||||
return str().equals(RHS);
|
||||
}
|
||||
|
||||
/// equals_lower - Check for string equality, ignoring case.
|
||||
bool equals_lower(StringRef RHS) const {
|
||||
return str().equals_lower(RHS);
|
||||
}
|
||||
|
||||
/// compare - Compare two strings; the result is -1, 0, or 1 if this string
|
||||
/// is lexicographically less than, equal to, or greater than the \arg RHS.
|
||||
int compare(StringRef RHS) const {
|
||||
return str().compare(RHS);
|
||||
}
|
||||
|
||||
/// compare_lower - Compare two strings, ignoring case.
|
||||
int compare_lower(StringRef RHS) const {
|
||||
return str().compare_lower(RHS);
|
||||
}
|
||||
|
||||
/// compare_numeric - Compare two strings, treating sequences of digits as
|
||||
/// numbers.
|
||||
int compare_numeric(StringRef RHS) const {
|
||||
return str().compare_numeric(RHS);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Predicates
|
||||
/// @{
|
||||
|
||||
/// startswith - Check if this string starts with the given \arg Prefix.
|
||||
bool startswith(StringRef Prefix) const {
|
||||
return str().startswith(Prefix);
|
||||
}
|
||||
|
||||
/// endswith - Check if this string ends with the given \arg Suffix.
|
||||
bool endswith(StringRef Suffix) const {
|
||||
return str().endswith(Suffix);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name String Searching
|
||||
/// @{
|
||||
|
||||
/// find - Search for the first character \arg C in the string.
|
||||
///
|
||||
/// \return - The index of the first occurrence of \arg C, or npos if not
|
||||
/// found.
|
||||
size_t find(char C, size_t From = 0) const {
|
||||
return str().find(C, From);
|
||||
}
|
||||
|
||||
/// find - Search for the first string \arg Str in the string.
|
||||
///
|
||||
/// \return - The index of the first occurrence of \arg Str, or npos if not
|
||||
/// found.
|
||||
size_t find(StringRef Str, size_t From = 0) const {
|
||||
return str().find(Str, From);
|
||||
}
|
||||
|
||||
/// rfind - Search for the last character \arg C in the string.
|
||||
///
|
||||
/// \return - The index of the last occurrence of \arg C, or npos if not
|
||||
/// found.
|
||||
size_t rfind(char C, size_t From = StringRef::npos) const {
|
||||
return str().rfind(C, From);
|
||||
}
|
||||
|
||||
/// rfind - Search for the last string \arg Str in the string.
|
||||
///
|
||||
/// \return - The index of the last occurrence of \arg Str, or npos if not
|
||||
/// found.
|
||||
size_t rfind(StringRef Str) const {
|
||||
return str().rfind(Str);
|
||||
}
|
||||
|
||||
/// find_first_of - Find the first character in the string that is \arg C,
|
||||
/// or npos if not found. Same as find.
|
||||
size_t find_first_of(char C, size_t From = 0) const {
|
||||
return str().find_first_of(C, From);
|
||||
}
|
||||
|
||||
/// find_first_of - Find the first character in the string that is in \arg
|
||||
/// Chars, or npos if not found.
|
||||
///
|
||||
/// Note: O(size() + Chars.size())
|
||||
size_t find_first_of(StringRef Chars, size_t From = 0) const {
|
||||
return str().find_first_of(Chars, From);
|
||||
}
|
||||
|
||||
/// find_first_not_of - Find the first character in the string that is not
|
||||
/// \arg C or npos if not found.
|
||||
size_t find_first_not_of(char C, size_t From = 0) const {
|
||||
return str().find_first_not_of(C, From);
|
||||
}
|
||||
|
||||
/// find_first_not_of - Find the first character in the string that is not
|
||||
/// in the string \arg Chars, or npos if not found.
|
||||
///
|
||||
/// Note: O(size() + Chars.size())
|
||||
size_t find_first_not_of(StringRef Chars, size_t From = 0) const {
|
||||
return str().find_first_not_of(Chars, From);
|
||||
}
|
||||
|
||||
/// find_last_of - Find the last character in the string that is \arg C, or
|
||||
/// npos if not found.
|
||||
size_t find_last_of(char C, size_t From = StringRef::npos) const {
|
||||
return str().find_last_of(C, From);
|
||||
}
|
||||
|
||||
/// find_last_of - Find the last character in the string that is in \arg C,
|
||||
/// or npos if not found.
|
||||
///
|
||||
/// Note: O(size() + Chars.size())
|
||||
size_t find_last_of(
|
||||
StringRef Chars, size_t From = StringRef::npos) const {
|
||||
return str().find_last_of(Chars, From);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Helpful Algorithms
|
||||
/// @{
|
||||
|
||||
/// count - Return the number of occurrences of \arg C in the string.
|
||||
size_t count(char C) const {
|
||||
return str().count(C);
|
||||
}
|
||||
|
||||
/// count - Return the number of non-overlapped occurrences of \arg Str in
|
||||
/// the string.
|
||||
size_t count(StringRef Str) const {
|
||||
return str().count(Str);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Substring Operations
|
||||
/// @{
|
||||
|
||||
/// substr - Return a reference to the substring from [Start, Start + N).
|
||||
///
|
||||
/// \param Start - The index of the starting character in the substring; if
|
||||
/// the index is npos or greater than the length of the string then the
|
||||
/// empty substring will be returned.
|
||||
///
|
||||
/// \param N - The number of characters to included in the substring. If N
|
||||
/// exceeds the number of characters remaining in the string, the string
|
||||
/// suffix (starting with \arg Start) will be returned.
|
||||
StringRef substr(size_t Start, size_t N = StringRef::npos) const {
|
||||
return str().substr(Start, N);
|
||||
}
|
||||
|
||||
/// slice - Return a reference to the substring from [Start, End).
|
||||
///
|
||||
/// \param Start - The index of the starting character in the substring; if
|
||||
/// the index is npos or greater than the length of the string then the
|
||||
/// empty substring will be returned.
|
||||
///
|
||||
/// \param End - The index following the last character to include in the
|
||||
/// substring. If this is npos, or less than \arg Start, or exceeds the
|
||||
/// number of characters remaining in the string, the string suffix
|
||||
/// (starting with \arg Start) will be returned.
|
||||
StringRef slice(size_t Start, size_t End) const {
|
||||
return str().slice(Start, End);
|
||||
}
|
||||
|
||||
// Extra methods.
|
||||
|
||||
/// Explicit conversion to StringRef
|
||||
StringRef str() const { return StringRef(this->begin(), this->size()); }
|
||||
|
||||
// TODO: Make this const, if it's safe...
|
||||
|
|
@ -48,7 +271,7 @@ public:
|
|||
return this->data();
|
||||
}
|
||||
|
||||
// Implicit conversion to StringRef.
|
||||
/// Implicit conversion to StringRef.
|
||||
operator StringRef() const { return str(); }
|
||||
|
||||
// Extra operators.
|
||||
|
|
|
|||
|
|
@ -23,30 +23,6 @@
|
|||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
namespace std {
|
||||
#if _MSC_VER <= 1310
|
||||
// Work around flawed VC++ implementation of std::uninitialized_copy. Define
|
||||
// additional overloads so that elements with pointer types are recognized as
|
||||
// scalars and not objects, causing bizarre type conversion errors.
|
||||
template<class T1, class T2>
|
||||
inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) {
|
||||
_Scalar_ptr_iterator_tag _Cat;
|
||||
return _Cat;
|
||||
}
|
||||
|
||||
template<class T1, class T2>
|
||||
inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) {
|
||||
_Scalar_ptr_iterator_tag _Cat;
|
||||
return _Cat;
|
||||
}
|
||||
#else
|
||||
// FIXME: It is not clear if the problem is fixed in VS 2005. What is clear
|
||||
// is that the above hack won't work if it wasn't fixed.
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// SmallVectorBase - This is all the non-templated stuff common to all
|
||||
|
|
@ -100,10 +76,10 @@ public:
|
|||
template <typename T>
|
||||
class SmallVectorTemplateCommon : public SmallVectorBase {
|
||||
protected:
|
||||
void setEnd(T *P) { this->EndX = P; }
|
||||
public:
|
||||
SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(Size) {}
|
||||
|
||||
void setEnd(T *P) { this->EndX = P; }
|
||||
public:
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T value_type;
|
||||
|
|
@ -174,7 +150,7 @@ public:
|
|||
/// implementations that are designed to work with non-POD-like T's.
|
||||
template <typename T, bool isPodLike>
|
||||
class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
|
||||
public:
|
||||
protected:
|
||||
SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
|
||||
|
||||
static void destroy_range(T *S, T *E) {
|
||||
|
|
@ -194,6 +170,23 @@ public:
|
|||
/// grow - 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);
|
||||
|
||||
public:
|
||||
void push_back(const T &Elt) {
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
new (this->end()) T(Elt);
|
||||
this->setEnd(this->end()+1);
|
||||
return;
|
||||
}
|
||||
this->grow();
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
this->setEnd(this->end()-1);
|
||||
this->end()->~T();
|
||||
}
|
||||
};
|
||||
|
||||
// Define this out-of-line to dissuade the C++ compiler from inlining it.
|
||||
|
|
@ -226,7 +219,7 @@ void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
|
|||
/// implementations that are designed to work with POD-like T's.
|
||||
template <typename T>
|
||||
class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
|
||||
public:
|
||||
protected:
|
||||
SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
|
||||
|
||||
// No need to do a destroy loop for POD's.
|
||||
|
|
@ -255,6 +248,21 @@ public:
|
|||
void grow(size_t MinSize = 0) {
|
||||
this->grow_pod(MinSize*sizeof(T), sizeof(T));
|
||||
}
|
||||
public:
|
||||
void push_back(const T &Elt) {
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
*this->end() = Elt;
|
||||
this->setEnd(this->end()+1);
|
||||
return;
|
||||
}
|
||||
this->grow();
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
this->setEnd(this->end()-1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -270,11 +278,13 @@ public:
|
|||
typedef typename SuperClass::iterator iterator;
|
||||
typedef typename SuperClass::size_type size_type;
|
||||
|
||||
protected:
|
||||
// Default ctor - Initialize to empty.
|
||||
explicit SmallVectorImpl(unsigned N)
|
||||
: SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) {
|
||||
}
|
||||
|
||||
public:
|
||||
~SmallVectorImpl() {
|
||||
// Destroy the constructed elements in the vector.
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
|
|
@ -297,7 +307,7 @@ public:
|
|||
} else if (N > this->size()) {
|
||||
if (this->capacity() < N)
|
||||
this->grow(N);
|
||||
this->construct_range(this->end(), this->begin()+N, T());
|
||||
std::uninitialized_fill(this->end(), this->begin()+N, T());
|
||||
this->setEnd(this->begin()+N);
|
||||
}
|
||||
}
|
||||
|
|
@ -309,7 +319,7 @@ public:
|
|||
} else if (N > this->size()) {
|
||||
if (this->capacity() < N)
|
||||
this->grow(N);
|
||||
construct_range(this->end(), this->begin()+N, NV);
|
||||
std::uninitialized_fill(this->end(), this->begin()+N, NV);
|
||||
this->setEnd(this->begin()+N);
|
||||
}
|
||||
}
|
||||
|
|
@ -319,25 +329,9 @@ public:
|
|||
this->grow(N);
|
||||
}
|
||||
|
||||
void push_back(const T &Elt) {
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
new (this->end()) T(Elt);
|
||||
this->setEnd(this->end()+1);
|
||||
return;
|
||||
}
|
||||
this->grow();
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
this->setEnd(this->end()-1);
|
||||
this->end()->~T();
|
||||
}
|
||||
|
||||
T pop_back_val() {
|
||||
T Result = this->back();
|
||||
pop_back();
|
||||
this->pop_back();
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
|
@ -376,7 +370,7 @@ public:
|
|||
if (this->capacity() < NumElts)
|
||||
this->grow(NumElts);
|
||||
this->setEnd(this->begin()+NumElts);
|
||||
construct_range(this->begin(), this->end(), Elt);
|
||||
std::uninitialized_fill(this->begin(), this->end(), Elt);
|
||||
}
|
||||
|
||||
iterator erase(iterator I) {
|
||||
|
|
@ -384,7 +378,7 @@ public:
|
|||
// Shift all elts down one.
|
||||
std::copy(I+1, this->end(), I);
|
||||
// Drop the last elt.
|
||||
pop_back();
|
||||
this->pop_back();
|
||||
return(N);
|
||||
}
|
||||
|
||||
|
|
@ -400,7 +394,7 @@ public:
|
|||
|
||||
iterator insert(iterator I, const T &Elt) {
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
push_back(Elt);
|
||||
this->push_back(Elt);
|
||||
return this->end()-1;
|
||||
}
|
||||
|
||||
|
|
@ -554,12 +548,6 @@ public:
|
|||
assert(N <= this->capacity());
|
||||
this->setEnd(this->begin() + N);
|
||||
}
|
||||
|
||||
private:
|
||||
static void construct_range(T *S, T *E, const T &Elt) {
|
||||
for (; S != E; ++S)
|
||||
new (S) T(Elt);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -686,9 +674,7 @@ public:
|
|||
|
||||
explicit SmallVector(unsigned Size, const T &Value = T())
|
||||
: SmallVectorImpl<T>(NumTsAvailable) {
|
||||
this->reserve(Size);
|
||||
while (Size--)
|
||||
this->push_back(Value);
|
||||
this->assign(Size, Value);
|
||||
}
|
||||
|
||||
template<typename ItTy>
|
||||
|
|
@ -718,9 +704,7 @@ public:
|
|||
|
||||
explicit SmallVector(unsigned Size, const T &Value = T())
|
||||
: SmallVectorImpl<T>(0) {
|
||||
this->reserve(Size);
|
||||
while (Size--)
|
||||
this->push_back(Value);
|
||||
this->assign(Size, Value);
|
||||
}
|
||||
|
||||
template<typename ItTy>
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@
|
|||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cstring>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ public:
|
|||
else if (sizeof(BitWord) == 8)
|
||||
NumBits += CountPopulation_64(Bits[i]);
|
||||
else
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
return NumBits;
|
||||
}
|
||||
|
||||
|
|
@ -138,13 +138,11 @@ public:
|
|||
if (Bits[i] != 0) {
|
||||
if (sizeof(BitWord) == 4)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]);
|
||||
else if (sizeof(BitWord) == 8)
|
||||
if (sizeof(BitWord) == 8)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
|
||||
else
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
assert(0 && "Illegal empty element");
|
||||
return 0; // Not reached
|
||||
llvm_unreachable("Illegal empty element");
|
||||
}
|
||||
|
||||
/// find_next - Returns the index of the next set bit starting from the
|
||||
|
|
@ -165,10 +163,9 @@ public:
|
|||
if (Copy != 0) {
|
||||
if (sizeof(BitWord) == 4)
|
||||
return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy);
|
||||
else if (sizeof(BitWord) == 8)
|
||||
if (sizeof(BitWord) == 8)
|
||||
return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy);
|
||||
else
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
|
||||
// Check subsequent words.
|
||||
|
|
@ -176,10 +173,9 @@ public:
|
|||
if (Bits[i] != 0) {
|
||||
if (sizeof(BitWord) == 4)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]);
|
||||
else if (sizeof(BitWord) == 8)
|
||||
if (sizeof(BitWord) == 8)
|
||||
return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]);
|
||||
else
|
||||
assert(0 && "Unsupported!");
|
||||
llvm_unreachable("Unsupported!");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -264,15 +260,6 @@ public:
|
|||
}
|
||||
BecameZero = allzero;
|
||||
}
|
||||
|
||||
// Get a hash value for this element;
|
||||
uint64_t getHashValue() const {
|
||||
uint64_t HashVal = 0;
|
||||
for (unsigned i = 0; i < BITWORDS_PER_ELEMENT; ++i) {
|
||||
HashVal ^= Bits[i];
|
||||
}
|
||||
return HashVal;
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned ElementSize = 128>
|
||||
|
|
@ -813,18 +800,6 @@ public:
|
|||
iterator end() const {
|
||||
return iterator(this, true);
|
||||
}
|
||||
|
||||
// Get a hash value for this bitmap.
|
||||
uint64_t getHashValue() const {
|
||||
uint64_t HashVal = 0;
|
||||
for (ElementListConstIter Iter = Elements.begin();
|
||||
Iter != Elements.end();
|
||||
++Iter) {
|
||||
HashVal ^= Iter->index();
|
||||
HashVal ^= Iter->getHashValue();
|
||||
}
|
||||
return HashVal;
|
||||
}
|
||||
};
|
||||
|
||||
// Convenience functions to allow Or and And without dereferencing in the user
|
||||
|
|
|
|||
268
contrib/llvm/include/llvm/ADT/SparseSet.h
Normal file
268
contrib/llvm/include/llvm/ADT/SparseSet.h
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
//===--- llvm/ADT/SparseSet.h - Sparse set ----------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the SparseSet class derived from the version described in
|
||||
// Briggs, Torczon, "An efficient representation for sparse sets", ACM Letters
|
||||
// on Programming Languages and Systems, Volume 2 Issue 1-4, March-Dec. 1993.
|
||||
//
|
||||
// A sparse set holds a small number of objects identified by integer keys from
|
||||
// a moderately sized universe. The sparse set uses more memory than other
|
||||
// containers in order to provide faster operations.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_SPARSESET_H
|
||||
#define LLVM_ADT_SPARSESET_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <limits>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// SparseSetFunctor - Objects in a SparseSet are identified by small integer
|
||||
/// keys. A functor object is used to compute the key of an object. The
|
||||
/// functor's operator() must return an unsigned smaller than the universe.
|
||||
///
|
||||
/// The default functor implementation forwards to a getSparseSetKey() method
|
||||
/// on the object. It is intended for sparse sets holding ad-hoc structs.
|
||||
///
|
||||
template<typename ValueT>
|
||||
struct SparseSetFunctor {
|
||||
unsigned operator()(const ValueT &Val) {
|
||||
return Val.getSparseSetKey();
|
||||
}
|
||||
};
|
||||
|
||||
/// SparseSetFunctor<unsigned> - Provide a trivial identity functor for
|
||||
/// SparseSet<unsigned>.
|
||||
///
|
||||
template<> struct SparseSetFunctor<unsigned> {
|
||||
unsigned operator()(unsigned Val) { return Val; }
|
||||
};
|
||||
|
||||
/// SparseSet - Fast set implementation for objects that can be identified by
|
||||
/// small unsigned keys.
|
||||
///
|
||||
/// SparseSet allocates memory proportional to the size of the key universe, so
|
||||
/// it is not recommended for building composite data structures. It is useful
|
||||
/// for algorithms that require a single set with fast operations.
|
||||
///
|
||||
/// Compared to DenseSet and DenseMap, SparseSet provides constant-time fast
|
||||
/// clear() and iteration as fast as a vector. The find(), insert(), and
|
||||
/// erase() operations are all constant time, and typically faster than a hash
|
||||
/// table. The iteration order doesn't depend on numerical key values, it only
|
||||
/// depends on the order of insert() and erase() operations. When no elements
|
||||
/// have been erased, the iteration order is the insertion order.
|
||||
///
|
||||
/// Compared to BitVector, SparseSet<unsigned> uses 8x-40x more memory, but
|
||||
/// offers constant-time clear() and size() operations as well as fast
|
||||
/// iteration independent on the size of the universe.
|
||||
///
|
||||
/// SparseSet contains a dense vector holding all the objects and a sparse
|
||||
/// array holding indexes into the dense vector. Most of the memory is used by
|
||||
/// the sparse array which is the size of the key universe. The SparseT
|
||||
/// template parameter provides a space/speed tradeoff for sets holding many
|
||||
/// elements.
|
||||
///
|
||||
/// When SparseT is uint32_t, find() only touches 2 cache lines, but the sparse
|
||||
/// array uses 4 x Universe bytes.
|
||||
///
|
||||
/// When SparseT is uint8_t (the default), find() touches up to 2+[N/256] cache
|
||||
/// lines, but the sparse array is 4x smaller. N is the number of elements in
|
||||
/// the set.
|
||||
///
|
||||
/// For sets that may grow to thousands of elements, SparseT should be set to
|
||||
/// uint16_t or uint32_t.
|
||||
///
|
||||
/// @param ValueT The type of objects in the set.
|
||||
/// @param SparseT An unsigned integer type. See above.
|
||||
/// @param KeyFunctorT A functor that computes the unsigned key of a ValueT.
|
||||
///
|
||||
template<typename ValueT,
|
||||
typename SparseT = uint8_t,
|
||||
typename KeyFunctorT = SparseSetFunctor<ValueT> >
|
||||
class SparseSet {
|
||||
typedef SmallVector<ValueT, 8> DenseT;
|
||||
DenseT Dense;
|
||||
SparseT *Sparse;
|
||||
unsigned Universe;
|
||||
KeyFunctorT KeyOf;
|
||||
|
||||
// Disable copy construction and assignment.
|
||||
// This data structure is not meant to be used that way.
|
||||
SparseSet(const SparseSet&); // DO NOT IMPLEMENT.
|
||||
SparseSet &operator=(const SparseSet&); // DO NOT IMPLEMENT.
|
||||
|
||||
public:
|
||||
typedef ValueT value_type;
|
||||
typedef ValueT &reference;
|
||||
typedef const ValueT &const_reference;
|
||||
typedef ValueT *pointer;
|
||||
typedef const ValueT *const_pointer;
|
||||
|
||||
SparseSet() : Sparse(0), Universe(0) {}
|
||||
~SparseSet() { free(Sparse); }
|
||||
|
||||
/// setUniverse - Set the universe size which determines the largest key the
|
||||
/// set can hold. The universe must be sized before any elements can be
|
||||
/// added.
|
||||
///
|
||||
/// @param U Universe size. All object keys must be less than U.
|
||||
///
|
||||
void setUniverse(unsigned U) {
|
||||
// It's not hard to resize the universe on a non-empty set, but it doesn't
|
||||
// seem like a likely use case, so we can add that code when we need it.
|
||||
assert(empty() && "Can only resize universe on an empty map");
|
||||
// Hysteresis prevents needless reallocations.
|
||||
if (U >= Universe/4 && U <= Universe)
|
||||
return;
|
||||
free(Sparse);
|
||||
// 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)));
|
||||
Universe = U;
|
||||
}
|
||||
|
||||
// Import trivial vector stuff from DenseT.
|
||||
typedef typename DenseT::iterator iterator;
|
||||
typedef typename DenseT::const_iterator const_iterator;
|
||||
|
||||
const_iterator begin() const { return Dense.begin(); }
|
||||
const_iterator end() const { return Dense.end(); }
|
||||
iterator begin() { return Dense.begin(); }
|
||||
iterator end() { return Dense.end(); }
|
||||
|
||||
/// empty - Returns true if the set is empty.
|
||||
///
|
||||
/// This is not the same as BitVector::empty().
|
||||
///
|
||||
bool empty() const { return Dense.empty(); }
|
||||
|
||||
/// size - Returns the number of elements in the set.
|
||||
///
|
||||
/// This is not the same as BitVector::size() which returns the size of the
|
||||
/// universe.
|
||||
///
|
||||
unsigned size() const { return Dense.size(); }
|
||||
|
||||
/// clear - Clears the set. This is a very fast constant time operation.
|
||||
///
|
||||
void clear() {
|
||||
// Sparse does not need to be cleared, see find().
|
||||
Dense.clear();
|
||||
}
|
||||
|
||||
/// find - Find an element by its key.
|
||||
///
|
||||
/// @param Key A valid key to find.
|
||||
/// @returns An iterator to the element identified by key, or end().
|
||||
///
|
||||
iterator find(unsigned Key) {
|
||||
assert(Key < Universe && "Key out of range");
|
||||
assert(std::numeric_limits<SparseT>::is_integer &&
|
||||
!std::numeric_limits<SparseT>::is_signed &&
|
||||
"SparseT must be an unsigned integer type");
|
||||
const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u;
|
||||
for (unsigned i = Sparse[Key], e = size(); i < e; i += Stride) {
|
||||
const unsigned FoundKey = KeyOf(Dense[i]);
|
||||
assert(FoundKey < Universe && "Invalid key in set. Did object mutate?");
|
||||
if (Key == FoundKey)
|
||||
return begin() + i;
|
||||
// Stride is 0 when SparseT >= unsigned. We don't need to loop.
|
||||
if (!Stride)
|
||||
break;
|
||||
}
|
||||
return end();
|
||||
}
|
||||
|
||||
const_iterator find(unsigned Key) const {
|
||||
return const_cast<SparseSet*>(this)->find(Key);
|
||||
}
|
||||
|
||||
/// count - Returns true if this set contains an element identified by Key.
|
||||
///
|
||||
bool count(unsigned Key) const {
|
||||
return find(Key) != end();
|
||||
}
|
||||
|
||||
/// insert - Attempts to insert a new element.
|
||||
///
|
||||
/// If Val is successfully inserted, return (I, true), where I is an iterator
|
||||
/// pointing to the newly inserted element.
|
||||
///
|
||||
/// If the set already contains an element with the same key as Val, return
|
||||
/// (I, false), where I is an iterator pointing to the existing element.
|
||||
///
|
||||
/// Insertion invalidates all iterators.
|
||||
///
|
||||
std::pair<iterator, bool> insert(const ValueT &Val) {
|
||||
unsigned Key = KeyOf(Val);
|
||||
iterator I = find(Key);
|
||||
if (I != end())
|
||||
return std::make_pair(I, false);
|
||||
Sparse[Key] = size();
|
||||
Dense.push_back(Val);
|
||||
return std::make_pair(end() - 1, true);
|
||||
}
|
||||
|
||||
/// array subscript - If an element already exists with this key, return it.
|
||||
/// Otherwise, automatically construct a new value from Key, insert it,
|
||||
/// and return the newly inserted element.
|
||||
ValueT &operator[](unsigned Key) {
|
||||
return *insert(ValueT(Key)).first;
|
||||
}
|
||||
|
||||
/// erase - Erases an existing element identified by a valid iterator.
|
||||
///
|
||||
/// This invalidates all iterators, but erase() returns an iterator pointing
|
||||
/// to the next element. This makes it possible to erase selected elements
|
||||
/// while iterating over the set:
|
||||
///
|
||||
/// for (SparseSet::iterator I = Set.begin(); I != Set.end();)
|
||||
/// if (test(*I))
|
||||
/// I = Set.erase(I);
|
||||
/// else
|
||||
/// ++I;
|
||||
///
|
||||
/// Note that end() changes when elements are erased, unlike std::list.
|
||||
///
|
||||
iterator erase(iterator I) {
|
||||
assert(unsigned(I - begin()) < size() && "Invalid iterator");
|
||||
if (I != end() - 1) {
|
||||
*I = Dense.back();
|
||||
unsigned BackKey = KeyOf(Dense.back());
|
||||
assert(BackKey < Universe && "Invalid key in set. Did object mutate?");
|
||||
Sparse[BackKey] = I - begin();
|
||||
}
|
||||
// This depends on SmallVector::pop_back() not invalidating iterators.
|
||||
// std::vector::pop_back() doesn't give that guarantee.
|
||||
Dense.pop_back();
|
||||
return I;
|
||||
}
|
||||
|
||||
/// erase - Erases an element identified by Key, if it exists.
|
||||
///
|
||||
/// @param Key The key identifying the element to erase.
|
||||
/// @returns True when an element was erased, false if no element was found.
|
||||
///
|
||||
bool erase(unsigned Key) {
|
||||
iterator I = find(Key);
|
||||
if (I == end())
|
||||
return false;
|
||||
erase(I);
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
#define LLVM_ADT_STATISTIC_H
|
||||
|
||||
#include "llvm/Support/Atomic.h"
|
||||
#include "llvm/Support/Valgrind.h"
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
|
|
@ -110,6 +111,7 @@ protected:
|
|||
bool tmp = Initialized;
|
||||
sys::MemoryFence();
|
||||
if (!tmp) RegisterStatistic();
|
||||
TsanHappensAfter(this);
|
||||
return *this;
|
||||
}
|
||||
void RegisterStatistic();
|
||||
|
|
|
|||
|
|
@ -15,12 +15,7 @@
|
|||
#define LLVM_ADT_STRINGEXTRAS_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/DenseMapInfo.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
template<typename T> class SmallVectorImpl;
|
||||
|
|
@ -101,38 +96,6 @@ static inline std::string itostr(int64_t X) {
|
|||
return utostr(static_cast<uint64_t>(X));
|
||||
}
|
||||
|
||||
static inline std::string ftostr(double V) {
|
||||
char Buffer[200];
|
||||
sprintf(Buffer, "%20.6e", V);
|
||||
char *B = Buffer;
|
||||
while (*B == ' ') ++B;
|
||||
return B;
|
||||
}
|
||||
|
||||
static inline std::string ftostr(const APFloat& V) {
|
||||
if (&V.getSemantics() == &APFloat::IEEEdouble)
|
||||
return ftostr(V.convertToDouble());
|
||||
else if (&V.getSemantics() == &APFloat::IEEEsingle)
|
||||
return ftostr((double)V.convertToFloat());
|
||||
return "<unknown format in ftostr>"; // error
|
||||
}
|
||||
|
||||
static inline std::string LowercaseString(const std::string &S) {
|
||||
std::string result(S);
|
||||
for (unsigned i = 0; i < S.length(); ++i)
|
||||
if (isupper(result[i]))
|
||||
result[i] = char(tolower(result[i]));
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline std::string UppercaseString(const std::string &S) {
|
||||
std::string result(S);
|
||||
for (unsigned i = 0; i < S.length(); ++i)
|
||||
if (islower(result[i]))
|
||||
result[i] = char(toupper(result[i]));
|
||||
return result;
|
||||
}
|
||||
|
||||
/// StrInStrNoCase - Portable version of strcasestr. Locates the first
|
||||
/// occurrence of string 's1' in string 's2', ignoring case. Returns
|
||||
/// the offset of s2 in s1 or npos if s2 cannot be found.
|
||||
|
|
|
|||
|
|
@ -51,20 +51,11 @@ public:
|
|||
/// StringMapImpl - This is the base class of StringMap that is shared among
|
||||
/// all of its instantiations.
|
||||
class StringMapImpl {
|
||||
public:
|
||||
/// ItemBucket - The hash table consists of an array of these. If Item is
|
||||
/// non-null, this is an extant entry, otherwise, it is a hole.
|
||||
struct ItemBucket {
|
||||
/// FullHashValue - This remembers the full hash value of the key for
|
||||
/// easy scanning.
|
||||
unsigned FullHashValue;
|
||||
|
||||
/// Item - This is a pointer to the actual item object.
|
||||
StringMapEntryBase *Item;
|
||||
};
|
||||
|
||||
protected:
|
||||
ItemBucket *TheTable;
|
||||
// Array of NumBuckets pointers to entries, null pointers are holes.
|
||||
// TheTable[NumBuckets] contains a sentinel value for easy iteration. Follwed
|
||||
// by an array of the actual hash values as unsigned integers.
|
||||
StringMapEntryBase **TheTable;
|
||||
unsigned NumBuckets;
|
||||
unsigned NumItems;
|
||||
unsigned NumTombstones;
|
||||
|
|
@ -238,8 +229,9 @@ public:
|
|||
template<typename ValueTy, typename AllocatorTy = MallocAllocator>
|
||||
class StringMap : public StringMapImpl {
|
||||
AllocatorTy Allocator;
|
||||
typedef StringMapEntry<ValueTy> MapEntryTy;
|
||||
public:
|
||||
typedef StringMapEntry<ValueTy> MapEntryTy;
|
||||
|
||||
StringMap() : StringMapImpl(static_cast<unsigned>(sizeof(MapEntryTy))) {}
|
||||
explicit StringMap(unsigned InitialSize)
|
||||
: StringMapImpl(InitialSize, static_cast<unsigned>(sizeof(MapEntryTy))) {}
|
||||
|
|
@ -289,13 +281,13 @@ public:
|
|||
iterator find(StringRef Key) {
|
||||
int Bucket = FindKey(Key);
|
||||
if (Bucket == -1) return end();
|
||||
return iterator(TheTable+Bucket);
|
||||
return iterator(TheTable+Bucket, true);
|
||||
}
|
||||
|
||||
const_iterator find(StringRef Key) const {
|
||||
int Bucket = FindKey(Key);
|
||||
if (Bucket == -1) return end();
|
||||
return const_iterator(TheTable+Bucket);
|
||||
return const_iterator(TheTable+Bucket, true);
|
||||
}
|
||||
|
||||
/// lookup - Return the entry for the specified key, or a default
|
||||
|
|
@ -320,13 +312,13 @@ public:
|
|||
/// insert it and return true.
|
||||
bool insert(MapEntryTy *KeyValue) {
|
||||
unsigned BucketNo = LookupBucketFor(KeyValue->getKey());
|
||||
ItemBucket &Bucket = TheTable[BucketNo];
|
||||
if (Bucket.Item && Bucket.Item != getTombstoneVal())
|
||||
StringMapEntryBase *&Bucket = TheTable[BucketNo];
|
||||
if (Bucket && Bucket != getTombstoneVal())
|
||||
return false; // Already exists in map.
|
||||
|
||||
if (Bucket.Item == getTombstoneVal())
|
||||
if (Bucket == getTombstoneVal())
|
||||
--NumTombstones;
|
||||
Bucket.Item = KeyValue;
|
||||
Bucket = KeyValue;
|
||||
++NumItems;
|
||||
assert(NumItems + NumTombstones <= NumBuckets);
|
||||
|
||||
|
|
@ -340,10 +332,11 @@ public:
|
|||
|
||||
// Zap all values, resetting the keys back to non-present (not tombstone),
|
||||
// which is safe because we're removing all elements.
|
||||
for (ItemBucket *I = TheTable, *E = TheTable+NumBuckets; I != E; ++I) {
|
||||
if (I->Item && I->Item != getTombstoneVal()) {
|
||||
static_cast<MapEntryTy*>(I->Item)->Destroy(Allocator);
|
||||
I->Item = 0;
|
||||
for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
|
||||
StringMapEntryBase *&Bucket = TheTable[I];
|
||||
if (Bucket && Bucket != getTombstoneVal()) {
|
||||
static_cast<MapEntryTy*>(Bucket)->Destroy(Allocator);
|
||||
Bucket = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -357,21 +350,21 @@ public:
|
|||
template <typename InitTy>
|
||||
MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) {
|
||||
unsigned BucketNo = LookupBucketFor(Key);
|
||||
ItemBucket &Bucket = TheTable[BucketNo];
|
||||
if (Bucket.Item && Bucket.Item != getTombstoneVal())
|
||||
return *static_cast<MapEntryTy*>(Bucket.Item);
|
||||
StringMapEntryBase *&Bucket = TheTable[BucketNo];
|
||||
if (Bucket && Bucket != getTombstoneVal())
|
||||
return *static_cast<MapEntryTy*>(Bucket);
|
||||
|
||||
MapEntryTy *NewItem =
|
||||
MapEntryTy::Create(Key.begin(), Key.end(), Allocator, Val);
|
||||
|
||||
if (Bucket.Item == getTombstoneVal())
|
||||
if (Bucket == getTombstoneVal())
|
||||
--NumTombstones;
|
||||
++NumItems;
|
||||
assert(NumItems + NumTombstones <= NumBuckets);
|
||||
|
||||
// Fill in the bucket for the hash table. The FullHashValue was already
|
||||
// filled in by LookupBucketFor.
|
||||
Bucket.Item = NewItem;
|
||||
Bucket = NewItem;
|
||||
|
||||
RehashTable();
|
||||
return *NewItem;
|
||||
|
|
@ -410,21 +403,21 @@ public:
|
|||
template<typename ValueTy>
|
||||
class StringMapConstIterator {
|
||||
protected:
|
||||
StringMapImpl::ItemBucket *Ptr;
|
||||
StringMapEntryBase **Ptr;
|
||||
public:
|
||||
typedef StringMapEntry<ValueTy> value_type;
|
||||
|
||||
explicit StringMapConstIterator(StringMapImpl::ItemBucket *Bucket,
|
||||
explicit StringMapConstIterator(StringMapEntryBase **Bucket,
|
||||
bool NoAdvance = false)
|
||||
: Ptr(Bucket) {
|
||||
if (!NoAdvance) AdvancePastEmptyBuckets();
|
||||
}
|
||||
|
||||
const value_type &operator*() const {
|
||||
return *static_cast<StringMapEntry<ValueTy>*>(Ptr->Item);
|
||||
return *static_cast<StringMapEntry<ValueTy>*>(*Ptr);
|
||||
}
|
||||
const value_type *operator->() const {
|
||||
return static_cast<StringMapEntry<ValueTy>*>(Ptr->Item);
|
||||
return static_cast<StringMapEntry<ValueTy>*>(*Ptr);
|
||||
}
|
||||
|
||||
bool operator==(const StringMapConstIterator &RHS) const {
|
||||
|
|
@ -445,7 +438,7 @@ public:
|
|||
|
||||
private:
|
||||
void AdvancePastEmptyBuckets() {
|
||||
while (Ptr->Item == 0 || Ptr->Item == StringMapImpl::getTombstoneVal())
|
||||
while (*Ptr == 0 || *Ptr == StringMapImpl::getTombstoneVal())
|
||||
++Ptr;
|
||||
}
|
||||
};
|
||||
|
|
@ -453,15 +446,15 @@ private:
|
|||
template<typename ValueTy>
|
||||
class StringMapIterator : public StringMapConstIterator<ValueTy> {
|
||||
public:
|
||||
explicit StringMapIterator(StringMapImpl::ItemBucket *Bucket,
|
||||
explicit StringMapIterator(StringMapEntryBase **Bucket,
|
||||
bool NoAdvance = false)
|
||||
: StringMapConstIterator<ValueTy>(Bucket, NoAdvance) {
|
||||
}
|
||||
StringMapEntry<ValueTy> &operator*() const {
|
||||
return *static_cast<StringMapEntry<ValueTy>*>(this->Ptr->Item);
|
||||
return *static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
|
||||
}
|
||||
StringMapEntry<ValueTy> *operator->() const {
|
||||
return static_cast<StringMapEntry<ValueTy>*>(this->Ptr->Item);
|
||||
return static_cast<StringMapEntry<ValueTy>*>(*this->Ptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -10,15 +10,26 @@
|
|||
#ifndef LLVM_ADT_STRINGREF_H
|
||||
#define LLVM_ADT_STRINGREF_H
|
||||
|
||||
#include "llvm/Support/type_traits.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
template<typename T>
|
||||
class SmallVectorImpl;
|
||||
class APInt;
|
||||
class hash_code;
|
||||
class StringRef;
|
||||
|
||||
/// Helper functions for StringRef::getAsInteger.
|
||||
bool getAsUnsignedInteger(StringRef Str, unsigned Radix,
|
||||
unsigned long long &Result);
|
||||
|
||||
bool getAsSignedInteger(StringRef Str, unsigned Radix, long long &Result);
|
||||
|
||||
/// StringRef - Represent a constant reference to a string, i.e. a character
|
||||
/// array and a length, which need not be null terminated.
|
||||
|
|
@ -304,14 +315,29 @@ namespace llvm {
|
|||
///
|
||||
/// If the string is invalid or if only a subset of the string is valid,
|
||||
/// this returns true to signify the error. The string is considered
|
||||
/// erroneous if empty.
|
||||
/// erroneous if empty or if it overflows T.
|
||||
///
|
||||
bool getAsInteger(unsigned Radix, long long &Result) const;
|
||||
bool getAsInteger(unsigned Radix, unsigned long long &Result) const;
|
||||
bool getAsInteger(unsigned Radix, int &Result) const;
|
||||
bool getAsInteger(unsigned Radix, unsigned &Result) const;
|
||||
template <typename T>
|
||||
typename enable_if_c<std::numeric_limits<T>::is_signed, bool>::type
|
||||
getAsInteger(unsigned Radix, T &Result) const {
|
||||
long long LLVal;
|
||||
if (getAsSignedInteger(*this, Radix, LLVal) ||
|
||||
static_cast<T>(LLVal) != LLVal)
|
||||
return true;
|
||||
Result = LLVal;
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Provide overloads for int/unsigned that check for overflow.
|
||||
template <typename T>
|
||||
typename enable_if_c<!std::numeric_limits<T>::is_signed, bool>::type
|
||||
getAsInteger(unsigned Radix, T &Result) const {
|
||||
unsigned long long ULLVal;
|
||||
if (getAsUnsignedInteger(*this, Radix, ULLVal) ||
|
||||
static_cast<T>(ULLVal) != ULLVal)
|
||||
return true;
|
||||
Result = ULLVal;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getAsInteger - Parse the current string as an integer of the
|
||||
/// specified radix, or of an autosensed radix if the radix given
|
||||
|
|
@ -326,6 +352,16 @@ namespace llvm {
|
|||
/// string is well-formed in the given radix.
|
||||
bool getAsInteger(unsigned Radix, APInt &Result) const;
|
||||
|
||||
/// @}
|
||||
/// @name String Operations
|
||||
/// @{
|
||||
|
||||
// lower - Convert the given ASCII string to lowercase.
|
||||
std::string lower() const;
|
||||
|
||||
/// upper - Convert the given ASCII string to uppercase.
|
||||
std::string upper() const;
|
||||
|
||||
/// @}
|
||||
/// @name Substring Operations
|
||||
/// @{
|
||||
|
|
@ -343,6 +379,20 @@ namespace llvm {
|
|||
Start = min(Start, Length);
|
||||
return StringRef(Data + Start, min(N, Length - Start));
|
||||
}
|
||||
|
||||
/// drop_front - Return a StringRef equal to 'this' but with the first
|
||||
/// elements dropped.
|
||||
StringRef drop_front(unsigned N = 1) const {
|
||||
assert(size() >= N && "Dropping more elements than exist");
|
||||
return substr(N);
|
||||
}
|
||||
|
||||
/// drop_back - Return a StringRef equal to 'this' but with the last
|
||||
/// elements dropped.
|
||||
StringRef drop_back(unsigned N = 1) const {
|
||||
assert(size() >= N && "Dropping more elements than exist");
|
||||
return substr(0, size()-N);
|
||||
}
|
||||
|
||||
/// slice - Return a reference to the substring from [Start, End).
|
||||
///
|
||||
|
|
@ -466,6 +516,9 @@ namespace llvm {
|
|||
|
||||
/// @}
|
||||
|
||||
/// \brief Compute a hash_code for a StringRef.
|
||||
hash_code hash_value(StringRef S);
|
||||
|
||||
// StringRefs can be treated like a POD type.
|
||||
template <typename T> struct isPodLike;
|
||||
template <> struct isPodLike<StringRef> { static const bool value = true; };
|
||||
|
|
|
|||
|
|
@ -37,6 +37,15 @@ public:
|
|||
delete V;
|
||||
}
|
||||
|
||||
// implicit conversion operator to ArrayRef.
|
||||
operator ArrayRef<EltTy>() const {
|
||||
if (Val.isNull())
|
||||
return ArrayRef<EltTy>();
|
||||
if (Val.template is<EltTy>())
|
||||
return *Val.getAddrOfPtr1();
|
||||
return *Val.template get<VecTy*>();
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
// This vector can be empty if it contains no element, or if it
|
||||
// contains a pointer to an empty vector.
|
||||
|
|
@ -54,18 +63,20 @@ public:
|
|||
return Val.template get<VecTy*>()->size();
|
||||
}
|
||||
|
||||
typedef const EltTy *iterator;
|
||||
iterator begin() const {
|
||||
typedef const EltTy *const_iterator;
|
||||
typedef EltTy *iterator;
|
||||
|
||||
iterator begin() {
|
||||
if (empty())
|
||||
return 0;
|
||||
|
||||
if (Val.template is<EltTy>())
|
||||
return Val.template getAddrOf<EltTy>();
|
||||
return Val.getAddrOfPtr1();
|
||||
|
||||
return Val.template get<VecTy *>()->begin();
|
||||
|
||||
}
|
||||
iterator end() const {
|
||||
iterator end() {
|
||||
if (empty())
|
||||
return 0;
|
||||
|
||||
|
|
@ -75,7 +86,14 @@ public:
|
|||
return Val.template get<VecTy *>()->end();
|
||||
}
|
||||
|
||||
|
||||
const_iterator begin() const {
|
||||
return (const_iterator)const_cast<TinyPtrVector*>(this)->begin();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return (const_iterator)const_cast<TinyPtrVector*>(this)->end();
|
||||
}
|
||||
|
||||
EltTy operator[](unsigned i) const {
|
||||
assert(!Val.isNull() && "can't index into an empty vector");
|
||||
if (EltTy V = Val.template dyn_cast<EltTy>()) {
|
||||
|
|
@ -124,6 +142,20 @@ public:
|
|||
}
|
||||
// Otherwise, we're already empty.
|
||||
}
|
||||
|
||||
iterator erase(iterator I) {
|
||||
// If we have a single value, convert to empty.
|
||||
if (Val.template is<EltTy>()) {
|
||||
if (I == begin())
|
||||
Val = (EltTy)0;
|
||||
} else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
|
||||
// multiple items in a vector; just do the erase, there is no
|
||||
// benefit to collapsing back to a pointer
|
||||
return Vec->erase(I);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET.
|
||||
|
|
|
|||
|
|
@ -220,8 +220,7 @@ bool Trie<Payload>::addString(const std::string& s, const Payload& data) {
|
|||
assert(0 && "FIXME!");
|
||||
return false;
|
||||
case Node::DontMatch:
|
||||
assert(0 && "Impossible!");
|
||||
return false;
|
||||
llvm_unreachable("Impossible!");
|
||||
case Node::LabelIsPrefix:
|
||||
s1 = s1.substr(nNode->label().length());
|
||||
cNode = nNode;
|
||||
|
|
@ -258,8 +257,7 @@ const Payload& Trie<Payload>::lookup(const std::string& s) const {
|
|||
case Node::StringIsPrefix:
|
||||
return Empty;
|
||||
case Node::DontMatch:
|
||||
assert(0 && "Impossible!");
|
||||
return Empty;
|
||||
llvm_unreachable("Impossible!");
|
||||
case Node::LabelIsPrefix:
|
||||
s1 = s1.substr(nNode->label().length());
|
||||
cNode = nNode;
|
||||
|
|
|
|||
|
|
@ -43,20 +43,19 @@ public:
|
|||
enum ArchType {
|
||||
UnknownArch,
|
||||
|
||||
alpha, // Alpha: alpha
|
||||
arm, // ARM; arm, armv.*, xscale
|
||||
bfin, // Blackfin: bfin
|
||||
cellspu, // CellSPU: spu, cellspu
|
||||
hexagon, // Hexagon: hexagon
|
||||
mips, // MIPS: mips, mipsallegrex
|
||||
mipsel, // MIPSEL: mipsel, mipsallegrexel, psp
|
||||
mipsel, // MIPSEL: mipsel, mipsallegrexel
|
||||
mips64, // MIPS64: mips64
|
||||
mips64el,// MIPS64EL: mips64el
|
||||
msp430, // MSP430: msp430
|
||||
ppc, // PPC: powerpc
|
||||
ppc64, // PPC64: powerpc64, ppu
|
||||
r600, // R600: AMD GPUs HD2XXX - HD6XXX
|
||||
sparc, // Sparc: sparc
|
||||
sparcv9, // Sparcv9: Sparcv9
|
||||
systemz, // SystemZ: s390x
|
||||
tce, // TCE (http://tce.cs.tut.fi/): tce
|
||||
thumb, // Thumb: thumb, thumbv.*
|
||||
x86, // X86: i[3-9]86
|
||||
|
|
@ -66,16 +65,16 @@ public:
|
|||
ptx32, // PTX: ptx (32-bit)
|
||||
ptx64, // PTX: ptx (64-bit)
|
||||
le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten)
|
||||
amdil, // amdil: amd IL
|
||||
|
||||
InvalidArch
|
||||
amdil // amdil: amd IL
|
||||
};
|
||||
enum VendorType {
|
||||
UnknownVendor,
|
||||
|
||||
Apple,
|
||||
PC,
|
||||
SCEI
|
||||
SCEI,
|
||||
BGP,
|
||||
BGQ
|
||||
};
|
||||
enum OSType {
|
||||
UnknownOS,
|
||||
|
|
@ -93,61 +92,52 @@ public:
|
|||
MinGW32, // i*86-pc-mingw32, *-w64-mingw32
|
||||
NetBSD,
|
||||
OpenBSD,
|
||||
Psp,
|
||||
Solaris,
|
||||
Win32,
|
||||
Haiku,
|
||||
Minix,
|
||||
RTEMS,
|
||||
NativeClient
|
||||
NativeClient,
|
||||
CNK // BG/P Compute-Node Kernel
|
||||
};
|
||||
enum EnvironmentType {
|
||||
UnknownEnvironment,
|
||||
|
||||
GNU,
|
||||
GNUEABI,
|
||||
GNUEABIHF,
|
||||
EABI,
|
||||
MachO
|
||||
MachO,
|
||||
ANDROIDEABI
|
||||
};
|
||||
|
||||
private:
|
||||
std::string Data;
|
||||
|
||||
/// The parsed arch type (or InvalidArch if uninitialized).
|
||||
mutable ArchType Arch;
|
||||
/// The parsed arch type.
|
||||
ArchType Arch;
|
||||
|
||||
/// The parsed vendor type.
|
||||
mutable VendorType Vendor;
|
||||
VendorType Vendor;
|
||||
|
||||
/// The parsed OS type.
|
||||
mutable OSType OS;
|
||||
OSType OS;
|
||||
|
||||
/// The parsed Environment type.
|
||||
mutable EnvironmentType Environment;
|
||||
|
||||
bool isInitialized() const { return Arch != InvalidArch; }
|
||||
static ArchType ParseArch(StringRef ArchName);
|
||||
static VendorType ParseVendor(StringRef VendorName);
|
||||
static OSType ParseOS(StringRef OSName);
|
||||
static EnvironmentType ParseEnvironment(StringRef EnvironmentName);
|
||||
void Parse() const;
|
||||
EnvironmentType Environment;
|
||||
|
||||
public:
|
||||
/// @name Constructors
|
||||
/// @{
|
||||
|
||||
Triple() : Data(), Arch(InvalidArch) {}
|
||||
explicit Triple(const Twine &Str) : Data(Str.str()), Arch(InvalidArch) {}
|
||||
Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr)
|
||||
: Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr).str()),
|
||||
Arch(InvalidArch) {
|
||||
}
|
||||
/// \brief Default constructor is the same as an empty string and leaves all
|
||||
/// triple fields unknown.
|
||||
Triple() : Data(), Arch(), Vendor(), OS(), Environment() {}
|
||||
|
||||
explicit Triple(const Twine &Str);
|
||||
Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr);
|
||||
Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
|
||||
const Twine &EnvironmentStr)
|
||||
: Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr + Twine('-') +
|
||||
EnvironmentStr).str()), Arch(InvalidArch) {
|
||||
}
|
||||
const Twine &EnvironmentStr);
|
||||
|
||||
/// @}
|
||||
/// @name Normalization
|
||||
|
|
@ -164,22 +154,13 @@ public:
|
|||
/// @{
|
||||
|
||||
/// getArch - Get the parsed architecture type of this triple.
|
||||
ArchType getArch() const {
|
||||
if (!isInitialized()) Parse();
|
||||
return Arch;
|
||||
}
|
||||
ArchType getArch() const { return Arch; }
|
||||
|
||||
/// getVendor - Get the parsed vendor type of this triple.
|
||||
VendorType getVendor() const {
|
||||
if (!isInitialized()) Parse();
|
||||
return Vendor;
|
||||
}
|
||||
VendorType getVendor() const { return Vendor; }
|
||||
|
||||
/// getOS - Get the parsed operating system type of this triple.
|
||||
OSType getOS() const {
|
||||
if (!isInitialized()) Parse();
|
||||
return OS;
|
||||
}
|
||||
OSType getOS() const { return OS; }
|
||||
|
||||
/// hasEnvironment - Does this triple have the optional environment
|
||||
/// (fourth) component?
|
||||
|
|
@ -188,11 +169,31 @@ public:
|
|||
}
|
||||
|
||||
/// getEnvironment - Get the parsed environment type of this triple.
|
||||
EnvironmentType getEnvironment() const {
|
||||
if (!isInitialized()) Parse();
|
||||
return Environment;
|
||||
EnvironmentType getEnvironment() const { return Environment; }
|
||||
|
||||
/// getOSVersion - Parse the version number from the OS name component of the
|
||||
/// triple, if present.
|
||||
///
|
||||
/// For example, "fooos1.2.3" would return (1, 2, 3).
|
||||
///
|
||||
/// If an entry is not defined, it will be returned as 0.
|
||||
void getOSVersion(unsigned &Major, unsigned &Minor, unsigned &Micro) const;
|
||||
|
||||
/// getOSMajorVersion - Return just the major version number, this is
|
||||
/// specialized because it is a common query.
|
||||
unsigned getOSMajorVersion() const {
|
||||
unsigned Maj, Min, Micro;
|
||||
getOSVersion(Maj, Min, Micro);
|
||||
return Maj;
|
||||
}
|
||||
|
||||
/// getMacOSXVersion - Parse the version number as with getOSVersion and then
|
||||
/// translate generic "darwin" versions to the corresponding OS X versions.
|
||||
/// This may also be called with IOS triples but the OS X version number is
|
||||
/// just set to a constant 10.4.0 in that case. Returns true if successful.
|
||||
bool getMacOSXVersion(unsigned &Major, unsigned &Minor,
|
||||
unsigned &Micro) const;
|
||||
|
||||
/// @}
|
||||
/// @name Direct Component Access
|
||||
/// @{
|
||||
|
|
@ -221,21 +222,28 @@ public:
|
|||
/// if the environment component is present).
|
||||
StringRef getOSAndEnvironmentName() const;
|
||||
|
||||
/// getOSVersion - Parse the version number from the OS name component of the
|
||||
/// triple, if present.
|
||||
///
|
||||
/// For example, "fooos1.2.3" would return (1, 2, 3).
|
||||
///
|
||||
/// If an entry is not defined, it will be returned as 0.
|
||||
void getOSVersion(unsigned &Major, unsigned &Minor, unsigned &Micro) const;
|
||||
/// @}
|
||||
/// @name Convenience Predicates
|
||||
/// @{
|
||||
|
||||
/// getOSMajorVersion - Return just the major version number, this is
|
||||
/// specialized because it is a common query.
|
||||
unsigned getOSMajorVersion() const {
|
||||
unsigned Maj, Min, Micro;
|
||||
getOSVersion(Maj, Min, Micro);
|
||||
return Maj;
|
||||
}
|
||||
/// \brief Test whether the architecture is 64-bit
|
||||
///
|
||||
/// Note that this tests for 64-bit pointer width, and nothing else. Note
|
||||
/// that we intentionally expose only three predicates, 64-bit, 32-bit, and
|
||||
/// 16-bit. The inner details of pointer width for particular architectures
|
||||
/// is not summed up in the triple, and so only a coarse grained predicate
|
||||
/// system is provided.
|
||||
bool isArch64Bit() const;
|
||||
|
||||
/// \brief Test whether the architecture is 32-bit
|
||||
///
|
||||
/// Note that this tests for 32-bit pointer width, and nothing else.
|
||||
bool isArch32Bit() const;
|
||||
|
||||
/// \brief Test whether the architecture is 16-bit
|
||||
///
|
||||
/// Note that this tests for 16-bit pointer width, and nothing else.
|
||||
bool isArch16Bit() const;
|
||||
|
||||
/// isOSVersionLT - Helper function for doing comparisons against version
|
||||
/// numbers included in the target triple.
|
||||
|
|
@ -254,23 +262,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both
|
||||
/// "darwin" and "osx" as OS X triples.
|
||||
bool isMacOSX() const {
|
||||
return getOS() == Triple::Darwin || getOS() == Triple::MacOSX;
|
||||
}
|
||||
|
||||
/// isOSDarwin - Is this a "Darwin" OS (OS X or iOS).
|
||||
bool isOSDarwin() const {
|
||||
return isMacOSX() || getOS() == Triple::IOS;
|
||||
}
|
||||
|
||||
/// isOSWindows - Is this a "Windows" OS.
|
||||
bool isOSWindows() const {
|
||||
return getOS() == Triple::Win32 || getOS() == Triple::Cygwin ||
|
||||
getOS() == Triple::MinGW32;
|
||||
}
|
||||
|
||||
/// isMacOSXVersionLT - Comparison function for checking OS X version
|
||||
/// compatibility, which handles supporting skewed version numbering schemes
|
||||
/// used by the "darwin" triples.
|
||||
|
|
@ -287,6 +278,43 @@ public:
|
|||
return isOSVersionLT(Minor + 4, Micro, 0);
|
||||
}
|
||||
|
||||
/// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both
|
||||
/// "darwin" and "osx" as OS X triples.
|
||||
bool isMacOSX() const {
|
||||
return getOS() == Triple::Darwin || getOS() == Triple::MacOSX;
|
||||
}
|
||||
|
||||
/// isOSDarwin - Is this a "Darwin" OS (OS X or iOS).
|
||||
bool isOSDarwin() const {
|
||||
return isMacOSX() || getOS() == Triple::IOS;
|
||||
}
|
||||
|
||||
/// \brief Tests for either Cygwin or MinGW OS
|
||||
bool isOSCygMing() const {
|
||||
return getOS() == Triple::Cygwin || getOS() == Triple::MinGW32;
|
||||
}
|
||||
|
||||
/// isOSWindows - Is this a "Windows" OS.
|
||||
bool isOSWindows() const {
|
||||
return getOS() == Triple::Win32 || isOSCygMing();
|
||||
}
|
||||
|
||||
/// \brief Tests whether the OS uses the ELF binary format.
|
||||
bool isOSBinFormatELF() const {
|
||||
return !isOSDarwin() && !isOSWindows();
|
||||
}
|
||||
|
||||
/// \brief Tests whether the OS uses the COFF binary format.
|
||||
bool isOSBinFormatCOFF() const {
|
||||
return isOSWindows();
|
||||
}
|
||||
|
||||
/// \brief Tests whether the environment is MachO.
|
||||
// FIXME: Should this be an OSBinFormat predicate?
|
||||
bool isEnvironmentMachO() const {
|
||||
return getEnvironment() == Triple::MachO || isOSDarwin();
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Mutators
|
||||
/// @{
|
||||
|
|
@ -334,6 +362,26 @@ public:
|
|||
/// the target assembler.
|
||||
const char *getArchNameForAssembler();
|
||||
|
||||
/// @}
|
||||
/// @name Helpers to build variants of a particular triple.
|
||||
/// @{
|
||||
|
||||
/// \brief Form a triple with a 32-bit variant of the current architecture.
|
||||
///
|
||||
/// This can be used to move across "families" of architectures where useful.
|
||||
///
|
||||
/// \returns A new triple with a 32-bit architecture or an unknown
|
||||
/// architecture if no such variant can be found.
|
||||
llvm::Triple get32BitArchVariant() const;
|
||||
|
||||
/// \brief Form a triple with a 64-bit variant of the current architecture.
|
||||
///
|
||||
/// This can be used to move across "families" of architectures where useful.
|
||||
///
|
||||
/// \returns A new triple with a 64-bit architecture or an unknown
|
||||
/// architecture if no such variant can be found.
|
||||
llvm::Triple get64BitArchVariant() const;
|
||||
|
||||
/// @}
|
||||
/// @name Static helpers for IDs.
|
||||
/// @{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -425,7 +426,7 @@ namespace llvm {
|
|||
StringRef getSingleStringRef() const {
|
||||
assert(isSingleStringRef() &&"This cannot be had as a single stringref!");
|
||||
switch (getLHSKind()) {
|
||||
default: assert(0 && "Out of sync with isSingleStringRef");
|
||||
default: llvm_unreachable("Out of sync with isSingleStringRef");
|
||||
case EmptyKind: return StringRef();
|
||||
case CStringKind: return StringRef(LHS.cString);
|
||||
case StdStringKind: return StringRef(*LHS.stdString);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
namespace llvm {
|
||||
|
||||
template<typename KeyT, typename ValueT, typename Config, typename ValueInfoT>
|
||||
template<typename KeyT, typename ValueT, typename Config>
|
||||
class ValueMapCallbackVH;
|
||||
|
||||
template<typename DenseMapT, typename KeyT>
|
||||
|
|
@ -72,13 +72,11 @@ struct ValueMapConfig {
|
|||
};
|
||||
|
||||
/// See the file comment.
|
||||
template<typename KeyT, typename ValueT, typename Config = ValueMapConfig<KeyT>,
|
||||
typename ValueInfoT = DenseMapInfo<ValueT> >
|
||||
template<typename KeyT, typename ValueT, typename Config =ValueMapConfig<KeyT> >
|
||||
class ValueMap {
|
||||
friend class ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT>;
|
||||
typedef ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT> ValueMapCVH;
|
||||
typedef DenseMap<ValueMapCVH, ValueT, DenseMapInfo<ValueMapCVH>,
|
||||
ValueInfoT> MapT;
|
||||
friend class ValueMapCallbackVH<KeyT, ValueT, Config>;
|
||||
typedef ValueMapCallbackVH<KeyT, ValueT, Config> ValueMapCVH;
|
||||
typedef DenseMap<ValueMapCVH, ValueT, DenseMapInfo<ValueMapCVH> > MapT;
|
||||
typedef typename Config::ExtraData ExtraData;
|
||||
MapT Map;
|
||||
ExtraData Data;
|
||||
|
|
@ -190,11 +188,11 @@ private:
|
|||
|
||||
// This CallbackVH updates its ValueMap when the contained Value changes,
|
||||
// according to the user's preferences expressed through the Config object.
|
||||
template<typename KeyT, typename ValueT, typename Config, typename ValueInfoT>
|
||||
template<typename KeyT, typename ValueT, typename Config>
|
||||
class ValueMapCallbackVH : public CallbackVH {
|
||||
friend class ValueMap<KeyT, ValueT, Config, ValueInfoT>;
|
||||
friend class ValueMap<KeyT, ValueT, Config>;
|
||||
friend struct DenseMapInfo<ValueMapCallbackVH>;
|
||||
typedef ValueMap<KeyT, ValueT, Config, ValueInfoT> ValueMapT;
|
||||
typedef ValueMap<KeyT, ValueT, Config> ValueMapT;
|
||||
typedef typename llvm::remove_pointer<KeyT>::type KeySansPointerT;
|
||||
|
||||
ValueMapT *Map;
|
||||
|
|
@ -244,9 +242,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<typename KeyT, typename ValueT, typename Config, typename ValueInfoT>
|
||||
struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT> > {
|
||||
typedef ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT> VH;
|
||||
template<typename KeyT, typename ValueT, typename Config>
|
||||
struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config> > {
|
||||
typedef ValueMapCallbackVH<KeyT, ValueT, Config> VH;
|
||||
typedef DenseMapInfo<KeyT> PointerInfo;
|
||||
|
||||
static inline VH getEmptyKey() {
|
||||
|
|
|
|||
331
contrib/llvm/include/llvm/ADT/VariadicFunction.h
Normal file
331
contrib/llvm/include/llvm/ADT/VariadicFunction.h
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
//===--- VariadicFunctions.h - Variadic Functions ---------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements compile-time type-safe variadic functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_VARIADIC_FUNCTION_H
|
||||
#define LLVM_ADT_VARIADIC_FUNCTION_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
// Define macros to aid in expanding a comma separated series with the index of
|
||||
// the series pasted onto the last token.
|
||||
#define LLVM_COMMA_JOIN1(x) x ## 0
|
||||
#define LLVM_COMMA_JOIN2(x) LLVM_COMMA_JOIN1(x), x ## 1
|
||||
#define LLVM_COMMA_JOIN3(x) LLVM_COMMA_JOIN2(x), x ## 2
|
||||
#define LLVM_COMMA_JOIN4(x) LLVM_COMMA_JOIN3(x), x ## 3
|
||||
#define LLVM_COMMA_JOIN5(x) LLVM_COMMA_JOIN4(x), x ## 4
|
||||
#define LLVM_COMMA_JOIN6(x) LLVM_COMMA_JOIN5(x), x ## 5
|
||||
#define LLVM_COMMA_JOIN7(x) LLVM_COMMA_JOIN6(x), x ## 6
|
||||
#define LLVM_COMMA_JOIN8(x) LLVM_COMMA_JOIN7(x), x ## 7
|
||||
#define LLVM_COMMA_JOIN9(x) LLVM_COMMA_JOIN8(x), x ## 8
|
||||
#define LLVM_COMMA_JOIN10(x) LLVM_COMMA_JOIN9(x), x ## 9
|
||||
#define LLVM_COMMA_JOIN11(x) LLVM_COMMA_JOIN10(x), x ## 10
|
||||
#define LLVM_COMMA_JOIN12(x) LLVM_COMMA_JOIN11(x), x ## 11
|
||||
#define LLVM_COMMA_JOIN13(x) LLVM_COMMA_JOIN12(x), x ## 12
|
||||
#define LLVM_COMMA_JOIN14(x) LLVM_COMMA_JOIN13(x), x ## 13
|
||||
#define LLVM_COMMA_JOIN15(x) LLVM_COMMA_JOIN14(x), x ## 14
|
||||
#define LLVM_COMMA_JOIN16(x) LLVM_COMMA_JOIN15(x), x ## 15
|
||||
#define LLVM_COMMA_JOIN17(x) LLVM_COMMA_JOIN16(x), x ## 16
|
||||
#define LLVM_COMMA_JOIN18(x) LLVM_COMMA_JOIN17(x), x ## 17
|
||||
#define LLVM_COMMA_JOIN19(x) LLVM_COMMA_JOIN18(x), x ## 18
|
||||
#define LLVM_COMMA_JOIN20(x) LLVM_COMMA_JOIN19(x), x ## 19
|
||||
#define LLVM_COMMA_JOIN21(x) LLVM_COMMA_JOIN20(x), x ## 20
|
||||
#define LLVM_COMMA_JOIN22(x) LLVM_COMMA_JOIN21(x), x ## 21
|
||||
#define LLVM_COMMA_JOIN23(x) LLVM_COMMA_JOIN22(x), x ## 22
|
||||
#define LLVM_COMMA_JOIN24(x) LLVM_COMMA_JOIN23(x), x ## 23
|
||||
#define LLVM_COMMA_JOIN25(x) LLVM_COMMA_JOIN24(x), x ## 24
|
||||
#define LLVM_COMMA_JOIN26(x) LLVM_COMMA_JOIN25(x), x ## 25
|
||||
#define LLVM_COMMA_JOIN27(x) LLVM_COMMA_JOIN26(x), x ## 26
|
||||
#define LLVM_COMMA_JOIN28(x) LLVM_COMMA_JOIN27(x), x ## 27
|
||||
#define LLVM_COMMA_JOIN29(x) LLVM_COMMA_JOIN28(x), x ## 28
|
||||
#define LLVM_COMMA_JOIN30(x) LLVM_COMMA_JOIN29(x), x ## 29
|
||||
#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.
|
||||
///
|
||||
/// The VariadicFunction class template makes it easy to define
|
||||
/// type-safe variadic functions where all arguments have the same
|
||||
/// type.
|
||||
///
|
||||
/// Suppose we need a variadic function like this:
|
||||
///
|
||||
/// ResultT Foo(const ArgT &A_0, const ArgT &A_1, ..., const ArgT &A_N);
|
||||
///
|
||||
/// Instead of many overloads of Foo(), we only need to define a helper
|
||||
/// function that takes an array of arguments:
|
||||
///
|
||||
/// ResultT FooImpl(ArrayRef<const ArgT *> Args) {
|
||||
/// // 'Args[i]' is a pointer to the i-th argument passed to Foo().
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// and then define Foo() like this:
|
||||
///
|
||||
/// const VariadicFunction<ResultT, ArgT, FooImpl> Foo;
|
||||
///
|
||||
/// VariadicFunction takes care of defining the overloads of Foo().
|
||||
///
|
||||
/// Actually, Foo is a function object (i.e. functor) instead of a plain
|
||||
/// function. This object is stateless and its constructor/destructor
|
||||
/// does nothing, so it's safe to create global objects and call Foo(...) at
|
||||
/// any time.
|
||||
///
|
||||
/// Sometimes we need a variadic function to have some fixed leading
|
||||
/// arguments whose types may be different from that of the optional
|
||||
/// arguments. For example:
|
||||
///
|
||||
/// bool FullMatch(const StringRef &S, const RE &Regex,
|
||||
/// const ArgT &A_0, ..., const ArgT &A_N);
|
||||
///
|
||||
/// VariadicFunctionN is for such cases, where N is the number of fixed
|
||||
/// arguments. It is like VariadicFunction, except that it takes N more
|
||||
/// template arguments for the types of the fixed arguments:
|
||||
///
|
||||
/// bool FullMatchImpl(const StringRef &S, const RE &Regex,
|
||||
/// ArrayRef<const ArgT *> Args) { ... }
|
||||
/// const VariadicFunction2<bool, const StringRef&,
|
||||
/// const RE&, ArgT, FullMatchImpl>
|
||||
/// FullMatch;
|
||||
///
|
||||
/// Currently VariadicFunction and friends support up-to 3
|
||||
/// fixed leading arguments and up-to 32 optional arguments.
|
||||
template <typename ResultT, typename ArgT,
|
||||
ResultT (*Func)(ArrayRef<const ArgT *>)>
|
||||
struct VariadicFunction {
|
||||
ResultT operator()() const {
|
||||
return Func(ArrayRef<const ArgT *>());
|
||||
}
|
||||
|
||||
#define LLVM_DEFINE_OVERLOAD(N) \
|
||||
ResultT operator()(LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
|
||||
const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
|
||||
return Func(makeArrayRef(Args)); \
|
||||
}
|
||||
LLVM_DEFINE_OVERLOAD(1)
|
||||
LLVM_DEFINE_OVERLOAD(2)
|
||||
LLVM_DEFINE_OVERLOAD(3)
|
||||
LLVM_DEFINE_OVERLOAD(4)
|
||||
LLVM_DEFINE_OVERLOAD(5)
|
||||
LLVM_DEFINE_OVERLOAD(6)
|
||||
LLVM_DEFINE_OVERLOAD(7)
|
||||
LLVM_DEFINE_OVERLOAD(8)
|
||||
LLVM_DEFINE_OVERLOAD(9)
|
||||
LLVM_DEFINE_OVERLOAD(10)
|
||||
LLVM_DEFINE_OVERLOAD(11)
|
||||
LLVM_DEFINE_OVERLOAD(12)
|
||||
LLVM_DEFINE_OVERLOAD(13)
|
||||
LLVM_DEFINE_OVERLOAD(14)
|
||||
LLVM_DEFINE_OVERLOAD(15)
|
||||
LLVM_DEFINE_OVERLOAD(16)
|
||||
LLVM_DEFINE_OVERLOAD(17)
|
||||
LLVM_DEFINE_OVERLOAD(18)
|
||||
LLVM_DEFINE_OVERLOAD(19)
|
||||
LLVM_DEFINE_OVERLOAD(20)
|
||||
LLVM_DEFINE_OVERLOAD(21)
|
||||
LLVM_DEFINE_OVERLOAD(22)
|
||||
LLVM_DEFINE_OVERLOAD(23)
|
||||
LLVM_DEFINE_OVERLOAD(24)
|
||||
LLVM_DEFINE_OVERLOAD(25)
|
||||
LLVM_DEFINE_OVERLOAD(26)
|
||||
LLVM_DEFINE_OVERLOAD(27)
|
||||
LLVM_DEFINE_OVERLOAD(28)
|
||||
LLVM_DEFINE_OVERLOAD(29)
|
||||
LLVM_DEFINE_OVERLOAD(30)
|
||||
LLVM_DEFINE_OVERLOAD(31)
|
||||
LLVM_DEFINE_OVERLOAD(32)
|
||||
#undef LLVM_DEFINE_OVERLOAD
|
||||
};
|
||||
|
||||
template <typename ResultT, typename Param0T, typename ArgT,
|
||||
ResultT (*Func)(Param0T, ArrayRef<const ArgT *>)>
|
||||
struct VariadicFunction1 {
|
||||
ResultT operator()(Param0T P0) const {
|
||||
return Func(P0, ArrayRef<const ArgT *>());
|
||||
}
|
||||
|
||||
#define LLVM_DEFINE_OVERLOAD(N) \
|
||||
ResultT operator()(Param0T P0, LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
|
||||
const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
|
||||
return Func(P0, makeArrayRef(Args)); \
|
||||
}
|
||||
LLVM_DEFINE_OVERLOAD(1)
|
||||
LLVM_DEFINE_OVERLOAD(2)
|
||||
LLVM_DEFINE_OVERLOAD(3)
|
||||
LLVM_DEFINE_OVERLOAD(4)
|
||||
LLVM_DEFINE_OVERLOAD(5)
|
||||
LLVM_DEFINE_OVERLOAD(6)
|
||||
LLVM_DEFINE_OVERLOAD(7)
|
||||
LLVM_DEFINE_OVERLOAD(8)
|
||||
LLVM_DEFINE_OVERLOAD(9)
|
||||
LLVM_DEFINE_OVERLOAD(10)
|
||||
LLVM_DEFINE_OVERLOAD(11)
|
||||
LLVM_DEFINE_OVERLOAD(12)
|
||||
LLVM_DEFINE_OVERLOAD(13)
|
||||
LLVM_DEFINE_OVERLOAD(14)
|
||||
LLVM_DEFINE_OVERLOAD(15)
|
||||
LLVM_DEFINE_OVERLOAD(16)
|
||||
LLVM_DEFINE_OVERLOAD(17)
|
||||
LLVM_DEFINE_OVERLOAD(18)
|
||||
LLVM_DEFINE_OVERLOAD(19)
|
||||
LLVM_DEFINE_OVERLOAD(20)
|
||||
LLVM_DEFINE_OVERLOAD(21)
|
||||
LLVM_DEFINE_OVERLOAD(22)
|
||||
LLVM_DEFINE_OVERLOAD(23)
|
||||
LLVM_DEFINE_OVERLOAD(24)
|
||||
LLVM_DEFINE_OVERLOAD(25)
|
||||
LLVM_DEFINE_OVERLOAD(26)
|
||||
LLVM_DEFINE_OVERLOAD(27)
|
||||
LLVM_DEFINE_OVERLOAD(28)
|
||||
LLVM_DEFINE_OVERLOAD(29)
|
||||
LLVM_DEFINE_OVERLOAD(30)
|
||||
LLVM_DEFINE_OVERLOAD(31)
|
||||
LLVM_DEFINE_OVERLOAD(32)
|
||||
#undef LLVM_DEFINE_OVERLOAD
|
||||
};
|
||||
|
||||
template <typename ResultT, typename Param0T, typename Param1T, typename ArgT,
|
||||
ResultT (*Func)(Param0T, Param1T, ArrayRef<const ArgT *>)>
|
||||
struct VariadicFunction2 {
|
||||
ResultT operator()(Param0T P0, Param1T P1) const {
|
||||
return Func(P0, P1, ArrayRef<const ArgT *>());
|
||||
}
|
||||
|
||||
#define LLVM_DEFINE_OVERLOAD(N) \
|
||||
ResultT operator()(Param0T P0, Param1T P1, \
|
||||
LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
|
||||
const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
|
||||
return Func(P0, P1, makeAraryRef(Args)); \
|
||||
}
|
||||
LLVM_DEFINE_OVERLOAD(1)
|
||||
LLVM_DEFINE_OVERLOAD(2)
|
||||
LLVM_DEFINE_OVERLOAD(3)
|
||||
LLVM_DEFINE_OVERLOAD(4)
|
||||
LLVM_DEFINE_OVERLOAD(5)
|
||||
LLVM_DEFINE_OVERLOAD(6)
|
||||
LLVM_DEFINE_OVERLOAD(7)
|
||||
LLVM_DEFINE_OVERLOAD(8)
|
||||
LLVM_DEFINE_OVERLOAD(9)
|
||||
LLVM_DEFINE_OVERLOAD(10)
|
||||
LLVM_DEFINE_OVERLOAD(11)
|
||||
LLVM_DEFINE_OVERLOAD(12)
|
||||
LLVM_DEFINE_OVERLOAD(13)
|
||||
LLVM_DEFINE_OVERLOAD(14)
|
||||
LLVM_DEFINE_OVERLOAD(15)
|
||||
LLVM_DEFINE_OVERLOAD(16)
|
||||
LLVM_DEFINE_OVERLOAD(17)
|
||||
LLVM_DEFINE_OVERLOAD(18)
|
||||
LLVM_DEFINE_OVERLOAD(19)
|
||||
LLVM_DEFINE_OVERLOAD(20)
|
||||
LLVM_DEFINE_OVERLOAD(21)
|
||||
LLVM_DEFINE_OVERLOAD(22)
|
||||
LLVM_DEFINE_OVERLOAD(23)
|
||||
LLVM_DEFINE_OVERLOAD(24)
|
||||
LLVM_DEFINE_OVERLOAD(25)
|
||||
LLVM_DEFINE_OVERLOAD(26)
|
||||
LLVM_DEFINE_OVERLOAD(27)
|
||||
LLVM_DEFINE_OVERLOAD(28)
|
||||
LLVM_DEFINE_OVERLOAD(29)
|
||||
LLVM_DEFINE_OVERLOAD(30)
|
||||
LLVM_DEFINE_OVERLOAD(31)
|
||||
LLVM_DEFINE_OVERLOAD(32)
|
||||
#undef LLVM_DEFINE_OVERLOAD
|
||||
};
|
||||
|
||||
template <typename ResultT, typename Param0T, typename Param1T,
|
||||
typename Param2T, typename ArgT,
|
||||
ResultT (*Func)(Param0T, Param1T, Param2T, ArrayRef<const ArgT *>)>
|
||||
struct VariadicFunction3 {
|
||||
ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const {
|
||||
return Func(P0, P1, P2, ArrayRef<const ArgT *>());
|
||||
}
|
||||
|
||||
#define LLVM_DEFINE_OVERLOAD(N) \
|
||||
ResultT operator()(Param0T P0, Param1T P1, Param2T P2, \
|
||||
LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
|
||||
const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
|
||||
return Func(P0, P1, P2, makeArrayRef(Args)); \
|
||||
}
|
||||
LLVM_DEFINE_OVERLOAD(1)
|
||||
LLVM_DEFINE_OVERLOAD(2)
|
||||
LLVM_DEFINE_OVERLOAD(3)
|
||||
LLVM_DEFINE_OVERLOAD(4)
|
||||
LLVM_DEFINE_OVERLOAD(5)
|
||||
LLVM_DEFINE_OVERLOAD(6)
|
||||
LLVM_DEFINE_OVERLOAD(7)
|
||||
LLVM_DEFINE_OVERLOAD(8)
|
||||
LLVM_DEFINE_OVERLOAD(9)
|
||||
LLVM_DEFINE_OVERLOAD(10)
|
||||
LLVM_DEFINE_OVERLOAD(11)
|
||||
LLVM_DEFINE_OVERLOAD(12)
|
||||
LLVM_DEFINE_OVERLOAD(13)
|
||||
LLVM_DEFINE_OVERLOAD(14)
|
||||
LLVM_DEFINE_OVERLOAD(15)
|
||||
LLVM_DEFINE_OVERLOAD(16)
|
||||
LLVM_DEFINE_OVERLOAD(17)
|
||||
LLVM_DEFINE_OVERLOAD(18)
|
||||
LLVM_DEFINE_OVERLOAD(19)
|
||||
LLVM_DEFINE_OVERLOAD(20)
|
||||
LLVM_DEFINE_OVERLOAD(21)
|
||||
LLVM_DEFINE_OVERLOAD(22)
|
||||
LLVM_DEFINE_OVERLOAD(23)
|
||||
LLVM_DEFINE_OVERLOAD(24)
|
||||
LLVM_DEFINE_OVERLOAD(25)
|
||||
LLVM_DEFINE_OVERLOAD(26)
|
||||
LLVM_DEFINE_OVERLOAD(27)
|
||||
LLVM_DEFINE_OVERLOAD(28)
|
||||
LLVM_DEFINE_OVERLOAD(29)
|
||||
LLVM_DEFINE_OVERLOAD(30)
|
||||
LLVM_DEFINE_OVERLOAD(31)
|
||||
LLVM_DEFINE_OVERLOAD(32)
|
||||
#undef LLVM_DEFINE_OVERLOAD
|
||||
};
|
||||
|
||||
// Cleanup the macro namespace.
|
||||
#undef LLVM_COMMA_JOIN1
|
||||
#undef LLVM_COMMA_JOIN2
|
||||
#undef LLVM_COMMA_JOIN3
|
||||
#undef LLVM_COMMA_JOIN4
|
||||
#undef LLVM_COMMA_JOIN5
|
||||
#undef LLVM_COMMA_JOIN6
|
||||
#undef LLVM_COMMA_JOIN7
|
||||
#undef LLVM_COMMA_JOIN8
|
||||
#undef LLVM_COMMA_JOIN9
|
||||
#undef LLVM_COMMA_JOIN10
|
||||
#undef LLVM_COMMA_JOIN11
|
||||
#undef LLVM_COMMA_JOIN12
|
||||
#undef LLVM_COMMA_JOIN13
|
||||
#undef LLVM_COMMA_JOIN14
|
||||
#undef LLVM_COMMA_JOIN15
|
||||
#undef LLVM_COMMA_JOIN16
|
||||
#undef LLVM_COMMA_JOIN17
|
||||
#undef LLVM_COMMA_JOIN18
|
||||
#undef LLVM_COMMA_JOIN19
|
||||
#undef LLVM_COMMA_JOIN20
|
||||
#undef LLVM_COMMA_JOIN21
|
||||
#undef LLVM_COMMA_JOIN22
|
||||
#undef LLVM_COMMA_JOIN23
|
||||
#undef LLVM_COMMA_JOIN24
|
||||
#undef LLVM_COMMA_JOIN25
|
||||
#undef LLVM_COMMA_JOIN26
|
||||
#undef LLVM_COMMA_JOIN27
|
||||
#undef LLVM_COMMA_JOIN28
|
||||
#undef LLVM_COMMA_JOIN29
|
||||
#undef LLVM_COMMA_JOIN30
|
||||
#undef LLVM_COMMA_JOIN31
|
||||
#undef LLVM_COMMA_JOIN32
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_ADT_VARIADIC_FUNCTION_H
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
//===-- llvm/ADT/VectorExtras.h - Helpers for std::vector -------*- 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 helper functions which are useful for working with the
|
||||
// std::vector class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_VECTOREXTRAS_H
|
||||
#define LLVM_ADT_VECTOREXTRAS_H
|
||||
|
||||
#include <cstdarg>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// make_vector - Helper function which is useful for building temporary vectors
|
||||
/// to pass into type construction of CallInst ctors. This turns a null
|
||||
/// terminated list of pointers (or other value types) into a real live vector.
|
||||
///
|
||||
template<typename T>
|
||||
inline std::vector<T> make_vector(T A, ...) {
|
||||
va_list Args;
|
||||
va_start(Args, A);
|
||||
std::vector<T> Result;
|
||||
Result.push_back(A);
|
||||
while (T Val = va_arg(Args, T))
|
||||
Result.push_back(Val);
|
||||
va_end(Args);
|
||||
return Result;
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
102
contrib/llvm/include/llvm/ADT/edit_distance.h
Normal file
102
contrib/llvm/include/llvm/ADT/edit_distance.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
//===-- llvm/ADT/edit_distance.h - Array edit distance function --- 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 Levenshtein distance function that works for any two
|
||||
// sequences, with each element of each sequence being analogous to a character
|
||||
// in a string.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_EDIT_DISTANCE_H
|
||||
#define LLVM_ADT_EDIT_DISTANCE_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief Determine the edit distance between two sequences.
|
||||
///
|
||||
/// \param FromArray the first sequence to compare.
|
||||
///
|
||||
/// \param ToArray the second sequence to compare.
|
||||
///
|
||||
/// \param AllowReplacements whether to allow element replacements (change one
|
||||
/// element into another) as a single operation, rather than as two operations
|
||||
/// (an insertion and a removal).
|
||||
///
|
||||
/// \param MaxEditDistance If non-zero, the maximum edit distance that this
|
||||
/// routine is allowed to compute. If the edit distance will exceed that
|
||||
/// maximum, returns \c MaxEditDistance+1.
|
||||
///
|
||||
/// \returns the minimum number of element insertions, removals, or (if
|
||||
/// \p AllowReplacements is \c true) replacements needed to transform one of
|
||||
/// the given sequences into the other. If zero, the sequences are identical.
|
||||
template<typename T>
|
||||
unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray,
|
||||
bool AllowReplacements = true,
|
||||
unsigned MaxEditDistance = 0) {
|
||||
// The algorithm implemented below is the "classic"
|
||||
// dynamic-programming algorithm for computing the Levenshtein
|
||||
// distance, which is described here:
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Levenshtein_distance
|
||||
//
|
||||
// Although the algorithm is typically described using an m x n
|
||||
// array, only two rows are used at a time, so this implemenation
|
||||
// just keeps two separate vectors for those two rows.
|
||||
typename ArrayRef<T>::size_type m = FromArray.size();
|
||||
typename ArrayRef<T>::size_type n = ToArray.size();
|
||||
|
||||
const unsigned SmallBufferSize = 64;
|
||||
unsigned SmallBuffer[SmallBufferSize];
|
||||
llvm::OwningArrayPtr<unsigned> Allocated;
|
||||
unsigned *Previous = SmallBuffer;
|
||||
if (2*(n + 1) > SmallBufferSize) {
|
||||
Previous = new unsigned [2*(n+1)];
|
||||
Allocated.reset(Previous);
|
||||
}
|
||||
unsigned *Current = Previous + (n + 1);
|
||||
|
||||
for (unsigned i = 0; i <= n; ++i)
|
||||
Previous[i] = i;
|
||||
|
||||
for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) {
|
||||
Current[0] = y;
|
||||
unsigned BestThisRow = Current[0];
|
||||
|
||||
for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) {
|
||||
if (AllowReplacements) {
|
||||
Current[x] = std::min(
|
||||
Previous[x-1] + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u),
|
||||
std::min(Current[x-1], Previous[x])+1);
|
||||
}
|
||||
else {
|
||||
if (FromArray[y-1] == ToArray[x-1]) Current[x] = Previous[x-1];
|
||||
else Current[x] = std::min(Current[x-1], Previous[x]) + 1;
|
||||
}
|
||||
BestThisRow = std::min(BestThisRow, Current[x]);
|
||||
}
|
||||
|
||||
if (MaxEditDistance && BestThisRow > MaxEditDistance)
|
||||
return MaxEditDistance + 1;
|
||||
|
||||
unsigned *tmp = Current;
|
||||
Current = Previous;
|
||||
Previous = tmp;
|
||||
}
|
||||
|
||||
unsigned Result = Previous[n];
|
||||
return Result;
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
|
@ -652,10 +652,6 @@ struct ilist : public iplist<NodeTy> {
|
|||
void push_front(const NodeTy &val) { insert(this->begin(), val); }
|
||||
void push_back(const NodeTy &val) { insert(this->end(), val); }
|
||||
|
||||
// Special forms of insert...
|
||||
template<class InIt> void insert(iterator where, InIt first, InIt last) {
|
||||
for (; first != last; ++first) insert(where, *first);
|
||||
}
|
||||
void insert(iterator where, size_type count, const NodeTy &val) {
|
||||
for (; count != 0; --count) insert(where, val);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ public:
|
|||
}
|
||||
|
||||
/// doesAccessArgPointees - Return true if functions with the specified
|
||||
/// behavior are known to potentially read or write from objects pointed
|
||||
/// behavior are known to potentially read or write from objects pointed
|
||||
/// to be their pointer-typed arguments (with arbitrary offsets).
|
||||
///
|
||||
static bool doesAccessArgPointees(ModRefBehavior MRB) {
|
||||
|
|
@ -568,6 +568,11 @@ bool isNoAliasCall(const Value *V);
|
|||
///
|
||||
bool isIdentifiedObject(const Value *V);
|
||||
|
||||
/// isKnownNonNull - Return true if this pointer couldn't possibly be null by
|
||||
/// its definition. This returns true for allocas, non-extern-weak globals and
|
||||
/// byval arguments.
|
||||
bool isKnownNonNull(const Value *V);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ private:
|
|||
}
|
||||
void setVolatile() { Volatile = true; }
|
||||
|
||||
public:
|
||||
/// aliasesPointer - Return true if the specified pointer "may" (or must)
|
||||
/// alias one of the members in the set.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
|
@ -41,7 +40,7 @@ class MachineBlockFrequencyInfo;
|
|||
template<class BlockT, class FunctionT, class BlockProbInfoT>
|
||||
class BlockFrequencyImpl {
|
||||
|
||||
DenseMap<BlockT *, BlockFrequency> Freqs;
|
||||
DenseMap<const BlockT *, BlockFrequency> Freqs;
|
||||
|
||||
BlockProbInfoT *BPI;
|
||||
|
||||
|
|
@ -52,15 +51,16 @@ class BlockFrequencyImpl {
|
|||
const uint32_t EntryFreq;
|
||||
|
||||
std::string getBlockName(BasicBlock *BB) const {
|
||||
return BB->getNameStr();
|
||||
return BB->getName().str();
|
||||
}
|
||||
|
||||
std::string getBlockName(MachineBasicBlock *MBB) const {
|
||||
std::stringstream ss;
|
||||
std::string str;
|
||||
raw_string_ostream ss(str);
|
||||
ss << "BB#" << MBB->getNumber();
|
||||
|
||||
if (const BasicBlock *BB = MBB->getBasicBlock())
|
||||
ss << " derived from LLVM BB " << BB->getNameStr();
|
||||
ss << " derived from LLVM BB " << BB->getName();
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
|
@ -308,8 +308,9 @@ class BlockFrequencyImpl {
|
|||
|
||||
public:
|
||||
/// getBlockFreq - Return block frequency. Return 0 if we don't have it.
|
||||
BlockFrequency getBlockFreq(BlockT *BB) const {
|
||||
typename DenseMap<BlockT *, BlockFrequency>::const_iterator I = Freqs.find(BB);
|
||||
BlockFrequency getBlockFreq(const BlockT *BB) const {
|
||||
typename DenseMap<const BlockT *, BlockFrequency>::const_iterator
|
||||
I = Freqs.find(BB);
|
||||
if (I != Freqs.end())
|
||||
return I->second;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public:
|
|||
/// that we should not rely on the value itself, but only on the comparison to
|
||||
/// the other block frequencies. We do this to avoid using of floating points.
|
||||
///
|
||||
BlockFrequency getBlockFreq(BasicBlock *BB) const;
|
||||
BlockFrequency getBlockFreq(const BasicBlock *BB) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,13 +17,82 @@
|
|||
#include "llvm/InitializePasses.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Support/BranchProbability.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LoopInfo;
|
||||
class raw_ostream;
|
||||
|
||||
/// \brief Analysis pass providing branch probability information.
|
||||
///
|
||||
/// This is a function analysis pass which provides information on the relative
|
||||
/// probabilities of each "edge" in the function's CFG where such an edge is
|
||||
/// defined by a pair of basic blocks. The probability for a given block and
|
||||
/// a successor block are always relative to the probabilities of the other
|
||||
/// successor blocks. Another way of looking at it is that the probabilities
|
||||
/// for a given block B and each of its successors should sum to exactly
|
||||
/// one (100%).
|
||||
class BranchProbabilityInfo : public FunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BranchProbabilityInfo() : FunctionPass(ID) {
|
||||
initializeBranchProbabilityInfoPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
bool runOnFunction(Function &F);
|
||||
void print(raw_ostream &OS, const Module *M = 0) const;
|
||||
|
||||
/// \brief 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
|
||||
/// leaving the 'Src' block. The returned probability is never zero, and can
|
||||
/// only be one if the source block has only one successor.
|
||||
BranchProbability getEdgeProbability(const BasicBlock *Src,
|
||||
const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief 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.
|
||||
///
|
||||
/// Given a basic block, look through its successors and if one exists for
|
||||
/// which \see isEdgeHot would return true, return that successor block.
|
||||
BasicBlock *getHotSucc(BasicBlock *BB) const;
|
||||
|
||||
/// \brief 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
|
||||
/// returned.
|
||||
raw_ostream &printEdgeProbability(raw_ostream &OS, const BasicBlock *Src,
|
||||
const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief Get the raw edge weight calculated for the block pair.
|
||||
///
|
||||
/// This returns the raw edge weight. It is guaranteed to fall between 1 and
|
||||
/// UINT32_MAX. Note that the raw edge weight is not meaningful in isolation.
|
||||
/// This interface should be very carefully, and primarily by routines that
|
||||
/// are updating the analysis by later calling setEdgeWeight.
|
||||
uint32_t getEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst) const;
|
||||
|
||||
/// \brief Set the raw edge weight for the block pair.
|
||||
///
|
||||
/// This allows a pass to explicitly set the edge weight for a block. It can
|
||||
/// be used when updating the CFG to update and preserve the branch
|
||||
/// probability information. Read the implementation of how these edge
|
||||
/// weights are calculated carefully before using!
|
||||
void setEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst,
|
||||
uint32_t Weight);
|
||||
|
||||
private:
|
||||
typedef std::pair<const BasicBlock *, const BasicBlock *> Edge;
|
||||
|
||||
// Default weight value. Used when we don't have information about the edge.
|
||||
// TODO: DEFAULT_WEIGHT makes sense during static predication, when none of
|
||||
|
|
@ -33,49 +102,26 @@ class BranchProbabilityInfo : public FunctionPass {
|
|||
// weight to just "inherit" the non-zero weight of an adjacent successor.
|
||||
static const uint32_t DEFAULT_WEIGHT = 16;
|
||||
|
||||
typedef std::pair<const BasicBlock *, const BasicBlock *> Edge;
|
||||
|
||||
DenseMap<Edge, uint32_t> Weights;
|
||||
|
||||
// Get sum of the block successors' weights.
|
||||
/// \brief Handle to the LoopInfo analysis.
|
||||
LoopInfo *LI;
|
||||
|
||||
/// \brief Track the last function we run over for printing.
|
||||
Function *LastF;
|
||||
|
||||
/// \brief Track the set of blocks directly succeeded by a returning block.
|
||||
SmallPtrSet<BasicBlock *, 16> PostDominatedByUnreachable;
|
||||
|
||||
/// \brief Get sum of the block successors' weights.
|
||||
uint32_t getSumForBlock(const BasicBlock *BB) const;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BranchProbabilityInfo() : FunctionPass(ID) {
|
||||
initializeBranchProbabilityInfoPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
bool runOnFunction(Function &F);
|
||||
|
||||
// Returned value is between 1 and UINT32_MAX. Look at
|
||||
// BranchProbabilityInfo.cpp for details.
|
||||
uint32_t getEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst) const;
|
||||
|
||||
// Look at BranchProbabilityInfo.cpp for details. Use it with caution!
|
||||
void setEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst,
|
||||
uint32_t Weight);
|
||||
|
||||
// A 'Hot' edge is an edge which probability is >= 80%.
|
||||
bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const;
|
||||
|
||||
// Return a hot successor for the block BB or null if there isn't one.
|
||||
BasicBlock *getHotSucc(BasicBlock *BB) const;
|
||||
|
||||
// Return a probability as a fraction between 0 (0% probability) and
|
||||
// 1 (100% probability), however the value is never equal to 0, and can be 1
|
||||
// only iff SRC block has only one successor.
|
||||
BranchProbability getEdgeProbability(const BasicBlock *Src,
|
||||
const BasicBlock *Dst) const;
|
||||
|
||||
// Print value between 0 (0% probability) and 1 (100% probability),
|
||||
// however the value is never equal to 0, and can be 1 only iff SRC block
|
||||
// has only one successor.
|
||||
raw_ostream &printEdgeProbability(raw_ostream &OS, BasicBlock *Src,
|
||||
BasicBlock *Dst) const;
|
||||
bool calcUnreachableHeuristics(BasicBlock *BB);
|
||||
bool calcMetadataWeights(BasicBlock *BB);
|
||||
bool calcPointerHeuristics(BasicBlock *BB);
|
||||
bool calcLoopBranchHeuristics(BasicBlock *BB);
|
||||
bool calcZeroHeuristics(BasicBlock *BB);
|
||||
bool calcFloatingPointHeuristics(BasicBlock *BB);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
|
|||
DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
|
||||
|
||||
static std::string getGraphName(const Function *F) {
|
||||
return "CFG for '" + F->getNameStr() + "' function";
|
||||
return "CFG for '" + F->getName().str() + "' function";
|
||||
}
|
||||
|
||||
static std::string getSimpleNodeLabel(const BasicBlock *Node,
|
||||
const Function *Graph) {
|
||||
const Function *) {
|
||||
if (!Node->getName().empty())
|
||||
return Node->getNameStr();
|
||||
return Node->getName().str();
|
||||
|
||||
std::string Str;
|
||||
raw_string_ostream OS(Str);
|
||||
|
|
@ -45,7 +45,7 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
|
|||
}
|
||||
|
||||
static std::string getCompleteNodeLabel(const BasicBlock *Node,
|
||||
const Function *Graph) {
|
||||
const Function *) {
|
||||
std::string Str;
|
||||
raw_string_ostream OS(Str);
|
||||
|
||||
|
|
@ -95,7 +95,9 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
|
|||
|
||||
std::string Str;
|
||||
raw_string_ostream OS(Str);
|
||||
OS << SI->getCaseValue(SuccNo)->getValue();
|
||||
SwitchInst::ConstCaseIt Case =
|
||||
SwitchInst::ConstCaseIt::fromSuccessorIndex(SI, SuccNo);
|
||||
OS << Case.getCaseValue()->getValue();
|
||||
return OS.str();
|
||||
}
|
||||
return "";
|
||||
|
|
|
|||
|
|
@ -14,9 +14,12 @@
|
|||
#ifndef LLVM_ANALYSIS_CAPTURETRACKING_H
|
||||
#define LLVM_ANALYSIS_CAPTURETRACKING_H
|
||||
|
||||
namespace llvm {
|
||||
class Value;
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
|
||||
namespace llvm {
|
||||
/// PointerMayBeCaptured - Return true if this pointer value may be captured
|
||||
/// by the enclosing function (which is required to exist). This routine can
|
||||
/// be expensive, so consider caching the results. The boolean ReturnCaptures
|
||||
|
|
@ -28,6 +31,33 @@ namespace llvm {
|
|||
bool ReturnCaptures,
|
||||
bool StoreCaptures);
|
||||
|
||||
/// This callback is used in conjunction with PointerMayBeCaptured. In
|
||||
/// addition to the interface here, you'll need to provide your own getters
|
||||
/// to see whether anything was captured.
|
||||
struct CaptureTracker {
|
||||
virtual ~CaptureTracker();
|
||||
|
||||
/// tooManyUses - The depth of traversal has breached a limit. There may be
|
||||
/// capturing instructions that will not be passed into captured().
|
||||
virtual void tooManyUses() = 0;
|
||||
|
||||
/// shouldExplore - This is the use of a value derived from the pointer.
|
||||
/// To prune the search (ie., assume that none of its users could possibly
|
||||
/// capture) return false. To search it, return true.
|
||||
///
|
||||
/// U->getUser() is always an Instruction.
|
||||
virtual bool shouldExplore(Use *U) = 0;
|
||||
|
||||
/// captured - Information about the pointer was captured by the user of
|
||||
/// use U. Return true to stop the traversal or false to continue looking
|
||||
/// for more capturing instructions.
|
||||
virtual bool captured(Use *U) = 0;
|
||||
};
|
||||
|
||||
/// PointerMayBeCaptured - Visit the value and the values derived from it and
|
||||
/// find values which appear to be capturing the pointer value. This feeds
|
||||
/// results into and is controlled by the CaptureTracker object.
|
||||
void PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker);
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//===- CodeMetrics.h - Measures the weight of a function---------*- C++ -*-===//
|
||||
//===- CodeMetrics.h - Code cost measurements -------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
|
@ -18,80 +18,75 @@
|
|||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BasicBlock;
|
||||
class Function;
|
||||
class Instruction;
|
||||
class TargetData;
|
||||
class Value;
|
||||
|
||||
// CodeMetrics - Calculate size and a few similar metrics for a set of
|
||||
// basic blocks.
|
||||
/// \brief Check whether an instruction is likely to be "free" when lowered.
|
||||
bool isInstructionFree(const Instruction *I, const TargetData *TD = 0);
|
||||
|
||||
/// \brief Check whether a call will lower to something small.
|
||||
///
|
||||
/// This tests checks whether calls to this function will lower to something
|
||||
/// significantly cheaper than a traditional call, often a single
|
||||
/// instruction.
|
||||
bool callIsSmall(const Function *F);
|
||||
|
||||
/// \brief Utility to calculate the size and a few similar metrics for a set
|
||||
/// of basic blocks.
|
||||
struct CodeMetrics {
|
||||
/// NeverInline - True if this callee should never be inlined into a
|
||||
/// caller.
|
||||
// bool NeverInline;
|
||||
/// \brief True if this function contains a call to setjmp or other functions
|
||||
/// with attribute "returns twice" without having the attribute itself.
|
||||
bool exposesReturnsTwice;
|
||||
|
||||
// True if this function contains a call to setjmp or _setjmp
|
||||
bool callsSetJmp;
|
||||
|
||||
// True if this function calls itself
|
||||
/// \brief True if this function calls itself.
|
||||
bool isRecursive;
|
||||
|
||||
// True if this function contains one or more indirect branches
|
||||
/// \brief True if this function contains one or more indirect branches.
|
||||
bool containsIndirectBr;
|
||||
|
||||
/// usesDynamicAlloca - True if this function calls alloca (in the C sense).
|
||||
/// \brief True if this function calls alloca (in the C sense).
|
||||
bool usesDynamicAlloca;
|
||||
|
||||
/// NumInsts, NumBlocks - Keep track of how large each function is, which
|
||||
/// is used to estimate the code size cost of inlining it.
|
||||
unsigned NumInsts, NumBlocks;
|
||||
/// \brief Number of instructions in the analyzed blocks.
|
||||
unsigned NumInsts;
|
||||
|
||||
/// NumBBInsts - Keeps track of basic block code size estimates.
|
||||
/// \brief Number of analyzed blocks.
|
||||
unsigned NumBlocks;
|
||||
|
||||
/// \brief Keeps track of basic block code size estimates.
|
||||
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
|
||||
|
||||
/// NumCalls - Keep track of the number of calls to 'big' functions.
|
||||
/// \brief Keep track of the number of calls to 'big' functions.
|
||||
unsigned NumCalls;
|
||||
|
||||
/// NumInlineCandidates - Keep track of the number of calls to internal
|
||||
/// functions with only a single caller. These are likely targets for
|
||||
/// future inlining, likely exposed by interleaved devirtualization.
|
||||
/// \brief 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;
|
||||
|
||||
/// NumVectorInsts - Keep track of how many instructions produce vector
|
||||
/// values. The inliner is being more aggressive with inlining vector
|
||||
/// kernels.
|
||||
/// \brief How many instructions produce vector values.
|
||||
///
|
||||
/// The inliner is more aggressive with inlining vector kernels.
|
||||
unsigned NumVectorInsts;
|
||||
|
||||
/// NumRets - Keep track of how many Ret instructions the block contains.
|
||||
/// \brief How many 'ret' instructions the blocks contain.
|
||||
unsigned NumRets;
|
||||
|
||||
CodeMetrics() : callsSetJmp(false), isRecursive(false),
|
||||
CodeMetrics() : exposesReturnsTwice(false), isRecursive(false),
|
||||
containsIndirectBr(false), usesDynamicAlloca(false),
|
||||
NumInsts(0), NumBlocks(0), NumCalls(0),
|
||||
NumInlineCandidates(0), NumVectorInsts(0),
|
||||
NumRets(0) {}
|
||||
|
||||
/// analyzeBasicBlock - Add information about the specified basic block
|
||||
/// to the current structure.
|
||||
/// \brief Add information about a block to the current state.
|
||||
void analyzeBasicBlock(const BasicBlock *BB, const TargetData *TD = 0);
|
||||
|
||||
/// analyzeFunction - Add information about the specified function
|
||||
/// to the current structure.
|
||||
/// \brief Add information about a function to the current state.
|
||||
void analyzeFunction(Function *F, const TargetData *TD = 0);
|
||||
|
||||
/// CountCodeReductionForConstant - Figure out an approximation for how
|
||||
/// many instructions will be constant folded if the specified value is
|
||||
/// constant.
|
||||
unsigned CountCodeReductionForConstant(Value *V);
|
||||
|
||||
/// CountBonusForConstant - Figure out an approximation for how much
|
||||
/// per-call performance boost we can expect if the specified value is
|
||||
/// constant.
|
||||
unsigned CountBonusForConstant(Value *V);
|
||||
|
||||
/// CountCodeReductionForAlloca - Figure out an approximation of how much
|
||||
/// smaller the function will be if it is inlined into a context where an
|
||||
/// argument becomes an alloca.
|
||||
///
|
||||
unsigned CountCodeReductionForAlloca(Value *V);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ namespace llvm {
|
|||
class ConstantExpr;
|
||||
class Instruction;
|
||||
class TargetData;
|
||||
class TargetLibraryInfo;
|
||||
class Function;
|
||||
class Type;
|
||||
template<typename T>
|
||||
|
|
@ -35,13 +36,15 @@ namespace llvm {
|
|||
/// Note that this fails if not all of the operands are constant. Otherwise,
|
||||
/// this function can only fail when attempting to fold instructions like loads
|
||||
/// and stores, which have no constant expression form.
|
||||
Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0);
|
||||
Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldConstantExpression - Attempt to fold the constant expression
|
||||
/// using the specified TargetData. If successful, the constant result is
|
||||
/// result is returned, if not, null is returned.
|
||||
Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
|
||||
const TargetData *TD = 0);
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
|
||||
/// specified operands. If successful, the constant result is returned, if not,
|
||||
|
|
@ -51,7 +54,8 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
|
|||
///
|
||||
Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
|
||||
ArrayRef<Constant *> Ops,
|
||||
const TargetData *TD = 0);
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare
|
||||
/// instruction (icmp/fcmp) with the specified operands. If it fails, it
|
||||
|
|
@ -59,7 +63,8 @@ Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
|
|||
///
|
||||
Constant *ConstantFoldCompareInstOperands(unsigned Predicate,
|
||||
Constant *LHS, Constant *RHS,
|
||||
const TargetData *TD = 0);
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
|
||||
/// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue
|
||||
/// instruction with the specified operands and indices. The constant result is
|
||||
|
|
@ -76,15 +81,22 @@ Constant *ConstantFoldLoadFromConstPtr(Constant *C, const TargetData *TD = 0);
|
|||
/// getelementptr constantexpr, return the constant value being addressed by the
|
||||
/// constant expression, or null if something is funny and we can't decide.
|
||||
Constant *ConstantFoldLoadThroughGEPConstantExpr(Constant *C, ConstantExpr *CE);
|
||||
|
||||
|
||||
/// ConstantFoldLoadThroughGEPIndices - Given a constant and getelementptr
|
||||
/// indices (with an *implied* zero pointer index that is not in the list),
|
||||
/// return the constant value being addressed by a virtual load, or null if
|
||||
/// something is funny and we can't decide.
|
||||
Constant *ConstantFoldLoadThroughGEPIndices(Constant *C,
|
||||
ArrayRef<Constant*> Indices);
|
||||
|
||||
/// canConstantFoldCallTo - Return true if its even possible to fold a call to
|
||||
/// the specified function.
|
||||
bool canConstantFoldCallTo(const Function *F);
|
||||
|
||||
/// ConstantFoldCall - Attempt to constant fold a call to the specified function
|
||||
/// with the specified arguments, returning null if unsuccessful.
|
||||
Constant *
|
||||
ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands);
|
||||
Constant *ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands,
|
||||
const TargetLibraryInfo *TLI = 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ namespace llvm {
|
|||
class DISubprogram;
|
||||
class DITemplateTypeParameter;
|
||||
class DITemplateValueParameter;
|
||||
class DIObjCProperty;
|
||||
|
||||
class DIBuilder {
|
||||
private:
|
||||
|
|
@ -190,6 +191,39 @@ namespace llvm {
|
|||
StringRef PropertySetterName = StringRef(),
|
||||
unsigned PropertyAttributes = 0);
|
||||
|
||||
/// createObjCIVar - Create debugging information entry for Objective-C
|
||||
/// instance variable.
|
||||
/// @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 Ty Parent type.
|
||||
/// @param Property Property associated with this ivar.
|
||||
DIType createObjCIVar(StringRef Name, DIFile File,
|
||||
unsigned LineNo, uint64_t SizeInBits,
|
||||
uint64_t AlignInBits, uint64_t OffsetInBits,
|
||||
unsigned Flags, DIType Ty,
|
||||
MDNode *PropertyNode);
|
||||
|
||||
/// createObjCProperty - Create debugging information entry for Objective-C
|
||||
/// property.
|
||||
/// @param Name Property name.
|
||||
/// @param File File where this property is defined.
|
||||
/// @param LineNumber Line number.
|
||||
/// @param GetterName Name of the Objective C property getter selector.
|
||||
/// @param SetterName Name of the Objective C property setter selector.
|
||||
/// @param PropertyAttributes Objective C property attributes.
|
||||
/// @param Ty Type.
|
||||
DIObjCProperty createObjCProperty(StringRef Name,
|
||||
DIFile File, unsigned LineNumber,
|
||||
StringRef GetterName,
|
||||
StringRef SetterName,
|
||||
unsigned PropertyAttributes,
|
||||
DIType Ty);
|
||||
|
||||
/// createClassType - Create debugging information entry for a class.
|
||||
/// @param Scope Scope in which this class is defined.
|
||||
/// @param Name class name.
|
||||
|
|
@ -313,6 +347,10 @@ namespace llvm {
|
|||
DIType createTemporaryType();
|
||||
DIType createTemporaryType(DIFile F);
|
||||
|
||||
/// createForwardDecl - Create a temporary forward-declared type.
|
||||
DIType createForwardDecl(unsigned Tag, StringRef Name, DIFile F,
|
||||
unsigned Line, unsigned RuntimeLang = 0);
|
||||
|
||||
/// retainType - Retain DIType in a module even if it is not referenced
|
||||
/// through debug info anchors.
|
||||
void retainType(DIType T);
|
||||
|
|
@ -407,6 +445,7 @@ namespace llvm {
|
|||
/// @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. is this function prototyped or not.
|
||||
/// This flags are used to emit dwarf attributes.
|
||||
/// @param isOptimized True if optimization is ON.
|
||||
|
|
@ -417,6 +456,7 @@ namespace llvm {
|
|||
DIFile File, unsigned LineNo,
|
||||
DIType Ty, bool isLocalToUnit,
|
||||
bool isDefinition,
|
||||
unsigned ScopeLine,
|
||||
unsigned Flags = 0,
|
||||
bool isOptimized = false,
|
||||
Function *Fn = 0,
|
||||
|
|
@ -470,7 +510,7 @@ namespace llvm {
|
|||
/// @param Scope Lexical block.
|
||||
/// @param File Source file.
|
||||
DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope,
|
||||
DIFile File);
|
||||
DIFile File);
|
||||
|
||||
/// createLexicalBlock - This creates a descriptor for a lexical block
|
||||
/// with the specified parent context.
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ struct DOTGraphTraitsViewer : public FunctionPass {
|
|||
std::string Title, GraphName;
|
||||
Graph = &getAnalysis<Analysis>();
|
||||
GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
|
||||
Title = GraphName + " for '" + F.getNameStr() + "' function";
|
||||
Title = GraphName + " for '" + F.getName().str() + "' function";
|
||||
ViewGraph(Graph, Name, Simple, Title);
|
||||
|
||||
return false;
|
||||
|
|
@ -55,7 +55,7 @@ struct DOTGraphTraitsPrinter : public FunctionPass {
|
|||
|
||||
virtual bool runOnFunction(Function &F) {
|
||||
Analysis *Graph;
|
||||
std::string Filename = Name + "." + F.getNameStr() + ".dot";
|
||||
std::string Filename = Name + "." + F.getName().str() + ".dot";
|
||||
errs() << "Writing '" << Filename << "'...";
|
||||
|
||||
std::string ErrorInfo;
|
||||
|
|
@ -64,7 +64,7 @@ struct DOTGraphTraitsPrinter : public FunctionPass {
|
|||
|
||||
std::string Title, GraphName;
|
||||
GraphName = DOTGraphTraits<Analysis*>::getGraphName(Graph);
|
||||
Title = GraphName + " for '" + F.getNameStr() + "' function";
|
||||
Title = GraphName + " for '" + F.getName().str() + "' function";
|
||||
|
||||
if (ErrorInfo.empty())
|
||||
WriteGraph(File, Graph, Simple, Title);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ namespace llvm {
|
|||
class DILexicalBlockFile;
|
||||
class DIVariable;
|
||||
class DIType;
|
||||
class DIObjCProperty;
|
||||
|
||||
/// DIDescriptor - A thin wraper around MDNode to access encoded debug info.
|
||||
/// This should not be stored in a container, because underly MDNode may
|
||||
|
|
@ -128,6 +129,7 @@ namespace llvm {
|
|||
bool isUnspecifiedParameter() const;
|
||||
bool isTemplateTypeParameter() const;
|
||||
bool isTemplateValueParameter() const;
|
||||
bool isObjCProperty() const;
|
||||
};
|
||||
|
||||
/// DISubrange - This is used to represent ranges, for array bounds.
|
||||
|
|
@ -135,8 +137,8 @@ namespace llvm {
|
|||
public:
|
||||
explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {}
|
||||
|
||||
int64_t getLo() const { return (int64_t)getUInt64Field(1); }
|
||||
int64_t getHi() const { return (int64_t)getUInt64Field(2); }
|
||||
uint64_t getLo() const { return getUInt64Field(1); }
|
||||
uint64_t getHi() const { return getUInt64Field(2); }
|
||||
};
|
||||
|
||||
/// DIArray - This descriptor holds an array of descriptors.
|
||||
|
|
@ -153,6 +155,7 @@ namespace llvm {
|
|||
|
||||
/// DIScope - A base class for various scopes.
|
||||
class DIScope : public DIDescriptor {
|
||||
virtual void anchor();
|
||||
public:
|
||||
explicit DIScope(const MDNode *N = 0) : DIDescriptor (N) {}
|
||||
virtual ~DIScope() {}
|
||||
|
|
@ -163,6 +166,7 @@ namespace llvm {
|
|||
|
||||
/// DICompileUnit - A wrapper for a compile unit.
|
||||
class DICompileUnit : public DIScope {
|
||||
virtual void anchor();
|
||||
public:
|
||||
explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {}
|
||||
|
||||
|
|
@ -202,6 +206,7 @@ namespace llvm {
|
|||
|
||||
/// DIFile - This is a wrapper for a file.
|
||||
class DIFile : public DIScope {
|
||||
virtual void anchor();
|
||||
public:
|
||||
explicit DIFile(const MDNode *N = 0) : DIScope(N) {
|
||||
if (DbgNode && !isFile())
|
||||
|
|
@ -230,7 +235,7 @@ namespace llvm {
|
|||
/// FIXME: Types should be factored much better so that CV qualifiers and
|
||||
/// others do not require a huge and empty descriptor full of zeros.
|
||||
class DIType : public DIScope {
|
||||
public:
|
||||
virtual void anchor();
|
||||
protected:
|
||||
// This ctor is used when the Tag has already been validated by a derived
|
||||
// ctor.
|
||||
|
|
@ -240,7 +245,6 @@ namespace llvm {
|
|||
|
||||
/// Verify - Verify that a type descriptor is well formed.
|
||||
bool Verify() const;
|
||||
public:
|
||||
explicit DIType(const MDNode *N);
|
||||
explicit DIType() {}
|
||||
virtual ~DIType() {}
|
||||
|
|
@ -320,6 +324,7 @@ namespace llvm {
|
|||
|
||||
/// DIBasicType - A basic type, like 'int' or 'float'.
|
||||
class DIBasicType : public DIType {
|
||||
virtual void anchor();
|
||||
public:
|
||||
explicit DIBasicType(const MDNode *N = 0) : DIType(N) {}
|
||||
|
||||
|
|
@ -338,6 +343,7 @@ namespace llvm {
|
|||
/// DIDerivedType - A simple derived type, like a const qualified type,
|
||||
/// a typedef, a pointer or reference, etc.
|
||||
class DIDerivedType : public DIType {
|
||||
virtual void anchor();
|
||||
protected:
|
||||
explicit DIDerivedType(const MDNode *N, bool, bool)
|
||||
: DIType(N, true, true) {}
|
||||
|
|
@ -351,29 +357,45 @@ namespace llvm {
|
|||
/// return base type size.
|
||||
uint64_t getOriginalTypeSize() const;
|
||||
|
||||
StringRef getObjCPropertyName() const { return getStringField(10); }
|
||||
/// getObjCProperty - Return property node, if this ivar is
|
||||
/// associated with one.
|
||||
MDNode *getObjCProperty() const;
|
||||
|
||||
StringRef getObjCPropertyName() const {
|
||||
if (getVersion() > LLVMDebugVersion11)
|
||||
return StringRef();
|
||||
return getStringField(10);
|
||||
}
|
||||
StringRef getObjCPropertyGetterName() const {
|
||||
assert (getVersion() <= LLVMDebugVersion11 && "Invalid Request");
|
||||
return getStringField(11);
|
||||
}
|
||||
StringRef getObjCPropertySetterName() const {
|
||||
assert (getVersion() <= LLVMDebugVersion11 && "Invalid Request");
|
||||
return getStringField(12);
|
||||
}
|
||||
bool isReadOnlyObjCProperty() {
|
||||
assert (getVersion() <= LLVMDebugVersion11 && "Invalid Request");
|
||||
return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_readonly) != 0;
|
||||
}
|
||||
bool isReadWriteObjCProperty() {
|
||||
assert (getVersion() <= LLVMDebugVersion11 && "Invalid Request");
|
||||
return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0;
|
||||
}
|
||||
bool isAssignObjCProperty() {
|
||||
assert (getVersion() <= LLVMDebugVersion11 && "Invalid Request");
|
||||
return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_assign) != 0;
|
||||
}
|
||||
bool isRetainObjCProperty() {
|
||||
assert (getVersion() <= LLVMDebugVersion11 && "Invalid Request");
|
||||
return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_retain) != 0;
|
||||
}
|
||||
bool isCopyObjCProperty() {
|
||||
assert (getVersion() <= LLVMDebugVersion11 && "Invalid Request");
|
||||
return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_copy) != 0;
|
||||
}
|
||||
bool isNonAtomicObjCProperty() {
|
||||
assert (getVersion() <= LLVMDebugVersion11 && "Invalid Request");
|
||||
return (getUnsignedField(13) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0;
|
||||
}
|
||||
|
||||
|
|
@ -391,6 +413,7 @@ namespace llvm {
|
|||
/// other types, like a function or struct.
|
||||
/// FIXME: Why is this a DIDerivedType??
|
||||
class DICompositeType : public DIDerivedType {
|
||||
virtual void anchor();
|
||||
public:
|
||||
explicit DICompositeType(const MDNode *N = 0)
|
||||
: DIDerivedType(N, true, true) {
|
||||
|
|
@ -454,6 +477,7 @@ namespace llvm {
|
|||
|
||||
/// DISubprogram - This is a wrapper for a subprogram (e.g. a function).
|
||||
class DISubprogram : public DIScope {
|
||||
virtual void anchor();
|
||||
public:
|
||||
explicit DISubprogram(const MDNode *N = 0) : DIScope(N) {}
|
||||
|
||||
|
|
@ -495,6 +519,7 @@ namespace llvm {
|
|||
DICompositeType getContainingType() const {
|
||||
return getFieldAs<DICompositeType>(13);
|
||||
}
|
||||
|
||||
unsigned isArtificial() const {
|
||||
if (getVersion() <= llvm::LLVMDebugVersion8)
|
||||
return getUnsignedField(14);
|
||||
|
|
@ -543,6 +568,11 @@ namespace llvm {
|
|||
return getFieldAs<DIFile>(6).getDirectory();
|
||||
}
|
||||
|
||||
/// getScopeLineNumber - Get the beginning of the scope of the
|
||||
/// function, not necessarily where the name of the program
|
||||
/// starts.
|
||||
unsigned getScopeLineNumber() const { return getUnsignedField(20); }
|
||||
|
||||
/// Verify - Verify that a subprogram descriptor is well formed.
|
||||
bool Verify() const;
|
||||
|
||||
|
|
@ -621,7 +651,7 @@ namespace llvm {
|
|||
|
||||
DIScope getContext() const { return getFieldAs<DIScope>(1); }
|
||||
StringRef getName() const { return getStringField(2); }
|
||||
DICompileUnit getCompileUnit() const{
|
||||
DICompileUnit getCompileUnit() const {
|
||||
assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!");
|
||||
if (getVersion() == llvm::LLVMDebugVersion7)
|
||||
return getFieldAs<DICompileUnit>(3);
|
||||
|
|
@ -687,6 +717,7 @@ namespace llvm {
|
|||
|
||||
/// DILexicalBlock - This is a wrapper for a lexical block.
|
||||
class DILexicalBlock : public DIScope {
|
||||
virtual void anchor();
|
||||
public:
|
||||
explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {}
|
||||
DIScope getContext() const { return getFieldAs<DIScope>(1); }
|
||||
|
|
@ -705,6 +736,7 @@ namespace llvm {
|
|||
/// DILexicalBlockFile - This is a wrapper for a lexical block with
|
||||
/// a filename change.
|
||||
class DILexicalBlockFile : public DIScope {
|
||||
virtual void anchor();
|
||||
public:
|
||||
explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {}
|
||||
DIScope getContext() const { return getScope().getContext(); }
|
||||
|
|
@ -724,6 +756,7 @@ namespace llvm {
|
|||
|
||||
/// DINameSpace - A wrapper for a C++ style name space.
|
||||
class DINameSpace : public DIScope {
|
||||
virtual void anchor();
|
||||
public:
|
||||
explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {}
|
||||
DIScope getContext() const { return getFieldAs<DIScope>(1); }
|
||||
|
|
@ -760,6 +793,51 @@ namespace llvm {
|
|||
bool Verify() const;
|
||||
};
|
||||
|
||||
class DIObjCProperty : public DIDescriptor {
|
||||
public:
|
||||
explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) { }
|
||||
|
||||
StringRef getObjCPropertyName() const { return getStringField(1); }
|
||||
DIFile getFile() const { return getFieldAs<DIFile>(2); }
|
||||
unsigned getLineNumber() const { return getUnsignedField(3); }
|
||||
|
||||
StringRef getObjCPropertyGetterName() const {
|
||||
return getStringField(4);
|
||||
}
|
||||
StringRef getObjCPropertySetterName() const {
|
||||
return getStringField(5);
|
||||
}
|
||||
bool isReadOnlyObjCProperty() {
|
||||
return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0;
|
||||
}
|
||||
bool isReadWriteObjCProperty() {
|
||||
return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0;
|
||||
}
|
||||
bool isAssignObjCProperty() {
|
||||
return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0;
|
||||
}
|
||||
bool isRetainObjCProperty() {
|
||||
return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0;
|
||||
}
|
||||
bool isCopyObjCProperty() {
|
||||
return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0;
|
||||
}
|
||||
bool isNonAtomicObjCProperty() {
|
||||
return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0;
|
||||
}
|
||||
|
||||
DIType getType() const { return getFieldAs<DIType>(7); }
|
||||
|
||||
/// Verify - Verify that a derived type descriptor is well formed.
|
||||
bool Verify() const;
|
||||
|
||||
/// print - print derived type.
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
/// dump - print derived type to dbgs() with a newline.
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
/// getDISubprogram - Find subprogram that is enclosing this scope.
|
||||
DISubprogram getDISubprogram(const MDNode *Scope);
|
||||
|
||||
|
|
@ -816,7 +894,7 @@ namespace llvm {
|
|||
/// addGlobalVariable - Add global variable into GVs.
|
||||
bool addGlobalVariable(DIGlobalVariable DIG);
|
||||
|
||||
// addSubprogram - Add subprgoram into SPs.
|
||||
// addSubprogram - Add subprogram into SPs.
|
||||
bool addSubprogram(DISubprogram SP);
|
||||
|
||||
/// addType - Add type into Tys.
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ public:
|
|||
/// used to compute a forward dominator frontiers.
|
||||
///
|
||||
class DominanceFrontier : public DominanceFrontierBase {
|
||||
virtual void anchor();
|
||||
public:
|
||||
static char ID; // Pass ID, replacement for typeid
|
||||
DominanceFrontier() :
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
|
|||
|
||||
// it might be that some blocks did not get a DFS number (e.g., blocks of
|
||||
// infinite loops). In these cases an artificial exit node is required.
|
||||
MultipleRoots |= (DT.isPostDominator() && N != F.size());
|
||||
MultipleRoots |= (DT.isPostDominator() && N != GraphTraits<FuncT*>::size(&F));
|
||||
|
||||
// When naively implemented, the Lengauer-Tarjan algorithm requires a separate
|
||||
// bucket for each vertex. However, this is unnecessary, because each vertex
|
||||
|
|
|
|||
|
|
@ -185,6 +185,18 @@ void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT,
|
|||
|
||||
template<class NodeT>
|
||||
class DominatorTreeBase : public DominatorBase<NodeT> {
|
||||
bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
|
||||
const DomTreeNodeBase<NodeT> *B) const {
|
||||
assert(A != B);
|
||||
assert(isReachableFromEntry(B));
|
||||
assert(isReachableFromEntry(A));
|
||||
|
||||
const DomTreeNodeBase<NodeT> *IDom;
|
||||
while ((IDom = B->getIDom()) != 0 && IDom != A && IDom != B)
|
||||
B = IDom; // Walk up the tree
|
||||
return IDom != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef DenseMap<NodeT*, DomTreeNodeBase<NodeT>*> DomTreeNodeMapType;
|
||||
DomTreeNodeMapType DomTreeNodes;
|
||||
|
|
@ -321,8 +333,7 @@ public:
|
|||
/// block. This is the same as using operator[] on this class.
|
||||
///
|
||||
inline DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const {
|
||||
typename DomTreeNodeMapType::const_iterator I = DomTreeNodes.find(BB);
|
||||
return I != DomTreeNodes.end() ? I->second : 0;
|
||||
return DomTreeNodes.lookup(BB);
|
||||
}
|
||||
|
||||
/// getRootNode - This returns the entry node for the CFG of the function. If
|
||||
|
|
@ -339,38 +350,26 @@ public:
|
|||
/// Note that this is not a constant time operation!
|
||||
///
|
||||
bool properlyDominates(const DomTreeNodeBase<NodeT> *A,
|
||||
const DomTreeNodeBase<NodeT> *B) const {
|
||||
if (A == 0 || B == 0) return false;
|
||||
return dominatedBySlowTreeWalk(A, B);
|
||||
}
|
||||
|
||||
inline bool properlyDominates(const NodeT *A, const NodeT *B) {
|
||||
const DomTreeNodeBase<NodeT> *B) {
|
||||
if (A == 0 || B == 0)
|
||||
return false;
|
||||
if (A == B)
|
||||
return false;
|
||||
|
||||
// Cast away the const qualifiers here. This is ok since
|
||||
// this function doesn't actually return the values returned
|
||||
// from getNode.
|
||||
return properlyDominates(getNode(const_cast<NodeT *>(A)),
|
||||
getNode(const_cast<NodeT *>(B)));
|
||||
}
|
||||
|
||||
bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
|
||||
const DomTreeNodeBase<NodeT> *B) const {
|
||||
const DomTreeNodeBase<NodeT> *IDom;
|
||||
if (A == 0 || B == 0) return false;
|
||||
while ((IDom = B->getIDom()) != 0 && IDom != A && IDom != B)
|
||||
B = IDom; // Walk up the tree
|
||||
return IDom != 0;
|
||||
return dominates(A, B);
|
||||
}
|
||||
|
||||
bool properlyDominates(const NodeT *A, const NodeT *B);
|
||||
|
||||
/// isReachableFromEntry - Return true if A is dominated by the entry
|
||||
/// block of the function containing it.
|
||||
bool isReachableFromEntry(const NodeT* A) {
|
||||
bool isReachableFromEntry(const NodeT* A) const {
|
||||
assert(!this->isPostDominator() &&
|
||||
"This is not implemented for post dominators");
|
||||
return dominates(&A->getParent()->front(), A);
|
||||
return isReachableFromEntry(getNode(const_cast<NodeT *>(A)));
|
||||
}
|
||||
|
||||
inline bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const {
|
||||
return A;
|
||||
}
|
||||
|
||||
/// dominates - Returns true iff A dominates B. Note that this is not a
|
||||
|
|
@ -378,10 +377,16 @@ public:
|
|||
///
|
||||
inline bool dominates(const DomTreeNodeBase<NodeT> *A,
|
||||
const DomTreeNodeBase<NodeT> *B) {
|
||||
// A node trivially dominates itself.
|
||||
if (B == A)
|
||||
return true; // A node trivially dominates itself.
|
||||
return true;
|
||||
|
||||
if (A == 0 || B == 0)
|
||||
// An unreachable node is dominated by anything.
|
||||
if (!isReachableFromEntry(B))
|
||||
return true;
|
||||
|
||||
// And dominates nothing.
|
||||
if (!isReachableFromEntry(A))
|
||||
return false;
|
||||
|
||||
// Compare the result of the tree walk and the dfs numbers, if expensive
|
||||
|
|
@ -406,16 +411,7 @@ public:
|
|||
return dominatedBySlowTreeWalk(A, B);
|
||||
}
|
||||
|
||||
inline bool dominates(const NodeT *A, const NodeT *B) {
|
||||
if (A == B)
|
||||
return true;
|
||||
|
||||
// Cast away the const qualifiers here. This is ok since
|
||||
// this function doesn't actually return the values returned
|
||||
// from getNode.
|
||||
return dominates(getNode(const_cast<NodeT *>(A)),
|
||||
getNode(const_cast<NodeT *>(B)));
|
||||
}
|
||||
bool dominates(const NodeT *A, const NodeT *B);
|
||||
|
||||
NodeT *getRoot() const {
|
||||
assert(this->Roots.size() == 1 && "Should always have entry node!");
|
||||
|
|
@ -623,9 +619,8 @@ protected:
|
|||
}
|
||||
|
||||
DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) {
|
||||
typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.find(BB);
|
||||
if (I != this->DomTreeNodes.end() && I->second)
|
||||
return I->second;
|
||||
if (DomTreeNodeBase<NodeT> *Node = getNode(BB))
|
||||
return Node;
|
||||
|
||||
// Haven't calculated this node yet? Get or calculate the node for the
|
||||
// immediate dominator.
|
||||
|
|
@ -641,8 +636,7 @@ protected:
|
|||
}
|
||||
|
||||
inline NodeT *getIDom(NodeT *BB) const {
|
||||
typename DenseMap<NodeT*, NodeT*>::const_iterator I = IDoms.find(BB);
|
||||
return I != IDoms.end() ? I->second : 0;
|
||||
return IDoms.lookup(BB);
|
||||
}
|
||||
|
||||
inline void addRoot(NodeT* BB) {
|
||||
|
|
@ -653,21 +647,24 @@ public:
|
|||
/// recalculate - compute a dominator tree for the given function
|
||||
template<class FT>
|
||||
void recalculate(FT& F) {
|
||||
typedef GraphTraits<FT*> TraitsTy;
|
||||
reset();
|
||||
this->Vertex.push_back(0);
|
||||
|
||||
if (!this->IsPostDominators) {
|
||||
// Initialize root
|
||||
this->Roots.push_back(&F.front());
|
||||
this->IDoms[&F.front()] = 0;
|
||||
this->DomTreeNodes[&F.front()] = 0;
|
||||
NodeT *entry = TraitsTy::getEntryNode(&F);
|
||||
this->Roots.push_back(entry);
|
||||
this->IDoms[entry] = 0;
|
||||
this->DomTreeNodes[entry] = 0;
|
||||
|
||||
Calculate<FT, NodeT*>(*this, F);
|
||||
} else {
|
||||
// Initialize the roots list
|
||||
for (typename FT::iterator I = F.begin(), E = F.end(); I != E; ++I) {
|
||||
if (std::distance(GraphTraits<FT*>::child_begin(I),
|
||||
GraphTraits<FT*>::child_end(I)) == 0)
|
||||
for (typename TraitsTy::nodes_iterator I = TraitsTy::nodes_begin(&F),
|
||||
E = TraitsTy::nodes_end(&F); I != E; ++I) {
|
||||
if (std::distance(TraitsTy::child_begin(I),
|
||||
TraitsTy::child_end(I)) == 0)
|
||||
addRoot(I);
|
||||
|
||||
// Prepopulate maps so that we don't get iterator invalidation issues later.
|
||||
|
|
@ -680,6 +677,32 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// These two functions are declared out of line as a workaround for building
|
||||
// with old (< r147295) versions of clang because of pr11642.
|
||||
template<class NodeT>
|
||||
bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) {
|
||||
if (A == B)
|
||||
return true;
|
||||
|
||||
// Cast away the const qualifiers here. This is ok since
|
||||
// this function doesn't actually return the values returned
|
||||
// from getNode.
|
||||
return dominates(getNode(const_cast<NodeT *>(A)),
|
||||
getNode(const_cast<NodeT *>(B)));
|
||||
}
|
||||
template<class NodeT>
|
||||
bool
|
||||
DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) {
|
||||
if (A == B)
|
||||
return false;
|
||||
|
||||
// Cast away the const qualifiers here. This is ok since
|
||||
// this function doesn't actually return the values returned
|
||||
// from getNode.
|
||||
return dominates(getNode(const_cast<NodeT *>(A)),
|
||||
getNode(const_cast<NodeT *>(B)));
|
||||
}
|
||||
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>);
|
||||
|
||||
//===-------------------------------------
|
||||
|
|
@ -749,9 +772,12 @@ public:
|
|||
return DT->dominates(A, B);
|
||||
}
|
||||
|
||||
// dominates - Return true if A dominates B. This performs the
|
||||
// special checks necessary if A and B are in the same basic block.
|
||||
bool dominates(const Instruction *A, const Instruction *B) const;
|
||||
// dominates - Return true if Def dominates a use in User. This performs
|
||||
// the special checks necessary if Def and User are in the same basic block.
|
||||
// Note that Def doesn't dominate a use in Def itself!
|
||||
bool dominates(const Instruction *Def, const Use &U) const;
|
||||
bool dominates(const Instruction *Def, const Instruction *User) const;
|
||||
bool dominates(const Instruction *Def, const BasicBlock *BB) const;
|
||||
|
||||
bool properlyDominates(const DomTreeNode *A, const DomTreeNode *B) const {
|
||||
return DT->properlyDominates(A, B);
|
||||
|
|
@ -814,10 +840,12 @@ public:
|
|||
DT->splitBlock(NewBB);
|
||||
}
|
||||
|
||||
bool isReachableFromEntry(const BasicBlock* A) {
|
||||
bool isReachableFromEntry(const BasicBlock* A) const {
|
||||
return DT->isReachableFromEntry(A);
|
||||
}
|
||||
|
||||
bool isReachableFromEntry(const Use &U) const;
|
||||
|
||||
|
||||
virtual void releaseMemory() {
|
||||
DT->releaseMemory();
|
||||
|
|
|
|||
|
|
@ -166,10 +166,16 @@ public:
|
|||
const_iterator end() const { return IVUses.end(); }
|
||||
bool empty() const { return IVUses.empty(); }
|
||||
|
||||
bool isIVUserOrOperand(Instruction *Inst) const {
|
||||
return Processed.count(Inst);
|
||||
}
|
||||
|
||||
void print(raw_ostream &OS, const Module* = 0) const;
|
||||
|
||||
/// dump - This method is used for debugging.
|
||||
void dump() const;
|
||||
protected:
|
||||
bool AddUsersImpl(Instruction *I, SmallPtrSet<Loop*,16> &SimpleLoopNests);
|
||||
};
|
||||
|
||||
Pass *createIVUsersPass();
|
||||
|
|
|
|||
|
|
@ -14,171 +14,118 @@
|
|||
#ifndef LLVM_ANALYSIS_INLINECOST_H
|
||||
#define LLVM_ANALYSIS_INLINECOST_H
|
||||
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/ValueMap.h"
|
||||
#include "llvm/Analysis/CodeMetrics.h"
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <vector>
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/ValueMap.h"
|
||||
#include "llvm/Analysis/CodeMetrics.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Value;
|
||||
class Function;
|
||||
class BasicBlock;
|
||||
class CallSite;
|
||||
template<class PtrType, unsigned SmallSize>
|
||||
class SmallPtrSet;
|
||||
class TargetData;
|
||||
|
||||
namespace InlineConstants {
|
||||
// Various magic constants used to adjust heuristics.
|
||||
const int InstrCost = 5;
|
||||
const int IndirectCallBonus = -100;
|
||||
const int IndirectCallThreshold = 100;
|
||||
const int CallPenalty = 25;
|
||||
const int LastCallToStaticBonus = -15000;
|
||||
const int ColdccPenalty = 2000;
|
||||
const int NoreturnPenalty = 10000;
|
||||
}
|
||||
|
||||
/// InlineCost - Represent 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; smaller values increase the likelihood of the function
|
||||
/// being inlined.
|
||||
/// \brief 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;
|
||||
/// smaller values increase the likelihood of the function being inlined.
|
||||
///
|
||||
/// Objects of this type also provide the adjusted threshold for inlining
|
||||
/// based on the information available for a particular callsite. They can be
|
||||
/// directly tested to determine if inlining should occur given the cost and
|
||||
/// threshold for this cost metric.
|
||||
class InlineCost {
|
||||
enum Kind {
|
||||
Value,
|
||||
Always,
|
||||
Never
|
||||
enum SentinelValues {
|
||||
AlwaysInlineCost = INT_MIN,
|
||||
NeverInlineCost = INT_MAX
|
||||
};
|
||||
|
||||
// This is a do-it-yourself implementation of
|
||||
// int Cost : 30;
|
||||
// unsigned Type : 2;
|
||||
// We used to use bitfields, but they were sometimes miscompiled (PR3822).
|
||||
enum { TYPE_BITS = 2 };
|
||||
enum { COST_BITS = unsigned(sizeof(unsigned)) * CHAR_BIT - TYPE_BITS };
|
||||
unsigned TypedCost; // int Cost : COST_BITS; unsigned Type : TYPE_BITS;
|
||||
/// \brief The estimated cost of inlining this callsite.
|
||||
const int Cost;
|
||||
|
||||
Kind getType() const {
|
||||
return Kind(TypedCost >> COST_BITS);
|
||||
}
|
||||
/// \brief The adjusted threshold against which this cost was computed.
|
||||
const int Threshold;
|
||||
|
||||
int getCost() const {
|
||||
// Sign-extend the bottom COST_BITS bits.
|
||||
return (int(TypedCost << TYPE_BITS)) >> TYPE_BITS;
|
||||
}
|
||||
// Trivial constructor, interesting logic in the factory functions below.
|
||||
InlineCost(int Cost, int Threshold)
|
||||
: Cost(Cost), Threshold(Threshold) {}
|
||||
|
||||
InlineCost(int C, int T) {
|
||||
TypedCost = (unsigned(C << TYPE_BITS) >> TYPE_BITS) | (T << COST_BITS);
|
||||
assert(getCost() == C && "Cost exceeds InlineCost precision");
|
||||
}
|
||||
public:
|
||||
static InlineCost get(int Cost) { return InlineCost(Cost, Value); }
|
||||
static InlineCost getAlways() { return InlineCost(0, Always); }
|
||||
static InlineCost getNever() { return InlineCost(0, Never); }
|
||||
|
||||
bool isVariable() const { return getType() == Value; }
|
||||
bool isAlways() const { return getType() == Always; }
|
||||
bool isNever() const { return getType() == Never; }
|
||||
|
||||
/// getValue() - Return a "variable" inline cost's amount. It is
|
||||
/// an error to call this on an "always" or "never" InlineCost.
|
||||
int getValue() const {
|
||||
assert(getType() == Value && "Invalid access of InlineCost");
|
||||
return getCost();
|
||||
static InlineCost get(int Cost, int Threshold) {
|
||||
assert(Cost > AlwaysInlineCost && "Cost crosses sentinel value");
|
||||
assert(Cost < NeverInlineCost && "Cost crosses sentinel value");
|
||||
return InlineCost(Cost, Threshold);
|
||||
}
|
||||
static InlineCost getAlways() {
|
||||
return InlineCost(AlwaysInlineCost, 0);
|
||||
}
|
||||
static InlineCost getNever() {
|
||||
return InlineCost(NeverInlineCost, 0);
|
||||
}
|
||||
|
||||
/// \brief Test whether the inline cost is low enough for inlining.
|
||||
operator bool() const {
|
||||
return Cost < Threshold;
|
||||
}
|
||||
|
||||
bool isAlways() const { return Cost == AlwaysInlineCost; }
|
||||
bool isNever() const { return Cost == NeverInlineCost; }
|
||||
bool isVariable() const { return !isAlways() && !isNever(); }
|
||||
|
||||
/// \brief 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 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(); }
|
||||
};
|
||||
|
||||
/// InlineCostAnalyzer - Cost analyzer used by inliner.
|
||||
class InlineCostAnalyzer {
|
||||
struct ArgInfo {
|
||||
public:
|
||||
unsigned ConstantWeight;
|
||||
unsigned AllocaWeight;
|
||||
|
||||
ArgInfo(unsigned CWeight, unsigned AWeight)
|
||||
: ConstantWeight(CWeight), AllocaWeight(AWeight)
|
||||
{}
|
||||
};
|
||||
|
||||
struct FunctionInfo {
|
||||
CodeMetrics Metrics;
|
||||
|
||||
/// ArgumentWeights - Each formal argument of the function is inspected to
|
||||
/// see if it is used in any contexts where making it a constant or alloca
|
||||
/// would reduce the code size. If so, we add some value to the argument
|
||||
/// entry here.
|
||||
std::vector<ArgInfo> ArgumentWeights;
|
||||
|
||||
/// analyzeFunction - Add information about the specified function
|
||||
/// to the current structure.
|
||||
void analyzeFunction(Function *F, const TargetData *TD);
|
||||
|
||||
/// NeverInline - Returns true if the function should never be
|
||||
/// inlined into any caller.
|
||||
bool NeverInline();
|
||||
};
|
||||
|
||||
// The Function* for a function can be changed (by ArgumentPromotion);
|
||||
// the ValueMap will update itself when this happens.
|
||||
ValueMap<const Function *, FunctionInfo> CachedFunctionInfo;
|
||||
|
||||
// TargetData if available, or null.
|
||||
const TargetData *TD;
|
||||
|
||||
int CountBonusForConstant(Value *V, Constant *C = NULL);
|
||||
int ConstantFunctionBonus(CallSite CS, Constant *C);
|
||||
int getInlineSize(CallSite CS, Function *Callee);
|
||||
int getInlineBonuses(CallSite CS, Function *Callee);
|
||||
public:
|
||||
InlineCostAnalyzer(): TD(0) {}
|
||||
|
||||
void setTargetData(const TargetData *TData) { TD = TData; }
|
||||
|
||||
/// getInlineCost - The heuristic used to determine if we should inline the
|
||||
/// function call or not.
|
||||
/// \brief Get an InlineCost object representing the cost of inlining this
|
||||
/// callsite.
|
||||
///
|
||||
InlineCost getInlineCost(CallSite CS,
|
||||
SmallPtrSet<const Function *, 16> &NeverInline);
|
||||
/// Note that threshold is passed into this function. Only costs below the
|
||||
/// threshold are computed with any accuracy. The threshold can be used to
|
||||
/// bound the computation necessary to determine whether the cost is
|
||||
/// sufficiently low to warrant inlining.
|
||||
InlineCost getInlineCost(CallSite CS, int Threshold);
|
||||
/// getCalledFunction - The heuristic used to determine if we should inline
|
||||
/// the function call or not. The callee is explicitly specified, to allow
|
||||
/// you to calculate the cost of inlining a function via a pointer. The
|
||||
/// result assumes that the inlined version will always be used. You should
|
||||
/// weight it yourself in cases where this callee will not always be called.
|
||||
InlineCost getInlineCost(CallSite CS,
|
||||
Function *Callee,
|
||||
SmallPtrSet<const Function *, 16> &NeverInline);
|
||||
|
||||
/// getSpecializationBonus - The heuristic used to determine the per-call
|
||||
/// performance boost for using a specialization of Callee with argument
|
||||
/// SpecializedArgNos replaced by a constant.
|
||||
int getSpecializationBonus(Function *Callee,
|
||||
SmallVectorImpl<unsigned> &SpecializedArgNo);
|
||||
|
||||
/// getSpecializationCost - The heuristic used to determine the code-size
|
||||
/// impact of creating a specialized version of Callee with argument
|
||||
/// SpecializedArgNo replaced by a constant.
|
||||
InlineCost getSpecializationCost(Function *Callee,
|
||||
SmallVectorImpl<unsigned> &SpecializedArgNo);
|
||||
|
||||
/// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a
|
||||
/// higher threshold to determine if the function call should be inlined.
|
||||
float getInlineFudgeFactor(CallSite CS);
|
||||
|
||||
/// resetCachedFunctionInfo - erase any cached cost info for this function.
|
||||
void resetCachedCostInfo(Function* Caller) {
|
||||
CachedFunctionInfo[Caller] = FunctionInfo();
|
||||
}
|
||||
|
||||
/// growCachedCostInfo - update the cached cost info for Caller after Callee
|
||||
/// has been inlined. If Callee is NULL it means a dead call has been
|
||||
/// eliminated.
|
||||
void growCachedCostInfo(Function* Caller, Function* Callee);
|
||||
|
||||
/// clear - empty the cache of inline costs
|
||||
void clear();
|
||||
/// 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.
|
||||
//
|
||||
// Note: This is used by out-of-tree passes, please do not remove without
|
||||
// adding a replacement API.
|
||||
InlineCost getInlineCost(CallSite CS, Function *Callee, int Threshold);
|
||||
};
|
||||
|
||||
/// callIsSmall - If a call is likely to lower to a single target instruction,
|
||||
|
|
|
|||
|
|
@ -20,147 +20,198 @@
|
|||
#define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H
|
||||
|
||||
namespace llvm {
|
||||
class DominatorTree;
|
||||
class Instruction;
|
||||
class Value;
|
||||
class TargetData;
|
||||
template<typename T>
|
||||
class ArrayRef;
|
||||
class DominatorTree;
|
||||
class Instruction;
|
||||
class TargetData;
|
||||
class TargetLibraryInfo;
|
||||
class Type;
|
||||
class Value;
|
||||
|
||||
/// SimplifyAddInst - Given operands for an Add, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
||||
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySubInst - Given operands for a Sub, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
||||
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyMulInst - Given operands for a Mul, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyMulInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySDivInst - Given operands for an SDiv, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifySDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyUDivInst - Given operands for a UDiv, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyUDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
Value *SimplifyUDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyFDivInst - Given operands for an FDiv, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyFDivInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySRemInst - Given operands for an SRem, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifySRemInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
Value *SimplifySRemInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyURemInst - Given operands for a URem, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyURemInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyFRemInst - Given operands for an FRem, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyFRemInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyShlInst - Given operands for a Shl, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
|
||||
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyLShrInst - Given operands for a LShr, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const TargetData *TD = 0, const DominatorTree *DT=0);
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyAShrInst - Given operands for a AShr, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyAndInst - Given operands for an And, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyAndInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyOrInst - Given operands for an Or, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyOrInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyXorInst - Given operands for a Xor, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyXorInst(Value *LHS, Value *RHS, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const TargetData *TD = 0,
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const TargetData *TD = 0,
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifySelectInst - Given operands for a SelectInst, see if we can fold
|
||||
/// the result. If not, this returns null.
|
||||
Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyGEPInst(ArrayRef<Value *> Ops,
|
||||
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
||||
Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we
|
||||
/// can fold the result. If not, this returns null.
|
||||
Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
|
||||
ArrayRef<unsigned> Idxs,
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
|
||||
/// the result. If not, this returns null.
|
||||
Value *SimplifyTruncInst(Value *Op, Type *Ty, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
//=== Helper functions for higher up the class hierarchy.
|
||||
|
||||
|
||||
/// SimplifyCmpInst - Given operands for a CmpInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyBinOp - Given operands for a BinaryOperator, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
|
||||
const TargetData *TD = 0, const DominatorTree *DT = 0);
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// SimplifyInstruction - See if we can compute a simplified version of this
|
||||
/// instruction. If not, this returns null.
|
||||
Value *SimplifyInstruction(Instruction *I, const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
|
||||
/// ReplaceAndSimplifyAllUses - Perform From->replaceAllUsesWith(To) and then
|
||||
/// delete the From instruction. In addition to a basic RAUW, this does a
|
||||
/// recursive simplification of the updated instructions. This catches
|
||||
/// things where one simplification exposes other opportunities. This only
|
||||
/// simplifies and deletes scalar operations, it does not change the CFG.
|
||||
/// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses
|
||||
/// recursively.
|
||||
///
|
||||
void ReplaceAndSimplifyAllUses(Instruction *From, Value *To,
|
||||
const TargetData *TD = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
/// This first performs a normal RAUW of I with SimpleV. It then recursively
|
||||
/// attempts to simplify those users updated by the operation. The 'I'
|
||||
/// instruction must not be equal to the simplified value 'SimpleV'.
|
||||
///
|
||||
/// The function returns true if any simplifications were performed.
|
||||
bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
|
||||
/// \brief Recursively attempt to simplify an instruction.
|
||||
///
|
||||
/// This routine uses SimplifyInstruction to simplify 'I', and if successful
|
||||
/// replaces uses of 'I' with the simplified value. It then recurses on each
|
||||
/// of the users impacted. It returns true if any simplifications were
|
||||
/// performed.
|
||||
bool recursivelySimplifyInstruction(Instruction *I,
|
||||
const TargetData *TD = 0,
|
||||
const TargetLibraryInfo *TLI = 0,
|
||||
const DominatorTree *DT = 0);
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -101,14 +101,14 @@ public:
|
|||
IntervalIterator(Function *M, bool OwnMemory) : IOwnMem(OwnMemory) {
|
||||
OrigContainer = M;
|
||||
if (!ProcessInterval(&M->front())) {
|
||||
assert(0 && "ProcessInterval should never fail for first interval!");
|
||||
llvm_unreachable("ProcessInterval should never fail for first interval!");
|
||||
}
|
||||
}
|
||||
|
||||
IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) {
|
||||
OrigContainer = &IP;
|
||||
if (!ProcessInterval(IP.getRootInterval())) {
|
||||
assert(0 && "ProcessInterval should never fail for first interval!");
|
||||
llvm_unreachable("ProcessInterval should never fail for first interval!");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,12 +20,14 @@
|
|||
namespace llvm {
|
||||
class Constant;
|
||||
class TargetData;
|
||||
class TargetLibraryInfo;
|
||||
class Value;
|
||||
|
||||
/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint
|
||||
/// information.
|
||||
class LazyValueInfo : public FunctionPass {
|
||||
class TargetData *TD;
|
||||
class TargetLibraryInfo *TLI;
|
||||
void *PImpl;
|
||||
LazyValueInfo(const LazyValueInfo&); // DO NOT IMPLEMENT.
|
||||
void operator=(const LazyValueInfo&); // DO NOT IMPLEMENT.
|
||||
|
|
@ -68,9 +70,7 @@ public:
|
|||
|
||||
// Implementation boilerplate.
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual void releaseMemory();
|
||||
virtual bool runOnFunction(Function &F);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ namespace llvm {
|
|||
|
||||
class AliasAnalysis;
|
||||
class TargetData;
|
||||
class MDNode;
|
||||
|
||||
/// isSafeToLoadUnconditionally - Return true if we know that executing a load
|
||||
/// from this value cannot trap. If it is not obviously safe to load from the
|
||||
|
|
@ -41,10 +42,15 @@ bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
|
|||
/// MaxInstsToScan specifies the maximum instructions to scan in the block.
|
||||
/// If it is set to 0, it will scan the whole block. You can also optionally
|
||||
/// specify an alias analysis implementation, which makes this more precise.
|
||||
///
|
||||
/// If TBAATag is non-null and a load or store is found, the TBAA tag from the
|
||||
/// load or store is recorded there. If there is no TBAA tag or if no access
|
||||
/// is found, it is left unmodified.
|
||||
Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB,
|
||||
BasicBlock::iterator &ScanFrom,
|
||||
unsigned MaxInstsToScan = 6,
|
||||
AliasAnalysis *AA = 0);
|
||||
AliasAnalysis *AA = 0,
|
||||
MDNode **TBAATag = 0);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
// * whether or not a particular block branches out of the loop
|
||||
// * the successor blocks of the loop
|
||||
// * the loop depth
|
||||
// * the trip count
|
||||
// * etc...
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -416,14 +415,26 @@ public:
|
|||
#ifndef NDEBUG
|
||||
assert(!Blocks.empty() && "Loop header is missing");
|
||||
|
||||
// Setup for using a depth-first iterator to visit every block in the loop.
|
||||
SmallVector<BlockT*, 8> ExitBBs;
|
||||
getExitBlocks(ExitBBs);
|
||||
llvm::SmallPtrSet<BlockT*, 8> VisitSet;
|
||||
VisitSet.insert(ExitBBs.begin(), ExitBBs.end());
|
||||
df_ext_iterator<BlockT*, llvm::SmallPtrSet<BlockT*, 8> >
|
||||
BI = df_ext_begin(getHeader(), VisitSet),
|
||||
BE = df_ext_end(getHeader(), VisitSet);
|
||||
|
||||
// Keep track of the number of BBs visited.
|
||||
unsigned NumVisited = 0;
|
||||
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
|
||||
std::sort(LoopBBs.begin(), LoopBBs.end());
|
||||
|
||||
// Check the individual blocks.
|
||||
for (block_iterator I = block_begin(), E = block_end(); I != E; ++I) {
|
||||
BlockT *BB = *I;
|
||||
for ( ; BI != BE; ++BI) {
|
||||
BlockT *BB = *BI;
|
||||
bool HasInsideLoopSuccs = false;
|
||||
bool HasInsideLoopPreds = false;
|
||||
SmallVector<BlockT *, 2> OutsideLoopPreds;
|
||||
|
|
@ -440,7 +451,7 @@ public:
|
|||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB);
|
||||
PI != PE; ++PI) {
|
||||
typename InvBlockTraits::NodeType *N = *PI;
|
||||
BlockT *N = *PI;
|
||||
if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N))
|
||||
HasInsideLoopPreds = true;
|
||||
else
|
||||
|
|
@ -464,8 +475,12 @@ public:
|
|||
assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!");
|
||||
assert(BB != getHeader()->getParent()->begin() &&
|
||||
"Loop contains function entry block!");
|
||||
|
||||
NumVisited++;
|
||||
}
|
||||
|
||||
assert(NumVisited == getNumBlocks() && "Unreachable block in loop");
|
||||
|
||||
// Check the subloops.
|
||||
for (iterator I = begin(), E = end(); I != E; ++I)
|
||||
// Each block in each subloop should be contained within this loop.
|
||||
|
|
@ -571,37 +586,6 @@ public:
|
|||
///
|
||||
PHINode *getCanonicalInductionVariable() const;
|
||||
|
||||
/// getTripCount - Return a loop-invariant LLVM value indicating the number of
|
||||
/// times the loop will be executed. Note that this means that the backedge
|
||||
/// of the loop executes N-1 times. If the trip-count cannot be determined,
|
||||
/// this returns null.
|
||||
///
|
||||
/// The IndVarSimplify pass transforms loops to have a form that this
|
||||
/// function easily understands.
|
||||
///
|
||||
Value *getTripCount() const;
|
||||
|
||||
/// getSmallConstantTripCount - Returns the trip count of this loop as a
|
||||
/// normal unsigned value, if possible. Returns 0 if the trip count is unknown
|
||||
/// of not constant. Will also return 0 if the trip count is very large
|
||||
/// (>= 2^32)
|
||||
///
|
||||
/// The IndVarSimplify pass transforms loops to have a form that this
|
||||
/// function easily understands.
|
||||
///
|
||||
unsigned getSmallConstantTripCount() const;
|
||||
|
||||
/// getSmallConstantTripMultiple - Returns the largest constant divisor of the
|
||||
/// trip count of this loop as a normal unsigned value, if possible. This
|
||||
/// means that the actual trip count is always a multiple of the returned
|
||||
/// value (don't forget the trip count could very well be zero as well!).
|
||||
///
|
||||
/// Returns 1 if the trip count is unknown or not guaranteed to be the
|
||||
/// multiple of a constant (which is also the case if the trip count is simply
|
||||
/// constant, use getSmallConstantTripCount for that case), Will also return 1
|
||||
/// if the trip count is very large (>= 2^32).
|
||||
unsigned getSmallConstantTripMultiple() const;
|
||||
|
||||
/// isLCSSAForm - Return true if the Loop is in LCSSA form
|
||||
bool isLCSSAForm(DominatorTree &DT) const;
|
||||
|
||||
|
|
@ -610,6 +594,9 @@ public:
|
|||
/// normal form.
|
||||
bool isLoopSimplifyForm() const;
|
||||
|
||||
/// isSafeToClone - Return true if the loop body is safe to clone in practice.
|
||||
bool isSafeToClone() const;
|
||||
|
||||
/// hasDedicatedExits - Return true if no exit block for the loop
|
||||
/// has a predecessor that is outside the loop.
|
||||
bool hasDedicatedExits() const;
|
||||
|
|
@ -671,9 +658,7 @@ public:
|
|||
/// block is in no loop (for example the entry node), null is returned.
|
||||
///
|
||||
LoopT *getLoopFor(const BlockT *BB) const {
|
||||
typename DenseMap<BlockT *, LoopT *>::const_iterator I=
|
||||
BBMap.find(const_cast<BlockT*>(BB));
|
||||
return I != BBMap.end() ? I->second : 0;
|
||||
return BBMap.lookup(const_cast<BlockT*>(BB));
|
||||
}
|
||||
|
||||
/// operator[] - same as getLoopFor...
|
||||
|
|
@ -712,9 +697,7 @@ public:
|
|||
/// the loop hierarchy tree.
|
||||
void changeLoopFor(BlockT *BB, LoopT *L) {
|
||||
if (!L) {
|
||||
typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB);
|
||||
if (I != BBMap.end())
|
||||
BBMap.erase(I);
|
||||
BBMap.erase(BB);
|
||||
return;
|
||||
}
|
||||
BBMap[BB] = L;
|
||||
|
|
@ -771,7 +754,7 @@ public:
|
|||
}
|
||||
|
||||
LoopT *ConsiderForLoop(BlockT *BB, DominatorTreeBase<BlockT> &DT) {
|
||||
if (BBMap.find(BB) != BBMap.end()) return 0;// Haven't processed this node?
|
||||
if (BBMap.count(BB)) return 0; // Haven't processed this node?
|
||||
|
||||
std::vector<BlockT *> TodoStack;
|
||||
|
||||
|
|
@ -782,7 +765,8 @@ public:
|
|||
InvBlockTraits::child_begin(BB), E = InvBlockTraits::child_end(BB);
|
||||
I != E; ++I) {
|
||||
typename InvBlockTraits::NodeType *N = *I;
|
||||
if (DT.dominates(BB, N)) // If BB dominates its predecessor...
|
||||
// If BB dominates its predecessor...
|
||||
if (DT.dominates(BB, N) && DT.isReachableFromEntry(N))
|
||||
TodoStack.push_back(N);
|
||||
}
|
||||
|
||||
|
|
@ -792,14 +776,12 @@ public:
|
|||
LoopT *L = new LoopT(BB);
|
||||
BBMap[BB] = L;
|
||||
|
||||
BlockT *EntryBlock = BB->getParent()->begin();
|
||||
|
||||
while (!TodoStack.empty()) { // Process all the nodes in the loop
|
||||
BlockT *X = TodoStack.back();
|
||||
TodoStack.pop_back();
|
||||
|
||||
if (!L->contains(X) && // As of yet unprocessed??
|
||||
DT.dominates(EntryBlock, X)) { // X is reachable from entry block?
|
||||
DT.isReachableFromEntry(X)) {
|
||||
// Check to see if this block already belongs to a loop. If this occurs
|
||||
// then we have a case where a loop that is supposed to be a child of
|
||||
// the current loop was processed before the current loop. When this
|
||||
|
|
|
|||
|
|
@ -324,6 +324,7 @@ namespace llvm {
|
|||
/// Current AA implementation, just a cache.
|
||||
AliasAnalysis *AA;
|
||||
TargetData *TD;
|
||||
DominatorTree *DT;
|
||||
OwningPtr<PredIteratorCache> PredCache;
|
||||
public:
|
||||
MemoryDependenceAnalysis();
|
||||
|
|
@ -430,6 +431,9 @@ namespace llvm {
|
|||
|
||||
void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P);
|
||||
|
||||
AliasAnalysis::ModRefResult
|
||||
getModRefInfo(const Instruction *Inst, const AliasAnalysis::Location &Loc);
|
||||
|
||||
/// verifyRemoved - Verify that the specified instruction does not occur
|
||||
/// in our internal data structures.
|
||||
void verifyRemoved(Instruction *Inst) const;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@
|
|||
namespace llvm {
|
||||
class DominatorTree;
|
||||
class TargetData;
|
||||
|
||||
class TargetLibraryInfo;
|
||||
|
||||
/// PHITransAddr - An address value which tracks and handles phi translation.
|
||||
/// As we walk "up" the CFG through predecessors, we need to ensure that the
|
||||
/// address we're tracking is kept up to date. For example, if we're analyzing
|
||||
|
|
@ -37,11 +38,14 @@ class PHITransAddr {
|
|||
|
||||
/// TD - The target data we are playing with if known, otherwise null.
|
||||
const TargetData *TD;
|
||||
|
||||
/// TLI - The target library info if known, otherwise null.
|
||||
const TargetLibraryInfo *TLI;
|
||||
|
||||
/// InstInputs - The inputs for our symbolic address.
|
||||
SmallVector<Instruction*, 4> InstInputs;
|
||||
public:
|
||||
PHITransAddr(Value *addr, const TargetData *td) : Addr(addr), TD(td) {
|
||||
PHITransAddr(Value *addr, const TargetData *td) : Addr(addr), TD(td), TLI(0) {
|
||||
// If the address is an instruction, the whole thing is considered an input.
|
||||
if (Instruction *I = dyn_cast<Instruction>(Addr))
|
||||
InstInputs.push_back(I);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#define LLVM_ANALYSIS_PROFILEINFO_H
|
||||
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
|
|
@ -85,13 +86,11 @@ namespace llvm {
|
|||
|
||||
// getFunction() - Returns the Function for an Edge, checking for validity.
|
||||
static const FType* getFunction(Edge e) {
|
||||
if (e.first) {
|
||||
if (e.first)
|
||||
return e.first->getParent();
|
||||
} else if (e.second) {
|
||||
if (e.second)
|
||||
return e.second->getParent();
|
||||
}
|
||||
assert(0 && "Invalid ProfileInfo::Edge");
|
||||
return (const FType*)0;
|
||||
llvm_unreachable("Invalid ProfileInfo::Edge");
|
||||
}
|
||||
|
||||
// getEdge() - Creates an Edge from two BasicBlocks.
|
||||
|
|
|
|||
|
|
@ -681,7 +681,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RegionNode &Node) {
|
|||
if (Node.isSubRegion())
|
||||
return OS << Node.getNodeAs<Region>()->getNameStr();
|
||||
else
|
||||
return OS << Node.getNodeAs<BasicBlock>()->getNameStr();
|
||||
return OS << Node.getNodeAs<BasicBlock>()->getName();
|
||||
}
|
||||
} // End llvm namespace
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ namespace llvm {
|
|||
class Type;
|
||||
class ScalarEvolution;
|
||||
class TargetData;
|
||||
class TargetLibraryInfo;
|
||||
class LLVMContext;
|
||||
class Loop;
|
||||
class LoopInfo;
|
||||
|
|
@ -118,6 +119,10 @@ namespace llvm {
|
|||
///
|
||||
bool isAllOnesValue() const;
|
||||
|
||||
/// isNonConstantNegative - Return true if the specified scev is negated,
|
||||
/// but not a constant.
|
||||
bool isNonConstantNegative() const;
|
||||
|
||||
/// print - Print out the internal representation of this scalar to the
|
||||
/// specified stream. This should really only be used for debugging
|
||||
/// purposes.
|
||||
|
|
@ -135,7 +140,7 @@ namespace llvm {
|
|||
ID = X.FastID;
|
||||
}
|
||||
static bool Equals(const SCEV &X, const FoldingSetNodeID &ID,
|
||||
FoldingSetNodeID &TempID) {
|
||||
unsigned IDHash, FoldingSetNodeID &TempID) {
|
||||
return ID == X.FastID;
|
||||
}
|
||||
static unsigned ComputeHash(const SCEV &X, FoldingSetNodeID &TempID) {
|
||||
|
|
@ -224,6 +229,10 @@ namespace llvm {
|
|||
///
|
||||
TargetData *TD;
|
||||
|
||||
/// TLI - The target library information for the target we are targeting.
|
||||
///
|
||||
TargetLibraryInfo *TLI;
|
||||
|
||||
/// DT - The dominator tree.
|
||||
///
|
||||
DominatorTree *DT;
|
||||
|
|
@ -721,16 +730,21 @@ namespace llvm {
|
|||
const SCEV *LHS, const SCEV *RHS);
|
||||
|
||||
/// getSmallConstantTripCount - Returns the maximum trip count of this loop
|
||||
/// as a normal unsigned value, if possible. Returns 0 if the trip count is
|
||||
/// unknown or not constant.
|
||||
unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitBlock);
|
||||
/// as a normal unsigned value. Returns 0 if the trip count is unknown or
|
||||
/// not constant. This "trip count" assumes that control exits via
|
||||
/// ExitingBlock. More precisely, it is the number of times that control may
|
||||
/// reach ExitingBlock before taking the branch. For loops with multiple
|
||||
/// exits, it may not be the number times that the loop header executes if
|
||||
/// the loop exits prematurely via another branch.
|
||||
unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitingBlock);
|
||||
|
||||
/// getSmallConstantTripMultiple - Returns the largest constant divisor of
|
||||
/// the trip count of this loop as a normal unsigned value, if
|
||||
/// possible. This means that the actual trip count is always a multiple of
|
||||
/// the returned value (don't forget the trip count could very well be zero
|
||||
/// as well!).
|
||||
unsigned getSmallConstantTripMultiple(Loop *L, BasicBlock *ExitBlock);
|
||||
/// as well!). As explained in the comments for getSmallConstantTripCount,
|
||||
/// this assumes that control exits the loop via ExitingBlock.
|
||||
unsigned getSmallConstantTripMultiple(Loop *L, BasicBlock *ExitingBlock);
|
||||
|
||||
// getExitCount - Get the expression for the number of loop iterations for
|
||||
// which this loop is guaranteed not to exit via ExitingBlock. Otherwise
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
class TargetLowering;
|
||||
|
||||
/// SCEVExpander - This class uses information about analyze scalars to
|
||||
/// rewrite expressions in canonical form.
|
||||
///
|
||||
|
|
@ -58,6 +60,9 @@ namespace llvm {
|
|||
/// insert the IV increment at this position.
|
||||
Instruction *IVIncInsertPos;
|
||||
|
||||
/// Phis that complete an IV chain. Reuse
|
||||
std::set<AssertingVH<PHINode> > ChainedPhis;
|
||||
|
||||
/// CanonicalMode - When true, expressions are expanded in "canonical"
|
||||
/// form. In particular, addrecs are expanded as arithmetic based on
|
||||
/// a canonical induction variable. When false, expression are expanded
|
||||
|
|
@ -100,6 +105,7 @@ namespace llvm {
|
|||
InsertedExpressions.clear();
|
||||
InsertedValues.clear();
|
||||
InsertedPostIncValues.clear();
|
||||
ChainedPhis.clear();
|
||||
}
|
||||
|
||||
/// getOrInsertCanonicalInductionVariable - This method returns the
|
||||
|
|
@ -108,14 +114,18 @@ namespace llvm {
|
|||
/// starts at zero and steps by one on each iteration.
|
||||
PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, Type *Ty);
|
||||
|
||||
/// hoistStep - Utility for hoisting an IV increment.
|
||||
static bool hoistStep(Instruction *IncV, Instruction *InsertPos,
|
||||
const DominatorTree *DT);
|
||||
/// getIVIncOperand - Return the induction variable increment's IV operand.
|
||||
Instruction *getIVIncOperand(Instruction *IncV, Instruction *InsertPos,
|
||||
bool allowScale);
|
||||
|
||||
/// hoistIVInc - Utility for hoisting an IV increment.
|
||||
bool hoistIVInc(Instruction *IncV, Instruction *InsertPos);
|
||||
|
||||
/// replaceCongruentIVs - replace congruent phis with their most canonical
|
||||
/// representative. Return the number of phis eliminated.
|
||||
unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT,
|
||||
SmallVectorImpl<WeakVH> &DeadInsts);
|
||||
SmallVectorImpl<WeakVH> &DeadInsts,
|
||||
const TargetLowering *TLI = NULL);
|
||||
|
||||
/// expandCodeFor - Insert code to directly compute the specified SCEV
|
||||
/// expression into the program. The inserted code is inserted into the
|
||||
|
|
@ -161,6 +171,16 @@ namespace llvm {
|
|||
void clearInsertPoint() {
|
||||
Builder.ClearInsertionPoint();
|
||||
}
|
||||
|
||||
/// isInsertedInstruction - Return true if the specified instruction was
|
||||
/// inserted by the code rewriter. If so, the client should not modify the
|
||||
/// instruction.
|
||||
bool isInsertedInstruction(Instruction *I) const {
|
||||
return InsertedValues.count(I) || InsertedPostIncValues.count(I);
|
||||
}
|
||||
|
||||
void setChainedPhi(PHINode *PN) { ChainedPhis.insert(PN); }
|
||||
|
||||
private:
|
||||
LLVMContext &getContext() const { return SE.getContext(); }
|
||||
|
||||
|
|
@ -195,13 +215,6 @@ namespace llvm {
|
|||
/// result will be expanded to have that type, with a cast if necessary.
|
||||
Value *expandCodeFor(const SCEV *SH, Type *Ty = 0);
|
||||
|
||||
/// isInsertedInstruction - Return true if the specified instruction was
|
||||
/// inserted by the code rewriter. If so, the client should not modify the
|
||||
/// instruction.
|
||||
bool isInsertedInstruction(Instruction *I) const {
|
||||
return InsertedValues.count(I) || InsertedPostIncValues.count(I);
|
||||
}
|
||||
|
||||
/// getRelevantLoop - Determine the most "relevant" loop for the given SCEV.
|
||||
const Loop *getRelevantLoop(const SCEV *);
|
||||
|
||||
|
|
@ -244,6 +257,8 @@ namespace llvm {
|
|||
const Loop *L,
|
||||
Type *ExpandTy,
|
||||
Type *IntTy);
|
||||
Value *expandIVInc(PHINode *PN, Value *StepV, const Loop *L,
|
||||
Type *ExpandTy, Type *IntTy, bool useSubtract);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -491,7 +491,6 @@ namespace llvm {
|
|||
|
||||
RetVal visitCouldNotCompute(const SCEVCouldNotCompute *S) {
|
||||
llvm_unreachable("Invalid use of SCEVCouldNotCompute!");
|
||||
return RetVal();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,15 +17,15 @@
|
|||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
template <typename T> class SmallVectorImpl;
|
||||
class Value;
|
||||
class Instruction;
|
||||
class APInt;
|
||||
class TargetData;
|
||||
|
||||
class StringRef;
|
||||
class MDNode;
|
||||
|
||||
/// ComputeMaskedBits - Determine which of the bits specified in Mask are
|
||||
/// known to be either zero or one and return them in the KnownZero/KnownOne
|
||||
/// bit sets. This code only analyzes bits in Mask, in order to short-circuit
|
||||
|
|
@ -36,10 +36,10 @@ namespace llvm {
|
|||
/// where V is a vector, the mask, known zero, and known one values are the
|
||||
/// same width as the vector element, and the bit is set only if it is true
|
||||
/// for all of the elements in the vector.
|
||||
void ComputeMaskedBits(Value *V, const APInt &Mask, APInt &KnownZero,
|
||||
APInt &KnownOne, const TargetData *TD = 0,
|
||||
unsigned Depth = 0);
|
||||
|
||||
void ComputeMaskedBits(Value *V, APInt &KnownZero, APInt &KnownOne,
|
||||
const TargetData *TD = 0, unsigned Depth = 0);
|
||||
void computeMaskedBitsLoad(const MDNode &Ranges, APInt &KnownZero);
|
||||
|
||||
/// ComputeSignBit - Determine whether the sign bit is known to be zero or
|
||||
/// one. Convenience wrapper around ComputeMaskedBits.
|
||||
void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,
|
||||
|
|
@ -48,8 +48,10 @@ namespace llvm {
|
|||
/// isPowerOfTwo - Return true if the given value is known to have exactly one
|
||||
/// bit set when defined. For vectors return true if every element is known to
|
||||
/// be a power of two when defined. Supports values with integer or pointer
|
||||
/// type and vectors of integers.
|
||||
bool isPowerOfTwo(Value *V, const TargetData *TD = 0, unsigned Depth = 0);
|
||||
/// type and vectors of integers. If 'OrZero' is set then returns true if the
|
||||
/// given value is either a power of two or zero.
|
||||
bool isPowerOfTwo(Value *V, const TargetData *TD = 0, bool OrZero = false,
|
||||
unsigned Depth = 0);
|
||||
|
||||
/// isKnownNonZero - Return true if the given value is known to be non-zero
|
||||
/// when defined. For vectors return true if every element is known to be
|
||||
|
|
@ -123,16 +125,15 @@ namespace llvm {
|
|||
return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD);
|
||||
}
|
||||
|
||||
/// GetConstantStringInfo - This function computes the length of a
|
||||
/// getConstantStringInfo - This function computes the length of a
|
||||
/// null-terminated C string pointed to by V. If successful, it returns true
|
||||
/// and returns the string in Str. If unsuccessful, it returns false. If
|
||||
/// StopAtNul is set to true (the default), the returned string is truncated
|
||||
/// by a nul character in the global. If StopAtNul is false, the nul
|
||||
/// character is included in the result string.
|
||||
bool GetConstantStringInfo(const Value *V, std::string &Str,
|
||||
uint64_t Offset = 0,
|
||||
bool StopAtNul = true);
|
||||
|
||||
/// and returns the string in Str. If unsuccessful, it returns false. This
|
||||
/// does not include the trailing nul character by default. If TrimAtNul is
|
||||
/// set to false, then this returns any trailing nul characters as well as any
|
||||
/// other characters that come after it.
|
||||
bool getConstantStringInfo(const Value *V, StringRef &Str,
|
||||
uint64_t Offset = 0, bool TrimAtNul = true);
|
||||
|
||||
/// GetStringLength - If we can compute the length of the string pointed to by
|
||||
/// the specified pointer, return 'len+1'. If we can't, return 0.
|
||||
uint64_t GetStringLength(Value *V);
|
||||
|
|
@ -154,6 +155,27 @@ namespace llvm {
|
|||
/// are lifetime markers.
|
||||
bool onlyUsedByLifetimeMarkers(const Value *V);
|
||||
|
||||
/// isSafeToSpeculativelyExecute - Return true if the instruction does not
|
||||
/// have any effects besides calculating the result and does not have
|
||||
/// undefined behavior.
|
||||
///
|
||||
/// This method never returns true for an instruction that returns true for
|
||||
/// mayHaveSideEffects; however, this method also does some other checks in
|
||||
/// addition. It checks for undefined behavior, like dividing by zero or
|
||||
/// loading from an invalid pointer (but not for undefined results, like a
|
||||
/// shift with a shift amount larger than the width of the result). It checks
|
||||
/// for malloc and alloca because speculatively executing them might cause a
|
||||
/// memory leak. It also returns false for instructions related to control
|
||||
/// flow, specifically terminators and PHI nodes.
|
||||
///
|
||||
/// This method only looks at the instruction itself and its operands, so if
|
||||
/// this method returns true, it is safe to move the instruction as long as
|
||||
/// the correct dominance relationships for the operands and users hold.
|
||||
/// However, this method can return true for instructions that read memory;
|
||||
/// for such instructions, moving them may change the resulting value.
|
||||
bool isSafeToSpeculativelyExecute(const Value *V,
|
||||
const TargetData *TD = 0);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ template<typename ValueSubClass, typename ItemParentClass>
|
|||
/// the function was called with.
|
||||
/// @brief LLVM Argument representation
|
||||
class Argument : public Value, public ilist_node<Argument> {
|
||||
virtual void anchor();
|
||||
Function *Parent;
|
||||
|
||||
friend class SymbolTableListTraits<Argument, Function>;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace llvm {
|
|||
class Function;
|
||||
class BasicBlock;
|
||||
class Instruction;
|
||||
class raw_ostream;
|
||||
class Value;
|
||||
class formatted_raw_ostream;
|
||||
|
||||
class AssemblyAnnotationWriter {
|
||||
|
|
@ -32,30 +32,30 @@ public:
|
|||
|
||||
/// emitFunctionAnnot - This may be implemented to emit a string right before
|
||||
/// the start of a function.
|
||||
virtual void emitFunctionAnnot(const Function *F,
|
||||
formatted_raw_ostream &OS) {}
|
||||
virtual void emitFunctionAnnot(const Function *,
|
||||
formatted_raw_ostream &) {}
|
||||
|
||||
/// emitBasicBlockStartAnnot - This may be implemented to emit a string right
|
||||
/// after the basic block label, but before the first instruction in the
|
||||
/// block.
|
||||
virtual void emitBasicBlockStartAnnot(const BasicBlock *BB,
|
||||
formatted_raw_ostream &OS) {
|
||||
virtual void emitBasicBlockStartAnnot(const BasicBlock *,
|
||||
formatted_raw_ostream &) {
|
||||
}
|
||||
|
||||
/// emitBasicBlockEndAnnot - This may be implemented to emit a string right
|
||||
/// after the basic block.
|
||||
virtual void emitBasicBlockEndAnnot(const BasicBlock *BB,
|
||||
formatted_raw_ostream &OS) {
|
||||
virtual void emitBasicBlockEndAnnot(const BasicBlock *,
|
||||
formatted_raw_ostream &) {
|
||||
}
|
||||
|
||||
/// emitInstructionAnnot - This may be implemented to emit a string right
|
||||
/// before an instruction is emitted.
|
||||
virtual void emitInstructionAnnot(const Instruction *I,
|
||||
formatted_raw_ostream &OS) {}
|
||||
virtual void emitInstructionAnnot(const Instruction *,
|
||||
formatted_raw_ostream &) {}
|
||||
|
||||
/// printInfoComment - This may be implemented to emit a comment to the
|
||||
/// right of an instruction or global value.
|
||||
virtual void printInfoComment(const Value &V, formatted_raw_ostream &OS) {}
|
||||
virtual void printInfoComment(const Value &, formatted_raw_ostream &) {}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ namespace llvm {
|
|||
class Module;
|
||||
class MemoryBuffer;
|
||||
class SMDiagnostic;
|
||||
class raw_ostream;
|
||||
class LLVMContext;
|
||||
|
||||
/// This function is the main interface to the LLVM Assembly Parser. It parses
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
namespace llvm {
|
||||
|
||||
class Type;
|
||||
class Module;
|
||||
class Value;
|
||||
class raw_ostream;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,66 @@
|
|||
namespace llvm {
|
||||
class Type;
|
||||
|
||||
namespace Attribute {
|
||||
/// We use this proxy POD type to allow constructing Attributes constants
|
||||
/// using initializer lists. Do not use this class directly.
|
||||
struct AttrConst {
|
||||
uint64_t v;
|
||||
AttrConst operator | (const AttrConst Attrs) const {
|
||||
AttrConst Res = {v | Attrs.v};
|
||||
return Res;
|
||||
}
|
||||
AttrConst operator ~ () const {
|
||||
AttrConst Res = {~v};
|
||||
return Res;
|
||||
}
|
||||
};
|
||||
} // namespace Attribute
|
||||
|
||||
|
||||
/// Attributes - A bitset of attributes.
|
||||
typedef unsigned Attributes;
|
||||
class Attributes {
|
||||
public:
|
||||
Attributes() : Bits(0) { }
|
||||
explicit Attributes(uint64_t Val) : Bits(Val) { }
|
||||
/*implicit*/ Attributes(Attribute::AttrConst Val) : Bits(Val.v) { }
|
||||
Attributes(const Attributes &Attrs) : Bits(Attrs.Bits) { }
|
||||
// This is a "safe bool() operator".
|
||||
operator const void *() const { return Bits ? this : 0; }
|
||||
bool isEmptyOrSingleton() const { return (Bits & (Bits - 1)) == 0; }
|
||||
Attributes &operator = (const Attributes &Attrs) {
|
||||
Bits = Attrs.Bits;
|
||||
return *this;
|
||||
}
|
||||
bool operator == (const Attributes &Attrs) const {
|
||||
return Bits == Attrs.Bits;
|
||||
}
|
||||
bool operator != (const Attributes &Attrs) const {
|
||||
return Bits != Attrs.Bits;
|
||||
}
|
||||
Attributes operator | (const Attributes &Attrs) const {
|
||||
return Attributes(Bits | Attrs.Bits);
|
||||
}
|
||||
Attributes operator & (const Attributes &Attrs) const {
|
||||
return Attributes(Bits & Attrs.Bits);
|
||||
}
|
||||
Attributes operator ^ (const Attributes &Attrs) const {
|
||||
return Attributes(Bits ^ Attrs.Bits);
|
||||
}
|
||||
Attributes &operator |= (const Attributes &Attrs) {
|
||||
Bits |= Attrs.Bits;
|
||||
return *this;
|
||||
}
|
||||
Attributes &operator &= (const Attributes &Attrs) {
|
||||
Bits &= Attrs.Bits;
|
||||
return *this;
|
||||
}
|
||||
Attributes operator ~ () const { return Attributes(~Bits); }
|
||||
uint64_t Raw() const { return Bits; }
|
||||
private:
|
||||
// Currently, we need less than 64 bits.
|
||||
uint64_t Bits;
|
||||
};
|
||||
|
||||
namespace Attribute {
|
||||
|
||||
|
|
@ -33,44 +91,55 @@ namespace Attribute {
|
|||
/// results or the function itself.
|
||||
/// @brief Function attributes.
|
||||
|
||||
const Attributes None = 0; ///< No attributes have been set
|
||||
const Attributes ZExt = 1<<0; ///< Zero extended before/after call
|
||||
const Attributes SExt = 1<<1; ///< Sign extended before/after call
|
||||
const Attributes NoReturn = 1<<2; ///< Mark the function as not returning
|
||||
const Attributes InReg = 1<<3; ///< Force argument to be passed in register
|
||||
const Attributes StructRet = 1<<4; ///< Hidden pointer to structure to return
|
||||
const Attributes NoUnwind = 1<<5; ///< Function doesn't unwind stack
|
||||
const Attributes NoAlias = 1<<6; ///< Considered to not alias after call
|
||||
const Attributes ByVal = 1<<7; ///< Pass structure by value
|
||||
const Attributes Nest = 1<<8; ///< Nested function static chain
|
||||
const Attributes ReadNone = 1<<9; ///< Function does not access memory
|
||||
const Attributes ReadOnly = 1<<10; ///< Function only reads from memory
|
||||
const Attributes NoInline = 1<<11; ///< inline=never
|
||||
const Attributes AlwaysInline = 1<<12; ///< inline=always
|
||||
const Attributes OptimizeForSize = 1<<13; ///< opt_size
|
||||
const Attributes StackProtect = 1<<14; ///< Stack protection.
|
||||
const Attributes StackProtectReq = 1<<15; ///< Stack protection required.
|
||||
const Attributes Alignment = 31<<16; ///< Alignment of parameter (5 bits)
|
||||
// We declare AttrConst objects that will be used throughout the code
|
||||
// and also raw uint64_t objects with _i suffix to be used below for other
|
||||
// constant declarations. This is done to avoid static CTORs and at the same
|
||||
// time to keep type-safety of Attributes.
|
||||
#define DECLARE_LLVM_ATTRIBUTE(name, value) \
|
||||
const uint64_t name##_i = value; \
|
||||
const AttrConst name = {value};
|
||||
|
||||
DECLARE_LLVM_ATTRIBUTE(None,0) ///< No attributes have been set
|
||||
DECLARE_LLVM_ATTRIBUTE(ZExt,1<<0) ///< Zero extended before/after call
|
||||
DECLARE_LLVM_ATTRIBUTE(SExt,1<<1) ///< Sign extended before/after call
|
||||
DECLARE_LLVM_ATTRIBUTE(NoReturn,1<<2) ///< Mark the function as not returning
|
||||
DECLARE_LLVM_ATTRIBUTE(InReg,1<<3) ///< Force argument to be passed in register
|
||||
DECLARE_LLVM_ATTRIBUTE(StructRet,1<<4) ///< Hidden pointer to structure to return
|
||||
DECLARE_LLVM_ATTRIBUTE(NoUnwind,1<<5) ///< Function doesn't unwind stack
|
||||
DECLARE_LLVM_ATTRIBUTE(NoAlias,1<<6) ///< Considered to not alias after call
|
||||
DECLARE_LLVM_ATTRIBUTE(ByVal,1<<7) ///< Pass structure by value
|
||||
DECLARE_LLVM_ATTRIBUTE(Nest,1<<8) ///< Nested function static chain
|
||||
DECLARE_LLVM_ATTRIBUTE(ReadNone,1<<9) ///< Function does not access memory
|
||||
DECLARE_LLVM_ATTRIBUTE(ReadOnly,1<<10) ///< Function only reads from memory
|
||||
DECLARE_LLVM_ATTRIBUTE(NoInline,1<<11) ///< inline=never
|
||||
DECLARE_LLVM_ATTRIBUTE(AlwaysInline,1<<12) ///< inline=always
|
||||
DECLARE_LLVM_ATTRIBUTE(OptimizeForSize,1<<13) ///< opt_size
|
||||
DECLARE_LLVM_ATTRIBUTE(StackProtect,1<<14) ///< Stack protection.
|
||||
DECLARE_LLVM_ATTRIBUTE(StackProtectReq,1<<15) ///< Stack protection required.
|
||||
DECLARE_LLVM_ATTRIBUTE(Alignment,31<<16) ///< Alignment of parameter (5 bits)
|
||||
// stored as log2 of alignment with +1 bias
|
||||
// 0 means unaligned different from align 1
|
||||
const Attributes NoCapture = 1<<21; ///< Function creates no aliases of pointer
|
||||
const Attributes NoRedZone = 1<<22; /// disable redzone
|
||||
const Attributes NoImplicitFloat = 1<<23; /// disable implicit floating point
|
||||
/// instructions.
|
||||
const Attributes Naked = 1<<24; ///< Naked function
|
||||
const Attributes InlineHint = 1<<25; ///< source said inlining was
|
||||
///desirable
|
||||
const Attributes StackAlignment = 7<<26; ///< Alignment of stack for
|
||||
///function (3 bits) stored as log2
|
||||
///of alignment with +1 bias
|
||||
///0 means unaligned (different from
|
||||
///alignstack(1))
|
||||
const Attributes ReturnsTwice = 1<<29; ///< Function can return twice
|
||||
const Attributes UWTable = 1<<30; ///< Function must be in a unwind
|
||||
///table
|
||||
const Attributes NonLazyBind = 1U<<31; ///< Function is called early and/or
|
||||
/// often, so lazy binding isn't
|
||||
/// worthwhile.
|
||||
DECLARE_LLVM_ATTRIBUTE(NoCapture,1<<21) ///< Function creates no aliases of pointer
|
||||
DECLARE_LLVM_ATTRIBUTE(NoRedZone,1<<22) /// disable redzone
|
||||
DECLARE_LLVM_ATTRIBUTE(NoImplicitFloat,1<<23) /// disable implicit floating point
|
||||
/// instructions.
|
||||
DECLARE_LLVM_ATTRIBUTE(Naked,1<<24) ///< Naked function
|
||||
DECLARE_LLVM_ATTRIBUTE(InlineHint,1<<25) ///< source said inlining was
|
||||
///desirable
|
||||
DECLARE_LLVM_ATTRIBUTE(StackAlignment,7<<26) ///< Alignment of stack for
|
||||
///function (3 bits) stored as log2
|
||||
///of alignment with +1 bias
|
||||
///0 means unaligned (different from
|
||||
///alignstack= {1))
|
||||
DECLARE_LLVM_ATTRIBUTE(ReturnsTwice,1<<29) ///< Function can return twice
|
||||
DECLARE_LLVM_ATTRIBUTE(UWTable,1<<30) ///< Function must be in a unwind
|
||||
///table
|
||||
DECLARE_LLVM_ATTRIBUTE(NonLazyBind,1U<<31) ///< Function is called early and/or
|
||||
/// often, so lazy binding isn't
|
||||
/// worthwhile.
|
||||
DECLARE_LLVM_ATTRIBUTE(AddressSafety,1ULL<<32) ///< Address safety checking is on.
|
||||
|
||||
#undef DECLARE_LLVM_ATTRIBUTE
|
||||
|
||||
/// Note that uwtable is about the ABI or the user mandating an entry in the
|
||||
/// unwind table. The nounwind attribute is about an exception passing by the
|
||||
|
|
@ -85,24 +154,26 @@ const Attributes NonLazyBind = 1U<<31; ///< Function is called early and/or
|
|||
/// uwtable + nounwind = Needs an entry because the ABI says so.
|
||||
|
||||
/// @brief Attributes that only apply to function parameters.
|
||||
const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
|
||||
const AttrConst ParameterOnly = {ByVal_i | Nest_i |
|
||||
StructRet_i | NoCapture_i};
|
||||
|
||||
/// @brief Attributes that may be applied to the function itself. These cannot
|
||||
/// be used on return values or function parameters.
|
||||
const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
|
||||
NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq |
|
||||
NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment |
|
||||
UWTable | NonLazyBind | ReturnsTwice;
|
||||
const AttrConst FunctionOnly = {NoReturn_i | NoUnwind_i | ReadNone_i |
|
||||
ReadOnly_i | NoInline_i | AlwaysInline_i | OptimizeForSize_i |
|
||||
StackProtect_i | StackProtectReq_i | NoRedZone_i | NoImplicitFloat_i |
|
||||
Naked_i | InlineHint_i | StackAlignment_i |
|
||||
UWTable_i | NonLazyBind_i | ReturnsTwice_i | AddressSafety_i};
|
||||
|
||||
/// @brief Parameter attributes that do not apply to vararg call arguments.
|
||||
const Attributes VarArgsIncompatible = StructRet;
|
||||
const AttrConst VarArgsIncompatible = {StructRet_i};
|
||||
|
||||
/// @brief Attributes that are mutually incompatible.
|
||||
const Attributes MutuallyIncompatible[4] = {
|
||||
ByVal | InReg | Nest | StructRet,
|
||||
ZExt | SExt,
|
||||
ReadNone | ReadOnly,
|
||||
NoInline | AlwaysInline
|
||||
const AttrConst MutuallyIncompatible[4] = {
|
||||
{ByVal_i | InReg_i | Nest_i | StructRet_i},
|
||||
{ZExt_i | SExt_i},
|
||||
{ReadNone_i | ReadOnly_i},
|
||||
{NoInline_i | AlwaysInline_i}
|
||||
};
|
||||
|
||||
/// @brief Which attributes cannot be applied to a type.
|
||||
|
|
@ -113,20 +184,20 @@ Attributes typeIncompatible(Type *Ty);
|
|||
inline Attributes constructAlignmentFromInt(unsigned i) {
|
||||
// Default alignment, allow the target to define how to align it.
|
||||
if (i == 0)
|
||||
return 0;
|
||||
return None;
|
||||
|
||||
assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
|
||||
assert(i <= 0x40000000 && "Alignment too large.");
|
||||
return (Log2_32(i)+1) << 16;
|
||||
return Attributes((Log2_32(i)+1) << 16);
|
||||
}
|
||||
|
||||
/// This returns the alignment field of an attribute as a byte alignment value.
|
||||
inline unsigned getAlignmentFromAttrs(Attributes A) {
|
||||
Attributes Align = A & Attribute::Alignment;
|
||||
if (Align == 0)
|
||||
if (!Align)
|
||||
return 0;
|
||||
|
||||
return 1U << ((Align >> 16) - 1);
|
||||
return 1U << ((Align.Raw() >> 16) - 1);
|
||||
}
|
||||
|
||||
/// This turns an int stack alignment (which must be a power of 2) into
|
||||
|
|
@ -134,21 +205,21 @@ inline unsigned getAlignmentFromAttrs(Attributes A) {
|
|||
inline Attributes constructStackAlignmentFromInt(unsigned i) {
|
||||
// Default alignment, allow the target to define how to align it.
|
||||
if (i == 0)
|
||||
return 0;
|
||||
return None;
|
||||
|
||||
assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
|
||||
assert(i <= 0x100 && "Alignment too large.");
|
||||
return (Log2_32(i)+1) << 26;
|
||||
return Attributes((Log2_32(i)+1) << 26);
|
||||
}
|
||||
|
||||
/// This returns the stack alignment field of an attribute as a byte alignment
|
||||
/// value.
|
||||
inline unsigned getStackAlignmentFromAttrs(Attributes A) {
|
||||
Attributes StackAlign = A & Attribute::StackAlignment;
|
||||
if (StackAlign == 0)
|
||||
if (!StackAlign)
|
||||
return 0;
|
||||
|
||||
return 1U << ((StackAlign >> 26) - 1);
|
||||
return 1U << ((StackAlign.Raw() >> 26) - 1);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -242,7 +313,7 @@ public:
|
|||
/// paramHasAttr - Return true if the specified parameter index has the
|
||||
/// specified attribute set.
|
||||
bool paramHasAttr(unsigned Idx, Attributes Attr) const {
|
||||
return (getAttributes(Idx) & Attr) != 0;
|
||||
return getAttributes(Idx) & Attr;
|
||||
}
|
||||
|
||||
/// getParamAlignment - Return the alignment for the specified function
|
||||
|
|
|
|||
|
|
@ -39,14 +39,6 @@ namespace llvm {
|
|||
/// This checks for global variables which should be upgraded. It returns true
|
||||
/// if it requires upgrading.
|
||||
bool UpgradeGlobalVariable(GlobalVariable *GV);
|
||||
|
||||
/// This function checks debug info intrinsics. If an intrinsic is invalid
|
||||
/// then this function simply removes the intrinsic.
|
||||
void CheckDebugInfoIntrinsics(Module *M);
|
||||
|
||||
/// This function upgrades the old pre-3.0 exception handling system to the
|
||||
/// new one. N.B. This will be removed in 3.1.
|
||||
void UpgradeExceptionHandling(Module *M);
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -110,12 +110,6 @@ public:
|
|||
const Function *getParent() const { return Parent; }
|
||||
Function *getParent() { return Parent; }
|
||||
|
||||
/// use_back - Specialize the methods defined in Value, as we know that an
|
||||
/// BasicBlock can only be used by Users (specifically terminators
|
||||
/// and BlockAddress's).
|
||||
User *use_back() { return cast<User>(*use_begin());}
|
||||
const User *use_back() const { return cast<User>(*use_begin());}
|
||||
|
||||
/// getTerminator() - If this is a well formed basic block, then this returns
|
||||
/// a pointer to the terminator instruction. If it is not, then you get a
|
||||
/// null pointer back.
|
||||
|
|
@ -274,6 +268,7 @@ public:
|
|||
/// getLandingPadInst() - Return the landingpad instruction associated with
|
||||
/// the landing pad.
|
||||
LandingPadInst *getLandingPadInst();
|
||||
const LandingPadInst *getLandingPadInst() const;
|
||||
|
||||
private:
|
||||
/// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ class Archive {
|
|||
/// @brief Look up multiple symbols in the archive.
|
||||
bool findModulesDefiningSymbols(
|
||||
std::set<std::string>& symbols, ///< Symbols to be sought
|
||||
std::set<Module*>& modules, ///< The modules matching \p symbols
|
||||
SmallVectorImpl<Module*>& modules, ///< The modules matching \p symbols
|
||||
std::string* ErrMessage ///< Error msg storage, if non-zero
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
|
|
@ -114,7 +115,6 @@ public:
|
|||
bool hasEncodingData() const { return hasEncodingData(getEncoding()); }
|
||||
static bool hasEncodingData(Encoding E) {
|
||||
switch (E) {
|
||||
default: assert(0 && "Unknown encoding");
|
||||
case Fixed:
|
||||
case VBR:
|
||||
return true;
|
||||
|
|
@ -123,6 +123,7 @@ public:
|
|||
case Blob:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("Invalid encoding");
|
||||
}
|
||||
|
||||
/// isChar6 - Return true if this character is legal in the Char6 encoding.
|
||||
|
|
@ -139,8 +140,7 @@ public:
|
|||
if (C >= '0' && C <= '9') return C-'0'+26+26;
|
||||
if (C == '.') return 62;
|
||||
if (C == '_') return 63;
|
||||
assert(0 && "Not a value Char6 character!");
|
||||
return 0;
|
||||
llvm_unreachable("Not a value Char6 character!");
|
||||
}
|
||||
|
||||
static char DecodeChar6(unsigned V) {
|
||||
|
|
@ -150,17 +150,18 @@ public:
|
|||
if (V < 26+26+10) return V-26-26+'0';
|
||||
if (V == 62) return '.';
|
||||
if (V == 63) return '_';
|
||||
assert(0 && "Not a value Char6 character!");
|
||||
return ' ';
|
||||
llvm_unreachable("Not a value Char6 character!");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; };
|
||||
|
||||
/// BitCodeAbbrev - This class represents an abbreviation record. An
|
||||
/// abbreviation allows a complex record that has redundancy to be stored in a
|
||||
/// specialized format instead of the fully-general, fully-vbr, format.
|
||||
class BitCodeAbbrev {
|
||||
SmallVector<BitCodeAbbrevOp, 8> OperandList;
|
||||
SmallVector<BitCodeAbbrevOp, 32> OperandList;
|
||||
unsigned char RefCount; // Number of things using this.
|
||||
~BitCodeAbbrev() {}
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@
|
|||
#ifndef BITSTREAM_READER_H
|
||||
#define BITSTREAM_READER_H
|
||||
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/Bitcode/BitCodes.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/StreamableMemoryObject.h"
|
||||
#include <climits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
|
@ -36,9 +39,7 @@ public:
|
|||
std::vector<std::pair<unsigned, std::string> > RecordNames;
|
||||
};
|
||||
private:
|
||||
/// FirstChar/LastChar - This remembers the first and last bytes of the
|
||||
/// stream.
|
||||
const unsigned char *FirstChar, *LastChar;
|
||||
OwningPtr<StreamableMemoryObject> BitcodeBytes;
|
||||
|
||||
std::vector<BlockInfo> BlockInfoRecords;
|
||||
|
||||
|
|
@ -47,10 +48,10 @@ private:
|
|||
/// uses this.
|
||||
bool IgnoreBlockInfoNames;
|
||||
|
||||
BitstreamReader(const BitstreamReader&); // NOT IMPLEMENTED
|
||||
void operator=(const BitstreamReader&); // NOT IMPLEMENTED
|
||||
BitstreamReader(const BitstreamReader&); // DO NOT IMPLEMENT
|
||||
void operator=(const BitstreamReader&); // DO NOT IMPLEMENT
|
||||
public:
|
||||
BitstreamReader() : FirstChar(0), LastChar(0), IgnoreBlockInfoNames(true) {
|
||||
BitstreamReader() : IgnoreBlockInfoNames(true) {
|
||||
}
|
||||
|
||||
BitstreamReader(const unsigned char *Start, const unsigned char *End) {
|
||||
|
|
@ -58,12 +59,17 @@ public:
|
|||
init(Start, End);
|
||||
}
|
||||
|
||||
void init(const unsigned char *Start, const unsigned char *End) {
|
||||
FirstChar = Start;
|
||||
LastChar = End;
|
||||
assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
|
||||
BitstreamReader(StreamableMemoryObject *bytes) {
|
||||
BitcodeBytes.reset(bytes);
|
||||
}
|
||||
|
||||
void init(const unsigned char *Start, const unsigned char *End) {
|
||||
assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
|
||||
BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End));
|
||||
}
|
||||
|
||||
StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; }
|
||||
|
||||
~BitstreamReader() {
|
||||
// Free the BlockInfoRecords.
|
||||
while (!BlockInfoRecords.empty()) {
|
||||
|
|
@ -75,9 +81,6 @@ public:
|
|||
BlockInfoRecords.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned char *getFirstChar() const { return FirstChar; }
|
||||
const unsigned char *getLastChar() const { return LastChar; }
|
||||
|
||||
/// CollectBlockInfoNames - This is called by clients that want block/record
|
||||
/// name information.
|
||||
|
|
@ -122,7 +125,7 @@ public:
|
|||
class BitstreamCursor {
|
||||
friend class Deserializer;
|
||||
BitstreamReader *BitStream;
|
||||
const unsigned char *NextChar;
|
||||
size_t NextChar;
|
||||
|
||||
/// CurWord - This is the current data we have pulled from the stream but have
|
||||
/// not returned to the client.
|
||||
|
|
@ -156,8 +159,7 @@ public:
|
|||
}
|
||||
|
||||
explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) {
|
||||
NextChar = R.getFirstChar();
|
||||
assert(NextChar && "Bitstream not initialized yet");
|
||||
NextChar = 0;
|
||||
CurWord = 0;
|
||||
BitsInCurWord = 0;
|
||||
CurCodeSize = 2;
|
||||
|
|
@ -167,8 +169,7 @@ public:
|
|||
freeState();
|
||||
|
||||
BitStream = &R;
|
||||
NextChar = R.getFirstChar();
|
||||
assert(NextChar && "Bitstream not initialized yet");
|
||||
NextChar = 0;
|
||||
CurWord = 0;
|
||||
BitsInCurWord = 0;
|
||||
CurCodeSize = 2;
|
||||
|
|
@ -225,13 +226,39 @@ public:
|
|||
/// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
|
||||
unsigned GetAbbrevIDWidth() const { return CurCodeSize; }
|
||||
|
||||
bool AtEndOfStream() const {
|
||||
return NextChar == BitStream->getLastChar() && BitsInCurWord == 0;
|
||||
bool isEndPos(size_t pos) {
|
||||
return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos));
|
||||
}
|
||||
|
||||
bool canSkipToPos(size_t pos) const {
|
||||
// pos can be skipped to if it is a valid address or one byte past the end.
|
||||
return pos == 0 || BitStream->getBitcodeBytes().isValidAddress(
|
||||
static_cast<uint64_t>(pos - 1));
|
||||
}
|
||||
|
||||
unsigned char getByte(size_t pos) {
|
||||
uint8_t byte = -1;
|
||||
BitStream->getBitcodeBytes().readByte(pos, &byte);
|
||||
return byte;
|
||||
}
|
||||
|
||||
uint32_t getWord(size_t pos) {
|
||||
uint8_t buf[sizeof(uint32_t)];
|
||||
memset(buf, 0xFF, sizeof(buf));
|
||||
BitStream->getBitcodeBytes().readBytes(pos,
|
||||
sizeof(buf),
|
||||
buf,
|
||||
NULL);
|
||||
return *reinterpret_cast<support::ulittle32_t *>(buf);
|
||||
}
|
||||
|
||||
bool AtEndOfStream() {
|
||||
return isEndPos(NextChar) && BitsInCurWord == 0;
|
||||
}
|
||||
|
||||
/// GetCurrentBitNo - Return the bit # of the bit we are reading.
|
||||
uint64_t GetCurrentBitNo() const {
|
||||
return (NextChar-BitStream->getFirstChar())*CHAR_BIT - BitsInCurWord;
|
||||
return NextChar*CHAR_BIT - BitsInCurWord;
|
||||
}
|
||||
|
||||
BitstreamReader *getBitStreamReader() {
|
||||
|
|
@ -246,12 +273,10 @@ public:
|
|||
void JumpToBit(uint64_t BitNo) {
|
||||
uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3;
|
||||
uintptr_t WordBitNo = uintptr_t(BitNo) & 31;
|
||||
assert(ByteNo <= (uintptr_t)(BitStream->getLastChar()-
|
||||
BitStream->getFirstChar()) &&
|
||||
"Invalid location");
|
||||
assert(canSkipToPos(ByteNo) && "Invalid location");
|
||||
|
||||
// Move the cursor to the right word.
|
||||
NextChar = BitStream->getFirstChar()+ByteNo;
|
||||
NextChar = ByteNo;
|
||||
BitsInCurWord = 0;
|
||||
CurWord = 0;
|
||||
|
||||
|
|
@ -272,7 +297,7 @@ public:
|
|||
}
|
||||
|
||||
// If we run out of data, stop at the end of the stream.
|
||||
if (NextChar == BitStream->getLastChar()) {
|
||||
if (isEndPos(NextChar)) {
|
||||
CurWord = 0;
|
||||
BitsInCurWord = 0;
|
||||
return 0;
|
||||
|
|
@ -281,8 +306,7 @@ public:
|
|||
unsigned R = CurWord;
|
||||
|
||||
// Read the next word from the stream.
|
||||
CurWord = (NextChar[0] << 0) | (NextChar[1] << 8) |
|
||||
(NextChar[2] << 16) | (NextChar[3] << 24);
|
||||
CurWord = getWord(NextChar);
|
||||
NextChar += 4;
|
||||
|
||||
// Extract NumBits-BitsInCurWord from what we just read.
|
||||
|
|
@ -376,9 +400,8 @@ public:
|
|||
|
||||
// Check that the block wasn't partially defined, and that the offset isn't
|
||||
// bogus.
|
||||
const unsigned char *const SkipTo = NextChar + NumWords*4;
|
||||
if (AtEndOfStream() || SkipTo > BitStream->getLastChar() ||
|
||||
SkipTo < BitStream->getFirstChar())
|
||||
size_t SkipTo = NextChar + NumWords*4;
|
||||
if (AtEndOfStream() || !canSkipToPos(SkipTo))
|
||||
return true;
|
||||
|
||||
NextChar = SkipTo;
|
||||
|
|
@ -409,8 +432,7 @@ public:
|
|||
if (NumWordsP) *NumWordsP = NumWords;
|
||||
|
||||
// Validate that this block is sane.
|
||||
if (CurCodeSize == 0 || AtEndOfStream() ||
|
||||
NextChar+NumWords*4 > BitStream->getLastChar())
|
||||
if (CurCodeSize == 0 || AtEndOfStream())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
@ -455,10 +477,10 @@ private:
|
|||
void ReadAbbreviatedField(const BitCodeAbbrevOp &Op,
|
||||
SmallVectorImpl<uint64_t> &Vals) {
|
||||
assert(!Op.isLiteral() && "Use ReadAbbreviatedLiteral for literals!");
|
||||
|
||||
|
||||
// Decode the value as we are commanded.
|
||||
switch (Op.getEncoding()) {
|
||||
default: assert(0 && "Unknown encoding!");
|
||||
default: llvm_unreachable("Unknown encoding!");
|
||||
case BitCodeAbbrevOp::Fixed:
|
||||
Vals.push_back(Read((unsigned)Op.getEncodingData()));
|
||||
break;
|
||||
|
|
@ -512,24 +534,25 @@ public:
|
|||
SkipToWord(); // 32-bit alignment
|
||||
|
||||
// Figure out where the end of this blob will be including tail padding.
|
||||
const unsigned char *NewEnd = NextChar+((NumElts+3)&~3);
|
||||
size_t NewEnd = NextChar+((NumElts+3)&~3);
|
||||
|
||||
// If this would read off the end of the bitcode file, just set the
|
||||
// record to empty and return.
|
||||
if (NewEnd > BitStream->getLastChar()) {
|
||||
if (!canSkipToPos(NewEnd)) {
|
||||
Vals.append(NumElts, 0);
|
||||
NextChar = BitStream->getLastChar();
|
||||
NextChar = BitStream->getBitcodeBytes().getExtent();
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, read the number of bytes. If we can return a reference to
|
||||
// the data, do so to avoid copying it.
|
||||
if (BlobStart) {
|
||||
*BlobStart = (const char*)NextChar;
|
||||
*BlobStart = (const char*)BitStream->getBitcodeBytes().getPointer(
|
||||
NextChar, NumElts);
|
||||
*BlobLen = NumElts;
|
||||
} else {
|
||||
for (; NumElts; ++NextChar, --NumElts)
|
||||
Vals.push_back(*NextChar);
|
||||
Vals.push_back(getByte(NextChar));
|
||||
}
|
||||
// Skip over tail padding.
|
||||
NextChar = NewEnd;
|
||||
|
|
|
|||
|
|
@ -16,13 +16,14 @@
|
|||
#define BITSTREAM_WRITER_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Bitcode/BitCodes.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BitstreamWriter {
|
||||
std::vector<unsigned char> &Out;
|
||||
SmallVectorImpl<char> &Out;
|
||||
|
||||
/// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use.
|
||||
unsigned CurBit;
|
||||
|
|
@ -59,8 +60,40 @@ class BitstreamWriter {
|
|||
};
|
||||
std::vector<BlockInfo> BlockInfoRecords;
|
||||
|
||||
// BackpatchWord - Backpatch a 32-bit word in the output with the specified
|
||||
// value.
|
||||
void BackpatchWord(unsigned ByteNo, unsigned NewWord) {
|
||||
Out[ByteNo++] = (unsigned char)(NewWord >> 0);
|
||||
Out[ByteNo++] = (unsigned char)(NewWord >> 8);
|
||||
Out[ByteNo++] = (unsigned char)(NewWord >> 16);
|
||||
Out[ByteNo ] = (unsigned char)(NewWord >> 24);
|
||||
}
|
||||
|
||||
void WriteByte(unsigned char Value) {
|
||||
Out.push_back(Value);
|
||||
}
|
||||
|
||||
void WriteWord(unsigned Value) {
|
||||
unsigned char Bytes[4] = {
|
||||
(unsigned char)(Value >> 0),
|
||||
(unsigned char)(Value >> 8),
|
||||
(unsigned char)(Value >> 16),
|
||||
(unsigned char)(Value >> 24) };
|
||||
Out.append(&Bytes[0], &Bytes[4]);
|
||||
}
|
||||
|
||||
unsigned GetBufferOffset() const {
|
||||
return Out.size();
|
||||
}
|
||||
|
||||
unsigned GetWordIndex() const {
|
||||
unsigned Offset = GetBufferOffset();
|
||||
assert((Offset & 3) == 0 && "Not 32-bit aligned");
|
||||
return Offset / 4;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit BitstreamWriter(std::vector<unsigned char> &O)
|
||||
explicit BitstreamWriter(SmallVectorImpl<char> &O)
|
||||
: Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {}
|
||||
|
||||
~BitstreamWriter() {
|
||||
|
|
@ -78,10 +111,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned char> &getBuffer() { return Out; }
|
||||
|
||||
/// \brief Retrieve the current position in the stream, in bits.
|
||||
uint64_t GetCurrentBitNo() const { return Out.size() * 8 + CurBit; }
|
||||
uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; }
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Basic Primitives for emitting bits to the stream.
|
||||
|
|
@ -97,11 +128,7 @@ public:
|
|||
}
|
||||
|
||||
// Add the current word.
|
||||
unsigned V = CurValue;
|
||||
Out.push_back((unsigned char)(V >> 0));
|
||||
Out.push_back((unsigned char)(V >> 8));
|
||||
Out.push_back((unsigned char)(V >> 16));
|
||||
Out.push_back((unsigned char)(V >> 24));
|
||||
WriteWord(CurValue);
|
||||
|
||||
if (CurBit)
|
||||
CurValue = Val >> (32-CurBit);
|
||||
|
|
@ -121,11 +148,7 @@ public:
|
|||
|
||||
void FlushToWord() {
|
||||
if (CurBit) {
|
||||
unsigned V = CurValue;
|
||||
Out.push_back((unsigned char)(V >> 0));
|
||||
Out.push_back((unsigned char)(V >> 8));
|
||||
Out.push_back((unsigned char)(V >> 16));
|
||||
Out.push_back((unsigned char)(V >> 24));
|
||||
WriteWord(CurValue);
|
||||
CurBit = 0;
|
||||
CurValue = 0;
|
||||
}
|
||||
|
|
@ -164,15 +187,6 @@ public:
|
|||
Emit(Val, CurCodeSize);
|
||||
}
|
||||
|
||||
// BackpatchWord - Backpatch a 32-bit word in the output with the specified
|
||||
// value.
|
||||
void BackpatchWord(unsigned ByteNo, unsigned NewWord) {
|
||||
Out[ByteNo++] = (unsigned char)(NewWord >> 0);
|
||||
Out[ByteNo++] = (unsigned char)(NewWord >> 8);
|
||||
Out[ByteNo++] = (unsigned char)(NewWord >> 16);
|
||||
Out[ByteNo ] = (unsigned char)(NewWord >> 24);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Block Manipulation
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
@ -199,7 +213,7 @@ public:
|
|||
EmitVBR(CodeLen, bitc::CodeLenWidth);
|
||||
FlushToWord();
|
||||
|
||||
unsigned BlockSizeWordLoc = static_cast<unsigned>(Out.size());
|
||||
unsigned BlockSizeWordIndex = GetWordIndex();
|
||||
unsigned OldCodeSize = CurCodeSize;
|
||||
|
||||
// Emit a placeholder, which will be replaced when the block is popped.
|
||||
|
|
@ -209,7 +223,7 @@ public:
|
|||
|
||||
// Push the outer block's abbrev set onto the stack, start out with an
|
||||
// empty abbrev set.
|
||||
BlockScope.push_back(Block(OldCodeSize, BlockSizeWordLoc/4));
|
||||
BlockScope.push_back(Block(OldCodeSize, BlockSizeWordIndex));
|
||||
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
|
||||
|
||||
// If there is a blockinfo for this BlockID, add all the predefined abbrevs
|
||||
|
|
@ -239,7 +253,7 @@ public:
|
|||
FlushToWord();
|
||||
|
||||
// Compute the size of the block, in words, not counting the size field.
|
||||
unsigned SizeInWords= static_cast<unsigned>(Out.size())/4-B.StartSizeWord-1;
|
||||
unsigned SizeInWords = GetWordIndex() - B.StartSizeWord - 1;
|
||||
unsigned ByteNo = B.StartSizeWord*4;
|
||||
|
||||
// Update the block size field in the header of this sub-block.
|
||||
|
|
@ -275,7 +289,7 @@ private:
|
|||
|
||||
// Encode the value as we are commanded.
|
||||
switch (Op.getEncoding()) {
|
||||
default: assert(0 && "Unknown encoding!");
|
||||
default: llvm_unreachable("Unknown encoding!");
|
||||
case BitCodeAbbrevOp::Fixed:
|
||||
if (Op.getEncodingData())
|
||||
Emit((unsigned)V, (unsigned)Op.getEncodingData());
|
||||
|
|
@ -355,25 +369,24 @@ private:
|
|||
|
||||
// Flush to a 32-bit alignment boundary.
|
||||
FlushToWord();
|
||||
assert((Out.size() & 3) == 0 && "Not 32-bit aligned");
|
||||
|
||||
// Emit each field as a literal byte.
|
||||
if (BlobData) {
|
||||
for (unsigned i = 0; i != BlobLen; ++i)
|
||||
Out.push_back((unsigned char)BlobData[i]);
|
||||
WriteByte((unsigned char)BlobData[i]);
|
||||
|
||||
// Know that blob data is consumed for assertion below.
|
||||
BlobData = 0;
|
||||
} else {
|
||||
for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) {
|
||||
assert(Vals[RecordIdx] < 256 && "Value too large to emit as blob");
|
||||
Out.push_back((unsigned char)Vals[RecordIdx]);
|
||||
WriteByte((unsigned char)Vals[RecordIdx]);
|
||||
}
|
||||
}
|
||||
|
||||
// Align end to 32-bits.
|
||||
while (Out.size() & 3)
|
||||
Out.push_back(0);
|
||||
|
||||
while (GetBufferOffset() & 3)
|
||||
WriteByte(0);
|
||||
} else { // Single scalar field.
|
||||
assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
|
||||
EmitAbbreviatedField(Op, Vals[RecordIdx]);
|
||||
|
|
@ -488,7 +501,7 @@ public:
|
|||
/// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
|
||||
void EnterBlockInfoBlock(unsigned CodeWidth) {
|
||||
EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, CodeWidth);
|
||||
BlockInfoCurBID = -1U;
|
||||
BlockInfoCurBID = ~0U;
|
||||
}
|
||||
private:
|
||||
/// SwitchToBlockID - If we aren't already talking about the specified block
|
||||
|
|
|
|||
|
|
@ -29,23 +29,21 @@ namespace bitc {
|
|||
|
||||
// Module sub-block id's.
|
||||
PARAMATTR_BLOCK_ID,
|
||||
|
||||
/// TYPE_BLOCK_ID_OLD - This is the type descriptor block in LLVM 2.9 and
|
||||
/// earlier, replaced with TYPE_BLOCK_ID2. FIXME: Remove in LLVM 3.1.
|
||||
TYPE_BLOCK_ID_OLD,
|
||||
|
||||
UNUSED_ID1,
|
||||
|
||||
CONSTANTS_BLOCK_ID,
|
||||
FUNCTION_BLOCK_ID,
|
||||
|
||||
/// TYPE_SYMTAB_BLOCK_ID_OLD - This type descriptor is from LLVM 2.9 and
|
||||
/// earlier bitcode files. FIXME: Remove in LLVM 3.1
|
||||
TYPE_SYMTAB_BLOCK_ID_OLD,
|
||||
UNUSED_ID2,
|
||||
|
||||
VALUE_SYMTAB_BLOCK_ID,
|
||||
METADATA_BLOCK_ID,
|
||||
METADATA_ATTACHMENT_ID,
|
||||
|
||||
TYPE_BLOCK_ID_NEW
|
||||
TYPE_BLOCK_ID_NEW,
|
||||
|
||||
USELIST_BLOCK_ID
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -63,10 +61,10 @@ namespace bitc {
|
|||
MODULE_CODE_GLOBALVAR = 7,
|
||||
|
||||
// FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment,
|
||||
// section, visibility]
|
||||
// section, visibility, gc, unnamed_addr]
|
||||
MODULE_CODE_FUNCTION = 8,
|
||||
|
||||
// ALIAS: [alias type, aliasee val#, linkage]
|
||||
// ALIAS: [alias type, aliasee val#, linkage, visibility]
|
||||
MODULE_CODE_ALIAS = 9,
|
||||
|
||||
/// MODULE_CODE_PURGEVALS: [numvals]
|
||||
|
|
@ -92,11 +90,12 @@ namespace bitc {
|
|||
TYPE_CODE_OPAQUE = 6, // OPAQUE
|
||||
TYPE_CODE_INTEGER = 7, // INTEGER: [width]
|
||||
TYPE_CODE_POINTER = 8, // POINTER: [pointee type]
|
||||
TYPE_CODE_FUNCTION = 9, // FUNCTION: [vararg, retty, paramty x N]
|
||||
|
||||
TYPE_CODE_FUNCTION_OLD = 9, // FUNCTION: [vararg, attrid, retty,
|
||||
// paramty x N]
|
||||
|
||||
TYPE_CODE_HALF = 10, // HALF
|
||||
|
||||
// FIXME: This is the encoding used for structs in LLVM 2.9 and earlier.
|
||||
// REMOVE this in LLVM 3.1
|
||||
TYPE_CODE_STRUCT_OLD = 10, // STRUCT: [ispacked, eltty x N]
|
||||
TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty]
|
||||
TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty]
|
||||
|
||||
|
|
@ -113,7 +112,9 @@ namespace bitc {
|
|||
|
||||
TYPE_CODE_STRUCT_ANON = 18, // STRUCT_ANON: [ispacked, eltty x N]
|
||||
TYPE_CODE_STRUCT_NAME = 19, // STRUCT_NAME: [strchr x N]
|
||||
TYPE_CODE_STRUCT_NAMED = 20 // STRUCT_NAMED: [ispacked, eltty x N]
|
||||
TYPE_CODE_STRUCT_NAMED = 20,// STRUCT_NAMED: [ispacked, eltty x N]
|
||||
|
||||
TYPE_CODE_FUNCTION = 21 // FUNCTION: [vararg, retty, paramty x N]
|
||||
};
|
||||
|
||||
// The type symbol table only has one code (TST_ENTRY_CODE).
|
||||
|
|
@ -163,7 +164,8 @@ namespace bitc {
|
|||
CST_CODE_INLINEASM = 18, // INLINEASM: [sideeffect,asmstr,conststr]
|
||||
CST_CODE_CE_SHUFVEC_EX = 19, // SHUFVEC_EX: [opty, opval, opval, opval]
|
||||
CST_CODE_CE_INBOUNDS_GEP = 20,// INBOUNDS_GEP: [n x operands]
|
||||
CST_CODE_BLOCKADDRESS = 21 // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#]
|
||||
CST_CODE_BLOCKADDRESS = 21, // CST_CODE_BLOCKADDRESS [fnty, fnval, bb#]
|
||||
CST_CODE_DATA = 22 // DATA: [n x elements]
|
||||
};
|
||||
|
||||
/// CastOpcodes - These are values used in the bitcode files to encode which
|
||||
|
|
@ -270,7 +272,7 @@ namespace bitc {
|
|||
FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#]
|
||||
FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, op0, op1, ...]
|
||||
FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...]
|
||||
FUNC_CODE_INST_UNWIND = 14, // UNWIND
|
||||
// 14 is unused.
|
||||
FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE
|
||||
|
||||
FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...]
|
||||
|
|
@ -314,6 +316,10 @@ namespace bitc {
|
|||
FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol
|
||||
// ordering, synchscope]
|
||||
};
|
||||
|
||||
enum UseListCodes {
|
||||
USELIST_CODE_ENTRY = 1 // USELIST_CODE_ENTRY: TBD.
|
||||
};
|
||||
} // End bitc namespace
|
||||
} // End llvm namespace
|
||||
|
||||
|
|
|
|||
|
|
@ -17,35 +17,45 @@
|
|||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class Module;
|
||||
class MemoryBuffer;
|
||||
class ModulePass;
|
||||
class BitstreamWriter;
|
||||
class MemoryBuffer;
|
||||
class DataStreamer;
|
||||
class LLVMContext;
|
||||
class Module;
|
||||
class ModulePass;
|
||||
class raw_ostream;
|
||||
|
||||
|
||||
/// getLazyBitcodeModule - Read the header of the specified bitcode buffer
|
||||
/// and prepare for lazy deserialization of function bodies. If successful,
|
||||
/// this takes ownership of 'buffer' and returns a non-null pointer. On
|
||||
/// error, this returns null, *does not* take ownership of Buffer, and fills
|
||||
/// in *ErrMsg with an error description if ErrMsg is non-null.
|
||||
Module *getLazyBitcodeModule(MemoryBuffer *Buffer,
|
||||
LLVMContext& Context,
|
||||
LLVMContext &Context,
|
||||
std::string *ErrMsg = 0);
|
||||
|
||||
/// getStreamedBitcodeModule - Read the header of the specified stream
|
||||
/// and prepare for lazy deserialization and streaming of function bodies.
|
||||
/// On error, this returns null, and fills in *ErrMsg with an error
|
||||
/// description if ErrMsg is non-null.
|
||||
Module *getStreamedBitcodeModule(const std::string &name,
|
||||
DataStreamer *streamer,
|
||||
LLVMContext &Context,
|
||||
std::string *ErrMsg = 0);
|
||||
|
||||
/// getBitcodeTargetTriple - Read the header of the specified bitcode
|
||||
/// buffer and extract just the triple information. If successful,
|
||||
/// this returns a string and *does not* take ownership
|
||||
/// of 'buffer'. On error, this returns "", and fills in *ErrMsg
|
||||
/// if ErrMsg is non-null.
|
||||
std::string getBitcodeTargetTriple(MemoryBuffer *Buffer,
|
||||
LLVMContext& Context,
|
||||
LLVMContext &Context,
|
||||
std::string *ErrMsg = 0);
|
||||
|
||||
/// ParseBitcodeFile - Read the specified bitcode file, returning the module.
|
||||
/// If an error occurs, this returns null and fills in *ErrMsg if it is
|
||||
/// non-null. This method *never* takes ownership of Buffer.
|
||||
Module *ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext& Context,
|
||||
Module *ParseBitcodeFile(MemoryBuffer *Buffer, LLVMContext &Context,
|
||||
std::string *ErrMsg = 0);
|
||||
|
||||
/// WriteBitcodeToFile - Write the specified module to the specified
|
||||
|
|
@ -53,15 +63,11 @@ namespace llvm {
|
|||
/// should be in "binary" mode.
|
||||
void WriteBitcodeToFile(const Module *M, raw_ostream &Out);
|
||||
|
||||
/// WriteBitcodeToStream - Write the specified module to the specified
|
||||
/// raw output stream.
|
||||
void WriteBitcodeToStream(const Module *M, BitstreamWriter &Stream);
|
||||
|
||||
/// createBitcodeWriterPass - Create and return a pass that writes the module
|
||||
/// to the specified ostream.
|
||||
ModulePass *createBitcodeWriterPass(raw_ostream &Str);
|
||||
|
||||
|
||||
|
||||
|
||||
/// isBitcodeWrapper - Return true if the given bytes are the magic bytes
|
||||
/// for an LLVM IR bitcode wrapper.
|
||||
///
|
||||
|
|
@ -109,21 +115,24 @@ namespace llvm {
|
|||
/// uint32_t BitcodeSize; // Size of traditional bitcode file.
|
||||
/// ... potentially other gunk ...
|
||||
/// };
|
||||
///
|
||||
///
|
||||
/// This function is called when we find a file with a matching magic number.
|
||||
/// In this case, skip down to the subsection of the file that is actually a
|
||||
/// BC file.
|
||||
static inline bool SkipBitcodeWrapperHeader(unsigned char *&BufPtr,
|
||||
unsigned char *&BufEnd) {
|
||||
/// If 'VerifyBufferSize' is true, check that the buffer is large enough to
|
||||
/// contain the whole bitcode file.
|
||||
static inline bool SkipBitcodeWrapperHeader(const unsigned char *&BufPtr,
|
||||
const unsigned char *&BufEnd,
|
||||
bool VerifyBufferSize) {
|
||||
enum {
|
||||
KnownHeaderSize = 4*4, // Size of header we read.
|
||||
OffsetField = 2*4, // Offset in bytes to Offset field.
|
||||
SizeField = 3*4 // Offset in bytes to Size field.
|
||||
};
|
||||
|
||||
|
||||
// Must contain the header!
|
||||
if (BufEnd-BufPtr < KnownHeaderSize) return true;
|
||||
|
||||
|
||||
unsigned Offset = ( BufPtr[OffsetField ] |
|
||||
(BufPtr[OffsetField+1] << 8) |
|
||||
(BufPtr[OffsetField+2] << 16) |
|
||||
|
|
@ -132,9 +141,9 @@ namespace llvm {
|
|||
(BufPtr[SizeField +1] << 8) |
|
||||
(BufPtr[SizeField +2] << 16) |
|
||||
(BufPtr[SizeField +3] << 24));
|
||||
|
||||
|
||||
// Verify that Offset+Size fits in the file.
|
||||
if (Offset+Size > unsigned(BufEnd-BufPtr))
|
||||
if (VerifyBufferSize && Offset+Size > unsigned(BufEnd-BufPtr))
|
||||
return true;
|
||||
BufPtr += Offset;
|
||||
BufEnd = BufPtr+Size;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ namespace llvm {
|
|||
class GlobalVariable;
|
||||
class TargetLowering;
|
||||
class SDNode;
|
||||
class SDValue;
|
||||
class SelectionDAG;
|
||||
|
||||
/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence
|
||||
|
|
@ -70,6 +71,10 @@ bool hasInlineAsmMemConstraint(InlineAsm::ConstraintInfoVector &CInfos,
|
|||
///
|
||||
ISD::CondCode getFCmpCondCode(FCmpInst::Predicate Pred);
|
||||
|
||||
/// getFCmpCodeWithoutNaN - Given an ISD condition code comparing floats,
|
||||
/// return the equivalent code if we're allowed to assume that NaNs won't occur.
|
||||
ISD::CondCode getFCmpCodeWithoutNaN(ISD::CondCode CC);
|
||||
|
||||
/// getICmpCondCode - Return the ISD condition code corresponding to
|
||||
/// the given LLVM IR integer condition code.
|
||||
///
|
||||
|
|
@ -85,7 +90,7 @@ bool isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr,
|
|||
const TargetLowering &TLI);
|
||||
|
||||
bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node,
|
||||
const TargetLowering &TLI);
|
||||
SDValue &Chain, const TargetLowering &TLI);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
|
|
|
|||
|
|
@ -18,16 +18,12 @@
|
|||
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace llvm {
|
||||
class BlockAddress;
|
||||
class GCStrategy;
|
||||
class Constant;
|
||||
class ConstantArray;
|
||||
class ConstantFP;
|
||||
class ConstantInt;
|
||||
class ConstantStruct;
|
||||
class ConstantVector;
|
||||
class GCMetadataPrinter;
|
||||
class GlobalValue;
|
||||
class GlobalVariable;
|
||||
|
|
@ -37,14 +33,11 @@ namespace llvm {
|
|||
class MachineLocation;
|
||||
class MachineLoopInfo;
|
||||
class MachineLoop;
|
||||
class MachineConstantPool;
|
||||
class MachineConstantPoolEntry;
|
||||
class MachineConstantPoolValue;
|
||||
class MachineJumpTableInfo;
|
||||
class MachineModuleInfo;
|
||||
class MachineMove;
|
||||
class MCAsmInfo;
|
||||
class MCInst;
|
||||
class MCContext;
|
||||
class MCSection;
|
||||
class MCStreamer;
|
||||
|
|
@ -56,8 +49,6 @@ namespace llvm {
|
|||
class TargetLoweringObjectFile;
|
||||
class TargetData;
|
||||
class TargetMachine;
|
||||
class Twine;
|
||||
class Type;
|
||||
|
||||
/// AsmPrinter - This class is intended to be used as a driving class for all
|
||||
/// asm writers.
|
||||
|
|
@ -97,6 +88,11 @@ namespace llvm {
|
|||
///
|
||||
MCSymbol *CurrentFnSym;
|
||||
|
||||
/// The symbol used to represent the start of the current function for the
|
||||
/// purpose of calculating its size (e.g. using the .size directive). By
|
||||
/// default, this is equal to CurrentFnSym.
|
||||
MCSymbol *CurrentFnSymForSize;
|
||||
|
||||
private:
|
||||
// GCMetadataPrinters - The garbage collection metadata printer table.
|
||||
void *GCMetadataPrinters; // Really a DenseMap.
|
||||
|
|
@ -194,6 +190,11 @@ namespace llvm {
|
|||
|
||||
bool needsSEHMoves();
|
||||
|
||||
/// needsRelocationsForDwarfStringPool - Specifies whether the object format
|
||||
/// expects to use relocations to refer to debug entries. Alternatively we
|
||||
/// emit section offsets in bytes from the start of the string pool.
|
||||
bool needsRelocationsForDwarfStringPool() const;
|
||||
|
||||
/// EmitConstantPool - Print to the current output stream assembly
|
||||
/// representations of the constants in the constant pool MCP. This is
|
||||
/// used to print out constants which have been "spilled to memory" by
|
||||
|
|
@ -256,13 +257,20 @@ namespace llvm {
|
|||
|
||||
/// EmitInstruction - Targets should implement this to emit instructions.
|
||||
virtual void EmitInstruction(const MachineInstr *) {
|
||||
assert(0 && "EmitInstruction not implemented");
|
||||
llvm_unreachable("EmitInstruction not implemented");
|
||||
}
|
||||
|
||||
virtual void EmitFunctionEntryLabel();
|
||||
|
||||
virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
|
||||
|
||||
/// EmitXXStructor - Targets can override this to change how global
|
||||
/// constants that are part of a C++ static/global constructor list are
|
||||
/// emitted.
|
||||
virtual void EmitXXStructor(const Constant *CV) {
|
||||
EmitGlobalConstant(CV);
|
||||
}
|
||||
|
||||
/// isBlockOnlyReachableByFallthough - Return true if the basic block has
|
||||
/// exactly one predecessor and the control transfer mechanism between
|
||||
/// the predecessor and this block is a fall-through.
|
||||
|
|
@ -466,7 +474,7 @@ namespace llvm {
|
|||
const MachineBasicBlock *MBB,
|
||||
unsigned uid) const;
|
||||
void EmitLLVMUsedList(const Constant *List);
|
||||
void EmitXXStructorList(const Constant *List);
|
||||
void EmitXXStructorList(const Constant *List, bool isCtor);
|
||||
GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue