diff options
Diffstat (limited to 'include/llvm/Support')
81 files changed, 3694 insertions, 1339 deletions
diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index d6b0ab8..bba3424 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -19,7 +19,6 @@ #include <cstddef> namespace llvm { - template <typename T> struct AlignmentCalcImpl { char x; @@ -49,7 +48,6 @@ struct AlignOf { enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 }; enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 }; enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; - }; /// alignOf - A templated function that returns the minimum alignment of @@ -59,112 +57,148 @@ struct AlignOf { template <typename T> inline unsigned alignOf() { return AlignOf<T>::Alignment; } - +/// \struct AlignedCharArray /// \brief Helper for building an aligned character array type. /// /// This template is used to explicitly build up a collection of aligned -/// character types. We have to build these up using a macro and explicit +/// character array types. We have to build these up using a macro and explicit /// specialization to cope with old versions of MSVC and GCC where only an /// integer literal can be used to specify an alignment constraint. Once built /// up here, we can then begin to indirect between these using normal C++ /// template parameters. -template <size_t Alignment> struct AlignedCharArrayImpl; // MSVC requires special handling here. #ifndef _MSC_VER #if __has_feature(cxx_alignas) -#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ - template <> struct AlignedCharArrayImpl<x> { \ - char alignas(x) aligned; \ - } +template<std::size_t Alignment, std::size_t Size> +struct AlignedCharArray { + alignas(Alignment) char buffer[Size]; +}; + #elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES) +/// \brief Create a type with an aligned char buffer. +template<std::size_t Alignment, std::size_t Size> +struct AlignedCharArray; + #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ - template <> struct AlignedCharArrayImpl<x> { \ - char aligned __attribute__((aligned(x))); \ - } -#else -# error No supported align as directive. -#endif + template<std::size_t Size> \ + struct AlignedCharArray<x, Size> { \ + __attribute__((aligned(x))) char buffer[Size]; \ + }; -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) #undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT +#else +# error No supported align as directive. +#endif + #else // _MSC_VER +/// \brief Create a type with an aligned char buffer. +template<std::size_t Alignment, std::size_t Size> +struct AlignedCharArray; + // We provide special variations of this template for the most common // alignments because __declspec(align(...)) doesn't actually work when it is // a member of a by-value function argument in MSVC, even if the alignment -// request is something reasonably like 8-byte or 16-byte. -template <> struct AlignedCharArrayImpl<1> { char aligned; }; -template <> struct AlignedCharArrayImpl<2> { short aligned; }; -template <> struct AlignedCharArrayImpl<4> { int aligned; }; -template <> struct AlignedCharArrayImpl<8> { double aligned; }; +// request is something reasonably like 8-byte or 16-byte. Note that we can't +// even include the declspec with the union that forces the alignment because +// MSVC warns on the existence of the declspec despite the union member forcing +// proper alignment. + +template<std::size_t Size> +struct AlignedCharArray<1, Size> { + union { + char aligned; + char buffer[Size]; + }; +}; + +template<std::size_t Size> +struct AlignedCharArray<2, Size> { + union { + short aligned; + char buffer[Size]; + }; +}; + +template<std::size_t Size> +struct AlignedCharArray<4, Size> { + union { + int aligned; + char buffer[Size]; + }; +}; + +template<std::size_t Size> +struct AlignedCharArray<8, Size> { + union { + double aligned; + char buffer[Size]; + }; +}; + + +// The rest of these are provided with a __declspec(align(...)) and we simply +// can't pass them by-value as function arguments on MSVC. #define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ - template <> struct AlignedCharArrayImpl<x> { \ - __declspec(align(x)) char aligned; \ - } -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096); -LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192); -// Any larger and MSVC complains. + template<std::size_t Size> \ + struct AlignedCharArray<x, Size> { \ + __declspec(align(x)) char buffer[Size]; \ + }; + +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64) +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) + #undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT #endif // _MSC_VER +namespace detail { +template <typename T1, + typename T2 = char, typename T3 = char, typename T4 = char, + typename T5 = char, typename T6 = char, typename T7 = char> +class AlignerImpl { + T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; + + AlignerImpl(); // Never defined or instantiated. +}; + +template <typename T1, + typename T2 = char, typename T3 = char, typename T4 = char, + typename T5 = char, typename T6 = char, typename T7 = char> +union SizerImpl { + char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)], + arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)]; +}; +} // end namespace detail + /// \brief This union template exposes a suitably aligned and sized character /// array member which can hold elements of any of up to four types. /// /// These types may be arrays, structs, or any other types. The goal is to -/// produce a union type containing a character array which, when used, forms -/// storage suitable to placement new any of these types over. Support for more -/// than four types can be added at the cost of more boiler plate. +/// expose a char array buffer member which can be used as suitable storage for +/// a placement new of any of these types. Support for more than seven types can +/// be added at the cost of more boiler plate. template <typename T1, - typename T2 = char, typename T3 = char, typename T4 = char> -union AlignedCharArrayUnion { -private: - class AlignerImpl { - T1 t1; T2 t2; T3 t3; T4 t4; - - AlignerImpl(); // Never defined or instantiated. - }; - union SizerImpl { - char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)]; - }; - -public: - /// \brief The character array buffer for use by clients. - /// - /// No other member of this union should be referenced. The exist purely to - /// constrain the layout of this character array. - char buffer[sizeof(SizerImpl)]; - -private: - // Tests seem to indicate that both Clang and GCC will properly register the - // alignment of a struct containing an aligned member, and this alignment - // should carry over to the character array in the union. - llvm::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment> nonce_member; + typename T2 = char, typename T3 = char, typename T4 = char, + typename T5 = char, typename T6 = char, typename T7 = char> +struct AlignedCharArrayUnion : llvm::AlignedCharArray< + AlignOf<detail::AlignerImpl<T1, T2, T3, T4, T5, T6, T7> >::Alignment, + sizeof(detail::SizerImpl<T1, T2, T3, T4, T5, T6, T7>)> { }; - } // end namespace llvm #endif diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index a644b13..3243fd9 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -15,12 +15,12 @@ #define LLVM_SUPPORT_ALLOCATOR_H #include "llvm/Support/AlignOf.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MathExtras.h" #include <algorithm> #include <cassert> -#include <cstdlib> #include <cstddef> +#include <cstdlib> namespace llvm { template <typename T> struct ReferenceAdder { typedef T& result; }; diff --git a/include/llvm/Support/ArrayRecycler.h b/include/llvm/Support/ArrayRecycler.h new file mode 100644 index 0000000..c7e0cba --- /dev/null +++ b/include/llvm/Support/ArrayRecycler.h @@ -0,0 +1,143 @@ +//==- llvm/Support/ArrayRecycler.h - Recycling of Arrays ---------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ArrayRecycler class template which can recycle small +// arrays allocated from one of the allocators in Allocator.h +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ARRAYRECYCLER_H +#define LLVM_SUPPORT_ARRAYRECYCLER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MathExtras.h" + +namespace llvm { + +class BumpPtrAllocator; + +/// Recycle small arrays allocated from a BumpPtrAllocator. +/// +/// Arrays are allocated in a small number of fixed sizes. For each supported +/// array size, the ArrayRecycler keeps a free list of available arrays. +/// +template<class T, size_t Align = AlignOf<T>::Alignment> +class ArrayRecycler { + // The free list for a given array size is a simple singly linked list. + // We can't use iplist or Recycler here since those classes can't be copied. + struct FreeList { + FreeList *Next; + }; + + // Keep a free list for each array size. + SmallVector<FreeList*, 8> Bucket; + + // Remove an entry from the free list in Bucket[Idx] and return it. + // Return NULL if no entries are available. + T *pop(unsigned Idx) { + if (Idx >= Bucket.size()) + return 0; + FreeList *Entry = Bucket[Idx]; + if (!Entry) + return 0; + Bucket[Idx] = Entry->Next; + return reinterpret_cast<T*>(Entry); + } + + // Add an entry to the free list at Bucket[Idx]. + void push(unsigned Idx, T *Ptr) { + assert(Ptr && "Cannot recycle NULL pointer"); + assert(sizeof(T) >= sizeof(FreeList) && "Objects are too small"); + assert(Align >= AlignOf<FreeList>::Alignment && "Object underaligned"); + FreeList *Entry = reinterpret_cast<FreeList*>(Ptr); + if (Idx >= Bucket.size()) + Bucket.resize(size_t(Idx) + 1); + Entry->Next = Bucket[Idx]; + Bucket[Idx] = Entry; + } + +public: + /// The size of an allocated array is represented by a Capacity instance. + /// + /// This class is much smaller than a size_t, and it provides methods to work + /// with the set of legal array capacities. + class Capacity { + uint8_t Index; + explicit Capacity(uint8_t idx) : Index(idx) {} + + public: + Capacity() : Index(0) {} + + /// Get the capacity of an array that can hold at least N elements. + static Capacity get(size_t N) { + return Capacity(N ? Log2_64_Ceil(N) : 0); + } + + /// Get the number of elements in an array with this capacity. + size_t getSize() const { return size_t(1u) << Index; } + + /// Get the bucket number for this capacity. + unsigned getBucket() const { return Index; } + + /// Get the next larger capacity. Large capacities grow exponentially, so + /// this function can be used to reallocate incrementally growing vectors + /// in amortized linear time. + Capacity getNext() const { return Capacity(Index + 1); } + }; + + ~ArrayRecycler() { + // The client should always call clear() so recycled arrays can be returned + // to the allocator. + assert(Bucket.empty() && "Non-empty ArrayRecycler deleted!"); + } + + /// Release all the tracked allocations to the allocator. The recycler must + /// be free of any tracked allocations before being deleted. + template<class AllocatorType> + void clear(AllocatorType &Allocator) { + for (; !Bucket.empty(); Bucket.pop_back()) + while (T *Ptr = pop(Bucket.size() - 1)) + Allocator.Deallocate(Ptr); + } + + /// Special case for BumpPtrAllocator which has an empty Deallocate() + /// function. + /// + /// There is no need to traverse the free lists, pulling all the objects into + /// cache. + void clear(BumpPtrAllocator&) { + Bucket.clear(); + } + + /// Allocate an array of at least the requested capacity. + /// + /// Return an existing recycled array, or allocate one from Allocator if + /// none are available for recycling. + /// + template<class AllocatorType> + T *allocate(Capacity Cap, AllocatorType &Allocator) { + // Try to recycle an existing array. + if (T *Ptr = pop(Cap.getBucket())) + return Ptr; + // Nope, get more memory. + return static_cast<T*>(Allocator.Allocate(sizeof(T)*Cap.getSize(), Align)); + } + + /// Deallocate an array with the specified Capacity. + /// + /// Cap must be the same capacity that was given to allocate(). + /// + void deallocate(Capacity Cap, T *Ptr) { + push(Cap.getBucket(), Ptr); + } +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/Support/Atomic.h b/include/llvm/Support/Atomic.h index 1a6c606..9ec23e8 100644 --- a/include/llvm/Support/Atomic.h +++ b/include/llvm/Support/Atomic.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_ATOMIC_H -#define LLVM_SYSTEM_ATOMIC_H +#ifndef LLVM_SUPPORT_ATOMIC_H +#define LLVM_SUPPORT_ATOMIC_H #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/Support/CFG.h b/include/llvm/Support/CFG.h index f5dc8ea..265b886 100644 --- a/include/llvm/Support/CFG.h +++ b/include/llvm/Support/CFG.h @@ -16,8 +16,8 @@ #define LLVM_SUPPORT_CFG_H #include "llvm/ADT/GraphTraits.h" -#include "llvm/Function.h" -#include "llvm/InstrTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" namespace llvm { @@ -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 ba8adb0..823b43a 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -20,8 +20,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_WIN_COFF_H -#define LLVM_SUPPORT_WIN_COFF_H +#ifndef LLVM_SUPPORT_COFF_H +#define LLVM_SUPPORT_COFF_H #include "llvm/Support/DataTypes.h" #include <cassert> @@ -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 ad8d6d4..92107ac 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -26,11 +26,10 @@ #ifndef LLVM_SUPPORT_CALLSITE_H #define LLVM_SUPPORT_CALLSITE_H -#include "llvm/Attributes.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/BasicBlock.h" -#include "llvm/CallingConv.h" -#include "llvm/Instructions.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/CallingConv.h" +#include "llvm/IR/Instructions.h" namespace llvm { @@ -177,20 +176,20 @@ public: /// getAttributes/setAttributes - get or set the parameter attributes of /// the call. - const AttrListPtr &getAttributes() const { + const AttributeSet &getAttributes() const { CALLSITE_DELEGATE_GETTER(getAttributes()); } - void setAttributes(const AttrListPtr &PAL) { + void setAttributes(const AttributeSet &PAL) { CALLSITE_DELEGATE_SETTER(setAttributes(PAL)); } /// \brief Return true if this function has the given attribute. - bool hasFnAttr(Attributes::AttrVal A) const { + bool hasFnAttr(Attribute::AttrKind A) const { CALLSITE_DELEGATE_GETTER(hasFnAttr(A)); } /// \brief Return true if the call or the callee has the given attribute. - bool paramHasAttr(unsigned i, Attributes::AttrVal A) const { + bool paramHasAttr(unsigned i, Attribute::AttrKind A) const { CALLSITE_DELEGATE_GETTER(paramHasAttr(i, A)); } @@ -244,12 +243,12 @@ public: /// @brief Determine whether this argument is not captured. bool doesNotCapture(unsigned ArgNo) const { - return paramHasAttr(ArgNo + 1, Attributes::NoCapture); + return paramHasAttr(ArgNo + 1, Attribute::NoCapture); } /// @brief Determine whether this argument is passed by value. bool isByValArgument(unsigned ArgNo) const { - return paramHasAttr(ArgNo + 1, Attributes::ByVal); + return paramHasAttr(ArgNo + 1, Attribute::ByVal); } /// hasArgument - Returns true if this CallSite passes the given Value* as an diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index 0c71882..0d2d6c9 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)); } }; @@ -55,8 +59,8 @@ struct isa_impl { /// \brief Always allow upcasts, and perform no dynamic check for them. template <typename To, typename From> struct isa_impl<To, From, - typename llvm::enable_if_c< - llvm::is_base_of<To, From>::value + typename enable_if< + llvm::is_base_of<To, From> >::type > { static inline bool doit(const From &) { return true; } @@ -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,12 +216,29 @@ template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { // cast<Instruction>(myVal)->getParent() // template <class X, class Y> -inline typename cast_retty<X, Y>::ret_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, const Y, + typename simplify_type<const Y>::SimpleType>::doit(Val); +} + +template <class X, class Y> +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); } +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) { + assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); + return cast_convert_val<X, Y*, + typename simplify_type<Y*>::SimpleType>::doit(Val); +} + // cast_or_null<X> - Functionally identical to cast, except that a null value is // accepted. // @@ -230,8 +259,21 @@ inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { // template <class X, class Y> -inline typename cast_retty<X, Y>::ret_type dyn_cast(const Y &Val) { - return isa<X>(Val) ? cast<X, Y>(Val) : 0; +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 cast_retty<X, Y>::ret_type dyn_cast(Y &Val) { + return isa<X>(Val) ? cast<X>(Val) : 0; +} + +template <class X, class Y> +inline typename enable_if< + is_same<Y, typename simplify_type<Y>::SimpleType>, + typename cast_retty<X, Y*>::ret_type +>::type dyn_cast(Y *Val) { + return isa<X>(Val) ? cast<X>(Val) : 0; } // dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 872c579..2e84d7b 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -20,10 +20,10 @@ #ifndef LLVM_SUPPORT_COMMANDLINE_H #define LLVM_SUPPORT_COMMANDLINE_H -#include "llvm/Support/type_traits.h" -#include "llvm/Support/Compiler.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/type_traits.h" #include <cassert> #include <climits> #include <cstdarg> @@ -469,8 +469,7 @@ public: template<class Opt> void apply(Opt &O) const { - for (unsigned i = 0, e = static_cast<unsigned>(Values.size()); - i != e; ++i) + for (size_t i = 0, e = Values.size(); i != e; ++i) O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, Values[i].second.second); } @@ -629,8 +628,7 @@ public: else ArgVal = ArgName; - for (unsigned i = 0, e = static_cast<unsigned>(Values.size()); - i != e; ++i) + for (size_t i = 0, e = Values.size(); i != e; ++i) if (Values[i].Name == ArgVal) { V = Values[i].V.getValue(); return false; @@ -1092,7 +1090,7 @@ public: // Make sure we initialize the value with the default constructor for the // type. - opt_storage() : Value(DataType()) {} + opt_storage() : Value(DataType()), Default(DataType()) {} template<class T> void setValue(const T &V, bool initial = false) { diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 7ceeb32..13d057b 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -15,29 +15,90 @@ #ifndef LLVM_SUPPORT_COMPILER_H #define LLVM_SUPPORT_COMPILER_H +#include "llvm/Config/llvm-config.h" + #ifndef __has_feature # define __has_feature(x) 0 #endif -/// LLVM_HAS_RVALUE_REFERENCES - Does the compiler provide r-value references? +/// \brief Does the compiler support r-value references? /// This implies that <utility> provides the one-argument std::move; it /// does not imply the existence of any other C++ library features. #if (__has_feature(cxx_rvalue_references) \ || defined(__GXX_EXPERIMENTAL_CXX0X__) \ || (defined(_MSC_VER) && _MSC_VER >= 1600)) -#define LLVM_USE_RVALUE_REFERENCES 1 +#define LLVM_HAS_RVALUE_REFERENCES 1 +#else +#define LLVM_HAS_RVALUE_REFERENCES 0 +#endif + +/// \brief Does the compiler support r-value reference *this? +/// +/// Sadly, this is separate from just r-value reference support because GCC +/// implemented everything but this thus far. No release of GCC yet has support +/// for this feature so it is enabled with Clang only. +/// FIXME: This should change to a version check when GCC grows support for it. +#if __has_feature(cxx_rvalue_references) +#define LLVM_HAS_RVALUE_REFERENCE_THIS 1 +#else +#define LLVM_HAS_RVALUE_REFERENCE_THIS 0 +#endif + +/// \macro LLVM_HAS_CXX11_TYPETRAITS +/// \brief Does the compiler have the C++11 type traits. +/// +/// #include <type_traits> +/// +/// * enable_if +/// * {true,false}_type +/// * is_constructible +/// * etc... +#if defined(__GXX_EXPERIMENTAL_CXX0X__) \ + || (defined(_MSC_VER) && _MSC_VER >= 1700) +#define LLVM_HAS_CXX11_TYPETRAITS 1 +#else +#define LLVM_HAS_CXX11_TYPETRAITS 0 +#endif + +/// \macro LLVM_HAS_CXX11_STDLIB +/// \brief Does the compiler have the C++11 standard library. +/// +/// Implies LLVM_HAS_RVALUE_REFERENCES, LLVM_HAS_CXX11_TYPETRAITS +#if defined(__GXX_EXPERIMENTAL_CXX0X__) \ + || (defined(_MSC_VER) && _MSC_VER >= 1700) +#define LLVM_HAS_CXX11_STDLIB 1 #else -#define LLVM_USE_RVALUE_REFERENCES 0 +#define LLVM_HAS_CXX11_STDLIB 0 +#endif + +/// \macro LLVM_HAS_VARIADIC_TEMPLATES +/// \brief Does this compiler support variadic templates. +/// +/// Implies LLVM_HAS_RVALUE_REFERENCES and the existence of std::forward. +#if __has_feature(cxx_variadic_templates) +# define LLVM_HAS_VARIADIC_TEMPLATES 1 +#else +# define LLVM_HAS_VARIADIC_TEMPLATES 0 #endif /// llvm_move - Expands to ::std::move if the compiler supports /// r-value references; otherwise, expands to the argument. -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES #define llvm_move(value) (::std::move(value)) #else #define llvm_move(value) (value) #endif +/// Expands to '&' if r-value references are supported. +/// +/// This can be used to provide l-value/r-value overrides of member functions. +/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS +#if LLVM_HAS_RVALUE_REFERENCE_THIS +#define LLVM_LVALUE_FUNCTION & +#else +#define LLVM_LVALUE_FUNCTION +#endif + /// LLVM_DELETED_FUNCTION - Expands to = delete if the compiler supports it. /// Use to mark functions as uncallable. Member functions with this should /// be declared private so that some behavior is kept in C++03 mode. @@ -59,7 +120,8 @@ /// LLVM_FINAL - Expands to 'final' if the compiler supports it. /// Use to mark classes or virtual methods as final. -#if (__has_feature(cxx_override_control)) +#if __has_feature(cxx_override_control) \ + || (defined(_MSC_VER) && _MSC_VER >= 1700) #define LLVM_FINAL final #else #define LLVM_FINAL @@ -67,12 +129,19 @@ /// LLVM_OVERRIDE - Expands to 'override' if the compiler supports it. /// Use to mark virtual methods as overriding a base class method. -#if (__has_feature(cxx_override_control)) +#if __has_feature(cxx_override_control) \ + || (defined(_MSC_VER) && _MSC_VER >= 1700) #define LLVM_OVERRIDE override #else #define LLVM_OVERRIDE #endif +#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define LLVM_CONSTEXPR constexpr +#else +# define LLVM_CONSTEXPR +#endif + /// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked /// into a shared library, then the class should be private to the library and /// not accessible from outside it. Can also be used to mark variables and @@ -129,7 +198,6 @@ #define LLVM_UNLIKELY(EXPR) (EXPR) #endif - // C++ doesn't support 'extern template' of template specializations. GCC does, // but requires __extension__ before it. In the header, use this: // EXTERN_TEMPLATE_INSTANTIATION(class foo<bar>); @@ -143,8 +211,8 @@ #define TEMPLATE_INSTANTIATION(X) #endif -// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, -// mark a method "not for inlining". +/// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, +/// mark a method "not for inlining". #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) #define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) #elif defined(_MSC_VER) @@ -153,10 +221,10 @@ #define LLVM_ATTRIBUTE_NOINLINE #endif -// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do -// so, mark a method "always inline" because it is performance sensitive. GCC -// 3.4 supported this but is buggy in various cases and produces unimplemented -// errors, just use it in GCC 4.0 and later. +/// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do +/// so, mark a method "always inline" because it is performance sensitive. GCC +/// 3.4 supported this but is buggy in various cases and produces unimplemented +/// errors, just use it in GCC 4.0 and later. #if __GNUC__ > 3 #define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) #elif defined(_MSC_VER) @@ -165,7 +233,6 @@ #define LLVM_ATTRIBUTE_ALWAYS_INLINE #endif - #ifdef __GNUC__ #define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) #elif defined(_MSC_VER) @@ -174,8 +241,8 @@ #define LLVM_ATTRIBUTE_NORETURN #endif -// LLVM_EXTENSION - Support compilers where we have a keyword to suppress -// pedantic diagnostics. +/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress +/// pedantic diagnostics. #ifdef __GNUC__ #define LLVM_EXTENSION __extension__ #else @@ -197,16 +264,18 @@ decl #endif -// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands -// to an expression which states that it is undefined behavior for the -// compiler to reach this point. Otherwise is not defined. +/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands +/// to an expression which states that it is undefined behavior for the +/// compiler to reach this point. Otherwise is not defined. #if defined(__clang__) || (__GNUC__ > 4) \ || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) # define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() +#elif defined(_MSC_VER) +# define LLVM_BUILTIN_UNREACHABLE __assume(false) #endif -// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression -// which causes the program to exit abnormally. +/// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression +/// which causes the program to exit abnormally. #if defined(__clang__) || (__GNUC__ > 4) \ || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) # define LLVM_BUILTIN_TRAP __builtin_trap() @@ -214,4 +283,82 @@ # define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 #endif +/// \macro LLVM_ASSUME_ALIGNED +/// \brief Returns a pointer with an assumed alignment. +#if !defined(__clang__) && ((__GNUC__ > 4) \ + || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) +// FIXME: Enable on clang when it supports it. +# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) +#elif defined(LLVM_BUILTIN_UNREACHABLE) +# define LLVM_ASSUME_ALIGNED(p, a) \ + (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p))) +#else +# define LLVM_ASSUME_ALIGNED(p, a) (p) +#endif + +/// \macro LLVM_FUNCTION_NAME +/// \brief Expands to __func__ on compilers which support it. Otherwise, +/// expands to a compiler-dependent replacement. +#if defined(_MSC_VER) +# define LLVM_FUNCTION_NAME __FUNCTION__ +#else +# define LLVM_FUNCTION_NAME __func__ +#endif + +#if defined(HAVE_SANITIZER_MSAN_INTERFACE_H) +# include <sanitizer/msan_interface.h> +#else +# define __msan_allocated_memory(p, size) +# define __msan_unpoison(p, size) +#endif + +/// \macro LLVM_MEMORY_SANITIZER_BUILD +/// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. +#if __has_feature(memory_sanitizer) +# define LLVM_MEMORY_SANITIZER_BUILD 1 +#else +# define LLVM_MEMORY_SANITIZER_BUILD 0 +#endif + +/// \macro LLVM_ADDRESS_SANITIZER_BUILD +/// \brief Whether LLVM itself is built with AddressSanitizer instrumentation. +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) +# define LLVM_ADDRESS_SANITIZER_BUILD 1 +#else +# define LLVM_ADDRESS_SANITIZER_BUILD 0 +#endif + +/// \macro LLVM_IS_UNALIGNED_ACCESS_FAST +/// \brief Is unaligned memory access fast on the host machine. +/// +/// Don't specialize on alignment for platforms where unaligned memory accesses +/// generates the same code as aligned memory accesses for common types. +#if defined(_M_AMD64) || defined(_M_IX86) || defined(__amd64) || \ + defined(__amd64__) || defined(__x86_64) || defined(__x86_64__) || \ + defined(_X86_) || defined(__i386) || defined(__i386__) +# define LLVM_IS_UNALIGNED_ACCESS_FAST 1 +#else +# define LLVM_IS_UNALIGNED_ACCESS_FAST 0 +#endif + +/// \macro LLVM_EXPLICIT +/// \brief Expands to explicit on compilers which support explicit conversion +/// operators. Otherwise expands to nothing. +#if (__has_feature(cxx_explicit_conversions) \ + || defined(__GXX_EXPERIMENTAL_CXX0X__)) +#define LLVM_EXPLICIT explicit +#else +#define LLVM_EXPLICIT +#endif + +/// \macro LLVM_STATIC_ASSERT +/// \brief Expands to C/C++'s static_assert on compilers which support it. +#if __has_feature(cxx_static_assert) +# define LLVM_STATIC_ASSERT(expr, msg) static_assert(expr, msg) +#elif __has_feature(c_static_assert) +# define LLVM_STATIC_ASSERT(expr, msg) _Static_assert(expr, msg) +#else +# define LLVM_STATIC_ASSERT(expr, msg) +#endif + #endif diff --git a/include/llvm/Support/ConstantFolder.h b/include/llvm/Support/ConstantFolder.h index 93aa343..4aad952 100644 --- a/include/llvm/Support/ConstantFolder.h +++ b/include/llvm/Support/ConstantFolder.h @@ -17,8 +17,8 @@ #ifndef LLVM_SUPPORT_CONSTANTFOLDER_H #define LLVM_SUPPORT_CONSTANTFOLDER_H -#include "llvm/Constants.h" -#include "llvm/InstrTypes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/InstrTypes.h" namespace llvm { diff --git a/include/llvm/Support/ConstantRange.h b/include/llvm/Support/ConstantRange.h index 90dd69f..0f29256 100644 --- a/include/llvm/Support/ConstantRange.h +++ b/include/llvm/Support/ConstantRange.h @@ -29,8 +29,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_CONSTANT_RANGE_H -#define LLVM_SUPPORT_CONSTANT_RANGE_H +#ifndef LLVM_SUPPORT_CONSTANTRANGE_H +#define LLVM_SUPPORT_CONSTANTRANGE_H #include "llvm/ADT/APInt.h" #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h new file mode 100644 index 0000000..1eae6d6 --- /dev/null +++ b/include/llvm/Support/ConvertUTF.h @@ -0,0 +1,228 @@ +/*===--- ConvertUTF.h - Universal Character Names conversions ---------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *==------------------------------------------------------------------------==*/ +/* + * Copyright 2001-2004 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + +/* --------------------------------------------------------------------- + + Conversions between UTF32, UTF-16, and UTF-8. Header file. + + Several funtions are included here, forming a complete set of + conversions between the three formats. UTF-7 is not included + here, but is handled in a separate source file. + + Each of these routines takes pointers to input buffers and output + buffers. The input buffers are const. + + Each routine converts the text between *sourceStart and sourceEnd, + putting the result into the buffer between *targetStart and + targetEnd. Note: the end pointers are *after* the last item: e.g. + *(sourceEnd - 1) is the last item. + + The return result indicates whether the conversion was successful, + and if not, whether the problem was in the source or target buffers. + (Only the first encountered problem is indicated.) + + After the conversion, *sourceStart and *targetStart are both + updated to point to the end of last text successfully converted in + the respective buffers. + + Input parameters: + sourceStart - pointer to a pointer to the source buffer. + The contents of this are modified on return so that + it points at the next thing to be converted. + targetStart - similarly, pointer to pointer to the target buffer. + sourceEnd, targetEnd - respectively pointers to the ends of the + two buffers, for overflow checking only. + + These conversion functions take a ConversionFlags argument. When this + flag is set to strict, both irregular sequences and isolated surrogates + will cause an error. When the flag is set to lenient, both irregular + sequences and isolated surrogates are converted. + + Whether the flag is strict or lenient, all illegal sequences will cause + an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, + or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + must check for illegal sequences. + + When the flag is set to lenient, characters over 0x10FFFF are converted + to the replacement character; otherwise (when the flag is set to strict) + they constitute an error. + + Output parameters: + The value "sourceIllegal" is returned from some routines if the input + sequence is malformed. When "sourceIllegal" is returned, the source + value will point to the illegal value that caused the problem. E.g., + in UTF-8 when a sequence is malformed, it points to the start of the + malformed sequence. + + Author: Mark E. Davis, 1994. + Rev History: Rick McGowan, fixes & updates May 2001. + Fixes & updates, Sept 2001. + +------------------------------------------------------------------------ */ + +#ifndef CLANG_BASIC_CONVERTUTF_H +#define CLANG_BASIC_CONVERTUTF_H + +/* --------------------------------------------------------------------- + The following 4 definitions are compiler-specific. + The C standard does not guarantee that wchar_t has at least + 16 bits, so wchar_t is no less portable than unsigned short! + All should be unsigned values to avoid sign extension during + bit mask & shift operations. +------------------------------------------------------------------------ */ + +typedef unsigned int UTF32; /* at least 32 bits */ +typedef unsigned short UTF16; /* at least 16 bits */ +typedef unsigned char UTF8; /* typically 8 bits */ +typedef unsigned char Boolean; /* 0 or 1 */ + +/* Some fundamental constants */ +#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD +#define UNI_MAX_BMP (UTF32)0x0000FFFF +#define UNI_MAX_UTF16 (UTF32)0x0010FFFF +#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF +#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF + +#define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4 + +typedef enum { + conversionOK, /* conversion successful */ + sourceExhausted, /* partial character in source, but hit end */ + targetExhausted, /* insuff. room in target for conversion */ + sourceIllegal /* source sequence is illegal/malformed */ +} ConversionResult; + +typedef enum { + strictConversion = 0, + lenientConversion +} ConversionFlags; + +/* This is for C++ and does no harm in C */ +#ifdef __cplusplus +extern "C" { +#endif + +ConversionResult ConvertUTF8toUTF16 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF8toUTF32 ( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF8 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF8 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF16toUTF32 ( + const UTF16** sourceStart, const UTF16* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +ConversionResult ConvertUTF32toUTF16 ( + const UTF32** sourceStart, const UTF32* sourceEnd, + UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); + +Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); + +Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd); + +unsigned getNumBytesForUTF8(UTF8 firstByte); + +#ifdef __cplusplus +} + +/*************************************************************************/ +/* Below are LLVM-specific wrappers of the functions above. */ + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +/** + * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on + * WideCharWidth. The converted data is written to ResultPtr, which needs to + * point to at least WideCharWidth * (Source.Size() + 1) bytes. On success, + * ResultPtr will point one after the end of the copied string. On failure, + * ResultPtr will not be changed, and ErrorPtr will be set to the location of + * the first character which could not be converted. + * \return true on success. + */ +bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, + char *&ResultPtr, const UTF8 *&ErrorPtr); + +/** + * Convert an Unicode code point to UTF8 sequence. + * + * \param Source a Unicode code point. + * \param [in,out] ResultPtr pointer to the output buffer, needs to be at least + * \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is + * updated one past end of the converted sequence. + * + * \returns true on success. + */ +bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr); + +/** + * Convert the first UTF8 sequence in the given source buffer to a UTF32 + * code point. + * + * \param [in,out] source A pointer to the source buffer. If the conversion + * succeeds, this pointer will be updated to point to the byte just past the + * end of the converted sequence. + * \param sourceEnd A pointer just past the end of the source buffer. + * \param [out] target The converted code + * \param flags Whether the conversion is strict or lenient. + * + * \returns conversionOK on success + * + * \sa ConvertUTF8toUTF32 + */ +static inline ConversionResult convertUTF8Sequence(const UTF8 **source, + const UTF8 *sourceEnd, + UTF32 *target, + ConversionFlags flags) { + if (*source == sourceEnd) + return sourceExhausted; + unsigned size = getNumBytesForUTF8(**source); + if ((ptrdiff_t)size > sourceEnd - *source) + return sourceExhausted; + return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags); +} +} /* end namespace llvm */ + +#endif + +/* --------------------------------------------------------------------- */ + +#endif diff --git a/include/llvm/Support/DOTGraphTraits.h b/include/llvm/Support/DOTGraphTraits.h index 483f267..95e37c0 100644 --- a/include/llvm/Support/DOTGraphTraits.h +++ b/include/llvm/Support/DOTGraphTraits.h @@ -79,6 +79,11 @@ public: return false; } + template<typename GraphType> + static std::string getNodeDescription(const void *, const GraphType &) { + return ""; + } + /// If you want to specify custom node attributes, this is the place to do so /// template<typename GraphType> diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h index a3ae782..e8a19cd 100644 --- a/include/llvm/Support/DataExtractor.h +++ b/include/llvm/Support/DataExtractor.h @@ -18,22 +18,24 @@ namespace llvm { class DataExtractor { StringRef Data; uint8_t IsLittleEndian; - uint8_t PointerSize; + uint8_t AddressSize; public: /// Construct with a buffer that is owned by the caller. /// /// This constructor allows us to use data that is owned by the /// caller. The data must stay around as long as this object is /// valid. - DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t PointerSize) - : Data(Data), IsLittleEndian(IsLittleEndian), PointerSize(PointerSize) {} + DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize) + : Data(Data), IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {} - /// getData - Get the data pointed to by this extractor. + /// \brief Get the data pointed to by this extractor. StringRef getData() const { return Data; } - /// isLittleEndian - Get the endianess for this extractor. + /// \brief Get the endianess for this extractor. bool isLittleEndian() const { return IsLittleEndian; } - /// getAddressSize - Get the address size for this extractor. - uint8_t getAddressSize() const { return PointerSize; } + /// \brief Get the address size for this extractor. + uint8_t getAddressSize() const { return AddressSize; } + /// \brief Set the address size for this extractor. + void setAddressSize(uint8_t Size) { AddressSize = Size; } /// Extract a C string from \a *offset_ptr. /// @@ -113,7 +115,7 @@ public: /// /// Extract a single pointer from the data and update the offset /// pointed to by \a offset_ptr. The size of the extracted pointer - /// comes from the \a m_addr_size member variable and should be + /// is \a getAddressSize(), so the address size has to be /// set correctly prior to extracting any pointer values. /// /// @param[in,out] offset_ptr @@ -126,7 +128,7 @@ public: /// @return /// The extracted pointer value as a 64 integer. uint64_t getAddress(uint32_t *offset_ptr) const { - return getUnsigned(offset_ptr, PointerSize); + return getUnsigned(offset_ptr, AddressSize); } /// Extract a uint8_t value from \a *offset_ptr. diff --git a/include/llvm/Support/DataFlow.h b/include/llvm/Support/DataFlow.h index 355c402..a09ccaa 100644 --- a/include/llvm/Support/DataFlow.h +++ b/include/llvm/Support/DataFlow.h @@ -14,8 +14,8 @@ #ifndef LLVM_SUPPORT_DATAFLOW_H #define LLVM_SUPPORT_DATAFLOW_H -#include "llvm/User.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/IR/User.h" namespace llvm { diff --git a/include/llvm/Support/DataStream.h b/include/llvm/Support/DataStream.h index fedb0c9..8bc4133 100644 --- a/include/llvm/Support/DataStream.h +++ b/include/llvm/Support/DataStream.h @@ -14,8 +14,8 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_DATASTREAM_H_ -#define LLVM_SUPPORT_DATASTREAM_H_ +#ifndef LLVM_SUPPORT_DATASTREAM_H +#define LLVM_SUPPORT_DATASTREAM_H #include <string> diff --git a/include/llvm/Support/DebugLoc.h b/include/llvm/Support/DebugLoc.h index 0498075..f35d407 100644 --- a/include/llvm/Support/DebugLoc.h +++ b/include/llvm/Support/DebugLoc.h @@ -9,7 +9,7 @@ // // This file defines a number of light weight data structures used // to describe and track debug location information. -// +// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_DEBUGLOC_H @@ -19,7 +19,7 @@ namespace llvm { template <typename T> struct DenseMapInfo; class MDNode; class LLVMContext; - + /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, /// and MachineInstr to compactly encode file/line/scope information for an /// operation. @@ -46,18 +46,18 @@ namespace llvm { /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 /// for either means unknown. unsigned LineCol; - + /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information, /// decoded by LLVMContext. 0 is unknown. int ScopeIdx; public: DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown. - + /// get - Get a new DebugLoc that corresponds to the specified line/col /// scope/inline location. static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, MDNode *InlinedAt = 0); - + /// getFromDILocation - Translate the DILocation quad into a DebugLoc. static DebugLoc getFromDILocation(MDNode *N); @@ -66,32 +66,32 @@ namespace llvm { /// isUnknown - Return true if this is an unknown location. bool isUnknown() const { return ScopeIdx == 0; } - + unsigned getLine() const { return (LineCol << 8) >> 8; // Mask out column. } - + unsigned getCol() const { return LineCol >> 24; } - + /// getScope - This returns the scope pointer for this DebugLoc, or null if /// invalid. MDNode *getScope(const LLVMContext &Ctx) const; - + /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or /// null if invalid or not present. MDNode *getInlinedAt(const LLVMContext &Ctx) const; - + /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, const LLVMContext &Ctx) const; - - + + /// getAsMDNode - This method converts the compressed DebugLoc node into a /// DILocation compatible MDNode. MDNode *getAsMDNode(const LLVMContext &Ctx) const; - + bool operator==(const DebugLoc &DL) const { return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx; } @@ -109,4 +109,4 @@ namespace llvm { }; } // end namespace llvm -#endif /* LLVM_DEBUGLOC_H */ +#endif /* LLVM_SUPPORT_DEBUGLOC_H */ diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index 8f18a99..b52914f 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -16,6 +16,9 @@ #ifndef LLVM_SUPPORT_DWARF_H #define LLVM_SUPPORT_DWARF_H +#include "llvm/Support/DataTypes.h" + + namespace llvm { //===----------------------------------------------------------------------===// @@ -37,7 +40,7 @@ enum { namespace dwarf { //===----------------------------------------------------------------------===// -// Dwarf constants as gleaned from the DWARF Debugging Information Format V.3 +// Dwarf constants as gleaned from the DWARF Debugging Information Format V.4 // reference manual http://dwarf.freestandards.org . // @@ -50,15 +53,19 @@ enum llvm_dwarf_constants { DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. DW_TAG_arg_variable = 0x101, // Tag for argument variables. - DW_TAG_return_variable = 0x102, // Tag for return variables. - DW_TAG_vector_type = 0x103, // Tag for vector types. DW_TAG_user_base = 0x1000, // Recommended base for user tags. - DW_CIE_VERSION = 1, // Common frame information version. - DW_CIE_ID = 0xffffffff // Common frame information mark. + DW_CIE_VERSION = 1 // Common frame information version. }; + +// Special ID values that distinguish a CIE from a FDE in DWARF CFI. +// Not inside an enum because a 64-bit value is needed. +const uint32_t DW_CIE_ID = UINT32_MAX; +const uint64_t DW64_CIE_ID = UINT64_MAX; + + enum dwarf_constants { DWARF_VERSION = 2, @@ -231,6 +238,10 @@ enum dwarf_constants { DW_AT_const_expr = 0x6c, DW_AT_enum_class = 0x6d, DW_AT_linkage_name = 0x6e, + + DW_AT_lo_user = 0x2000, + DW_AT_hi_user = 0x3fff, + DW_AT_MIPS_loop_begin = 0x2002, DW_AT_MIPS_tail_loop_begin = 0x2003, DW_AT_MIPS_epilog_begin = 0x2004, @@ -246,6 +257,12 @@ enum dwarf_constants { DW_AT_MIPS_ptr_dopetype = 0x200e, DW_AT_MIPS_allocatable_dopetype = 0x200f, DW_AT_MIPS_assumed_shape_dopetype = 0x2010, + + // This one appears to have only been implemented by Open64 for + // fortran and may conflict with other extensions. + DW_AT_MIPS_assumed_size = 0x2011, + + // GNU extensions DW_AT_sf_names = 0x2101, DW_AT_src_info = 0x2102, DW_AT_mac_info = 0x2103, @@ -254,9 +271,14 @@ enum dwarf_constants { DW_AT_body_end = 0x2106, DW_AT_GNU_vector = 0x2107, DW_AT_GNU_template_name = 0x2110, - DW_AT_MIPS_assumed_size = 0x2011, - DW_AT_lo_user = 0x2000, - DW_AT_hi_user = 0x3fff, + + // Extensions for Fission proposal. + DW_AT_GNU_dwo_name = 0x2130, + DW_AT_GNU_dwo_id = 0x2131, + DW_AT_GNU_ranges_base = 0x2132, + DW_AT_GNU_addr_base = 0x2133, + DW_AT_GNU_pubnames = 0x2134, + DW_AT_GNU_pubtypes = 0x2135, // Apple extensions. DW_AT_APPLE_optimized = 0x3fe1, @@ -300,6 +322,10 @@ enum dwarf_constants { DW_FORM_flag_present = 0x19, DW_FORM_ref_sig8 = 0x20, + // Extensions for Fission proposal + DW_FORM_GNU_addr_index = 0x1f01, + DW_FORM_GNU_str_index = 0x1f02, + // Operation encodings DW_OP_addr = 0x03, DW_OP_deref = 0x06, @@ -458,6 +484,10 @@ enum dwarf_constants { DW_OP_lo_user = 0xe0, DW_OP_hi_user = 0xff, + // Extensions for Fission proposal. + DW_OP_GNU_addr_index = 0xfb, + DW_OP_GNU_const_index = 0xfc, + // Encoding attribute values DW_ATE_address = 0x01, DW_ATE_boolean = 0x02, diff --git a/include/llvm/Support/DynamicLibrary.h b/include/llvm/Support/DynamicLibrary.h index 0f59cbf..1e2d16c 100644 --- a/include/llvm/Support/DynamicLibrary.h +++ b/include/llvm/Support/DynamicLibrary.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_DYNAMIC_LIBRARY_H -#define LLVM_SYSTEM_DYNAMIC_LIBRARY_H +#ifndef LLVM_SYSTEM_DYNAMICLIBRARY_H +#define LLVM_SYSTEM_DYNAMICLIBRARY_H #include <string> diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 2cd2671..ea597fc 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -271,6 +271,7 @@ enum { EM_SLE9X = 179, // Infineon Technologies SLE9X core EM_L10M = 180, // Intel L10M EM_K10M = 181, // Intel K10M + EM_AARCH64 = 183, // ARM AArch64 EM_AVR32 = 185, // Atmel Corporation 32-bit microprocessor family EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller EM_TILE64 = 187, // Tilera TILE64 multicore architecture family @@ -366,7 +367,8 @@ enum { R_X86_64_SIZE64 = 33, R_X86_64_GOTPC32_TLSDESC = 34, R_X86_64_TLSDESC_CALL = 35, - R_X86_64_TLSDESC = 36 + R_X86_64_TLSDESC = 36, + R_X86_64_IRELATIVE = 37 }; // i386 relocations. @@ -464,20 +466,140 @@ enum { // ELF Relocation types for PPC64 enum { + R_PPC64_ADDR32 = 1, R_PPC64_ADDR16_LO = 4, R_PPC64_ADDR16_HI = 5, R_PPC64_ADDR14 = 7, R_PPC64_REL24 = 10, + R_PPC64_REL32 = 26, R_PPC64_ADDR64 = 38, R_PPC64_ADDR16_HIGHER = 39, R_PPC64_ADDR16_HIGHEST = 41, + R_PPC64_REL64 = 44, R_PPC64_TOC16 = 47, + R_PPC64_TOC16_LO = 48, + R_PPC64_TOC16_HA = 50, R_PPC64_TOC = 51, - R_PPC64_TOC16_DS = 63 + 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_DTPREL16_LO = 75, + R_PPC64_DTPREL16_HA = 77, + R_PPC64_GOT_TLSGD16_LO = 80, + R_PPC64_GOT_TLSGD16_HA = 82, + R_PPC64_GOT_TLSLD16_LO = 84, + R_PPC64_GOT_TLSLD16_HA = 86, + R_PPC64_GOT_TPREL16_LO_DS = 88, + R_PPC64_GOT_TPREL16_HA = 90, + R_PPC64_TLSGD = 107, + R_PPC64_TLSLD = 108 +}; + +// ELF Relocation types for AArch64 + +enum { + R_AARCH64_NONE = 0x100, + + R_AARCH64_ABS64 = 0x101, + R_AARCH64_ABS32 = 0x102, + R_AARCH64_ABS16 = 0x103, + R_AARCH64_PREL64 = 0x104, + R_AARCH64_PREL32 = 0x105, + R_AARCH64_PREL16 = 0x106, + + R_AARCH64_MOVW_UABS_G0 = 0x107, + R_AARCH64_MOVW_UABS_G0_NC = 0x108, + R_AARCH64_MOVW_UABS_G1 = 0x109, + R_AARCH64_MOVW_UABS_G1_NC = 0x10a, + R_AARCH64_MOVW_UABS_G2 = 0x10b, + R_AARCH64_MOVW_UABS_G2_NC = 0x10c, + R_AARCH64_MOVW_UABS_G3 = 0x10d, + R_AARCH64_MOVW_SABS_G0 = 0x10e, + R_AARCH64_MOVW_SABS_G1 = 0x10f, + R_AARCH64_MOVW_SABS_G2 = 0x110, + + R_AARCH64_LD_PREL_LO19 = 0x111, + R_AARCH64_ADR_PREL_LO21 = 0x112, + R_AARCH64_ADR_PREL_PG_HI21 = 0x113, + R_AARCH64_ADD_ABS_LO12_NC = 0x115, + R_AARCH64_LDST8_ABS_LO12_NC = 0x116, + + R_AARCH64_TSTBR14 = 0x117, + R_AARCH64_CONDBR19 = 0x118, + R_AARCH64_JUMP26 = 0x11a, + R_AARCH64_CALL26 = 0x11b, + + R_AARCH64_LDST16_ABS_LO12_NC = 0x11c, + R_AARCH64_LDST32_ABS_LO12_NC = 0x11d, + R_AARCH64_LDST64_ABS_LO12_NC = 0x11e, + + R_AARCH64_LDST128_ABS_LO12_NC = 0x12b, + + R_AARCH64_ADR_GOT_PAGE = 0x137, + R_AARCH64_LD64_GOT_LO12_NC = 0x138, + + R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 0x20b, + R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 0x20c, + R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 0x20d, + R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 0x20e, + R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 0x20f, + R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 0x210, + R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 0x211, + R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 0x212, + R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 0x213, + R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 0x214, + R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 0x215, + R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 0x216, + R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 0x217, + R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 0x218, + R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 0x219, + R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 0x21a, + + R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 0x21b, + R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 0x21c, + R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 0x21d, + R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 0x21e, + R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 0x21f, + + R_AARCH64_TLSLE_MOVW_TPREL_G2 = 0x220, + R_AARCH64_TLSLE_MOVW_TPREL_G1 = 0x221, + R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 0x222, + R_AARCH64_TLSLE_MOVW_TPREL_G0 = 0x223, + R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 0x224, + R_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x225, + R_AARCH64_TLSLE_ADD_TPREL_LO12 = 0x226, + R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x227, + R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 0x228, + R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 0x229, + R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 0x22a, + R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 0x22b, + R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 0x22c, + R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 0x22d, + R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 0x22e, + R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 0x22f, + + R_AARCH64_TLSDESC_ADR_PAGE = 0x232, + R_AARCH64_TLSDESC_LD64_LO12_NC = 0x233, + R_AARCH64_TLSDESC_ADD_LO12_NC = 0x234, + + R_AARCH64_TLSDESC_CALL = 0x239 }; // ARM Specific e_flags -enum { EF_ARM_EABIMASK = 0xFF000000U }; +enum { + EF_ARM_SOFT_FLOAT = 0x00000200U, + EF_ARM_VFP_FLOAT = 0x00000400U, + EF_ARM_EABI_UNKNOWN = 0x00000000U, + EF_ARM_EABI_VER1 = 0x01000000U, + EF_ARM_EABI_VER2 = 0x02000000U, + EF_ARM_EABI_VER3 = 0x03000000U, + EF_ARM_EABI_VER4 = 0x04000000U, + EF_ARM_EABI_VER5 = 0x05000000U, + EF_ARM_EABIMASK = 0xFF000000U +}; // ELF Relocation types for ARM // Meets 2.08 ABI Specs. @@ -621,6 +743,13 @@ enum { EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions EF_MIPS_PIC = 0x00000002, // Position independent code EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code + EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI + + //ARCH_ASE + EF_MIPS_MICROMIPS = 0x02000000, // microMIPS + EF_MIPS_ARCH_ASE_M16 = + 0x04000000, // Has Mips-16 ISA extensions + //ARCH EF_MIPS_ARCH_1 = 0x00000000, // MIPS1 instruction set EF_MIPS_ARCH_2 = 0x10000000, // MIPS2 instruction set EF_MIPS_ARCH_3 = 0x20000000, // MIPS3 instruction set @@ -691,6 +820,11 @@ enum { R_MIPS_NUM = 218 }; +// Special values for the st_other field in the symbol table entry for MIPS. +enum { + STO_MIPS_MICROMIPS = 0x80 // MIPS Specific ISA for MicroMips +}; + // Hexagon Specific e_flags // Release 5 ABI enum { @@ -710,14 +844,14 @@ enum { }; // Hexagon specific Section indexes for common small data -// Release 5 ABI +// Release 5 ABI enum { SHN_HEXAGON_SCOMMON = 0xff00, // Other access sizes SHN_HEXAGON_SCOMMON_1 = 0xff01, // Byte-sized access SHN_HEXAGON_SCOMMON_2 = 0xff02, // Half-word-sized access SHN_HEXAGON_SCOMMON_4 = 0xff03, // Word-sized access SHN_HEXAGON_SCOMMON_8 = 0xff04 // Double-word-size access -}; +}; // ELF Relocation types for Hexagon // Release 5 ABI @@ -878,7 +1012,7 @@ enum { SHT_GNU_verneed = 0x6ffffffe, // GNU version references. SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. - SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type. + SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. // Fixme: All this is duplicated in MCSectionELF. Why?? // Exception Index table SHT_ARM_EXIDX = 0x70000001U, @@ -888,10 +1022,14 @@ enum { SHT_ARM_ATTRIBUTES = 0x70000003U, SHT_ARM_DEBUGOVERLAY = 0x70000004U, SHT_ARM_OVERLAYSECTION = 0x70000005U, - + SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in + // this section based on their sizes SHT_X86_64_UNWIND = 0x70000001, // Unwind information - SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type. + SHT_MIPS_REGINFO = 0x70000006, // Register usage information + SHT_MIPS_OPTIONS = 0x7000000d, // General options + + SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. SHT_HIUSER = 0xffffffff // Highest type reserved for applications. }; @@ -953,7 +1091,14 @@ enum { // sets this flag besides being able to refer to data in a section that does // not set it; likewise, a small code model object can refer only to code in a // section that does not set this flag. - SHF_X86_64_LARGE = 0x10000000 + SHF_X86_64_LARGE = 0x10000000, + + // All sections with the GPREL flag are grouped into a global data area + // for faster accesses + SHF_HEX_GPREL = 0x10000000, + + // Do not strip this section. FIXME: We need target specific SHF_ enums. + SHF_MIPS_NOSTRIP = 0x8000000 }; // Section Group Flags @@ -988,7 +1133,7 @@ struct Elf64_Sym { Elf64_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 - Elf64_Half st_shndx; // Which section (header table index) it's defined in + Elf64_Half st_shndx; // Which section (header tbl index) it's defined in Elf64_Addr st_value; // Value or address associated with the symbol Elf64_Xword st_size; // Size of the symbol @@ -1043,6 +1188,11 @@ enum { STV_PROTECTED = 3 // Visible in other components but not preemptable }; +// Symbol number. +enum { + STN_UNDEF = 0 +}; + // Relocation entry, without explicit addend. struct Elf32_Rel { Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) @@ -1083,14 +1233,14 @@ struct Elf64_Rel { // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: - Elf64_Xword getSymbol() const { return (r_info >> 32); } - unsigned char getType() const { - return (unsigned char) (r_info & 0xffffffffL); + Elf64_Word getSymbol() const { return (r_info >> 32); } + Elf64_Word getType() const { + return (Elf64_Word) (r_info & 0xffffffffL); } - void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(Elf64_Xword s, unsigned char t) { - r_info = (s << 32) + (t&0xffffffffL); + void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } + void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf64_Word s, Elf64_Word t) { + r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); } }; @@ -1102,14 +1252,14 @@ struct Elf64_Rela { // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: - Elf64_Xword getSymbol() const { return (r_info >> 32); } - unsigned char getType() const { - return (unsigned char) (r_info & 0xffffffffL); + Elf64_Word getSymbol() const { return (r_info >> 32); } + Elf64_Word getType() const { + return (Elf64_Word) (r_info & 0xffffffffL); } - void setSymbol(Elf64_Xword s) { setSymbolAndType(s, getType()); } - void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } - void setSymbolAndType(Elf64_Xword s, unsigned char t) { - r_info = (s << 32) + (t&0xffffffffL); + void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } + void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf64_Word s, Elf64_Word t) { + r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); } }; @@ -1131,7 +1281,7 @@ struct Elf64_Phdr { Elf64_Word p_flags; // Segment flags Elf64_Off p_offset; // File offset where segment is located, in bytes Elf64_Addr p_vaddr; // Virtual address of beginning of segment - Elf64_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf64_Addr p_paddr; // Physical addr of beginning of segment (OS-specific) Elf64_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) Elf64_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) Elf64_Xword p_align; // Segment alignment constraint @@ -1162,7 +1312,7 @@ enum { PT_GNU_RELRO = 0x6474e552, // Read-only after relocation. // ARM program header types. - PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility information + PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info // These all contain stack unwind tables. PT_ARM_EXIDX = 0x70000001, PT_ARM_UNWIND = 0x70000001 diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 8d5649d..d438fac 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -14,136 +14,78 @@ #ifndef LLVM_SUPPORT_ENDIAN_H #define LLVM_SUPPORT_ENDIAN_H +#include "llvm/Support/AlignOf.h" #include "llvm/Support/Host.h" #include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/type_traits.h" namespace llvm { namespace support { +enum endianness {big, little, native}; -enum endianness {big, little}; -enum alignment {unaligned, aligned}; +// These are named values for common alignments. +enum {aligned = 0, unaligned = 1}; namespace detail { - -template<typename value_type, alignment align> -struct alignment_access_helper; - -template<typename value_type> -struct alignment_access_helper<value_type, aligned> -{ - value_type val; -}; - -// Provides unaligned loads and stores. -#pragma pack(push) -#pragma pack(1) -template<typename value_type> -struct alignment_access_helper<value_type, unaligned> -{ - value_type val; -}; -#pragma pack(pop) - + /// \brief ::value is either alignment, or alignof(T) if alignment is 0. + template<class T, int alignment> + struct PickAlignment { + enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment}; + }; } // end namespace detail namespace endian { - template<typename value_type, alignment align> - inline value_type read_le(const void *memory) { - value_type t = - reinterpret_cast<const detail::alignment_access_helper - <value_type, align> *>(memory)->val; - if (sys::isBigEndianHost()) - return sys::SwapByteOrder(t); - return t; - } - - template<typename value_type, alignment align> - inline void write_le(void *memory, value_type value) { - if (sys::isBigEndianHost()) - value = sys::SwapByteOrder(value); - reinterpret_cast<detail::alignment_access_helper<value_type, align> *> - (memory)->val = value; - } +template<typename value_type, endianness endian> +inline value_type byte_swap(value_type value) { + if (endian != native && sys::isBigEndianHost() != (endian == big)) + return sys::SwapByteOrder(value); + return value; +} - template<typename value_type, alignment align> - inline value_type read_be(const void *memory) { - value_type t = - reinterpret_cast<const detail::alignment_access_helper - <value_type, align> *>(memory)->val; - if (sys::isLittleEndianHost()) - return sys::SwapByteOrder(t); - return t; - } +template<typename value_type, + endianness endian, + std::size_t alignment> +inline value_type read(const void *memory) { + value_type ret; + + memcpy(&ret, + LLVM_ASSUME_ALIGNED(memory, + (detail::PickAlignment<value_type, alignment>::value)), + sizeof(value_type)); + return byte_swap<value_type, endian>(ret); +} - template<typename value_type, alignment align> - inline void write_be(void *memory, value_type value) { - if (sys::isLittleEndianHost()) - value = sys::SwapByteOrder(value); - reinterpret_cast<detail::alignment_access_helper<value_type, align> *> - (memory)->val = value; - } +template<typename value_type, + endianness endian, + std::size_t alignment> +inline void write(void *memory, value_type value) { + value = byte_swap<value_type, endian>(value); + memcpy(LLVM_ASSUME_ALIGNED(memory, + (detail::PickAlignment<value_type, alignment>::value)), + &value, + sizeof(value_type)); } +} // end namespace endian namespace detail { - template<typename value_type, endianness endian, - alignment align> -class packed_endian_specific_integral; - -template<typename value_type> -class packed_endian_specific_integral<value_type, little, unaligned> { -public: - operator value_type() const { - return endian::read_le<value_type, unaligned>(Value); - } - void operator=(value_type newValue) { - endian::write_le<value_type, unaligned>((void *)&Value, newValue); - } -private: - uint8_t Value[sizeof(value_type)]; -}; - -template<typename value_type> -class packed_endian_specific_integral<value_type, big, unaligned> { -public: + std::size_t alignment> +struct packed_endian_specific_integral { operator value_type() const { - return endian::read_be<value_type, unaligned>(Value); + return endian::read<value_type, endian, alignment>( + (const void*)Value.buffer); } - void operator=(value_type newValue) { - endian::write_be<value_type, unaligned>((void *)&Value, newValue); - } -private: - uint8_t Value[sizeof(value_type)]; -}; -template<typename value_type> -class packed_endian_specific_integral<value_type, little, aligned> { -public: - operator value_type() const { - return endian::read_le<value_type, aligned>(&Value); - } void operator=(value_type newValue) { - endian::write_le<value_type, aligned>((void *)&Value, newValue); + endian::write<value_type, endian, alignment>( + (void*)Value.buffer, newValue); } -private: - value_type Value; -}; -template<typename value_type> -class packed_endian_specific_integral<value_type, big, aligned> { -public: - operator value_type() const { - return endian::read_be<value_type, aligned>(&Value); - } - void operator=(value_type newValue) { - endian::write_be<value_type, aligned>((void *)&Value, newValue); - } private: - value_type Value; + AlignedCharArray<PickAlignment<value_type, alignment>::value, + sizeof(value_type)> Value; }; - } // end namespace detail typedef detail::packed_endian_specific_integral @@ -218,6 +160,19 @@ typedef detail::packed_endian_specific_integral typedef detail::packed_endian_specific_integral <int64_t, big, aligned> aligned_big64_t; +typedef detail::packed_endian_specific_integral + <uint16_t, native, unaligned> unaligned_uint16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, native, unaligned> unaligned_uint32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, native, unaligned> unaligned_uint64_t; + +typedef detail::packed_endian_specific_integral + <int16_t, native, unaligned> unaligned_int16_t; +typedef detail::packed_endian_specific_integral + <int32_t, native, unaligned> unaligned_int32_t; +typedef detail::packed_endian_specific_integral + <int64_t, native, unaligned> unaligned_int64_t; } // end namespace llvm } // end namespace support diff --git a/include/llvm/Support/Errno.h b/include/llvm/Support/Errno.h index 150bdb7..8e145c7 100644 --- a/include/llvm/Support/Errno.h +++ b/include/llvm/Support/Errno.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_ERRNO_H -#define LLVM_SYSTEM_ERRNO_H +#ifndef LLVM_SUPPORT_ERRNO_H +#define LLVM_SUPPORT_ERRNO_H #include <string> diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h index 95b0109..b948d97 100644 --- a/include/llvm/Support/ErrorHandling.h +++ b/include/llvm/Support/ErrorHandling.h @@ -15,8 +15,8 @@ #ifndef LLVM_SUPPORT_ERRORHANDLING_H #define LLVM_SUPPORT_ERRORHANDLING_H -#include "llvm/Support/Compiler.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include <string> namespace llvm { @@ -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/ErrorOr.h b/include/llvm/Support/ErrorOr.h new file mode 100644 index 0000000..f3ac305 --- /dev/null +++ b/include/llvm/Support/ErrorOr.h @@ -0,0 +1,514 @@ +//===- llvm/Support/ErrorOr.h - Error Smart Pointer -----------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// +/// Provides ErrorOr<T> smart pointer. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERROR_OR_H +#define LLVM_SUPPORT_ERROR_OR_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/system_error.h" +#include "llvm/Support/type_traits.h" + +#include <cassert> +#if LLVM_HAS_CXX11_TYPETRAITS +#include <type_traits> +#endif + +namespace llvm { +struct ErrorHolderBase { + error_code Error; + uint16_t RefCount; + bool HasUserData; + + ErrorHolderBase() : RefCount(1) {} + + void aquire() { + ++RefCount; + } + + void release() { + if (--RefCount == 0) + delete this; + } + +protected: + virtual ~ErrorHolderBase() {} +}; + +template<class T> +struct ErrorHolder : ErrorHolderBase { +#if LLVM_HAS_RVALUE_REFERENCES + ErrorHolder(T &&UD) : UserData(llvm_move(UD)) {} +#else + ErrorHolder(T &UD) : UserData(UD) {} +#endif + T UserData; +}; + +template<class Tp> struct ErrorOrUserDataTraits : llvm::false_type {}; + +#if LLVM_HAS_CXX11_TYPETRAITS && LLVM_HAS_RVALUE_REFERENCES +template<class T, class V> +typename std::enable_if< std::is_constructible<T, V>::value + , typename std::remove_reference<V>::type>::type && + moveIfMoveConstructible(V &Val) { + return std::move(Val); +} + +template<class T, class V> +typename std::enable_if< !std::is_constructible<T, V>::value + , typename std::remove_reference<V>::type>::type & +moveIfMoveConstructible(V &Val) { + return Val; +} +#else +template<class T, class V> +V &moveIfMoveConstructible(V &Val) { + return Val; +} +#endif + +/// \brief Stores a reference that can be changed. +template <typename T> +class ReferenceStorage { + T *Storage; + +public: + ReferenceStorage(T &Ref) : Storage(&Ref) {} + + operator T &() const { return *Storage; } + T &get() const { return *Storage; } +}; + +/// \brief Represents either an error or a value T. +/// +/// ErrorOr<T> is a pointer-like class that represents the result of an +/// operation. The result is either an error, or a value of type T. This is +/// designed to emulate the usage of returning a pointer where nullptr indicates +/// failure. However instead of just knowing that the operation failed, we also +/// have an error_code and optional user data that describes why it failed. +/// +/// It is used like the following. +/// \code +/// ErrorOr<Buffer> getBuffer(); +/// void handleError(error_code ec); +/// +/// auto buffer = getBuffer(); +/// if (!buffer) +/// handleError(buffer); +/// buffer->write("adena"); +/// \endcode +/// +/// ErrorOr<T> also supports user defined data for specific error_codes. To use +/// this feature you must first add a template specialization of +/// ErrorOrUserDataTraits derived from std::true_type for your type in the lld +/// namespace. This specialization must have a static error_code error() +/// function that returns the error_code this data is used with. +/// +/// getError<UserData>() may be called to get either the stored user data, or +/// a default constructed UserData if none was stored. +/// +/// Example: +/// \code +/// struct InvalidArgError { +/// InvalidArgError() {} +/// InvalidArgError(std::string S) : ArgName(S) {} +/// std::string ArgName; +/// }; +/// +/// namespace llvm { +/// template<> +/// struct ErrorOrUserDataTraits<InvalidArgError> : std::true_type { +/// static error_code error() { +/// return make_error_code(errc::invalid_argument); +/// } +/// }; +/// } // end namespace llvm +/// +/// using namespace llvm; +/// +/// ErrorOr<int> foo() { +/// return InvalidArgError("adena"); +/// } +/// +/// int main() { +/// auto a = foo(); +/// if (!a && error_code(a) == errc::invalid_argument) +/// llvm::errs() << a.getError<InvalidArgError>().ArgName << "\n"; +/// } +/// \endcode +/// +/// An implicit conversion to bool provides a way to check if there was an +/// error. The unary * and -> operators provide pointer like access to the +/// value. Accessing the value when there is an error has undefined behavior. +/// +/// When T is a reference type the behaivor is slightly different. The reference +/// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and +/// there is special handling to make operator -> work as if T was not a +/// reference. +/// +/// T cannot be a rvalue reference. +template<class T> +class ErrorOr { + template <class OtherT> friend class ErrorOr; + static const bool isRef = is_reference<T>::value; + typedef ReferenceStorage<typename remove_reference<T>::type> wrap; + +public: + typedef typename + conditional< isRef + , wrap + , T + >::type storage_type; + +private: + typedef typename remove_reference<T>::type &reference; + typedef typename remove_reference<T>::type *pointer; + +public: + ErrorOr() : IsValid(false) {} + + template <class E> + ErrorOr(E ErrorCode, typename enable_if_c<is_error_code_enum<E>::value || + is_error_condition_enum<E>::value, + void *>::type = 0) + : HasError(true), IsValid(true) { + Error = new ErrorHolderBase; + Error->Error = make_error_code(ErrorCode); + Error->HasUserData = false; + } + + ErrorOr(llvm::error_code EC) : HasError(true), IsValid(true) { + Error = new ErrorHolderBase; + Error->Error = EC; + Error->HasUserData = false; + } + + template<class UserDataT> + ErrorOr(UserDataT UD, typename + enable_if_c<ErrorOrUserDataTraits<UserDataT>::value>::type* = 0) + : HasError(true), IsValid(true) { + Error = new ErrorHolder<UserDataT>(llvm_move(UD)); + Error->Error = ErrorOrUserDataTraits<UserDataT>::error(); + Error->HasUserData = true; + } + + ErrorOr(T Val) : HasError(false), IsValid(true) { + new (get()) storage_type(moveIfMoveConstructible<storage_type>(Val)); + } + + ErrorOr(const ErrorOr &Other) : IsValid(false) { + copyConstruct(Other); + } + + template <class OtherT> + ErrorOr(const ErrorOr<OtherT> &Other) : IsValid(false) { + copyConstruct(Other); + } + + ErrorOr &operator =(const ErrorOr &Other) { + copyAssign(Other); + return *this; + } + + template <class OtherT> + ErrorOr &operator =(const ErrorOr<OtherT> &Other) { + copyAssign(Other); + return *this; + } + +#if LLVM_HAS_RVALUE_REFERENCES + ErrorOr(ErrorOr &&Other) : IsValid(false) { + moveConstruct(std::move(Other)); + } + + template <class OtherT> + ErrorOr(ErrorOr<OtherT> &&Other) : IsValid(false) { + moveConstruct(std::move(Other)); + } + + ErrorOr &operator =(ErrorOr &&Other) { + moveAssign(std::move(Other)); + return *this; + } + + template <class OtherT> + ErrorOr &operator =(ErrorOr<OtherT> &&Other) { + moveAssign(std::move(Other)); + return *this; + } +#endif + + ~ErrorOr() { + if (!IsValid) + return; + if (HasError) + Error->release(); + else + get()->~storage_type(); + } + + template<class ET> + ET getError() const { + assert(IsValid && "Cannot get the error of a default constructed ErrorOr!"); + assert(HasError && "Cannot get an error if none exists!"); + assert(ErrorOrUserDataTraits<ET>::error() == Error->Error && + "Incorrect user error data type for error!"); + if (!Error->HasUserData) + return ET(); + return reinterpret_cast<const ErrorHolder<ET>*>(Error)->UserData; + } + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + /// \brief Return false if there is an error. + operator unspecified_bool_type() const { + assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); + return HasError ? 0 : unspecified_bool_true; + } + + operator llvm::error_code() const { + assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); + return HasError ? Error->Error : llvm::error_code::success(); + } + + pointer operator ->() { + return toPointer(get()); + } + + reference operator *() { + return *get(); + } + +private: + template <class OtherT> + void copyConstruct(const ErrorOr<OtherT> &Other) { + // Construct an invalid ErrorOr if other is invalid. + if (!Other.IsValid) + return; + IsValid = true; + if (!Other.HasError) { + // Get the other value. + HasError = false; + new (get()) storage_type(*Other.get()); + } else { + // Get other's error. + Error = Other.Error; + HasError = true; + Error->aquire(); + } + } + + template <class T1> + static bool compareThisIfSameType(const T1 &a, const T1 &b) { + return &a == &b; + } + + template <class T1, class T2> + static bool compareThisIfSameType(const T1 &a, const T2 &b) { + return false; + } + + template <class OtherT> + void copyAssign(const ErrorOr<OtherT> &Other) { + if (compareThisIfSameType(*this, Other)) + return; + + this->~ErrorOr(); + new (this) ErrorOr(Other); + } + +#if LLVM_HAS_RVALUE_REFERENCES + template <class OtherT> + void moveConstruct(ErrorOr<OtherT> &&Other) { + // Construct an invalid ErrorOr if other is invalid. + if (!Other.IsValid) + return; + IsValid = true; + if (!Other.HasError) { + // Get the other value. + HasError = false; + new (get()) storage_type(std::move(*Other.get())); + // Tell other not to do any destruction. + Other.IsValid = false; + } else { + // Get other's error. + Error = Other.Error; + HasError = true; + // Tell other not to do any destruction. + Other.IsValid = false; + } + } + + template <class OtherT> + void moveAssign(ErrorOr<OtherT> &&Other) { + if (compareThisIfSameType(*this, Other)) + return; + + this->~ErrorOr(); + new (this) ErrorOr(std::move(Other)); + } +#endif + + pointer toPointer(pointer Val) { + return Val; + } + + pointer toPointer(wrap *Val) { + return &Val->get(); + } + + storage_type *get() { + assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); + assert(!HasError && "Cannot get value when an error exists!"); + return reinterpret_cast<storage_type*>(TStorage.buffer); + } + + const storage_type *get() const { + assert(IsValid && "Can't do anything on a default constructed ErrorOr!"); + assert(!HasError && "Cannot get value when an error exists!"); + return reinterpret_cast<const storage_type*>(TStorage.buffer); + } + + union { + AlignedCharArrayUnion<storage_type> TStorage; + ErrorHolderBase *Error; + }; + bool HasError : 1; + bool IsValid : 1; +}; + +// ErrorOr specialization for void. +template <> +class ErrorOr<void> { +public: + ErrorOr() : Error(0, 0) {} + + template <class E> + ErrorOr(E ErrorCode, typename enable_if_c<is_error_code_enum<E>::value || + is_error_condition_enum<E>::value, + void *> ::type = 0) + : Error(0, 0) { + error_code EC = make_error_code(ErrorCode); + if (EC == errc::success) { + Error.setInt(1); + return; + } + ErrorHolderBase *EHB = new ErrorHolderBase; + EHB->Error = EC; + EHB->HasUserData = false; + Error.setPointer(EHB); + } + + ErrorOr(llvm::error_code EC) : Error(0, 0) { + if (EC == errc::success) { + Error.setInt(1); + return; + } + ErrorHolderBase *E = new ErrorHolderBase; + E->Error = EC; + E->HasUserData = false; + Error.setPointer(E); + } + + template<class UserDataT> + ErrorOr(UserDataT UD, typename + enable_if_c<ErrorOrUserDataTraits<UserDataT>::value>::type* = 0) + : Error(0, 0) { + ErrorHolderBase *E = new ErrorHolder<UserDataT>(llvm_move(UD)); + E->Error = ErrorOrUserDataTraits<UserDataT>::error(); + E->HasUserData = true; + Error.setPointer(E); + } + + ErrorOr(const ErrorOr &Other) : Error(0, 0) { + Error = Other.Error; + if (Other.Error.getPointer()->Error) { + Error.getPointer()->aquire(); + } + } + + ErrorOr &operator =(const ErrorOr &Other) { + if (this == &Other) + return *this; + + this->~ErrorOr(); + new (this) ErrorOr(Other); + + return *this; + } + +#if LLVM_HAS_RVALUE_REFERENCES + ErrorOr(ErrorOr &&Other) : Error(0) { + // Get other's error. + Error = Other.Error; + // Tell other not to do any destruction. + Other.Error.setPointer(0); + } + + ErrorOr &operator =(ErrorOr &&Other) { + if (this == &Other) + return *this; + + this->~ErrorOr(); + new (this) ErrorOr(std::move(Other)); + + return *this; + } +#endif + + ~ErrorOr() { + if (Error.getPointer()) + Error.getPointer()->release(); + } + + template<class ET> + ET getError() const { + assert(ErrorOrUserDataTraits<ET>::error() == *this && + "Incorrect user error data type for error!"); + if (!Error.getPointer()->HasUserData) + return ET(); + return reinterpret_cast<const ErrorHolder<ET> *>( + Error.getPointer())->UserData; + } + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + /// \brief Return false if there is an error. + operator unspecified_bool_type() const { + return Error.getInt() ? unspecified_bool_true : 0; + } + + operator llvm::error_code() const { + return Error.getInt() ? make_error_code(errc::success) + : Error.getPointer()->Error; + } + +private: + // If the bit is 1, the error is success. + llvm::PointerIntPair<ErrorHolderBase *, 1> Error; +}; + +template<class T, class E> +typename enable_if_c<is_error_code_enum<E>::value || + is_error_condition_enum<E>::value, bool>::type +operator ==(ErrorOr<T> &Err, E Code) { + return error_code(Err) == Code; +} +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/FEnv.h b/include/llvm/Support/FEnv.h index f6f4333..8560ee0 100644 --- a/include/llvm/Support/FEnv.h +++ b/include/llvm/Support/FEnv.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_FENV_H -#define LLVM_SYSTEM_FENV_H +#ifndef LLVM_SUPPORT_FENV_H +#define LLVM_SUPPORT_FENV_H #include "llvm/Config/config.h" #include <cerrno> @@ -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/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index bcd35e3..cbc9c46 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -14,85 +14,79 @@ #ifndef LLVM_SUPPORT_FILEOUTPUTBUFFER_H #define LLVM_SUPPORT_FILEOUTPUTBUFFER_H +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/FileSystem.h" namespace llvm { - class error_code; -template<class T> class OwningPtr; /// FileOutputBuffer - This interface provides simple way to create an in-memory -/// buffer which will be written to a file. During the lifetime of these +/// buffer which will be written to a file. During the lifetime of these /// objects, the content or existence of the specified file is undefined. That /// is, creating an OutputBuffer for a file may immediately remove the file. -/// If the FileOutputBuffer is committed, the target file's content will become -/// the buffer content at the time of the commit. If the FileOutputBuffer is +/// If the FileOutputBuffer is committed, the target file's content will become +/// the buffer content at the time of the commit. If the FileOutputBuffer is /// not committed, the file will be deleted in the FileOutputBuffer destructor. class FileOutputBuffer { public: enum { F_executable = 1 /// set the 'x' bit on the resulting file - }; + }; /// Factory method to create an OutputBuffer object which manages a read/write /// buffer of the specified size. When committed, the buffer will be written - /// to the file at the specified path. - static error_code create(StringRef FilePath, size_t Size, - OwningPtr<FileOutputBuffer> &Result, - unsigned Flags=0); - + /// to the file at the specified path. + static error_code create(StringRef FilePath, size_t Size, + OwningPtr<FileOutputBuffer> &Result, + unsigned Flags = 0); /// Returns a pointer to the start of the buffer. - uint8_t *getBufferStart() const { - return BufferStart; + uint8_t *getBufferStart() { + return (uint8_t*)Region->data(); } - + /// Returns a pointer to the end of the buffer. - uint8_t *getBufferEnd() const { - return BufferEnd; + uint8_t *getBufferEnd() { + return (uint8_t*)Region->data() + Region->size(); } - + /// Returns size of the buffer. size_t getBufferSize() const { - return BufferEnd - BufferStart; + return Region->size(); } - + /// Returns path where file will show up if buffer is committed. StringRef getPath() const { return FinalPath; } - - /// Flushes the content of the buffer to its file and deallocates the + + /// Flushes the content of the buffer to its file and deallocates the /// buffer. If commit() is not called before this object's destructor /// is called, the file is deleted in the destructor. The optional parameter /// is used if it turns out you want the file size to be smaller than /// initially requested. error_code commit(int64_t NewSmallerSize = -1); - + /// If this object was previously committed, the destructor just deletes /// this object. If this object was not committed, the destructor /// deallocates the buffer and the target file is never written. ~FileOutputBuffer(); - private: FileOutputBuffer(const FileOutputBuffer &) LLVM_DELETED_FUNCTION; FileOutputBuffer &operator=(const FileOutputBuffer &) LLVM_DELETED_FUNCTION; -protected: - FileOutputBuffer(uint8_t *Start, uint8_t *End, - StringRef Path, StringRef TempPath); - - uint8_t *BufferStart; - uint8_t *BufferEnd; + + FileOutputBuffer(llvm::sys::fs::mapped_file_region *R, + StringRef Path, StringRef TempPath); + + OwningPtr<llvm::sys::fs::mapped_file_region> Region; SmallString<128> FinalPath; SmallString<128> TempPath; }; - - - } // end namespace llvm #endif diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index b455b28..ffa6427 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -24,8 +24,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_FILE_SYSTEM_H -#define LLVM_SUPPORT_FILE_SYSTEM_H +#ifndef LLVM_SUPPORT_FILESYSTEM_H +#define LLVM_SUPPORT_FILESYSTEM_H #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" @@ -602,12 +602,12 @@ private: void *FileMappingHandle; #endif - error_code init(int FD, uint64_t Offset); + error_code init(int FD, bool CloseFD, uint64_t Offset); public: typedef char char_type; -#if LLVM_USE_RVALUE_REFERENCES +#if LLVM_HAS_RVALUE_REFERENCES mapped_file_region(mapped_file_region&&); mapped_file_region &operator =(mapped_file_region&&); #endif @@ -633,8 +633,10 @@ public: error_code &ec); /// \param fd An open file descriptor to map. mapped_file_region takes - /// ownership. It must have been opended in the correct mode. + /// ownership if closefd is true. It must have been opended in the correct + /// mode. mapped_file_region(int fd, + bool closefd, mapmode mode, uint64_t length, uint64_t offset, diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index 21635dc..2e4bd5a 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/GCOV.h b/include/llvm/Support/GCOV.h index e552315..f1040f5 100644 --- a/include/llvm/Support/GCOV.h +++ b/include/llvm/Support/GCOV.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_GCOV_H -#define LLVM_GCOV_H +#ifndef LLVM_SUPPORT_GCOV_H +#define LLVM_SUPPORT_GCOV_H #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" diff --git a/include/llvm/Support/GetElementPtrTypeIterator.h b/include/llvm/Support/GetElementPtrTypeIterator.h index ef92c95..5a90553 100644 --- a/include/llvm/Support/GetElementPtrTypeIterator.h +++ b/include/llvm/Support/GetElementPtrTypeIterator.h @@ -12,11 +12,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_GETELEMENTPTRTYPE_H -#define LLVM_SUPPORT_GETELEMENTPTRTYPE_H +#ifndef LLVM_SUPPORT_GETELEMENTPTRTYPEITERATOR_H +#define LLVM_SUPPORT_GETELEMENTPTRTYPEITERATOR_H -#include "llvm/User.h" -#include "llvm/DerivedTypes.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/User.h" namespace llvm { template<typename ItTy = User::const_op_iterator> @@ -83,15 +83,15 @@ namespace llvm { typedef generic_gep_type_iterator<> gep_type_iterator; inline gep_type_iterator gep_type_begin(const User *GEP) { - return gep_type_iterator::begin(GEP->getOperand(0)->getType(), - GEP->op_begin()+1); + return gep_type_iterator::begin + (GEP->getOperand(0)->getType()->getScalarType(), GEP->op_begin()+1); } inline gep_type_iterator gep_type_end(const User *GEP) { return gep_type_iterator::end(GEP->op_end()); } inline gep_type_iterator gep_type_begin(const User &GEP) { - return gep_type_iterator::begin(GEP.getOperand(0)->getType(), - GEP.op_begin()+1); + return gep_type_iterator::begin + (GEP.getOperand(0)->getType()->getScalarType(), GEP.op_begin()+1); } inline gep_type_iterator gep_type_end(const User &GEP) { return gep_type_iterator::end(GEP.op_end()); diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index f178b0c..22181d4 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -23,17 +23,21 @@ #ifndef LLVM_SUPPORT_GRAPHWRITER_H #define LLVM_SUPPORT_GRAPHWRITER_H -#include "llvm/Support/DOTGraphTraits.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/Support/DOTGraphTraits.h" #include "llvm/Support/Path.h" -#include <vector> +#include "llvm/Support/raw_ostream.h" #include <cassert> +#include <vector> namespace llvm { namespace DOT { // Private functions... std::string EscapeString(const std::string &Label); + + /// \brief Get a color string for this node number. Simply round-robin selects + /// from a reasonable number of colors. + StringRef getColorString(unsigned NodeNumber); } namespace GraphProgram { @@ -173,6 +177,10 @@ public: // If we should include the address of the node in the label, do so now. if (DTraits.hasNodeAddressLabel(Node, G)) O << "|" << static_cast<const void*>(Node); + + std::string NodeDesc = DTraits.getNodeDescription(Node, G); + if (!NodeDesc.empty()) + O << "|" << DOT::EscapeString(NodeDesc); } std::string edgeSourceLabels; @@ -193,6 +201,10 @@ public: // If we should include the address of the node in the label, do so now. if (DTraits.hasNodeAddressLabel(Node, G)) O << "|" << static_cast<const void*>(Node); + + std::string NodeDesc = DTraits.getNodeDescription(Node, G); + if (!NodeDesc.empty()) + O << "|" << DOT::EscapeString(NodeDesc); } if (DTraits.hasEdgeDestLabels()) { diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h index b331016..3a44405 100644 --- a/include/llvm/Support/Host.h +++ b/include/llvm/Support/Host.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_HOST_H -#define LLVM_SYSTEM_HOST_H +#ifndef LLVM_SUPPORT_HOST_H +#define LLVM_SUPPORT_HOST_H #include "llvm/ADT/StringMap.h" #include <string> @@ -42,6 +42,10 @@ namespace sys { /// CPU_TYPE-VENDOR-KERNEL-OPERATING_SYSTEM std::string getDefaultTargetTriple(); + /// getProcessTriple() - Return an appropriate target triple for generating + /// code to be loaded into the current process, e.g. when using the JIT. + std::string getProcessTriple(); + /// getHostCPUName - Get the LLVM name for the host CPU. The particular format /// of the name is target dependent, and suitable for passing as -mcpu to the /// target which matches the host. diff --git a/include/llvm/Support/IRReader.h b/include/llvm/Support/IRReader.h deleted file mode 100644 index 6d8a9b3..0000000 --- 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/IncludeFile.h b/include/llvm/Support/IncludeFile.h index a931972..2067e34 100644 --- a/include/llvm/Support/IncludeFile.h +++ b/include/llvm/Support/IncludeFile.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_INCLUDEFILE_H -#define LLVM_SYSTEM_INCLUDEFILE_H +#ifndef LLVM_SUPPORT_INCLUDEFILE_H +#define LLVM_SUPPORT_INCLUDEFILE_H /// This macro is the public interface that IncludeFile.h exports. This gives /// us the option to implement the "link the definition" capability in any diff --git a/include/llvm/Support/InstIterator.h b/include/llvm/Support/InstIterator.h index 7d3f883..ac936a1 100644 --- a/include/llvm/Support/InstIterator.h +++ b/include/llvm/Support/InstIterator.h @@ -19,8 +19,8 @@ #ifndef LLVM_SUPPORT_INSTITERATOR_H #define LLVM_SUPPORT_INSTITERATOR_H -#include "llvm/BasicBlock.h" -#include "llvm/Function.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" namespace llvm { diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h deleted file mode 100644 index 6dfb4de..0000000 --- a/include/llvm/Support/InstVisitor.h +++ /dev/null @@ -1,288 +0,0 @@ -//===- llvm/Support/InstVisitor.h - Define instruction visitors -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - - -#ifndef LLVM_SUPPORT_INSTVISITOR_H -#define LLVM_SUPPORT_INSTVISITOR_H - -#include "llvm/Function.h" -#include "llvm/Instructions.h" -#include "llvm/Intrinsics.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Module.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Support/ErrorHandling.h" - -namespace llvm { - -// We operate on opaque instruction classes, so forward declare all instruction -// types now... -// -#define HANDLE_INST(NUM, OPCODE, CLASS) class CLASS; -#include "llvm/Instruction.def" - -#define DELEGATE(CLASS_TO_VISIT) \ - return static_cast<SubClass*>(this)-> \ - visit##CLASS_TO_VISIT(static_cast<CLASS_TO_VISIT&>(I)) - - -/// @brief Base class for instruction visitors -/// -/// Instruction visitors are used when you want to perform different actions -/// for different kinds of instructions without having to use lots of casts -/// and a big switch statement (in your code, that is). -/// -/// To define your own visitor, inherit from this class, specifying your -/// new type for the 'SubClass' template parameter, and "override" visitXXX -/// functions in your class. I say "override" because this class is defined -/// in terms of statically resolved overloading, not virtual functions. -/// -/// For example, here is a visitor that counts the number of malloc -/// instructions processed: -/// -/// /// Declare the class. Note that we derive from InstVisitor instantiated -/// /// with _our new subclasses_ type. -/// /// -/// struct CountAllocaVisitor : public InstVisitor<CountAllocaVisitor> { -/// unsigned Count; -/// CountAllocaVisitor() : Count(0) {} -/// -/// void visitAllocaInst(AllocaInst &AI) { ++Count; } -/// }; -/// -/// And this class would be used like this: -/// CountAllocaVisitor CAV; -/// CAV.visit(function); -/// NumAllocas = CAV.Count; -/// -/// The defined has 'visit' methods for Instruction, and also for BasicBlock, -/// Function, and Module, which recursively process all contained instructions. -/// -/// Note that if you don't implement visitXXX for some instruction type, -/// the visitXXX method for instruction superclass will be invoked. So -/// if instructions are added in the future, they will be automatically -/// supported, if you handle one of their superclasses. -/// -/// The optional second template argument specifies the type that instruction -/// visitation functions should return. If you specify this, you *MUST* provide -/// an implementation of visitInstruction though!. -/// -/// Note that this class is specifically designed as a template to avoid -/// virtual function call overhead. Defining and using an InstVisitor is just -/// as efficient as having your own switch statement over the instruction -/// opcode. -template<typename SubClass, typename RetTy=void> -class InstVisitor { - //===--------------------------------------------------------------------===// - // Interface code - This is the public interface of the InstVisitor that you - // use to visit instructions... - // - -public: - // Generic visit method - Allow visitation to all instructions in a range - template<class Iterator> - void visit(Iterator Start, Iterator End) { - while (Start != End) - static_cast<SubClass*>(this)->visit(*Start++); - } - - // Define visitors for functions and basic blocks... - // - void visit(Module &M) { - static_cast<SubClass*>(this)->visitModule(M); - visit(M.begin(), M.end()); - } - void visit(Function &F) { - static_cast<SubClass*>(this)->visitFunction(F); - visit(F.begin(), F.end()); - } - void visit(BasicBlock &BB) { - static_cast<SubClass*>(this)->visitBasicBlock(BB); - visit(BB.begin(), BB.end()); - } - - // Forwarding functions so that the user can visit with pointers AND refs. - void visit(Module *M) { visit(*M); } - void visit(Function *F) { visit(*F); } - void visit(BasicBlock *BB) { visit(*BB); } - RetTy visit(Instruction *I) { return visit(*I); } - - // visit - Finally, code to visit an instruction... - // - RetTy visit(Instruction &I) { - switch (I.getOpcode()) { - default: llvm_unreachable("Unknown instruction type encountered!"); - // Build the switch statement using the Instruction.def file... -#define HANDLE_INST(NUM, OPCODE, CLASS) \ - case Instruction::OPCODE: return \ - static_cast<SubClass*>(this)-> \ - visit##OPCODE(static_cast<CLASS&>(I)); -#include "llvm/Instruction.def" - } - } - - //===--------------------------------------------------------------------===// - // Visitation functions... these functions provide default fallbacks in case - // the user does not specify what to do for a particular instruction type. - // The default behavior is to generalize the instruction type to its subtype - // and try visiting the subtype. All of this should be inlined perfectly, - // because there are no virtual functions to get in the way. - // - - // When visiting a module, function or basic block directly, these methods get - // called to indicate when transitioning into a new unit. - // - void visitModule (Module &M) {} - void visitFunction (Function &F) {} - void visitBasicBlock(BasicBlock &BB) {} - - // Define instruction specific visitor functions that can be overridden to - // handle SPECIFIC instructions. These functions automatically define - // visitMul to proxy to visitBinaryOperator for instance in case the user does - // not need this generality. - // - // These functions can also implement fan-out, when a single opcode and - // instruction have multiple more specific Instruction subclasses. The Call - // instruction currently supports this. We implement that by redirecting that - // instruction to a special delegation helper. -#define HANDLE_INST(NUM, OPCODE, CLASS) \ - RetTy visit##OPCODE(CLASS &I) { \ - if (NUM == Instruction::Call) \ - return delegateCallInst(I); \ - else \ - DELEGATE(CLASS); \ - } -#include "llvm/Instruction.def" - - // Specific Instruction type classes... note that all of the casts are - // necessary because we use the instruction classes as opaque types... - // - RetTy visitReturnInst(ReturnInst &I) { DELEGATE(TerminatorInst);} - RetTy visitBranchInst(BranchInst &I) { DELEGATE(TerminatorInst);} - RetTy visitSwitchInst(SwitchInst &I) { DELEGATE(TerminatorInst);} - RetTy visitIndirectBrInst(IndirectBrInst &I) { DELEGATE(TerminatorInst);} - RetTy visitResumeInst(ResumeInst &I) { DELEGATE(TerminatorInst);} - RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);} - RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);} - RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);} - RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(UnaryInstruction);} - RetTy visitLoadInst(LoadInst &I) { DELEGATE(UnaryInstruction);} - RetTy visitStoreInst(StoreInst &I) { DELEGATE(Instruction);} - RetTy visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) { DELEGATE(Instruction);} - RetTy visitAtomicRMWInst(AtomicRMWInst &I) { DELEGATE(Instruction);} - RetTy visitFenceInst(FenceInst &I) { DELEGATE(Instruction);} - RetTy visitGetElementPtrInst(GetElementPtrInst &I){ DELEGATE(Instruction);} - RetTy visitPHINode(PHINode &I) { DELEGATE(Instruction);} - RetTy visitTruncInst(TruncInst &I) { DELEGATE(CastInst);} - RetTy visitZExtInst(ZExtInst &I) { DELEGATE(CastInst);} - RetTy visitSExtInst(SExtInst &I) { DELEGATE(CastInst);} - RetTy visitFPTruncInst(FPTruncInst &I) { DELEGATE(CastInst);} - RetTy visitFPExtInst(FPExtInst &I) { DELEGATE(CastInst);} - RetTy visitFPToUIInst(FPToUIInst &I) { DELEGATE(CastInst);} - RetTy visitFPToSIInst(FPToSIInst &I) { DELEGATE(CastInst);} - RetTy visitUIToFPInst(UIToFPInst &I) { DELEGATE(CastInst);} - RetTy visitSIToFPInst(SIToFPInst &I) { DELEGATE(CastInst);} - RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst);} - RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst);} - RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst);} - RetTy visitSelectInst(SelectInst &I) { DELEGATE(Instruction);} - RetTy visitVAArgInst(VAArgInst &I) { DELEGATE(UnaryInstruction);} - RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);} - RetTy visitInsertElementInst(InsertElementInst &I) { DELEGATE(Instruction);} - RetTy visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction);} - RetTy visitExtractValueInst(ExtractValueInst &I){ DELEGATE(UnaryInstruction);} - RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); } - RetTy visitLandingPadInst(LandingPadInst &I) { DELEGATE(Instruction); } - - // Handle the special instrinsic instruction classes. - RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgInfoIntrinsic);} - RetTy visitDbgValueInst(DbgValueInst &I) { DELEGATE(DbgInfoIntrinsic);} - RetTy visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { DELEGATE(IntrinsicInst); } - RetTy visitMemSetInst(MemSetInst &I) { DELEGATE(MemIntrinsic); } - RetTy visitMemCpyInst(MemCpyInst &I) { DELEGATE(MemTransferInst); } - RetTy visitMemMoveInst(MemMoveInst &I) { DELEGATE(MemTransferInst); } - RetTy visitMemTransferInst(MemTransferInst &I) { DELEGATE(MemIntrinsic); } - RetTy visitMemIntrinsic(MemIntrinsic &I) { DELEGATE(IntrinsicInst); } - RetTy visitVAStartInst(VAStartInst &I) { DELEGATE(IntrinsicInst); } - RetTy visitVAEndInst(VAEndInst &I) { DELEGATE(IntrinsicInst); } - RetTy visitVACopyInst(VACopyInst &I) { DELEGATE(IntrinsicInst); } - RetTy visitIntrinsicInst(IntrinsicInst &I) { DELEGATE(CallInst); } - - // Call and Invoke are slightly different as they delegate first through - // a generic CallSite visitor. - RetTy visitCallInst(CallInst &I) { - return static_cast<SubClass*>(this)->visitCallSite(&I); - } - RetTy visitInvokeInst(InvokeInst &I) { - return static_cast<SubClass*>(this)->visitCallSite(&I); - } - - // Next level propagators: If the user does not overload a specific - // instruction type, they can overload one of these to get the whole class - // of instructions... - // - RetTy visitCastInst(CastInst &I) { DELEGATE(UnaryInstruction);} - RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction);} - RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction);} - RetTy visitTerminatorInst(TerminatorInst &I) { DELEGATE(Instruction);} - RetTy visitUnaryInstruction(UnaryInstruction &I){ DELEGATE(Instruction);} - - // Provide a special visitor for a 'callsite' that visits both calls and - // invokes. When unimplemented, properly delegates to either the terminator or - // regular instruction visitor. - RetTy visitCallSite(CallSite CS) { - assert(CS); - Instruction &I = *CS.getInstruction(); - if (CS.isCall()) - DELEGATE(Instruction); - - assert(CS.isInvoke()); - DELEGATE(TerminatorInst); - } - - // If the user wants a 'default' case, they can choose to override this - // function. If this function is not overloaded in the user's subclass, then - // this instruction just gets ignored. - // - // Note that you MUST override this function if your return type is not void. - // - void visitInstruction(Instruction &I) {} // Ignore unhandled instructions - -private: - // Special helper function to delegate to CallInst subclass visitors. - RetTy delegateCallInst(CallInst &I) { - if (const Function *F = I.getCalledFunction()) { - switch ((Intrinsic::ID)F->getIntrinsicID()) { - default: DELEGATE(IntrinsicInst); - case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst); - case Intrinsic::dbg_value: DELEGATE(DbgValueInst); - case Intrinsic::memcpy: DELEGATE(MemCpyInst); - case Intrinsic::memmove: DELEGATE(MemMoveInst); - case Intrinsic::memset: DELEGATE(MemSetInst); - case Intrinsic::vastart: DELEGATE(VAStartInst); - case Intrinsic::vaend: DELEGATE(VAEndInst); - case Intrinsic::vacopy: DELEGATE(VACopyInst); - case Intrinsic::not_intrinsic: break; - } - } - DELEGATE(CallInst); - } - - // An overload that will never actually be called, it is used only from dead - // code in the dispatching from opcodes to instruction subclasses. - RetTy delegateCallInst(Instruction &I) { - llvm_unreachable("delegateCallInst called for non-CallInst"); - } -}; - -#undef DELEGATE - -} // End llvm namespace - -#endif diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h index 03039fd..ce34d78 100644 --- a/include/llvm/Support/IntegersSubset.h +++ b/include/llvm/Support/IntegersSubset.h @@ -15,15 +15,14 @@ // //===----------------------------------------------------------------------===// -#ifndef CONSTANTRANGESSET_H_ -#define CONSTANTRANGESSET_H_ +#ifndef LLVM_SUPPORT_INTEGERSSUBSET_H +#define LLVM_SUPPORT_INTEGERSSUBSET_H +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/LLVMContext.h" #include <list> -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" - namespace llvm { // The IntItem is a wrapper for APInt. @@ -538,4 +537,4 @@ public: } -#endif /* CONSTANTRANGESSET_H_ */ +#endif /* CLLVM_SUPPORT_INTEGERSSUBSET_H */ diff --git a/include/llvm/Support/IntegersSubsetMapping.h b/include/llvm/Support/IntegersSubsetMapping.h index 7635d5e..641ce78 100644 --- a/include/llvm/Support/IntegersSubsetMapping.h +++ b/include/llvm/Support/IntegersSubsetMapping.h @@ -17,8 +17,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CRSBUILDER_H_ -#define CRSBUILDER_H_ +#ifndef LLVM_SUPPORT_INTEGERSSUBSETMAPPING_H +#define LLVM_SUPPORT_INTEGERSSUBSETMAPPING_H #include "llvm/Support/IntegersSubset.h" #include <list> @@ -585,4 +585,4 @@ typedef IntegersSubsetMapping<BasicBlock> IntegersSubsetToBB; } -#endif /* CRSBUILDER_H_ */ +#endif /* LLVM_SUPPORT_INTEGERSSUBSETMAPPING_CRSBUILDER_H */ diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index b52e5bc..802b4f3 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_LEB128_H -#define LLVM_SYSTEM_LEB128_H +#ifndef LLVM_SUPPORT_LEB128_H +#define LLVM_SUPPORT_LEB128_H #include "llvm/Support/raw_ostream.h" diff --git a/include/llvm/Support/Locale.h b/include/llvm/Support/Locale.h index b0f1295..b384d58 100644 --- a/include/llvm/Support/Locale.h +++ b/include/llvm/Support/Locale.h @@ -1,5 +1,5 @@ -#ifndef LLVM_SUPPORT_LOCALE -#define LLVM_SUPPORT_LOCALE +#ifndef LLVM_SUPPORT_LOCALE_H +#define LLVM_SUPPORT_LOCALE_H #include "llvm/ADT/StringRef.h" @@ -14,4 +14,4 @@ bool isPrint(int c); } } -#endif // LLVM_SUPPORT_LOCALE +#endif // LLVM_SUPPORT_LOCALE_H diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index 8c4a760..9df8675 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -41,6 +41,7 @@ public: }; private: + SmallString<128> FileName; SmallString<128> LockFileName; SmallString<128> UniqueLockFileName; diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 11f9e63..d6ae58d 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -16,6 +16,10 @@ #include "llvm/Support/SwapByteOrder.h" +#ifdef _MSC_VER +# include <intrin.h> +#endif + namespace llvm { // NOTE: The following support functions use the _32/_64 extensions instead of @@ -61,7 +65,7 @@ inline bool isShiftedInt(int64_t x) { /// isUInt - Checks if an unsigned integer fits into the given bit width. template<unsigned N> inline bool isUInt(uint64_t x) { - return N >= 64 || x < (UINT64_C(1)<<N); + return N >= 64 || x < (UINT64_C(1)<<(N)); } // Template specializations to get better code for common cases. template<> @@ -254,7 +258,10 @@ inline unsigned CountTrailingZeros_32(uint32_t Value) { 4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18 }; - return Mod37BitPosition[(-Value & Value) % 37]; + // Replace "-Value" by "1+~Value" in the following commented code to avoid + // MSVC warning C4146 + // return Mod37BitPosition[(-Value & Value) % 37]; + return Mod37BitPosition[((1 + ~Value) & Value) % 37]; #endif } @@ -281,7 +288,10 @@ inline unsigned CountTrailingZeros_64(uint64_t Value) { 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, 7, 48, 35, 6, 34, 33, 0 }; - return Mod67Position[(-Value & Value) % 67]; + // Replace "-Value" by "1+~Value" in the following commented code to avoid + // MSVC warning C4146 + // return Mod67Position[(-Value & Value) % 67]; + return Mod67Position[((1 + ~Value) & Value) % 67]; #endif } @@ -416,7 +426,11 @@ int IsInf(double d); /// alignment that may be assumed after adding the two together. inline uint64_t MinAlign(uint64_t A, uint64_t B) { // The largest power of 2 that divides both A and B. - return (A | B) & -(A | B); + // + // Replace "-Value" by "1+~Value" in the following commented code to avoid + // MSVC warning C4146 + // return (A | B) & -(A | B); + return (A | B) & (1 + ~(A | B)); } /// NextPowerOf2 - Returns the next power of two (in 64-bits) diff --git a/include/llvm/Support/Memory.h b/include/llvm/Support/Memory.h index 025eee7..a08c796 100644 --- a/include/llvm/Support/Memory.h +++ b/include/llvm/Support/Memory.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_MEMORY_H -#define LLVM_SYSTEM_MEMORY_H +#ifndef LLVM_SUPPORT_MEMORY_H +#define LLVM_SUPPORT_MEMORY_H #include "llvm/Support/DataTypes.h" #include "llvm/Support/system_error.h" diff --git a/include/llvm/Support/MemoryObject.h b/include/llvm/Support/MemoryObject.h index b778b08..732b0f0 100644 --- a/include/llvm/Support/MemoryObject.h +++ b/include/llvm/Support/MemoryObject.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MEMORYOBJECT_H -#define MEMORYOBJECT_H +#ifndef LLVM_SUPPORT_MEMORYOBJECT_H +#define LLVM_SUPPORT_MEMORYOBJECT_H #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h index 6abc533..496a438 100644 --- a/include/llvm/Support/Mutex.h +++ b/include/llvm/Support/Mutex.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_MUTEX_H -#define LLVM_SYSTEM_MUTEX_H +#ifndef LLVM_SUPPORT_MUTEX_H +#define LLVM_SUPPORT_MUTEX_H #include "llvm/Support/Compiler.h" #include "llvm/Support/Threading.h" diff --git a/include/llvm/Support/NoFolder.h b/include/llvm/Support/NoFolder.h index 8e41a64..ecfbbaa 100644 --- a/include/llvm/Support/NoFolder.h +++ b/include/llvm/Support/NoFolder.h @@ -23,8 +23,8 @@ #define LLVM_SUPPORT_NOFOLDER_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/Constants.h" -#include "llvm/Instructions.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" namespace llvm { diff --git a/include/llvm/Support/PassNameParser.h b/include/llvm/Support/PassNameParser.h index a24a6f0..317416c 100644 --- a/include/llvm/Support/PassNameParser.h +++ b/include/llvm/Support/PassNameParser.h @@ -20,11 +20,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_PASS_NAME_PARSER_H -#define LLVM_SUPPORT_PASS_NAME_PARSER_H +#ifndef LLVM_SUPPORT_PASSNAMEPARSER_H +#define LLVM_SUPPORT_PASSNAMEPARSER_H -#include "llvm/Pass.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" diff --git a/include/llvm/Support/PathV1.h b/include/llvm/Support/PathV1.h index 643ee8c..86328f0 100644 --- a/include/llvm/Support/PathV1.h +++ b/include/llvm/Support/PathV1.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_PATH_H -#define LLVM_SYSTEM_PATH_H +#ifndef LLVM_SUPPORT_PATHV1_H +#define LLVM_SUPPORT_PATHV1_H #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h index 221fa8b..9fbe434 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/Support/PatternMatch.h @@ -29,9 +29,11 @@ #ifndef LLVM_SUPPORT_PATTERNMATCH_H #define LLVM_SUPPORT_PATTERNMATCH_H -#include "llvm/Constants.h" -#include "llvm/Instructions.h" -#include "llvm/Operator.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Operator.h" +#include "llvm/Support/CallSite.h" namespace llvm { namespace PatternMatch { @@ -41,13 +43,13 @@ bool match(Val *V, const Pattern &P) { return const_cast<Pattern&>(P).match(V); } - + template<typename SubPattern_t> struct OneUse_match { SubPattern_t SubPattern; - + OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} - + template<typename OpTy> bool match(OpTy *V) { return V->hasOneUse() && SubPattern.match(V); @@ -56,8 +58,8 @@ struct OneUse_match { template<typename T> inline OneUse_match<T> m_OneUse(const T &SubPattern) { return SubPattern; } - - + + template<typename Class> struct class_match { template<typename ITy> @@ -74,7 +76,53 @@ inline class_match<ConstantInt> m_ConstantInt() { inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); } inline class_match<Constant> m_Constant() { return class_match<Constant>(); } - + +/// Matching combinators +template<typename LTy, typename RTy> +struct match_combine_or { + LTy L; + RTy R; + + match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + + template<typename ITy> + bool match(ITy *V) { + if (L.match(V)) + return true; + if (R.match(V)) + return true; + return false; + } +}; + +template<typename LTy, typename RTy> +struct match_combine_and { + LTy L; + RTy R; + + match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + + template<typename ITy> + bool match(ITy *V) { + if (L.match(V)) + if (R.match(V)) + return true; + return false; + } +}; + +/// Combine two pattern matchers matching L || R +template<typename LTy, typename RTy> +inline match_combine_or<LTy, RTy> m_CombineOr(const LTy &L, const RTy &R) { + return match_combine_or<LTy, RTy>(L, R); +} + +/// Combine two pattern matchers matching L && R +template<typename LTy, typename RTy> +inline match_combine_and<LTy, RTy> m_CombineAnd(const LTy &L, const RTy &R) { + return match_combine_and<LTy, RTy>(L, R); +} + struct match_zero { template<typename ITy> bool match(ITy *V) { @@ -83,12 +131,33 @@ struct match_zero { return false; } }; - + /// m_Zero() - Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. inline match_zero m_Zero() { return match_zero(); } - - + +struct match_neg_zero { + template<typename ITy> + bool match(ITy *V) { + if (const Constant *C = dyn_cast<Constant>(V)) + return C->isNegativeZeroValue(); + return false; + } +}; + +/// m_NegZero() - Match an arbitrary zero/null constant. This includes +/// zero_initializer for vectors and ConstantPointerNull for pointers. For +/// floating point constants, this will match negative zero but not positive +/// zero +inline match_neg_zero m_NegZero() { return match_neg_zero(); } + +/// m_AnyZero() - Match an arbitrary zero/null constant. This includes +/// zero_initializer for vectors and ConstantPointerNull for pointers. For +/// floating point constants, this will match negative zero and positive zero +inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() { + return m_CombineOr(m_Zero(), m_NegZero()); +} + struct apint_match { const APInt *&Res; apint_match(const APInt *&R) : Res(R) {} @@ -98,28 +167,22 @@ struct apint_match { Res = &CI->getValue(); return true; } - // FIXME: Remove this. - if (ConstantVector *CV = dyn_cast<ConstantVector>(V)) - if (ConstantInt *CI = - dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) { - Res = &CI->getValue(); - return true; - } - if (ConstantDataVector *CV = dyn_cast<ConstantDataVector>(V)) - if (ConstantInt *CI = - dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) { - Res = &CI->getValue(); - return true; - } + if (V->getType()->isVectorTy()) + if (const Constant *C = dyn_cast<Constant>(V)) + if (ConstantInt *CI = + dyn_cast_or_null<ConstantInt>(C->getSplatValue())) { + Res = &CI->getValue(); + return true; + } return false; } }; - + /// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the /// specified pointer to the contained APInt. inline apint_match m_APInt(const APInt *&Res) { return Res; } - + template<int64_t Val> struct constantint_match { template<typename ITy> @@ -151,17 +214,15 @@ struct cst_pred_ty : public Predicate { bool match(ITy *V) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) return this->isValue(CI->getValue()); - // FIXME: Remove this. - if (const ConstantVector *CV = dyn_cast<ConstantVector>(V)) - if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) - return this->isValue(CI->getValue()); - if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(V)) - if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) - return this->isValue(CI->getValue()); + if (V->getType()->isVectorTy()) + if (const Constant *C = dyn_cast<Constant>(V)) + if (const ConstantInt *CI = + dyn_cast_or_null<ConstantInt>(C->getSplatValue())) + return this->isValue(CI->getValue()); return false; } }; - + /// api_pred_ty - This helper class is used to match scalar and vector constants /// that satisfy a specified predicate, and bind them to an APInt. template<typename Predicate> @@ -175,27 +236,19 @@ struct api_pred_ty : public Predicate { Res = &CI->getValue(); return true; } - - // FIXME: remove. - if (const ConstantVector *CV = dyn_cast<ConstantVector>(V)) - if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) - if (this->isValue(CI->getValue())) { - Res = &CI->getValue(); - return true; - } - - if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(V)) - if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) - if (this->isValue(CI->getValue())) { - Res = &CI->getValue(); - return true; - } + if (V->getType()->isVectorTy()) + if (const Constant *C = dyn_cast<Constant>(V)) + if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue())) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } return false; } }; - - + + struct is_one { bool isValue(const APInt &C) { return C == 1; } }; @@ -203,11 +256,11 @@ struct is_one { /// m_One() - Match an integer 1 or a vector with all elements equal to 1. inline cst_pred_ty<is_one> m_One() { return cst_pred_ty<is_one>(); } inline api_pred_ty<is_one> m_One(const APInt *&V) { return V; } - + struct is_all_ones { bool isValue(const APInt &C) { return C.isAllOnesValue(); } }; - + /// m_AllOnes() - Match an integer or vector with all bits set to true. inline cst_pred_ty<is_all_ones> m_AllOnes() {return cst_pred_ty<is_all_ones>();} inline api_pred_ty<is_all_ones> m_AllOnes(const APInt *&V) { return V; } @@ -252,6 +305,9 @@ inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; } /// m_Constant - Match a Constant, capturing the value if we match. inline bind_ty<Constant> m_Constant(Constant *&C) { return C; } +/// m_ConstantFP - Match a ConstantFP, capturing the value if we match. +inline bind_ty<ConstantFP> m_ConstantFP(ConstantFP *&C) { return C; } + /// specificval_ty - Match a specified Value*. struct specificval_ty { const Value *Val; @@ -266,10 +322,35 @@ struct specificval_ty { /// m_Specific - Match if we have a specific specified value. inline specificval_ty m_Specific(const Value *V) { return V; } +/// Match a specified floating point value or vector of all elements of that +/// value. +struct specific_fpval { + double Val; + specific_fpval(double V) : Val(V) {} + + template<typename ITy> + bool match(ITy *V) { + if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V)) + return CFP->isExactlyValue(Val); + if (V->getType()->isVectorTy()) + if (const Constant *C = dyn_cast<Constant>(V)) + if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(C->getSplatValue())) + return CFP->isExactlyValue(Val); + return false; + } +}; + +/// Match a specific floating point value or vector with all elements equal to +/// the value. +inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } + +/// Match a float 1.0 or vector with all elements equal to 1.0. +inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } + struct bind_const_intval_ty { uint64_t &VR; bind_const_intval_ty(uint64_t &V) : VR(V) {} - + template<typename ITy> bool match(ITy *V) { if (ConstantInt *CV = dyn_cast<ConstantInt>(V)) @@ -284,7 +365,7 @@ struct bind_const_intval_ty { /// m_ConstantInt - Match a ConstantInt and bind to its value. This does not /// match ConstantInts wider than 64-bits. inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; } - + //===----------------------------------------------------------------------===// // Matchers for specific binary operators. // @@ -583,7 +664,7 @@ inline CastClass_match<OpTy, Instruction::BitCast> m_BitCast(const OpTy &Op) { return CastClass_match<OpTy, Instruction::BitCast>(Op); } - + /// m_PtrToInt template<typename OpTy> inline CastClass_match<OpTy, Instruction::PtrToInt> @@ -611,7 +692,7 @@ inline CastClass_match<OpTy, Instruction::ZExt> m_ZExt(const OpTy &Op) { return CastClass_match<OpTy, Instruction::ZExt>(Op); } - + //===----------------------------------------------------------------------===// // Matchers for unary operators @@ -700,6 +781,25 @@ inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; } // Matchers for control flow. // +struct br_match { + BasicBlock *&Succ; + br_match(BasicBlock *&Succ) + : Succ(Succ) { + } + + template<typename OpTy> + bool match(OpTy *V) { + if (BranchInst *BI = dyn_cast<BranchInst>(V)) + if (BI->isUnconditional()) { + Succ = BI->getSuccessor(0); + return true; + } + return false; + } +}; + +inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); } + template<typename Cond_t> struct brc_match { Cond_t Cond; @@ -818,6 +918,102 @@ m_UMin(const LHS &L, const RHS &R) { return MaxMin_match<LHS, RHS, umin_pred_ty>(L, R); } +template<typename Opnd_t> +struct Argument_match { + unsigned OpI; + Opnd_t Val; + Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) { } + + template<typename OpTy> + bool match(OpTy *V) { + CallSite CS(V); + return CS.isCall() && Val.match(CS.getArgument(OpI)); + } +}; + +/// Match an argument +template<unsigned OpI, typename Opnd_t> +inline Argument_match<Opnd_t> m_Argument(const Opnd_t &Op) { + return Argument_match<Opnd_t>(OpI, Op); +} + +/// Intrinsic matchers. +struct IntrinsicID_match { + unsigned ID; + IntrinsicID_match(unsigned IntrID) : ID(IntrID) { } + + template<typename OpTy> + bool match(OpTy *V) { + IntrinsicInst *II = dyn_cast<IntrinsicInst>(V); + return II && II->getIntrinsicID() == ID; + } +}; + +/// Intrinsic matches are combinations of ID matchers, and argument +/// matchers. Higher arity matcher are defined recursively in terms of and-ing +/// them with lower arity matchers. Here's some convenient typedefs for up to +/// several arguments, and more can be added as needed +template <typename T0 = void, typename T1 = void, typename T2 = void, + typename T3 = void, typename T4 = void, typename T5 = void, + typename T6 = void, typename T7 = void, typename T8 = void, + typename T9 = void, typename T10 = void> struct m_Intrinsic_Ty; +template <typename T0> +struct m_Intrinsic_Ty<T0> { + typedef match_combine_and<IntrinsicID_match, Argument_match<T0> > Ty; +}; +template <typename T0, typename T1> +struct m_Intrinsic_Ty<T0, T1> { + typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty, + Argument_match<T1> > Ty; +}; +template <typename T0, typename T1, typename T2> +struct m_Intrinsic_Ty<T0, T1, T2> { + typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1>::Ty, + Argument_match<T2> > Ty; +}; +template <typename T0, typename T1, typename T2, typename T3> +struct m_Intrinsic_Ty<T0, T1, T2, T3> { + typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1, T2>::Ty, + Argument_match<T3> > Ty; +}; + +/// Match intrinsic calls like this: +/// m_Intrinsic<Intrinsic::fabs>(m_Value(X)) +template <unsigned IntrID> +inline IntrinsicID_match +m_Intrinsic() { return IntrinsicID_match(IntrID); } + +template<unsigned IntrID, typename T0> +inline typename m_Intrinsic_Ty<T0>::Ty +m_Intrinsic(const T0 &Op0) { + return m_CombineAnd(m_Intrinsic<IntrID>(), m_Argument<0>(Op0)); +} + +template<unsigned IntrID, typename T0, typename T1> +inline typename m_Intrinsic_Ty<T0, T1>::Ty +m_Intrinsic(const T0 &Op0, const T1 &Op1) { + return m_CombineAnd(m_Intrinsic<IntrID>(Op0), m_Argument<1>(Op1)); +} + +template<unsigned IntrID, typename T0, typename T1, typename T2> +inline typename m_Intrinsic_Ty<T0, T1, T2>::Ty +m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) { + return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1), m_Argument<2>(Op2)); +} + +template<unsigned IntrID, typename T0, typename T1, typename T2, typename T3> +inline typename m_Intrinsic_Ty<T0, T1, T2, T3>::Ty +m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) { + return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1, Op2), m_Argument<3>(Op3)); +} + +// Helper intrinsic matching specializations +template<typename Opnd0> +inline typename m_Intrinsic_Ty<Opnd0>::Ty +m_BSwap(const Opnd0 &Op0) { + return m_Intrinsic<Intrinsic::bswap>(Op0); +} + } // end namespace PatternMatch } // end namespace llvm diff --git a/include/llvm/Support/PredIteratorCache.h b/include/llvm/Support/PredIteratorCache.h index bb66a8e..c5fb780 100644 --- a/include/llvm/Support/PredIteratorCache.h +++ b/include/llvm/Support/PredIteratorCache.h @@ -11,10 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/Allocator.h" -#include "llvm/Support/CFG.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/CFG.h" #ifndef LLVM_SUPPORT_PREDITERATORCACHE_H #define LLVM_SUPPORT_PREDITERATORCACHE_H diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index 088897c..4256d4a 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -6,152 +6,246 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file declares the llvm::sys::Process class. -// +/// \file +/// +/// Provides a library for accessing information about this process and other +/// processes on the operating system. Also provides means of spawning +/// subprocess for commands. The design of this library is modeled after the +/// proposed design of the Boost.Process library, and is design specifically to +/// follow the style of standard libraries and potentially become a proposal +/// for a standard library. +/// +/// This file declares the llvm::sys::Process class which contains a collection +/// of legacy static interfaces for extracting various information about the +/// current process. The goal is to migrate users of this API over to the new +/// interfaces. +/// //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_PROCESS_H -#define LLVM_SYSTEM_PROCESS_H +#ifndef LLVM_SUPPORT_PROCESS_H +#define LLVM_SUPPORT_PROCESS_H +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/TimeValue.h" namespace llvm { namespace sys { - /// This class provides an abstraction for getting information about the - /// currently executing process. - /// @since 1.4 - /// @brief An abstraction for operating system processes. - class Process { - /// @name Accessors - /// @{ - public: - /// This static function will return the operating system's virtual memory - /// page size. - /// @returns The number of bytes in a virtual memory page. - /// @brief Get the virtual memory page size - static unsigned GetPageSize(); - - /// This static function will return the total amount of memory allocated - /// by the process. This only counts the memory allocated via the malloc, - /// calloc and realloc functions and includes any "free" holes in the - /// allocated space. - /// @brief Return process memory usage. - static size_t GetMallocUsage(); - - /// This static function will return the total memory usage of the - /// process. This includes code, data, stack and mapped pages usage. Notei - /// that the value returned here is not necessarily the Running Set Size, - /// it is the total virtual memory usage, regardless of mapped state of - /// that memory. - static size_t GetTotalMemoryUsage(); - - /// This static function will set \p user_time to the amount of CPU time - /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU - /// time spent in system (kernel) mode. If the operating system does not - /// support collection of these metrics, a zero TimeValue will be for both - /// values. - static void GetTimeUsage( - TimeValue& elapsed, - ///< Returns the TimeValue::now() giving current time - TimeValue& user_time, - ///< Returns the current amount of user time for the process - TimeValue& sys_time - ///< Returns the current amount of system time for the process - ); - - /// This static function will return the process' current user id number. - /// Not all operating systems support this feature. Where it is not - /// supported, the function should return 65536 as the value. - static int GetCurrentUserId(); - - /// This static function will return the process' current group id number. - /// Not all operating systems support this feature. Where it is not - /// supported, the function should return 65536 as the value. - static int GetCurrentGroupId(); - - /// This function makes the necessary calls to the operating system to - /// prevent core files or any other kind of large memory dumps that can - /// occur when a program fails. - /// @brief Prevent core file generation. - static void PreventCoreFiles(); - - /// This function determines if the standard input is connected directly - /// to a user's input (keyboard probably), rather than coming from a file - /// or pipe. - static bool StandardInIsUserInput(); - - /// This function determines if the standard output is connected to a - /// "tty" or "console" window. That is, the output would be displayed to - /// the user rather than being put on a pipe or stored in a file. - static bool StandardOutIsDisplayed(); - - /// This function determines if the standard error is connected to a - /// "tty" or "console" window. That is, the output would be displayed to - /// the user rather than being put on a pipe or stored in a file. - static bool StandardErrIsDisplayed(); - - /// This function determines if the given file descriptor is connected to - /// a "tty" or "console" window. That is, the output would be displayed to - /// the user rather than being put on a pipe or stored in a file. - static bool FileDescriptorIsDisplayed(int fd); - - /// This function determines if the given file descriptor is displayd and - /// supports colors. - static bool FileDescriptorHasColors(int fd); - - /// This function determines the number of columns in the window - /// if standard output is connected to a "tty" or "console" - /// window. If standard output is not connected to a tty or - /// console, or if the number of columns cannot be determined, - /// this routine returns zero. - static unsigned StandardOutColumns(); - - /// This function determines the number of columns in the window - /// if standard error is connected to a "tty" or "console" - /// window. If standard error is not connected to a tty or - /// console, or if the number of columns cannot be determined, - /// this routine returns zero. - static unsigned StandardErrColumns(); - - /// This function determines whether the terminal connected to standard - /// output supports colors. If standard output is not connected to a - /// terminal, this function returns false. - static bool StandardOutHasColors(); - - /// This function determines whether the terminal connected to standard - /// error supports colors. If standard error is not connected to a - /// terminal, this function returns false. - static bool StandardErrHasColors(); - - /// Whether changing colors requires the output to be flushed. - /// This is needed on systems that don't support escape sequences for - /// changing colors. - static bool ColorNeedsFlush(); - - /// This function returns the colorcode escape sequences. - /// If ColorNeedsFlush() is true then this function will change the colors - /// and return an empty escape sequence. In that case it is the - /// responsibility of the client to flush the output stream prior to - /// calling this function. - static const char *OutputColor(char c, bool bold, bool bg); - - /// Same as OutputColor, but only enables the bold attribute. - static const char *OutputBold(bool bg); - - /// This function returns the escape sequence to reverse forground and - /// background colors. - static const char *OutputReverse(); - - /// Resets the terminals colors, or returns an escape sequence to do so. - static const char *ResetColor(); - - /// Get the result of a process wide random number generator. The - /// generator will be automatically seeded in non-deterministic fashion. - static unsigned GetRandomNumber(); - /// @} - }; +class self_process; + +/// \brief Generic base class which exposes information about an operating +/// system process. +/// +/// This base class is the core interface behind any OS process. It exposes +/// methods to query for generic information about a particular process. +/// +/// Subclasses implement this interface based on the mechanisms available, and +/// can optionally expose more interfaces unique to certain process kinds. +class process { +protected: + /// \brief Only specific subclasses of process objects can be destroyed. + virtual ~process(); + +public: + /// \brief Operating system specific type to identify a process. + /// + /// Note that the windows one is defined to 'void *' as this is the + /// documented type for HANDLE on windows, and we don't want to pull in the + /// Windows headers here. +#if defined(LLVM_ON_UNIX) + typedef pid_t id_type; +#elif defined(LLVM_ON_WIN32) + typedef void *id_type; // Must match the type of HANDLE. +#else +#error Unsupported operating system. +#endif + + /// \brief Get the operating system specific identifier for this process. + virtual id_type get_id() = 0; + + /// \brief Get the user time consumed by this process. + /// + /// Note that this is often an approximation and may be zero on platforms + /// where we don't have good support for the functionality. + virtual TimeValue get_user_time() const = 0; + + /// \brief Get the system time consumed by this process. + /// + /// Note that this is often an approximation and may be zero on platforms + /// where we don't have good support for the functionality. + virtual TimeValue get_system_time() const = 0; + + /// \brief Get the wall time consumed by this process. + /// + /// Note that this is often an approximation and may be zero on platforms + /// where we don't have good support for the functionality. + virtual TimeValue get_wall_time() const = 0; + + /// \name Static factory routines for processes. + /// @{ + + /// \brief Get the process object for the current process. + static self_process *get_self(); + + /// @} + +}; + +/// \brief The specific class representing the current process. +/// +/// The current process can both specialize the implementation of the routines +/// and can expose certain information not available for other OS processes. +class self_process : public process { + friend class process; + + /// \brief Private destructor, as users shouldn't create objects of this + /// type. + virtual ~self_process(); + +public: + virtual id_type get_id(); + virtual TimeValue get_user_time() const; + virtual TimeValue get_system_time() const; + virtual TimeValue get_wall_time() const; + + /// \name Process configuration (sysconf on POSIX) + /// @{ + + /// \brief Get the virtual memory page size. + /// + /// Query the operating system for this process's page size. + size_t page_size() const { return PageSize; }; + + /// @} + +private: + /// \name Cached process state. + /// @{ + + /// \brief Cached page size, this cannot vary during the life of the process. + size_t PageSize; + + /// @} + + /// \brief Constructor, used by \c process::get_self() only. + self_process(); +}; + + +/// \brief A collection of legacy interfaces for querying information about the +/// current executing process. +class Process { +public: + /// \brief Return process memory usage. + /// This static function will return the total amount of memory allocated + /// by the process. This only counts the memory allocated via the malloc, + /// calloc and realloc functions and includes any "free" holes in the + /// allocated space. + static size_t GetMallocUsage(); + + /// This static function will set \p user_time to the amount of CPU time + /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU + /// time spent in system (kernel) mode. If the operating system does not + /// support collection of these metrics, a zero TimeValue will be for both + /// values. + /// \param elapsed Returns the TimeValue::now() giving current time + /// \param user_time Returns the current amount of user time for the process + /// \param sys_time Returns the current amount of system time for the process + static void GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, + TimeValue &sys_time); + + /// This static function will return the process' current user id number. + /// Not all operating systems support this feature. Where it is not + /// supported, the function should return 65536 as the value. + static int GetCurrentUserId(); + + /// This static function will return the process' current group id number. + /// Not all operating systems support this feature. Where it is not + /// supported, the function should return 65536 as the value. + static int GetCurrentGroupId(); + + /// This function makes the necessary calls to the operating system to + /// prevent core files or any other kind of large memory dumps that can + /// occur when a program fails. + /// @brief Prevent core file generation. + static void PreventCoreFiles(); + + /// This function determines if the standard input is connected directly + /// to a user's input (keyboard probably), rather than coming from a file + /// or pipe. + static bool StandardInIsUserInput(); + + /// This function determines if the standard output is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardOutIsDisplayed(); + + /// This function determines if the standard error is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardErrIsDisplayed(); + + /// This function determines if the given file descriptor is connected to + /// a "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool FileDescriptorIsDisplayed(int fd); + + /// This function determines if the given file descriptor is displayd and + /// supports colors. + static bool FileDescriptorHasColors(int fd); + + /// This function determines the number of columns in the window + /// if standard output is connected to a "tty" or "console" + /// window. If standard output is not connected to a tty or + /// console, or if the number of columns cannot be determined, + /// this routine returns zero. + static unsigned StandardOutColumns(); + + /// This function determines the number of columns in the window + /// if standard error is connected to a "tty" or "console" + /// window. If standard error is not connected to a tty or + /// console, or if the number of columns cannot be determined, + /// this routine returns zero. + static unsigned StandardErrColumns(); + + /// This function determines whether the terminal connected to standard + /// output supports colors. If standard output is not connected to a + /// terminal, this function returns false. + static bool StandardOutHasColors(); + + /// This function determines whether the terminal connected to standard + /// error supports colors. If standard error is not connected to a + /// terminal, this function returns false. + static bool StandardErrHasColors(); + + /// Whether changing colors requires the output to be flushed. + /// This is needed on systems that don't support escape sequences for + /// changing colors. + static bool ColorNeedsFlush(); + + /// This function returns the colorcode escape sequences. + /// If ColorNeedsFlush() is true then this function will change the colors + /// and return an empty escape sequence. In that case it is the + /// responsibility of the client to flush the output stream prior to + /// calling this function. + static const char *OutputColor(char c, bool bold, bool bg); + + /// Same as OutputColor, but only enables the bold attribute. + static const char *OutputBold(bool bg); + + /// This function returns the escape sequence to reverse forground and + /// background colors. + static const char *OutputReverse(); + + /// Resets the terminals colors, or returns an escape sequence to do so. + static const char *ResetColor(); + + /// Get the result of a process wide random number generator. The + /// generator will be automatically seeded in non-deterministic fashion. + static unsigned GetRandomNumber(); +}; + } } diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 7c9a951..bf65011 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_PROGRAM_H -#define LLVM_SYSTEM_PROGRAM_H +#ifndef LLVM_SUPPORT_PROGRAM_H +#define LLVM_SUPPORT_PROGRAM_H #include "llvm/Support/Path.h" @@ -39,14 +39,10 @@ namespace sys { /// @name Methods /// @{ - public: Program(); ~Program(); - /// Return process ID of this program. - unsigned GetPid() const; - /// This function executes the program using the \p arguments provided. The /// invoked program will inherit the stdin, stdout, and stderr file /// descriptors, the environment and other configuration settings of the @@ -103,17 +99,7 @@ namespace sys { ///< is non-empty upon return an error occurred while waiting. ); - /// This function terminates the program. - /// @returns true if an error occurred. - /// @see Execute - /// @brief Terminates the program. - bool Kill - ( std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string - ///< instance in which error messages will be returned. If the string - ///< is non-empty upon return an error occurred while killing the - ///< program. - ); - + public: /// This static constructor (factory) will attempt to locate a program in /// the operating system's file system using some pre-determined set of /// locations to search (e.g. the PATH on Unix). Paths with slashes are @@ -139,7 +125,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 diff --git a/include/llvm/Support/Recycler.h b/include/llvm/Support/Recycler.h index fa6e189..bcc561d 100644 --- a/include/llvm/Support/Recycler.h +++ b/include/llvm/Support/Recycler.h @@ -22,6 +22,8 @@ namespace llvm { +class BumpPtrAllocator; + /// PrintRecyclingAllocatorStats - Helper for RecyclingAllocator for /// printing statistics. /// @@ -87,6 +89,15 @@ public: } } + /// Special case for BumpPtrAllocator which has an empty Deallocate() + /// function. + /// + /// There is no need to traverse the free list, pulling all the objects into + /// cache. + void clear(BumpPtrAllocator&) { + FreeList.clearAndLeakNodesUnsafely(); + } + template<class SubClass, class AllocatorType> SubClass *Allocate(AllocatorType &Allocator) { assert(sizeof(SubClass) <= Size && diff --git a/include/llvm/Support/Regex.h b/include/llvm/Support/Regex.h index ffe09b1..82df2c6 100644 --- a/include/llvm/Support/Regex.h +++ b/include/llvm/Support/Regex.h @@ -7,7 +7,10 @@ // //===----------------------------------------------------------------------===// // -// This file implements a POSIX regular expression matcher. +// This file implements a POSIX regular expression matcher. Both Basic and +// Extended POSIX regular expressions (ERE) are supported. EREs were extended +// to support backreferences in matches. +// This implementation also supports matching strings with embedded NUL chars. // //===----------------------------------------------------------------------===// @@ -33,12 +36,14 @@ namespace llvm { /// null string after any newline in the string in addition to its normal /// function, and the $ anchor matches the null string before any /// newline in the string in addition to its normal function. - Newline=2 + Newline=2, + /// By default, the POSIX extended regular expression (ERE) syntax is + /// assumed. Pass this flag to turn on basic regular expressions (BRE) + /// instead. + BasicRegex=4 }; - /// Compiles the given POSIX Extended Regular Expression \p Regex. - /// This implementation supports regexes and matching strings with embedded - /// NUL characters. + /// Compiles the given regular expression \p Regex. Regex(StringRef Regex, unsigned Flags = NoFlags); ~Regex(); diff --git a/include/llvm/Support/RegistryParser.h b/include/llvm/Support/RegistryParser.h index 2cc5783..a6997b6 100644 --- a/include/llvm/Support/RegistryParser.h +++ b/include/llvm/Support/RegistryParser.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_REGISTRY_PARSER_H -#define LLVM_SUPPORT_REGISTRY_PARSER_H +#ifndef LLVM_SUPPORT_REGISTRYPARSER_H +#define LLVM_SUPPORT_REGISTRYPARSER_H #include "llvm/Support/CommandLine.h" #include "llvm/Support/Registry.h" @@ -52,4 +52,4 @@ namespace llvm { } -#endif // LLVM_SUPPORT_REGISTRY_PARSER_H +#endif // LLVM_SUPPORT_REGISTRYPARSER_H diff --git a/include/llvm/Support/SMLoc.h b/include/llvm/Support/SMLoc.h index 1bf810b..0906471 100644 --- a/include/llvm/Support/SMLoc.h +++ b/include/llvm/Support/SMLoc.h @@ -12,14 +12,14 @@ // //===----------------------------------------------------------------------===// -#ifndef SUPPORT_SMLOC_H -#define SUPPORT_SMLOC_H +#ifndef LLVM_SUPPORT_SMLOC_H +#define LLVM_SUPPORT_SMLOC_H #include <cassert> namespace llvm { -/// SMLoc - Represents a location in source code. +/// Represents a location in source code. class SMLoc { const char *Ptr; public: @@ -39,9 +39,11 @@ public: } }; -/// SMRange - Represents a range in source code. Note that unlike standard STL -/// ranges, the locations specified are considered to be *inclusive*. For -/// example, [X,X] *does* include X, it isn't an empty range. +/// Represents a range in source code. +/// +/// SMRange is implemented using a half-open range, as is the convention in C++. +/// In the string "abc", the range (1,3] represents the substring "bc", and the +/// range (2,2] represents an empty range between the characters "b" and "c". class SMRange { public: SMLoc Start, End; diff --git a/include/llvm/Support/SaveAndRestore.h b/include/llvm/Support/SaveAndRestore.h index ffa99b9..6330bec 100644 --- a/include/llvm/Support/SaveAndRestore.h +++ b/include/llvm/Support/SaveAndRestore.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_SAVERESTORE -#define LLVM_ADT_SAVERESTORE +#ifndef LLVM_SUPPORT_SAVEANDRESTORE_H +#define LLVM_SUPPORT_SAVEANDRESTORE_H namespace llvm { diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h index 634f4cf..465656b 100644 --- a/include/llvm/Support/Signals.h +++ b/include/llvm/Support/Signals.h @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_SIGNALS_H -#define LLVM_SYSTEM_SIGNALS_H +#ifndef LLVM_SUPPORT_SIGNALS_H +#define LLVM_SUPPORT_SIGNALS_H #include "llvm/Support/Path.h" +#include <cstdio> namespace llvm { namespace sys { @@ -38,6 +39,9 @@ namespace sys { /// @brief Print a stack trace if a fatal signal occurs. void PrintStackTraceOnErrorSignal(); + /// \brief Print the stack trace using the given \c FILE object. + void PrintStackTrace(FILE *); + /// AddSignalHandler - Add a function to be called when an abort/kill signal /// is delivered to the process. The handler can have a cookie passed to it /// to identify what instance of the handler it is. diff --git a/include/llvm/Support/Solaris.h b/include/llvm/Support/Solaris.h index 57eee2c..6228c4b 100644 --- a/include/llvm/Support/Solaris.h +++ b/include/llvm/Support/Solaris.h @@ -11,8 +11,8 @@ * *===----------------------------------------------------------------------===*/ -#ifndef LLVM_SYSTEM_SOLARIS_H -#define LLVM_SYSTEM_SOLARIS_H +#ifndef LLVM_SUPPORT_SOLARIS_H +#define LLVM_SUPPORT_SOLARIS_H #include <sys/types.h> #include <sys/regset.h> diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index bcf95f2..02abf92 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -13,17 +13,20 @@ // //===----------------------------------------------------------------------===// -#ifndef SUPPORT_SOURCEMGR_H -#define SUPPORT_SOURCEMGR_H +#ifndef LLVM_SUPPORT_SOURCEMGR_H +#define LLVM_SUPPORT_SOURCEMGR_H -#include "llvm/Support/SMLoc.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/SMLoc.h" #include <string> namespace llvm { class MemoryBuffer; class SourceMgr; class SMDiagnostic; + class SMFixIt; class Twine; class raw_ostream; @@ -95,6 +98,10 @@ public: return Buffers[i].Buffer; } + unsigned getNumBuffers() const { + return Buffers.size(); + } + SMLoc getParentIncludeLoc(unsigned i) const { assert(i < Buffers.size() && "Invalid Buffer ID!"); return Buffers[i].IncludeLoc; @@ -139,6 +146,7 @@ public: /// the default error handler is used. void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef<SMRange> Ranges = ArrayRef<SMRange>(), + ArrayRef<SMFixIt> FixIts = ArrayRef<SMFixIt>(), bool ShowColors = true) const; @@ -148,7 +156,8 @@ public: /// @param Msg If non-null, the kind of message (e.g., "error") which is /// prefixed to the message. SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, - ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) const; + ArrayRef<SMRange> Ranges = ArrayRef<SMRange>(), + ArrayRef<SMFixIt> FixIts = ArrayRef<SMFixIt>()) const; /// PrintIncludeStack - Prints the names of included files and the line of the /// file they were included from. A diagnostic handler can use this before @@ -160,6 +169,38 @@ public: }; +/// Represents a single fixit, a replacement of one range of text with another. +class SMFixIt { + SMRange Range; + + std::string Text; + +public: + // FIXME: Twine.str() is not very efficient. + SMFixIt(SMLoc Loc, const Twine &Insertion) + : Range(Loc, Loc), Text(Insertion.str()) { + assert(Loc.isValid()); + } + + // FIXME: Twine.str() is not very efficient. + SMFixIt(SMRange R, const Twine &Replacement) + : Range(R), Text(Replacement.str()) { + assert(R.isValid()); + } + + StringRef getText() const { return Text; } + SMRange getRange() const { return Range; } + + bool operator<(const SMFixIt &Other) const { + if (Range.Start.getPointer() != Other.Range.Start.getPointer()) + return Range.Start.getPointer() < Other.Range.Start.getPointer(); + if (Range.End.getPointer() != Other.Range.End.getPointer()) + return Range.End.getPointer() < Other.Range.End.getPointer(); + return Text < Other.Text; + } +}; + + /// SMDiagnostic - Instances of this class encapsulate one diagnostic report, /// allowing printing to a raw_ostream as a caret diagnostic. class SMDiagnostic { @@ -170,35 +211,46 @@ class SMDiagnostic { SourceMgr::DiagKind Kind; std::string Message, LineContents; std::vector<std::pair<unsigned, unsigned> > Ranges; + SmallVector<SMFixIt, 4> FixIts; public: // Null diagnostic. SMDiagnostic() : SM(0), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} // Diagnostic with no location (e.g. file not found, command line arg error). - SMDiagnostic(const std::string &filename, SourceMgr::DiagKind Knd, - const std::string &Msg) + SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg) : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {} // Diagnostic with a location. - SMDiagnostic(const SourceMgr &sm, SMLoc L, const std::string &FN, + SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, int Line, int Col, SourceMgr::DiagKind Kind, - const std::string &Msg, const std::string &LineStr, - ArrayRef<std::pair<unsigned,unsigned> > Ranges); + StringRef Msg, StringRef LineStr, + ArrayRef<std::pair<unsigned,unsigned> > Ranges, + ArrayRef<SMFixIt> FixIts = ArrayRef<SMFixIt>()); const SourceMgr *getSourceMgr() const { return SM; } SMLoc getLoc() const { return Loc; } - const std::string &getFilename() const { return Filename; } + StringRef getFilename() const { return Filename; } int getLineNo() const { return LineNo; } int getColumnNo() const { return ColumnNo; } SourceMgr::DiagKind getKind() const { return Kind; } - const std::string &getMessage() const { return Message; } - const std::string &getLineContents() const { return LineContents; } - const std::vector<std::pair<unsigned, unsigned> > &getRanges() const { + StringRef getMessage() const { return Message; } + StringRef getLineContents() const { return LineContents; } + ArrayRef<std::pair<unsigned, unsigned> > getRanges() const { return Ranges; } - void print(const char *ProgName, raw_ostream &S, bool ShowColors = true) const; + + void addFixIt(const SMFixIt &Hint) { + FixIts.push_back(Hint); + } + + ArrayRef<SMFixIt> getFixIts() const { + return FixIts; + } + + void print(const char *ProgName, raw_ostream &S, + bool ShowColors = true) const; }; } // end llvm namespace diff --git a/include/llvm/Support/StreamableMemoryObject.h b/include/llvm/Support/StreamableMemoryObject.h index a2b4bcb..3855485 100644 --- a/include/llvm/Support/StreamableMemoryObject.h +++ b/include/llvm/Support/StreamableMemoryObject.h @@ -8,13 +8,13 @@ //===----------------------------------------------------------------------===// -#ifndef STREAMABLEMEMORYOBJECT_H_ -#define STREAMABLEMEMORYOBJECT_H_ +#ifndef LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H +#define LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/MemoryObject.h" #include "llvm/Support/DataStream.h" +#include "llvm/Support/MemoryObject.h" #include <vector> namespace llvm { diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h index de05e0b..71adbc5 100644 --- a/include/llvm/Support/StringPool.h +++ b/include/llvm/Support/StringPool.h @@ -30,8 +30,8 @@ #define LLVM_SUPPORT_STRINGPOOL_H #include "llvm/ADT/StringMap.h" -#include <new> #include <cassert> +#include <new> namespace llvm { diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index 6c0592c..e65f9cc 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_SWAP_BYTE_ORDER_H -#define LLVM_SYSTEM_SWAP_BYTE_ORDER_H +#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H +#define LLVM_SUPPORT_SWAPBYTEORDER_H #include "llvm/Support/DataTypes.h" #include <cstddef> diff --git a/include/llvm/Support/TargetFolder.h b/include/llvm/Support/TargetFolder.h index 45f7816..5c1978d 100644 --- a/include/llvm/Support/TargetFolder.h +++ b/include/llvm/Support/TargetFolder.h @@ -19,10 +19,10 @@ #ifndef LLVM_SUPPORT_TARGETFOLDER_H #define LLVM_SUPPORT_TARGETFOLDER_H -#include "llvm/Constants.h" -#include "llvm/InstrTypes.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Analysis/ConstantFolding.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/InstrTypes.h" namespace llvm { diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index ca58bfb..b06676d 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -19,10 +19,10 @@ #ifndef LLVM_SUPPORT_TARGETREGISTRY_H #define LLVM_SUPPORT_TARGETREGISTRY_H -#include "llvm/Support/CodeGen.h" #include "llvm/ADT/Triple.h" -#include <string> +#include "llvm/Support/CodeGen.h" #include <cassert> +#include <string> namespace llvm { class AsmPrinter; @@ -41,7 +41,6 @@ namespace llvm { class MCRegisterInfo; class MCStreamer; class MCSubtargetInfo; - class MCTargetAsmLexer; class MCTargetAsmParser; class TargetMachine; class TargetOptions; @@ -96,9 +95,6 @@ namespace llvm { typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, StringRef TT, StringRef CPU); - typedef MCTargetAsmLexer *(*MCAsmLexerCtorTy)(const Target &T, - const MCRegisterInfo &MRI, - const MCAsmInfo &MAI); typedef MCTargetAsmParser *(*MCAsmParserCtorTy)(MCSubtargetInfo &STI, MCAsmParser &P); typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, @@ -182,10 +178,6 @@ namespace llvm { /// MCAsmBackend, if registered. MCAsmBackendCtorTy MCAsmBackendCtorFn; - /// MCAsmLexerCtorFn - Construction function for this target's - /// MCTargetAsmLexer, if registered. - MCAsmLexerCtorTy MCAsmLexerCtorFn; - /// MCAsmParserCtorFn - Construction function for this target's /// MCTargetAsmParser, if registered. MCAsmParserCtorTy MCAsmParserCtorFn; @@ -242,9 +234,6 @@ namespace llvm { /// hasMCAsmBackend - Check if this target supports .o generation. bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != 0; } - /// hasMCAsmLexer - Check if this target supports .s lexing. - bool hasMCAsmLexer() const { return MCAsmLexerCtorFn != 0; } - /// hasAsmParser - Check if this target supports .s parsing. bool hasMCAsmParser() const { return MCAsmParserCtorFn != 0; } @@ -360,15 +349,6 @@ namespace llvm { return MCAsmBackendCtorFn(*this, Triple, CPU); } - /// createMCAsmLexer - Create a target specific assembly lexer. - /// - MCTargetAsmLexer *createMCAsmLexer(const MCRegisterInfo &MRI, - const MCAsmInfo &MAI) const { - if (!MCAsmLexerCtorFn) - return 0; - return MCAsmLexerCtorFn(*this, MRI, MAI); - } - /// createMCAsmParser - Create a target specific assembly parser. /// /// \param Parser The target independent parser implementation to use for @@ -676,20 +656,6 @@ namespace llvm { T.MCAsmBackendCtorFn = Fn; } - /// RegisterMCAsmLexer - Register a MCTargetAsmLexer implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCAsmLexer for the target. - static void RegisterMCAsmLexer(Target &T, Target::MCAsmLexerCtorTy Fn) { - if (!T.MCAsmLexerCtorFn) - T.MCAsmLexerCtorFn = Fn; - } - /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for /// the given target. /// @@ -1070,28 +1036,6 @@ namespace llvm { } }; - /// RegisterMCAsmLexer - Helper template for registering a target specific - /// assembly lexer, for use in the target machine initialization - /// function. Usage: - /// - /// extern "C" void LLVMInitializeFooMCAsmLexer() { - /// extern Target TheFooTarget; - /// RegisterMCAsmLexer<FooMCAsmLexer> X(TheFooTarget); - /// } - template<class MCAsmLexerImpl> - struct RegisterMCAsmLexer { - RegisterMCAsmLexer(Target &T) { - TargetRegistry::RegisterMCAsmLexer(T, &Allocator); - } - - private: - static MCTargetAsmLexer *Allocator(const Target &T, - const MCRegisterInfo &MRI, - const MCAsmInfo &MAI) { - return new MCAsmLexerImpl(T, MRI, MAI); - } - }; - /// RegisterMCAsmParser - Helper template for registering a target specific /// assembly parser, for use in the target machine initialization /// function. Usage: diff --git a/include/llvm/Support/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h index 62ec90a..7518626 100644 --- a/include/llvm/Support/ThreadLocal.h +++ b/include/llvm/Support/ThreadLocal.h @@ -11,11 +11,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_THREAD_LOCAL_H -#define LLVM_SYSTEM_THREAD_LOCAL_H +#ifndef LLVM_SUPPORT_THREADLOCAL_H +#define LLVM_SUPPORT_THREADLOCAL_H -#include "llvm/Support/Threading.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Threading.h" #include <cassert> namespace llvm { diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h index 9017afb..a7e8774 100644 --- a/include/llvm/Support/Threading.h +++ b/include/llvm/Support/Threading.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_THREADING_H -#define LLVM_SYSTEM_THREADING_H +#ifndef LLVM_SUPPORT_THREADING_H +#define LLVM_SUPPORT_THREADING_H namespace llvm { /// llvm_start_multithreaded - Allocate and initialize structures needed to diff --git a/include/llvm/Support/TimeValue.h b/include/llvm/Support/TimeValue.h index e780b50..4b48b84 100644 --- a/include/llvm/Support/TimeValue.h +++ b/include/llvm/Support/TimeValue.h @@ -11,12 +11,12 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_SUPPORT_TIMEVALUE_H +#define LLVM_SUPPORT_TIMEVALUE_H + #include "llvm/Support/DataTypes.h" #include <string> -#ifndef LLVM_SYSTEM_TIMEVALUE_H -#define LLVM_SYSTEM_TIMEVALUE_H - namespace llvm { namespace sys { /// This class is used where a precise fixed point in time is required. The @@ -82,6 +82,9 @@ namespace sys { /// @name Constructors /// @{ public: + /// \brief Default construct a time value, initializing to ZeroTime. + TimeValue() : seconds_(0), nanos_(0) {} + /// Caller provides the exact value in seconds and nanoseconds. The /// \p nanos argument defaults to zero for convenience. /// @brief Explicit constructor @@ -237,7 +240,7 @@ namespace sys { /// Posix, correcting for the difference in Posix zero time. /// @brief Convert to unix time (100 nanoseconds since 12:00:00a Jan 1,1970) uint64_t toPosixTime() const { - uint64_t result = seconds_ - PosixZeroTime.seconds_; + uint64_t result = seconds_ - PosixZeroTimeSeconds; result += nanos_ / NANOSECONDS_PER_POSIX_TICK; return result; } @@ -245,14 +248,14 @@ namespace sys { /// Converts the TimeValue into the corresponding number of seconds /// since the epoch (00:00:00 Jan 1,1970). uint64_t toEpochTime() const { - return seconds_ - PosixZeroTime.seconds_; + return seconds_ - PosixZeroTimeSeconds; } /// Converts the TimeValue into the corresponding number of "ticks" for /// Win32 platforms, correcting for the difference in Win32 zero time. /// @brief Convert to windows time (seconds since 12:00:00a Jan 1, 1601) uint64_t toWin32Time() const { - uint64_t result = seconds_ - Win32ZeroTime.seconds_; + uint64_t result = seconds_ - Win32ZeroTimeSeconds; result += nanos_ / NANOSECONDS_PER_WIN32_TICK; return result; } @@ -261,7 +264,7 @@ namespace sys { /// correction for the Posix zero time. /// @brief Convert to timespec time (ala POSIX.1b) void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const { - seconds = seconds_ - PosixZeroTime.seconds_; + seconds = seconds_ - PosixZeroTimeSeconds; nanos = nanos_; } @@ -328,7 +331,7 @@ namespace sys { /// TimeValue and assigns that value to \p this. /// @brief Convert seconds form PosixTime to TimeValue void fromEpochTime( SecondsType seconds ) { - seconds_ = seconds + PosixZeroTime.seconds_; + seconds_ = seconds + PosixZeroTimeSeconds; nanos_ = 0; this->normalize(); } @@ -337,7 +340,7 @@ namespace sys { /// corresponding TimeValue and assigns that value to \p this. /// @brief Convert seconds form Windows FILETIME to TimeValue void fromWin32Time( uint64_t win32Time ) { - this->seconds_ = win32Time / 10000000 + Win32ZeroTime.seconds_; + this->seconds_ = win32Time / 10000000 + Win32ZeroTimeSeconds; this->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; } @@ -357,6 +360,9 @@ namespace sys { /// Store the values as a <timeval>. SecondsType seconds_;///< Stores the seconds part of the TimeVal NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal + + static const SecondsType PosixZeroTimeSeconds; + static const SecondsType Win32ZeroTimeSeconds; /// @} }; diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index a741882..d009d7f 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -6,22 +6,17 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines three classes: Timer, TimeRegion, and TimerGroup, -// documented below. -// -//===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_TIMER_H #define LLVM_SUPPORT_TIMER_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" -#include "llvm/ADT/StringRef.h" #include <cassert> #include <string> -#include <vector> #include <utility> +#include <vector> namespace llvm { @@ -78,7 +73,7 @@ public: /// invocations of its startTimer()/stopTimer() methods. Given appropriate OS /// support it can also keep track of the RSS of the program at various points. /// By default, the Timer will print the amount of time it has captured to -/// standard error when the laster timer is destroyed, otherwise it is printed +/// standard error when the last timer is destroyed, otherwise it is printed /// when its TimerGroup is destroyed. Timers do not print their information /// if they are never started. /// @@ -126,7 +121,7 @@ private: /// The TimeRegion class is used as a helper class to call the startTimer() and /// stopTimer() methods of the Timer class. When the object is constructed, it -/// starts the timer specified as it's argument. When it is destroyed, it stops +/// starts the timer specified as its argument. When it is destroyed, it stops /// the relevant timer. This makes it easy to time a region of code. /// class TimeRegion { diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h index 65b182a..b3b7c57 100644 --- a/include/llvm/Support/ToolOutputFile.h +++ b/include/llvm/Support/ToolOutputFile.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_TOOL_OUTPUT_FILE_H -#define LLVM_SUPPORT_TOOL_OUTPUT_FILE_H +#ifndef LLVM_SUPPORT_TOOLOUTPUTFILE_H +#define LLVM_SUPPORT_TOOLOUTPUTFILE_H #include "llvm/Support/raw_ostream.h" diff --git a/include/llvm/Support/Valgrind.h b/include/llvm/Support/Valgrind.h index e147647..a1397db 100644 --- a/include/llvm/Support/Valgrind.h +++ b/include/llvm/Support/Valgrind.h @@ -16,8 +16,8 @@ #ifndef LLVM_SYSTEM_VALGRIND_H #define LLVM_SYSTEM_VALGRIND_H -#include "llvm/Support/Compiler.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Support/Compiler.h" #include <stddef.h> #if LLVM_ENABLE_THREADS != 0 && !defined(NDEBUG) diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h index dbcf0fd..b49341c 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/Support/ValueHandle.h @@ -16,10 +16,11 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/Value.h" +#include "llvm/IR/Value.h" 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 0000000..b58496b --- /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 8d74e10..ecce713 100644 --- a/include/llvm/Support/Win64EH.h +++ b/include/llvm/Support/Win64EH.h @@ -17,6 +17,7 @@ #define LLVM_SUPPORT_WIN64EH_H #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Endian.h" namespace llvm { namespace Win64EH { @@ -39,11 +40,17 @@ enum UnwindOpcodes { /// or part thereof. union UnwindCode { struct { - uint8_t codeOffset; - uint8_t unwindOp:4, - opInfo:4; + support::ulittle8_t CodeOffset; + support::ulittle8_t UnwindOpAndOpInfo; } u; - uint16_t frameOffset; + support::ulittle16_t FrameOffset; + + uint8_t getUnwindOp() const { + return u.UnwindOpAndOpInfo & 0x0F; + } + uint8_t getOpInfo() const { + return (u.UnwindOpAndOpInfo >> 4) & 0x0F; + } }; enum { @@ -60,37 +67,75 @@ enum { /// RuntimeFunction - An entry in the table of functions with unwind info. struct RuntimeFunction { - uint64_t startAddress; - uint64_t endAddress; - uint64_t unwindInfoOffset; + support::ulittle32_t StartAddress; + support::ulittle32_t EndAddress; + support::ulittle32_t UnwindInfoOffset; }; /// UnwindInfo - An entry in the exception table. struct UnwindInfo { - uint8_t version:3, - flags:5; - uint8_t prologSize; - uint8_t numCodes; - uint8_t frameRegister:4, - frameOffset:4; - UnwindCode unwindCodes[1]; + support::ulittle8_t VersionAndFlags; + support::ulittle8_t PrologSize; + support::ulittle8_t NumCodes; + support::ulittle8_t FrameRegisterAndOffset; + UnwindCode UnwindCodes[1]; + uint8_t getVersion() const { + return VersionAndFlags & 0x07; + } + uint8_t getFlags() const { + return (VersionAndFlags >> 3) & 0x1f; + } + uint8_t getFrameRegister() const { + return FrameRegisterAndOffset & 0x0f; + } + uint8_t getFrameOffset() const { + return (FrameRegisterAndOffset >> 4) & 0x0f; + } + + // The data after unwindCodes depends on flags. + // If UNW_ExceptionHandler or UNW_TerminateHandler is set then follows + // the address of the language-specific exception handler. + // If UNW_ChainInfo is set then follows a RuntimeFunction which defines + // the chained unwind info. + // For more information please see MSDN at: + // http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx + + /// \brief Return pointer to language specific data part of UnwindInfo. void *getLanguageSpecificData() { - return reinterpret_cast<void *>(&unwindCodes[(numCodes+1) & ~1]); + return reinterpret_cast<void *>(&UnwindCodes[(NumCodes+1) & ~1]); } - uint64_t getLanguageSpecificHandlerOffset() { - return *reinterpret_cast<uint64_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]); } - void setLanguageSpecificHandlerOffset(uint64_t offset) { - *reinterpret_cast<uint64_t *>(getLanguageSpecificData()) = offset; + + /// \brief Return image-relative offset of language-specific exception handler. + uint32_t getLanguageSpecificHandlerOffset() const { + return *reinterpret_cast<const uint32_t *>(getLanguageSpecificData()); } - RuntimeFunction *getChainedFunctionEntry() { - return reinterpret_cast<RuntimeFunction *>(getLanguageSpecificData()); + + /// \brief Set image-relative offset of language-specific exception handler. + void setLanguageSpecificHandlerOffset(uint32_t offset) { + *reinterpret_cast<uint32_t *>(getLanguageSpecificData()) = offset; } + + /// \brief Return pointer to exception-specific data. void *getExceptionData() { - return reinterpret_cast<void *>(reinterpret_cast<uint64_t *>( + return reinterpret_cast<void *>(reinterpret_cast<uint32_t *>( getLanguageSpecificData())+1); } + + /// \brief Return pointer to chained unwind info. + 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/YAMLParser.h b/include/llvm/Support/YAMLParser.h index 12958fa..6e4f57f 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -35,15 +35,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_YAML_PARSER_H -#define LLVM_SUPPORT_YAML_PARSER_H +#ifndef LLVM_SUPPORT_YAMLPARSER_H +#define LLVM_SUPPORT_YAMLPARSER_H #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/SMLoc.h" - #include <limits> #include <utility> @@ -77,7 +76,11 @@ std::string escape(StringRef Input); /// documents. class Stream { public: + /// @brief This keeps a reference to the string referenced by \p Input. Stream(StringRef Input, SourceMgr &); + + /// @brief This takes ownership of \p InputBuffer. + Stream(MemoryBuffer *InputBuffer, SourceMgr &); ~Stream(); document_iterator begin(); @@ -181,7 +184,7 @@ public: : Node(NK_Scalar, D, Anchor) , Value(Val) { SMLoc Start = SMLoc::getFromPointer(Val.begin()); - SMLoc End = SMLoc::getFromPointer(Val.end() - 1); + SMLoc End = SMLoc::getFromPointer(Val.end()); SourceRange = SMRange(Start, End); } diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h new file mode 100644 index 0000000..801868f --- /dev/null +++ b/include/llvm/Support/YAMLTraits.h @@ -0,0 +1,1104 @@ +//===- llvm/Supporrt/YAMLTraits.h -------------------------------*- C++ -*-===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_YAMLTRAITS_H +#define LLVM_SUPPORT_YAMLTRAITS_H + + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/YAMLParser.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/system_error.h" +#include "llvm/Support/type_traits.h" + + +namespace llvm { +namespace yaml { + + +/// This class should be specialized by any type that needs to be converted +/// to/from a YAML mapping. For example: +/// +/// struct ScalarBitSetTraits<MyStruct> { +/// static void mapping(IO &io, MyStruct &s) { +/// io.mapRequired("name", s.name); +/// io.mapRequired("size", s.size); +/// io.mapOptional("age", s.age); +/// } +/// }; +template<class T> +struct MappingTraits { + // Must provide: + // static void mapping(IO &io, T &fields); +}; + + +/// This class should be specialized by any integral type that converts +/// to/from a YAML scalar where there is a one-to-one mapping between +/// in-memory values and a string in YAML. For example: +/// +/// struct ScalarEnumerationTraits<Colors> { +/// static void enumeration(IO &io, Colors &value) { +/// io.enumCase(value, "red", cRed); +/// io.enumCase(value, "blue", cBlue); +/// io.enumCase(value, "green", cGreen); +/// } +/// }; +template<typename T> +struct ScalarEnumerationTraits { + // Must provide: + // static void enumeration(IO &io, T &value); +}; + + +/// This class should be specialized by any integer type that is a union +/// of bit values and the YAML representation is a flow sequence of +/// strings. For example: +/// +/// struct ScalarBitSetTraits<MyFlags> { +/// static void bitset(IO &io, MyFlags &value) { +/// io.bitSetCase(value, "big", flagBig); +/// io.bitSetCase(value, "flat", flagFlat); +/// io.bitSetCase(value, "round", flagRound); +/// } +/// }; +template<typename T> +struct ScalarBitSetTraits { + // Must provide: + // static void bitset(IO &io, T &value); +}; + + +/// This class should be specialized by type that requires custom conversion +/// to/from a yaml scalar. For example: +/// +/// template<> +/// struct ScalarTraits<MyType> { +/// static void output(const MyType &val, void*, llvm::raw_ostream &out) { +/// // stream out custom formatting +/// out << llvm::format("%x", val); +/// } +/// static StringRef input(StringRef scalar, void*, MyType &value) { +/// // parse scalar and set `value` +/// // return empty string on success, or error string +/// return StringRef(); +/// } +/// }; +template<typename T> +struct ScalarTraits { + // Must provide: + // + // Function to write the value as a string: + //static void output(const T &value, void *ctxt, llvm::raw_ostream &out); + // + // Function to convert a string to a value. Returns the empty + // StringRef on success or an error string if string is malformed: + //static StringRef input(StringRef scalar, void *ctxt, T &value); +}; + + +/// This class should be specialized by any type that needs to be converted +/// to/from a YAML sequence. For example: +/// +/// template<> +/// struct SequenceTraits< std::vector<MyType> > { +/// static size_t size(IO &io, std::vector<MyType> &seq) { +/// return seq.size(); +/// } +/// static MyType& element(IO &, std::vector<MyType> &seq, size_t index) { +/// if ( index >= seq.size() ) +/// seq.resize(index+1); +/// return seq[index]; +/// } +/// }; +template<typename T> +struct SequenceTraits { + // Must provide: + // static size_t size(IO &io, T &seq); + // static T::value_type& element(IO &io, T &seq, size_t index); + // + // The following is option and will cause generated YAML to use + // a flow sequence (e.g. [a,b,c]). + // static const bool flow = true; +}; + + +/// This class should be specialized by any type that needs to be converted +/// to/from a list of YAML documents. +template<typename T> +struct DocumentListTraits { + // Must provide: + // static size_t size(IO &io, T &seq); + // static T::value_type& element(IO &io, T &seq, size_t index); +}; + + +// Only used by compiler if both template types are the same +template <typename T, T> +struct SameType; + +// Only used for better diagnostics of missing traits +template <typename T> +struct MissingTrait; + + + +// Test if ScalarEnumerationTraits<T> is defined on type T. +template <class T> +struct has_ScalarEnumerationTraits +{ + typedef void (*Signature_enumeration)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_enumeration, &U::enumeration>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<ScalarEnumerationTraits<T> >(0)) == 1); +}; + + +// Test if ScalarBitSetTraits<T> is defined on type T. +template <class T> +struct has_ScalarBitSetTraits +{ + typedef void (*Signature_bitset)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_bitset, &U::bitset>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(0)) == 1); +}; + + +// Test if ScalarTraits<T> is defined on type T. +template <class T> +struct has_ScalarTraits +{ + typedef StringRef (*Signature_input)(StringRef, void*, T&); + typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&); + + template <typename U> + static char test(SameType<Signature_input, &U::input>*, + SameType<Signature_output, &U::output>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<ScalarTraits<T> >(0,0)) == 1); +}; + + +// Test if MappingTraits<T> is defined on type T. +template <class T> +struct has_MappingTraits +{ + typedef void (*Signature_mapping)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_mapping, &U::mapping>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<MappingTraits<T> >(0)) == 1); +}; + + +// Test if SequenceTraits<T> is defined on type T. +template <class T> +struct has_SequenceMethodTraits +{ + typedef size_t (*Signature_size)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_size, &U::size>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<SequenceTraits<T> >(0)) == 1); +}; + + +// has_FlowTraits<int> will cause an error with some compilers because +// it subclasses int. Using this wrapper only instantiates the +// real has_FlowTraits only if the template type is a class. +template <typename T, bool Enabled = llvm::is_class<T>::value> +class has_FlowTraits +{ +public: + static const bool value = false; +}; + +// Some older gcc compilers don't support straight forward tests +// for members, so test for ambiguity cause by the base and derived +// classes both defining the member. +template <class T> +struct has_FlowTraits<T, true> +{ + struct Fallback { bool flow; }; + struct Derived : T, Fallback { }; + + template<typename C> + static char (&f(SameType<bool Fallback::*, &C::flow>*))[1]; + + template<typename C> + static char (&f(...))[2]; + +public: + static bool const value = sizeof(f<Derived>(0)) == 2; +}; + + + +// Test if SequenceTraits<T> is defined on type T +template<typename T> +struct has_SequenceTraits : public llvm::integral_constant<bool, + has_SequenceMethodTraits<T>::value > { }; + + +// Test if DocumentListTraits<T> is defined on type T +template <class T> +struct has_DocumentListTraits +{ + typedef size_t (*Signature_size)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_size, &U::size>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<DocumentListTraits<T> >(0)) == 1); +}; + + + + +template<typename T> +struct missingTraits : public llvm::integral_constant<bool, + !has_ScalarEnumerationTraits<T>::value + && !has_ScalarBitSetTraits<T>::value + && !has_ScalarTraits<T>::value + && !has_MappingTraits<T>::value + && !has_SequenceTraits<T>::value + && !has_DocumentListTraits<T>::value > {}; + + +// Base class for Input and Output. +class IO { +public: + + IO(void *Ctxt=NULL); + virtual ~IO(); + + virtual bool outputting() = 0; + + virtual unsigned beginSequence() = 0; + virtual bool preflightElement(unsigned, void *&) = 0; + virtual void postflightElement(void*) = 0; + virtual void endSequence() = 0; + + virtual unsigned beginFlowSequence() = 0; + virtual bool preflightFlowElement(unsigned, void *&) = 0; + virtual void postflightFlowElement(void*) = 0; + virtual void endFlowSequence() = 0; + + virtual void beginMapping() = 0; + virtual void endMapping() = 0; + virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; + virtual void postflightKey(void*) = 0; + + virtual void beginEnumScalar() = 0; + virtual bool matchEnumScalar(const char*, bool) = 0; + virtual void endEnumScalar() = 0; + + virtual bool beginBitSetScalar(bool &) = 0; + virtual bool bitSetMatch(const char*, bool) = 0; + virtual void endBitSetScalar() = 0; + + virtual void scalarString(StringRef &) = 0; + + virtual void setError(const Twine &) = 0; + + template <typename T> + void enumCase(T &Val, const char* Str, const T ConstVal) { + if ( matchEnumScalar(Str, outputting() && Val == ConstVal) ) { + Val = ConstVal; + } + } + + // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF + template <typename T> + void enumCase(T &Val, const char* Str, const uint32_t ConstVal) { + if ( matchEnumScalar(Str, outputting() && Val == static_cast<T>(ConstVal)) ) { + Val = ConstVal; + } + } + + template <typename T> + void bitSetCase(T &Val, const char* Str, const T ConstVal) { + if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { + Val = Val | ConstVal; + } + } + + // allow anonymous enum values to be used with LLVM_YAML_STRONG_TYPEDEF + template <typename T> + void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) { + if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { + Val = Val | ConstVal; + } + } + + void *getContext(); + void setContext(void *); + + template <typename T> + void mapRequired(const char* Key, T& Val) { + this->processKey(Key, Val, true); + } + + template <typename T> + typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type + mapOptional(const char* Key, T& Val) { + // omit key/value instead of outputting empty sequence + if ( this->outputting() && !(Val.begin() != Val.end()) ) + return; + this->processKey(Key, Val, false); + } + + template <typename T> + typename llvm::enable_if_c<!has_SequenceTraits<T>::value,void>::type + mapOptional(const char* Key, T& Val) { + this->processKey(Key, Val, false); + } + + template <typename T> + void mapOptional(const char* Key, T& Val, const T& Default) { + this->processKeyWithDefault(Key, Val, Default, false); + } + + +private: + template <typename T> + void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue, + bool Required) { + void *SaveInfo; + bool UseDefault; + const bool sameAsDefault = outputting() && Val == DefaultValue; + if ( this->preflightKey(Key, Required, sameAsDefault, UseDefault, + SaveInfo) ) { + yamlize(*this, Val, Required); + this->postflightKey(SaveInfo); + } + else { + if ( UseDefault ) + Val = DefaultValue; + } + } + + template <typename T> + void processKey(const char *Key, T &Val, bool Required) { + void *SaveInfo; + bool UseDefault; + if ( this->preflightKey(Key, Required, false, UseDefault, SaveInfo) ) { + yamlize(*this, Val, Required); + this->postflightKey(SaveInfo); + } + } + +private: + void *Ctxt; +}; + + + +template<typename T> +typename llvm::enable_if_c<has_ScalarEnumerationTraits<T>::value,void>::type +yamlize(IO &io, T &Val, bool) { + io.beginEnumScalar(); + ScalarEnumerationTraits<T>::enumeration(io, Val); + io.endEnumScalar(); +} + +template<typename T> +typename llvm::enable_if_c<has_ScalarBitSetTraits<T>::value,void>::type +yamlize(IO &io, T &Val, bool) { + bool DoClear; + if ( io.beginBitSetScalar(DoClear) ) { + if ( DoClear ) + Val = static_cast<T>(0); + ScalarBitSetTraits<T>::bitset(io, Val); + io.endBitSetScalar(); + } +} + + +template<typename T> +typename llvm::enable_if_c<has_ScalarTraits<T>::value,void>::type +yamlize(IO &io, T &Val, bool) { + if ( io.outputting() ) { + std::string Storage; + llvm::raw_string_ostream Buffer(Storage); + ScalarTraits<T>::output(Val, io.getContext(), Buffer); + StringRef Str = Buffer.str(); + io.scalarString(Str); + } + else { + StringRef Str; + io.scalarString(Str); + StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val); + if ( !Result.empty() ) { + io.setError(llvm::Twine(Result)); + } + } +} + + +template<typename T> +typename llvm::enable_if_c<has_MappingTraits<T>::value, void>::type +yamlize(IO &io, T &Val, bool) { + io.beginMapping(); + MappingTraits<T>::mapping(io, Val); + io.endMapping(); +} + +template<typename T> +typename llvm::enable_if_c<missingTraits<T>::value, void>::type +yamlize(IO &io, T &Val, bool) { + char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; +} + +template<typename T> +typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type +yamlize(IO &io, T &Seq, bool) { + if ( has_FlowTraits< SequenceTraits<T> >::value ) { + unsigned incnt = io.beginFlowSequence(); + unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; + for(unsigned i=0; i < count; ++i) { + void *SaveInfo; + if ( io.preflightFlowElement(i, SaveInfo) ) { + yamlize(io, SequenceTraits<T>::element(io, Seq, i), true); + io.postflightFlowElement(SaveInfo); + } + } + io.endFlowSequence(); + } + else { + unsigned incnt = io.beginSequence(); + unsigned count = io.outputting() ? SequenceTraits<T>::size(io, Seq) : incnt; + for(unsigned i=0; i < count; ++i) { + void *SaveInfo; + if ( io.preflightElement(i, SaveInfo) ) { + yamlize(io, SequenceTraits<T>::element(io, Seq, i), true); + io.postflightElement(SaveInfo); + } + } + io.endSequence(); + } +} + + +template<> +struct ScalarTraits<bool> { + static void output(const bool &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, bool &); +}; + +template<> +struct ScalarTraits<StringRef> { + static void output(const StringRef &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, StringRef &); +}; + +template<> +struct ScalarTraits<uint8_t> { + static void output(const uint8_t &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, uint8_t &); +}; + +template<> +struct ScalarTraits<uint16_t> { + static void output(const uint16_t &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, uint16_t &); +}; + +template<> +struct ScalarTraits<uint32_t> { + static void output(const uint32_t &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, uint32_t &); +}; + +template<> +struct ScalarTraits<uint64_t> { + static void output(const uint64_t &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, uint64_t &); +}; + +template<> +struct ScalarTraits<int8_t> { + static void output(const int8_t &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, int8_t &); +}; + +template<> +struct ScalarTraits<int16_t> { + static void output(const int16_t &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, int16_t &); +}; + +template<> +struct ScalarTraits<int32_t> { + static void output(const int32_t &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, int32_t &); +}; + +template<> +struct ScalarTraits<int64_t> { + static void output(const int64_t &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, int64_t &); +}; + +template<> +struct ScalarTraits<float> { + static void output(const float &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, float &); +}; + +template<> +struct ScalarTraits<double> { + static void output(const double &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, double &); +}; + + + +// Utility for use within MappingTraits<>::mapping() method +// to [de]normalize an object for use with YAML conversion. +template <typename TNorm, typename TFinal> +struct MappingNormalization { + MappingNormalization(IO &i_o, TFinal &Obj) + : io(i_o), BufPtr(NULL), Result(Obj) { + if ( io.outputting() ) { + BufPtr = new (&Buffer) TNorm(io, Obj); + } + else { + BufPtr = new (&Buffer) TNorm(io); + } + } + + ~MappingNormalization() { + if ( ! io.outputting() ) { + Result = BufPtr->denormalize(io); + } + BufPtr->~TNorm(); + } + + TNorm* operator->() { return BufPtr; } + +private: + typedef llvm::AlignedCharArrayUnion<TNorm> Storage; + + Storage Buffer; + IO &io; + TNorm *BufPtr; + TFinal &Result; +}; + + + +// Utility for use within MappingTraits<>::mapping() method +// to [de]normalize an object for use with YAML conversion. +template <typename TNorm, typename TFinal> +struct MappingNormalizationHeap { + MappingNormalizationHeap(IO &i_o, TFinal &Obj) + : io(i_o), BufPtr(NULL), Result(Obj) { + if ( io.outputting() ) { + BufPtr = new (&Buffer) TNorm(io, Obj); + } + else { + BufPtr = new TNorm(io); + } + } + + ~MappingNormalizationHeap() { + if ( io.outputting() ) { + BufPtr->~TNorm(); + } + else { + Result = BufPtr->denormalize(io); + } + } + + TNorm* operator->() { return BufPtr; } + +private: + typedef llvm::AlignedCharArrayUnion<TNorm> Storage; + + Storage Buffer; + IO &io; + TNorm *BufPtr; + TFinal &Result; +}; + + + +/// +/// The Input class is used to parse a yaml document into in-memory structs +/// and vectors. +/// +/// It works by using YAMLParser to do a syntax parse of the entire yaml +/// document, then the Input class builds a graph of HNodes which wraps +/// each yaml Node. The extra layer is buffering. The low level yaml +/// parser only lets you look at each node once. The buffering layer lets +/// you search and interate multiple times. This is necessary because +/// the mapRequired() method calls may not be in the same order +/// as the keys in the document. +/// +class Input : public IO { +public: + // Construct a yaml Input object from a StringRef and optional user-data. + Input(StringRef InputContent, void *Ctxt=NULL); + ~Input(); + + // Check if there was an syntax or semantic error during parsing. + llvm::error_code error(); + + // To set alternate error reporting. + void setDiagHandler(llvm::SourceMgr::DiagHandlerTy Handler, void *Ctxt = 0); + +private: + virtual bool outputting(); + virtual void beginMapping(); + virtual void endMapping(); + virtual bool preflightKey(const char *, bool, bool, bool &, void *&); + virtual void postflightKey(void *); + virtual unsigned beginSequence(); + virtual void endSequence(); + virtual bool preflightElement(unsigned index, void *&); + virtual void postflightElement(void *); + virtual unsigned beginFlowSequence(); + virtual bool preflightFlowElement(unsigned , void *&); + virtual void postflightFlowElement(void *); + virtual void endFlowSequence(); + virtual void beginEnumScalar(); + virtual bool matchEnumScalar(const char*, bool); + virtual void endEnumScalar(); + virtual bool beginBitSetScalar(bool &); + virtual bool bitSetMatch(const char *, bool ); + virtual void endBitSetScalar(); + virtual void scalarString(StringRef &); + virtual void setError(const Twine &message); + + class HNode { + public: + HNode(Node *n) : _node(n) { } + virtual ~HNode() { } + static inline bool classof(const HNode *) { return true; } + + Node *_node; + }; + + class EmptyHNode : public HNode { + public: + EmptyHNode(Node *n) : HNode(n) { } + virtual ~EmptyHNode() {} + static inline bool classof(const HNode *n) { + return NullNode::classof(n->_node); + } + static inline bool classof(const EmptyHNode *) { return true; } + }; + + class ScalarHNode : public HNode { + public: + ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } + virtual ~ScalarHNode() { } + + StringRef value() const { return _value; } + + static inline bool classof(const HNode *n) { + return ScalarNode::classof(n->_node); + } + static inline bool classof(const ScalarHNode *) { return true; } + protected: + StringRef _value; + }; + + class MapHNode : public HNode { + public: + MapHNode(Node *n) : HNode(n) { } + virtual ~MapHNode(); + + static inline bool classof(const HNode *n) { + return MappingNode::classof(n->_node); + } + static inline bool classof(const MapHNode *) { return true; } + + struct StrMappingInfo { + static StringRef getEmptyKey() { return StringRef(); } + static StringRef getTombstoneKey() { return StringRef(" ", 0); } + static unsigned getHashValue(StringRef const val) { + return llvm::HashString(val); } + static bool isEqual(StringRef const lhs, + StringRef const rhs) { return lhs.equals(rhs); } + }; + typedef llvm::DenseMap<StringRef, HNode*, StrMappingInfo> NameToNode; + + bool isValidKey(StringRef key); + + NameToNode Mapping; + llvm::SmallVector<const char*, 6> ValidKeys; + }; + + class SequenceHNode : public HNode { + public: + SequenceHNode(Node *n) : HNode(n) { } + virtual ~SequenceHNode(); + + static inline bool classof(const HNode *n) { + return SequenceNode::classof(n->_node); + } + static inline bool classof(const SequenceHNode *) { return true; } + + std::vector<HNode*> Entries; + }; + + Input::HNode *createHNodes(Node *node); + void setError(HNode *hnode, const Twine &message); + void setError(Node *node, const Twine &message); + + +public: + // These are only used by operator>>. They could be private + // if those templated things could be made friends. + bool setCurrentDocument(); + void nextDocument(); + +private: + llvm::SourceMgr SrcMgr; // must be before Strm + OwningPtr<llvm::yaml::Stream> Strm; + OwningPtr<HNode> TopNode; + llvm::error_code EC; + llvm::BumpPtrAllocator StringAllocator; + llvm::yaml::document_iterator DocIterator; + std::vector<bool> BitValuesUsed; + HNode *CurrentNode; + bool ScalarMatchFound; +}; + + + + +/// +/// The Output class is used to generate a yaml document from in-memory structs +/// and vectors. +/// +class Output : public IO { +public: + Output(llvm::raw_ostream &, void *Ctxt=NULL); + virtual ~Output(); + + virtual bool outputting(); + virtual void beginMapping(); + virtual void endMapping(); + virtual bool preflightKey(const char *key, bool, bool, bool &, void *&); + virtual void postflightKey(void *); + virtual unsigned beginSequence(); + virtual void endSequence(); + virtual bool preflightElement(unsigned, void *&); + virtual void postflightElement(void *); + virtual unsigned beginFlowSequence(); + virtual bool preflightFlowElement(unsigned, void *&); + virtual void postflightFlowElement(void *); + virtual void endFlowSequence(); + virtual void beginEnumScalar(); + virtual bool matchEnumScalar(const char*, bool); + virtual void endEnumScalar(); + virtual bool beginBitSetScalar(bool &); + virtual bool bitSetMatch(const char *, bool ); + virtual void endBitSetScalar(); + virtual void scalarString(StringRef &); + virtual void setError(const Twine &message); + +public: + // These are only used by operator<<. They could be private + // if that templated operator could be made a friend. + void beginDocuments(); + bool preflightDocument(unsigned); + void postflightDocument(); + void endDocuments(); + +private: + void output(StringRef s); + void outputUpToEndOfLine(StringRef s); + void newLineCheck(); + void outputNewLine(); + void paddedKey(StringRef key); + + enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey }; + + llvm::raw_ostream &Out; + SmallVector<InState, 8> StateStack; + int Column; + int ColumnAtFlowStart; + bool NeedBitValueComma; + bool NeedFlowSequenceComma; + bool EnumerationMatchFound; + bool NeedsNewLine; +}; + + + + +/// YAML I/O does conversion based on types. But often native data types +/// are just a typedef of built in intergral types (e.g. int). But the C++ +/// type matching system sees through the typedef and all the typedefed types +/// look like a built in type. This will cause the generic YAML I/O conversion +/// to be used. To provide better control over the YAML conversion, you can +/// use this macro instead of typedef. It will create a class with one field +/// and automatic conversion operators to and from the base type. +/// Based on BOOST_STRONG_TYPEDEF +#define LLVM_YAML_STRONG_TYPEDEF(_base, _type) \ + struct _type { \ + _type() { } \ + _type(const _base v) : value(v) { } \ + _type(const _type &v) : value(v.value) {} \ + _type &operator=(const _type &rhs) { value = rhs.value; return *this; }\ + _type &operator=(const _base &rhs) { value = rhs; return *this; } \ + operator const _base & () const { return value; } \ + bool operator==(const _type &rhs) const { return value == rhs.value; } \ + bool operator==(const _base &rhs) const { return value == rhs; } \ + bool operator<(const _type &rhs) const { return value < rhs.value; } \ + _base value; \ + }; + + + +/// +/// Use these types instead of uintXX_t in any mapping to have +/// its yaml output formatted as hexadecimal. +/// +LLVM_YAML_STRONG_TYPEDEF(uint8_t, Hex8) +LLVM_YAML_STRONG_TYPEDEF(uint16_t, Hex16) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, Hex32) +LLVM_YAML_STRONG_TYPEDEF(uint64_t, Hex64) + + +template<> +struct ScalarTraits<Hex8> { + static void output(const Hex8 &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, Hex8 &); +}; + +template<> +struct ScalarTraits<Hex16> { + static void output(const Hex16 &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, Hex16 &); +}; + +template<> +struct ScalarTraits<Hex32> { + static void output(const Hex32 &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, Hex32 &); +}; + +template<> +struct ScalarTraits<Hex64> { + static void output(const Hex64 &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, Hex64 &); +}; + + +// Define non-member operator>> so that Input can stream in a document list. +template <typename T> +inline +typename llvm::enable_if_c<has_DocumentListTraits<T>::value,Input &>::type +operator>>(Input &yin, T &docList) { + int i = 0; + while ( yin.setCurrentDocument() ) { + yamlize(yin, DocumentListTraits<T>::element(yin, docList, i), true); + if ( yin.error() ) + return yin; + yin.nextDocument(); + ++i; + } + return yin; +} + +// Define non-member operator>> so that Input can stream in a map as a document. +template <typename T> +inline +typename llvm::enable_if_c<has_MappingTraits<T>::value,Input &>::type +operator>>(Input &yin, T &docMap) { + yin.setCurrentDocument(); + yamlize(yin, docMap, true); + return yin; +} + +// Define non-member operator>> so that Input can stream in a sequence as +// a document. +template <typename T> +inline +typename llvm::enable_if_c<has_SequenceTraits<T>::value,Input &>::type +operator>>(Input &yin, T &docSeq) { + yin.setCurrentDocument(); + yamlize(yin, docSeq, true); + return yin; +} + +// Provide better error message about types missing a trait specialization +template <typename T> +inline +typename llvm::enable_if_c<missingTraits<T>::value,Input &>::type +operator>>(Input &yin, T &docSeq) { + char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; + return yin; +} + + +// Define non-member operator<< so that Output can stream out document list. +template <typename T> +inline +typename llvm::enable_if_c<has_DocumentListTraits<T>::value,Output &>::type +operator<<(Output &yout, T &docList) { + yout.beginDocuments(); + const size_t count = DocumentListTraits<T>::size(yout, docList); + for(size_t i=0; i < count; ++i) { + if ( yout.preflightDocument(i) ) { + yamlize(yout, DocumentListTraits<T>::element(yout, docList, i), true); + yout.postflightDocument(); + } + } + yout.endDocuments(); + return yout; +} + +// Define non-member operator<< so that Output can stream out a map. +template <typename T> +inline +typename llvm::enable_if_c<has_MappingTraits<T>::value,Output &>::type +operator<<(Output &yout, T &map) { + yout.beginDocuments(); + if ( yout.preflightDocument(0) ) { + yamlize(yout, map, true); + yout.postflightDocument(); + } + yout.endDocuments(); + return yout; +} + +// Define non-member operator<< so that Output can stream out a sequence. +template <typename T> +inline +typename llvm::enable_if_c<has_SequenceTraits<T>::value,Output &>::type +operator<<(Output &yout, T &seq) { + yout.beginDocuments(); + if ( yout.preflightDocument(0) ) { + yamlize(yout, seq, true); + yout.postflightDocument(); + } + yout.endDocuments(); + return yout; +} + +// Provide better error message about types missing a trait specialization +template <typename T> +inline +typename llvm::enable_if_c<missingTraits<T>::value,Output &>::type +operator<<(Output &yout, T &seq) { + char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; + return yout; +} + + +} // namespace yaml +} // namespace llvm + + +/// Utility for declaring that a std::vector of a particular type +/// should be considered a YAML sequence. +#define LLVM_YAML_IS_SEQUENCE_VECTOR(_type) \ + namespace llvm { \ + namespace yaml { \ + template<> \ + struct SequenceTraits< std::vector<_type> > { \ + static size_t size(IO &io, std::vector<_type> &seq) { \ + return seq.size(); \ + } \ + static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ + if ( index >= seq.size() ) \ + seq.resize(index+1); \ + return seq[index]; \ + } \ + }; \ + } \ + } + +/// Utility for declaring that a std::vector of a particular type +/// should be considered a YAML flow sequence. +#define LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(_type) \ + namespace llvm { \ + namespace yaml { \ + template<> \ + struct SequenceTraits< std::vector<_type> > { \ + static size_t size(IO &io, std::vector<_type> &seq) { \ + return seq.size(); \ + } \ + static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ + if ( index >= seq.size() ) \ + seq.resize(index+1); \ + return seq[index]; \ + } \ + static const bool flow = true; \ + }; \ + } \ + } + +/// Utility for declaring that a std::vector of a particular type +/// should be considered a YAML document list. +#define LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(_type) \ + namespace llvm { \ + namespace yaml { \ + template<> \ + struct DocumentListTraits< std::vector<_type> > { \ + static size_t size(IO &io, std::vector<_type> &seq) { \ + return seq.size(); \ + } \ + static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ + if ( index >= seq.size() ) \ + seq.resize(index+1); \ + return seq[index]; \ + } \ + }; \ + } \ + } + + + +#endif // LLVM_SUPPORT_YAMLTRAITS_H diff --git a/include/llvm/Support/circular_raw_ostream.h b/include/llvm/Support/circular_raw_ostream.h index 2823af3..9000306 100644 --- a/include/llvm/Support/circular_raw_ostream.h +++ b/include/llvm/Support/circular_raw_ostream.h @@ -71,7 +71,7 @@ namespace llvm /// flushBuffer - Dump the contents of the buffer to Stream. /// - void flushBuffer(void) { + void flushBuffer() { if (Filled) // Write the older portion of the buffer. TheStream->write(Cur, BufferArray + BufferSize - Cur); @@ -151,7 +151,7 @@ namespace llvm /// flushBufferWithBanner - Force output of the buffer along with /// a small header. /// - void flushBufferWithBanner(void); + void flushBufferWithBanner(); private: /// releaseStream - Delete the held stream if needed. Otherwise, diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index eab0f2d..d2b4a2a 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -29,7 +29,6 @@ namespace llvm { /// a chunk at a time. class raw_ostream { private: - // Do not implement. raw_ostream is noncopyable. void operator=(const raw_ostream &) LLVM_DELETED_FUNCTION; raw_ostream(const raw_ostream &) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/Support/system_error.h b/include/llvm/Support/system_error.h index 0d164f6..43dace6 100644 --- a/include/llvm/Support/system_error.h +++ b/include/llvm/Support/system_error.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYSTEM_SYSTEM_ERROR_H -#define LLVM_SYSTEM_SYSTEM_ERROR_H +#ifndef LLVM_SUPPORT_SYSTEM_ERROR_H +#define LLVM_SUPPORT_SYSTEM_ERROR_H #include "llvm/Support/Compiler.h" diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index f930639..906e97c 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -145,6 +145,10 @@ template <typename T> struct is_pointer<T* const> : true_type {}; template <typename T> struct is_pointer<T* volatile> : true_type {}; template <typename T> struct is_pointer<T* const volatile> : true_type {}; +/// \brief Metafunction that determines wheather the given type is a reference. +template <typename T> struct is_reference : false_type {}; +template <typename T> struct is_reference<T&> : true_type {}; + /// \brief Metafunction that determines whether the given type is either an /// integral type or an enumeration type. /// @@ -205,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; }; |