diff options
Diffstat (limited to 'include')
150 files changed, 2402 insertions, 1745 deletions
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index e85fb97505..63e816effc 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -18,13 +18,6 @@ #include "llvm/Support/DataTypes.h" #ifdef __cplusplus - -/* Need these includes to support the LLVM 'cast' template for the C++ 'wrap' - and 'unwrap' conversion functions. */ -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Module.h" -#include "llvm/PassRegistry.h" - extern "C" { #endif @@ -60,11 +53,6 @@ extern "C" { * with C++ due to name mangling. So in addition to C, this interface enables * tools written in such languages. * - * When included into a C++ source file, also declares 'wrap' and 'unwrap' - * helpers to perform opaque reference<-->pointer conversions. These helpers - * are shorter and more tightly typed than writing the casts by hand when - * authoring bindings. In assert builds, they will do runtime type checking. - * * @{ */ @@ -352,6 +340,63 @@ typedef enum { LLVMLandingPadFilter /**< A filter clause */ } LLVMLandingPadClauseTy; +typedef enum { + LLVMNotThreadLocal = 0, + LLVMGeneralDynamicTLSModel, + LLVMLocalDynamicTLSModel, + LLVMInitialExecTLSModel, + LLVMLocalExecTLSModel +} LLVMThreadLocalMode; + +typedef enum { + LLVMAtomicOrderingNotAtomic = 0, /**< A load or store which is not atomic */ + LLVMAtomicOrderingUnordered = 1, /**< Lowest level of atomicity, guarantees + somewhat sane results, lock free. */ + LLVMAtomicOrderingMonotonic = 2, /**< guarantees that if you take all the + operations affecting a specific address, + a consistent ordering exists */ + LLVMAtomicOrderingAcquire = 4, /**< Acquire provides a barrier of the sort + necessary to acquire a lock to access other + memory with normal loads and stores. */ + LLVMAtomicOrderingRelease = 5, /**< Release is similar to Acquire, but with + a barrier of the sort necessary to release + a lock. */ + LLVMAtomicOrderingAcquireRelease = 6, /**< provides both an Acquire and a + Release barrier (for fences and + operations which both read and write + memory). */ + LLVMAtomicOrderingSequentiallyConsistent = 7 /**< provides Acquire semantics + for loads and Release + semantics for stores. + Additionally, it guarantees + that a total ordering exists + between all + SequentiallyConsistent + operations. */ +} LLVMAtomicOrdering; + +typedef enum { + LLVMAtomicRMWBinOpXchg, /**< Set the new value and return the one old */ + LLVMAtomicRMWBinOpAdd, /**< Add a value and return the old one */ + LLVMAtomicRMWBinOpSub, /**< Subtract a value and return the old one */ + LLVMAtomicRMWBinOpAnd, /**< And a value and return the old one */ + LLVMAtomicRMWBinOpNand, /**< Not-And a value and return the old one */ + LLVMAtomicRMWBinOpOr, /**< OR a value and return the old one */ + LLVMAtomicRMWBinOpXor, /**< Xor a value and return the old one */ + LLVMAtomicRMWBinOpMax, /**< Sets the value if it's greater than the + original using a signed comparison and return + the old one */ + LLVMAtomicRMWBinOpMin, /**< Sets the value if it's Smaller than the + original using a signed comparison and return + the old one */ + LLVMAtomicRMWBinOpUMax, /**< Sets the value if it's greater than the + original using an unsigned comparison and return + the old one */ + LLVMAtomicRMWBinOpUMin /**< Sets the value if it's greater than the + original using an unsigned comparison and return + the old one */ +} LLVMAtomicRMWBinOp; + /** * @} */ @@ -1606,6 +1651,10 @@ LLVMBool LLVMIsThreadLocal(LLVMValueRef GlobalVar); void LLVMSetThreadLocal(LLVMValueRef GlobalVar, LLVMBool IsThreadLocal); LLVMBool LLVMIsGlobalConstant(LLVMValueRef GlobalVar); void LLVMSetGlobalConstant(LLVMValueRef GlobalVar, LLVMBool IsConstant); +LLVMThreadLocalMode LLVMGetThreadLocalMode(LLVMValueRef GlobalVar); +void LLVMSetThreadLocalMode(LLVMValueRef GlobalVar, LLVMThreadLocalMode Mode); +LLVMBool LLVMIsExternallyInitialized(LLVMValueRef GlobalVar); +void LLVMSetExternallyInitialized(LLVMValueRef GlobalVar, LLVMBool IsExtInit); /** * @} @@ -1694,6 +1743,13 @@ void LLVMSetGC(LLVMValueRef Fn, const char *Name); void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA); /** + * Add a target-dependent attribute to a fuction + * @see llvm::AttrBuilder::addAttribute() + */ +void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A, + const char *V); + +/** * Obtain an attribute from a function. * * @see llvm::Function::getAttributes() @@ -2515,6 +2571,10 @@ LLVMValueRef LLVMBuildIsNotNull(LLVMBuilderRef, LLVMValueRef Val, const char *Name); LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name); +LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op, + LLVMValueRef PTR, LLVMValueRef Val, + LLVMAtomicOrdering ordering, + LLVMBool singleThread); /** * @} @@ -2560,6 +2620,8 @@ LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRange(const char *InputData, LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRangeCopy(const char *InputData, size_t InputDataLength, const char *BufferName); +const char *LLVMGetBufferStart(LLVMMemoryBufferRef MemBuf); +size_t LLVMGetBufferSize(LLVMMemoryBufferRef MemBuf); void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf); /** @@ -2669,100 +2731,6 @@ LLVMBool LLVMIsMultithreaded(); #ifdef __cplusplus } - -namespace llvm { - class MemoryBuffer; - class PassManagerBase; - - #define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ - inline ty *unwrap(ref P) { \ - return reinterpret_cast<ty*>(P); \ - } \ - \ - inline ref wrap(const ty *P) { \ - return reinterpret_cast<ref>(const_cast<ty*>(P)); \ - } - - #define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref) \ - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ - \ - template<typename T> \ - inline T *unwrap(ref P) { \ - return cast<T>(unwrap(P)); \ - } - - #define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref) \ - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ - \ - template<typename T> \ - inline T *unwrap(ref P) { \ - T *Q = (T*)unwrap(P); \ - assert(Q && "Invalid cast!"); \ - return Q; \ - } - - DEFINE_ISA_CONVERSION_FUNCTIONS (Type, LLVMTypeRef ) - DEFINE_ISA_CONVERSION_FUNCTIONS (Value, LLVMValueRef ) - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module, LLVMModuleRef ) - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef ) - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRBuilder<>, LLVMBuilderRef ) - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef ) - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef ) - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef ) - DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBase, LLVMPassManagerRef ) - DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassRegistry, LLVMPassRegistryRef ) - /* LLVMModuleProviderRef exists for historical reasons, but now just holds a - * Module. - */ - inline Module *unwrap(LLVMModuleProviderRef MP) { - return reinterpret_cast<Module*>(MP); - } - - #undef DEFINE_STDCXX_CONVERSION_FUNCTIONS - #undef DEFINE_ISA_CONVERSION_FUNCTIONS - #undef DEFINE_SIMPLE_CONVERSION_FUNCTIONS - - /* Specialized opaque context conversions. - */ - inline LLVMContext **unwrap(LLVMContextRef* Tys) { - return reinterpret_cast<LLVMContext**>(Tys); - } - - inline LLVMContextRef *wrap(const LLVMContext **Tys) { - return reinterpret_cast<LLVMContextRef*>(const_cast<LLVMContext**>(Tys)); - } - - /* Specialized opaque type conversions. - */ - inline Type **unwrap(LLVMTypeRef* Tys) { - return reinterpret_cast<Type**>(Tys); - } - - inline LLVMTypeRef *wrap(Type **Tys) { - return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys)); - } - - /* Specialized opaque value conversions. - */ - inline Value **unwrap(LLVMValueRef *Vals) { - return reinterpret_cast<Value**>(Vals); - } - - template<typename T> - inline T **unwrap(LLVMValueRef *Vals, unsigned Length) { - #ifdef DEBUG - for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I) - cast<T>(*I); - #endif - (void)Length; - return reinterpret_cast<T**>(Vals); - } - - inline LLVMValueRef *wrap(const Value **Vals) { - return reinterpret_cast<LLVMValueRef*>(const_cast<Value**>(Vals)); - } -} - #endif /* !defined(__cplusplus) */ #endif /* !defined(LLVM_C_CORE_H) */ diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index cb77bb2e2e..8fae77def4 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -21,6 +21,7 @@ #include "llvm-c/Core.h" #include "llvm-c/Target.h" +#include "llvm-c/TargetMachine.h" #ifdef __cplusplus extern "C" { @@ -34,11 +35,19 @@ extern "C" { */ void LLVMLinkInJIT(void); +void LLVMLinkInMCJIT(void); void LLVMLinkInInterpreter(void); typedef struct LLVMOpaqueGenericValue *LLVMGenericValueRef; typedef struct LLVMOpaqueExecutionEngine *LLVMExecutionEngineRef; +struct LLVMMCJITCompilerOptions { + unsigned OptLevel; + LLVMCodeModel CodeModel; + LLVMBool NoFramePointerElim; + LLVMBool EnableFastISel; +}; + /*===-- Operations on generic values --------------------------------------===*/ LLVMGenericValueRef LLVMCreateGenericValueOfInt(LLVMTypeRef Ty, @@ -75,6 +84,31 @@ LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, unsigned OptLevel, char **OutError); +void LLVMInitializeMCJITCompilerOptions( + struct LLVMMCJITCompilerOptions *Options, size_t SizeOfOptions); + +/** + * Create an MCJIT execution engine for a module, with the given options. It is + * the responsibility of the caller to ensure that all fields in Options up to + * the given SizeOfOptions are initialized. It is correct to pass a smaller + * value of SizeOfOptions that omits some fields. The canonical way of using + * this is: + * + * LLVMMCJITCompilerOptions options; + * LLVMInitializeMCJITCompilerOptions(&options, sizeof(options)); + * ... fill in those options you care about + * LLVMCreateMCJITCompilerForModule(&jit, mod, &options, sizeof(options), + * &error); + * + * Note that this is also correct, though possibly suboptimal: + * + * LLVMCreateMCJITCompilerForModule(&jit, mod, 0, 0, &error); + */ +LLVMBool LLVMCreateMCJITCompilerForModule( + LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, + struct LLVMMCJITCompilerOptions *Options, size_t SizeOfOptions, + char **OutError); + /** Deprecated: Use LLVMCreateExecutionEngineForModule instead. */ LLVMBool LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, LLVMModuleProviderRef MP, @@ -123,7 +157,8 @@ LLVMBool LLVMRemoveModuleProvider(LLVMExecutionEngineRef EE, LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, LLVMValueRef *OutFn); -void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, LLVMValueRef Fn); +void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE, + LLVMValueRef Fn); LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE); @@ -137,27 +172,7 @@ void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); */ #ifdef __cplusplus -} - -namespace llvm { - struct GenericValue; - class ExecutionEngine; - - #define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ - inline ty *unwrap(ref P) { \ - return reinterpret_cast<ty*>(P); \ - } \ - \ - inline ref wrap(const ty *P) { \ - return reinterpret_cast<ref>(const_cast<ty*>(P)); \ - } - - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(GenericValue, LLVMGenericValueRef ) - DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionEngine, LLVMExecutionEngineRef) - - #undef DEFINE_SIMPLE_CONVERSION_FUNCTIONS -} - +} #endif /* defined(__cplusplus) */ #endif diff --git a/include/llvm-c/Object.h b/include/llvm-c/Object.h index e2dad62b4e..ecccfeed7f 100644 --- a/include/llvm-c/Object.h +++ b/include/llvm-c/Object.h @@ -23,8 +23,6 @@ #include "llvm/Config/llvm-config.h" #ifdef __cplusplus -#include "llvm/Object/ObjectFile.h" - extern "C" { #endif @@ -99,50 +97,6 @@ const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI); #ifdef __cplusplus } - -namespace llvm { - namespace object { - inline ObjectFile *unwrap(LLVMObjectFileRef OF) { - return reinterpret_cast<ObjectFile*>(OF); - } - - inline LLVMObjectFileRef wrap(const ObjectFile *OF) { - return reinterpret_cast<LLVMObjectFileRef>(const_cast<ObjectFile*>(OF)); - } - - inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { - return reinterpret_cast<section_iterator*>(SI); - } - - inline LLVMSectionIteratorRef - wrap(const section_iterator *SI) { - 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)); - } - - } -} - #endif /* defined(__cplusplus) */ #endif diff --git a/include/llvm-c/Target.h b/include/llvm-c/Target.h index 57abfa0207..80fc3e5ad7 100644 --- a/include/llvm-c/Target.h +++ b/include/llvm-c/Target.h @@ -235,29 +235,6 @@ void LLVMDisposeTargetData(LLVMTargetDataRef); #ifdef __cplusplus } - -namespace llvm { - class DataLayout; - class TargetLibraryInfo; - - inline DataLayout *unwrap(LLVMTargetDataRef P) { - return reinterpret_cast<DataLayout*>(P); - } - - inline LLVMTargetDataRef wrap(const DataLayout *P) { - return reinterpret_cast<LLVMTargetDataRef>(const_cast<DataLayout*>(P)); - } - - inline TargetLibraryInfo *unwrap(LLVMTargetLibraryInfoRef P) { - return reinterpret_cast<TargetLibraryInfo*>(P); - } - - inline LLVMTargetLibraryInfoRef wrap(const TargetLibraryInfo *P) { - TargetLibraryInfo *X = const_cast<TargetLibraryInfo*>(P); - return reinterpret_cast<LLVMTargetLibraryInfoRef>(X); - } -} - #endif /* defined(__cplusplus) */ #endif diff --git a/include/llvm-c/TargetMachine.h b/include/llvm-c/TargetMachine.h index 691abdfcb4..5e355959f6 100644 --- a/include/llvm-c/TargetMachine.h +++ b/include/llvm-c/TargetMachine.h @@ -25,7 +25,7 @@ #ifdef __cplusplus extern "C" { #endif -typedef struct LLVMTargetMachine *LLVMTargetMachineRef; +typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; typedef struct LLVMTarget *LLVMTargetRef; typedef enum { @@ -114,30 +114,11 @@ LLVMTargetDataRef LLVMGetTargetMachineData(LLVMTargetMachineRef T); LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M, char *Filename, LLVMCodeGenFileType codegen, char **ErrorMessage); - - - +/** Compile the LLVM IR stored in \p M and store the result in \p OutMemBuf. */ +LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M, + LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf); #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 diff --git a/include/llvm-c/Transforms/PassManagerBuilder.h b/include/llvm-c/Transforms/PassManagerBuilder.h index 82e513d490..545f8aae8c 100644 --- a/include/llvm-c/Transforms/PassManagerBuilder.h +++ b/include/llvm-c/Transforms/PassManagerBuilder.h @@ -86,16 +86,6 @@ void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB, #ifdef __cplusplus } - -namespace llvm { - inline PassManagerBuilder *unwrap(LLVMPassManagerBuilderRef P) { - return reinterpret_cast<PassManagerBuilder*>(P); - } - - inline LLVMPassManagerBuilderRef wrap(PassManagerBuilder *P) { - return reinterpret_cast<LLVMPassManagerBuilderRef>(P); - } -} #endif #endif diff --git a/include/llvm-c/Transforms/Vectorize.h b/include/llvm-c/Transforms/Vectorize.h index 68a9bdd388..c9102da602 100644 --- a/include/llvm-c/Transforms/Vectorize.h +++ b/include/llvm-c/Transforms/Vectorize.h @@ -39,6 +39,9 @@ void LLVMAddBBVectorizePass(LLVMPassManagerRef PM); /** See llvm::createLoopVectorizePass function. */ void LLVMAddLoopVectorizePass(LLVMPassManagerRef PM); +/** See llvm::createSLPVectorizerPass function. */ +void LLVMAddSLPVectorizePass(LLVMPassManagerRef PM); + /** * @} */ diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 42e123930d..11be4c513e 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -161,11 +161,11 @@ public: } APSInt& operator++() { - static_cast<APInt&>(*this)++; + ++(static_cast<APInt&>(*this)); return *this; } APSInt& operator--() { - static_cast<APInt&>(*this)--; + --(static_cast<APInt&>(*this)); return *this; } APSInt operator++(int) { diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index d410619964..31fd6d899d 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -618,7 +618,7 @@ public: unsigned OldNumBuckets = NumBuckets; BucketT *OldBuckets = Buckets; - allocateBuckets(std::max<unsigned>(64, NextPowerOf2(AtLeast-1))); + allocateBuckets(std::max<unsigned>(64, static_cast<unsigned>(NextPowerOf2(AtLeast-1)))); assert(Buckets); if (!OldBuckets) { this->BaseT::initEmpty(); diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index cda31a261d..e434417da7 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -151,7 +151,7 @@ namespace detail { inline uint64_t fetch64(const char *p) { uint64_t result; memcpy(&result, p, sizeof(result)); - if (sys::isBigEndianHost()) + if (sys::IsBigEndianHost) return sys::SwapByteOrder(result); return result; } @@ -159,7 +159,7 @@ inline uint64_t fetch64(const char *p) { inline uint32_t fetch32(const char *p) { uint32_t result; memcpy(&result, p, sizeof(result)); - if (sys::isBigEndianHost()) + if (sys::IsBigEndianHost) return sys::SwapByteOrder(result); return result; } diff --git a/include/llvm/ADT/InMemoryStruct.h b/include/llvm/ADT/InMemoryStruct.h deleted file mode 100644 index a56084501a..0000000000 --- a/include/llvm/ADT/InMemoryStruct.h +++ /dev/null @@ -1,77 +0,0 @@ -//===- InMemoryStruct.h - Indirect Struct Access Smart Pointer --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_INMEMORYSTRUCT_H -#define LLVM_ADT_INMEMORYSTRUCT_H - -#include <cassert> - -namespace llvm { - -/// \brief Helper object for abstracting access to an in-memory structure which -/// may require some kind of temporary storage. -/// -/// This class is designed to be used for accessing file data structures which -/// in the common case can be accessed from a direct pointer to a memory mapped -/// object, but which in some cases may require indirect access to a temporary -/// structure (which, for example, may have undergone endianness translation). -template<typename T> -class InMemoryStruct { - typedef T value_type; - typedef value_type &reference; - typedef value_type *pointer; - typedef const value_type &const_reference; - typedef const value_type *const_pointer; - - /// \brief The smart pointer target. - value_type *Target; - - /// \brief A temporary object which can be used as a target of the smart - /// pointer. - value_type Contents; - -private: - -public: - InMemoryStruct() : Target(0) {} - InMemoryStruct(reference Value) : Target(&Contents), Contents(Value) {} - InMemoryStruct(pointer Value) : Target(Value) {} - InMemoryStruct(const InMemoryStruct<T> &Value) { *this = Value; } - - void operator=(const InMemoryStruct<T> &Value) { - if (Value.Target != &Value.Contents) { - Target = Value.Target; - } else { - Target = &Contents; - Contents = Value.Contents; - } - } - - const_reference operator*() const { - assert(Target && "Cannot dereference null pointer"); - return *Target; - } - reference operator*() { - assert(Target && "Cannot dereference null pointer"); - return *Target; - } - - const_pointer operator->() const { - return Target; - } - pointer operator->() { - return Target; - } - - operator bool() const { return Target != 0; } -}; - -} - -#endif diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index 9e5ab021a5..b8b8861995 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -226,13 +226,13 @@ namespace llvm { template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > { typedef T* SimpleType; - static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { + static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) { return Val.getPtr(); } }; template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > { - typedef T* SimpleType; + typedef /*const*/ T* SimpleType; static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) { return Val.getPtr(); } diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index 81d73ed8b9..194e53fac2 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -128,20 +128,6 @@ public: #endif }; -template<typename T> struct simplify_type; - -template <typename T> -struct simplify_type<const Optional<T> > { - typedef const T* SimpleType; - static SimpleType getSimplifiedValue(const Optional<T> &Val) { - return Val.getPointer(); - } -}; - -template <typename T> -struct simplify_type<Optional<T> > - : public simplify_type<const Optional<T> > {}; - template <typename T> struct isPodLike; template <typename T> struct isPodLike<Optional<T> > { // An Optional<T> is pod-like if T is. diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index cce2efb6ac..0299a83c44 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -29,7 +29,7 @@ struct DenseMapInfo; /// on the number of bits available according to PointerLikeTypeTraits for the /// type. /// -/// Note that PointerIntPair always puts the Int part in the highest bits +/// Note that PointerIntPair always puts the IntVal part in the highest bits /// possible. For example, PointerIntPair<void*, 1, bool> will put the bit for /// the bool into bit #2, not bit #0, which allows the low two bits to be used /// for something else. For example, this allows: @@ -57,13 +57,13 @@ class PointerIntPair { }; public: PointerIntPair() : Value(0) {} - PointerIntPair(PointerTy Ptr, IntType Int) { + PointerIntPair(PointerTy PtrVal, IntType IntVal) { assert(IntBits <= PtrTraits::NumLowBitsAvailable && "PointerIntPair formed with integer size too large for pointer"); - setPointerAndInt(Ptr, Int); + setPointerAndInt(PtrVal, IntVal); } - explicit PointerIntPair(PointerTy Ptr) { - initWithPointer(Ptr); + explicit PointerIntPair(PointerTy PtrVal) { + initWithPointer(PtrVal); } PointerTy getPointer() const { @@ -75,41 +75,41 @@ public: return (IntType)((Value >> IntShift) & IntMask); } - void setPointer(PointerTy Ptr) { - intptr_t PtrVal - = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr)); - assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + void setPointer(PointerTy PtrVal) { + intptr_t PtrWord + = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal)); + assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && "Pointer is not sufficiently aligned"); // Preserve all low bits, just update the pointer. - Value = PtrVal | (Value & ~PointerBitMask); + Value = PtrWord | (Value & ~PointerBitMask); } - void setInt(IntType Int) { - intptr_t IntVal = Int; - assert(IntVal < (1 << IntBits) && "Integer too large for field"); + void setInt(IntType IntVal) { + intptr_t IntWord = static_cast<intptr_t>(IntVal); + assert(IntWord < (1 << IntBits) && "Integer too large for field"); // Preserve all bits other than the ones we are updating. Value &= ~ShiftedIntMask; // Remove integer field. - Value |= IntVal << IntShift; // Set new integer. + Value |= IntWord << IntShift; // Set new integer. } - void initWithPointer(PointerTy Ptr) { - intptr_t PtrVal - = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr)); - assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + void initWithPointer(PointerTy PtrVal) { + intptr_t PtrWord + = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal)); + assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && "Pointer is not sufficiently aligned"); - Value = PtrVal; + Value = PtrWord; } - void setPointerAndInt(PointerTy Ptr, IntType Int) { - intptr_t PtrVal - = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(Ptr)); - assert((PtrVal & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + void setPointerAndInt(PointerTy PtrVal, IntType IntVal) { + intptr_t PtrWord + = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal)); + assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && "Pointer is not sufficiently aligned"); - intptr_t IntVal = Int; - assert(IntVal < (1 << IntBits) && "Integer too large for field"); + intptr_t IntWord = static_cast<intptr_t>(IntVal); + assert(IntWord < (1 << IntBits) && "Integer too large for field"); - Value = PtrVal | (IntVal << IntShift); + Value = PtrWord | (IntWord << IntShift); } PointerTy const *getAddrOfPointer() const { diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index 7f6350e444..59fa3f39c9 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -260,7 +260,7 @@ class ReversePostOrderTraversal { typedef typename GT::NodeType NodeType; std::vector<NodeType*> Blocks; // Block list in normal PO order inline void Initialize(NodeType *BB) { - copy(po_begin(BB), po_end(BB), back_inserter(Blocks)); + std::copy(po_begin(BB), po_end(BB), std::back_inserter(Blocks)); } public: typedef typename std::vector<NodeType*>::reverse_iterator rpo_iterator; diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index 3bb883088c..8c7304197f 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -54,8 +54,6 @@ protected: /// then the set is in 'small mode'. const void **CurArray; /// CurArraySize - The allocated size of CurArray, always a power of two. - /// Note that CurArray points to an array that has CurArraySize+1 elements in - /// it, so that the end iterator actually points to valid memory. unsigned CurArraySize; // If small, this is # elts allocated consecutively @@ -68,9 +66,6 @@ protected: SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) { assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 && "Initial size must be a power of two!"); - // The end pointer, always valid, is set to a valid element to help the - // iterator. - CurArray[SmallSize] = 0; clear(); } ~SmallPtrSetImpl(); @@ -147,9 +142,11 @@ protected: class SmallPtrSetIteratorImpl { protected: const void *const *Bucket; + const void *const *End; public: - explicit SmallPtrSetIteratorImpl(const void *const *BP) : Bucket(BP) { - AdvanceIfNotValid(); + explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E) + : Bucket(BP), End(E) { + AdvanceIfNotValid(); } bool operator==(const SmallPtrSetIteratorImpl &RHS) const { @@ -164,8 +161,10 @@ protected: /// that is. This is guaranteed to stop because the end() bucket is marked /// valid. void AdvanceIfNotValid() { - while (*Bucket == SmallPtrSetImpl::getEmptyMarker() || - *Bucket == SmallPtrSetImpl::getTombstoneMarker()) + assert(Bucket <= End); + while (Bucket != End && + (*Bucket == SmallPtrSetImpl::getEmptyMarker() || + *Bucket == SmallPtrSetImpl::getTombstoneMarker())) ++Bucket; } }; @@ -182,12 +181,13 @@ public: typedef std::ptrdiff_t difference_type; typedef std::forward_iterator_tag iterator_category; - explicit SmallPtrSetIterator(const void *const *BP) - : SmallPtrSetIteratorImpl(BP) {} + explicit SmallPtrSetIterator(const void *const *BP, const void *const *E) + : SmallPtrSetIteratorImpl(BP, E) {} // Most methods provided by baseclass. const PtrTy operator*() const { + assert(Bucket < End); return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket)); } @@ -236,9 +236,8 @@ template<class PtrType, unsigned SmallSize> class SmallPtrSet : public SmallPtrSetImpl { // Make sure that SmallSize is a power of two, round up if not. enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val }; - /// SmallStorage - Fixed size storage used in 'small mode'. The extra element - /// ensures that the end iterator actually points to valid memory. - const void *SmallStorage[SmallSizePowTwo+1]; + /// SmallStorage - Fixed size storage used in 'small mode'. + const void *SmallStorage[SmallSizePowTwo]; typedef PointerLikeTypeTraits<PtrType> PtrTraits; public: SmallPtrSet() : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {} @@ -275,10 +274,10 @@ public: typedef SmallPtrSetIterator<PtrType> iterator; typedef SmallPtrSetIterator<PtrType> const_iterator; inline iterator begin() const { - return iterator(CurArray); + return iterator(CurArray, CurArray+CurArraySize); } inline iterator end() const { - return iterator(CurArray+CurArraySize); + return iterator(CurArray+CurArraySize, CurArray+CurArraySize); } // Allow assignment from any smallptrset with the same element type even if it diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h index 4eb7de895a..5dfe924f6d 100644 --- a/include/llvm/ADT/SmallSet.h +++ b/include/llvm/ADT/SmallSet.h @@ -55,6 +55,7 @@ public: } /// insert - Insert an element into the set if it isn't already there. + /// Returns true if the element is inserted (it was not in the set before). bool insert(const T &V) { if (!isSmall()) return Set.insert(V).second; diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 9167f87218..7ba0a714bf 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -16,6 +16,7 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/type_traits.h" #include <algorithm> #include <cassert> @@ -267,7 +268,8 @@ template <typename T, bool isPodLike> void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) { size_t CurCapacity = this->capacity(); size_t CurSize = this->size(); - size_t NewCapacity = 2*CurCapacity + 1; // Always grow, even from zero. + // Always grow, even from zero. + size_t NewCapacity = size_t(NextPowerOf2(CurCapacity+2)); if (NewCapacity < MinSize) NewCapacity = MinSize; T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T))); diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 224855e3f8..d013d05623 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -260,7 +260,7 @@ namespace llvm { /// Find the first character in the string that is \p C, or npos if not /// found. Same as find. - size_type find_first_of(char C, size_t From = 0) const { + size_t find_first_of(char C, size_t From = 0) const { return find(C, From); } @@ -268,21 +268,21 @@ namespace llvm { /// not found. /// /// Complexity: O(size() + Chars.size()) - size_type find_first_of(StringRef Chars, size_t From = 0) const; + size_t find_first_of(StringRef Chars, size_t From = 0) const; /// Find the first character in the string that is not \p C or npos if not /// found. - size_type find_first_not_of(char C, size_t From = 0) const; + size_t find_first_not_of(char C, size_t From = 0) const; /// Find the first character in the string that is not in the string /// \p Chars, or npos if not found. /// /// Complexity: O(size() + Chars.size()) - size_type find_first_not_of(StringRef Chars, size_t From = 0) const; + size_t find_first_not_of(StringRef Chars, size_t From = 0) const; /// Find the last character in the string that is \p C, or npos if not /// found. - size_type find_last_of(char C, size_t From = npos) const { + size_t find_last_of(char C, size_t From = npos) const { return rfind(C, From); } @@ -290,17 +290,17 @@ namespace llvm { /// found. /// /// Complexity: O(size() + Chars.size()) - size_type find_last_of(StringRef Chars, size_t From = npos) const; + size_t find_last_of(StringRef Chars, size_t From = npos) const; /// Find the last character in the string that is not \p C, or npos if not /// found. - size_type find_last_not_of(char C, size_t From = npos) const; + size_t find_last_not_of(char C, size_t From = npos) const; /// Find the last character in the string that is not in \p Chars, or /// npos if not found. /// /// Complexity: O(size() + Chars.size()) - size_type find_last_not_of(StringRef Chars, size_t From = npos) const; + size_t find_last_not_of(StringRef Chars, size_t From = npos) const; /// @} /// @name Helpful Algorithms @@ -390,14 +390,14 @@ namespace llvm { /// Return a StringRef equal to 'this' but with the first \p N elements /// dropped. - StringRef drop_front(unsigned N = 1) const { + StringRef drop_front(size_t N = 1) const { assert(size() >= N && "Dropping more elements than exist"); return substr(N); } /// Return a StringRef equal to 'this' but with the last \p N elements /// dropped. - StringRef drop_back(unsigned N = 1) const { + StringRef drop_back(size_t N = 1) const { assert(size() >= N && "Dropping more elements than exist"); return substr(0, size()-N); } diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 8fac222c13..75b562afdf 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -43,7 +43,7 @@ public: enum ArchType { UnknownArch, - arm, // ARM; arm, armv.*, xscale + arm, // ARM: arm, armv.*, xscale aarch64, // AArch64: aarch64 hexagon, // Hexagon: hexagon mips, // MIPS: mips, mipsallegrex diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index cc290d51d2..e16c6b4913 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -236,7 +236,7 @@ namespace llvm { /// getLHSKind - Get the NodeKind of the left-hand side. NodeKind getLHSKind() const { return (NodeKind) LHSKind; } - /// getRHSKind - Get the NodeKind of the left-hand side. + /// getRHSKind - Get the NodeKind of the right-hand side. NodeKind getRHSKind() const { return (NodeKind) RHSKind; } /// printOneChild - Print one child from a twine. diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index aeb78484c6..71dab2ef55 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -274,12 +274,12 @@ template<typename From> struct simplify_type; template<typename NodeTy> struct simplify_type<ilist_iterator<NodeTy> > { typedef NodeTy* SimpleType; - static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) { + static SimpleType getSimplifiedValue(ilist_iterator<NodeTy> &Node) { return &*Node; } }; template<typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy> > { - typedef NodeTy* SimpleType; + typedef /*const*/ NodeTy* SimpleType; static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) { return &*Node; diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index 163331c262..da007072e5 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -20,7 +20,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/Support/CallSite.h" #include "llvm/Support/ValueHandle.h" #include <vector> diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h index f220c58244..b3e2d18eb2 100644 --- a/include/llvm/Analysis/BlockFrequencyImpl.h +++ b/include/llvm/Analysis/BlockFrequencyImpl.h @@ -271,7 +271,7 @@ class BlockFrequencyImpl { BlockT *EntryBlock = fn->begin(); - copy(po_begin(EntryBlock), po_end(EntryBlock), back_inserter(POT)); + std::copy(po_begin(EntryBlock), po_end(EntryBlock), std::back_inserter(POT)); unsigned RPOidx = 0; for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) { diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index 63262eb9a3..488338302a 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -146,14 +146,6 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *TD, const TargetLibraryInfo *TLI, bool RoundToAlign = false); -/// \brief Compute the size of the underlying object pointed by Ptr. Returns -/// true and the object size in Size if successful, and false otherwise. -/// If RoundToAlign is true, then Size is rounded up to the aligment of allocas, -/// byval arguments, and global variables. -bool getUnderlyingObjectSize(const Value *Ptr, uint64_t &Size, - const DataLayout *TD, const TargetLibraryInfo *TLI, - bool RoundToAlign = false); - typedef std::pair<APInt, APInt> SizeOffsetType; @@ -163,14 +155,12 @@ typedef std::pair<APInt, APInt> SizeOffsetType; class ObjectSizeOffsetVisitor : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> { - typedef DenseMap<const Value*, SizeOffsetType> CacheMapTy; - const DataLayout *TD; const TargetLibraryInfo *TLI; bool RoundToAlign; unsigned IntTyBits; APInt Zero; - CacheMapTy CacheMap; + SmallPtrSet<Instruction *, 8> SeenInsts; APInt align(APInt Size, uint64_t Align); diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 69cc293811..e87319516c 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -266,6 +266,24 @@ public: /// @param BB The new exit basic block of the region. void replaceExit(BasicBlock *BB); + /// @brief Recursively replace the entry basic block of the region. + /// + /// This function replaces the entry basic block with a new basic block. It + /// also updates all child regions that have the same entry basic block as + /// this region. + /// + /// @param NewEntry The new entry basic block. + void replaceEntryRecursive(BasicBlock *NewEntry); + + /// @brief Recursively replace the exit basic block of the region. + /// + /// This function replaces the exit basic block with a new basic block. It + /// also updates all child regions that have the same exit basic block as + /// this region. + /// + /// @param NewExit The new exit basic block. + void replaceExitRecursive(BasicBlock *NewExit); + /// @brief Get the exit BasicBlock of the Region. /// @return The exit BasicBlock of the Region, NULL if this is the TopLevel /// Region. diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 42fd3927c8..306549fba4 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -338,6 +338,10 @@ namespace llvm { /// getMax - Get the max backedge taken count for the loop. const SCEV *getMax(ScalarEvolution *SE) const; + /// Return true if any backedge taken count expressions refer to the given + /// subexpression. + bool hasOperand(const SCEV *S, ScalarEvolution *SE) const; + /// clear - Invalidate this result and free associated memory. void clear(); }; diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index ccab19495f..a9d6725d86 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -263,6 +263,13 @@ public: SK_ExtractSubvector ///< ExtractSubvector Index indicates start offset. }; + /// \brief Additonal information about an operand's possible values. + enum OperandValueKind { + OK_AnyValue, // Operand can have any value. + OK_UniformValue, // Operand is uniform (splat of a value). + OK_UniformConstantValue // Operand is uniform constant. + }; + /// \return The number of scalar or vector registers that the target has. /// If 'Vectors' is true, it returns the number of vector registers. If it is /// set to false, it returns the number of scalar registers. @@ -277,7 +284,9 @@ public: virtual unsigned getMaximumUnrollFactor() const; /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. - virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty) const; + virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, + OperandValueKind Opd1Info = OK_AnyValue, + OperandValueKind Opd2Info = OK_AnyValue) const; /// \return The cost of a shuffle instruction of kind Kind and of type Tp. /// The index and subtype parameters are used by the subvector insertion and diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 2d2976cde1..f3139739cd 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -126,7 +126,7 @@ public: } }; - + /// BitstreamEntry - When advancing through a bitstream cursor, each advance can /// discover a few different kinds of entries: /// Error - Malformed bitcode was found. @@ -142,7 +142,7 @@ struct BitstreamEntry { SubBlock, Record } Kind; - + unsigned ID; static BitstreamEntry getError() { @@ -170,7 +170,7 @@ class BitstreamCursor { BitstreamReader *BitStream; size_t NextChar; - + /// CurWord/word_t - This is the current data we have pulled from the stream /// but have not returned to the client. This is specifically and /// intentionally defined to follow the word size of the host machine for @@ -199,7 +199,7 @@ class BitstreamCursor { /// BlockScope - This tracks the codesize of parent blocks. SmallVector<Block, 8> BlockScope; - + public: BitstreamCursor() : BitStream(0), NextChar(0) { } @@ -231,7 +231,7 @@ public: void operator=(const BitstreamCursor &RHS); void freeState(); - + bool isEndPos(size_t pos) { return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos)); } @@ -278,7 +278,7 @@ public: /// returned just like normal records. AF_DontAutoprocessAbbrevs = 2 }; - + /// advance - Advance the current bitstream, returning the next entry in the /// stream. BitstreamEntry advance(unsigned Flags = 0) { @@ -290,10 +290,10 @@ public: return BitstreamEntry::getError(); return BitstreamEntry::getEndBlock(); } - + if (Code == bitc::ENTER_SUBBLOCK) return BitstreamEntry::getSubBlock(ReadSubBlockID()); - + if (Code == bitc::DEFINE_ABBREV && !(Flags & AF_DontAutoprocessAbbrevs)) { // We read and accumulate abbrev's, the client can't do anything with @@ -314,7 +314,7 @@ public: BitstreamEntry Entry = advance(Flags); if (Entry.Kind != BitstreamEntry::SubBlock) return Entry; - + // If we found a sub-block, just skip over it and check the next entry. if (SkipBlock()) return BitstreamEntry::getError(); @@ -345,7 +345,7 @@ public: uint32_t Read(unsigned NumBits) { assert(NumBits && NumBits <= 32 && "Cannot return zero or more than 32 bits!"); - + // If the field is fully contained by CurWord, return it quickly. if (BitsInCurWord >= NumBits) { uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits)); @@ -365,15 +365,15 @@ public: // Read the next word from the stream. uint8_t Array[sizeof(word_t)] = {0}; - + BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), Array, NULL); - + // Handle big-endian byte-swapping if necessary. support::detail::packed_endian_specific_integral <word_t, support::little, support::unaligned> EndianValue; memcpy(&EndianValue, Array, sizeof(Array)); - + CurWord = EndianValue; NextChar += sizeof(word_t); @@ -450,7 +450,7 @@ private: BitsInCurWord = 32; return; } - + BitsInCurWord = 0; CurWord = 0; } @@ -493,7 +493,7 @@ public: /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter /// the block, and return true if the block has an error. bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0); - + bool ReadBlockEnd() { if (BlockScope.empty()) return true; @@ -529,7 +529,7 @@ private: void readAbbreviatedField(const BitCodeAbbrevOp &Op, SmallVectorImpl<uint64_t> &Vals); void skipAbbreviatedField(const BitCodeAbbrevOp &Op); - + public: /// getAbbrev - Return the abbreviation for the specified AbbrevId. @@ -541,7 +541,7 @@ public: /// skipRecord - Read the current record and discard it. void skipRecord(unsigned AbbrevID); - + unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, StringRef *Blob = 0); @@ -549,7 +549,7 @@ public: // Abbrev Processing //===--------------------------------------------------------------------===// void ReadAbbrevRecord(); - + bool ReadBlockInfoBlock(); }; diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index 7b68f8761a..a837211875 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -458,7 +458,7 @@ public: template<typename uintty> void EmitRecordWithArray(unsigned Abbrev, SmallVectorImpl<uintty> &Vals, const char *ArrayData, unsigned ArrayLen) { - return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(ArrayData, + return EmitRecordWithAbbrevImpl(Abbrev, Vals, StringRef(ArrayData, ArrayLen)); } diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index e0a6e3f402..c2fd6ce367 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -25,6 +25,7 @@ namespace llvm { class BlockAddress; class GCStrategy; class Constant; + class ConstantArray; class GCMetadataPrinter; class GlobalValue; class GlobalVariable; @@ -134,6 +135,9 @@ namespace llvm { /// getDataLayout - Return information about data layout. const DataLayout &getDataLayout() const; + /// getTargetTriple - Return the target triple string. + StringRef getTargetTriple() const; + /// getCurrentSection() - Return the current section we are emitting to. const MCSection *getCurrentSection() const; @@ -480,7 +484,7 @@ namespace llvm { void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid) const; - void EmitLLVMUsedList(const Constant *List); + void EmitLLVMUsedList(const ConstantArray *InitList); void EmitXXStructorList(const Constant *List, bool isCtor); GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C); }; diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 705db7e643..471e9bfc40 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -123,12 +123,28 @@ public: /// index value. std::pair<unsigned, bool> getRegForGEPIndex(const Value *V); - /// TryToFoldLoad - The specified machine instr operand is a vreg, and that + /// \brief We're checking to see if we can fold \p LI into \p FoldInst. + /// Note that we could have a sequence where multiple LLVM IR instructions + /// are folded into the same machineinstr. For example we could have: + /// A: x = load i32 *P + /// B: y = icmp A, 42 + /// C: br y, ... + /// + /// In this scenario, \p LI is "A", and \p FoldInst is "C". We know + /// about "B" (and any other folded instructions) because it is between + /// A and C. + /// + /// If we succeed folding, return true. + /// + bool tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst); + + /// \brief The specified machine instr operand is a vreg, and that /// vreg is being provided by the specified load instruction. If possible, /// try to fold the load as an operand to the instruction, returning true if /// possible. - virtual bool TryToFoldLoad(MachineInstr * /*MI*/, unsigned /*OpNo*/, - const LoadInst * /*LI*/) { + /// This method should be implemented by targets. + virtual bool tryToFoldLoadIntoMI(MachineInstr * /*MI*/, unsigned /*OpNo*/, + const LoadInst * /*LI*/) { return false; } diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index c407b61674..456d2dcb51 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -26,6 +26,12 @@ namespace llvm { /// Creates an ocaml-compatible metadata printer. void linkOcamlGCPrinter(); + + /// Creates an erlang-compatible garbage collector. + void linkErlangGC(); + + /// Creates an erlang-compatible metadata printer. + void linkErlangGCPrinter(); /// Creates a shadow stack garbage collector. This collector requires no code /// generator support. diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 442729b5d7..0fd211b4a8 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -602,14 +602,6 @@ namespace ISD { /// specifier. PREFETCH, - /// OUTCHAIN = MEMBARRIER(INCHAIN, load-load, load-store, store-load, - /// store-store, device) - /// This corresponds to the memory.barrier intrinsic. - /// it takes an input chain, 4 operands to specify the type of barrier, an - /// operand specifying if the barrier applies to device and uncached memory - /// and produces an output chain. - MEMBARRIER, - /// OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) /// This corresponds to the fence instruction. It takes an input chain, and /// two integer constants: an AtomicOrdering and a SynchronizationScope. diff --git a/include/llvm/CodeGen/LinkAllAsmWriterComponents.h b/include/llvm/CodeGen/LinkAllAsmWriterComponents.h index 4b941730a2..722b0de6f7 100644 --- a/include/llvm/CodeGen/LinkAllAsmWriterComponents.h +++ b/include/llvm/CodeGen/LinkAllAsmWriterComponents.h @@ -30,6 +30,7 @@ namespace { return; llvm::linkOcamlGCPrinter(); + llvm::linkErlangGCPrinter(); } } ForceAsmWriterLinking; // Force link by creating a global definition. diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 2145eb80bd..916c0f233e 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -37,6 +37,7 @@ namespace { (void) llvm::createDefaultPBQPRegisterAllocator(); llvm::linkOcamlGC(); + llvm::linkErlangGC(); llvm::linkShadowStackGC(); (void) llvm::createBURRListDAGScheduler(NULL, llvm::CodeGenOpt::Default); diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 244be9c501..cb09a49666 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -399,6 +399,15 @@ namespace llvm { return r != end() && r->containsRange(Start, End); } + /// True iff this live range is a single segment that lies between the + /// specified boundaries, exclusively. Vregs live across a backedge are not + /// considered local. The boundaries are expected to lie within an extended + /// basic block, so vregs that are not live out should contain no holes. + bool isLocal(SlotIndex Start, SlotIndex End) const { + return beginIndex() > Start.getBaseIndex() && + endIndex() < End.getBoundaryIndex(); + } + /// removeRange - Remove the specified range from this interval. Note that /// the range must be a single LiveRange in its entirety. void removeRange(SlotIndex Start, SlotIndex End, diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 4632368157..7d72f37255 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -20,9 +20,7 @@ #ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H #define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H -#include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/LiveInterval.h" #include "llvm/CodeGen/MachineBasicBlock.h" @@ -36,6 +34,7 @@ namespace llvm { class AliasAnalysis; + class BitVector; class LiveRangeCalc; class LiveVariables; class MachineDominatorTree; diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index def7b00ce7..8a32a3c11a 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -83,7 +83,7 @@ private: /// allUsesAvailableAt - Return true if all registers used by OrigMI at /// OrigIdx are also available with the same value at UseIdx. bool allUsesAvailableAt(const MachineInstr *OrigMI, SlotIndex OrigIdx, - SlotIndex UseIdx); + SlotIndex UseIdx) const; /// foldAsLoad - If LI has a single use and a single def that can be folded as /// a load, eliminate the register by folding the def into the use. diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index 3c5ed9297e..6628fd278e 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -29,21 +29,19 @@ #ifndef LLVM_CODEGEN_LIVEVARIABLES_H #define LLVM_CODEGEN_LIVEVARIABLES_H -#include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SparseBitVector.h" -#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Target/TargetRegisterInfo.h" namespace llvm { +class MachineBasicBlock; class MachineRegisterInfo; -class TargetRegisterInfo; class LiveVariables : public MachineFunctionPass { public: diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 492a3ff49f..0f2f8746b3 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -71,7 +71,6 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> { std::vector<MachineBasicBlock *> Predecessors; std::vector<MachineBasicBlock *> Successors; - /// Weights - Keep track of the weights to the successors. This vector /// has the same order as Successors, or it is empty if we don't use it /// (disable optimization). @@ -96,6 +95,10 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> { /// target of an indirect branch. bool AddressTaken; + /// \brief since getSymbol is a relatively heavy-weight operation, the symbol + /// is only computed once and is cached. + mutable MCSymbol *CachedMCSymbol; + // Intrusive list support MachineBasicBlock() {} diff --git a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h index 1c9bdd954c..98dd03b45c 100644 --- a/include/llvm/CodeGen/MachineBranchProbabilityInfo.h +++ b/include/llvm/CodeGen/MachineBranchProbabilityInfo.h @@ -1,4 +1,3 @@ - //==- MachineBranchProbabilityInfo.h - Machine Branch Probability Analysis -==// // // The LLVM Compiler Infrastructure diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 82c4cd6598..c886e256e0 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -352,8 +352,8 @@ public: // Internal functions used to automatically number MachineBasicBlocks // - /// getNextMBBNumber - Returns the next unique number to be assigned - /// to a MachineBasicBlock in this MachineFunction. + /// \brief Adds the MBB to the internal numbering. Returns the unique number + /// assigned to the MBB. /// unsigned addToMBBNumbering(MachineBasicBlock *MBB) { MBBNumbering.push_back(MBB); diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index ddb127120f..00a55b57f3 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -34,22 +34,22 @@ struct MachinePointerInfo { /// If this is null, then the access is to a pointer in the default address /// space. const Value *V; - + /// Offset - This is an offset from the base Value*. int64_t Offset; - + explicit MachinePointerInfo(const Value *v = 0, int64_t offset = 0) : V(v), Offset(offset) {} - + MachinePointerInfo getWithOffset(int64_t O) const { if (V == 0) return MachinePointerInfo(0, 0); return MachinePointerInfo(V, Offset+O); } - + /// getAddrSpace - Return the LLVM IR address space number that this pointer /// points into. unsigned getAddrSpace() const; - + /// getConstantPool - Return a MachinePointerInfo record that refers to the /// constant pool. static MachinePointerInfo getConstantPool(); @@ -57,20 +57,20 @@ struct MachinePointerInfo { /// getFixedStack - Return a MachinePointerInfo record that refers to the /// the specified FrameIndex. static MachinePointerInfo getFixedStack(int FI, int64_t offset = 0); - + /// getJumpTable - Return a MachinePointerInfo record that refers to a /// jump table entry. static MachinePointerInfo getJumpTable(); - + /// getGOT - Return a MachinePointerInfo record that refers to a /// GOT entry. static MachinePointerInfo getGOT(); - + /// getStack - stack pointer relative access. static MachinePointerInfo getStack(int64_t Offset); }; - - + + //===----------------------------------------------------------------------===// /// MachineMemOperand - A description of a memory reference used in the backend. /// Instead of holding a StoreInst or LoadInst, this class holds the address @@ -99,8 +99,11 @@ public: MONonTemporal = 8, /// The memory access is invariant. MOInvariant = 16, + // Target hints allow target passes to annotate memory operations. + MOTargetStartBit = 5, + MOTargetNumBits = 3, // This is the number of bits we need to represent flags. - MOMaxBits = 5 + MOMaxBits = 8 }; /// MachineMemOperand - Construct an MachineMemOperand object with the @@ -110,7 +113,7 @@ public: const MDNode *Ranges = 0); const MachinePointerInfo &getPointerInfo() const { return PtrInfo; } - + /// getValue - Return the base address of the memory access. This may either /// be a normal LLVM IR Value, or one of the special values used in CodeGen. /// Special values are those obtained via @@ -123,6 +126,9 @@ public: /// getFlags - Return the raw flags of the source value, \see MemOperandFlags. unsigned int getFlags() const { return Flags & ((1 << MOMaxBits) - 1); } + /// Bitwise OR the current flags with the given flags. + void setFlags(unsigned f) { Flags |= (f & ((1 << MOMaxBits) - 1)); } + /// getOffset - For normal values, this is a byte offset added to the base /// address. For PseudoSourceValue::FPRel values, this is the FrameIndex /// number. diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 1db6252ef4..a3acec8095 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -295,7 +295,7 @@ public: /// isUsedFunction - Return true if the functions in the llvm.used list. This /// does not return true for things in llvm.compiler.used unless they are also /// in llvm.used. - bool isUsedFunction(const Function *F) { + bool isUsedFunction(const Function *F) const { return UsedFunctions.count(F); } diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 4b43cc1095..24ba7bb1ac 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -157,6 +157,12 @@ public: // Strictly for use by MachineInstr.cpp. void moveOperands(MachineOperand *Dst, MachineOperand *Src, unsigned NumOps); + /// Verify the sanity of the use list for Reg. + void verifyUseList(unsigned Reg) const; + + /// Verify the use list of all registers. + void verifyUseLists() const; + /// reg_begin/reg_end - Provide iteration support to walk over all definitions /// and uses of a register within the MachineFunction that corresponds to this /// MachineRegisterInfo object. diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 57febe7746..769e4b42a5 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -274,6 +274,10 @@ public: Mutations.push_back(Mutation); } + /// \brief True if an edge can be added from PredSU to SuccSU without creating + /// a cycle. + bool canAddEdge(SUnit *SuccSU, SUnit *PredSU); + /// \brief Add a DAG edge to the given SU with the given predecessor /// dependence data. /// @@ -297,6 +301,10 @@ public: /// reorderable instructions. virtual void schedule(); + /// Change the position of an instruction within the basic block and update + /// live ranges and region boundary iterators. + void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); + /// Get current register pressure for the top scheduled instructions. const IntervalPressure &getTopPressure() const { return TopPressure; } const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; } @@ -362,7 +370,6 @@ protected: void updateScheduledPressure(const std::vector<unsigned> &NewMaxPressure); - void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); bool checkSchedLimit(); void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots, diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h index eaaa70a67d..4e087fc62d 100644 --- a/include/llvm/CodeGen/MachineTraceMetrics.h +++ b/include/llvm/CodeGen/MachineTraceMetrics.h @@ -107,6 +107,13 @@ public: /// Get the fixed resource information about MBB. Compute it on demand. const FixedBlockInfo *getResources(const MachineBasicBlock*); + /// Get the scaled number of cycles used per processor resource in MBB. + /// This is an array with SchedModel.getNumProcResourceKinds() entries. + /// The getResources() function above must have been called first. + /// + /// These numbers have already been scaled by SchedModel.getResourceFactor(). + ArrayRef<unsigned> getProcResourceCycles(unsigned MBBNum) const; + /// A virtual register or regunit required by a basic block or its trace /// successors. struct LiveInReg { @@ -253,9 +260,13 @@ public: /// independent, exposing the maximum instruction-level parallelism. /// /// Any blocks in Extrablocks are included as if they were part of the - /// trace. + /// trace. Likewise, extra resources required by the specified scheduling + /// classes are included. For the caller to account for extra machine + /// instructions, it must first resolve each instruction's scheduling class. unsigned getResourceLength(ArrayRef<const MachineBasicBlock*> Extrablocks = - ArrayRef<const MachineBasicBlock*>()) const; + ArrayRef<const MachineBasicBlock*>(), + ArrayRef<const MCSchedClassDesc*> ExtraInstrs = + ArrayRef<const MCSchedClassDesc*>()) const; /// Return the length of the (data dependency) critical path through the /// trace. @@ -284,6 +295,8 @@ public: class Ensemble { SmallVector<TraceBlockInfo, 4> BlockInfo; DenseMap<const MachineInstr*, InstrCycles> Cycles; + SmallVector<unsigned, 0> ProcResourceDepths; + SmallVector<unsigned, 0> ProcResourceHeights; friend class Trace; void computeTrace(const MachineBasicBlock*); @@ -303,6 +316,8 @@ public: const MachineLoop *getLoopFor(const MachineBasicBlock*) const; const TraceBlockInfo *getDepthResources(const MachineBasicBlock*) const; const TraceBlockInfo *getHeightResources(const MachineBasicBlock*) const; + ArrayRef<unsigned> getProcResourceDepths(unsigned MBBNum) const; + ArrayRef<unsigned> getProcResourceHeights(unsigned MBBNum) const; public: virtual ~Ensemble(); @@ -343,8 +358,22 @@ private: // One entry per basic block, indexed by block number. SmallVector<FixedBlockInfo, 4> BlockInfo; + // Cycles consumed on each processor resource per block. + // The number of processor resource kinds is constant for a given subtarget, + // but it is not known at compile time. The number of cycles consumed by + // block B on processor resource R is at ProcResourceCycles[B*Kinds + R] + // where Kinds = SchedModel.getNumProcResourceKinds(). + SmallVector<unsigned, 0> ProcResourceCycles; + // One ensemble per strategy. Ensemble* Ensembles[TS_NumStrategies]; + + // Convert scaled resource usage to a cycle count that can be compared with + // latencies. + unsigned getCycles(unsigned Scaled) { + unsigned Factor = SchedModel.getLatencyFactor(); + return (Scaled + Factor - 1) / Factor; + } }; inline raw_ostream &operator<<(raw_ostream &OS, diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 4d559b5799..b02f63e70b 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -35,6 +35,48 @@ namespace llvm { class PassConfigImpl; +/// Discriminated union of Pass ID types. +/// +/// The PassConfig API prefers dealing with IDs because they are safer and more +/// efficient. IDs decouple configuration from instantiation. This way, when a +/// pass is overriden, it isn't unnecessarily instantiated. It is also unsafe to +/// refer to a Pass pointer after adding it to a pass manager, which deletes +/// redundant pass instances. +/// +/// However, it is convient to directly instantiate target passes with +/// non-default ctors. These often don't have a registered PassInfo. Rather than +/// force all target passes to implement the pass registry boilerplate, allow +/// the PassConfig API to handle either type. +/// +/// AnalysisID is sadly char*, so PointerIntPair won't work. +class IdentifyingPassPtr { + union { + AnalysisID ID; + Pass *P; + }; + bool IsInstance; +public: + IdentifyingPassPtr() : P(0), IsInstance(false) {} + IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr), IsInstance(false) {} + IdentifyingPassPtr(Pass *InstancePtr) : P(InstancePtr), IsInstance(true) {} + + bool isValid() const { return P; } + bool isInstance() const { return IsInstance; } + + AnalysisID getID() const { + assert(!IsInstance && "Not a Pass ID"); + return ID; + } + Pass *getInstance() const { + assert(IsInstance && "Not a Pass Instance"); + return P; + } +}; + +template <> struct isPodLike<IdentifyingPassPtr> { + static const bool value = true; +}; + /// Target-Independent Code Generator Pass Configuration Options. /// /// This is an ImmutablePass solely for the purpose of exposing CodeGen options @@ -117,20 +159,22 @@ public: /// Allow the target to override a specific pass without overriding the pass /// pipeline. When passes are added to the standard pipeline at the /// point where StandardID is expected, add TargetID in its place. - void substitutePass(AnalysisID StandardID, AnalysisID TargetID); + void substitutePass(AnalysisID StandardID, IdentifyingPassPtr TargetID); /// Insert InsertedPassID pass after TargetPassID pass. - void insertPass(AnalysisID TargetPassID, AnalysisID InsertedPassID); + void insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID); /// Allow the target to enable a specific standard pass by default. void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); } /// Allow the target to disable a specific standard pass by default. - void disablePass(AnalysisID PassID) { substitutePass(PassID, 0); } + void disablePass(AnalysisID PassID) { + substitutePass(PassID, IdentifyingPassPtr()); + } /// Return the pass substituted for StandardID by the target. /// If no substitution exists, return StandardID. - AnalysisID getPassSubstitution(AnalysisID StandardID) const; + IdentifyingPassPtr getPassSubstitution(AnalysisID StandardID) const; /// Return true if the optimized regalloc pipeline is enabled. bool getOptimizeRegAlloc() const; @@ -222,17 +266,6 @@ protected: return false; } - /// addFinalizeRegAlloc - This method may be implemented by targets that want - /// to run passes within the regalloc pipeline, immediately after the register - /// allocation pass itself. These passes run as soon as virtual regisiters - /// have been rewritten to physical registers but before and other postRA - /// optimization happens. Targets that have marked instructions for bundling - /// must have finalized those bundles by the time these passes have run, - /// because subsequent passes are not guaranteed to be bundle-aware. - virtual bool addFinalizeRegAlloc() { - return false; - } - /// addPostRegAlloc - This method may be implemented by targets that want to /// run passes after register allocation pass pipeline but before /// prolog-epilog insertion. This should return true if -print-machineinstrs @@ -444,10 +477,6 @@ namespace llvm { /// information. extern char &MachineBlockPlacementStatsID; - /// Code Placement - This pass optimize code placement and aligns loop - /// headers to target specific alignment boundary. - extern char &CodePlacementOptID; - /// GCLowering Pass - Performs target-independent LLVM IR transformations for /// highly portable strategies. /// diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index b617c14558..8b8e3d90f7 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -29,6 +29,7 @@ namespace llvm { class MachineFunction; class MachineLoopInfo; class TargetRegisterInfo; + template<class T> class OwningPtr; /// This class wraps up a PBQP instance representing a register allocation /// problem, plus the structures necessary to map back from the PBQP solution @@ -123,11 +124,9 @@ namespace llvm { /// Build a PBQP instance to represent the register allocation problem for /// the given MachineFunction. - virtual std::auto_ptr<PBQPRAProblem> build( - MachineFunction *mf, - const LiveIntervals *lis, - const MachineLoopInfo *loopInfo, - const RegSet &vregs); + virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, + const MachineLoopInfo *loopInfo, + const RegSet &vregs); private: void addSpillCosts(PBQP::Vector &costVec, PBQP::PBQPNum spillCost); @@ -144,11 +143,9 @@ namespace llvm { /// Build a PBQP instance to represent the register allocation problem for /// the given MachineFunction. - virtual std::auto_ptr<PBQPRAProblem> build( - MachineFunction *mf, - const LiveIntervals *lis, - const MachineLoopInfo *loopInfo, - const RegSet &vregs); + virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, + const MachineLoopInfo *loopInfo, + const RegSet &vregs); private: @@ -161,7 +158,7 @@ namespace llvm { PBQP::PBQPNum benefit); }; - FunctionPass* createPBQPRegisterAllocator(std::auto_ptr<PBQPBuilder> builder, + FunctionPass* createPBQPRegisterAllocator(OwningPtr<PBQPBuilder> &builder, char *customPassID=0); } diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 01199205b5..95bf29167c 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -40,21 +40,23 @@ class RegScavenger { /// registers. bool Tracking; - /// ScavengingFrameIndex - Special spill slot used for scavenging a register - /// post register allocation. - int ScavengingFrameIndex; + /// Information on scavenged registers (held in a spill slot). + struct ScavengedInfo { + ScavengedInfo(int FI = -1) : FrameIndex(FI), Reg(0), Restore(NULL) {} - /// ScavengedReg - If none zero, the specific register is currently being - /// scavenged. That is, it is spilled to the special scavenging stack slot. - unsigned ScavengedReg; + /// A spill slot used for scavenging a register post register allocation. + int FrameIndex; - /// ScavengedRC - Register class of the scavenged register. - /// - const TargetRegisterClass *ScavengedRC; + /// If non-zero, the specific register is currently being + /// scavenged. That is, it is spilled to this scavenging stack slot. + unsigned Reg; + + /// The instruction that restores the scavenged register from stack. + const MachineInstr *Restore; + }; - /// ScavengeRestore - Instruction that restores the scavenged register from - /// stack. - const MachineInstr *ScavengeRestore; + /// A vector of information on scavenged registers. + SmallVector<ScavengedInfo, 2> Scavenged; /// CalleeSavedrRegs - A bitvector of callee saved registers for the target. /// @@ -71,8 +73,7 @@ class RegScavenger { public: RegScavenger() - : MBB(NULL), NumPhysRegs(0), Tracking(false), - ScavengingFrameIndex(-1), ScavengedReg(0), ScavengedRC(NULL) {} + : MBB(NULL), NumPhysRegs(0), Tracking(false) {} /// enterBasicBlock - Start tracking liveness from the begin of the specific /// basic block. @@ -92,9 +93,25 @@ public: while (MBBI != I) forward(); } + /// Invert the behavior of forward() on the current instruction (undo the + /// changes to the available registers made by forward()). + void unprocess(); + + /// Unprocess instructions until you reach the provided iterator. + void unprocess(MachineBasicBlock::iterator I) { + while (MBBI != I) unprocess(); + } + /// skipTo - Move the internal MBB iterator but do not update register states. - /// - void skipTo(MachineBasicBlock::iterator I) { MBBI = I; } + void skipTo(MachineBasicBlock::iterator I) { + if (I == MachineBasicBlock::iterator(NULL)) + Tracking = false; + MBBI = I; + } + + MachineBasicBlock::iterator getCurrentPosition() const { + return MBBI; + } /// getRegsUsed - return all registers currently in use in used. void getRegsUsed(BitVector &used, bool includeReserved); @@ -107,10 +124,28 @@ public: /// Return 0 if none is found. unsigned FindUnusedReg(const TargetRegisterClass *RegClass) const; - /// setScavengingFrameIndex / getScavengingFrameIndex - accessor and setter of - /// ScavengingFrameIndex. - void setScavengingFrameIndex(int FI) { ScavengingFrameIndex = FI; } - int getScavengingFrameIndex() const { return ScavengingFrameIndex; } + /// Add a scavenging frame index. + void addScavengingFrameIndex(int FI) { + Scavenged.push_back(ScavengedInfo(FI)); + } + + /// Query whether a frame index is a scavenging frame index. + bool isScavengingFrameIndex(int FI) const { + for (SmallVector<ScavengedInfo, 2>::const_iterator I = Scavenged.begin(), + IE = Scavenged.end(); I != IE; ++I) + if (I->FrameIndex == FI) + return true; + + return false; + } + + /// Get an array of scavenging frame indices. + void getScavengingFrameIndices(SmallVectorImpl<int> &A) const { + for (SmallVector<ScavengedInfo, 2>::const_iterator I = Scavenged.begin(), + IE = Scavenged.end(); I != IE; ++I) + if (I->FrameIndex >= 0) + A.push_back(I->FrameIndex); + } /// scavengeRegister - Make a register of the specific register class /// available and do the appropriate bookkeeping. SPAdj is the stack @@ -149,6 +184,10 @@ private: RegsAvailable |= Regs; } + /// Processes the current instruction and fill the KillRegs and DefRegs bit + /// vectors. + void determineKillsAndDefs(); + /// Add Reg and all its sub-registers to BV. void addRegWithSubRegs(BitVector &BV, unsigned Reg); diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 8c959da696..7cff27e172 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -302,6 +302,7 @@ namespace llvm { bool isCallOp : 1; // Is a function call operand. bool isTwoAddress : 1; // Is a two-address instruction. bool isCommutable : 1; // Is a commutable instruction. + bool hasPhysRegUses : 1; // Has physreg uses. bool hasPhysRegDefs : 1; // Has physreg defs that are being used. bool hasPhysRegClobbers : 1; // Has any physreg defs, used or not. bool isPending : 1; // True once pending. @@ -331,10 +332,10 @@ namespace llvm { NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false), isCallOp(false), - isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), - hasPhysRegClobbers(false), isPending(false), isAvailable(false), - isScheduled(false), isScheduleHigh(false), isScheduleLow(false), - isCloned(false), SchedulingPref(Sched::None), + isTwoAddress(false), isCommutable(false), hasPhysRegUses(false), + hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), + isAvailable(false), isScheduled(false), isScheduleHigh(false), + isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -345,10 +346,10 @@ namespace llvm { NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false), isCallOp(false), - isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), - hasPhysRegClobbers(false), isPending(false), isAvailable(false), - isScheduled(false), isScheduleHigh(false), isScheduleLow(false), - isCloned(false), SchedulingPref(Sched::None), + isTwoAddress(false), isCommutable(false), hasPhysRegUses(false), + hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), + isAvailable(false), isScheduled(false), isScheduleHigh(false), + isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -358,10 +359,10 @@ namespace llvm { NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0), Latency(0), isVRegCycle(false), isCall(false), isCallOp(false), - isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), - hasPhysRegClobbers(false), isPending(false), isAvailable(false), - isScheduled(false), isScheduleHigh(false), isScheduleLow(false), - isCloned(false), SchedulingPref(Sched::None), + isTwoAddress(false), isCommutable(false), hasPhysRegUses(false), + hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), + isAvailable(false), isScheduled(false), isScheduleHigh(false), + isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -726,9 +727,8 @@ namespace llvm { /// IsReachable - Checks if SU is reachable from TargetSU. bool IsReachable(const SUnit *SU, const SUnit *TargetSU); - /// WillCreateCycle - Returns true if adding an edge from SU to TargetSU - /// will create a cycle. - bool WillCreateCycle(SUnit *SU, SUnit *TargetSU); + /// WillCreateCycle - Return true if addPred(TargetSU, SU) creates a cycle. + bool WillCreateCycle(SUnit *TargetSU, SUnit *SU); /// AddPred - Updates the topological ordering to accommodate an edge /// to be added from SUnit X to SUnit Y. diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 2219520ca1..990cac6348 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -105,6 +105,10 @@ namespace llvm { MachineBasicBlock::iterator RegionEnd; /// The index in BB of RegionEnd. + /// + /// This is the instruction number from the top of the current block, not + /// the SlotIndex. It is only used by the AntiDepBreaker and should be + /// removed once that client is obsolete. unsigned EndIndex; /// After calling BuildSchedGraph, each machine instruction in the current @@ -146,6 +150,9 @@ namespace llvm { virtual ~ScheduleDAGInstrs() {} + /// \brief Expose LiveIntervals for use in DAG mutators and such. + LiveIntervals *getLIS() const { return LIS; } + /// \brief Get the machine model for instruction scheduling. const TargetSchedModel *getSchedModel() const { return &SchedModel; } diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index e5adf67249..8c064bf2d4 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -810,31 +810,32 @@ public: MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, - SDValue Op1, SDValue Op2, SDValue Op3); + SDValue Op1, SDValue Op2, SDValue Op3); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT, - const SDValue *Ops, unsigned NumOps); + ArrayRef<SDValue> Ops); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, - SDValue Op1); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, - EVT VT2, SDValue Op1, SDValue Op2); - MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, - EVT VT2, SDValue Op1, SDValue Op2, SDValue Op3); + SDValue Op1); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + SDValue Op1, SDValue Op2); + MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, + SDValue Op1, SDValue Op2, SDValue Op3); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, - const SDValue *Ops, unsigned NumOps); + ArrayRef<SDValue> Ops); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, - EVT VT3, SDValue Op1, SDValue Op2); + EVT VT3, SDValue Op1, SDValue Op2); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, - EVT VT3, SDValue Op1, SDValue Op2, SDValue Op3); + EVT VT3, SDValue Op1, SDValue Op2, + SDValue Op3); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, - EVT VT3, const SDValue *Ops, unsigned NumOps); + EVT VT3, ArrayRef<SDValue> Ops); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, EVT VT1, EVT VT2, - EVT VT3, EVT VT4, const SDValue *Ops, unsigned NumOps); + EVT VT3, EVT VT4, ArrayRef<SDValue> Ops); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, - ArrayRef<EVT> ResultTys, const SDValue *Ops, - unsigned NumOps); + ArrayRef<EVT> ResultTys, + ArrayRef<SDValue> Ops); MachineSDNode *getMachineNode(unsigned Opcode, DebugLoc dl, SDVTList VTs, - const SDValue *Ops, unsigned NumOps); + ArrayRef<SDValue> Ops); /// getTargetExtractSubreg - A convenience function for creating /// TargetInstrInfo::EXTRACT_SUBREG nodes. diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 5f503deff1..a4721db685 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -259,9 +259,6 @@ private: void SelectBasicBlock(BasicBlock::const_iterator Begin, BasicBlock::const_iterator End, bool &HadTailCall); - - bool TryToFoldFastISelLoad(const LoadInst *LI, const Instruction *FoldInst, - FastISel *FastIS); void FinishBasicBlock(); void CodeGenAndEmitDAG(); diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 05f3b1494f..fef567f56b 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -196,14 +196,14 @@ template <> struct isPodLike<SDValue> { static const bool value = true; }; /// SDValues as if they were SDNode*'s. template<> struct simplify_type<SDValue> { typedef SDNode* SimpleType; - static SimpleType getSimplifiedValue(const SDValue &Val) { - return static_cast<SimpleType>(Val.getNode()); + static SimpleType getSimplifiedValue(SDValue &Val) { + return Val.getNode(); } }; template<> struct simplify_type<const SDValue> { - typedef SDNode* SimpleType; + typedef /*const*/ SDNode* SimpleType; static SimpleType getSimplifiedValue(const SDValue &Val) { - return static_cast<SimpleType>(Val.getNode()); + return Val.getNode(); } }; @@ -295,14 +295,8 @@ private: /// SDValues as if they were SDNode*'s. template<> struct simplify_type<SDUse> { typedef SDNode* SimpleType; - static SimpleType getSimplifiedValue(const SDUse &Val) { - return static_cast<SimpleType>(Val.getNode()); - } -}; -template<> struct simplify_type<const SDUse> { - typedef SDNode* SimpleType; - static SimpleType getSimplifiedValue(const SDUse &Val) { - return static_cast<SimpleType>(Val.getNode()); + static SimpleType getSimplifiedValue(SDUse &Val) { + return Val.getNode(); } }; diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index a277080466..26d0433f3e 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -53,6 +53,20 @@ namespace llvm { this->index = index; } +#ifdef EXPENSIVE_CHECKS + // When EXPENSIVE_CHECKS is defined, "erased" index list entries will + // actually be moved to a "graveyard" list, and have their pointers + // poisoned, so that dangling SlotIndex access can be reliably detected. + void setPoison() { + intptr_t tmp = reinterpret_cast<intptr_t>(mi); + assert(((tmp & 0x1) == 0x0) && "Pointer already poisoned?"); + tmp |= 0x1; + mi = reinterpret_cast<MachineInstr*>(tmp); + } + + bool isPoisoned() const { return (reinterpret_cast<intptr_t>(mi) & 0x1) == 0x1; } +#endif // EXPENSIVE_CHECKS + }; template <> @@ -109,6 +123,10 @@ namespace llvm { IndexListEntry* listEntry() const { assert(isValid() && "Attempt to compare reserved index."); +#ifdef EXPENSIVE_CHECKS + assert(!lie.getPointer()->isPoisoned() && + "Attempt to access deleted list-entry."); +#endif // EXPENSIVE_CHECKS return lie.getPointer(); } @@ -282,7 +300,6 @@ namespace llvm { template <> struct isPodLike<SlotIndex> { static const bool value = true; }; - inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) { li.print(os); return os; @@ -313,6 +330,10 @@ namespace llvm { typedef ilist<IndexListEntry> IndexList; IndexList indexList; +#ifdef EXPENSIVE_CHECKS + IndexList graveyardList; +#endif // EXPENSIVE_CHECKS + MachineFunction *mf; typedef DenseMap<const MachineInstr*, SlotIndex> Mi2IndexMap; @@ -643,6 +664,32 @@ namespace llvm { std::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare()); } + /// \brief Free the resources that were required to maintain a SlotIndex. + /// + /// Once an index is no longer needed (for instance because the instruction + /// at that index has been moved), the resources required to maintain the + /// index can be relinquished to reduce memory use and improve renumbering + /// performance. Any remaining SlotIndex objects that point to the same + /// index are left 'dangling' (much the same as a dangling pointer to a + /// freed object) and should not be accessed, except to destruct them. + /// + /// Like dangling pointers, access to dangling SlotIndexes can cause + /// painful-to-track-down bugs, especially if the memory for the index + /// previously pointed to has been re-used. To detect dangling SlotIndex + /// bugs, build with EXPENSIVE_CHECKS=1. This will cause "erased" indexes to + /// be retained in a graveyard instead of being freed. Operations on indexes + /// in the graveyard will trigger an assertion. + void eraseIndex(SlotIndex index) { + IndexListEntry *entry = index.listEntry(); +#ifdef EXPENSIVE_CHECKS + indexList.remove(entry); + graveyardList.push_back(entry); + entry->setPoison(); +#else + indexList.erase(entry); +#endif + } + }; diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index e7098e48bf..5b22c9c685 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -128,6 +128,12 @@ public: virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const; + + /// emitModuleFlags - Emit Obj-C garbage collection and linker options. Only + /// linker option emission is implemented for COFF. + virtual void emitModuleFlags(MCStreamer &Streamer, + ArrayRef<Module::ModuleFlagEntry> ModuleFlags, + Mangler *Mang, const TargetMachine &TM) const; }; } // end namespace llvm diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index 76df6ac8e6..da26985949 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -44,13 +44,13 @@ def v4i8 : ValueType<32 , 20>; // 4 x i8 vector value def v8i8 : ValueType<64 , 21>; // 8 x i8 vector value def v16i8 : ValueType<128, 22>; // 16 x i8 vector value def v32i8 : ValueType<256, 23>; // 32 x i8 vector value -def v64i8 : ValueType<256, 24>; // 64 x i8 vector value +def v64i8 : ValueType<512, 24>; // 64 x i8 vector value def v1i16 : ValueType<16 , 25>; // 1 x i16 vector value def v2i16 : ValueType<32 , 26>; // 2 x i16 vector value def v4i16 : ValueType<64 , 27>; // 4 x i16 vector value def v8i16 : ValueType<128, 28>; // 8 x i16 vector value def v16i16 : ValueType<256, 29>; // 16 x i16 vector value -def v32i16 : ValueType<256, 30>; // 32 x i16 vector value +def v32i16 : ValueType<512, 30>; // 32 x i16 vector value def v1i32 : ValueType<32 , 31>; // 1 x i32 vector value def v2i32 : ValueType<64 , 32>; // 2 x i32 vector value def v4i32 : ValueType<128, 33>; // 4 x i32 vector value diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 0a26857397..93c2582ae2 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -69,6 +69,9 @@ /* Define to 1 if you have the `closedir' function. */ #cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR} +/* Define to 1 if you have the <cxxabi.h> header file. */ +#cmakedefine HAVE_CXXABI_H ${HAVE_CXXABI_H} + /* Define to 1 if you have the <CrashReporterClient.h> header file. */ #undef HAVE_CRASHREPORTERCLIENT_H @@ -230,6 +233,9 @@ /* Define to 1 if you have the `udis86' library (-ludis86). */ #undef HAVE_LIBUDIS86 +/* Define to 1 if you have the 'z' library (-lz). */ +#cmakedefine HAVE_LIBZ ${HAVE_LIBZ} + /* Define to 1 if you have the <limits.h> header file. */ #cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H} @@ -498,6 +504,9 @@ /* Define if the xdot.py program is available */ #cmakedefine HAVE_XDOT_PY ${HAVE_XDOT_PY} +/* Define to 1 if you have the <zlib.h> header file. */ +#cmakedefine HAVE_ZLIB_H ${HAVE_ZLIB_H} + /* Have host's _alloca */ #cmakedefine HAVE__ALLOCA ${HAVE__ALLOCA} @@ -570,6 +579,9 @@ /* Define if threads enabled */ #cmakedefine01 LLVM_ENABLE_THREADS +/* Define if zlib compression is available */ +#cmakedefine01 LLVM_ENABLE_ZLIB + /* Installation directory for config files */ #cmakedefine LLVM_ETCDIR "${LLVM_ETCDIR}" diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 2f9e6ffe23..7fa00b8a03 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -78,6 +78,17 @@ /* Define to 1 if you have the <ctype.h> header file. */ #undef HAVE_CTYPE_H +/* Define to 1 if you have the <cxxabi.h> header file. */ +#undef HAVE_CXXABI_H + +/* Define to 1 if you have the declaration of `FE_ALL_EXCEPT', and to 0 if you + don't. */ +#undef HAVE_DECL_FE_ALL_EXCEPT + +/* Define to 1 if you have the declaration of `FE_INEXACT', and to 0 if you + don't. */ +#undef HAVE_DECL_FE_INEXACT + /* Define to 1 if you have the declaration of `strerror_s', and to 0 if you don't. */ #undef HAVE_DECL_STRERROR_S @@ -218,6 +229,9 @@ /* Define to 1 if you have the `udis86' library (-ludis86). */ #undef HAVE_LIBUDIS86 +/* Define to 1 if you have the `z' library (-lz). */ +#undef HAVE_LIBZ + /* Define to 1 if you have the <limits.h> header file. */ #undef HAVE_LIMITS_H @@ -495,6 +509,9 @@ /* Define if the xdot.py program is available */ #undef HAVE_XDOT_PY +/* Define to 1 if you have the <zlib.h> header file. */ +#undef HAVE_ZLIB_H + /* Have host's _alloca */ #undef HAVE__ALLOCA @@ -567,6 +584,9 @@ /* Define if threads enabled */ #undef LLVM_ENABLE_THREADS +/* Define if zlib is enabled */ +#undef LLVM_ENABLE_ZLIB + /* Installation directory for config files */ #undef LLVM_ETCDIR diff --git a/include/llvm/DIBuilder.h b/include/llvm/DIBuilder.h index d59847558a..2c0f712a93 100644 --- a/include/llvm/DIBuilder.h +++ b/include/llvm/DIBuilder.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines a DIBuilder that is useful for creating debugging +// This file defines a DIBuilder that is useful for creating debugging // information entries in LLVM IR form. // //===----------------------------------------------------------------------===// @@ -37,11 +37,13 @@ namespace llvm { class DIType; class DIArray; class DIGlobalVariable; + class DIImportedModule; class DINameSpace; class DIVariable; class DISubrange; class DILexicalBlockFile; class DILexicalBlock; + class DIScope; class DISubprogram; class DITemplateTypeParameter; class DITemplateValueParameter; @@ -57,6 +59,7 @@ namespace llvm { MDNode *TempRetainTypes; MDNode *TempSubprograms; MDNode *TempGVs; + MDNode *TempImportedModules; Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value @@ -65,6 +68,7 @@ namespace llvm { SmallVector<Value *, 4> AllRetainTypes; SmallVector<Value *, 4> AllSubprograms; SmallVector<Value *, 4> AllGVs; + SmallVector<Value *, 4> AllImportedModules; DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; @@ -82,18 +86,18 @@ namespace llvm { /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 /// @param File File name /// @param Dir Directory - /// @param Producer String identify producer of debugging information. + /// @param Producer String identify producer of debugging information. /// Usuall this is a compiler version string. /// @param isOptimized A boolean flag which indicates whether optimization /// is ON or not. - /// @param Flags This string lists command line options. This string is + /// @param Flags This string lists command line options. This string is /// directly embedded in debug info output which may be used /// by a tool analyzing generated debugging information. - /// @param RV This indicates runtime version for languages like + /// @param RV This indicates runtime version for languages like /// Objective-C. /// @param SplitName The name of the file that we'll split debug info out /// into. - void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, + void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, StringRef Producer, bool isOptimized, StringRef Flags, unsigned RV, StringRef SplitName = StringRef()); @@ -101,14 +105,14 @@ namespace llvm { /// createFile - Create a file descriptor to hold debugging information /// for a file. DIFile createFile(StringRef Filename, StringRef Directory); - + /// createEnumerator - Create a single enumerator value. DIEnumerator createEnumerator(StringRef Name, uint64_t Val); /// createNullPtrType - Create C++0x nullptr type. DIType createNullPtrType(StringRef Name); - /// createBasicType - Create debugging information entry for a basic + /// createBasicType - Create debugging information entry for a basic /// type. /// @param Name Type name. /// @param SizeInBits Size of the type. @@ -158,7 +162,7 @@ namespace llvm { /// @param Ty Original type. /// @param BaseTy Base type. Ty is inherits from base. /// @param BaseOffset Base offset. - /// @param Flags Flags to describe inheritance attribute, + /// @param Flags Flags to describe inheritance attribute, /// e.g. private DIDerivedType createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, unsigned Flags); @@ -209,8 +213,8 @@ namespace llvm { /// selector. /// @param PropertyAttributes Objective C property attributes. DIType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned LineNo, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType Ty, StringRef PropertyName = StringRef(), StringRef PropertyGetterName = StringRef(), @@ -229,8 +233,8 @@ namespace llvm { /// @param Ty Parent type. /// @param PropertyNode Property associated with this ivar. DIType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned LineNo, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, DIType Ty, MDNode *PropertyNode); @@ -249,7 +253,7 @@ namespace llvm { 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. @@ -261,16 +265,17 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Elements class members. /// @param VTableHolder Debug info of the base class that contains vtable - /// for this type. This is used in + /// for this type. This is used in /// DW_AT_containing_type. See DWARF documentation /// for more info. /// @param TemplateParms Template type parameters. - DIType createClassType(DIDescriptor Scope, StringRef Name, DIFile File, - unsigned LineNumber, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType DerivedFrom, - DIArray Elements, MDNode *VTableHolder = 0, - MDNode *TemplateParms = 0); + DICompositeType createClassType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + DIType DerivedFrom, DIArray Elements, + MDNode *VTableHolder = 0, + MDNode *TemplateParms = 0); /// createStructType - Create debugging information entry for a struct. /// @param Scope Scope in which this struct is defined. @@ -345,22 +350,25 @@ namespace llvm { /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DIType createVectorType(uint64_t Size, uint64_t AlignInBits, + DIType createVectorType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts); - /// createEnumerationType - Create debugging information entry for an + /// createEnumerationType - Create debugging information entry for an /// enumeration. - /// @param Scope Scope in which this enumeration is defined. - /// @param Name Union name. - /// @param File File where this member is defined. - /// @param LineNumber Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param Elements Enumeration elements. - DICompositeType createEnumerationType( - DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements, - DIType ClassType); + /// @param Scope Scope in which this enumeration is defined. + /// @param Name Union name. + /// @param File File where this member is defined. + /// @param LineNumber Line number. + /// @param SizeInBits Member size. + /// @param AlignInBits Member alignment. + /// @param Elements Enumeration elements. + /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. + DICompositeType createEnumerationType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNumber, + uint64_t SizeInBits, + uint64_t AlignInBits, + DIArray Elements, + DIType UnderlyingType); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. @@ -375,16 +383,12 @@ namespace llvm { /// flag set. DIType createObjectPointerType(DIType Ty); - /// createTemporaryType - Create a temporary forward-declared type. - DIType createTemporaryType(); - DIType createTemporaryType(DIFile F); - /// createForwardDecl - Create a temporary forward-declared type. DIType createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, uint64_t AlignInBits = 0); - /// retainType - Retain DIType in a module even if it is not referenced + /// retainType - Retain DIType in a module even if it is not referenced /// through debug info anchors. void retainType(DIType T); @@ -411,8 +415,21 @@ namespace llvm { createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo, DIType Ty, bool isLocalToUnit, llvm::Value *Val); + /// \brief Create a new descriptor for the specified global. + /// @param Name Name of the variable. + /// @param LinkageName Mangled variable name. + /// @param File File where this variable is defined. + /// @param LineNo Line number. + /// @param Ty Variable Type. + /// @param isLocalToUnit Boolean flag indicate whether this variable is + /// externally visible or not. + /// @param Val llvm::Value of the variable. + DIGlobalVariable + createGlobalVariable(StringRef Name, StringRef LinkageName, DIFile File, + unsigned LineNo, DIType Ty, bool isLocalToUnit, + llvm::Value *Val); - /// createStaticVariable - Create a new descriptor for the specified + /// createStaticVariable - Create a new descriptor for the specified /// variable. /// @param Context Variable scope. /// @param Name Name of the variable. @@ -425,13 +442,13 @@ namespace llvm { /// @param Val llvm::Value of the variable. /// @param Decl Reference to the corresponding declaration. DIGlobalVariable - createStaticVariable(DIDescriptor Context, StringRef Name, - StringRef LinkageName, DIFile File, unsigned LineNo, + createStaticVariable(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile File, unsigned LineNo, DIType Ty, bool isLocalToUnit, llvm::Value *Val, MDNode *Decl = NULL); - /// createLocalVariable - Create a new descriptor for the specified + /// createLocalVariable - Create a new descriptor for the specified /// local variable. /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or /// DW_TAG_arg_variable. @@ -508,7 +525,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 Virtuality Attributes describing virtualness. e.g. pure + /// @param Virtuality Attributes describing virtualness. e.g. pure /// virtual function. /// @param VTableIndex Index no of this method in virtual table. /// @param VTableHolder Type that holds vtable. @@ -546,7 +563,7 @@ namespace llvm { /// @param File Source file. DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File); - + /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. /// @param Scope Parent lexical scope. @@ -556,6 +573,13 @@ namespace llvm { DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, unsigned Line, unsigned Col); + /// \brief Create a descriptor for an imported module. + /// @param Context The scope this module is imported into + /// @param NS The namespace being imported here + /// @param Line Line number + DIImportedModule createImportedModule(DIScope Context, DINameSpace NS, + unsigned Line); + /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. @@ -577,16 +601,16 @@ namespace llvm { /// @param VarInfo Variable's debug info descriptor. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, + DIVariable VarInfo, BasicBlock *InsertAtEnd); - + /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, + DIVariable VarInfo, Instruction *InsertBefore); }; diff --git a/include/llvm/DebugInfo.h b/include/llvm/DebugInfo.h index a9d5a4b7b6..f9b58f4770 100644 --- a/include/llvm/DebugInfo.h +++ b/include/llvm/DebugInfo.h @@ -125,6 +125,7 @@ namespace llvm { bool isTemplateTypeParameter() const; bool isTemplateValueParameter() const; bool isObjCProperty() const; + bool isImportedModule() const; /// print - print descriptor. void print(raw_ostream &OS) const; @@ -177,6 +178,7 @@ namespace llvm { if (DbgNode && !isFile()) DbgNode = 0; } + MDNode *getFileNode() const; bool Verify() const; }; @@ -188,22 +190,17 @@ namespace llvm { explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} unsigned getLanguage() const { return getUnsignedField(2); } - StringRef getFilename() const { - return getFieldAs<DIFile>(3).getFilename(); - } - StringRef getDirectory() const { - return getFieldAs<DIFile>(3).getDirectory(); - } - StringRef getProducer() const { return getStringField(4); } + StringRef getProducer() const { return getStringField(3); } - bool isOptimized() const { return getUnsignedField(5) != 0; } - StringRef getFlags() const { return getStringField(6); } - unsigned getRunTimeVersion() const { return getUnsignedField(7); } + bool isOptimized() const { return getUnsignedField(4) != 0; } + StringRef getFlags() const { return getStringField(5); } + unsigned getRunTimeVersion() const { return getUnsignedField(6); } DIArray getEnumTypes() const; DIArray getRetainedTypes() const; DIArray getSubprograms() const; DIArray getGlobalVariables() const; + DIArray getImportedModules() const; StringRef getSplitDebugFilename() const { return getStringField(12); } @@ -241,9 +238,8 @@ namespace llvm { explicit DIType(const MDNode *N); explicit DIType() {} - DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getName() const { return getStringField(2); } - DIFile getFile() const { return getFieldAs<DIFile>(3); } + DIScope getContext() const { return getFieldAs<DIScope>(2); } + StringRef getName() const { return getStringField(3); } unsigned getLineNumber() const { return getUnsignedField(4); } uint64_t getSizeInBits() const { return getUInt64Field(5); } uint64_t getAlignInBits() const { return getUInt64Field(6); } @@ -288,12 +284,6 @@ namespace llvm { bool isValid() const { return DbgNode && (isBasicType() || isDerivedType() || isCompositeType()); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(3).getDirectory(); - } - StringRef getFilename() const { - return getFieldAs<DIFile>(3).getFilename(); - } /// isUnsignedDIType - Return true if type encoding is unsigned. bool isUnsignedDIType(); @@ -354,7 +344,10 @@ namespace llvm { /// DICompositeType - This descriptor holds a type that can refer to multiple /// other types, like a function or struct. - /// FIXME: Why is this a DIDerivedType?? + /// DICompositeType is derived from DIDerivedType because some + /// composite types (such as enums) can be derived from basic types + // FIXME: Make this derive from DIType directly & just store the + // base type in a single DIType field. class DICompositeType : public DIDerivedType { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -366,10 +359,12 @@ namespace llvm { } DIArray getTypeArray() const { return getFieldAs<DIArray>(10); } + void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); unsigned getRunTimeLang() const { return getUnsignedField(11); } DICompositeType getContainingType() const { return getFieldAs<DICompositeType>(12); } + void setContainingType(DICompositeType ContainingType); DIArray getTemplateParams() const { return getFieldAs<DIArray>(13); } /// Verify - Verify that a composite type descriptor is well formed. @@ -426,78 +421,66 @@ namespace llvm { StringRef getName() const { return getStringField(3); } StringRef getDisplayName() const { return getStringField(4); } StringRef getLinkageName() const { return getStringField(5); } - unsigned getLineNumber() const { return getUnsignedField(7); } - DICompositeType getType() const { return getFieldAs<DICompositeType>(8); } + unsigned getLineNumber() const { return getUnsignedField(6); } + DICompositeType getType() const { return getFieldAs<DICompositeType>(7); } /// getReturnTypeName - Subprogram return types are encoded either as /// DIType or as DICompositeType. StringRef getReturnTypeName() const { - DICompositeType DCT(getFieldAs<DICompositeType>(8)); + DICompositeType DCT(getFieldAs<DICompositeType>(7)); if (DCT.Verify()) { DIArray A = DCT.getTypeArray(); DIType T(A.getElement(0)); return T.getName(); } - DIType T(getFieldAs<DIType>(8)); + DIType T(getFieldAs<DIType>(7)); return T.getName(); } /// isLocalToUnit - Return true if this subprogram is local to the current /// compile unit, like 'static' in C. - unsigned isLocalToUnit() const { return getUnsignedField(9); } - unsigned isDefinition() const { return getUnsignedField(10); } + unsigned isLocalToUnit() const { return getUnsignedField(8); } + unsigned isDefinition() const { return getUnsignedField(9); } - unsigned getVirtuality() const { return getUnsignedField(11); } - unsigned getVirtualIndex() const { return getUnsignedField(12); } + unsigned getVirtuality() const { return getUnsignedField(10); } + unsigned getVirtualIndex() const { return getUnsignedField(11); } DICompositeType getContainingType() const { - return getFieldAs<DICompositeType>(13); + return getFieldAs<DICompositeType>(12); } unsigned getFlags() const { - return getUnsignedField(14); + return getUnsignedField(13); } unsigned isArtificial() const { - return (getUnsignedField(14) & FlagArtificial) != 0; + return (getUnsignedField(13) & FlagArtificial) != 0; } /// isPrivate - Return true if this subprogram has "private" /// access specifier. bool isPrivate() const { - return (getUnsignedField(14) & FlagPrivate) != 0; + return (getUnsignedField(13) & FlagPrivate) != 0; } /// isProtected - Return true if this subprogram has "protected" /// access specifier. bool isProtected() const { - return (getUnsignedField(14) & FlagProtected) != 0; + return (getUnsignedField(13) & FlagProtected) != 0; } /// isExplicit - Return true if this subprogram is marked as explicit. bool isExplicit() const { - return (getUnsignedField(14) & FlagExplicit) != 0; + return (getUnsignedField(13) & FlagExplicit) != 0; } /// isPrototyped - Return true if this subprogram is prototyped. bool isPrototyped() const { - return (getUnsignedField(14) & FlagPrototyped) != 0; + return (getUnsignedField(13) & FlagPrototyped) != 0; } unsigned isOptimized() const; - StringRef getFilename() const { - return getFieldAs<DIFile>(6).getFilename(); - } - - StringRef getDirectory() const { - return getFieldAs<DIFile>(6).getDirectory(); - } - - DIFile getFile() const { - return getFieldAs<DIFile>(6); - } - /// 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); } + unsigned getScopeLineNumber() const { return getUnsignedField(19); } /// Verify - Verify that a subprogram descriptor is well formed. bool Verify() const; @@ -506,11 +489,11 @@ namespace llvm { /// information for the function F. bool describes(const Function *F); - Function *getFunction() const { return getFunctionField(16); } - void replaceFunction(Function *F) { replaceFunctionField(16, F); } - DIArray getTemplateParams() const { return getFieldAs<DIArray>(17); } + Function *getFunction() const { return getFunctionField(15); } + void replaceFunction(Function *F) { replaceFunctionField(15, F); } + DIArray getTemplateParams() const { return getFieldAs<DIArray>(16); } DISubprogram getFunctionDeclaration() const { - return getFieldAs<DISubprogram>(18); + return getFieldAs<DISubprogram>(17); } MDNode *getVariablesNodes() const; DIArray getVariables() const; @@ -614,15 +597,9 @@ namespace llvm { class DILexicalBlock : public DIScope { public: explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(1); } - unsigned getLineNumber() const { return getUnsignedField(2); } - unsigned getColumnNumber() const { return getUnsignedField(3); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(4).getDirectory(); - } - StringRef getFilename() const { - return getFieldAs<DIFile>(4).getFilename(); - } + DIScope getContext() const { return getFieldAs<DIScope>(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + unsigned getColumnNumber() const { return getUnsignedField(4); } bool Verify() const; }; @@ -634,28 +611,18 @@ namespace llvm { DIScope getContext() const { if (getScope().isSubprogram()) return getScope(); return getScope().getContext(); } unsigned getLineNumber() const { return getScope().getLineNumber(); } unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(2).getDirectory(); - } - StringRef getFilename() const { - return getFieldAs<DIFile>(2).getFilename(); - } - DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(1); } + DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); } bool Verify() const; }; /// DINameSpace - A wrapper for a C++ style name space. class DINameSpace : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getName() const { return getStringField(2); } - StringRef getDirectory() const { - return getFieldAs<DIFile>(3).getDirectory(); - } - StringRef getFilename() const { - return getFieldAs<DIFile>(3).getFilename(); - } + DIScope getContext() const { return getFieldAs<DIScope>(2); } + StringRef getName() const { return getStringField(3); } unsigned getLineNumber() const { return getUnsignedField(4); } bool Verify() const; }; @@ -716,6 +683,18 @@ namespace llvm { bool Verify() const; }; + /// \brief An imported module (C++ using directive or similar). + class DIImportedModule : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + public: + explicit DIImportedModule(const MDNode *N) : DIDescriptor(N) { } + DIScope getContext() const { return getFieldAs<DIScope>(1); } + DINameSpace getNameSpace() const { return getFieldAs<DINameSpace>(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + bool Verify() const; + }; + /// getDISubprogram - Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h new file mode 100644 index 0000000000..eaaccfb4f3 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFFormValue.h @@ -0,0 +1,82 @@ +//===-- DWARFFormValue.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H +#define LLVM_DEBUGINFO_DWARFFORMVALUE_H + +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class DWARFCompileUnit; +class raw_ostream; + +class DWARFFormValue { +public: + struct ValueType { + ValueType() : data(NULL) { + uval = 0; + } + + union { + uint64_t uval; + int64_t sval; + const char* cstr; + }; + const uint8_t* data; + }; + + enum { + eValueTypeInvalid = 0, + eValueTypeUnsigned, + eValueTypeSigned, + eValueTypeCStr, + eValueTypeBlock + }; + +private: + uint16_t Form; // Form for this value. + ValueType Value; // Contains all data for the form. + +public: + DWARFFormValue(uint16_t form = 0) : Form(form) {} + uint16_t getForm() const { return Form; } + const ValueType& value() const { return Value; } + void dump(raw_ostream &OS, const DWARFCompileUnit* cu) const; + bool extractValue(DataExtractor data, uint32_t *offset_ptr, + const DWARFCompileUnit *cu); + bool isInlinedCStr() const { + return Value.data != NULL && Value.data == (const uint8_t*)Value.cstr; + } + const uint8_t *BlockData() const; + uint64_t getReference(const DWARFCompileUnit* cu) const; + + /// Resolve any compile unit specific references so that we don't need + /// the compile unit at a later time in order to work with the form + /// value. + bool resolveCompileUnitReferences(const DWARFCompileUnit* cu); + uint64_t getUnsigned() const { return Value.uval; } + int64_t getSigned() const { return Value.sval; } + const char *getAsCString(const DataExtractor *debug_str_data_ptr) const; + const char *getIndirectCString(const DataExtractor *, + const DataExtractor *) const; + uint64_t getIndirectAddress(const DataExtractor *, + const DWARFCompileUnit *) const; + bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, + const DWARFCompileUnit *cu) const; + static bool skipValue(uint16_t form, DataExtractor debug_info_data, + uint32_t *offset_ptr, const DWARFCompileUnit *cu); + static bool isBlockForm(uint16_t form); + static bool isDataForm(uint16_t form); + static const uint8_t *getFixedFormSizes(uint8_t AddrSize, uint16_t Version); +}; + +} + +#endif diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 3fd69e266b..bbaebc6f90 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -15,6 +15,7 @@ #ifndef LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H #define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H +#include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -42,6 +43,7 @@ class JITMemoryManager; class MachineCodeInfo; class Module; class MutexGuard; +class ObjectCache; class DataLayout; class Triple; class Type; @@ -371,6 +373,12 @@ public: virtual void RegisterJITEventListener(JITEventListener *) {} virtual void UnregisterJITEventListener(JITEventListener *) {} + /// Sets the pre-compiled object cache. The ownership of the ObjectCache is + /// not changed. Supported by MCJIT but not JIT. + virtual void setObjectCache(ObjectCache *) { + llvm_unreachable("No support for an object cache"); + } + /// DisableLazyCompilation - When lazy compilation is off (the default), the /// JIT will eagerly compile every function reachable from the argument to /// getPointerToFunction. If lazy compilation is turned on, the JIT will only @@ -625,6 +633,9 @@ public: ExecutionEngine *create(TargetMachine *TM); }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionEngine, LLVMExecutionEngineRef) + } // End llvm namespace #endif diff --git a/include/llvm/ExecutionEngine/GenericValue.h b/include/llvm/ExecutionEngine/GenericValue.h index 21b99421b3..0e92f79eba 100644 --- a/include/llvm/ExecutionEngine/GenericValue.h +++ b/include/llvm/ExecutionEngine/GenericValue.h @@ -35,14 +35,19 @@ struct GenericValue { struct IntPair UIntPairVal; unsigned char Untyped[8]; }; - APInt IntVal; // also used for long doubles - - GenericValue() : DoubleVal(0.0), IntVal(1,0) {} + APInt IntVal; // also used for long doubles. + // For aggregate data types. + std::vector<GenericValue> AggregateVal; + + // to make code faster, set GenericValue to zero could be omitted, but it is + // potentially can cause problems, since GenericValue to store garbage + // instead of zero. + GenericValue() : IntVal(1,0) {UIntPairVal.first = 0; UIntPairVal.second = 0;} explicit GenericValue(void *V) : PointerVal(V), IntVal(1,0) { } }; inline GenericValue PTOGV(void *P) { return GenericValue(P); } inline void* GVTOP(const GenericValue &GV) { return GV.PointerVal; } -} // End llvm namespace +} // End llvm namespace. #endif diff --git a/include/llvm/ExecutionEngine/ObjectCache.h b/include/llvm/ExecutionEngine/ObjectCache.h new file mode 100644 index 0000000000..0bee86161b --- /dev/null +++ b/include/llvm/ExecutionEngine/ObjectCache.h @@ -0,0 +1,54 @@ +//===-- ObjectCache.h - Class definition for the ObjectCache -----C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_EXECUTIONENGINE_OBJECTCACHE_H +#define LLVM_LIB_EXECUTIONENGINE_OBJECTCACHE_H + +#include "llvm/Support/MemoryBuffer.h" + +namespace llvm { + +class Module; + +/// This is the base ObjectCache type which can be provided to an +/// ExecutionEngine for the purpose of avoiding compilation for Modules that +/// have already been compiled and an object file is available. +class ObjectCache { +public: + ObjectCache() { } + + virtual ~ObjectCache() { } + + /// notifyObjectCompiled - Provides a pointer to compiled code for Module M. + virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) = 0; + + /// getObjectCopy - Returns a pointer to a newly allocated MemoryBuffer that + /// contains the object which corresponds with Module M, or 0 if an object is + /// not available. The caller owns the MemoryBuffer returned by this function. + MemoryBuffer* getObjectCopy(const Module* M) { + const MemoryBuffer* Obj = getObject(M); + if (Obj) + return MemoryBuffer::getMemBufferCopy(Obj->getBuffer()); + else + return 0; + } + +protected: + /// getObject - Returns a pointer to a MemoryBuffer that contains an object + /// that corresponds with Module M, or 0 if an object is not available. + /// The pointer returned by this function is not suitable for loading because + /// the memory is read-only and owned by the ObjectCache. To retrieve an + /// owning pointer to a MemoryBuffer (which is suitable for calling + /// RuntimeDyld::loadObject() with) use getObjectCopy() instead. + virtual const MemoryBuffer* getObject(const Module* M) = 0; +}; + +} + +#endif diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index ae5004e130..9ac8c92524 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -87,9 +87,7 @@ public: /// explicit cache flush, otherwise JIT code manipulations (like resolved /// relocations) will get to the data cache but not to the instruction cache. /// - /// This method is not called by RuntimeDyld or MCJIT during the load - /// process. Clients may call this function when needed. See the lli - /// tool for example use. + /// This method is called from applyPermissions. virtual void invalidateInstructionCache(); private: diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index ef4e4fc7aa..40d61ff685 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -78,6 +78,10 @@ public: /// containing function. bool hasStructRetAttr() const; + /// \brief Return true if this argument has the returned attribute on it in + /// its containing function. + bool hasReturnedAttr() const; + /// \brief Add a Attribute to an argument. void addAttr(AttributeSet AS); diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 074b38779a..2c7da6485d 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -87,6 +87,7 @@ public: OptimizeForSize, ///< opt_size ReadNone, ///< Function does not access memory ReadOnly, ///< Function only reads from memory + Returned, ///< Return value is always equal to this argument ReturnsTwice, ///< Function can return twice SExt, ///< Sign extended before/after call StackAlignment, ///< Alignment of stack for function (3 bits) @@ -209,7 +210,7 @@ private: AttributeSetImpl *pImpl; /// \brief The attributes for the specified index are returned. - AttributeSetNode *getAttributes(unsigned Idx) const; + AttributeSetNode *getAttributes(unsigned Index) const; /// \brief Create an AttributeSet with the specified parameters in it. static AttributeSet get(LLVMContext &C, @@ -233,35 +234,35 @@ public: /// \brief Return an AttributeSet with the specified parameters in it. static AttributeSet get(LLVMContext &C, ArrayRef<AttributeSet> Attrs); - static AttributeSet get(LLVMContext &C, unsigned Idx, + static AttributeSet get(LLVMContext &C, unsigned Index, ArrayRef<Attribute::AttrKind> Kind); - static AttributeSet get(LLVMContext &C, unsigned Idx, AttrBuilder &B); + static AttributeSet get(LLVMContext &C, unsigned Index, AttrBuilder &B); /// \brief Add an attribute to the attribute set at the given index. Since /// attribute sets are immutable, this returns a new set. - AttributeSet addAttribute(LLVMContext &C, unsigned Idx, + AttributeSet addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const; /// \brief Add an attribute to the attribute set at the given index. Since /// attribute sets are immutable, this returns a new set. - AttributeSet addAttribute(LLVMContext &C, unsigned Idx, + AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind) const; /// \brief Add attributes to the attribute set at the given index. Since /// attribute sets are immutable, this returns a new set. - AttributeSet addAttributes(LLVMContext &C, unsigned Idx, + AttributeSet addAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; /// \brief Remove the specified attribute at the specified index from this /// attribute list. Since attribute lists are immutable, this returns the new /// list. - AttributeSet removeAttribute(LLVMContext &C, unsigned Idx, + AttributeSet removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const; /// \brief Remove the specified attributes at the specified index from this /// attribute list. Since attribute lists are immutable, this returns the new /// list. - AttributeSet removeAttributes(LLVMContext &C, unsigned Idx, + AttributeSet removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; //===--------------------------------------------------------------------===// @@ -272,7 +273,7 @@ public: LLVMContext &getContext() const; /// \brief The attributes for the specified index are returned. - AttributeSet getParamAttributes(unsigned Idx) const; + AttributeSet getParamAttributes(unsigned Index) const; /// \brief The attributes for the ret value are returned. AttributeSet getRetAttributes() const; @@ -300,7 +301,7 @@ public: Attribute getAttribute(unsigned Index, StringRef Kind) const; /// \brief Return the alignment for the specified function parameter. - unsigned getParamAlignment(unsigned Idx) const; + unsigned getParamAlignment(unsigned Index) const; /// \brief Get the stack alignment. unsigned getStackAlignment(unsigned Index) const; @@ -310,8 +311,8 @@ public: typedef ArrayRef<Attribute>::iterator iterator; - iterator begin(unsigned Idx) const; - iterator end(unsigned Idx) const; + iterator begin(unsigned Slot) const; + iterator end(unsigned Slot) const; /// operator==/!= - Provide equality predicates. bool operator==(const AttributeSet &RHS) const { @@ -344,7 +345,7 @@ public: unsigned getNumSlots() const; /// \brief Return the index for the given slot. - uint64_t getSlotIndex(unsigned Slot) const; + unsigned getSlotIndex(unsigned Slot) const; /// \brief Return the attributes at the given slot. AttributeSet getSlotAttributes(unsigned Slot) const; @@ -473,9 +474,6 @@ public: bool td_empty() const { return TargetDepAttrs.empty(); } - /// \brief Remove attributes that are used on functions only. - void removeFunctionOnlyAttrs(); - bool operator==(const AttrBuilder &B); bool operator!=(const AttrBuilder &B) { return !(*this == B); diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index ea5695a9e6..3bdc95d556 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ilist.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/SymbolTableListTraits.h" +#include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -298,6 +299,9 @@ private: } }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef) + } // End llvm namespace #endif diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index ad258f9aca..2f29f54594 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -26,6 +26,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/Constant.h" #include "llvm/IR/OperandTraits.h" +#include "llvm/IR/DerivedTypes.h" namespace llvm { @@ -138,7 +139,7 @@ public: /// which reduces the amount of casting needed in parts of the compiler. /// inline IntegerType *getType() const { - return reinterpret_cast<IntegerType*>(Value::getType()); + return cast<IntegerType>(Value::getType()); } /// This static method returns true if the type Ty is big enough to @@ -354,7 +355,7 @@ public: /// which reduces the amount of casting needed in parts of the compiler. /// inline ArrayType *getType() const { - return reinterpret_cast<ArrayType*>(Value::getType()); + return cast<ArrayType>(Value::getType()); } virtual void destroyConstant(); @@ -412,7 +413,7 @@ public: /// getType() specialization - Reduce amount of casting... /// inline StructType *getType() const { - return reinterpret_cast<StructType*>(Value::getType()); + return cast<StructType>(Value::getType()); } virtual void destroyConstant(); @@ -455,7 +456,7 @@ public: /// which reduces the amount of casting needed in parts of the compiler. /// inline VectorType *getType() const { - return reinterpret_cast<VectorType*>(Value::getType()); + return cast<VectorType>(Value::getType()); } /// getSplatValue - If this is a splat constant, meaning that all of the @@ -486,7 +487,7 @@ class ConstantPointerNull : public Constant { ConstantPointerNull(const ConstantPointerNull &) LLVM_DELETED_FUNCTION; protected: explicit ConstantPointerNull(PointerType *T) - : Constant(reinterpret_cast<Type*>(T), + : Constant(T, Value::ConstantPointerNullVal, 0, 0) {} protected: @@ -504,7 +505,7 @@ public: /// which reduces the amount of casting needed in parts of the compiler. /// inline PointerType *getType() const { - return reinterpret_cast<PointerType*>(Value::getType()); + return cast<PointerType>(Value::getType()); } /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -580,7 +581,7 @@ public: /// SequentialType, which reduces the amount of casting needed in parts of the /// compiler. inline SequentialType *getType() const { - return reinterpret_cast<SequentialType*>(Value::getType()); + return cast<SequentialType>(Value::getType()); } /// getElementType - Return the element type of the array/vector. @@ -679,7 +680,7 @@ public: /// which reduces the amount of casting needed in parts of the compiler. /// inline ArrayType *getType() const { - return reinterpret_cast<ArrayType*>(Value::getType()); + return cast<ArrayType>(Value::getType()); } /// Methods for support type inquiry through isa, cast, and dyn_cast: @@ -732,7 +733,7 @@ public: /// which reduces the amount of casting needed in parts of the compiler. /// inline VectorType *getType() const { - return reinterpret_cast<VectorType*>(Value::getType()); + return cast<VectorType>(Value::getType()); } /// Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 4d3016c72f..b0def6be3f 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -22,6 +22,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Type.h" #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" @@ -169,13 +171,13 @@ public: /// Initialize target data from properties stored in the module. explicit DataLayout(const Module *M); - DataLayout(const DataLayout &TD) : + DataLayout(const DataLayout &DL) : ImmutablePass(ID), - LittleEndian(TD.isLittleEndian()), - StackNaturalAlign(TD.StackNaturalAlign), - LegalIntWidths(TD.LegalIntWidths), - Alignments(TD.Alignments), - Pointers(TD.Pointers), + LittleEndian(DL.isLittleEndian()), + StackNaturalAlign(DL.StackNaturalAlign), + LegalIntWidths(DL.LegalIntWidths), + Alignments(DL.Alignments), + Pointers(DL.Pointers), LayoutMap(0) { } @@ -350,6 +352,10 @@ public: /// type. Type *getIntPtrType(Type *) const; + /// getSmallestLegalIntType - Return the smallest integer type with size at + /// least as big as Width bits. + Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const; + /// getIndexedOffset - return the offset from the beginning of the type for /// the specified indices. This is used to implement getelementptr. uint64_t getIndexedOffset(Type *Ty, ArrayRef<Value *> Indices) const; @@ -420,9 +426,52 @@ public: private: friend class DataLayout; // Only DataLayout can create this class - StructLayout(StructType *ST, const DataLayout &TD); + StructLayout(StructType *ST, const DataLayout &DL); }; + +// The implementation of this method is provided inline as it is particularly +// well suited to constant folding when called on a specific Type subclass. +inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { + assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); + switch (Ty->getTypeID()) { + case Type::LabelTyID: + return getPointerSizeInBits(0); + case Type::PointerTyID: + return getPointerSizeInBits(cast<PointerType>(Ty)->getAddressSpace()); + case Type::ArrayTyID: { + ArrayType *ATy = cast<ArrayType>(Ty); + return ATy->getNumElements() * + getTypeAllocSizeInBits(ATy->getElementType()); + } + case Type::StructTyID: + // Get the layout annotation... which is lazily created on demand. + return getStructLayout(cast<StructType>(Ty))->getSizeInBits(); + case Type::IntegerTyID: + return cast<IntegerType>(Ty)->getBitWidth(); + case Type::HalfTyID: + return 16; + case Type::FloatTyID: + return 32; + case Type::DoubleTyID: + case Type::X86_MMXTyID: + return 64; + case Type::PPC_FP128TyID: + case Type::FP128TyID: + return 128; + // In memory objects this is always aligned to a higher boundary, but + // only 80 bits contain information. + case Type::X86_FP80TyID: + return 80; + case Type::VectorTyID: { + VectorType *VTy = cast<VectorType>(Ty); + return VTy->getNumElements() * getTypeSizeInBits(VTy->getElementType()); + } + default: + llvm_unreachable("DataLayout::getTypeSizeInBits(): Unsupported type"); + } +} + } // End llvm namespace #endif diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index 6c00f596ba..e279e60e47 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -117,7 +117,7 @@ public: /// argument type. static bool isValidArgumentType(Type *ArgTy); - bool isVarArg() const { return getSubclassData(); } + bool isVarArg() const { return getSubclassData()!=0; } Type *getReturnType() const { return ContainedTys[0]; } typedef Type::subtype_iterator param_iterator; diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index f398bc1b87..260302a594 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -19,6 +19,7 @@ #define LLVM_IR_GLOBALVALUE_H #include "llvm/IR/Constant.h" +#include "llvm/IR/DerivedTypes.h" namespace llvm { @@ -105,7 +106,7 @@ public: /// getType - Global values are always pointers. inline PointerType *getType() const { - return reinterpret_cast<PointerType*>(User::getType()); + return cast<PointerType>(User::getType()); } static LinkageTypes getLinkOnceLinkage(bool ODR) { diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 1c71d0a901..f11d3b4e0b 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -23,6 +23,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Operator.h" +#include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/ConstantFolder.h" namespace llvm { @@ -48,6 +49,10 @@ protected: class IRBuilderBase { DebugLoc CurDbgLocation; protected: + /// Save the current debug location here while we are suppressing + /// line table entries. + llvm::DebugLoc SavedDbgLocation; + BasicBlock *BB; BasicBlock::iterator InsertPt; LLVMContext &Context; @@ -112,6 +117,23 @@ public: CurDbgLocation = L; } + /// \brief Temporarily suppress DebugLocations from being attached + /// to emitted instructions, until the next call to + /// SetCurrentDebugLocation() or EnableDebugLocations(). Use this + /// if you want an instruction to be counted towards the prologue or + /// if there is no useful source location. + void DisableDebugLocations() { + llvm::DebugLoc Empty; + SavedDbgLocation = getCurrentDebugLocation(); + SetCurrentDebugLocation(Empty); + } + + /// \brief Restore the previously saved DebugLocation. + void EnableDebugLocations() { + assert(CurDbgLocation.isUnknown()); + SetCurrentDebugLocation(SavedDbgLocation); + } + /// \brief Get location information used by debugging information. DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } @@ -1396,6 +1418,9 @@ public: } }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRBuilder<>, LLVMBuilderRef) + } #endif diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index c97cd91d73..e69ddec1e3 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -63,14 +63,13 @@ namespace Intrinsic { /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function /// declaration for an intrinsic, and return it. /// - /// The Tys and numTys parameters are for intrinsics with overloaded types - /// (e.g., those using iAny, fAny, vAny, or iPTRAny). For a declaration for an - /// overloaded intrinsic, Tys should point to an array of numTys pointers to - /// Type, and must provide exactly one type for each overloaded type in the - /// intrinsic. + /// The Tys parameter is for intrinsics with overloaded types (e.g., those + /// using iAny, fAny, vAny, or iPTRAny). For a declaration of an overloaded + /// intrinsic, Tys must provide exactly one type for each overloaded type in + /// the intrinsic. Function *getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys = ArrayRef<Type*>()); - + /// Map a GCC builtin name to an intrinsic ID. ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName); diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index cde39ccd3c..5664f79250 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -117,28 +117,33 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". // Loads. These don't map directly to GCC builtins because they represent the // source address with a single pointer. def int_ppc_altivec_lvx : - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_ppc_altivec_lvxl : - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_ppc_altivec_lvebx : - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_ppc_altivec_lvehx : - Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty], [IntrReadMem]>; + Intrinsic<[llvm_v8i16_ty], [llvm_ptr_ty], [IntrReadArgMem]>; def int_ppc_altivec_lvewx : - Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadMem]>; + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; // Stores. These don't map directly to GCC builtins because they represent the // source address with a single pointer. def int_ppc_altivec_stvx : - Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], + [IntrReadWriteArgMem]>; def int_ppc_altivec_stvxl : - Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], + [IntrReadWriteArgMem]>; def int_ppc_altivec_stvebx : - Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_v16i8_ty, llvm_ptr_ty], + [IntrReadWriteArgMem]>; def int_ppc_altivec_stvehx : - Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_v8i16_ty, llvm_ptr_ty], + [IntrReadWriteArgMem]>; def int_ppc_altivec_stvewx : - Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], []>; + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], + [IntrReadWriteArgMem]>; // Comparisons setting a vector. def int_ppc_altivec_vcmpbfp : GCCBuiltin<"__builtin_altivec_vcmpbfp">, diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index d2463c0efa..69e0ab4fa2 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -2550,7 +2550,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //===----------------------------------------------------------------------===// -// RDRAND intrinsics. Return a random value and whether it is valid. +// RDRAND intrinsics - Return a random value and whether it is valid. +// RDSEED intrinsics - Return a NIST SP800-90B & C compliant random value and +// whether it is valid. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // These are declared side-effecting so they don't get eliminated by CSE or @@ -2558,6 +2560,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_rdrand_16 : Intrinsic<[llvm_i16_ty, llvm_i32_ty], [], []>; def int_x86_rdrand_32 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [], []>; def int_x86_rdrand_64 : Intrinsic<[llvm_i64_ty, llvm_i32_ty], [], []>; + def int_x86_rdseed_16 : Intrinsic<[llvm_i16_ty, llvm_i32_ty], [], []>; + def int_x86_rdseed_32 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [], []>; + def int_x86_rdseed_64 : Intrinsic<[llvm_i64_ty, llvm_i32_ty], [], []>; } //===----------------------------------------------------------------------===// @@ -2570,4 +2575,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[], [], []>; def int_x86_xabort : GCCBuiltin<"__builtin_ia32_xabort">, Intrinsic<[], [llvm_i8_ty], [IntrNoReturn]>; + def int_x86_xtest : GCCBuiltin<"__builtin_ia32_xtest">, + Intrinsic<[llvm_i32_ty], [], []>; } diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index ae81e5b1c3..f25d820c2b 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -15,7 +15,9 @@ #ifndef LLVM_IR_LLVMCONTEXT_H #define LLVM_IR_LLVMCONTEXT_H +#include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" +#include "llvm-c/Core.h" namespace llvm { @@ -109,6 +111,19 @@ private: /// only care about operating on a single thread. extern LLVMContext &getGlobalContext(); +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMContext, LLVMContextRef) + +/* Specialized opaque context conversions. + */ +inline LLVMContext **unwrap(LLVMContextRef* Tys) { + return reinterpret_cast<LLVMContext**>(Tys); +} + +inline LLVMContextRef *wrap(const LLVMContext **Tys) { + return reinterpret_cast<LLVMContextRef*>(const_cast<LLVMContext**>(Tys)); +} + } #endif diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index 604051b90a..ce81b5498f 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -156,6 +156,41 @@ public: return MDNode::get(Context, Vals); } + /// \brief Return metadata for a TBAA struct node in the type DAG + /// with the given name, a list of pairs (offset, field type in the type DAG). + MDNode *createTBAAStructTypeNode(StringRef Name, + ArrayRef<std::pair<MDNode*, uint64_t> > Fields) { + SmallVector<Value *, 4> Ops(Fields.size() * 2 + 1); + Type *Int64 = IntegerType::get(Context, 64); + Ops[0] = createString(Name); + for (unsigned i = 0, e = Fields.size(); i != e; ++i) { + Ops[i * 2 + 1] = Fields[i].first; + Ops[i * 2 + 2] = ConstantInt::get(Int64, Fields[i].second); + } + return MDNode::get(Context, Ops); + } + + /// \brief Return metadata for a TBAA scalar type node with the + /// given name, an offset and a parent in the TBAA type DAG. + MDNode *createTBAAScalarTypeNode(StringRef Name, MDNode *Parent, + uint64_t Offset = 0) { + SmallVector<Value *, 4> Ops(3); + Type *Int64 = IntegerType::get(Context, 64); + Ops[0] = createString(Name); + Ops[1] = Parent; + Ops[2] = ConstantInt::get(Int64, Offset); + return MDNode::get(Context, Ops); + } + + /// \brief Return metadata for a TBAA tag node with the given + /// base type, access type and offset relative to the base type. + MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, + uint64_t Offset) { + Type *Int64 = IntegerType::get(Context, 64); + Value *Ops[3] = { BaseType, AccessType, ConstantInt::get(Int64, Offset) }; + return MDNode::get(Context, Ops); + } + }; } // end namespace llvm diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 4460aa435b..cb500ffe7c 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -20,6 +20,7 @@ #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Metadata.h" +#include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -584,6 +585,16 @@ inline raw_ostream &operator<<(raw_ostream &O, const Module &M) { return O; } +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Module, LLVMModuleRef) + +/* LLVMModuleProviderRef exists for historical reasons, but now just holds a + * Module. + */ +inline Module *unwrap(LLVMModuleProviderRef MP) { + return reinterpret_cast<Module*>(MP); +} + } // End llvm namespace #endif diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index d89ae243f5..1bf8789d30 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -17,8 +17,10 @@ #include "llvm/ADT/APFloat.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm-c/Core.h" namespace llvm { @@ -467,6 +469,19 @@ template <> struct GraphTraits<const Type*> { } }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_ISA_CONVERSION_FUNCTIONS(Type, LLVMTypeRef) + +/* Specialized opaque type conversions. + */ +inline Type **unwrap(LLVMTypeRef* Tys) { + return reinterpret_cast<Type**>(Tys); +} + +inline LLVMTypeRef *wrap(Type **Tys) { + return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys)); +} + } // End llvm namespace #endif diff --git a/include/llvm/IR/Use.h b/include/llvm/IR/Use.h index 33a69c4686..efd8b48a0e 100644 --- a/include/llvm/IR/Use.h +++ b/include/llvm/IR/Use.h @@ -26,7 +26,9 @@ #define LLVM_IR_USE_H #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" +#include "llvm-c/Core.h" #include <cstddef> #include <iterator> @@ -149,14 +151,14 @@ private: // casting operators. template<> struct simplify_type<Use> { typedef Value* SimpleType; - static SimpleType getSimplifiedValue(const Use &Val) { - return static_cast<SimpleType>(Val.get()); + static SimpleType getSimplifiedValue(Use &Val) { + return Val.get(); } }; template<> struct simplify_type<const Use> { - typedef Value* SimpleType; + typedef /*const*/ Value* SimpleType; static SimpleType getSimplifiedValue(const Use &Val) { - return static_cast<SimpleType>(Val.get()); + return Val.get(); } }; @@ -214,6 +216,9 @@ public: unsigned getOperandNo() const; }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Use, LLVMUseRef) + } // End llvm namespace #endif diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index a4d0a5d7df..505bdeb178 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -183,27 +183,17 @@ public: template<> struct simplify_type<User::op_iterator> { typedef Value* SimpleType; - - static SimpleType getSimplifiedValue(const User::op_iterator &Val) { - return static_cast<SimpleType>(Val->get()); + static SimpleType getSimplifiedValue(User::op_iterator &Val) { + return Val->get(); } }; - -template<> struct simplify_type<const User::op_iterator> - : public simplify_type<User::op_iterator> {}; - template<> struct simplify_type<User::const_op_iterator> { - typedef Value* SimpleType; - - static SimpleType getSimplifiedValue(const User::const_op_iterator &Val) { - return static_cast<SimpleType>(Val->get()); + typedef /*const*/ Value* SimpleType; + static SimpleType getSimplifiedValue(User::const_op_iterator &Val) { + return Val->get(); } }; -template<> struct simplify_type<const User::const_op_iterator> - : public simplify_type<User::const_op_iterator> {}; - - // value_use_iterator::getOperandNo - Requires the definition of the User class. template<typename UserTy> unsigned value_use_iterator<UserTy>::getOperandNo() const { diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index a4f78627a8..fb61a2ac70 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -16,7 +16,9 @@ #include "llvm/IR/Use.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" +#include "llvm-c/Core.h" namespace llvm { @@ -406,6 +408,29 @@ public: enum { NumLowBitsAvailable = 2 }; }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_ISA_CONVERSION_FUNCTIONS(Value, LLVMValueRef) + +/* Specialized opaque value conversions. + */ +inline Value **unwrap(LLVMValueRef *Vals) { + return reinterpret_cast<Value**>(Vals); +} + +template<typename T> +inline T **unwrap(LLVMValueRef *Vals, unsigned Length) { +#ifdef DEBUG + for (LLVMValueRef *I = Vals, *E = Vals + Length; I != E; ++I) + cast<T>(*I); +#endif + (void)Length; + return reinterpret_cast<T**>(Vals); +} + +inline LLVMValueRef *wrap(const Value **Vals) { + return reinterpret_cast<LLVMValueRef*>(const_cast<Value**>(Vals)); +} + } // End llvm namespace #endif diff --git a/include/llvm/IRReader/IRReader.h b/include/llvm/IRReader/IRReader.h new file mode 100644 index 0000000000..e2ae5f7164 --- /dev/null +++ b/include/llvm/IRReader/IRReader.h @@ -0,0 +1,55 @@ +//===---- llvm/IRReader/IRReader.h - Reader for LLVM IR files ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines functions for reading LLVM IR. They support both +// Bitcode and Assembly, automatically detecting the input format. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IRREADER_IRREADER_H +#define LLVM_IRREADER_IRREADER_H + +#include <string> + +namespace llvm { + +class Module; +class MemoryBuffer; +class SMDiagnostic; +class LLVMContext; + +/// If the given MemoryBuffer holds a bitcode image, return a Module for it +/// which does lazy deserialization of function bodies. Otherwise, attempt to +/// parse it as LLVM Assembly and return a fully populated Module. This +/// function *always* takes ownership of the given MemoryBuffer. +Module *getLazyIRModule(MemoryBuffer *Buffer, SMDiagnostic &Err, + LLVMContext &Context); + +/// If the given file holds a bitcode image, return a Module +/// for it which does lazy deserialization of function bodies. Otherwise, +/// attempt to parse it as LLVM Assembly and return a fully populated +/// Module. +Module *getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err, + LLVMContext &Context); + +/// If the given MemoryBuffer holds a bitcode image, return a Module +/// for it. Otherwise, attempt to parse it as LLVM Assembly and return +/// a Module for it. This function *always* takes ownership of the given +/// MemoryBuffer. +Module *ParseIR(MemoryBuffer *Buffer, SMDiagnostic &Err, LLVMContext &Context); + +/// If the given file holds a bitcode image, return a Module for it. +/// Otherwise, attempt to parse it as LLVM Assembly and return a Module +/// for it. +Module *ParseIRFile(const std::string &Filename, SMDiagnostic &Err, + LLVMContext &Context); + +} + +#endif diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index a6dbb0c7d2..5b2cd603c3 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -91,7 +91,6 @@ void initializeCFGViewerPass(PassRegistry&); void initializeCalculateSpillWeightsPass(PassRegistry&); void initializeCallGraphAnalysisGroup(PassRegistry&); void initializeCodeGenPreparePass(PassRegistry&); -void initializeCodePlacementOptPass(PassRegistry&); void initializeConstantMergePass(PassRegistry&); void initializeConstantPropagationPass(PassRegistry&); void initializeMachineCopyPropagationPass(PassRegistry&); @@ -272,6 +271,7 @@ void initializeInstSimplifierPass(PassRegistry&); void initializeUnpackMachineBundlesPass(PassRegistry&); void initializeFinalizeMachineBundlesPass(PassRegistry&); void initializeLoopVectorizePass(PassRegistry&); +void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); } diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 1f017e471d..ca1c13924e 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -161,6 +161,7 @@ namespace { (void) llvm::createMemDepPrinter(); (void) llvm::createInstructionSimplifierPass(); (void) llvm::createLoopVectorizePass(); + (void) llvm::createSLPVectorizerPass(); (void) llvm::createBBVectorizePass(); (void)new llvm::IntervalPartition(); diff --git a/include/llvm/Linker.h b/include/llvm/Linker.h index 8bf9efa8e2..679638427d 100644 --- a/include/llvm/Linker.h +++ b/include/llvm/Linker.h @@ -6,10 +6,6 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the interface to the module/file/archive linker. -// -//===----------------------------------------------------------------------===// #ifndef LLVM_LINKER_H #define LLVM_LINKER_H @@ -19,7 +15,6 @@ #include <vector> namespace llvm { - namespace sys { class Path; } class Module; class LLVMContext; @@ -31,8 +26,7 @@ class StringRef; /// In this case the Linker still retains ownership of the Module. If the /// releaseModule() method is used, the ownership of the Module is transferred /// to the caller and the Linker object is only suitable for destruction. -/// The Linker can link Modules from memory. It retains a set of search paths -/// in which to find any libraries presented to it. By default, the linker +/// The Linker can link Modules from memory. By default, the linker /// will generate error and warning messages to stderr but this capability can /// be turned off with the QuietWarnings and QuietErrors flags. It can also be /// instructed to verbosely print out the linking actions it is taking with @@ -96,16 +90,10 @@ class Linker { /// must arrange for its destruct. After this method is called, the Linker /// terminates the linking session for the returned Module. It will no /// longer utilize the returned Module but instead resets itself for - /// subsequent linking as if the constructor had been called. The Linker's - /// LibPaths and flags to be reset, and memory will be released. + /// subsequent linking as if the constructor had been called. /// @brief Release the linked/composite module. Module* releaseModule(); - /// This method gets the list of libraries that form the path that the - /// Linker will search when it is presented with a library name. - /// @brief Get the Linkers library path - const std::vector<sys::Path>& getLibPaths() const { return LibPaths; } - /// This method returns an error string suitable for printing to the user. /// The return value will be empty unless an error occurred in one of the /// LinkIn* methods. In those cases, the LinkIn* methods will have returned @@ -120,31 +108,6 @@ class Linker { /// @name Mutators /// @{ public: - /// Add a path to the list of paths that the Linker will search. The Linker - /// accumulates the set of libraries added - /// library paths for the target platform. The standard libraries will - /// always be searched last. The added libraries will be searched in the - /// order added. - /// @brief Add a path. - void addPath(const sys::Path& path); - - /// Add a set of paths to the list of paths that the linker will search. The - /// Linker accumulates the set of libraries added. The \p paths will be - /// added to the end of the Linker's list. Order will be retained. - /// @brief Add a set of paths. - void addPaths(const std::vector<std::string>& paths); - - /// This method augments the Linker's list of library paths with the system - /// paths of the host operating system, include LLVM_LIB_SEARCH_PATH. - /// @brief Add the system paths. - void addSystemPaths(); - - /// Control optional linker behavior by setting a group of flags. The flags - /// are defined in the ControlFlags enumeration. - /// @see ControlFlags - /// @brief Set control flags. - void setFlags(unsigned flags) { Flags = flags; } - /// This method links the \p Src module into the Linker's Composite module /// by calling LinkModules. /// @see LinkModules @@ -185,7 +148,6 @@ class Linker { private: LLVMContext& Context; ///< The context for global information Module* Composite; ///< The composite module linked together - std::vector<sys::Path> LibPaths; ///< The library search paths unsigned Flags; ///< Flags to control optional behavior. std::string Error; ///< Text of error that occurred. std::string ProgramName; ///< Name of the program being linked diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 28256b3677..d020de3004 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -217,6 +217,8 @@ namespace llvm { /// convention. bool HasMicrosoftFastStdCallMangling; // Defaults to false. + bool NeedsDwarfSectionOffsetDirective; + //===--- Alignment Information ----------------------------------------===// /// AlignDirective - The directive used to emit round up to an alignment @@ -320,9 +322,6 @@ namespace llvm { /// encode inline subroutine information. bool DwarfUsesInlineInfoSection; // Defaults to false. - /// DwarfSectionOffsetDirective - Special section offset directive. - const char* DwarfSectionOffsetDirective; // Defaults to NULL - /// DwarfUsesRelocationsAcrossSections - True if Dwarf2 output generally /// uses relocations for references to other .debug_* sections. bool DwarfUsesRelocationsAcrossSections; @@ -412,6 +411,10 @@ namespace llvm { return HasMicrosoftFastStdCallMangling; } + bool needsDwarfSectionOffsetDirective() const { + return NeedsDwarfSectionOffsetDirective; + } + // Accessors. // bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } @@ -557,9 +560,6 @@ namespace llvm { bool doesDwarfUseInlineInfoSection() const { return DwarfUsesInlineInfoSection; } - const char *getDwarfSectionOffsetDirective() const { - return DwarfSectionOffsetDirective; - } bool doesDwarfUseRelocationsAcrossSections() const { return DwarfUsesRelocationsAcrossSections; } diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 6aeb8b8c3a..2c8c602b38 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -459,7 +459,7 @@ class MCLEBFragment : public MCFragment { SmallString<8> Contents; public: - MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD) + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSectionData *SD = 0) : MCFragment(FT_LEB, SD), Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } @@ -495,7 +495,7 @@ class MCDwarfLineAddrFragment : public MCFragment { public: MCDwarfLineAddrFragment(int64_t _LineDelta, const MCExpr &_AddrDelta, - MCSectionData *SD) + MCSectionData *SD = 0) : MCFragment(FT_Dwarf, SD), LineDelta(_LineDelta), AddrDelta(&_AddrDelta) { Contents.push_back(0); } @@ -526,7 +526,7 @@ class MCDwarfCallFrameFragment : public MCFragment { SmallString<8> Contents; public: - MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD) + MCDwarfCallFrameFragment(const MCExpr &_AddrDelta, MCSectionData *SD = 0) : MCFragment(FT_DwarfFrame, SD), AddrDelta(&_AddrDelta) { Contents.push_back(0); } @@ -598,6 +598,10 @@ private: /// it. unsigned HasInstructions : 1; + /// Mapping from subsection number to insertion point for subsection numbers + /// below that number. + SmallVector<std::pair<unsigned, MCFragment *>, 1> SubsectionFragmentMap; + /// @} public: @@ -641,6 +645,8 @@ public: bool empty() const { return Fragments.empty(); } + iterator getSubsectionInsertionPoint(unsigned Subsection); + bool isBundleLocked() const { return BundleLockState != NotBundleLocked; } diff --git a/include/llvm/MC/MCAtom.h b/include/llvm/MC/MCAtom.h index 682cf7cd76..ae5bf0bc20 100644 --- a/include/llvm/MC/MCAtom.h +++ b/include/llvm/MC/MCAtom.h @@ -46,8 +46,8 @@ class MCAtom { : Type(T), Parent(P), Begin(B), End(E) { } public: - bool isTextAtom() { return Type == TextAtom; } - bool isDataAtom() { return Type == DataAtom; } + bool isTextAtom() const { return Type == TextAtom; } + bool isDataAtom() const { return Type == DataAtom; } void addInst(const MCInst &I, uint64_t Address, unsigned Size); void addData(const MCData &D); diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index 6fb2d22be2..55c05b0363 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -50,7 +50,8 @@ public: virtual void InitSections(); virtual void InitToTextSection(); - virtual void ChangeSection(const MCSection *Section); + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection); virtual void EmitLabel(MCSymbol *Symbol); virtual void EmitDebugLabel(MCSymbol *Symbol); virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index b5bfed18ec..a2c5bd3f76 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -216,7 +216,9 @@ public: VK_Mips_GOT_HI16, VK_Mips_GOT_LO16, VK_Mips_CALL_HI16, - VK_Mips_CALL_LO16 + VK_Mips_CALL_LO16, + + VK_COFF_IMGREL32 // symbol@imgrel (image-relative) }; private: diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index e91c6a2e8e..4766815da5 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -171,7 +171,7 @@ public: void clear() { Operands.clear(); } size_t size() { return Operands.size(); } - typedef SmallVector<MCOperand, 8>::iterator iterator; + typedef SmallVectorImpl<MCOperand>::iterator iterator; iterator begin() { return Operands.begin(); } iterator end() { return Operands.end(); } iterator insert(iterator I, const MCOperand &Op) { diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index c8d748420e..a5853b602c 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -46,10 +46,15 @@ protected: unsigned FDEEncoding; unsigned FDECFIEncoding; unsigned TTypeEncoding; - // Section flags for eh_frame + + /// Section flags for eh_frame unsigned EHSectionType; unsigned EHSectionFlags; + /// CompactUnwindDwarfEHFrameOnly - Compact unwind encoding indicating that we + /// should emit only an EH frame. + unsigned CompactUnwindDwarfEHFrameOnly; + /// TextSection - Section directive for standard text. /// const MCSection *TextSection; @@ -201,6 +206,10 @@ public: } unsigned getTTypeEncoding() const { return TTypeEncoding; } + unsigned getCompactUnwindDwarfEHFrameOnly() const { + return CompactUnwindDwarfEHFrameOnly; + } + const MCSection *getTextSection() const { return TextSection; } const MCSection *getDataSection() const { return DataSection; } const MCSection *getBSSSection() const { return BSSSection; } diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index f06c49ff08..22a2839869 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -10,6 +10,7 @@ #ifndef LLVM_MC_MCOBJECTSTREAMER_H #define LLVM_MC_MCOBJECTSTREAMER_H +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCStreamer.h" namespace llvm { @@ -32,6 +33,7 @@ class raw_ostream; class MCObjectStreamer : public MCStreamer { MCAssembler *Assembler; MCSectionData *CurSectionData; + MCSectionData::iterator CurInsertionPoint; virtual void EmitInstToData(const MCInst &Inst) = 0; virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); @@ -56,6 +58,11 @@ protected: MCFragment *getCurrentFragment() const; + void insert(MCFragment *F) const { + CurSectionData->getFragmentList().insert(CurInsertionPoint, F); + F->setParent(CurSectionData); + } + /// Get a data fragment to write into, creating a new one if the current /// fragment is not a data fragment. MCDataFragment *getOrCreateDataFragment() const; @@ -76,7 +83,8 @@ public: virtual void EmitULEB128Value(const MCExpr *Value); virtual void EmitSLEB128Value(const MCExpr *Value); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - virtual void ChangeSection(const MCSection *Section); + virtual void ChangeSection(const MCSection *Section, + const MCExpr *Subsection); virtual void EmitInstruction(const MCInst &Inst); /// \brief Emit an instruction to a special fragment, because this instruction diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index d7e3902ac4..4ca5b9ae9e 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -33,15 +33,30 @@ class Twine; /// MCAsmParserSemaCallback - Generic Sema callback for assembly parser. class MCAsmParserSemaCallback { public: + typedef struct { + void *OpDecl; + bool IsVarDecl; + unsigned Length, Size, Type; + + void clear() { + OpDecl = 0; + IsVarDecl = false; + Length = 1; + Size = 0; + Type = 0; + } + } InlineAsmIdentifierInfo; + virtual ~MCAsmParserSemaCallback(); - virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc, - unsigned &Length, unsigned &Size, - unsigned &Type, bool &IsVarDecl) = 0; + virtual void *LookupInlineAsmIdentifier(StringRef &LineBuf, + InlineAsmIdentifierInfo &Info) = 0; virtual bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset) = 0; }; +typedef MCAsmParserSemaCallback::InlineAsmIdentifierInfo + InlineAsmIdentifierInfo; /// MCAsmParser - Generic assembler parser interface, for use by target specific /// assembly parsers. @@ -151,6 +166,13 @@ public: virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; bool parseExpression(const MCExpr *&Res); + /// parsePrimaryExpr - Parse a primary expression. + /// + /// @param Res - The value of the expression. The result is undefined + /// on error. + /// @result - False on success. + virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0; + /// parseParenExpression - Parse an arbitrary expression, assuming that an /// initial '(' has already been consumed. /// diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index c78cd976f2..818fbbd6c6 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -37,15 +37,8 @@ public: void setMCOperandNum (unsigned OpNum) { MCOperandNum = OpNum; } unsigned getMCOperandNum() { return MCOperandNum; } - unsigned getNameLen() { - assert (getStartLoc().isValid() && "Invalid StartLoc!"); - assert (getEndLoc().isValid() && "Invalid EndLoc!"); - return getEndLoc().getPointer() - getStartLoc().getPointer(); - } - - StringRef getName() { - return StringRef(getStartLoc().getPointer(), getNameLen()); - } + virtual StringRef getSymName() { return StringRef(); } + virtual void *getOpDecl() { return 0; } /// isToken - Is this a token operand? virtual bool isToken() const = 0; @@ -57,19 +50,12 @@ public: /// isMem - Is this a memory operand? virtual bool isMem() const = 0; - virtual unsigned getMemSize() const { return 0; } /// getStartLoc - Get the location of the first token of this operand. virtual SMLoc getStartLoc() const = 0; /// getEndLoc - Get the location of the last token of this operand. virtual SMLoc getEndLoc() const = 0; - /// needAsmRewrite - AsmRewrites happen in both the target-independent and - /// target-dependent parsers. The target-independent parser calls this - /// function to determine if the target-dependent parser has already taken - /// care of the rewrites. Only valid when parsing MS-style inline assembly. - virtual bool needAsmRewrite() const { return true; } - /// needAddressOf - Do we need to emit code to get the address of the /// variable/label? Only valid when parsing MS-style inline assembly. virtual bool needAddressOf() const { return false; } @@ -82,10 +68,6 @@ public: /// getOffsetOfLoc - Get the location of the offset operator. virtual SMLoc getOffsetOfLoc() const { return SMLoc(); } - /// needSizeDirective - Do we need to emit a sizing directive for this - /// operand? Only valid when parsing MS-style inline assembly. - virtual bool needSizeDirective() const { return false; } - /// print - Print a debug representation of the operand to the given stream. virtual void print(raw_ostream &OS) const = 0; /// dump - Print to the debug stream. diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index 5d6cac2b98..944bfcbf02 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -20,6 +20,7 @@ namespace llvm { class MCAsmInfo; + class MCExpr; class raw_ostream; /// MCSection - Instances of this class represent a uniqued identifier for a @@ -49,7 +50,8 @@ namespace llvm { SectionVariant getVariant() const { return Variant; } virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const = 0; + raw_ostream &OS, + const MCExpr *Subsection) const = 0; // Convenience routines to get label names for the beginning/end of a // section. diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 07c47144cb..50e33a5b04 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -60,7 +60,8 @@ namespace llvm { int getSelection () const { return Selection; } virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const; + raw_ostream &OS, + const MCExpr *Subsection) const; virtual bool UseCodeAlign() const; virtual bool isVirtualSection() const; diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 4b8b849c79..59799158ad 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -70,7 +70,8 @@ public: const MCSymbol *getGroup() const { return Group; } void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const; + raw_ostream &OS, + const MCExpr *Subsection) const; virtual bool UseCodeAlign() const; virtual bool isVirtualSection() const; diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index 898f571490..b68bd85968 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -175,7 +175,8 @@ public: unsigned &StubSize); // Out. virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const; + raw_ostream &OS, + const MCExpr *Subsection) const; virtual bool UseCodeAlign() const; virtual bool isVirtualSection() const; diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index a069a2b0ca..2cab481c3d 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -37,6 +37,8 @@ namespace llvm { class raw_ostream; class formatted_raw_ostream; + typedef std::pair<const MCSection *, const MCExpr *> MCSectionSubPair; + /// MCStreamer - Streaming machine code generation interface. This interface /// is intended to provide a programatic interface that is very similar to the /// level that an assembler .s file provides. It has callbacks to emit bytes, @@ -86,8 +88,7 @@ namespace llvm { /// SectionStack - This is stack of current and previous section /// values saved by PushSection. - SmallVector<std::pair<const MCSection *, - const MCSection *>, 4> SectionStack; + SmallVector<std::pair<MCSectionSubPair, MCSectionSubPair>, 4> SectionStack; bool AutoInitSections; @@ -174,25 +175,25 @@ namespace llvm { /// getCurrentSection - Return the current section that the streamer is /// emitting code to. - const MCSection *getCurrentSection() const { + MCSectionSubPair getCurrentSection() const { if (!SectionStack.empty()) return SectionStack.back().first; - return NULL; + return MCSectionSubPair(); } /// getPreviousSection - Return the previous section that the streamer is /// emitting code to. - const MCSection *getPreviousSection() const { + MCSectionSubPair getPreviousSection() const { if (!SectionStack.empty()) return SectionStack.back().second; - return NULL; + return MCSectionSubPair(); } /// ChangeSection - Update streamer for a new active section. /// /// This is called by PopSection and SwitchSection, if the current /// section changes. - virtual void ChangeSection(const MCSection *) = 0; + virtual void ChangeSection(const MCSection *, const MCExpr *) = 0; /// pushSection - Save the current and previous section on the /// section stack. @@ -208,11 +209,19 @@ namespace llvm { bool PopSection() { if (SectionStack.size() <= 1) return false; - const MCSection *oldSection = SectionStack.pop_back_val().first; - const MCSection *curSection = SectionStack.back().first; + MCSectionSubPair oldSection = SectionStack.pop_back_val().first; + MCSectionSubPair curSection = SectionStack.back().first; if (oldSection != curSection) - ChangeSection(curSection); + ChangeSection(curSection.first, curSection.second); + return true; + } + + bool SubSection(const MCExpr *Subsection) { + if (SectionStack.empty()) + return false; + + SwitchSection(SectionStack.back().first.first, Subsection); return true; } @@ -220,25 +229,26 @@ namespace llvm { /// @p Section. This is required to update CurSection. /// /// This corresponds to assembler directives like .section, .text, etc. - void SwitchSection(const MCSection *Section) { + void SwitchSection(const MCSection *Section, const MCExpr *Subsection = 0) { assert(Section && "Cannot switch to a null section!"); - const MCSection *curSection = SectionStack.back().first; + MCSectionSubPair curSection = SectionStack.back().first; SectionStack.back().second = curSection; - if (Section != curSection) { - SectionStack.back().first = Section; - ChangeSection(Section); + if (MCSectionSubPair(Section, Subsection) != curSection) { + SectionStack.back().first = MCSectionSubPair(Section, Subsection); + ChangeSection(Section, Subsection); } } /// SwitchSectionNoChange - Set the current section where code is being /// emitted to @p Section. This is required to update CurSection. This /// version does not call ChangeSection. - void SwitchSectionNoChange(const MCSection *Section) { + void SwitchSectionNoChange(const MCSection *Section, + const MCExpr *Subsection = 0) { assert(Section && "Cannot switch to a null section!"); - const MCSection *curSection = SectionStack.back().first; + MCSectionSubPair curSection = SectionStack.back().first; SectionStack.back().second = curSection; - if (Section != curSection) - SectionStack.back().first = Section; + if (MCSectionSubPair(Section, Subsection) != curSection) + SectionStack.back().first = MCSectionSubPair(Section, Subsection); } /// Initialize the streamer. diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 4c5b176125..6e878df3cb 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -22,6 +22,7 @@ class MCInst; template <typename T> class SmallVectorImpl; enum AsmRewriteKind { + AOK_Delete = 0, // Rewrite should be ignored. AOK_Align, // Rewrite align as .align. AOK_DotOperator, // Rewrite a dot operator expression as an immediate. // E.g., [eax].foo.bar -> [eax].8 @@ -34,6 +35,19 @@ enum AsmRewriteKind { AOK_Skip // Skip emission (e.g., offset/type operators). }; +const char AsmRewritePrecedence [] = { + 0, // AOK_Delete + 1, // AOK_Align + 1, // AOK_DotOperator + 1, // AOK_Emit + 3, // AOK_Imm + 3, // AOK_ImmPrefix + 2, // AOK_Input + 2, // AOK_Output + 4, // AOK_SizeDirective + 1 // AOK_Skip +}; + struct AsmRewrite { AsmRewriteKind Kind; SMLoc Loc; diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index 11df5749d4..f13e7d5480 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -11,7 +11,9 @@ #define LLVM_MC_MCWINCOFFOBJECTWRITER_H namespace llvm { + class MCFixup; class MCObjectWriter; + class MCValue; class raw_ostream; class MCWinCOFFObjectTargetWriter { @@ -24,7 +26,9 @@ namespace llvm { virtual ~MCWinCOFFObjectTargetWriter() {} unsigned getMachine() const { return Machine; } - virtual unsigned getRelocType(unsigned FixupKind) const = 0; + virtual unsigned getRelocType(const MCValue &Target, + const MCFixup &Fixup, + bool IsCrossSection) const = 0; }; /// \brief Construct a new Win COFF writer instance. diff --git a/include/llvm/MC/MachineLocation.h b/include/llvm/MC/MachineLocation.h index 5caad337f8..83c8b72ee4 100644 --- a/include/llvm/MC/MachineLocation.h +++ b/include/llvm/MC/MachineLocation.h @@ -9,7 +9,7 @@ // The MachineLocation class is used to represent a simple location in a machine // frame. Locations will be one of two forms; a register or an address formed // from a base address plus an offset. Register indirection can be specified by -// using an offset of zero. +// explicitly passing an offset to the constructor. // // The MachineMove class is used to represent abstract move operations in the // prolog/epilog of a compiled function. A collection of these objects can be @@ -37,8 +37,10 @@ public: }; MachineLocation() : IsRegister(false), Register(0), Offset(0) {} + /// Create a direct register location. explicit MachineLocation(unsigned R) : IsRegister(true), Register(R), Offset(0) {} + /// Create a register-indirect location with an offset. MachineLocation(unsigned R, int O) : IsRegister(false), Register(R), Offset(O) {} @@ -48,17 +50,20 @@ public: } // Accessors + bool isIndirect() const { return !IsRegister; } bool isReg() const { return IsRegister; } unsigned getReg() const { return Register; } int getOffset() const { return Offset; } void setIsRegister(bool Is) { IsRegister = Is; } void setRegister(unsigned R) { Register = R; } void setOffset(int O) { Offset = O; } + /// Make this location a direct register location. void set(unsigned R) { IsRegister = true; Register = R; Offset = 0; } + /// Make this location a register-indirect+offset location. void set(unsigned R, int O) { IsRegister = false; Register = R; diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index 37ae03b45c..8862c8b762 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -62,10 +62,8 @@ struct SubtargetInfoKV { /// /// SubtargetFeatures - Manages the enabling and disabling of subtarget /// specific features. Features are encoded as a string of the form -/// "cpu,+attr1,+attr2,-attr3,...,+attrN" +/// "+attr1,+attr2,-attr3,...,+attrN" /// A comma separates each feature from the next (all lowercase.) -/// The first feature is always the CPU subtype (eg. pentiumm). If the CPU -/// value is "generic" then the CPU subtype should be generic for the target. /// Each of the remaining features is prefixed with + or - indicating whether /// that feature should be enabled or disabled contrary to the cpu /// specification. diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 8bbcd8b4d4..78fcf6feb8 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -41,11 +41,17 @@ protected: // Object and children. ID_StartObjects, ID_COFF, + ID_ELF32L, // ELF 32-bit, little endian ID_ELF32B, // ELF 32-bit, big endian ID_ELF64L, // ELF 64-bit, little endian ID_ELF64B, // ELF 64-bit, big endian - ID_MachO, + + ID_MachO32L, // MachO 32-bit, little endian + ID_MachO32B, // MachO 32-bit, big endian + ID_MachO64L, // MachO 64-bit, little endian + ID_MachO64B, // MachO 64-bit, big endian + ID_EndObjects }; @@ -56,6 +62,13 @@ protected: return is64Bits ? ID_ELF64B : ID_ELF32B; } + static unsigned int getMachOType(bool isLE, bool is64Bits) { + if (isLE) + return is64Bits ? ID_MachO64L : ID_MachO32L; + else + return is64Bits ? ID_MachO64B : ID_MachO32B; + } + public: virtual ~Binary(); @@ -79,7 +92,7 @@ public: } bool isMachO() const { - return TypeID == ID_MachO; + return TypeID >= ID_MachO32L && TypeID <= ID_MachO64B; } bool isCOFF() const { @@ -87,7 +100,8 @@ public: } bool isLittleEndian() const { - return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B); + return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || + TypeID == ID_MachO32B || TypeID == ID_MachO64B); } }; diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index d5ff6f9594..491a17eb94 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -83,9 +83,8 @@ template<class ELFT> struct ELFDataTypeTypedefHelper; /// ELF 32bit types. -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, false> > +template<endianness TargetEndianness, std::size_t MaxAlign> +struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, false> > : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { typedef uint32_t value_type; typedef support::detail::packed_endian_specific_integral @@ -97,9 +96,8 @@ struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, false> > }; /// ELF 64bit types. -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, true> > +template<endianness TargetEndianness, std::size_t MaxAlign> +struct ELFDataTypeTypedefHelper<ELFType<TargetEndianness, MaxAlign, true> > : ELFDataTypeTypedefHelperCommon<TargetEndianness, MaxAlign> { typedef uint64_t value_type; typedef support::detail::packed_endian_specific_integral @@ -111,27 +109,29 @@ struct ELFDataTypeTypedefHelper<ELFT<TargetEndianness, MaxAlign, true> > }; // I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(ELFT) \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Addr Elf_Addr; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Off Elf_Off; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Half Elf_Half; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Word Elf_Word; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Sword Elf_Sword; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Xword Elf_Xword; \ -typedef typename ELFDataTypeTypedefHelper <ELFT>::Elf_Sxword Elf_Sxword; - -// This is required to get template types into a macro :( -#define LLVM_ELF_COMMA , - - // Section header. +#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Addr Elf_Addr; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Off Elf_Off; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Half Elf_Half; \ +typedef typename ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Word Elf_Word; \ +typedef typename \ + ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Sword Elf_Sword; \ +typedef typename \ + ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Xword Elf_Xword; \ +typedef typename \ + ELFDataTypeTypedefHelper<ELFType<E,M,W> >::Elf_Sxword Elf_Sxword; + +#define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ + LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ + ELFT::Is64Bits) + +// Section header. template<class ELFT> struct Elf_Shdr_Base; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Shdr_Base<ELFT<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_flags; // Section flags (SHF_*) @@ -144,11 +144,9 @@ struct Elf_Shdr_Base<ELFT<TargetEndianness, MaxAlign, false> > { Elf_Word sh_entsize; // Size of records contained within the section }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Shdr_Base<ELFT<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Shdr_Base<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Xword sh_flags; // Section flags (SHF_*) @@ -177,11 +175,9 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base<ELFT> { template<class ELFT> struct Elf_Sym_Base; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Sym_Base<ELFT<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Word st_name; // Symbol name (index into string table) Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol @@ -190,11 +186,9 @@ struct Elf_Sym_Base<ELFT<TargetEndianness, MaxAlign, false> > { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Sym_Base<ELFT<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Sym_Base<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved @@ -222,7 +216,7 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> { /// (.gnu.version). This structure is identical for ELF32 and ELF64. template<class ELFT> struct Elf_Versym_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Half vs_index; // Version index with flags (e.g. VERSYM_HIDDEN) }; @@ -233,7 +227,7 @@ struct Elf_Verdaux_Impl; /// (.gnu.version_d). This structure is identical for ELF32 and ELF64. template<class ELFT> struct Elf_Verdef_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) typedef Elf_Verdaux_Impl<ELFT> Elf_Verdaux; Elf_Half vd_version; // Version of this structure (e.g. VER_DEF_CURRENT) Elf_Half vd_flags; // Bitwise flags (VER_DEF_*) @@ -253,7 +247,7 @@ struct Elf_Verdef_Impl { /// section (.gnu.version_d). This structure is identical for ELF32 and ELF64. template<class ELFT> struct Elf_Verdaux_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Word vda_name; // Version name (offset in string table) Elf_Word vda_next; // Offset to next Verdaux entry (in bytes) }; @@ -262,7 +256,7 @@ struct Elf_Verdaux_Impl { /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. template<class ELFT> struct Elf_Verneed_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Half vn_version; // Version of this structure (e.g. VER_NEED_CURRENT) Elf_Half vn_cnt; // Number of associated Vernaux entries Elf_Word vn_file; // Library name (string table offset) @@ -274,7 +268,7 @@ struct Elf_Verneed_Impl { /// section (.gnu.version_r). This structure is identical for ELF32 and ELF64. template<class ELFT> struct Elf_Vernaux_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Elf_Word vna_hash; // Hash of dependency name Elf_Half vna_flags; // Bitwise Flags (VER_FLAG_*) Elf_Half vna_other; // Version index, used in .gnu.version entries @@ -287,11 +281,9 @@ struct Elf_Vernaux_Impl { template<class ELFT> struct Elf_Dyn_Base; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Dyn_Base<ELFT<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Sword d_tag; union { Elf_Word d_val; @@ -299,11 +291,9 @@ struct Elf_Dyn_Base<ELFT<TargetEndianness, MaxAlign, false> > { } d_un; }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Dyn_Base<ELFT<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Dyn_Base<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -325,90 +315,129 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base<ELFT> { template<class ELFT, bool isRela> struct Elf_Rel_Base; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, false> { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { + r_info = R; + } }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, false> { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply + + uint64_t getRInfo(bool isMips64EL) const { + uint64_t t = r_info; + if (!isMips64EL) + return t; + // Mip64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little ending 32 bit number followed + // by a 32 bit big endian number. + return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | + ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); + return r_info; + } + void setRInfo(uint64_t R) { + // FIXME: Add mips64el support. + r_info = R; + } }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, true> { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply Elf_Sword r_addend; // Compute value for relocatable field by adding this + + uint32_t getRInfo(bool isMips64EL) const { + assert(!isMips64EL); + return r_info; + } + void setRInfo(uint32_t R) { + r_info = R; + } }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, true> { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, true> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Xword r_info; // Symbol table index and type of relocation to apply Elf_Sxword r_addend; // Compute value for relocatable field by adding this. + + uint64_t getRInfo(bool isMips64EL) const { + // Mip64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little ending 32 bit number followed + // by a 32 bit big endian number. + uint64_t t = r_info; + if (!isMips64EL) + return t; + return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | + ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); + } + void setRInfo(uint64_t R) { + // FIXME: Add mips64el support. + r_info = R; + } }; template<class ELFT, bool isRela> struct Elf_Rel_Impl; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign, bool isRela> -struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, true>, isRela> - : Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela> { - using Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, true>, isRela>::r_info; - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign, bool isRela> +struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, true>, isRela> + : Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, true>, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: - uint32_t getSymbol() const { return (uint32_t) (r_info >> 32); } - uint32_t getType() const { - return (uint32_t) (r_info & 0xffffffffL); + uint32_t getSymbol(bool isMips64EL) const { + return (uint32_t) (this->getRInfo(isMips64EL) >> 32); + } + uint32_t getType(bool isMips64EL) const { + return (uint32_t) (this->getRInfo(isMips64EL) & 0xffffffffL); } void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } void setType(uint32_t t) { setSymbolAndType(getSymbol(), t); } void setSymbolAndType(uint32_t s, uint32_t t) { - r_info = ((uint64_t)s << 32) + (t&0xffffffffL); + this->setRInfo(((uint64_t)s << 32) + (t&0xffffffffL)); } }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign, bool isRela> -struct Elf_Rel_Impl<ELFT<TargetEndianness, MaxAlign, false>, isRela> - : Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela> { - using Elf_Rel_Base<ELFT<TargetEndianness, MaxAlign, false>, isRela>::r_info; - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign, bool isRela> +struct Elf_Rel_Impl<ELFType<TargetEndianness, MaxAlign, false>, isRela> + : Elf_Rel_Base<ELFType<TargetEndianness, MaxAlign, false>, isRela> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // and ELF32_R_INFO macros defined in the ELF specification: - uint32_t getSymbol() const { return (r_info >> 8); } - unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } + uint32_t getSymbol(bool isMips64EL) const { + return this->getRInfo(isMips64EL) >> 8; + } + unsigned char getType(bool isMips64EL) const { + return (unsigned char) (this->getRInfo(isMips64EL) & 0x0ff); + } void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); } void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } void setSymbolAndType(uint32_t s, unsigned char t) { - r_info = (s << 8) + t; + this->setRInfo((s << 8) + t); } }; template<class ELFT> struct Elf_Ehdr_Impl { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes Elf_Half e_type; // Type of file (see ET_*) Elf_Half e_machine; // Required architecture for this file (see EM_*) @@ -434,11 +463,9 @@ struct Elf_Ehdr_Impl { template<class ELFT> struct Elf_Phdr_Impl; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, false> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA false>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, false> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) Elf_Word p_type; // Type of segment Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Addr p_vaddr; // Virtual Address of beginning of segment @@ -449,11 +476,9 @@ struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, false> > { Elf_Word p_align; // Segment alignment constraint }; -template<template<endianness, std::size_t, bool> class ELFT, - endianness TargetEndianness, std::size_t MaxAlign> -struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, true> > { - LLVM_ELF_IMPORT_TYPES(ELFT<TargetEndianness LLVM_ELF_COMMA - MaxAlign LLVM_ELF_COMMA true>) +template<endianness TargetEndianness, std::size_t MaxAlign> +struct Elf_Phdr_Impl<ELFType<TargetEndianness, MaxAlign, true> > { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) Elf_Word p_type; // Type of segment Elf_Word p_flags; // Segment flags Elf_Off p_offset; // FileOffset where segment is located, in bytes @@ -466,7 +491,7 @@ struct Elf_Phdr_Impl<ELFT<TargetEndianness, MaxAlign, true> > { template<class ELFT> class ELFObjectFile : public ObjectFile { - LLVM_ELF_IMPORT_TYPES(ELFT) + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) public: /// \brief Iterate over constant sized entities. @@ -584,6 +609,8 @@ private: mutable const char *dt_soname; private: + uint64_t getROffset(DataRefImpl Rel) const; + // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. class VersionMapEntry : public PointerIntPair<const void*, 1> { @@ -640,6 +667,7 @@ public: protected: const Elf_Sym *getSymbol(DataRefImpl Symb) const; // FIXME: Should be private? void validateSymbol(DataRefImpl Symb) const; + StringRef getRelocationTypeName(uint32_t Type) const; public: error_code getSymbolName(const Elf_Shdr *section, @@ -656,6 +684,7 @@ protected: virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; @@ -705,6 +734,13 @@ protected: public: ELFObjectFile(MemoryBuffer *Object, error_code &ec); + + bool isMips64EL() const { + return Header->e_machine == ELF::EM_MIPS && + Header->getFileClass() == ELF::ELFCLASS64 && + Header->getDataEncoding() == ELF::ELFDATA2LSB; + } + virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; @@ -792,6 +828,7 @@ public: uint64_t getNumSections() const; uint64_t getStringTableIndex() const; ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; + const Elf_Ehdr *getElfHeader() const; const Elf_Shdr *getSection(const Elf_Sym *symb) const; const Elf_Shdr *getElfSection(section_iterator &It) const; const Elf_Sym *getElfSymbol(symbol_iterator &It) const; @@ -971,6 +1008,12 @@ ELFObjectFile<ELFT>::getSection(const Elf_Sym *symb) const { } template<class ELFT> +const typename ELFObjectFile<ELFT>::Elf_Ehdr * +ELFObjectFile<ELFT>::getElfHeader() const { + return Header; +} + +template<class ELFT> const typename ELFObjectFile<ELFT>::Elf_Shdr * ELFObjectFile<ELFT>::getElfSection(section_iterator &It) const { llvm::object::DataRefImpl ShdrRef = It->getRawDataRefImpl(); @@ -1060,6 +1103,11 @@ error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, IsRelocatable = true; } Result = symb->st_value; + + // Clear the ARM/Thumb indicator flag. + if (Header->e_machine == ELF::EM_ARM) + Result &= ~1; + if (IsRelocatable && Section != 0) Result += Section->sh_addr; return object_error::success; @@ -1070,6 +1118,21 @@ error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb, } template<class ELFT> +error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const { + uint32_t flags; + getSymbolFlags(Symb, flags); + if (flags & SymbolRef::SF_Common) { + uint64_t Value; + getSymbolValue(Symb, Value); + Res = Value; + } else { + Res = 0; + } + return object_error::success; +} + +template<class ELFT> error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb, uint64_t &Result) const { validateSymbol(Symb); @@ -1375,8 +1438,16 @@ template<class ELFT> error_code ELFObjectFile<ELFT>::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { - // FIXME: Unimplemented. - Result = false; + validateSymbol(Symb); + + const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); + const Elf_Sym *symb = getSymbol(Symb); + + unsigned shndx = symb->st_shndx; + bool Reserved = shndx >= ELF::SHN_LORESERVE + && shndx <= ELF::SHN_HIRESERVE; + + Result = !Reserved && (sec == getSection(symb->st_shndx)); return object_error::success; } @@ -1449,11 +1520,11 @@ error_code ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel, default : report_fatal_error("Invalid section type in Rel!"); case ELF::SHT_REL : { - symbolIdx = getRel(Rel)->getSymbol(); + symbolIdx = getRel(Rel)->getSymbol(isMips64EL()); break; } case ELF::SHT_RELA : { - symbolIdx = getRela(Rel)->getSymbol(); + symbolIdx = getRela(Rel)->getSymbol(isMips64EL()); break; } } @@ -1470,45 +1541,32 @@ error_code ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel, template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel, uint64_t &Result) const { - uint64_t offset; - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - offset = getRel(Rel)->r_offset; - break; - } - case ELF::SHT_RELA : { - offset = getRela(Rel)->r_offset; - break; - } - } - - Result = offset; + assert((Header->e_type == ELF::ET_EXEC || Header->e_type == ELF::ET_DYN) && + "Only executable and shared objects files have addresses"); + Result = getROffset(Rel); return object_error::success; } template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel, uint64_t &Result) const { - uint64_t offset; + assert(Header->e_type == ELF::ET_REL && + "Only relocatable object files have relocation offsets"); + Result = getROffset(Rel); + return object_error::success; +} + +template<class ELFT> +uint64_t ELFObjectFile<ELFT>::getROffset(DataRefImpl Rel) const { const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - offset = getRel(Rel)->r_offset; - break; - } - case ELF::SHT_RELA : { - offset = getRela(Rel)->r_offset; - break; - } + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: + return getRel(Rel)->r_offset; + case ELF::SHT_RELA: + return getRela(Rel)->r_offset; } - - Result = offset - sec->sh_addr; - return object_error::success; } template<class ELFT> @@ -1519,11 +1577,11 @@ error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, default : report_fatal_error("Invalid section type in Rel!"); case ELF::SHT_REL : { - Result = getRel(Rel)->getType(); + Result = getRel(Rel)->getType(isMips64EL()); break; } case ELF::SHT_RELA : { - Result = getRela(Rel)->getType(); + Result = getRela(Rel)->getType(isMips64EL()); break; } } @@ -1531,29 +1589,14 @@ error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel, } #define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ - case ELF::enum: res = #enum; break; + case ELF::enum: Res = #enum; break; template<class ELFT> -error_code ELFObjectFile<ELFT>::getRelocationTypeName( - DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - const Elf_Shdr *sec = getSection(Rel.w.b); - uint32_t type; - StringRef res; - switch (sec->sh_type) { - default : - return object_error::parse_failed; - case ELF::SHT_REL : { - type = getRel(Rel)->getType(); - break; - } - case ELF::SHT_RELA : { - type = getRela(Rel)->getType(); - break; - } - } +StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { + StringRef Res = "Unknown"; switch (Header->e_machine) { case ELF::EM_X86_64: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32); @@ -1581,17 +1624,22 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLTOFF64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC); - default: - res = "Unknown"; + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_IRELATIVE); + default: break; } break; case ELF::EM_386: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32); @@ -1632,12 +1680,68 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE); - default: - res = "Unknown"; + default: break; + } + break; + case ELF::EM_MIPS: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_26); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LITERAL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT5); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT6); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_DISP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_PAGE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_OFST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SUB); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_A); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_B); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_DELETE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SCN_DISP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_ADD_IMMEDIATE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PJUMP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_RELGOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JALR); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_LDM); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GOTTPREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NUM); + default: break; } break; case ELF::EM_AARCH64: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS32); @@ -1711,13 +1815,11 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_LD64_LO12_NC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADD_LO12_NC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_CALL); - - default: - res = "Unknown"; + default: break; } break; case ELF::EM_ARM: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PC24); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32); @@ -1849,12 +1951,11 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ME_TOO); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ32); - default: - res = "Unknown"; + default: break; } break; case ELF::EM_HEXAGON: - switch (type) { + switch (Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_NONE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL); @@ -1941,20 +2042,118 @@ error_code ELFObjectFile<ELFT>::getRelocationTypeName( LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32_6_X); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16_X); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_11_X); - default: - res = "Unknown"; + default: break; } break; - default: - res = "Unknown"; + case ELF::EM_PPC: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HA); + default: break; + } + break; + case ELF::EM_PPC64: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSGD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSLD); + default: break; + } + break; + default: break; } - Result.append(res.begin(), res.end()); - return object_error::success; + return Res; } #undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME template<class ELFT> +error_code ELFObjectFile<ELFT>::getRelocationTypeName( + DataRefImpl Rel, SmallVectorImpl<char> &Result) const { + const Elf_Shdr *sec = getSection(Rel.w.b); + uint32_t type; + switch (sec->sh_type) { + default : + return object_error::parse_failed; + case ELF::SHT_REL : { + type = getRel(Rel)->getType(isMips64EL()); + break; + } + case ELF::SHT_RELA : { + type = getRela(Rel)->getType(isMips64EL()); + break; + } + } + + if (!isMips64EL()) { + StringRef Name = getRelocationTypeName(type); + Result.append(Name.begin(), Name.end()); + } else { + uint8_t Type1 = (type >> 0) & 0xFF; + uint8_t Type2 = (type >> 8) & 0xFF; + uint8_t Type3 = (type >> 16) & 0xFF; + + // Concat all three relocation type names. + StringRef Name = getRelocationTypeName(Type1); + Result.append(Name.begin(), Name.end()); + + Name = getRelocationTypeName(Type2); + Result.append(1, '/'); + Result.append(Name.begin(), Name.end()); + + Name = getRelocationTypeName(Type3); + Result.append(1, '/'); + Result.append(Name.begin(), Name.end()); + } + + return object_error::success; +} + +template<class ELFT> error_code ELFObjectFile<ELFT>::getRelocationAdditionalInfo( DataRefImpl Rel, int64_t &Result) const { const Elf_Shdr *sec = getSection(Rel.w.b); @@ -1984,14 +2183,14 @@ error_code ELFObjectFile<ELFT>::getRelocationValueString( default: return object_error::parse_failed; case ELF::SHT_REL: { - type = getRel(Rel)->getType(); - symbol_index = getRel(Rel)->getSymbol(); + type = getRel(Rel)->getType(isMips64EL()); + symbol_index = getRel(Rel)->getSymbol(isMips64EL()); // TODO: Read implicit addend from section data. break; } case ELF::SHT_RELA: { - type = getRela(Rel)->getType(); - symbol_index = getRela(Rel)->getSymbol(); + type = getRela(Rel)->getType(isMips64EL()); + symbol_index = getRela(Rel)->getSymbol(isMips64EL()); addend = getRela(Rel)->r_addend; break; } @@ -2056,8 +2255,7 @@ ELFObjectFile<ELFT>::ELFObjectFile(MemoryBuffer *Object, error_code &ec) : ObjectFile(getELFType( static_cast<endianness>(ELFT::TargetEndianness) == support::little, ELFT::Is64Bits), - Object, - ec) + Object) , isDyldELFObject(false) , SectionHeaderTable(0) , dot_shstrtab_sec(0) @@ -2305,8 +2503,9 @@ ELFObjectFile<ELFT>::end_dynamic_table(bool NULLEnd) const { if (NULLEnd) { Elf_Dyn_iterator Start = begin_dynamic_table(); - for (; Start != Ret && Start->getTag() != ELF::DT_NULL; ++Start) - ; + while (Start != Ret && Start->getTag() != ELF::DT_NULL) + ++Start; + // Include the DT_NULL. if (Start != Ret) ++Start; @@ -2323,10 +2522,9 @@ StringRef ELFObjectFile<ELFT>::getLoadName() const { // Find the DT_SONAME entry Elf_Dyn_iterator it = begin_dynamic_table(); Elf_Dyn_iterator ie = end_dynamic_table(); - for (; it != ie; ++it) { - if (it->getTag() == ELF::DT_SONAME) - break; - } + while (it != ie && it->getTag() != ELF::DT_SONAME) + ++it; + if (it != ie) { if (dot_dynstr_sec == NULL) report_fatal_error("Dynamic string table is missing"); @@ -2343,10 +2541,8 @@ library_iterator ELFObjectFile<ELFT>::begin_libraries_needed() const { // Find the first DT_NEEDED entry Elf_Dyn_iterator i = begin_dynamic_table(); Elf_Dyn_iterator e = end_dynamic_table(); - for (; i != e; ++i) { - if (i->getTag() == ELF::DT_NEEDED) - break; - } + while (i != e && i->getTag() != ELF::DT_NEEDED) + ++i; DataRefImpl DRI; DRI.p = reinterpret_cast<uintptr_t>(i.get()); @@ -2361,11 +2557,10 @@ error_code ELFObjectFile<ELFT>::getLibraryNext(DataRefImpl Data, reinterpret_cast<const char *>(Data.p)); Elf_Dyn_iterator e = end_dynamic_table(); - // Skip the current dynamic table entry. - ++i; - - // Find the next DT_NEEDED entry. - for (; i != e && i->getTag() != ELF::DT_NEEDED; ++i); + // Skip the current dynamic table entry and find the next DT_NEEDED entry. + do + ++i; + while (i != e && i->getTag() != ELF::DT_NEEDED); DataRefImpl DRI; DRI.p = reinterpret_cast<uintptr_t>(i.get()); @@ -2706,6 +2901,21 @@ static inline error_code GetELFSymbolVersion(const ObjectFile *Obj, llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); } +/// This function returns the hash value for a symbol in the .dynsym section +/// Name of the API remains consistent as specified in the libelf +/// REF : http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash +static inline unsigned elf_hash(StringRef &symbolName) { + unsigned h = 0, g; + for (unsigned i = 0, j = symbolName.size(); i < j; i++) { + h = (h << 4) + symbolName[i]; + g = h & 0xf0000000L; + if (g != 0) + h ^= g >> 24; + h &= ~g; + } + return h; +} + } } diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index ed7aabd2c8..14cd4d767d 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -7,16 +7,17 @@ // //===----------------------------------------------------------------------===// // -// This file declares the MachOObjectFile class, which binds the MachOObject -// class to the generic ObjectFile wrapper. +// This file declares the MachOObjectFile class, which implement the ObjectFile +// interface for MachO files. // //===----------------------------------------------------------------------===// #ifndef LLVM_OBJECT_MACHO_H #define LLVM_OBJECT_MACHO_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Object/MachOObject.h" +#include "llvm/Object/MachOFormat.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" @@ -24,46 +25,26 @@ namespace llvm { namespace object { -typedef MachOObject::LoadCommandInfo LoadCommandInfo; - class MachOObjectFile : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec); - - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; - virtual section_iterator begin_sections() const; - virtual section_iterator end_sections() const; + struct LoadCommandInfo { + const char *Ptr; // Where in memory the load command is. + macho::LoadCommand C; // The command itself. + }; - virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; - virtual StringRef getLoadName() const; + MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, + error_code &ec); - // In a MachO file, sections have a segment name. This is used in the .o - // files. They have a single segment, but this field specifies which segment - // a section should be put in in the final object. - error_code getSectionFinalSegmentName(DataRefImpl Sec, StringRef &Res) const; - - MachOObject *getObject() { return MachOObj.get(); } - - static inline bool classof(const Binary *v) { - return v->isMachO(); - } - -protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const; virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; @@ -82,21 +63,17 @@ protected: virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S, + virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const; + virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const; + virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl<char> &Result) const; virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, @@ -108,28 +85,98 @@ protected: virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; -private: - OwningPtr<MachOObject> MachOObj; - mutable uint32_t RegisteredStringTable; - typedef SmallVector<DataRefImpl, 1> SectionList; - SectionList Sections; + // TODO: Would be useful to have an iterator based version + // of the load command interface too. + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; + + virtual symbol_iterator begin_dynamic_symbols() const; + virtual symbol_iterator end_dynamic_symbols() const; + + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; + + virtual library_iterator begin_libraries_needed() const; + virtual library_iterator end_libraries_needed() const; + + virtual uint8_t getBytesInAddress() const; + + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; + + virtual StringRef getLoadName() const; - void moveToNextSection(DataRefImpl &DRI) const; - void getSymbolTableEntry(DataRefImpl DRI, - InMemoryStruct<macho::SymbolTableEntry> &Res) const; - void getSymbol64TableEntry(DataRefImpl DRI, - InMemoryStruct<macho::Symbol64TableEntry> &Res) const; - void moveToNextSymbol(DataRefImpl &DRI) const; - void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const; - void getSection64(DataRefImpl DRI, - InMemoryStruct<macho::Section64> &Res) const; - void getRelocation(DataRefImpl Rel, - InMemoryStruct<macho::RelocationEntry> &Res) const; - std::size_t getSectionIndex(DataRefImpl Sec) const; - - void printRelocationTargetName(InMemoryStruct<macho::RelocationEntry>& RE, - raw_string_ostream &fmt) const; + relocation_iterator getSectionRelBegin(unsigned Index) const; + relocation_iterator getSectionRelEnd(unsigned Index) const; + + // In a MachO file, sections have a segment name. This is used in the .o + // files. They have a single segment, but this field specifies which segment + // a section should be put in in the final object. + StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; + + // Names are stored as 16 bytes. These returns the raw 16 bytes without + // interpreting them as a C string. + ArrayRef<char> getSectionRawName(DataRefImpl Sec) const; + ArrayRef<char> getSectionRawFinalSegmentName(DataRefImpl Sec) const; + + // MachO specific Info about relocations. + bool isRelocationScattered(const macho::RelocationEntry &RE) const; + unsigned getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const; + bool getPlainRelocationExternal(const macho::RelocationEntry &RE) const; + bool getScatteredRelocationScattered(const macho::RelocationEntry &RE) const; + uint32_t getScatteredRelocationValue(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationAddress(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationPCRel(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationLength(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationType(const macho::RelocationEntry &RE) const; + SectionRef getRelocationSection(const macho::RelocationEntry &RE) const; + + // Walk load commands. + LoadCommandInfo getFirstLoadCommandInfo() const; + LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const; + + // MachO specific structures. + macho::Section getSection(DataRefImpl DRI) const; + macho::Section64 getSection64(DataRefImpl DRI) const; + macho::Section getSection(const LoadCommandInfo &L, unsigned Index) const; + macho::Section64 getSection64(const LoadCommandInfo &L, unsigned Index) const; + macho::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const; + macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const; + + macho::LinkeditDataLoadCommand + getLinkeditDataLoadCommand(const LoadCommandInfo &L) const; + macho::SegmentLoadCommand + getSegmentLoadCommand(const LoadCommandInfo &L) const; + macho::Segment64LoadCommand + getSegment64LoadCommand(const LoadCommandInfo &L) const; + macho::LinkerOptionsLoadCommand + getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; + + macho::RelocationEntry getRelocation(DataRefImpl Rel) const; + macho::Header getHeader() const; + macho::Header64Ext getHeader64Ext() const; + macho::IndirectSymbolTableEntry + getIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC, + unsigned Index) const; + macho::DataInCodeTableEntry getDataInCodeTableEntry(uint32_t DataOffset, + unsigned Index) const; + macho::SymtabLoadCommand getSymtabLoadCommand() const; + macho::DysymtabLoadCommand getDysymtabLoadCommand() const; + + StringRef getStringTableData() const; + bool is64Bit() const; + void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; + + static bool classof(const Binary *v) { + return v->isMachO(); + } + +private: + typedef SmallVector<const char*, 1> SectionList; + SectionList Sections; + const char *SymtabLoadCmd; + const char *DysymtabLoadCmd; }; } diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h deleted file mode 100644 index 9e4ab199f5..0000000000 --- a/include/llvm/Object/MachOObject.h +++ /dev/null @@ -1,210 +0,0 @@ -//===- MachOObject.h - Mach-O Object File Wrapper ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_MACHOOBJECT_H -#define LLVM_OBJECT_MACHOOBJECT_H - -#include "llvm/ADT/InMemoryStruct.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Object/MachOFormat.h" -#include <string> - -namespace llvm { - -class MemoryBuffer; -class raw_ostream; - -namespace object { - -/// \brief Wrapper object for manipulating Mach-O object files. -/// -/// This class is designed to implement a full-featured, efficient, portable, -/// and robust Mach-O interface to Mach-O object files. It does not attempt to -/// smooth over rough edges in the Mach-O format or generalize access to object -/// independent features. -/// -/// The class is designed around accessing the Mach-O object which is expected -/// to be fully loaded into memory. -/// -/// This class is *not* suitable for concurrent use. For efficient operation, -/// the class uses APIs which rely on the ability to cache the results of -/// certain calls in internal objects which are not safe for concurrent -/// access. This allows the API to be zero-copy on the common paths. -// -// FIXME: It would be cool if we supported a "paged" MemoryBuffer -// implementation. This would allow us to implement a more sensible version of -// MemoryObject which can work like a MemoryBuffer, but be more efficient for -// objects which are in the current address space. -class MachOObject { -public: - struct LoadCommandInfo { - /// The load command information. - macho::LoadCommand Command; - - /// The offset to the start of the load command in memory. - uint64_t Offset; - }; - -private: - OwningPtr<MemoryBuffer> Buffer; - - /// Whether the object is little endian. - bool IsLittleEndian; - /// Whether the object is 64-bit. - bool Is64Bit; - /// Whether the object is swapped endianness from the host. - bool IsSwappedEndian; - /// Whether the string table has been registered. - bool HasStringTable; - - /// The cached information on the load commands. - LoadCommandInfo *LoadCommands; - mutable unsigned NumLoadedCommands; - - /// The cached copy of the header. - macho::Header Header; - macho::Header64Ext Header64Ext; - - /// Cache string table information. - StringRef StringTable; - -private: - MachOObject(MemoryBuffer *Buffer, bool IsLittleEndian, bool Is64Bit); - -public: - ~MachOObject(); - - /// \brief Load a Mach-O object from a MemoryBuffer object. - /// - /// \param Buffer - The buffer to load the object from. This routine takes - /// exclusive ownership of the buffer (which is passed to the returned object - /// on success). - /// \param ErrorStr [out] - If given, will be set to a user readable error - /// message on failure. - /// \returns The loaded object, or null on error. - static MachOObject *LoadFromBuffer(MemoryBuffer *Buffer, - std::string *ErrorStr = 0); - - /// @name File Information - /// @{ - - bool isLittleEndian() const { return IsLittleEndian; } - bool isSwappedEndian() const { return IsSwappedEndian; } - bool is64Bit() const { return Is64Bit; } - - unsigned getHeaderSize() const { - return Is64Bit ? macho::Header64Size : macho::Header32Size; - } - - StringRef getData(size_t Offset, size_t Size) const; - - /// @} - /// @name String Table Data - /// @{ - - StringRef getStringTableData() const { - assert(HasStringTable && "String table has not been registered!"); - return StringTable; - } - - StringRef getStringAtIndex(unsigned Index) const { - size_t End = getStringTableData().find('\0', Index); - return getStringTableData().slice(Index, End); - } - - void RegisterStringTable(macho::SymtabLoadCommand &SLC); - - /// @} - /// @name Object Header Access - /// @{ - - const macho::Header &getHeader() const { return Header; } - const macho::Header64Ext &getHeader64Ext() const { - assert(is64Bit() && "Invalid access!"); - return Header64Ext; - } - - /// @} - /// @name Object Structure Access - /// @{ - - /// \brief Retrieve the information for the given load command. - const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const; - - void ReadSegmentLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::SegmentLoadCommand> &Res) const; - void ReadSegment64LoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::Segment64LoadCommand> &Res) const; - void ReadSymtabLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::SymtabLoadCommand> &Res) const; - void ReadDysymtabLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::DysymtabLoadCommand> &Res) const; - void ReadLinkeditDataLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::LinkeditDataLoadCommand> &Res) const; - void ReadLinkerOptionsLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct<macho::LinkerOptionsLoadCommand> &Res) const; - void ReadIndirectSymbolTableEntry( - const macho::DysymtabLoadCommand &DLC, - unsigned Index, - InMemoryStruct<macho::IndirectSymbolTableEntry> &Res) const; - void ReadSection( - const LoadCommandInfo &LCI, - unsigned Index, - InMemoryStruct<macho::Section> &Res) const; - void ReadSection64( - const LoadCommandInfo &LCI, - unsigned Index, - InMemoryStruct<macho::Section64> &Res) const; - void ReadRelocationEntry( - uint64_t RelocationTableOffset, unsigned Index, - InMemoryStruct<macho::RelocationEntry> &Res) const; - void ReadSymbolTableEntry( - uint64_t SymbolTableOffset, unsigned Index, - InMemoryStruct<macho::SymbolTableEntry> &Res) const; - void ReadSymbol64TableEntry( - uint64_t SymbolTableOffset, unsigned Index, - InMemoryStruct<macho::Symbol64TableEntry> &Res) const; - void ReadDataInCodeTableEntry( - uint64_t TableOffset, unsigned Index, - InMemoryStruct<macho::DataInCodeTableEntry> &Res) const; - void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; - - /// @} - - /// @name Object Dump Facilities - /// @{ - /// dump - Support for debugging, callable in GDB: V->dump() - // - void dump() const; - void dumpHeader() const; - - /// print - Implement operator<< on Value. - /// - void print(raw_ostream &O) const; - void printHeader(raw_ostream &O) const; - - /// @} -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const MachOObject &V) { - V.print(OS); - return OS; -} - -} // end namespace object -} // end namespace llvm - -#endif diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 6a66653fe2..eb53cc0aab 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -217,6 +217,8 @@ public: /// mapped). error_code getAddress(uint64_t &Result) const; error_code getFileOffset(uint64_t &Result) const; + /// @brief Get the alignment of this symbol as the actual value (not log 2). + error_code getAlignment(uint32_t &Result) const; error_code getSize(uint64_t &Result) const; error_code getType(SymbolRef::Type &Result) const; @@ -227,9 +229,6 @@ public: /// Get symbol flags (bitwise OR of SymbolRef::Flags) error_code getFlags(uint32_t &Result) const; - /// @brief Return true for common symbols such as uninitialized globals - error_code isCommon(bool &Result) const; - /// @brief Get section this symbol is defined in reference to. Result is /// end_sections() if it is undefined or is an absolute symbol. error_code getSection(section_iterator &Result) const; @@ -276,7 +275,7 @@ class ObjectFile : public Binary { ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; protected: - ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec); + ObjectFile(unsigned int Type, MemoryBuffer *source); const uint8_t *base() const { return reinterpret_cast<const uint8_t *>(Data->getBufferStart()); @@ -295,6 +294,7 @@ protected: virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res)const=0; + virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const = 0; @@ -428,6 +428,10 @@ inline error_code SymbolRef::getFileOffset(uint64_t &Result) const { return OwningObject->getSymbolFileOffset(SymbolPimpl, Result); } +inline error_code SymbolRef::getAlignment(uint32_t &Result) const { + return OwningObject->getSymbolAlignment(SymbolPimpl, Result); +} + inline error_code SymbolRef::getSize(uint64_t &Result) const { return OwningObject->getSymbolSize(SymbolPimpl, Result); } diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 2dcbdf9053..59d810763f 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -133,7 +133,7 @@ private: int64_t Addend; R.getAdditionalInfo(Addend); uint64_t Address; - R.getAddress(Address); + R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } @@ -151,7 +151,7 @@ private: int64_t Addend; R.getAdditionalInfo(Addend); uint64_t Address; - R.getAddress(Address); + R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { diff --git a/include/llvm/PassManager.h b/include/llvm/PassManager.h index ce5fda79f9..b6a8186a4e 100644 --- a/include/llvm/PassManager.h +++ b/include/llvm/PassManager.h @@ -18,6 +18,7 @@ #define LLVM_PASSMANAGER_H #include "llvm/Pass.h" +#include "llvm/Support/CBindingWrapping.h" namespace llvm { @@ -98,6 +99,9 @@ private: Module *M; }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBase, LLVMPassManagerRef) + } // End llvm namespace #endif diff --git a/include/llvm/PassRegistry.h b/include/llvm/PassRegistry.h index 5d89c49221..f49c953e44 100644 --- a/include/llvm/PassRegistry.h +++ b/include/llvm/PassRegistry.h @@ -18,6 +18,8 @@ #define LLVM_PASSREGISTRY_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/CBindingWrapping.h" +#include "llvm-c/Core.h" namespace llvm { @@ -79,6 +81,9 @@ public: void removeRegistrationListener(PassRegistrationListener *L); }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassRegistry, LLVMPassRegistryRef) + } #endif diff --git a/include/llvm/Support/CBindingWrapping.h b/include/llvm/Support/CBindingWrapping.h new file mode 100644 index 0000000000..51097b8202 --- /dev/null +++ b/include/llvm/Support/CBindingWrapping.h @@ -0,0 +1,46 @@ +//===- llvm/Support/CBindingWrapph.h - C Interface Wrapping -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the wrapping macros for the C interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_C_BINDING_WRAPPING_H +#define LLVM_C_BINDING_WRAPPING_H + +#include "llvm/Support/Casting.h" + +#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + inline ty *unwrap(ref P) { \ + return reinterpret_cast<ty*>(P); \ + } \ + \ + inline ref wrap(const ty *P) { \ + return reinterpret_cast<ref>(const_cast<ty*>(P)); \ + } + +#define DEFINE_ISA_CONVERSION_FUNCTIONS(ty, ref) \ + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + \ + template<typename T> \ + inline T *unwrap(ref P) { \ + return cast<T>(unwrap(P)); \ + } + +#define DEFINE_STDCXX_CONVERSION_FUNCTIONS(ty, ref) \ + DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ + \ + template<typename T> \ + inline T *unwrap(ref P) { \ + T *Q = (T*)unwrap(P); \ + assert(Q && "Invalid cast!"); \ + return Q; \ + } + +#endif diff --git a/include/llvm/Support/CFG.h b/include/llvm/Support/CFG.h index a9fb65cba9..265b886daf 100644 --- a/include/llvm/Support/CFG.h +++ b/include/llvm/Support/CFG.h @@ -27,8 +27,9 @@ namespace llvm { template <class Ptr, class USE_iterator> // Predecessor Iterator class PredIterator : public std::iterator<std::forward_iterator_tag, - Ptr, ptrdiff_t> { - typedef std::iterator<std::forward_iterator_tag, Ptr, ptrdiff_t> super; + Ptr, ptrdiff_t, Ptr*, Ptr*> { + typedef std::iterator<std::forward_iterator_tag, Ptr, ptrdiff_t, Ptr*, + Ptr*> super; typedef PredIterator<Ptr, USE_iterator> Self; USE_iterator It; @@ -40,6 +41,7 @@ class PredIterator : public std::iterator<std::forward_iterator_tag, public: typedef typename super::pointer pointer; + typedef typename super::reference reference; PredIterator() {} explicit inline PredIterator(Ptr *bb) : It(bb->use_begin()) { @@ -50,7 +52,7 @@ public: inline bool operator==(const Self& x) const { return It == x.It; } inline bool operator!=(const Self& x) const { return !operator==(x); } - inline pointer operator*() const { + inline reference operator*() const { assert(!It.atEnd() && "pred_iterator out of range!"); return cast<TerminatorInst>(*It)->getParent(); } @@ -100,10 +102,11 @@ inline const_pred_iterator pred_end(const BasicBlock *BB) { template <class Term_, class BB_> // Successor Iterator class SuccIterator : public std::iterator<std::bidirectional_iterator_tag, - BB_, ptrdiff_t> { + BB_, ptrdiff_t, BB_*, BB_*> { const Term_ Term; unsigned idx; - typedef std::iterator<std::bidirectional_iterator_tag, BB_, ptrdiff_t> super; + typedef std::iterator<std::bidirectional_iterator_tag, BB_, ptrdiff_t, BB_*, + BB_*> super; typedef SuccIterator<Term_, BB_> Self; inline bool index_is_valid(int idx) { @@ -112,6 +115,7 @@ class SuccIterator : public std::iterator<std::bidirectional_iterator_tag, public: typedef typename super::pointer pointer; + typedef typename super::reference reference; // TODO: This can be random access iterator, only operator[] missing. explicit inline SuccIterator(Term_ T) : Term(T), idx(0) {// begin iterator @@ -142,7 +146,7 @@ public: inline bool operator==(const Self& x) const { return idx == x.idx; } inline bool operator!=(const Self& x) const { return !operator==(x); } - inline pointer operator*() const { return Term->getSuccessor(idx); } + inline reference operator*() const { return Term->getSuccessor(idx); } inline pointer operator->() const { return operator*(); } inline Self& operator++() { ++idx; return *this; } // Preincrement diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 02c44cdfad..823b43ad93 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -321,7 +321,8 @@ namespace COFF { IMAGE_COMDAT_SELECT_SAME_SIZE, IMAGE_COMDAT_SELECT_EXACT_MATCH, IMAGE_COMDAT_SELECT_ASSOCIATIVE, - IMAGE_COMDAT_SELECT_LARGEST + IMAGE_COMDAT_SELECT_LARGEST, + IMAGE_COMDAT_SELECT_NEWEST }; // Auxiliary Symbol Formats diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index 3ce0fef4a0..92107ac025 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -28,7 +28,6 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/IR/Attributes.h" -#include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Instructions.h" diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index 80f09db4f7..0d2d6c92fd 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -36,9 +36,13 @@ template<typename From> struct simplify_type { }; template<typename From> struct simplify_type<const From> { - typedef const From SimpleType; - static SimpleType &getSimplifiedValue(const From &Val) { - return simplify_type<From>::getSimplifiedValue(static_cast<From&>(Val)); + typedef typename simplify_type<From>::SimpleType NonConstSimpleType; + typedef typename add_const_past_pointer<NonConstSimpleType>::type + SimpleType; + typedef typename add_lvalue_reference_if_not_pointer<SimpleType>::type + RetType; + static RetType getSimplifiedValue(const From& Val) { + return simplify_type<From>::getSimplifiedValue(const_cast<From&>(Val)); } }; @@ -81,6 +85,13 @@ template <typename To, typename From> struct isa_impl_cl<To, From*> { } }; +template <typename To, typename From> struct isa_impl_cl<To, From*const> { + static inline bool doit(const From *Val) { + assert(Val && "isa<> used on a null pointer"); + return isa_impl<To, From>::doit(*Val); + } +}; + template <typename To, typename From> struct isa_impl_cl<To, const From*> { static inline bool doit(const From *Val) { assert(Val && "isa<> used on a null pointer"); @@ -102,7 +113,7 @@ struct isa_impl_wrap { static bool doit(const From &Val) { return isa_impl_wrap<To, SimpleFrom, typename simplify_type<SimpleFrom>::SimpleType>::doit( - simplify_type<From>::getSimplifiedValue(Val)); + simplify_type<const From>::getSimplifiedValue(Val)); } }; @@ -121,7 +132,8 @@ struct isa_impl_wrap<To, FromTy, FromTy> { // template <class X, class Y> inline bool isa(const Y &Val) { - return isa_impl_wrap<X, Y, typename simplify_type<Y>::SimpleType>::doit(Val); + return isa_impl_wrap<X, const Y, + typename simplify_type<const Y>::SimpleType>::doit(Val); } //===----------------------------------------------------------------------===// @@ -178,7 +190,7 @@ struct cast_retty { // template<class To, class From, class SimpleFrom> struct cast_convert_val { // This is not a simple type, use the template to simplify it... - static typename cast_retty<To, From>::ret_type doit(const From &Val) { + static typename cast_retty<To, From>::ret_type doit(From &Val) { return cast_convert_val<To, SimpleFrom, typename simplify_type<SimpleFrom>::SimpleType>::doit( simplify_type<From>::getSimplifiedValue(Val)); @@ -204,20 +216,14 @@ template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { // cast<Instruction>(myVal)->getParent() // template <class X, class Y> -inline typename enable_if_c< - !is_same<Y, typename simplify_type<Y>::SimpleType>::value, - typename cast_retty<X, Y>::ret_type ->::type cast(const Y &Val) { +inline typename cast_retty<X, const Y>::ret_type cast(const Y &Val) { assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); - return cast_convert_val<X, Y, - typename simplify_type<Y>::SimpleType>::doit(Val); + return cast_convert_val<X, const Y, + typename simplify_type<const Y>::SimpleType>::doit(Val); } template <class X, class Y> -inline typename enable_if< - is_same<Y, typename simplify_type<Y>::SimpleType>, - typename cast_retty<X, Y>::ret_type ->::type cast(Y &Val) { +inline typename cast_retty<X, Y>::ret_type cast(Y &Val) { assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); return cast_convert_val<X, Y, typename simplify_type<Y>::SimpleType>::doit(Val); @@ -253,18 +259,12 @@ inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { // template <class X, class Y> -inline typename enable_if_c< - !is_same<Y, typename simplify_type<Y>::SimpleType>::value, - typename cast_retty<X, Y>::ret_type ->::type dyn_cast(const Y &Val) { +inline typename cast_retty<X, const Y>::ret_type dyn_cast(const Y &Val) { return isa<X>(Val) ? cast<X>(Val) : 0; } template <class X, class Y> -inline typename enable_if< - is_same<Y, typename simplify_type<Y>::SimpleType>, - typename cast_retty<X, Y>::ret_type ->::type dyn_cast(Y &Val) { +inline typename cast_retty<X, Y>::ret_type dyn_cast(Y &Val) { return isa<X>(Val) ? cast<X>(Val) : 0; } diff --git a/include/llvm/Support/CodeGen.h b/include/llvm/Support/CodeGen.h index 1b66c94389..240eba6c8a 100644 --- a/include/llvm/Support/CodeGen.h +++ b/include/llvm/Support/CodeGen.h @@ -15,6 +15,9 @@ #ifndef LLVM_SUPPORT_CODEGEN_H #define LLVM_SUPPORT_CODEGEN_H +#include "llvm-c/TargetMachine.h" +#include "llvm/Support/ErrorHandling.h" + namespace llvm { // Relocation model types. @@ -47,6 +50,42 @@ namespace llvm { }; } + // Create wrappers for C Binding types (see CBindingWrapping.h). + inline CodeModel::Model unwrap(LLVMCodeModel Model) { + switch (Model) { + case LLVMCodeModelDefault: + return CodeModel::Default; + case LLVMCodeModelJITDefault: + return CodeModel::JITDefault; + case LLVMCodeModelSmall: + return CodeModel::Small; + case LLVMCodeModelKernel: + return CodeModel::Kernel; + case LLVMCodeModelMedium: + return CodeModel::Medium; + case LLVMCodeModelLarge: + return CodeModel::Large; + } + return CodeModel::Default; + } + + inline LLVMCodeModel wrap(CodeModel::Model Model) { + switch (Model) { + case CodeModel::Default: + return LLVMCodeModelDefault; + case CodeModel::JITDefault: + return LLVMCodeModelJITDefault; + case CodeModel::Small: + return LLVMCodeModelSmall; + case CodeModel::Kernel: + return LLVMCodeModelKernel; + case CodeModel::Medium: + return LLVMCodeModelMedium; + case CodeModel::Large: + return LLVMCodeModelLarge; + } + llvm_unreachable("Bad CodeModel!"); + } } // end llvm namespace #endif diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 25f42a98e7..13d057be04 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -351,4 +351,14 @@ #define LLVM_EXPLICIT #endif +/// \macro LLVM_STATIC_ASSERT +/// \brief Expands to C/C++'s static_assert on compilers which support it. +#if __has_feature(cxx_static_assert) +# define LLVM_STATIC_ASSERT(expr, msg) static_assert(expr, msg) +#elif __has_feature(c_static_assert) +# define LLVM_STATIC_ASSERT(expr, msg) _Static_assert(expr, msg) +#else +# define LLVM_STATIC_ASSERT(expr, msg) +#endif + #endif diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h new file mode 100644 index 0000000000..9b1142d035 --- /dev/null +++ b/include/llvm/Support/Compression.h @@ -0,0 +1,58 @@ +//===-- llvm/Support/Compression.h ---Compression----------------*- 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 basic functions for compression/uncompression. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COMPRESSION_H +#define LLVM_SUPPORT_COMPRESSION_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MemoryBuffer; +template<typename T> class OwningPtr; +class StringRef; + +namespace zlib { + +enum CompressionLevel { + NoCompression, + DefaultCompression, + BestSpeedCompression, + BestSizeCompression +}; + +enum Status { + StatusOK, + StatusUnsupported, // zlib is unavaliable + StatusOutOfMemory, // there was not enough memory + StatusBufferTooShort, // there was not enough room in the output buffer + StatusInvalidArg, // invalid input parameter + StatusInvalidData // data was corrupted or incomplete +}; + +bool isAvailable(); + +Status compress(StringRef InputBuffer, + OwningPtr<MemoryBuffer> &CompressedBuffer, + CompressionLevel Level = DefaultCompression); + +Status uncompress(StringRef InputBuffer, + OwningPtr<MemoryBuffer> &UncompressedBuffer, + size_t UncompressedSize); + +} // End of namespace zlib + +} // End of namespace llvm + +#endif + diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index cc9151ef50..232aadc3e0 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -466,6 +466,7 @@ enum { // ELF Relocation types for PPC64 enum { + R_PPC64_NONE = 0, R_PPC64_ADDR32 = 1, R_PPC64_ADDR16_LO = 4, R_PPC64_ADDR16_HI = 5, @@ -480,10 +481,13 @@ enum { R_PPC64_TOC16_LO = 48, R_PPC64_TOC16_HA = 50, R_PPC64_TOC = 51, + R_PPC64_ADDR16_DS = 56, + R_PPC64_ADDR16_LO_DS = 57, R_PPC64_TOC16_DS = 63, R_PPC64_TOC16_LO_DS = 64, R_PPC64_TLS = 67, R_PPC64_TPREL16_LO = 70, + R_PPC64_TPREL16_HA = 72, R_PPC64_DTPREL16_LO = 75, R_PPC64_DTPREL16_HA = 77, R_PPC64_GOT_TLSGD16_LO = 80, diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index d438facfa4..0d35849883 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -37,7 +37,7 @@ namespace detail { namespace endian { template<typename value_type, endianness endian> inline value_type byte_swap(value_type value) { - if (endian != native && sys::isBigEndianHost() != (endian == big)) + if (endian != native && sys::IsBigEndianHost != (endian == big)) return sys::SwapByteOrder(value); return value; } diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h index ca5dec0173..b948d97bff 100644 --- a/include/llvm/Support/ErrorHandling.h +++ b/include/llvm/Support/ErrorHandling.h @@ -24,7 +24,8 @@ namespace llvm { /// An error handler callback. typedef void (*fatal_error_handler_t)(void *user_data, - const std::string& reason); + const std::string& reason, + bool gen_crash_diag); /// install_fatal_error_handler - Installs a new error handler to be used /// whenever a serious (non-recoverable) error is encountered by LLVM. @@ -73,10 +74,14 @@ namespace llvm { /// standard error, followed by a newline. /// After the error handler is called this function will call exit(1), it /// does not return. - LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason); - LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason); - LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason); - LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, + bool gen_crash_diag = true); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const std::string &reason, + bool gen_crash_diag = true); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(StringRef reason, + bool gen_crash_diag = true); + LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const Twine &reason, + bool gen_crash_diag = true); /// This function calls abort(), and prints the optional message to stderr. /// Use the llvm_unreachable macro (that adds location info), instead of diff --git a/include/llvm/Support/FEnv.h b/include/llvm/Support/FEnv.h index d9cf7247a3..8560ee0a8a 100644 --- a/include/llvm/Support/FEnv.h +++ b/include/llvm/Support/FEnv.h @@ -32,7 +32,7 @@ namespace sys { /// llvm_fenv_clearexcept - Clear the floating-point exception state. static inline void llvm_fenv_clearexcept() { -#ifdef HAVE_FENV_H +#if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT feclearexcept(FE_ALL_EXCEPT); #endif errno = 0; @@ -43,7 +43,7 @@ static inline bool llvm_fenv_testexcept() { int errno_val = errno; if (errno_val == ERANGE || errno_val == EDOM) return true; -#ifdef HAVE_FENV_H +#if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT && HAVE_DECL_FE_INEXACT if (fetestexcept(FE_ALL_EXCEPT & ~FE_INEXACT)) return true; #endif diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index 21635dcfb6..2e4bd5aeca 100644 --- a/include/llvm/Support/FormattedStream.h +++ b/include/llvm/Support/FormattedStream.h @@ -17,125 +17,125 @@ #include "llvm/Support/raw_ostream.h" -namespace llvm -{ - /// formatted_raw_ostream - Formatted raw_fd_ostream to handle - /// asm-specific constructs. +namespace llvm { + +/// formatted_raw_ostream - A raw_ostream that wraps another one and keeps track +/// of column position, allowing padding out to specific column boundaries. +/// +class formatted_raw_ostream : public raw_ostream { +public: + /// DELETE_STREAM - Tell the destructor to delete the held stream. /// - class formatted_raw_ostream : public raw_ostream { - public: - /// DELETE_STREAM - Tell the destructor to delete the held stream. - /// - static const bool DELETE_STREAM = true; - - /// PRESERVE_STREAM - Tell the destructor to not delete the held - /// stream. - /// - static const bool PRESERVE_STREAM = false; - - private: - /// TheStream - The real stream we output to. We set it to be - /// unbuffered, since we're already doing our own buffering. - /// - raw_ostream *TheStream; - - /// DeleteStream - Do we need to delete TheStream in the - /// destructor? - /// - bool DeleteStream; - - /// ColumnScanned - The current output column of the data that's - /// been flushed and the portion of the buffer that's been - /// scanned. The column scheme is zero-based. - /// - unsigned ColumnScanned; - - /// Scanned - This points to one past the last character in the - /// buffer we've scanned. - /// - const char *Scanned; - - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; - - /// current_pos - Return the current position within the stream, - /// not counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE { - // Our current position in the stream is all the contents which have been - // written to the underlying stream (*not* the current position of the - // underlying stream). - return TheStream->tell(); - } - - /// ComputeColumn - Examine the given output buffer and figure out which - /// column we end up in after output. - /// - void ComputeColumn(const char *Ptr, size_t size); - - public: - /// formatted_raw_ostream - Open the specified file for - /// writing. If an error occurs, information about the error is - /// put into ErrorInfo, and the stream should be immediately - /// destroyed; the string will be empty if no error occurred. - /// - /// As a side effect, the given Stream is set to be Unbuffered. - /// This is because formatted_raw_ostream does its own buffering, - /// so it doesn't want another layer of buffering to be happening - /// underneath it. - /// - formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) - : raw_ostream(), TheStream(0), DeleteStream(false), ColumnScanned(0) { - setStream(Stream, Delete); - } - explicit formatted_raw_ostream() - : raw_ostream(), TheStream(0), DeleteStream(false), ColumnScanned(0) { - Scanned = 0; - } - - ~formatted_raw_ostream() { - flush(); - releaseStream(); - } - - void setStream(raw_ostream &Stream, bool Delete = false) { - releaseStream(); - - TheStream = &Stream; - DeleteStream = Delete; - - // This formatted_raw_ostream inherits from raw_ostream, so it'll do its - // own buffering, and it doesn't need or want TheStream to do another - // layer of buffering underneath. Resize the buffer to what TheStream - // had been using, and tell TheStream not to do its own buffering. - if (size_t BufferSize = TheStream->GetBufferSize()) - SetBufferSize(BufferSize); - else - SetUnbuffered(); - TheStream->SetUnbuffered(); + static const bool DELETE_STREAM = true; + + /// PRESERVE_STREAM - Tell the destructor to not delete the held + /// stream. + /// + static const bool PRESERVE_STREAM = false; + +private: + /// TheStream - The real stream we output to. We set it to be + /// unbuffered, since we're already doing our own buffering. + /// + raw_ostream *TheStream; - Scanned = 0; - } - - /// PadToColumn - Align the output to some column number. If the current - /// column is already equal to or more than NewCol, PadToColumn inserts one - /// space. - /// - /// \param NewCol - The column to move to. - formatted_raw_ostream &PadToColumn(unsigned NewCol); - - private: - void releaseStream() { - // Delete the stream if needed. Otherwise, transfer the buffer - // settings from this raw_ostream back to the underlying stream. - if (!TheStream) - return; - if (DeleteStream) - delete TheStream; - else if (size_t BufferSize = GetBufferSize()) - TheStream->SetBufferSize(BufferSize); - else - TheStream->SetUnbuffered(); - } - }; + /// DeleteStream - Do we need to delete TheStream in the + /// destructor? + /// + bool DeleteStream; + + /// ColumnScanned - The current output column of the data that's + /// been flushed and the portion of the buffer that's been + /// scanned. The column scheme is zero-based. + /// + unsigned ColumnScanned; + + /// Scanned - This points to one past the last character in the + /// buffer we've scanned. + /// + const char *Scanned; + + virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + + /// current_pos - Return the current position within the stream, + /// not counting the bytes currently in the buffer. + virtual uint64_t current_pos() const LLVM_OVERRIDE { + // Our current position in the stream is all the contents which have been + // written to the underlying stream (*not* the current position of the + // underlying stream). + return TheStream->tell(); + } + + /// ComputeColumn - Examine the given output buffer and figure out which + /// column we end up in after output. + /// + void ComputeColumn(const char *Ptr, size_t size); + +public: + /// formatted_raw_ostream - Open the specified file for + /// writing. If an error occurs, information about the error is + /// put into ErrorInfo, and the stream should be immediately + /// destroyed; the string will be empty if no error occurred. + /// + /// As a side effect, the given Stream is set to be Unbuffered. + /// This is because formatted_raw_ostream does its own buffering, + /// so it doesn't want another layer of buffering to be happening + /// underneath it. + /// + formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) + : raw_ostream(), TheStream(0), DeleteStream(false), ColumnScanned(0) { + setStream(Stream, Delete); + } + explicit formatted_raw_ostream() + : raw_ostream(), TheStream(0), DeleteStream(false), ColumnScanned(0) { + Scanned = 0; + } + + ~formatted_raw_ostream() { + flush(); + releaseStream(); + } + + void setStream(raw_ostream &Stream, bool Delete = false) { + releaseStream(); + + TheStream = &Stream; + DeleteStream = Delete; + + // This formatted_raw_ostream inherits from raw_ostream, so it'll do its + // own buffering, and it doesn't need or want TheStream to do another + // layer of buffering underneath. Resize the buffer to what TheStream + // had been using, and tell TheStream not to do its own buffering. + if (size_t BufferSize = TheStream->GetBufferSize()) + SetBufferSize(BufferSize); + else + SetUnbuffered(); + TheStream->SetUnbuffered(); + + Scanned = 0; + } + + /// PadToColumn - Align the output to some column number. If the current + /// column is already equal to or more than NewCol, PadToColumn inserts one + /// space. + /// + /// \param NewCol - The column to move to. + formatted_raw_ostream &PadToColumn(unsigned NewCol); + +private: + void releaseStream() { + // Delete the stream if needed. Otherwise, transfer the buffer + // settings from this raw_ostream back to the underlying stream. + if (!TheStream) + return; + if (DeleteStream) + delete TheStream; + else if (size_t BufferSize = GetBufferSize()) + TheStream->SetBufferSize(BufferSize); + else + TheStream->SetUnbuffered(); + } +}; /// fouts() - This returns a reference to a formatted_raw_ostream for /// standard output. Use it like: fouts() << "foo" << "bar"; diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h index 3a44405739..9a4036a8af 100644 --- a/include/llvm/Support/Host.h +++ b/include/llvm/Support/Host.h @@ -15,23 +15,27 @@ #define LLVM_SUPPORT_HOST_H #include "llvm/ADT/StringMap.h" + +#if defined(__linux__) +#include <endian.h> +#else +#ifndef LLVM_ON_WIN32 +#include <machine/endian.h> +#endif +#endif + #include <string> namespace llvm { namespace sys { - inline bool isLittleEndianHost() { - union { - int i; - char c; - }; - i = 1; - return c; - } +#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN + static const bool IsBigEndianHost = true; +#else + static const bool IsBigEndianHost = false; +#endif - inline bool isBigEndianHost() { - return !isLittleEndianHost(); - } + static const bool IsLittleEndianHost = !IsBigEndianHost; /// getDefaultTargetTriple() - Return the default target triple the compiler /// has been configured to produce code for. diff --git a/include/llvm/Support/IRReader.h b/include/llvm/Support/IRReader.h deleted file mode 100644 index 6d8a9b30ae..0000000000 --- a/include/llvm/Support/IRReader.h +++ /dev/null @@ -1,112 +0,0 @@ -//===---- llvm/Support/IRReader.h - Reader for LLVM IR files ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines functions for reading LLVM IR. They support both -// Bitcode and Assembly, automatically detecting the input format. -// -// These functions must be defined in a header file in order to avoid -// library dependencies, since they reference both Bitcode and Assembly -// functions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_IRREADER_H -#define LLVM_SUPPORT_IRREADER_H - -#include "llvm/ADT/OwningPtr.h" -#include "llvm/Assembly/Parser.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/system_error.h" - -namespace llvm { - - /// If the given MemoryBuffer holds a bitcode image, return a Module for it - /// which does lazy deserialization of function bodies. Otherwise, attempt to - /// parse it as LLVM Assembly and return a fully populated Module. This - /// function *always* takes ownership of the given MemoryBuffer. - inline Module *getLazyIRModule(MemoryBuffer *Buffer, - SMDiagnostic &Err, - LLVMContext &Context) { - if (isBitcode((const unsigned char *)Buffer->getBufferStart(), - (const unsigned char *)Buffer->getBufferEnd())) { - std::string ErrMsg; - Module *M = getLazyBitcodeModule(Buffer, Context, &ErrMsg); - if (M == 0) { - Err = SMDiagnostic(Buffer->getBufferIdentifier(), SourceMgr::DK_Error, - ErrMsg); - // ParseBitcodeFile does not take ownership of the Buffer in the - // case of an error. - delete Buffer; - } - return M; - } - - return ParseAssembly(Buffer, 0, Err, Context); - } - - /// If the given file holds a bitcode image, return a Module - /// for it which does lazy deserialization of function bodies. Otherwise, - /// attempt to parse it as LLVM Assembly and return a fully populated - /// Module. - inline Module *getLazyIRFileModule(const std::string &Filename, - SMDiagnostic &Err, - LLVMContext &Context) { - OwningPtr<MemoryBuffer> File; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { - Err = SMDiagnostic(Filename, SourceMgr::DK_Error, - "Could not open input file: " + ec.message()); - return 0; - } - - return getLazyIRModule(File.take(), Err, Context); - } - - /// If the given MemoryBuffer holds a bitcode image, return a Module - /// for it. Otherwise, attempt to parse it as LLVM Assembly and return - /// a Module for it. This function *always* takes ownership of the given - /// MemoryBuffer. - inline Module *ParseIR(MemoryBuffer *Buffer, - SMDiagnostic &Err, - LLVMContext &Context) { - if (isBitcode((const unsigned char *)Buffer->getBufferStart(), - (const unsigned char *)Buffer->getBufferEnd())) { - std::string ErrMsg; - Module *M = ParseBitcodeFile(Buffer, Context, &ErrMsg); - if (M == 0) - Err = SMDiagnostic(Buffer->getBufferIdentifier(), SourceMgr::DK_Error, - ErrMsg); - // ParseBitcodeFile does not take ownership of the Buffer. - delete Buffer; - return M; - } - - return ParseAssembly(Buffer, 0, Err, Context); - } - - /// If the given file holds a bitcode image, return a Module for it. - /// Otherwise, attempt to parse it as LLVM Assembly and return a Module - /// for it. - inline Module *ParseIRFile(const std::string &Filename, - SMDiagnostic &Err, - LLVMContext &Context) { - OwningPtr<MemoryBuffer> File; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { - Err = SMDiagnostic(Filename, SourceMgr::DK_Error, - "Could not open input file: " + ec.message()); - return 0; - } - - return ParseIR(File.take(), Err, Context); - } - -} - -#endif diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index 1f02907d9f..0cce726d48 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -15,8 +15,10 @@ #define LLVM_SUPPORT_MEMORYBUFFER_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm-c/Core.h" namespace llvm { @@ -137,6 +139,9 @@ public: virtual BufferKind getBufferKind() const = 0; }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef) + } // end namespace llvm #endif diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index a0cc27c024..fb177de97b 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -14,6 +14,7 @@ #ifndef LLVM_SUPPORT_PROGRAM_H #define LLVM_SUPPORT_PROGRAM_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Path.h" namespace llvm { @@ -125,7 +126,8 @@ namespace sys { const sys::Path** redirects = 0, unsigned secondsToWait = 0, unsigned memoryLimit = 0, - std::string* ErrMsg = 0); + std::string* ErrMsg = 0, + bool *ExecutionFailed = 0); /// A convenience function equivalent to Program prg; prg.Execute(..); /// @see Execute @@ -139,6 +141,10 @@ namespace sys { /// @} }; + + // Return true if the given arguments fit within system-specific + // argument length limits. + bool argumentsFitWithinSystemLimits(ArrayRef<const char*> Args); } } diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h index db44995d95..b49341c3ff 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/Support/ValueHandle.h @@ -20,6 +20,7 @@ namespace llvm { class ValueHandleBase; +template<typename From> struct simplify_type; // ValueHandleBase** is only 4-byte aligned. template<> @@ -162,14 +163,12 @@ public: // Specialize simplify_type to allow WeakVH to participate in // dyn_cast, isa, etc. -template<typename From> struct simplify_type; -template<> struct simplify_type<const WeakVH> { +template<> struct simplify_type<WeakVH> { typedef Value* SimpleType; - static SimpleType getSimplifiedValue(const WeakVH &WVH) { - return static_cast<Value *>(WVH); + static SimpleType getSimplifiedValue(WeakVH &WVH) { + return WVH; } }; -template<> struct simplify_type<WeakVH> : public simplify_type<const WeakVH> {}; /// AssertingVH - This is a Value Handle that points to a value and asserts out /// if the value is destroyed while the handle is still live. This is very @@ -236,18 +235,6 @@ public: ValueTy &operator*() const { return *getValPtr(); } }; -// Specialize simplify_type to allow AssertingVH to participate in -// dyn_cast, isa, etc. -template<typename From> struct simplify_type; -template<> struct simplify_type<const AssertingVH<Value> > { - typedef Value* SimpleType; - static SimpleType getSimplifiedValue(const AssertingVH<Value> &AVH) { - return static_cast<Value *>(AVH); - } -}; -template<> struct simplify_type<AssertingVH<Value> > - : public simplify_type<const AssertingVH<Value> > {}; - // Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. template<typename T> struct DenseMapInfo<AssertingVH<T> > { @@ -345,18 +332,6 @@ public: ValueTy &operator*() const { return *getValPtr(); } }; -// Specialize simplify_type to allow TrackingVH to participate in -// dyn_cast, isa, etc. -template<typename From> struct simplify_type; -template<> struct simplify_type<const TrackingVH<Value> > { - typedef Value* SimpleType; - static SimpleType getSimplifiedValue(const TrackingVH<Value> &AVH) { - return static_cast<Value *>(AVH); - } -}; -template<> struct simplify_type<TrackingVH<Value> > - : public simplify_type<const TrackingVH<Value> > {}; - /// CallbackVH - This is a value handle that allows subclasses to define /// callbacks that run when the underlying Value has RAUW called on it or is /// destroyed. This class can be used as the key of a map, as long as the user @@ -399,18 +374,6 @@ public: virtual void allUsesReplacedWith(Value *); }; -// Specialize simplify_type to allow CallbackVH to participate in -// dyn_cast, isa, etc. -template<typename From> struct simplify_type; -template<> struct simplify_type<const CallbackVH> { - typedef Value* SimpleType; - static SimpleType getSimplifiedValue(const CallbackVH &CVH) { - return static_cast<Value *>(CVH); - } -}; -template<> struct simplify_type<CallbackVH> - : public simplify_type<const CallbackVH> {}; - } // End llvm namespace #endif diff --git a/include/llvm/Support/Watchdog.h b/include/llvm/Support/Watchdog.h new file mode 100644 index 0000000000..b58496b2fb --- /dev/null +++ b/include/llvm/Support/Watchdog.h @@ -0,0 +1,38 @@ +//===--- Watchdog.h - Watchdog timer ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Watchdog class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WATCHDOG_H +#define LLVM_SUPPORT_WATCHDOG_H + +#include "llvm/Support/Compiler.h" + +namespace llvm { + namespace sys { + + /// This class provides an abstraction for a timeout around an operation + /// that must complete in a given amount of time. Failure to complete before + /// the timeout is an unrecoverable situation and no mechanisms to attempt + /// to handle it are provided. + class Watchdog { + public: + Watchdog(unsigned int seconds); + ~Watchdog(); + private: + // Noncopyable. + Watchdog(const Watchdog &other) LLVM_DELETED_FUNCTION; + Watchdog &operator=(const Watchdog &other) LLVM_DELETED_FUNCTION; + }; + } +} + +#endif diff --git a/include/llvm/Support/Win64EH.h b/include/llvm/Support/Win64EH.h index 164aca16bf..ecce713680 100644 --- a/include/llvm/Support/Win64EH.h +++ b/include/llvm/Support/Win64EH.h @@ -106,12 +106,17 @@ struct UnwindInfo { return reinterpret_cast<void *>(&UnwindCodes[(NumCodes+1) & ~1]); } - /// \brief Return image-relativ offset of language-specific exception handler. - uint32_t getLanguageSpecificHandlerOffset() { - return *reinterpret_cast<uint32_t *>(getLanguageSpecificData()); + /// \brief Return pointer to language specific data part of UnwindInfo. + const void *getLanguageSpecificData() const { + return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes+1) & ~1]); + } + + /// \brief Return image-relative offset of language-specific exception handler. + uint32_t getLanguageSpecificHandlerOffset() const { + return *reinterpret_cast<const uint32_t *>(getLanguageSpecificData()); } - /// \brief Set image-relativ offset of language-specific exception handler. + /// \brief Set image-relative offset of language-specific exception handler. void setLanguageSpecificHandlerOffset(uint32_t offset) { *reinterpret_cast<uint32_t *>(getLanguageSpecificData()) = offset; } @@ -126,6 +131,11 @@ struct UnwindInfo { RuntimeFunction *getChainedFunctionEntry() { return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData()); } + + /// \brief Return pointer to chained unwind info. + const RuntimeFunction *getChainedFunctionEntry() const { + return reinterpret_cast<const RuntimeFunction *>(getLanguageSpecificData()); + } }; diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index db43ccfece..906e97c91f 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -209,6 +209,26 @@ template <typename T> struct remove_pointer<T*volatile> { typedef T type; }; template <typename T> struct remove_pointer<T*const volatile> { typedef T type; }; +// If T is a pointer, just return it. If it is not, return T&. +template<typename T, typename Enable = void> +struct add_lvalue_reference_if_not_pointer { typedef T &type; }; + +template<typename T> +struct add_lvalue_reference_if_not_pointer<T, + typename enable_if<is_pointer<T> >::type> { + typedef T type; +}; + +// If T is a pointer to X, return a pointer to const X. If it is not, return +// const T. +template<typename T, typename Enable = void> +struct add_const_past_pointer { typedef const T type; }; + +template<typename T> +struct add_const_past_pointer<T, typename enable_if<is_pointer<T> >::type> { + typedef const typename remove_pointer<T>::type *type; +}; + template <bool, typename T, typename F> struct conditional { typedef T type; }; diff --git a/include/llvm/TableGen/Error.h b/include/llvm/TableGen/Error.h index 2f6b7e625c..2d0a2b45a9 100644 --- a/include/llvm/TableGen/Error.h +++ b/include/llvm/TableGen/Error.h @@ -32,6 +32,7 @@ LLVM_ATTRIBUTE_NORETURN void PrintFatalError(ArrayRef<SMLoc> ErrorLoc, const std::string &Msg); extern SourceMgr SrcMgr; +extern unsigned ErrorsPrinted; } // end namespace "llvm" diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index deee2eb6de..7de8b384c3 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -790,8 +790,8 @@ class AsmParser { // This can be used to perform target specific instruction post-processing. string AsmParserInstCleanup = ""; - //ShouldEmitMatchRegisterName - Set to false if the target needs a hand - //written register name matcher + // ShouldEmitMatchRegisterName - Set to false if the target needs a hand + // written register name matcher bit ShouldEmitMatchRegisterName = 1; } def DefaultAsmParser : AsmParser; @@ -807,6 +807,9 @@ class AsmParserVariant { // assembly language. int Variant = 0; + // Name - The AsmParser variant name (e.g., AT&T vs Intel). + string Name = ""; + // CommentDelimiter - If given, the delimiter string used to recognize // comments which are hard coded in the .td assembler strings for individual // instructions. @@ -860,9 +863,16 @@ class TokenAlias<string From, string To> { /// def : MnemonicAlias<"pushf", "pushfq">, Requires<[In64BitMode]>; /// def : MnemonicAlias<"pushf", "pushfl">, Requires<[In32BitMode]>; /// -class MnemonicAlias<string From, string To> { +/// Mnemonic aliases can also be constrained to specific variants, e.g.: +/// +/// def : MnemonicAlias<"pushf", "pushfq", "att">, Requires<[In64BitMode]>; +/// +/// If no variant (e.g., "att" or "intel") is specified then the alias is +/// applied unconditionally. +class MnemonicAlias<string From, string To, string VariantName = ""> { string FromMnemonic = From; string ToMnemonic = To; + string AsmVariantName = VariantName; // Predicates - Predicates that must be true for this remapping to happen. list<Predicate> Predicates = []; diff --git a/include/llvm/Target/TargetCallingConv.h b/include/llvm/Target/TargetCallingConv.h index 2160e371bd..1fd0bd98b6 100644 --- a/include/llvm/Target/TargetCallingConv.h +++ b/include/llvm/Target/TargetCallingConv.h @@ -36,13 +36,15 @@ namespace ISD { static const uint64_t ByValOffs = 4; static const uint64_t Nest = 1ULL<<5; ///< Nested fn static chain static const uint64_t NestOffs = 5; - static const uint64_t ByValAlign = 0xFULL << 6; ///< Struct alignment - static const uint64_t ByValAlignOffs = 6; - static const uint64_t Split = 1ULL << 10; - static const uint64_t SplitOffs = 10; + static const uint64_t Returned = 1ULL<<6; ///< Always returned + static const uint64_t ReturnedOffs = 6; + static const uint64_t ByValAlign = 0xFULL<<7; ///< Struct alignment + static const uint64_t ByValAlignOffs = 7; + static const uint64_t Split = 1ULL<<11; + static const uint64_t SplitOffs = 11; static const uint64_t OrigAlign = 0x1FULL<<27; static const uint64_t OrigAlignOffs = 27; - static const uint64_t ByValSize = 0xffffffffULL << 32; ///< Struct size + static const uint64_t ByValSize = 0xffffffffULL<<32; ///< Struct size static const uint64_t ByValSizeOffs = 32; static const uint64_t One = 1ULL; ///< 1 of this type, for shifts @@ -51,23 +53,26 @@ namespace ISD { public: ArgFlagsTy() : Flags(0) { } - bool isZExt() const { return Flags & ZExt; } - void setZExt() { Flags |= One << ZExtOffs; } + bool isZExt() const { return Flags & ZExt; } + void setZExt() { Flags |= One << ZExtOffs; } - bool isSExt() const { return Flags & SExt; } - void setSExt() { Flags |= One << SExtOffs; } + bool isSExt() const { return Flags & SExt; } + void setSExt() { Flags |= One << SExtOffs; } - bool isInReg() const { return Flags & InReg; } - void setInReg() { Flags |= One << InRegOffs; } + bool isInReg() const { return Flags & InReg; } + void setInReg() { Flags |= One << InRegOffs; } - bool isSRet() const { return Flags & SRet; } - void setSRet() { Flags |= One << SRetOffs; } + bool isSRet() const { return Flags & SRet; } + void setSRet() { Flags |= One << SRetOffs; } - bool isByVal() const { return Flags & ByVal; } - void setByVal() { Flags |= One << ByValOffs; } + bool isByVal() const { return Flags & ByVal; } + void setByVal() { Flags |= One << ByValOffs; } - bool isNest() const { return Flags & Nest; } - void setNest() { Flags |= One << NestOffs; } + bool isNest() const { return Flags & Nest; } + void setNest() { Flags |= One << NestOffs; } + + bool isReturned() const { return Flags & Returned; } + void setReturned() { Flags |= One << ReturnedOffs; } unsigned getByValAlign() const { return (unsigned) @@ -97,9 +102,6 @@ namespace ISD { Flags = (Flags & ~ByValSize) | (uint64_t(S) << ByValSizeOffs); } - /// getArgFlagsString - Returns the flags as a string, eg: "zext align:4". - std::string getArgFlagsString(); - /// getRawBits - Represent the flags as a bunch of bits. uint64_t getRawBits() const { return Flags; } }; diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index fb311d8508..d49ce1ce7f 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -364,11 +364,10 @@ public: /// condition code in Cond. /// /// When successful, also return the latency in cycles from TrueReg, - /// FalseReg, and Cond to the destination register. The Cond latency should - /// compensate for a conditional branch being removed. For example, if a - /// conditional branch has a 3 cycle latency from the condition code read, - /// and a cmov instruction has a 2 cycle latency from the condition code - /// read, CondCycles should be returned as -1. + /// FalseReg, and Cond to the destination register. In most cases, a select + /// instruction will be 1 cycle, so CondCycles = TrueCycles = FalseCycles = 1 + /// + /// Some x86 implementations have 2-cycle cmov instructions. /// /// @param MBB Block where select instruction would be inserted. /// @param Cond Condition returned by AnalyzeBranch. @@ -775,6 +774,10 @@ public: /// FoldImmediate - 'Reg' is known to be defined by a move immediate /// instruction, try to fold the immediate into the use instruction. + /// If MRI->hasOneNonDBGUse(Reg) is true, and this function returns true, + /// then the caller may assume that DefMI has been erased from its parent + /// block. The caller may assume that it will not be erased by this + /// function otherwise. virtual bool FoldImmediate(MachineInstr *UseMI, MachineInstr *DefMI, unsigned Reg, MachineRegisterInfo *MRI) const { return false; diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 5d74848b71..d5c9ebe0f2 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -135,6 +135,11 @@ public: const TargetLoweringObjectFile *TLOF); virtual ~TargetLoweringBase(); +protected: + /// \brief Initialize all of the actions to default values. + void initActions(); + +public: const TargetMachine &getTargetMachine() const { return TM; } const DataLayout *getDataLayout() const { return TD; } const TargetLoweringObjectFile &getObjFileLowering() const { return TLOF; } @@ -694,13 +699,6 @@ public: return false; } - /// This function returns true if the target would benefit from code placement - /// optimization. - /// @brief Determine if the target should perform code placement optimization. - bool shouldOptimizeCodePlacement() const { - return BenefitFromCodePlacementOpt; - } - /// getOptimalMemOpType - Returns the target specific optimal type for load /// and store operations as a result of memset, memcpy, and memmove /// lowering. If DstAlign is zero that means it's safe to destination @@ -812,13 +810,6 @@ public: return PrefLoopAlignment; } - /// getShouldFoldAtomicFences - return whether the combiner should fold - /// fence MEMBARRIER instructions into the atomic intrinsic instructions. - /// - bool getShouldFoldAtomicFences() const { - return ShouldFoldAtomicFences; - } - /// getInsertFencesFor - return whether the DAG builder should automatically /// insert fences and reduce ordering for atomics. /// @@ -858,6 +849,9 @@ public: // the derived class constructor to configure this object for the target. // + /// \brief Reset the operation actions based on target options. + virtual void resetOperationActions() {} + protected: /// setBooleanContents - Specify how the target extends the result of a /// boolean value from i1 to a wider type. See getBooleanContents. @@ -958,13 +952,17 @@ protected: RegClassForVT[VT.SimpleTy] = RC; } - /// clearRegisterClasses - remove all register classes + /// clearRegisterClasses - Remove all register classes. void clearRegisterClasses() { - for (unsigned i = 0 ; i<array_lengthof(RegClassForVT); i++) - RegClassForVT[i] = 0; + memset(RegClassForVT, 0,MVT::LAST_VALUETYPE * sizeof(TargetRegisterClass*)); + AvailableRegClasses.clear(); } + /// \brief Remove all operation actions. + void clearOperationActions() { + } + /// findRepresentativeClass - Return the largest legal super-reg register class /// of the register class for the specified type and its associated "cost". virtual std::pair<const TargetRegisterClass*, uint8_t> @@ -1096,12 +1094,6 @@ protected: MinStackArgumentAlignment = Align; } - /// setShouldFoldAtomicFences - Set if the target's implementation of the - /// atomic operation intrinsics includes locking. Default is false. - void setShouldFoldAtomicFences(bool fold) { - ShouldFoldAtomicFences = fold; - } - /// setInsertFencesForAtomic - Set if the DAG builder should /// automatically insert fences and reduce the order of atomic memory /// operations to Monotonic. @@ -1359,11 +1351,6 @@ private: /// unsigned PrefLoopAlignment; - /// ShouldFoldAtomicFences - Whether fencing MEMBARRIER instructions should - /// be folded into the enclosed atomic intrinsic instruction by the - /// combiner. - bool ShouldFoldAtomicFences; - /// InsertFencesForAtomic - Whether the DAG builder should automatically /// insert fences and reduce ordering for atomics. (This will be set for /// for most architectures with weak memory ordering.) @@ -1518,6 +1505,7 @@ public: // or until the element integer type is too big. If a legal type was not // found, fallback to the usual mechanism of widening/splitting the // vector. + EVT OldEltVT = EltVT; while (1) { // Increase the bitwidth of the element to the next pow-of-two // (which is greater than 8 bits). @@ -1536,6 +1524,10 @@ public: return LegalizeKind(TypePromoteInteger, EVT::getVectorVT(Context, EltVT, NumElts)); } + + // Reset the type to the unexpanded type if we did not find a legal vector + // type with a promoted vector element type. + EltVT = OldEltVT; } // Try to widen the vector until a legal type is found. @@ -1644,10 +1636,6 @@ protected: /// to memmove, used for functions with OpSize attribute. unsigned MaxStoresPerMemmoveOptSize; - /// This field specifies whether the target can benefit from code placement - /// optimization. - bool BenefitFromCodePlacementOpt; - /// PredictableSelectIsExpensive - Tells the code generator that select is /// more expensive than a branch if the branch is usually predicted right. bool PredictableSelectIsExpensive; @@ -1904,16 +1892,18 @@ public: struct ArgListEntry { SDValue Node; Type* Ty; - bool isSExt : 1; - bool isZExt : 1; - bool isInReg : 1; - bool isSRet : 1; - bool isNest : 1; - bool isByVal : 1; + bool isSExt : 1; + bool isZExt : 1; + bool isInReg : 1; + bool isSRet : 1; + bool isNest : 1; + bool isByVal : 1; + bool isReturned : 1; uint16_t Alignment; ArgListEntry() : isSExt(false), isZExt(false), isInReg(false), - isSRet(false), isNest(false), isByVal(false), Alignment(0) { } + isSRet(false), isNest(false), isByVal(false), isReturned(false), + Alignment(0) { } }; typedef std::vector<ArgListEntry> ArgListTy; diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 66f3a3c71b..37a79fe852 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -32,6 +32,7 @@ class MCContext; class PassManagerBase; class Target; class DataLayout; +class TargetLibraryInfo; class TargetFrameLowering; class TargetInstrInfo; class TargetIntrinsicInfo; diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index c31db24490..c763a595dd 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -208,6 +208,7 @@ namespace llvm { /// the value of this option. FPOpFusion::FPOpFusionMode AllowFPOpFusion; + bool operator==(const TargetOptions &); }; } // End llvm namespace diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 83bd7874df..d89a6e658e 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -414,9 +414,6 @@ def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch, def readcyclecounter : SDNode<"ISD::READCYCLECOUNTER", SDTIntLeaf, [SDNPHasChain, SDNPSideEffect]>; -def membarrier : SDNode<"ISD::MEMBARRIER" , SDTMemBarrier, - [SDNPHasChain, SDNPSideEffect]>; - def atomic_fence : SDNode<"ISD::ATOMIC_FENCE" , SDTAtomicFence, [SDNPHasChain, SDNPSideEffect]>; diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 209f68db6f..563721e128 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -103,7 +103,8 @@ public: bool DisableSimplifyLibCalls; bool DisableUnitAtATime; bool DisableUnrollLoops; - bool Vectorize; + bool BBVectorize; + bool SLPVectorize; bool LoopVectorize; private: diff --git a/include/llvm/Transforms/Utils/BlackList.h b/include/llvm/Transforms/Utils/BlackList.h index f19470e19d..316b364845 100644 --- a/include/llvm/Transforms/Utils/BlackList.h +++ b/include/llvm/Transforms/Utils/BlackList.h @@ -20,6 +20,7 @@ // global-init:*global_with_initialization_issues* // global-init-type:*Namespace::ClassName* // src:file_with_tricky_code.cc +// global-init-src:ignore-global-initializers-issues.cc // --- // Note that the wild card is in fact an llvm::Regex, but * is automatically // replaced with .* diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index 687c9d517b..267825079e 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -234,12 +234,12 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP, /// Dbg Intrinsic utilities /// -/// Inserts a llvm.dbg.value instrinsic before the stores to an alloca'd value +/// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value /// that has an associated llvm.dbg.decl intrinsic. bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, StoreInst *SI, DIBuilder &Builder); -/// Inserts a llvm.dbg.value instrinsic before the stores to an alloca'd value +/// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value /// that has an associated llvm.dbg.decl intrinsic. bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI, LoadInst *LI, DIBuilder &Builder); diff --git a/include/llvm/Transforms/Vectorize.h b/include/llvm/Transforms/Vectorize.h index d205dbdede..8d0db16116 100644 --- a/include/llvm/Transforms/Vectorize.h +++ b/include/llvm/Transforms/Vectorize.h @@ -117,6 +117,12 @@ createBBVectorizePass(const VectorizeConfig &C = VectorizeConfig()); Pass *createLoopVectorizePass(); //===----------------------------------------------------------------------===// +// +// SLPVectorizer - Create a bottom-up SLP vectorizer pass. +// +Pass *createSLPVectorizerPass(); + +//===----------------------------------------------------------------------===// /// @brief Vectorize the BasicBlock. /// /// @param BB The BasicBlock to be vectorized |