diff options
Diffstat (limited to 'include/llvm/Support')
64 files changed, 6326 insertions, 930 deletions
diff --git a/include/llvm/Support/AIXDataTypesFix.h b/include/llvm/Support/AIXDataTypesFix.h new file mode 100644 index 0000000..a9a9147 --- /dev/null +++ b/include/llvm/Support/AIXDataTypesFix.h @@ -0,0 +1,25 @@ +//===-- llvm/Support/AIXDataTypesFix.h - Fix datatype defs ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file overrides default system-defined types and limits which cannot be +// done in DataTypes.h.in because it is processed by autoheader first, which +// comments out any #undef statement +// +//===----------------------------------------------------------------------===// + +// No include guards desired! + +#ifndef SUPPORT_DATATYPES_H +#error "AIXDataTypesFix.h must only be included via DataTypes.h!" +#endif + +// GCC is strict about defining large constants: they must have LL modifier. +// These will be defined properly at the end of DataTypes.h +#undef INT64_MAX +#undef INT64_MIN diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 6a7a1a6..cebfa79 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -49,12 +49,12 @@ struct AlignOf { }; -/// alignof - A templated function that returns the mininum alignment of +/// alignOf - A templated function that returns the minimum alignment of /// of a type. This provides no extra functionality beyond the AlignOf /// class besides some cosmetic cleanliness. Example usage: -/// alignof<int>() returns the alignment of an int. +/// alignOf<int>() returns the alignment of an int. template <typename T> -static inline unsigned alignof() { return AlignOf<T>::Alignment; } +static inline unsigned alignOf() { return AlignOf<T>::Alignment; } } // end namespace llvm #endif diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index 4a7251f..c680709 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -16,13 +16,15 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/MathExtras.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <algorithm> #include <cassert> #include <cstdlib> #include <cstddef> namespace llvm { +template <typename T> struct ReferenceAdder { typedef T& result; }; +template <typename T> struct ReferenceAdder<T&> { typedef T result; }; class MallocAllocator { public: @@ -201,7 +203,7 @@ public: char *End = Slab == Allocator.CurSlab ? Allocator.CurPtr : (char *)Slab + Slab->Size; for (char *Ptr = (char*)(Slab+1); Ptr < End; Ptr += sizeof(T)) { - Ptr = Allocator.AlignPtr(Ptr, alignof<T>()); + Ptr = Allocator.AlignPtr(Ptr, alignOf<T>()); if (Ptr + sizeof(T) <= End) reinterpret_cast<T*>(Ptr)->~T(); } @@ -221,16 +223,12 @@ public: inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) { struct S { char c; -#ifdef __GNUC__ - char x __attribute__((aligned)); -#else union { double D; long double LD; long long L; void *P; } x; -#endif }; return Allocator.Allocate(Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x))); diff --git a/include/llvm/Support/Atomic.h b/include/llvm/Support/Atomic.h new file mode 100644 index 0000000..1a6c606 --- /dev/null +++ b/include/llvm/Support/Atomic.h @@ -0,0 +1,39 @@ +//===- llvm/Support/Atomic.h - Atomic Operations -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys atomic operations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_ATOMIC_H +#define LLVM_SYSTEM_ATOMIC_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + namespace sys { + void MemoryFence(); + +#ifdef _MSC_VER + typedef long cas_flag; +#else + typedef uint32_t cas_flag; +#endif + cas_flag CompareAndSwap(volatile cas_flag* ptr, + cas_flag new_value, + cas_flag old_value); + cas_flag AtomicIncrement(volatile cas_flag* ptr); + cas_flag AtomicDecrement(volatile cas_flag* ptr); + cas_flag AtomicAdd(volatile cas_flag* ptr, cas_flag val); + cas_flag AtomicMul(volatile cas_flag* ptr, cas_flag val); + cas_flag AtomicDiv(volatile cas_flag* ptr, cas_flag val); + } +} + +#endif diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 78254ae..6739255 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -11,7 +11,7 @@ // // Structures and enums defined within this file where created using // information from Microsoft's publicly available PE/COFF format document: -// +// // Microsoft Portable Executable and Common Object File Format Specification // Revision 8.1 - February 15, 2008 // @@ -23,7 +23,7 @@ #ifndef LLVM_SUPPORT_WIN_COFF_H #define LLVM_SUPPORT_WIN_COFF_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cstring> namespace llvm { @@ -69,7 +69,7 @@ namespace COFF { SF_ClassMask = 0x00FF0000, SF_ClassShift = 16, - SF_WeakReference = 0x01000000 + SF_WeakExternal = 0x01000000 }; enum SymbolSectionNumber { @@ -133,13 +133,13 @@ namespace COFF { }; enum SymbolComplexType { - IMAGE_SYM_DTYPE_NULL = 0, ///< No complex type; simple scalar variable. + IMAGE_SYM_DTYPE_NULL = 0, ///< No complex type; simple scalar variable. IMAGE_SYM_DTYPE_POINTER = 1, ///< A pointer to base type. IMAGE_SYM_DTYPE_FUNCTION = 2, ///< A function that returns a base type. IMAGE_SYM_DTYPE_ARRAY = 3, ///< An array of base type. - + /// Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT)) - SCT_COMPLEX_TYPE_SHIFT = 8 + SCT_COMPLEX_TYPE_SHIFT = 4 }; struct section { diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index 9b6a409..8a998a8 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -52,12 +52,7 @@ public: CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } CallSiteBase(ValTy *II) { *this = get(II); } - CallSiteBase(InstrTy *II) { - assert(II && "Null instruction given?"); - *this = get(II); - assert(I.getPointer() && "Not a call?"); - } - +protected: /// CallSiteBase::get - This static method is sort of like a constructor. It /// will create an appropriate call site for a Call or Invoke instruction, but /// it can also create a null initialized CallSiteBase object for something @@ -72,7 +67,7 @@ public: } return CallSiteBase(); } - +public: /// isCall - true if a CallInst is enclosed. /// Note that !isCall() does not mean it is an InvokeInst enclosed, /// it also could signify a NULL Instruction pointer. @@ -282,16 +277,6 @@ public: bool operator==(const CallSite &CS) const { return I == CS.I; } bool operator!=(const CallSite &CS) const { return I != CS.I; } - - /// CallSite::get - This static method is sort of like a constructor. It will - /// create an appropriate call site for a Call or Invoke instruction, but it - /// can also create a null initialized CallSite object for something which is - /// NOT a call site. - /// - static CallSite get(Value *V) { - return Base::get(V); - } - bool operator<(const CallSite &CS) const { return getInstruction() < CS.getInstruction(); } diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index c589171..6bb9806 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -232,8 +232,8 @@ inline typename cast_retty<X, Y>::ret_type dyn_cast(const Y &Val) { // value is accepted. // template <class X, class Y> -inline typename cast_retty<X, Y>::ret_type dyn_cast_or_null(const Y &Val) { - return (Val && isa<X>(Val)) ? cast<X, Y>(Val) : 0; +inline typename cast_retty<X, Y*>::ret_type dyn_cast_or_null(Y *Val) { + return (Val && isa<X>(Val)) ? cast<X>(Val) : 0; } } // End llvm namespace diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 14b36f8..67f0fd7 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -15,48 +15,50 @@ #ifndef LLVM_SUPPORT_COMPILER_H #define LLVM_SUPPORT_COMPILER_H +#ifndef __has_feature +# define __has_feature(x) 0 +#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 /// functions, making them private to any shared library they are linked into. - -/// LLVM_GLOBAL_VISIBILITY - If a class marked with this attribute is linked -/// into a shared library, then the class will be accessible from outside the -/// the library. Can also be used to mark variables and functions, making them -/// accessible from outside any shared library they are linked into. -#if defined(__MINGW32__) || defined(__CYGWIN__) -#define LLVM_LIBRARY_VISIBILITY -#define LLVM_GLOBAL_VISIBILITY __declspec(dllexport) -#elif (__GNUC__ >= 4) +#if (__GNUC__ >= 4) && !defined(__MINGW32__) && !defined(__CYGWIN__) #define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) -#define LLVM_GLOBAL_VISIBILITY __attribute__ ((visibility("default"))) #else #define LLVM_LIBRARY_VISIBILITY -#define LLVM_GLOBAL_VISIBILITY #endif #if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -#define ATTRIBUTE_USED __attribute__((__used__)) +#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) #else -#define ATTRIBUTE_USED +#define LLVM_ATTRIBUTE_USED #endif +// Some compilers warn about unused functions. When a function is sometimes +// used or not depending on build settings (e.g. a function only called from +// within "assert"), this attribute can be used to suppress such warnings. +// +// However, it shouldn't be used for unused *variables*, as those have a much +// more portable solution: +// (void)unused_var_name; +// Prefer cast-to-void wherever it is sufficient. #if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -#define ATTRIBUTE_UNUSED __attribute__((__unused__)) +#define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) #else -#define ATTRIBUTE_UNUSED +#define LLVM_ATTRIBUTE_UNUSED #endif #ifdef __GNUC__ // aka 'ATTRIBUTE_CONST' but following LLVM Conventions. -#define ATTRIBUTE_READNONE __attribute__((__const__)) +#define LLVM_ATTRIBUTE_READNONE __attribute__((__const__)) #else -#define ATTRIBUTE_READNONE +#define LLVM_ATTRIBUTE_READNONE #endif #ifdef __GNUC__ // aka 'ATTRIBUTE_PURE' but following LLVM Conventions. -#define ATTRIBUTE_READONLY __attribute__((__pure__)) +#define LLVM_ATTRIBUTE_READONLY __attribute__((__pure__)) #else -#define ATTRIBUTE_READONLY +#define LLVM_ATTRIBUTE_READONLY #endif #if (__GNUC__ >= 4) @@ -78,34 +80,50 @@ #define TEMPLATE_INSTANTIATION(X) #endif -// DISABLE_INLINE - 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 DISABLE_INLINE __attribute__((noinline)) +#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) #elif defined(_MSC_VER) -#define DISABLE_INLINE __declspec(noinline) +#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) #else -#define DISABLE_INLINE +#define LLVM_ATTRIBUTE_NOINLINE #endif -// 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 ALWAYS_INLINE __attribute__((always_inline)) +#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline #else -// TODO: No idea how to do this with MSVC. -#define ALWAYS_INLINE +#define LLVM_ATTRIBUTE_ALWAYS_INLINE #endif #ifdef __GNUC__ -#define NORETURN __attribute__((noreturn)) +#define LLVM_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define LLVM_ATTRIBUTE_NORETURN +#endif + +// LLVM_ATTRIBUTE_DEPRECATED(decl, "message") +#if __has_feature(attribute_deprecated_with_message) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl __attribute__((deprecated(message))) +#elif defined(__GNUC__) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl __attribute__((deprecated)) #elif defined(_MSC_VER) -#define NORETURN __declspec(noreturn) +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + __declspec(deprecated(message)) decl #else -#define NORETURN +# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \ + decl #endif #endif diff --git a/include/llvm/Support/ConstantFolder.h b/include/llvm/Support/ConstantFolder.h index ea6c5fd..bd3765d 100644 --- a/include/llvm/Support/ConstantFolder.h +++ b/include/llvm/Support/ConstantFolder.h @@ -33,50 +33,34 @@ public: // Binary Operators //===--------------------------------------------------------------------===// - Constant *CreateAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getAdd(LHS, RHS); - } - Constant *CreateNSWAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNSWAdd(LHS, RHS); - } - Constant *CreateNUWAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNUWAdd(LHS, RHS); + Constant *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW); } Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFAdd(LHS, RHS); } - Constant *CreateSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getSub(LHS, RHS); - } - Constant *CreateNSWSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNSWSub(LHS, RHS); - } - Constant *CreateNUWSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNUWSub(LHS, RHS); + Constant *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW); } Constant *CreateFSub(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFSub(LHS, RHS); } - Constant *CreateMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getMul(LHS, RHS); - } - Constant *CreateNSWMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNSWMul(LHS, RHS); - } - Constant *CreateNUWMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getNUWMul(LHS, RHS); + Constant *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW); } Constant *CreateFMul(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFMul(LHS, RHS); } - Constant *CreateUDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getUDiv(LHS, RHS); - } - Constant *CreateSDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getSDiv(LHS, RHS); + Constant *CreateUDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getUDiv(LHS, RHS, isExact); } - Constant *CreateExactSDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getExactSDiv(LHS, RHS); + Constant *CreateSDiv(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getSDiv(LHS, RHS, isExact); } Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFDiv(LHS, RHS); @@ -90,14 +74,17 @@ public: Constant *CreateFRem(Constant *LHS, Constant *RHS) const { return ConstantExpr::getFRem(LHS, RHS); } - Constant *CreateShl(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getShl(LHS, RHS); + Constant *CreateShl(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW); } - Constant *CreateLShr(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getLShr(LHS, RHS); + Constant *CreateLShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getLShr(LHS, RHS, isExact); } - Constant *CreateAShr(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getAShr(LHS, RHS); + Constant *CreateAShr(Constant *LHS, Constant *RHS, + bool isExact = false) const { + return ConstantExpr::getAShr(LHS, RHS, isExact); } Constant *CreateAnd(Constant *LHS, Constant *RHS) const { return ConstantExpr::getAnd(LHS, RHS); @@ -118,14 +105,9 @@ public: // Unary Operators //===--------------------------------------------------------------------===// - Constant *CreateNeg(Constant *C) const { - return ConstantExpr::getNeg(C); - } - Constant *CreateNSWNeg(Constant *C) const { - return ConstantExpr::getNSWNeg(C); - } - Constant *CreateNUWNeg(Constant *C) const { - return ConstantExpr::getNUWNeg(C); + Constant *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + return ConstantExpr::getNeg(C, HasNUW, HasNSW); } Constant *CreateFNeg(Constant *C) const { return ConstantExpr::getFNeg(C); diff --git a/include/llvm/Support/ConstantRange.h b/include/llvm/Support/ConstantRange.h index 29086b2..ced3a2c 100644 --- a/include/llvm/Support/ConstantRange.h +++ b/include/llvm/Support/ConstantRange.h @@ -33,7 +33,7 @@ #define LLVM_SUPPORT_CONSTANT_RANGE_H #include "llvm/ADT/APInt.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { @@ -54,7 +54,7 @@ public: /// @brief Initialize a range of values explicitly. This will assert out if /// Lower==Upper and Lower != Min or Max value for its type. It will also /// assert out if the two APInt's are not the same bit width. - ConstantRange(const APInt& Lower, const APInt& Upper); + ConstantRange(const APInt &Lower, const APInt &Upper); /// makeICmpRegion - Produce the smallest range that contains all values that /// might satisfy the comparison specified by Pred when compared to any value @@ -92,6 +92,11 @@ public: /// bool isWrappedSet() const; + /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of + /// its bitwidth, for example: i8 [120, 140). + /// + bool isSignWrappedSet() const; + /// contains - Return true if the specified value is in the set. /// bool contains(const APInt &Val) const; @@ -219,6 +224,14 @@ public: /// \p Other. ConstantRange udiv(const ConstantRange &Other) const; + /// binaryAnd - return a new range representing the possible values resulting + /// from a binary-and of a value in this range by a value in \p Other. + ConstantRange binaryAnd(const ConstantRange &Other) const; + + /// binaryOr - return a new range representing the possible values resulting + /// from a binary-or of a value in this range by a value in \p Other. + ConstantRange binaryOr(const ConstantRange &Other) const; + /// shl - Return a new range representing the possible values resulting /// from a left shift of a value in this range by a value in \p Other. /// TODO: This isn't fully implemented yet. diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index d66609f..2e9b5d4 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -67,6 +67,14 @@ public: /// the backtrace of the crash on failures. bool RunSafely(void (*Fn)(void*), void *UserData); + /// \brief Execute the provide callback function (with the given arguments) in + /// a protected context which is run in another thread (optionally with a + /// requested stack size). + /// + /// See RunSafely() and llvm_execute_on_thread(). + bool RunSafelyOnThread(void (*Fn)(void*), void *UserData, + unsigned RequestedStackSize = 0); + /// \brief Explicitly trigger a crash recovery in the current process, and /// return failure from RunSafely(). This function does not return. void HandleCrash(); diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake new file mode 100644 index 0000000..72c4518 --- /dev/null +++ b/include/llvm/Support/DataTypes.h.cmake @@ -0,0 +1,189 @@ +/*===-- include/Support/DataTypes.h - Define fixed size types -----*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file contains definitions to figure out the size of _HOST_ data types.*| +|* This file is important because different host OS's define different macros,*| +|* which makes portability tough. This file exports the following *| +|* definitions: *| +|* *| +|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| +|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| +|* *| +|* No library is required when using these functinons. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +/* Please leave this file C-compatible. */ + +#ifndef SUPPORT_DATATYPES_H +#define SUPPORT_DATATYPES_H + +#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} +#cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} +#cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} +#cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T} +#cmakedefine HAVE_U_INT64_T ${HAVE_U_INT64_T} + +#ifdef __cplusplus +#include <cmath> +#else +#include <math.h> +#endif + +#ifndef _MSC_VER + +/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS + being defined. We would define it here, but in order to prevent Bad Things + happening when system headers or C++ STL headers include stdint.h before we + define it here, we define it on the g++ command line (in Makefile.rules). */ +#if !defined(__STDC_LIMIT_MACROS) +# error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h" +#endif + +#if !defined(__STDC_CONSTANT_MACROS) +# error "Must #define __STDC_CONSTANT_MACROS before " \ + "#including Support/DataTypes.h" +#endif + +/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#ifdef _AIX +#include "llvm/Support/AIXDataTypesFix.h" +#endif + +/* Handle incorrect definition of uint64_t as u_int64_t */ +#ifndef HAVE_UINT64_T +#ifdef HAVE_U_INT64_T +typedef u_int64_t uint64_t; +#else +# error "Don't have a definition for uint64_t on this platform" +#endif +#endif + +#ifdef _OpenBSD_ +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#endif + +#else /* _MSC_VER */ +/* Visual C++ doesn't provide standard integer headers, but it does provide + built-in data types. */ +#include <stdlib.h> +#include <stddef.h> +#include <sys/types.h> +#ifdef __cplusplus +#include <cmath> +#else +#include <math.h> +#endif +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed int ssize_t; +#ifndef INT8_MAX +# define INT8_MAX 127 +#endif +#ifndef INT8_MIN +# define INT8_MIN -128 +#endif +#ifndef UINT8_MAX +# define UINT8_MAX 255 +#endif +#ifndef INT16_MAX +# define INT16_MAX 32767 +#endif +#ifndef INT16_MIN +# define INT16_MIN -32768 +#endif +#ifndef UINT16_MAX +# define UINT16_MAX 65535 +#endif +#ifndef INT32_MAX +# define INT32_MAX 2147483647 +#endif +#ifndef INT32_MIN +# define INT32_MIN -2147483648 +#endif +#ifndef UINT32_MAX +# define UINT32_MAX 4294967295U +#endif +/* Certain compatibility updates to VC++ introduce the `cstdint' + * header, which defines the INT*_C macros. On default installs they + * are absent. */ +#ifndef INT8_C +# define INT8_C(C) C##i8 +#endif +#ifndef UINT8_C +# define UINT8_C(C) C##ui8 +#endif +#ifndef INT16_C +# define INT16_C(C) C##i16 +#endif +#ifndef UINT16_C +# define UINT16_C(C) C##ui16 +#endif +#ifndef INT32_C +# define INT32_C(C) C##i32 +#endif +#ifndef UINT32_C +# define UINT32_C(C) C##ui32 +#endif +#ifndef INT64_C +# define INT64_C(C) C##i64 +#endif +#ifndef UINT64_C +# define UINT64_C(C) C##ui64 +#endif +#endif /* _MSC_VER */ + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#if __GNUC__ > 3 +#define END_WITH_NULL __attribute__((sentinel)) +#else +#define END_WITH_NULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* SUPPORT_DATATYPES_H */ diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in new file mode 100644 index 0000000..5965e8c --- /dev/null +++ b/include/llvm/Support/DataTypes.h.in @@ -0,0 +1,111 @@ +/*===-- include/System/DataTypes.h - Define fixed size types -----*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file contains definitions to figure out the size of _HOST_ data types.*| +|* This file is important because different host OS's define different macros,*| +|* which makes portability tough. This file exports the following *| +|* definitions: *| +|* *| +|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| +|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| +|* *| +|* No library is required when using these functions. *| +|* *| +|*===----------------------------------------------------------------------===*/ + +/* Please leave this file C-compatible. */ + +#ifndef SUPPORT_DATATYPES_H +#define SUPPORT_DATATYPES_H + +#undef HAVE_SYS_TYPES_H +#undef HAVE_INTTYPES_H +#undef HAVE_STDINT_H +#undef HAVE_UINT64_T +#undef HAVE_U_INT64_T + +#ifdef __cplusplus +#include <cmath> +#else +#include <math.h> +#endif + +/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS + being defined. We would define it here, but in order to prevent Bad Things + happening when system headers or C++ STL headers include stdint.h before we + define it here, we define it on the g++ command line (in Makefile.rules). */ +#if !defined(__STDC_LIMIT_MACROS) +# error "Must #define __STDC_LIMIT_MACROS before #including System/DataTypes.h" +#endif + +#if !defined(__STDC_CONSTANT_MACROS) +# error "Must #define __STDC_CONSTANT_MACROS before " \ + "#including System/DataTypes.h" +#endif + +/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#ifdef _AIX +#include "llvm/Support/AIXDataTypesFix.h" +#endif + +/* Handle incorrect definition of uint64_t as u_int64_t */ +#ifndef HAVE_UINT64_T +#ifdef HAVE_U_INT64_T +typedef u_int64_t uint64_t; +#else +# error "Don't have a definition for uint64_t on this platform" +#endif +#endif + +#ifdef _OpenBSD_ +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#endif + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#if __GNUC__ > 3 +#define END_WITH_NULL __attribute__((sentinel)) +#else +#define END_WITH_NULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* SUPPORT_DATATYPES_H */ diff --git a/include/llvm/Support/Disassembler.h b/include/llvm/Support/Disassembler.h new file mode 100644 index 0000000..6d1cc0f --- /dev/null +++ b/include/llvm/Support/Disassembler.h @@ -0,0 +1,35 @@ +//===- llvm/Support/Disassembler.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the necessary glue to call external disassembler +// libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_DISASSEMBLER_H +#define LLVM_SYSTEM_DISASSEMBLER_H + +#include "llvm/Support/DataTypes.h" +#include <string> + +namespace llvm { +namespace sys { + +/// This function returns true, if there is possible to use some external +/// disassembler library. False otherwise. +bool hasDisassembler(); + +/// This function provides some "glue" code to call external disassembler +/// libraries. +std::string disassembleBuffer(uint8_t* start, size_t length, uint64_t pc = 0); + +} +} + +#endif // LLVM_SYSTEM_DISASSEMBLER_H diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index 3ca8d96..5d0b5a9 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -22,7 +22,8 @@ namespace llvm { // Debug info constants. enum { - LLVMDebugVersion = (8 << 16), // Current version of debug information. + LLVMDebugVersion = (9 << 16), // Current version of debug information. + LLVMDebugVersion8 = (8 << 16), // Cconstant for version 8. LLVMDebugVersion7 = (7 << 16), // Constant for version 7. LLVMDebugVersion6 = (6 << 16), // Constant for version 6. LLVMDebugVersion5 = (5 << 16), // Constant for version 5. @@ -44,11 +45,9 @@ enum llvm_dwarf_constants { // llvm mock tags DW_TAG_invalid = ~0U, // Tag for invalid results. - DW_TAG_anchor = 0, // Tag for descriptor anchors. 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. @@ -118,6 +117,7 @@ enum dwarf_constants { DW_TAG_imported_unit = 0x3d, DW_TAG_condition = 0x3f, DW_TAG_shared_type = 0x40, + DW_TAG_rvalue_reference_type = 0x41, DW_TAG_lo_user = 0x4080, DW_TAG_hi_user = 0xffff, @@ -509,6 +509,7 @@ enum dwarf_constants { DW_DSC_range = 0x01, // Line Number Standard Opcode Encodings + DW_LNS_extended_op = 0x00, DW_LNS_copy = 0x01, DW_LNS_advance_pc = 0x02, DW_LNS_advance_line = 0x03, diff --git a/include/llvm/Support/DynamicLibrary.h b/include/llvm/Support/DynamicLibrary.h new file mode 100644 index 0000000..e6d9ff5 --- /dev/null +++ b/include/llvm/Support/DynamicLibrary.h @@ -0,0 +1,86 @@ +//===-- llvm/Support/DynamicLibrary.h - Portable Dynamic Library -*- 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 sys::DynamicLibrary class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_DYNAMIC_LIBRARY_H +#define LLVM_SYSTEM_DYNAMIC_LIBRARY_H + +#include <string> + +namespace llvm { +namespace sys { + + /// This class provides a portable interface to dynamic libraries which also + /// might be known as shared libraries, shared objects, dynamic shared + /// objects, or dynamic link libraries. Regardless of the terminology or the + /// operating system interface, this class provides a portable interface that + /// allows dynamic libraries to be loaded and searched for externally + /// defined symbols. This is typically used to provide "plug-in" support. + /// It also allows for symbols to be defined which don't live in any library, + /// but rather the main program itself, useful on Windows where the main + /// executable cannot be searched. + class DynamicLibrary { + DynamicLibrary(); // DO NOT IMPLEMENT + public: + /// This function allows a library to be loaded without instantiating a + /// DynamicLibrary object. Consequently, it is marked as being permanent + /// and will only be unloaded when the program terminates. This returns + /// false on success or returns true and fills in *ErrMsg on failure. + /// @brief Open a dynamic library permanently. + /// + /// NOTE: This function is not thread safe. + /// + static bool LoadLibraryPermanently(const char *filename, + std::string *ErrMsg = 0); + + /// This function will search through all previously loaded dynamic + /// libraries for the symbol \p symbolName. If it is found, the addressof + /// that symbol is returned. If not, null is returned. Note that this will + /// search permanently loaded libraries (LoadLibraryPermanently) as well + /// as ephemerally loaded libraries (constructors). + /// @throws std::string on error. + /// @brief Search through libraries for address of a symbol + /// + /// NOTE: This function is not thread safe. + /// + static void *SearchForAddressOfSymbol(const char *symbolName); + + /// @brief Convenience function for C++ophiles. + /// + /// NOTE: This function is not thread safe. + /// + static void *SearchForAddressOfSymbol(const std::string &symbolName) { + return SearchForAddressOfSymbol(symbolName.c_str()); + } + + /// This functions permanently adds the symbol \p symbolName with the + /// value \p symbolValue. These symbols are searched before any + /// libraries. + /// @brief Add searchable symbol/value pair. + /// + /// NOTE: This function is not thread safe. + /// + static void AddSymbol(const char *symbolName, void *symbolValue); + + /// @brief Convenience function for C++ophiles. + /// + /// NOTE: This function is not thread safe. + /// + static void AddSymbol(const std::string &symbolName, void *symbolValue) { + AddSymbol(symbolName.c_str(), symbolValue); + } + }; + +} // End sys namespace +} // End llvm namespace + +#endif // LLVM_SYSTEM_DYNAMIC_LIBRARY_H diff --git a/include/llvm/Support/DynamicLinker.h b/include/llvm/Support/DynamicLinker.h deleted file mode 100644 index b60ffa8..0000000 --- a/include/llvm/Support/DynamicLinker.h +++ /dev/null @@ -1,40 +0,0 @@ -//===-- llvm/Support/DynamicLinker.h - Portable Dynamic Linker --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Lightweight interface to dynamic library linking and loading, and dynamic -// symbol lookup functionality, in whatever form the operating system -// provides it. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_DYNAMICLINKER_H -#define LLVM_SUPPORT_DYNAMICLINKER_H - -#include <string> - -namespace llvm { - -/// LinkDynamicObject - Load the named file as a dynamic library -/// and link it with the currently running process. Returns false -/// on success, true if there is an error (and sets ErrorMessage -/// if it is not NULL). Analogous to dlopen(). -/// -bool LinkDynamicObject (const char *filename, std::string *ErrorMessage); - -/// GetAddressOfSymbol - Returns the address of the named symbol in -/// the currently running process, as reported by the dynamic linker, -/// or NULL if the symbol does not exist or some other error has -/// occurred. -/// -void *GetAddressOfSymbol (const char *symbolName); -void *GetAddressOfSymbol (const std::string &symbolName); - -} // End llvm namespace - -#endif // SUPPORT_DYNAMICLINKER_H diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 83478b7..cc72bd5 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -20,7 +20,7 @@ #ifndef LLVM_SUPPORT_ELF_H #define LLVM_SUPPORT_ELF_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <cstring> namespace llvm { @@ -126,25 +126,27 @@ enum { // Machine architectures enum { - EM_NONE = 0, // No machine - EM_M32 = 1, // AT&T WE 32100 - EM_SPARC = 2, // SPARC - EM_386 = 3, // Intel 386 - EM_68K = 4, // Motorola 68000 - EM_88K = 5, // Motorola 88000 - EM_486 = 6, // Intel 486 (deprecated) - EM_860 = 7, // Intel 80860 - EM_MIPS = 8, // MIPS R3000 - EM_PPC = 20, // PowerPC - EM_PPC64 = 21, // PowerPC64 - EM_ARM = 40, // ARM - EM_ALPHA = 41, // DEC Alpha - EM_SPARCV9 = 43, // SPARC V9 - EM_X86_64 = 62 // AMD64 + EM_NONE = 0, // No machine + EM_M32 = 1, // AT&T WE 32100 + EM_SPARC = 2, // SPARC + EM_386 = 3, // Intel 386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_486 = 6, // Intel 486 (deprecated) + EM_860 = 7, // Intel 80860 + EM_MIPS = 8, // MIPS R3000 + EM_PPC = 20, // PowerPC + EM_PPC64 = 21, // PowerPC64 + EM_ARM = 40, // ARM + EM_ALPHA = 41, // DEC Alpha + EM_SPARCV9 = 43, // SPARC V9 + EM_X86_64 = 62, // AMD64 + EM_MBLAZE = 47787 // Xilinx MicroBlaze }; // Object file classes. enum { + ELFCLASSNONE = 0, ELFCLASS32 = 1, // 32-bit object file ELFCLASS64 = 2 // 64-bit object file }; @@ -231,12 +233,206 @@ enum { R_386_GOTOFF = 9, R_386_GOTPC = 10, R_386_32PLT = 11, + R_386_TLS_TPOFF = 14, + R_386_TLS_IE = 15, + R_386_TLS_GOTIE = 16, + R_386_TLS_LE = 17, + R_386_TLS_GD = 18, + R_386_TLS_LDM = 19, R_386_16 = 20, R_386_PC16 = 21, R_386_8 = 22, - R_386_PC8 = 23 + R_386_PC8 = 23, + R_386_TLS_GD_32 = 24, + R_386_TLS_GD_PUSH = 25, + R_386_TLS_GD_CALL = 26, + R_386_TLS_GD_POP = 27, + R_386_TLS_LDM_32 = 28, + R_386_TLS_LDM_PUSH = 29, + R_386_TLS_LDM_CALL = 30, + R_386_TLS_LDM_POP = 31, + R_386_TLS_LDO_32 = 32, + R_386_TLS_IE_32 = 33, + R_386_TLS_LE_32 = 34, + R_386_TLS_DTPMOD32 = 35, + R_386_TLS_DTPOFF32 = 36, + R_386_TLS_TPOFF32 = 37, + R_386_TLS_GOTDESC = 39, + R_386_TLS_DESC_CALL = 40, + R_386_TLS_DESC = 41, + R_386_IRELATIVE = 42, + R_386_NUM = 43 +}; + +// MBlaze relocations. +enum { + R_MICROBLAZE_NONE = 0, + R_MICROBLAZE_32 = 1, + R_MICROBLAZE_32_PCREL = 2, + R_MICROBLAZE_64_PCREL = 3, + R_MICROBLAZE_32_PCREL_LO = 4, + R_MICROBLAZE_64 = 5, + R_MICROBLAZE_32_LO = 6, + R_MICROBLAZE_SRO32 = 7, + R_MICROBLAZE_SRW32 = 8, + R_MICROBLAZE_64_NONE = 9, + R_MICROBLAZE_32_SYM_OP_SYM = 10, + R_MICROBLAZE_GNU_VTINHERIT = 11, + R_MICROBLAZE_GNU_VTENTRY = 12, + R_MICROBLAZE_GOTPC_64 = 13, + R_MICROBLAZE_GOT_64 = 14, + R_MICROBLAZE_PLT_64 = 15, + R_MICROBLAZE_REL = 16, + R_MICROBLAZE_JUMP_SLOT = 17, + R_MICROBLAZE_GLOB_DAT = 18, + R_MICROBLAZE_GOTOFF_64 = 19, + R_MICROBLAZE_GOTOFF_32 = 20, + R_MICROBLAZE_COPY = 21 +}; + + +// ARM Specific e_flags +enum { EF_ARM_EABIMASK = 0xFF000000U }; + +// ELF Relocation types for ARM +// Meets 2.08 ABI Specs. + +enum { + R_ARM_NONE = 0x00, + R_ARM_PC24 = 0x01, + R_ARM_ABS32 = 0x02, + R_ARM_REL32 = 0x03, + R_ARM_LDR_PC_G0 = 0x04, + R_ARM_ABS16 = 0x05, + R_ARM_ABS12 = 0x06, + R_ARM_THM_ABS5 = 0x07, + R_ARM_ABS8 = 0x08, + R_ARM_SBREL32 = 0x09, + R_ARM_THM_CALL = 0x0a, + R_ARM_THM_PC8 = 0x0b, + R_ARM_BREL_ADJ = 0x0c, + R_ARM_TLS_DESC = 0x0d, + R_ARM_THM_SWI8 = 0x0e, + R_ARM_XPC25 = 0x0f, + R_ARM_THM_XPC22 = 0x10, + R_ARM_TLS_DTPMOD32 = 0x11, + R_ARM_TLS_DTPOFF32 = 0x12, + R_ARM_TLS_TPOFF32 = 0x13, + R_ARM_COPY = 0x14, + R_ARM_GLOB_DAT = 0x15, + R_ARM_JUMP_SLOT = 0x16, + R_ARM_RELATIVE = 0x17, + R_ARM_GOTOFF32 = 0x18, + R_ARM_BASE_PREL = 0x19, + R_ARM_GOT_BREL = 0x1a, + R_ARM_PLT32 = 0x1b, + R_ARM_CALL = 0x1c, + R_ARM_JUMP24 = 0x1d, + R_ARM_THM_JUMP24 = 0x1e, + R_ARM_BASE_ABS = 0x1f, + R_ARM_ALU_PCREL_7_0 = 0x20, + R_ARM_ALU_PCREL_15_8 = 0x21, + R_ARM_ALU_PCREL_23_15 = 0x22, + R_ARM_LDR_SBREL_11_0_NC = 0x23, + R_ARM_ALU_SBREL_19_12_NC = 0x24, + R_ARM_ALU_SBREL_27_20_CK = 0x25, + R_ARM_TARGET1 = 0x26, + R_ARM_SBREL31 = 0x27, + R_ARM_V4BX = 0x28, + R_ARM_TARGET2 = 0x29, + R_ARM_PREL31 = 0x2a, + R_ARM_MOVW_ABS_NC = 0x2b, + R_ARM_MOVT_ABS = 0x2c, + R_ARM_MOVW_PREL_NC = 0x2d, + R_ARM_MOVT_PREL = 0x2e, + R_ARM_THM_MOVW_ABS_NC = 0x2f, + R_ARM_THM_MOVT_ABS = 0x30, + R_ARM_THM_MOVW_PREL_NC = 0x31, + R_ARM_THM_MOVT_PREL = 0x32, + R_ARM_THM_JUMP19 = 0x33, + R_ARM_THM_JUMP6 = 0x34, + R_ARM_THM_ALU_PREL_11_0 = 0x35, + R_ARM_THM_PC12 = 0x36, + R_ARM_ABS32_NOI = 0x37, + R_ARM_REL32_NOI = 0x38, + R_ARM_ALU_PC_G0_NC = 0x39, + R_ARM_ALU_PC_G0 = 0x3a, + R_ARM_ALU_PC_G1_NC = 0x3b, + R_ARM_ALU_PC_G1 = 0x3c, + R_ARM_ALU_PC_G2 = 0x3d, + R_ARM_LDR_PC_G1 = 0x3e, + R_ARM_LDR_PC_G2 = 0x3f, + R_ARM_LDRS_PC_G0 = 0x40, + R_ARM_LDRS_PC_G1 = 0x41, + R_ARM_LDRS_PC_G2 = 0x42, + R_ARM_LDC_PC_G0 = 0x43, + R_ARM_LDC_PC_G1 = 0x44, + R_ARM_LDC_PC_G2 = 0x45, + R_ARM_ALU_SB_G0_NC = 0x46, + R_ARM_ALU_SB_G0 = 0x47, + R_ARM_ALU_SB_G1_NC = 0x48, + R_ARM_ALU_SB_G1 = 0x49, + R_ARM_ALU_SB_G2 = 0x4a, + R_ARM_LDR_SB_G0 = 0x4b, + R_ARM_LDR_SB_G1 = 0x4c, + R_ARM_LDR_SB_G2 = 0x4d, + R_ARM_LDRS_SB_G0 = 0x4e, + R_ARM_LDRS_SB_G1 = 0x4f, + R_ARM_LDRS_SB_G2 = 0x50, + R_ARM_LDC_SB_G0 = 0x51, + R_ARM_LDC_SB_G1 = 0x52, + R_ARM_LDC_SB_G2 = 0x53, + R_ARM_MOVW_BREL_NC = 0x54, + R_ARM_MOVT_BREL = 0x55, + R_ARM_MOVW_BREL = 0x56, + R_ARM_THM_MOVW_BREL_NC = 0x57, + R_ARM_THM_MOVT_BREL = 0x58, + R_ARM_THM_MOVW_BREL = 0x59, + R_ARM_TLS_GOTDESC = 0x5a, + R_ARM_TLS_CALL = 0x5b, + R_ARM_TLS_DESCSEQ = 0x5c, + R_ARM_THM_TLS_CALL = 0x5d, + R_ARM_PLT32_ABS = 0x5e, + R_ARM_GOT_ABS = 0x5f, + R_ARM_GOT_PREL = 0x60, + R_ARM_GOT_BREL12 = 0x61, + R_ARM_GOTOFF12 = 0x62, + R_ARM_GOTRELAX = 0x63, + R_ARM_GNU_VTENTRY = 0x64, + R_ARM_GNU_VTINHERIT = 0x65, + R_ARM_THM_JUMP11 = 0x66, + R_ARM_THM_JUMP8 = 0x67, + R_ARM_TLS_GD32 = 0x68, + R_ARM_TLS_LDM32 = 0x69, + R_ARM_TLS_LDO32 = 0x6a, + R_ARM_TLS_IE32 = 0x6b, + R_ARM_TLS_LE32 = 0x6c, + R_ARM_TLS_LDO12 = 0x6d, + R_ARM_TLS_LE12 = 0x6e, + R_ARM_TLS_IE12GP = 0x6f, + R_ARM_PRIVATE_0 = 0x70, + R_ARM_PRIVATE_1 = 0x71, + R_ARM_PRIVATE_2 = 0x72, + R_ARM_PRIVATE_3 = 0x73, + R_ARM_PRIVATE_4 = 0x74, + R_ARM_PRIVATE_5 = 0x75, + R_ARM_PRIVATE_6 = 0x76, + R_ARM_PRIVATE_7 = 0x77, + R_ARM_PRIVATE_8 = 0x78, + R_ARM_PRIVATE_9 = 0x79, + R_ARM_PRIVATE_10 = 0x7a, + R_ARM_PRIVATE_11 = 0x7b, + R_ARM_PRIVATE_12 = 0x7c, + R_ARM_PRIVATE_13 = 0x7d, + R_ARM_PRIVATE_14 = 0x7e, + R_ARM_PRIVATE_15 = 0x7f, + R_ARM_ME_TOO = 0x80, + R_ARM_THM_TLS_DESCSEQ16 = 0x81, + R_ARM_THM_TLS_DESCSEQ32 = 0x82 }; + + // Section header. struct Elf32_Shdr { Elf32_Word sh_name; // Section name (index into string table) @@ -273,6 +469,7 @@ enum { SHN_HIPROC = 0xff1f, // Highest processor-specific index SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables + SHN_XINDEX = 0xffff, // Mark that the index is >= SHN_LORESERVE SHN_HIRESERVE = 0xffff // Highest reserved index }; @@ -298,6 +495,18 @@ enum { SHT_LOOS = 0x60000000, // Lowest operating system-specific type. SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type. + // Fixme: All this is duplicated in MCSectionELF. Why?? + // Exception Index table + SHT_ARM_EXIDX = 0x70000001U, + // BPABI DLL dynamic linking pre-emption map + SHT_ARM_PREEMPTMAP = 0x70000002U, + // Object file compatibility attributes + SHT_ARM_ATTRIBUTES = 0x70000003U, + SHT_ARM_DEBUGOVERLAY = 0x70000004U, + SHT_ARM_OVERLAYSECTION = 0x70000005U, + + SHT_X86_64_UNWIND = 0x70000001, // Unwind information + SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. SHT_HIUSER = 0xffffffff // Highest type reserved for applications. @@ -305,10 +514,58 @@ enum { // Section flags. enum { - SHF_WRITE = 0x1, // Section data should be writable during execution. - SHF_ALLOC = 0x2, // Section occupies memory during program execution. - SHF_EXECINSTR = 0x4, // Section contains executable machine instructions. - SHF_MASKPROC = 0xf0000000 // Bits indicating processor-specific flags. + // Section data should be writable during execution. + SHF_WRITE = 0x1, + + // Section occupies memory during program execution. + SHF_ALLOC = 0x2, + + // Section contains executable machine instructions. + SHF_EXECINSTR = 0x4, + + // The data in this section may be merged. + SHF_MERGE = 0x10, + + // The data in this section is null-terminated strings. + SHF_STRINGS = 0x20, + + // A field in this section holds a section header table index. + SHF_INFO_LINK = 0x40U, + + // Adds special ordering requirements for link editors. + SHF_LINK_ORDER = 0x80U, + + // This section requires special OS-specific processing to avoid incorrect + // behavior. + SHF_OS_NONCONFORMING = 0x100U, + + // This section is a member of a section group. + SHF_GROUP = 0x200U, + + // This section holds Thread-Local Storage. + SHF_TLS = 0x400U, + + // Start of target-specific flags. + + /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped + /// together by the linker to form the constant pool and the cp register is + /// set to the start of the constant pool by the boot code. + XCORE_SHF_CP_SECTION = 0x800U, + + /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped + /// together by the linker to form the data section and the dp register is + /// set to the start of the section by the boot code. + XCORE_SHF_DP_SECTION = 0x1000U, + + // Bits indicating processor-specific flags. + SHF_MASKPROC = 0xf0000000 +}; + +// Section Group Flags +enum { + GRP_COMDAT = 0x1, + GRP_MASKOS = 0x0ff00000, + GRP_MASKPROC = 0xf0000000 }; // Symbol table entries for ELF32. diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h new file mode 100644 index 0000000..f62eab0 --- /dev/null +++ b/include/llvm/Support/Endian.h @@ -0,0 +1,213 @@ +//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares generic functions to read and write endian specific data. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ENDIAN_H +#define LLVM_SUPPORT_ENDIAN_H + +#include "llvm/Config/config.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}; +enum alignment {unaligned, aligned}; + +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) + +} // end namespace detail + +namespace endian { + template<typename value_type, alignment align> + static 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> + static 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, alignment align> + static 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, alignment align> + static 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; + } +} + +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); + } +private: + uint8_t Value[sizeof(value_type)]; +}; + +template<typename value_type> +class packed_endian_specific_integral<value_type, big, unaligned> { +public: + operator value_type() const { + return endian::read_be<value_type, unaligned>(Value); + } +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); + } +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); + } +private: + value_type Value; +}; + +} // end namespace detail + +typedef detail::packed_endian_specific_integral + <uint8_t, little, unaligned> ulittle8_t; +typedef detail::packed_endian_specific_integral + <uint16_t, little, unaligned> ulittle16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, little, unaligned> ulittle32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, little, unaligned> ulittle64_t; + +typedef detail::packed_endian_specific_integral + <int8_t, little, unaligned> little8_t; +typedef detail::packed_endian_specific_integral + <int16_t, little, unaligned> little16_t; +typedef detail::packed_endian_specific_integral + <int32_t, little, unaligned> little32_t; +typedef detail::packed_endian_specific_integral + <int64_t, little, unaligned> little64_t; + +typedef detail::packed_endian_specific_integral + <uint8_t, little, aligned> aligned_ulittle8_t; +typedef detail::packed_endian_specific_integral + <uint16_t, little, aligned> aligned_ulittle16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, little, aligned> aligned_ulittle32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, little, aligned> aligned_ulittle64_t; + +typedef detail::packed_endian_specific_integral + <int8_t, little, aligned> aligned_little8_t; +typedef detail::packed_endian_specific_integral + <int16_t, little, aligned> aligned_little16_t; +typedef detail::packed_endian_specific_integral + <int32_t, little, aligned> aligned_little32_t; +typedef detail::packed_endian_specific_integral + <int64_t, little, aligned> aligned_little64_t; + +typedef detail::packed_endian_specific_integral + <uint8_t, big, unaligned> ubig8_t; +typedef detail::packed_endian_specific_integral + <uint16_t, big, unaligned> ubig16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, big, unaligned> ubig32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, big, unaligned> ubig64_t; + +typedef detail::packed_endian_specific_integral + <int8_t, big, unaligned> big8_t; +typedef detail::packed_endian_specific_integral + <int16_t, big, unaligned> big16_t; +typedef detail::packed_endian_specific_integral + <int32_t, big, unaligned> big32_t; +typedef detail::packed_endian_specific_integral + <int64_t, big, unaligned> big64_t; + +typedef detail::packed_endian_specific_integral + <uint8_t, big, aligned> aligned_ubig8_t; +typedef detail::packed_endian_specific_integral + <uint16_t, big, aligned> aligned_ubig16_t; +typedef detail::packed_endian_specific_integral + <uint32_t, big, aligned> aligned_ubig32_t; +typedef detail::packed_endian_specific_integral + <uint64_t, big, aligned> aligned_ubig64_t; + +typedef detail::packed_endian_specific_integral + <int8_t, big, aligned> aligned_big8_t; +typedef detail::packed_endian_specific_integral + <int16_t, big, aligned> aligned_big16_t; +typedef detail::packed_endian_specific_integral + <int32_t, big, aligned> aligned_big32_t; +typedef detail::packed_endian_specific_integral + <int64_t, big, aligned> aligned_big64_t; + +} // end namespace llvm +} // end namespace support + +#endif diff --git a/include/llvm/Support/Errno.h b/include/llvm/Support/Errno.h new file mode 100644 index 0000000..150bdb7 --- /dev/null +++ b/include/llvm/Support/Errno.h @@ -0,0 +1,34 @@ +//===- llvm/Support/Errno.h - Portable+convenient errno handling -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares some portable and convenient functions to deal with errno. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_ERRNO_H +#define LLVM_SYSTEM_ERRNO_H + +#include <string> + +namespace llvm { +namespace sys { + +/// Returns a string representation of the errno value, using whatever +/// thread-safe variant of strerror() is available. Be sure to call this +/// immediately after the function that set errno, or errno may have been +/// overwritten by an intervening call. +std::string StrError(); + +/// Like the no-argument version above, but uses \p errnum instead of errno. +std::string StrError(int errnum); + +} // namespace sys +} // namespace llvm + +#endif // LLVM_SYSTEM_ERRNO_H diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h index 9854657..5eca438 100644 --- a/include/llvm/Support/ErrorHandling.h +++ b/include/llvm/Support/ErrorHandling.h @@ -16,6 +16,7 @@ #define LLVM_SUPPORT_ERRORHANDLING_H #include "llvm/Support/Compiler.h" +#include "llvm/ADT/StringRef.h" #include <string> namespace llvm { @@ -72,15 +73,17 @@ namespace llvm { /// standard error, followed by a newline. /// After the error handler is called this function will call exit(1), it /// does not return. - NORETURN void report_fatal_error(const char *reason); - NORETURN void report_fatal_error(const std::string &reason); - NORETURN void report_fatal_error(const Twine &reason); + 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); /// This function calls abort(), and prints the optional message to stderr. /// Use the llvm_unreachable macro (that adds location info), instead of /// calling this function directly. - NORETURN void llvm_unreachable_internal(const char *msg=0, - const char *file=0, unsigned line=0); + LLVM_ATTRIBUTE_NORETURN void llvm_unreachable_internal(const char *msg=0, + const char *file=0, + unsigned line=0); } /// Prints the message and location info to stderr in !NDEBUG builds. diff --git a/include/llvm/Support/FEnv.h b/include/llvm/Support/FEnv.h new file mode 100644 index 0000000..f6f4333 --- /dev/null +++ b/include/llvm/Support/FEnv.h @@ -0,0 +1,56 @@ +//===- llvm/Support/FEnv.h - Host floating-point exceptions ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides an operating system independent interface to +// floating-point exception interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_FENV_H +#define LLVM_SYSTEM_FENV_H + +#include "llvm/Config/config.h" +#include <cerrno> +#ifdef HAVE_FENV_H +#include <fenv.h> +#endif + +// FIXME: Clang's #include handling apparently doesn't work for libstdc++'s +// fenv.h; see PR6907 for details. +#if defined(__clang__) && defined(_GLIBCXX_FENV_H) +#undef HAVE_FENV_H +#endif + +namespace llvm { +namespace sys { + +/// llvm_fenv_clearexcept - Clear the floating-point exception state. +static inline void llvm_fenv_clearexcept() { +#ifdef HAVE_FENV_H + feclearexcept(FE_ALL_EXCEPT); +#endif + errno = 0; +} + +/// llvm_fenv_testexcept - Test if a floating-point exception was raised. +static inline bool llvm_fenv_testexcept() { + int errno_val = errno; + if (errno_val == ERANGE || errno_val == EDOM) + return true; +#ifdef HAVE_FENV_H + if (fetestexcept(FE_ALL_EXCEPT & ~FE_INEXACT)) + return true; +#endif + return false; +} + +} // End sys namespace +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h new file mode 100644 index 0000000..4001bf0 --- /dev/null +++ b/include/llvm/Support/FileSystem.h @@ -0,0 +1,690 @@ +//===- llvm/Support/FileSystem.h - File System OS Concept -------*- 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::fs namespace. It is designed after +// TR2/boost filesystem (v3), but modified to remove exception handling and the +// path class. +// +// All functions return an error_code and their actual work via the last out +// argument. The out argument is defined if and only if errc::success is +// returned. A function may return any error code in the generic or system +// category. However, they shall be equivalent to any error conditions listed +// in each functions respective documentation if the condition applies. [ note: +// this does not guarantee that error_code will be in the set of explicitly +// listed codes, but it does guarantee that if any of the explicitly listed +// errors occur, the correct error_code will be used ]. All functions may +// return errc::not_enough_memory if there is not enough memory to complete the +// operation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILE_SYSTEM_H +#define LLVM_SUPPORT_FILE_SYSTEM_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/PathV1.h" +#include "llvm/Support/system_error.h" +#include <ctime> +#include <iterator> +#include <string> + +namespace llvm { +namespace sys { +namespace fs { + +/// file_type - An "enum class" enumeration for the file system's view of the +/// type. +struct file_type { + enum _ { + status_error, + file_not_found, + regular_file, + directory_file, + symlink_file, + block_file, + character_file, + fifo_file, + socket_file, + type_unknown + }; + + file_type(_ v) : v_(v) {} + explicit file_type(int v) : v_(_(v)) {} + operator int() const {return v_;} + +private: + int v_; +}; + +/// copy_option - An "enum class" enumeration of copy semantics for copy +/// operations. +struct copy_option { + enum _ { + fail_if_exists, + overwrite_if_exists + }; + + copy_option(_ v) : v_(v) {} + explicit copy_option(int v) : v_(_(v)) {} + operator int() const {return v_;} + +private: + int v_; +}; + +/// space_info - Self explanatory. +struct space_info { + uint64_t capacity; + uint64_t free; + uint64_t available; +}; + +/// file_status - Represents the result of a call to stat and friends. It has +/// a platform specific member to store the result. +class file_status +{ + // implementation defined status field. + file_type Type; +public: + explicit file_status(file_type v=file_type::status_error) + : Type(v) {} + + file_type type() const { return Type; } + void type(file_type v) { Type = v; } +}; + +/// @} +/// @name Physical Operators +/// @{ + +/// @brief Make \a path an absolute path. +/// +/// Makes \a path absolute using the current directory if it is not already. An +/// empty \a path will result in the current directory. +/// +/// /absolute/path => /absolute/path +/// relative/../path => <current-directory>/relative/../path +/// +/// @param path A path that is modified to be an absolute path. +/// @returns errc::success if \a path has been made absolute, otherwise a +/// platform specific error_code. +error_code make_absolute(SmallVectorImpl<char> &path); + +/// @brief Copy the file at \a from to the path \a to. +/// +/// @param from The path to copy the file from. +/// @param to The path to copy the file to. +/// @param copt Behavior if \a to already exists. +/// @returns errc::success if the file has been successfully copied. +/// errc::file_exists if \a to already exists and \a copt == +/// copy_option::fail_if_exists. Otherwise a platform specific +/// error_code. +error_code copy_file(const Twine &from, const Twine &to, + copy_option copt = copy_option::fail_if_exists); + +/// @brief Create all the non-existent directories in path. +/// +/// @param path Directories to create. +/// @param existed Set to true if \a path already existed, false otherwise. +/// @returns errc::success if is_directory(path) and existed have been set, +/// otherwise a platform specific error_code. +error_code create_directories(const Twine &path, bool &existed); + +/// @brief Create the directory in path. +/// +/// @param path Directory to create. +/// @param existed Set to true if \a path already existed, false otherwise. +/// @returns errc::success if is_directory(path) and existed have been set, +/// otherwise a platform specific error_code. +error_code create_directory(const Twine &path, bool &existed); + +/// @brief Create a hard link from \a from to \a to. +/// +/// @param to The path to hard link to. +/// @param from The path to hard link from. This is created. +/// @returns errc::success if exists(to) && exists(from) && equivalent(to, from) +/// , otherwise a platform specific error_code. +error_code create_hard_link(const Twine &to, const Twine &from); + +/// @brief Create a symbolic link from \a from to \a to. +/// +/// @param to The path to symbolically link to. +/// @param from The path to symbolically link from. This is created. +/// @returns errc::success if exists(to) && exists(from) && is_symlink(from), +/// otherwise a platform specific error_code. +error_code create_symlink(const Twine &to, const Twine &from); + +/// @brief Get the current path. +/// +/// @param result Holds the current path on return. +/// @results errc::success if the current path has been stored in result, +/// otherwise a platform specific error_code. +error_code current_path(SmallVectorImpl<char> &result); + +/// @brief Remove path. Equivalent to POSIX remove(). +/// +/// @param path Input path. +/// @param existed Set to true if \a path existed, false if it did not. +/// undefined otherwise. +/// @results errc::success if path has been removed and existed has been +/// successfully set, otherwise a platform specific error_code. +error_code remove(const Twine &path, bool &existed); + +/// @brief Recursively remove all files below \a path, then \a path. Files are +/// removed as if by POSIX remove(). +/// +/// @param path Input path. +/// @param num_removed Number of files removed. +/// @results errc::success if path has been removed and num_removed has been +/// successfully set, otherwise a platform specific error_code. +error_code remove_all(const Twine &path, uint32_t &num_removed); + +/// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). +/// +/// @param from The path to rename from. +/// @param to The path to rename to. This is created. +error_code rename(const Twine &from, const Twine &to); + +/// @brief Resize path to size. File is resized as if by POSIX truncate(). +/// +/// @param path Input path. +/// @param size Size to resize to. +/// @returns errc::success if \a path has been resized to \a size, otherwise a +/// platform specific error_code. +error_code resize_file(const Twine &path, uint64_t size); + +/// @brief Make file readable. +/// +/// @param path Input path. +/// @param value If true, make readable, else, make unreadable. +/// @results errc::success if readability has been successfully set, otherwise a +/// platform specific error_code. +error_code set_read(const Twine &path, bool value); + +/// @brief Make file writeable. +/// +/// @param path Input path. +/// @param value If true, make writeable, else, make unwriteable. +/// @results errc::success if writeability has been successfully set, otherwise +/// a platform specific error_code. +error_code set_write(const Twine &path, bool value); + +/// @brief Make file executable. +/// +/// @param path Input path. +/// @param value If true, make executable, else, make unexecutable. +/// @results errc::success if executability has been successfully set, otherwise +/// a platform specific error_code. +error_code set_execute(const Twine &path, bool value); + +/// @} +/// @name Physical Observers +/// @{ + +/// @brief Does file exist? +/// +/// @param status A file_status previously returned from stat. +/// @results True if the file represented by status exists, false if it does +/// not. +bool exists(file_status status); + +/// @brief Does file exist? +/// +/// @param path Input path. +/// @param result Set to true if the file represented by status exists, false if +/// it does not. Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code exists(const Twine &path, bool &result); + +/// @brief Do file_status's represent the same thing? +/// +/// @param A Input file_status. +/// @param B Input file_status. +/// +/// assert(status_known(A) || status_known(B)); +/// +/// @results True if A and B both represent the same file system entity, false +/// otherwise. +bool equivalent(file_status A, file_status B); + +/// @brief Do paths represent the same thing? +/// +/// @param A Input path A. +/// @param B Input path B. +/// @param result Set to true if stat(A) and stat(B) have the same device and +/// inode (or equivalent). +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code equivalent(const Twine &A, const Twine &B, bool &result); + +/// @brief Get file size. +/// +/// @param path Input path. +/// @param result Set to the size of the file in \a path. +/// @returns errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code file_size(const Twine &path, uint64_t &result); + +/// @brief Does status represent a directory? +/// +/// @param status A file_status previously returned from status. +/// @results status.type() == file_type::directory_file. +bool is_directory(file_status status); + +/// @brief Is path a directory? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a directory, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_directory(const Twine &path, bool &result); + +/// @brief Is path an empty file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a an empty file, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_empty(const Twine &path, bool &result); + +/// @brief Does status represent a regular file? +/// +/// @param status A file_status previously returned from status. +/// @results status_known(status) && status.type() == file_type::regular_file. +bool is_regular_file(file_status status); + +/// @brief Is path a regular file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a regular file, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_regular_file(const Twine &path, bool &result); + +/// @brief Does this status represent something that exists but is not a +/// directory, regular file, or symlink? +/// +/// @param status A file_status previously returned from status. +/// @results exists(s) && !is_regular_file(s) && !is_directory(s) && +/// !is_symlink(s) +bool is_other(file_status status); + +/// @brief Is path something that exists but is not a directory, +/// regular file, or symlink? +/// +/// @param path Input path. +/// @param result Set to true if \a path exists, but is not a directory, regular +/// file, or a symlink, false if it does not. Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_other(const Twine &path, bool &result); + +/// @brief Does status represent a symlink? +/// +/// @param status A file_status previously returned from stat. +/// @param result status.type() == symlink_file. +bool is_symlink(file_status status); + +/// @brief Is path a symlink? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a symlink, false if it is not. +/// Undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_symlink(const Twine &path, bool &result); + +/// @brief Get last write time without changing it. +/// +/// @param path Input path. +/// @param result Set to the last write time (UNIX time) of \a path if it +/// exists. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code last_write_time(const Twine &path, std::time_t &result); + +/// @brief Set last write time. +/// +/// @param path Input path. +/// @param value Time to set (UNIX time) \a path's last write time to. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code set_last_write_time(const Twine &path, std::time_t value); + +/// @brief Read a symlink's value. +/// +/// @param path Input path. +/// @param result Set to the value of the symbolic link \a path. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code read_symlink(const Twine &path, SmallVectorImpl<char> &result); + +/// @brief Get disk space usage information. +/// +/// @param path Input path. +/// @param result Set to the capacity, free, and available space on the device +/// \a path is on. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code disk_space(const Twine &path, space_info &result); + +/// @brief Get file status as if by POSIX stat(). +/// +/// @param path Input path. +/// @param result Set to the file status. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code status(const Twine &path, file_status &result); + +/// @brief Is status available? +/// +/// @param path Input path. +/// @results True if status() != status_error. +bool status_known(file_status s); + +/// @brief Is status available? +/// +/// @param path Input path. +/// @param result Set to true if status() != status_error. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code status_known(const Twine &path, bool &result); + +/// @brief Get file status as if by POSIX lstat(). +/// +/// Does not resolve symlinks. +/// +/// @param path Input path. +/// @param result Set to the file status. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code symlink_status(const Twine &path, file_status &result); + +/// @brief Generate a unique path and open it as a file. +/// +/// Generates a unique path suitable for a temporary file and then opens it as a +/// file. The name is based on \a model with '%' replaced by a random char in +/// [0-9a-f]. If \a model is not an absolute path, a suitable temporary +/// directory will be prepended. +/// +/// This is an atomic operation. Either the file is created and opened, or the +/// file system is left untouched. +/// +/// clang-%%-%%-%%-%%-%%.s => /tmp/clang-a0-b1-c2-d3-e4.s +/// +/// @param model Name to base unique path off of. +/// @param result_fs Set to the opened file's file descriptor. +/// @param result_path Set to the opened file's absolute path. +/// @results errc::success if result_{fd,path} have been successfully set, +/// otherwise a platform specific error_code. +error_code unique_file(const Twine &model, int &result_fd, + SmallVectorImpl<char> &result_path); + +/// @brief Canonicalize path. +/// +/// Sets result to the file system's idea of what path is. The result is always +/// absolute and has the same capitalization as the file system. +/// +/// @param path Input path. +/// @param result Set to the canonicalized version of \a path. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code canonicalize(const Twine &path, SmallVectorImpl<char> &result); + +/// @brief Are \a path's first bytes \a magic? +/// +/// @param path Input path. +/// @param magic Byte sequence to compare \a path's first len(magic) bytes to. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code has_magic(const Twine &path, const Twine &magic, bool &result); + +/// @brief Get \a path's first \a len bytes. +/// +/// @param path Input path. +/// @param len Number of magic bytes to get. +/// @param result Set to the first \a len bytes in the file pointed to by +/// \a path. Or the entire file if file_size(path) < len, in which +/// case result.size() returns the size of the file. +/// @results errc::success if result has been successfully set, +/// errc::value_too_large if len is larger then the file pointed to by +/// \a path, otherwise a platform specific error_code. +error_code get_magic(const Twine &path, uint32_t len, + SmallVectorImpl<char> &result); + +/// @brief Get and identify \a path's type based on its content. +/// +/// @param path Input path. +/// @param result Set to the type of file, or LLVMFileType::Unknown_FileType. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code identify_magic(const Twine &path, LLVMFileType &result); + +/// @brief Is file bitcode? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a bitcode file, false if it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_bitcode(const Twine &path, bool &result); + +/// @brief Is file a dynamic library? +/// +/// @param path Input path. +/// @param result Set to true if \a path is a dynamic library, false if it is +/// not, undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_dynamic_library(const Twine &path, bool &result); + +/// @brief Is an object file? +/// +/// @param path Input path. +/// @param result Set to true if \a path is an object file, false if it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code is_object_file(const Twine &path, bool &result); + +/// @brief Can file be read? +/// +/// @param path Input path. +/// @param result Set to true if \a path is readable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_read(const Twine &path, bool &result); + +/// @brief Can file be written? +/// +/// @param path Input path. +/// @param result Set to true if \a path is writeable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_write(const Twine &path, bool &result); + +/// @brief Can file be executed? +/// +/// @param path Input path. +/// @param result Set to true if \a path is executable, false it it is not, +/// undefined otherwise. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code can_execute(const Twine &path, bool &result); + +/// @brief Get library paths the system linker uses. +/// +/// @param result Set to the list of system library paths. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetSystemLibraryPaths(SmallVectorImpl<std::string> &result); + +/// @brief Get bitcode library paths the system linker uses +/// + LLVM_LIB_SEARCH_PATH + LLVM_LIBDIR. +/// +/// @param result Set to the list of bitcode library paths. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetBitcodeLibraryPaths(SmallVectorImpl<std::string> &result); + +/// @brief Find a library. +/// +/// Find the path to a library using its short name. Use the system +/// dependent library paths to locate the library. +/// +/// c => /usr/lib/libc.so +/// +/// @param short_name Library name one would give to the system linker. +/// @param result Set to the absolute path \a short_name represents. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); + +/// @brief Get absolute path of main executable. +/// +/// @param argv0 The program name as it was spelled on the command line. +/// @param MainAddr Address of some symbol in the executable (not in a library). +/// @param result Set to the absolute path of the current executable. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code GetMainExecutable(const char *argv0, void *MainAddr, + SmallVectorImpl<char> &result); + +/// @} +/// @name Iterators +/// @{ + +/// directory_entry - A single entry in a directory. Caches the status either +/// from the result of the iteration syscall, or the first time status or +/// symlink_status is called. +class directory_entry { + std::string Path; + mutable file_status Status; + mutable file_status SymlinkStatus; + +public: + explicit directory_entry(const Twine &path, file_status st = file_status(), + file_status symlink_st = file_status()) + : Path(path.str()) + , Status(st) + , SymlinkStatus(symlink_st) {} + + directory_entry() {} + + void assign(const Twine &path, file_status st = file_status(), + file_status symlink_st = file_status()) { + Path = path.str(); + Status = st; + SymlinkStatus = symlink_st; + } + + void replace_filename(const Twine &filename, file_status st = file_status(), + file_status symlink_st = file_status()); + + StringRef path() const { return Path; } + error_code status(file_status &result) const; + error_code symlink_status(file_status &result) const; + + bool operator==(const directory_entry& rhs) const { return Path == rhs.Path; } + bool operator!=(const directory_entry& rhs) const { return !(*this == rhs); } + bool operator< (const directory_entry& rhs) const; + bool operator<=(const directory_entry& rhs) const; + bool operator> (const directory_entry& rhs) const; + bool operator>=(const directory_entry& rhs) const; +}; + +/// directory_iterator - Iterates through the entries in path. There is no +/// operator++ because we need an error_code. If it's really needed we can make +/// it call report_fatal_error on error. +class directory_iterator { + intptr_t IterationHandle; + directory_entry CurrentEntry; + + // Platform implementations implement these functions to handle iteration. + friend error_code directory_iterator_construct(directory_iterator &it, + StringRef path); + friend error_code directory_iterator_increment(directory_iterator &it); + friend error_code directory_iterator_destruct(directory_iterator &it); + +public: + explicit directory_iterator(const Twine &path, error_code &ec) + : IterationHandle(0) { + SmallString<128> path_storage; + ec = directory_iterator_construct(*this, path.toStringRef(path_storage)); + } + + /// Construct end iterator. + directory_iterator() : IterationHandle(0) {} + + ~directory_iterator() { + directory_iterator_destruct(*this); + } + + // No operator++ because we need error_code. + directory_iterator &increment(error_code &ec) { + ec = directory_iterator_increment(*this); + return *this; + } + + const directory_entry &operator*() const { return CurrentEntry; } + const directory_entry *operator->() const { return &CurrentEntry; } + + bool operator!=(const directory_iterator &RHS) const { + return CurrentEntry != RHS.CurrentEntry; + } + // Other members as required by + // C++ Std, 24.1.1 Input iterators [input.iterators] +}; + +/// recursive_directory_iterator - Same as directory_iterator except for it +/// recurses down into child directories. +class recursive_directory_iterator { + uint16_t Level; + bool HasNoPushRequest; + // implementation directory iterator status + +public: + explicit recursive_directory_iterator(const Twine &path, error_code &ec); + // No operator++ because we need error_code. + directory_iterator &increment(error_code &ec); + + const directory_entry &operator*() const; + const directory_entry *operator->() const; + + // observers + /// Gets the current level. path is at level 0. + int level() const; + /// Returns true if no_push has been called for this directory_entry. + bool no_push_request() const; + + // modifiers + /// Goes up one level if Level > 0. + void pop(); + /// Does not go down into the current directory_entry. + void no_push(); + + // Other members as required by + // C++ Std, 24.1.1 Input iterators [input.iterators] +}; + +/// @} + +} // end namespace fs +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h index d0dd4a7..748ce7c 100644 --- a/include/llvm/Support/FileUtilities.h +++ b/include/llvm/Support/FileUtilities.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_FILEUTILITIES_H #define LLVM_SUPPORT_FILEUTILITIES_H -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" namespace llvm { diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index 287c5ba..7573ef0 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -26,7 +26,7 @@ #include "llvm/Support/DOTGraphTraits.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/System/Path.h" +#include "llvm/Support/Path.h" #include <vector> #include <cassert> @@ -89,14 +89,28 @@ class GraphWriter { public: GraphWriter(raw_ostream &o, const GraphType &g, bool SN) : O(o), G(g) { - DTraits = DOTTraits(SN); -} + DTraits = DOTTraits(SN); + } + + void writeGraph(const std::string &Title = "") { + // Output the header for the graph... + writeHeader(Title); + + // Emit all of the nodes in the graph... + writeNodes(); + + // Output any customizations on the graph + DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, *this); - void writeHeader(const std::string &Name) { + // Output the end of the graph + writeFooter(); + } + + void writeHeader(const std::string &Title) { std::string GraphName = DTraits.getGraphName(G); - if (!Name.empty()) - O << "digraph \"" << DOT::EscapeString(Name) << "\" {\n"; + if (!Title.empty()) + O << "digraph \"" << DOT::EscapeString(Title) << "\" {\n"; else if (!GraphName.empty()) O << "digraph \"" << DOT::EscapeString(GraphName) << "\" {\n"; else @@ -105,8 +119,8 @@ public: if (DTraits.renderGraphFromBottomUp()) O << "\trankdir=\"BT\";\n"; - if (!Name.empty()) - O << "\tlabel=\"" << DOT::EscapeString(Name) << "\";\n"; + if (!Title.empty()) + O << "\tlabel=\"" << DOT::EscapeString(Title) << "\";\n"; else if (!GraphName.empty()) O << "\tlabel=\"" << DOT::EscapeString(GraphName) << "\";\n"; O << DTraits.getGraphProperties(G); @@ -282,22 +296,13 @@ public: template<typename GraphType> raw_ostream &WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames = false, - const std::string &Name = "", const std::string &Title = "") { // Start the graph emission process... GraphWriter<GraphType> W(O, G, ShortNames); - // Output the header for the graph... - W.writeHeader(Title); - - // Emit all of the nodes in the graph... - W.writeNodes(); - - // Output any customizations on the graph - DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); + // Emit the graph. + W.writeGraph(Title); - // Output the end of the graph - W.writeFooter(); return O; } @@ -322,7 +327,7 @@ sys::Path WriteGraph(const GraphType &G, const std::string &Name, raw_fd_ostream O(Filename.c_str(), ErrorInfo); if (ErrorInfo.empty()) { - llvm::WriteGraph(O, G, ShortNames, Name, Title); + llvm::WriteGraph(O, G, ShortNames, Title); errs() << " done. \n"; } else { errs() << "error opening file '" << Filename.str() << "' for writing!\n"; diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h new file mode 100644 index 0000000..f77d4c1 --- /dev/null +++ b/include/llvm/Support/Host.h @@ -0,0 +1,66 @@ +//===- llvm/Support/Host.h - Host machine characteristics --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods for querying the nature of the host machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_HOST_H +#define LLVM_SYSTEM_HOST_H + +#include "llvm/ADT/StringMap.h" +#include <string> + +namespace llvm { +namespace sys { + + inline bool isLittleEndianHost() { + union { + int i; + char c; + }; + i = 1; + return c; + } + + inline bool isBigEndianHost() { + return !isLittleEndianHost(); + } + + /// getHostTriple() - Return the target triple of the running + /// system. + /// + /// The target triple is a string in the format of: + /// CPU_TYPE-VENDOR-OPERATING_SYSTEM + /// or + /// CPU_TYPE-VENDOR-KERNEL-OPERATING_SYSTEM + std::string getHostTriple(); + + /// 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. + /// + /// \return - The host CPU name, or empty if the CPU could not be determined. + std::string getHostCPUName(); + + /// getHostCPUFeatures - Get the LLVM names for the host CPU features. + /// The particular format of the names are target dependent, and suitable for + /// passing as -mattr to the target which matches the host. + /// + /// \param Features - A string mapping feature names to either + /// true (if enabled) or false (if disabled). This routine makes no guarantees + /// about exactly which features may appear in this map, except that they are + /// all valid LLVM feature names. + /// + /// \return - True on success. + bool getHostCPUFeatures(StringMap<bool> &Features); +} +} + +#endif diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h index c827cce..2394a59 100644 --- a/include/llvm/Support/IRBuilder.h +++ b/include/llvm/Support/IRBuilder.h @@ -46,32 +46,39 @@ protected: BasicBlock::iterator InsertPt; LLVMContext &Context; public: - + IRBuilderBase(LLVMContext &context) : Context(context) { ClearInsertionPoint(); } - + //===--------------------------------------------------------------------===// // Builder configuration methods //===--------------------------------------------------------------------===// - + /// ClearInsertionPoint - Clear the insertion point: created instructions will /// not be inserted into a block. void ClearInsertionPoint() { BB = 0; } - + BasicBlock *GetInsertBlock() const { return BB; } BasicBlock::iterator GetInsertPoint() const { return InsertPt; } LLVMContext &getContext() const { return Context; } - + /// SetInsertPoint - This specifies that created instructions should be /// appended to the end of the specified block. void SetInsertPoint(BasicBlock *TheBB) { BB = TheBB; InsertPt = BB->end(); } + + /// SetInsertPoint - This specifies that created instructions should be + /// inserted before the specified instruction. + void SetInsertPoint(Instruction *I) { + BB = I->getParent(); + InsertPt = I; + } /// SetInsertPoint - This specifies that created instructions should be /// inserted at the specified point. @@ -79,17 +86,17 @@ public: BB = TheBB; InsertPt = IP; } - + /// SetCurrentDebugLocation - Set location information used by debugging /// information. void SetCurrentDebugLocation(const DebugLoc &L) { CurDbgLocation = L; } - + /// getCurrentDebugLocation - Get location information used by debugging /// information. const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } - + /// SetInstDebugLocation - If this builder has a current debug location, set /// it on the specified instruction. void SetInstDebugLocation(Instruction *I) const { @@ -142,7 +149,7 @@ public: //===--------------------------------------------------------------------===// // Miscellaneous creation methods. //===--------------------------------------------------------------------===// - + /// CreateGlobalString - Make a new global variable with an initializer that /// has array of i8 type filled in with the nul terminated string value /// specified. If Name is specified, it is the name of the global variable @@ -178,65 +185,100 @@ public: ConstantInt *getInt32(uint32_t C) { return ConstantInt::get(getInt32Ty(), C); } - + /// getInt64 - Get a constant 64-bit value. ConstantInt *getInt64(uint64_t C) { return ConstantInt::get(getInt64Ty(), C); } - + //===--------------------------------------------------------------------===// // Type creation methods //===--------------------------------------------------------------------===// - + /// getInt1Ty - Fetch the type representing a single bit const IntegerType *getInt1Ty() { return Type::getInt1Ty(Context); } - + /// getInt8Ty - Fetch the type representing an 8-bit integer. const IntegerType *getInt8Ty() { return Type::getInt8Ty(Context); } - + /// getInt16Ty - Fetch the type representing a 16-bit integer. const IntegerType *getInt16Ty() { return Type::getInt16Ty(Context); } - + /// getInt32Ty - Fetch the type resepresenting a 32-bit integer. const IntegerType *getInt32Ty() { return Type::getInt32Ty(Context); } - + /// getInt64Ty - Fetch the type representing a 64-bit integer. const IntegerType *getInt64Ty() { return Type::getInt64Ty(Context); } - + /// getFloatTy - Fetch the type representing a 32-bit floating point value. const Type *getFloatTy() { return Type::getFloatTy(Context); } - + /// getDoubleTy - Fetch the type representing a 64-bit floating point value. const Type *getDoubleTy() { return Type::getDoubleTy(Context); } - + /// getVoidTy - Fetch the type representing void. const Type *getVoidTy() { return Type::getVoidTy(Context); } - - const PointerType *getInt8PtrTy() { - return Type::getInt8PtrTy(Context); + + const PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { + return Type::getInt8PtrTy(Context, AddrSpace); } - + /// getCurrentFunctionReturnType - Get the return type of the current function /// that we're emitting into. const Type *getCurrentFunctionReturnType() const; -}; + /// CreateMemSet - Create and insert a memset to the specified pointer and the + /// specified value. If the pointer isn't an i8*, it will be converted. If a + /// TBAA tag is specified, it will be added to the instruction. + CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); + + /// CreateMemCpy - Create and insert a memcpy between the specified pointers. + /// If the pointers aren't i8*, they will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. + CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); + + /// CreateMemMove - Create and insert a memmove between the specified + /// pointers. If the pointers aren't i8*, they will be converted. If a TBAA + /// tag is specified, it will be added to the instruction. + CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0) { + return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + } + + CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, + bool isVolatile = false, MDNode *TBAATag = 0); +private: + Value *getCastedInt8PtrValue(Value *Ptr); +}; + /// IRBuilder - This provides a uniform API for creating instructions and /// inserting them into a basic block: either at the end of a BasicBlock, or /// at a specific iterator location in a block. @@ -258,25 +300,30 @@ public: IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter()) : IRBuilderBase(C), Inserter(I), Folder(F) { } - + explicit IRBuilder(LLVMContext &C) : IRBuilderBase(C), Folder(C) { } - + explicit IRBuilder(BasicBlock *TheBB, const T &F) : IRBuilderBase(TheBB->getContext()), Folder(F) { SetInsertPoint(TheBB); } - + explicit IRBuilder(BasicBlock *TheBB) : IRBuilderBase(TheBB->getContext()), Folder(Context) { SetInsertPoint(TheBB); } + + explicit IRBuilder(Instruction *IP) + : IRBuilderBase(IP->getContext()), Folder(Context) { + SetInsertPoint(IP); + } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F) : IRBuilderBase(TheBB->getContext()), Folder(F) { SetInsertPoint(TheBB, IP); } - + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP) : IRBuilderBase(TheBB->getContext()), Folder(Context) { SetInsertPoint(TheBB, IP); @@ -288,7 +335,7 @@ public: /// isNamePreserving - Return true if this builder is configured to actually /// add the requested names to IR created through it. bool isNamePreserving() const { return preserveNames; } - + /// Insert - Insert and return the specified instruction. template<typename InstTy> InstTy *Insert(InstTy *I, const Twine &Name = "") const { @@ -298,6 +345,11 @@ public: return I; } + /// Insert - No-op overload to handle constants. + Constant *Insert(Constant *C, const Twine& = "") const { + return C; + } + //===--------------------------------------------------------------------===// // Instruction creation methods: Terminators //===--------------------------------------------------------------------===// @@ -313,7 +365,7 @@ public: ReturnInst *CreateRet(Value *V) { return Insert(ReturnInst::Create(Context, V)); } - + /// CreateAggregateRet - Create a sequence of N insertvalue instructions, /// with one Value from the retVals array each, that build a aggregate /// return value one value at a time, and a ret instruction to return @@ -375,10 +427,12 @@ public: Args+3), Name); } /// CreateInvoke - Create an invoke instruction. - template<typename InputIterator> + template<typename RandomAccessIterator> InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, - BasicBlock *UnwindDest, InputIterator ArgBegin, - InputIterator ArgEnd, const Twine &Name = "") { + BasicBlock *UnwindDest, + RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, + const Twine &Name = "") { return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, ArgBegin, ArgEnd), Name); } @@ -394,177 +448,179 @@ public: //===--------------------------------------------------------------------===// // Instruction creation methods: Binary Operators //===--------------------------------------------------------------------===// - - Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "") { +private: + BinaryOperator *CreateInsertNUWNSWBinOp(BinaryOperator::BinaryOps Opc, + Value *LHS, Value *RHS, + const Twine &Name, + bool HasNUW, bool HasNSW) { + BinaryOperator *BO = Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; + } +public: + Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateAdd(LC, RC); - return Insert(BinaryOperator::CreateAdd(LHS, RHS), Name); + return Insert(Folder.CreateAdd(LC, RC, HasNUW, HasNSW), Name); + return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, + HasNUW, HasNSW); } Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNSWAdd(LC, RC); - return Insert(BinaryOperator::CreateNSWAdd(LHS, RHS), Name); + return CreateAdd(LHS, RHS, Name, false, true); } Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNUWAdd(LC, RC); - return Insert(BinaryOperator::CreateNUWAdd(LHS, RHS), Name); + return CreateAdd(LHS, RHS, Name, true, false); } Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFAdd(LC, RC); + return Insert(Folder.CreateFAdd(LC, RC), Name); return Insert(BinaryOperator::CreateFAdd(LHS, RHS), Name); } - Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateSub(LC, RC); - return Insert(BinaryOperator::CreateSub(LHS, RHS), Name); + return Insert(Folder.CreateSub(LC, RC), Name); + return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, + HasNUW, HasNSW); } Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNSWSub(LC, RC); - return Insert(BinaryOperator::CreateNSWSub(LHS, RHS), Name); + return CreateSub(LHS, RHS, Name, false, true); } Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNUWSub(LC, RC); - return Insert(BinaryOperator::CreateNUWSub(LHS, RHS), Name); + return CreateSub(LHS, RHS, Name, true, false); } Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFSub(LC, RC); + return Insert(Folder.CreateFSub(LC, RC), Name); return Insert(BinaryOperator::CreateFSub(LHS, RHS), Name); } - Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateMul(LC, RC); - return Insert(BinaryOperator::CreateMul(LHS, RHS), Name); + return Insert(Folder.CreateMul(LC, RC), Name); + return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, + HasNUW, HasNSW); } Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNSWMul(LC, RC); - return Insert(BinaryOperator::CreateNSWMul(LHS, RHS), Name); + return CreateMul(LHS, RHS, Name, false, true); } Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateNUWMul(LC, RC); - return Insert(BinaryOperator::CreateNUWMul(LHS, RHS), Name); + return CreateMul(LHS, RHS, Name, true, false); } Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFMul(LC, RC); + return Insert(Folder.CreateFMul(LC, RC), Name); return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name); } - Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateUDiv(LC, RC); - return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); + return Insert(Folder.CreateUDiv(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name); } - Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateSDiv(LC, RC); - return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); + Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateUDiv(LHS, RHS, Name, true); } - Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateExactSDiv(LC, RC); + return Insert(Folder.CreateSDiv(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name); } + Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { + return CreateSDiv(LHS, RHS, Name, true); + } Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFDiv(LC, RC); + return Insert(Folder.CreateFDiv(LC, RC), Name); return Insert(BinaryOperator::CreateFDiv(LHS, RHS), Name); } Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateURem(LC, RC); + return Insert(Folder.CreateURem(LC, RC), Name); return Insert(BinaryOperator::CreateURem(LHS, RHS), Name); } Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateSRem(LC, RC); + return Insert(Folder.CreateSRem(LC, RC), Name); return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); } Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFRem(LC, RC); + return Insert(Folder.CreateFRem(LC, RC), Name); return Insert(BinaryOperator::CreateFRem(LHS, RHS), Name); } - Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateShl(LC, RC); - return Insert(BinaryOperator::CreateShl(LHS, RHS), Name); + return Insert(Folder.CreateShl(LC, RC, HasNUW, HasNSW), Name); + return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name, + HasNUW, HasNSW); } - Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateShl(LC, RHSC); - return Insert(BinaryOperator::CreateShl(LHS, RHSC), Name); + Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, + HasNUW, HasNSW); } - Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateShl(LC, RHSC); - return Insert(BinaryOperator::CreateShl(LHS, RHSC), Name); + Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { + return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, + HasNUW, HasNSW); } - Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateLShr(LC, RC); - return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); + return Insert(Folder.CreateLShr(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name); } - Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateLShr(LC, RHSC); - return Insert(BinaryOperator::CreateLShr(LHS, RHSC), Name); + Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool isExact = false) { + return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } - Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateLShr(LC, RHSC); - return Insert(BinaryOperator::CreateLShr(LHS, RHSC), Name); + Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool isExact = false) { + return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } - Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "") { + Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "", + bool isExact = false) { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateAShr(LC, RC); - return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); + return Insert(Folder.CreateAShr(LC, RC, isExact), Name); + if (!isExact) + return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); + return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name); } - Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAShr(LC, RHSC); - return Insert(BinaryOperator::CreateAShr(LHS, RHSC), Name); + Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "", + bool isExact = false) { + return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } - Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAShr(LC, RHSC); - return Insert(BinaryOperator::CreateAShr(LHS, RHSC), Name); + Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "", + bool isExact = false) { + return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); } Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") { @@ -572,21 +628,15 @@ public: if (isa<ConstantInt>(RC) && cast<ConstantInt>(RC)->isAllOnesValue()) return LHS; // LHS & -1 -> LHS if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAnd(LC, RC); + return Insert(Folder.CreateAnd(LC, RC), Name); } return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name); } Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAnd(LC, RHSC); - return Insert(BinaryOperator::CreateAnd(LHS, RHSC), Name); + return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateAnd(LC, RHSC); - return Insert(BinaryOperator::CreateAnd(LHS, RHSC), Name); + return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") { @@ -594,73 +644,61 @@ public: if (RC->isNullValue()) return LHS; // LHS | 0 -> LHS if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateOr(LC, RC); + return Insert(Folder.CreateOr(LC, RC), Name); } return Insert(BinaryOperator::CreateOr(LHS, RHS), Name); } Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateOr(LC, RHSC); - return Insert(BinaryOperator::CreateOr(LHS, RHSC), Name); + return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateOr(LC, RHSC); - return Insert(BinaryOperator::CreateOr(LHS, RHSC), Name); + return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateXor(LC, RC); + return Insert(Folder.CreateXor(LC, RC), Name); return Insert(BinaryOperator::CreateXor(LHS, RHS), Name); } Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateXor(LC, RHSC); - return Insert(BinaryOperator::CreateXor(LHS, RHSC), Name); + return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") { - Constant *RHSC = ConstantInt::get(LHS->getType(), RHS); - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Folder.CreateXor(LC, RHSC); - return Insert(BinaryOperator::CreateXor(LHS, RHSC), Name); + return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); } Value *CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateBinOp(Opc, LC, RC); + return Insert(Folder.CreateBinOp(Opc, LC, RC), Name); return Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); } - Value *CreateNeg(Value *V, const Twine &Name = "") { + Value *CreateNeg(Value *V, const Twine &Name = "", + bool HasNUW = false, bool HasNSW = false) { if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNeg(VC); - return Insert(BinaryOperator::CreateNeg(V), Name); + return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name); + BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name); + if (HasNUW) BO->setHasNoUnsignedWrap(); + if (HasNSW) BO->setHasNoSignedWrap(); + return BO; } Value *CreateNSWNeg(Value *V, const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNSWNeg(VC); - return Insert(BinaryOperator::CreateNSWNeg(V), Name); + return CreateNeg(V, Name, false, true); } Value *CreateNUWNeg(Value *V, const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNUWNeg(VC); - return Insert(BinaryOperator::CreateNUWNeg(V), Name); + return CreateNeg(V, Name, true, false); } Value *CreateFNeg(Value *V, const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateFNeg(VC); + return Insert(Folder.CreateFNeg(VC), Name); return Insert(BinaryOperator::CreateFNeg(V), Name); } Value *CreateNot(Value *V, const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateNot(VC); + return Insert(Folder.CreateNot(VC), Name); return Insert(BinaryOperator::CreateNot(V), Name); } @@ -686,33 +724,39 @@ public: StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { return Insert(new StoreInst(Val, Ptr, isVolatile)); } - template<typename InputIterator> - Value *CreateGEP(Value *Ptr, InputIterator IdxBegin, InputIterator IdxEnd, + template<typename RandomAccessIterator> + Value *CreateGEP(Value *Ptr, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. - InputIterator i; + RandomAccessIterator i; for (i = IdxBegin; i < IdxEnd; ++i) if (!isa<Constant>(*i)) break; if (i == IdxEnd) - return Folder.CreateGetElementPtr(PC, &IdxBegin[0], IdxEnd - IdxBegin); + return Insert(Folder.CreateGetElementPtr(PC, &IdxBegin[0], + IdxEnd - IdxBegin), + Name); } return Insert(GetElementPtrInst::Create(Ptr, IdxBegin, IdxEnd), Name); } - template<typename InputIterator> - Value *CreateInBoundsGEP(Value *Ptr, InputIterator IdxBegin, - InputIterator IdxEnd, const Twine &Name = "") { + template<typename RandomAccessIterator> + Value *CreateInBoundsGEP(Value *Ptr, RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. - InputIterator i; + RandomAccessIterator i; for (i = IdxBegin; i < IdxEnd; ++i) if (!isa<Constant>(*i)) break; if (i == IdxEnd) - return Folder.CreateInBoundsGetElementPtr(PC, - &IdxBegin[0], - IdxEnd - IdxBegin); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, + &IdxBegin[0], + IdxEnd - IdxBegin), + Name); } return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxBegin, IdxEnd), Name); @@ -720,33 +764,33 @@ public: Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateGetElementPtr(PC, &IC, 1); + return Insert(Folder.CreateGetElementPtr(PC, &IC, 1), Name); return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); } Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateInBoundsGetElementPtr(PC, &IC, 1); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &IC, 1), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateGetElementPtr(PC, &Idx, 1), Name); - return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); + return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); } Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); } - Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, + Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), @@ -754,9 +798,9 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateGetElementPtr(PC, Idxs, 2), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); + return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); } Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name = "") { @@ -766,7 +810,7 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); } @@ -774,16 +818,16 @@ public: Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateGetElementPtr(PC, &Idx, 1), Name); - return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); + return Insert(GetElementPtrInst::Create(Ptr, &Idx, &Idx+1), Name); } Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, &Idx, 1), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, &Idx, &Idx+1), Name); } @@ -795,9 +839,9 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateGetElementPtr(PC, Idxs, 2), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); + return Insert(GetElementPtrInst::Create(Ptr, Idxs, Idxs+2), Name); } Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -807,14 +851,14 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2); + return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs, 2), Name); return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs, Idxs+2), Name); } Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); } - + /// CreateGlobalStringPtr - Same as CreateGlobalString, but return a pointer /// with "i8*" type instead of a pointer to array of i8. Value *CreateGlobalStringPtr(const char *Str = "", const Twine &Name = "") { @@ -823,7 +867,7 @@ public: Value *Args[] = { zero, zero }; return CreateInBoundsGEP(gv, Args, Args+2, Name); } - + //===--------------------------------------------------------------------===// // Instruction creation methods: Cast/Conversion Operators //===--------------------------------------------------------------------===// @@ -873,7 +917,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateZExtOrBitCast(VC, DestTy); + return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name); } Value *CreateSExtOrBitCast(Value *V, const Type *DestTy, @@ -881,7 +925,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateSExtOrBitCast(VC, DestTy); + return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name); } Value *CreateTruncOrBitCast(Value *V, const Type *DestTy, @@ -889,7 +933,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateTruncOrBitCast(VC, DestTy); + return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name); return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name); } Value *CreateCast(Instruction::CastOps Op, Value *V, const Type *DestTy, @@ -897,7 +941,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateCast(Op, VC, DestTy); + return Insert(Folder.CreateCast(Op, VC, DestTy), Name); return Insert(CastInst::Create(Op, V, DestTy), Name); } Value *CreatePointerCast(Value *V, const Type *DestTy, @@ -905,7 +949,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreatePointerCast(VC, DestTy); + return Insert(Folder.CreatePointerCast(VC, DestTy), Name); return Insert(CastInst::CreatePointerCast(V, DestTy), Name); } Value *CreateIntCast(Value *V, const Type *DestTy, bool isSigned, @@ -913,7 +957,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateIntCast(VC, DestTy, isSigned); + return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } private: @@ -925,7 +969,7 @@ public: if (V->getType() == DestTy) return V; if (Constant *VC = dyn_cast<Constant>(V)) - return Folder.CreateFPCast(VC, DestTy); + return Insert(Folder.CreateFPCast(VC, DestTy), Name); return Insert(CastInst::CreateFPCast(V, DestTy), Name); } @@ -1011,14 +1055,14 @@ public: const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateICmp(P, LC, RC); + return Insert(Folder.CreateICmp(P, LC, RC), Name); return Insert(new ICmpInst(P, LHS, RHS), Name); } Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name = "") { if (Constant *LC = dyn_cast<Constant>(LHS)) if (Constant *RC = dyn_cast<Constant>(RHS)) - return Folder.CreateFCmp(P, LC, RC); + return Insert(Folder.CreateFCmp(P, LC, RC), Name); return Insert(new FCmpInst(P, LHS, RHS), Name); } @@ -1057,9 +1101,9 @@ public: return Insert(CallInst::Create(Callee, Args, Args+5), Name); } - template<typename InputIterator> - CallInst *CreateCall(Value *Callee, InputIterator ArgBegin, - InputIterator ArgEnd, const Twine &Name = "") { + template<typename RandomAccessIterator> + CallInst *CreateCall(Value *Callee, RandomAccessIterator ArgBegin, + RandomAccessIterator ArgEnd, const Twine &Name = "") { return Insert(CallInst::Create(Callee, ArgBegin, ArgEnd), Name); } @@ -1068,7 +1112,7 @@ public: if (Constant *CC = dyn_cast<Constant>(C)) if (Constant *TC = dyn_cast<Constant>(True)) if (Constant *FC = dyn_cast<Constant>(False)) - return Folder.CreateSelect(CC, TC, FC); + return Insert(Folder.CreateSelect(CC, TC, FC), Name); return Insert(SelectInst::Create(C, True, False), Name); } @@ -1080,7 +1124,7 @@ public: const Twine &Name = "") { if (Constant *VC = dyn_cast<Constant>(Vec)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateExtractElement(VC, IC); + return Insert(Folder.CreateExtractElement(VC, IC), Name); return Insert(ExtractElementInst::Create(Vec, Idx), Name); } @@ -1089,7 +1133,7 @@ public: if (Constant *VC = dyn_cast<Constant>(Vec)) if (Constant *NC = dyn_cast<Constant>(NewElt)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Folder.CreateInsertElement(VC, NC, IC); + return Insert(Folder.CreateInsertElement(VC, NC, IC), Name); return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); } @@ -1098,24 +1142,25 @@ public: if (Constant *V1C = dyn_cast<Constant>(V1)) if (Constant *V2C = dyn_cast<Constant>(V2)) if (Constant *MC = dyn_cast<Constant>(Mask)) - return Folder.CreateShuffleVector(V1C, V2C, MC); + return Insert(Folder.CreateShuffleVector(V1C, V2C, MC), Name); return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); } Value *CreateExtractValue(Value *Agg, unsigned Idx, const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) - return Folder.CreateExtractValue(AggC, &Idx, 1); + return Insert(Folder.CreateExtractValue(AggC, &Idx, 1), Name); return Insert(ExtractValueInst::Create(Agg, Idx), Name); } - template<typename InputIterator> + template<typename RandomAccessIterator> Value *CreateExtractValue(Value *Agg, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) - return Folder.CreateExtractValue(AggC, IdxBegin, IdxEnd - IdxBegin); + return Insert(Folder.CreateExtractValue(AggC, IdxBegin, IdxEnd-IdxBegin), + Name); return Insert(ExtractValueInst::Create(Agg, IdxBegin, IdxEnd), Name); } @@ -1123,18 +1168,20 @@ public: const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) if (Constant *ValC = dyn_cast<Constant>(Val)) - return Folder.CreateInsertValue(AggC, ValC, &Idx, 1); + return Insert(Folder.CreateInsertValue(AggC, ValC, &Idx, 1), Name); return Insert(InsertValueInst::Create(Agg, Val, Idx), Name); } - template<typename InputIterator> + template<typename RandomAccessIterator> Value *CreateInsertValue(Value *Agg, Value *Val, - InputIterator IdxBegin, - InputIterator IdxEnd, + RandomAccessIterator IdxBegin, + RandomAccessIterator IdxEnd, const Twine &Name = "") { if (Constant *AggC = dyn_cast<Constant>(Agg)) if (Constant *ValC = dyn_cast<Constant>(Val)) - return Folder.CreateInsertValue(AggC, ValC, IdxBegin, IdxEnd-IdxBegin); + return Insert(Folder.CreateInsertValue(AggC, ValC, IdxBegin, + IdxEnd - IdxBegin), + Name); return Insert(InsertValueInst::Create(Agg, Val, IdxBegin, IdxEnd), Name); } diff --git a/include/llvm/Support/IRReader.h b/include/llvm/Support/IRReader.h index a44da52..292c001 100644 --- a/include/llvm/Support/IRReader.h +++ b/include/llvm/Support/IRReader.h @@ -19,10 +19,12 @@ #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 { @@ -56,15 +58,14 @@ namespace llvm { inline Module *getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err, LLVMContext &Context) { - std::string ErrMsg; - MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); - if (F == 0) { - Err = SMDiagnostic(Filename, - "Could not open input file: " + ErrMsg); + OwningPtr<MemoryBuffer> File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { + Err = SMDiagnostic(Filename, + "Could not open input file: " + ec.message()); return 0; } - return getLazyIRModule(F, Err, Context); + return getLazyIRModule(File.take(), Err, Context); } /// If the given MemoryBuffer holds a bitcode image, return a Module @@ -94,15 +95,14 @@ namespace llvm { inline Module *ParseIRFile(const std::string &Filename, SMDiagnostic &Err, LLVMContext &Context) { - std::string ErrMsg; - MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); - if (F == 0) { - Err = SMDiagnostic(Filename, - "Could not open input file: " + ErrMsg); + OwningPtr<MemoryBuffer> File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { + Err = SMDiagnostic(Filename, + "Could not open input file: " + ec.message()); return 0; } - return ParseIR(F, Err, Context); + return ParseIR(File.take(), Err, Context); } } diff --git a/include/llvm/Support/IncludeFile.h b/include/llvm/Support/IncludeFile.h new file mode 100644 index 0000000..a931972 --- /dev/null +++ b/include/llvm/Support/IncludeFile.h @@ -0,0 +1,79 @@ +//===- llvm/Support/IncludeFile.h - Ensure Linking Of Library ---*- 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 FORCE_DEFINING_FILE_TO_BE_LINKED and DEFINE_FILE_FOR +// macros. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_INCLUDEFILE_H +#define LLVM_SYSTEM_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 +/// manner that we choose. All header files that depend on a specific .cpp +/// file being linked at run time should use this macro instead of the +/// IncludeFile class directly. +/// +/// For example, foo.h would use:<br/> +/// <tt>FORCE_DEFINING_FILE_TO_BE_LINKED(foo)</tt><br/> +/// +/// And, foo.cp would use:<br/> +/// <tt>DEFINING_FILE_FOR(foo)</tt><br/> +#ifdef __GNUC__ +// If the `used' attribute is available, use it to create a variable +// with an initializer that will force the linking of the defining file. +#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ + namespace llvm { \ + extern const char name ## LinkVar; \ + __attribute__((used)) static const char *const name ## LinkObj = \ + &name ## LinkVar; \ + } +#else +// Otherwise use a constructor call. +#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ + namespace llvm { \ + extern const char name ## LinkVar; \ + static const IncludeFile name ## LinkObj ( &name ## LinkVar ); \ + } +#endif + +/// This macro is the counterpart to FORCE_DEFINING_FILE_TO_BE_LINKED. It should +/// be used in a .cpp file to define the name referenced in a header file that +/// will cause linkage of the .cpp file. It should only be used at extern level. +#define DEFINING_FILE_FOR(name) \ + namespace llvm { const char name ## LinkVar = 0; } + +namespace llvm { + +/// This class is used in the implementation of FORCE_DEFINING_FILE_TO_BE_LINKED +/// macro to make sure that the implementation of a header file is included +/// into a tool that uses the header. This is solely +/// to overcome problems linking .a files and not getting the implementation +/// of compilation units we need. This is commonly an issue with the various +/// Passes but also occurs elsewhere in LLVM. We like to use .a files because +/// they link faster and provide the smallest executables. However, sometimes +/// those executables are too small, if the program doesn't reference something +/// that might be needed, especially by a loaded share object. This little class +/// helps to resolve that problem. The basic strategy is to use this class in +/// a header file and pass the address of a variable to the constructor. If the +/// variable is defined in the header file's corresponding .cpp file then all +/// tools/libraries that \#include the header file will require the .cpp as +/// well. +/// For example:<br/> +/// <tt>extern int LinkMyCodeStub;</tt><br/> +/// <tt>static IncludeFile LinkMyModule(&LinkMyCodeStub);</tt><br/> +/// @brief Class to ensure linking of corresponding object file. +struct IncludeFile { + explicit IncludeFile(const void *); +}; + +} + +#endif diff --git a/include/llvm/Support/LICENSE.TXT b/include/llvm/Support/LICENSE.TXT new file mode 100644 index 0000000..3479b3f --- /dev/null +++ b/include/llvm/Support/LICENSE.TXT @@ -0,0 +1,6 @@ +LLVM System Interface Library +------------------------------------------------------------------------------- +The LLVM System Interface Library is licensed under the Illinois Open Source +License and has the following additional copyright: + +Copyright (C) 2004 eXtensible Systems, Inc. diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index 4c13177..6841a0f 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -14,7 +14,7 @@ #ifndef LLVM_SUPPORT_MACHO_H #define LLVM_SUPPORT_MACHO_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" // NOTE: The enums in this file are intentially named to be different than those // in the headers in /usr/include/mach (on darwin systems) to avoid conflicts @@ -23,7 +23,7 @@ namespace llvm { namespace MachO { // Enums from <mach-o/loader.h> enum { - // Constants for the "magic" field in llvm::MachO::mach_header and + // Constants for the "magic" field in llvm::MachO::mach_header and // llvm::MachO::mach_header_64 HeaderMagic32 = 0xFEEDFACEu, // MH_MAGIC HeaderMagic32Swapped = 0xCEFAEDFEu, // MH_CIGAM @@ -71,7 +71,7 @@ namespace llvm { HeaderFlagBitNoReexportedDylibs = 0x00100000u, // MH_NO_REEXPORTED_DYLIBS HeaderFlagBitPIE = 0x00200000u, // MH_PIE HeaderFlagBitDeadStrippableDylib = 0x00400000u, // MH_DEAD_STRIPPABLE_DYLIB - + // Constants for the "cmd" field in llvm::MachO::load_command LoadCommandDynamicLinkerRequired = 0x80000000u, // LC_REQ_DYLD LoadCommandSegment32 = 0x00000001u, // LC_SEGMENT @@ -110,7 +110,7 @@ namespace llvm { LoadCommandDynamicLinkerInfo = 0x00000022u, // LC_DYLD_INFO LoadCommandDynamicLinkerInfoOnly = 0x80000022u, // LC_DYLD_INFO_ONLY LoadCommandDylibLoadUpward = 0x80000023u, // LC_LOAD_UPWARD_DYLIB - + // Constant bits for the "flags" field in llvm::MachO::segment_command SegmentCommandFlagBitHighVM = 0x1u, // SG_HIGHVM SegmentCommandFlagBitFixedVMLibrary = 0x2u, // SG_FVMLIB @@ -243,20 +243,20 @@ namespace llvm { StabFunction = 0x24u, // N_FUN StabStaticSymbol = 0x26u, // N_STSYM StabLocalCommon = 0x28u, // N_LCSYM - StabBeginSymbol = 0x2Eu, // N_BNSYM + StabBeginSymbol = 0x2Eu, // N_BNSYM StabSourceFileOptions = 0x3Cu, // N_OPT StabRegisterSymbol = 0x40u, // N_RSYM StabSourceLine = 0x44u, // N_SLINE - StabEndSymbol = 0x4Eu, // N_ENSYM + StabEndSymbol = 0x4Eu, // N_ENSYM StabStructureType = 0x60u, // N_SSYM StabSourceFileName = 0x64u, // N_SO StabObjectFileName = 0x66u, // N_OSO StabLocalSymbol = 0x80u, // N_LSYM StabBeginIncludeFileName = 0x82u, // N_BINCL StabIncludeFileName = 0x84u, // N_SOL - StabCompilerParameters = 0x86u, // N_PARAMS - StabCompilerVersion = 0x88u, // N_VERSION - StabCompilerOptLevel = 0x8Au, // N_OLEVEL + StabCompilerParameters = 0x86u, // N_PARAMS + StabCompilerVersion = 0x88u, // N_VERSION + StabCompilerOptLevel = 0x8Au, // N_OLEVEL StabParameter = 0xA0u, // N_PSYM StabEndIncludeFile = 0xA2u, // N_EINCL StabAlternateEntry = 0xA4u, // N_ENTRY @@ -269,9 +269,9 @@ namespace llvm { StabLength = 0xFEu // N_LENG }; - + // Structs from <mach-o/loader.h> - + struct mach_header { uint32_t magic; uint32_t cputype; @@ -636,12 +636,12 @@ namespace llvm { }; // Get/Set functions from <mach-o/nlist.h> - + static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) { return (((n_desc) >> 8u) & 0xffu); } - + static inline void SET_LIBRARY_ORDINAL(uint16_t &n_desc, uint8_t ordinal) { n_desc = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8)); @@ -651,7 +651,7 @@ namespace llvm { { return (n_desc >> 8u) & 0x0fu; } - + static inline void SET_COMM_ALIGN (uint16_t &n_desc, uint8_t align) { n_desc = ((n_desc & 0xf0ffu) | ((align & 0x0fu) << 8u)); @@ -662,7 +662,7 @@ namespace llvm { // Capability bits used in the definition of cpu_type. CPUArchMask = 0xff000000, // Mask for architecture bits CPUArchABI64 = 0x01000000, // 64 bit ABI - + // Constants for the cputype field. CPUTypeI386 = 7, CPUTypeX86_64 = CPUTypeI386 | CPUArchABI64, @@ -673,19 +673,21 @@ namespace llvm { // Constants for the cpusubtype field. - + // X86 CPUSubType_I386_ALL = 3, CPUSubType_X86_64_ALL = 3, - + // ARM CPUSubType_ARM_ALL = 0, CPUSubType_ARM_V4T = 5, + CPUSubType_ARM_V5 = 7, CPUSubType_ARM_V6 = 6, + CPUSubType_ARM_V7 = 9, // PowerPC CPUSubType_POWERPC_ALL = 0, - + CPUSubType_SPARC_ALL = 0 }; } // end namespace MachO diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index b8e2235..53e73ad 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -14,8 +14,8 @@ #ifndef LLVM_SUPPORT_MANAGED_STATIC_H #define LLVM_SUPPORT_MANAGED_STATIC_H -#include "llvm/System/Atomic.h" -#include "llvm/System/Threading.h" +#include "llvm/Support/Atomic.h" +#include "llvm/Support/Threading.h" namespace llvm { @@ -91,12 +91,6 @@ public: } }; -template<void (*CleanupFn)(void*)> -class ManagedCleanup : public ManagedStaticBase { -public: - void Register() { RegisterManagedStatic(0, CleanupFn); } -}; - /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. void llvm_shutdown(); diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 982813f..4627557 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -14,7 +14,7 @@ #ifndef LLVM_SUPPORT_MATHEXTRAS_H #define LLVM_SUPPORT_MATHEXTRAS_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/SwapByteOrder.h" namespace llvm { @@ -70,6 +70,18 @@ inline bool isUInt<32>(uint64_t x) { return static_cast<uint32_t>(x) == x; } +/// isUIntN - Checks if an unsigned integer fits into the given (dynamic) +/// bit width. +inline bool isUIntN(unsigned N, uint64_t x) { + return x == (x & (~0ULL >> (64 - N))); +} + +/// isIntN - Checks if an signed integer fits into the given (dynamic) +/// bit width. +inline bool isIntN(unsigned N, int64_t x) { + return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); +} + /// isMask_32 - This function returns true if the argument is a sequence of ones /// starting at the least significant bit with the remainder zero (32 bit /// version). Ex. isMask_32(0x0000FFFFU) == true. @@ -112,47 +124,19 @@ inline bool isPowerOf2_64(uint64_t Value) { /// ByteSwap_16 - This function returns a byte-swapped representation of the /// 16-bit argument, Value. inline uint16_t ByteSwap_16(uint16_t Value) { -#if defined(_MSC_VER) && !defined(_DEBUG) - // The DLL version of the runtime lacks these functions (bug!?), but in a - // release build they're replaced with BSWAP instructions anyway. - return _byteswap_ushort(Value); -#else - uint16_t Hi = Value << 8; - uint16_t Lo = Value >> 8; - return Hi | Lo; -#endif + return sys::SwapByteOrder_16(Value); } /// ByteSwap_32 - This function returns a byte-swapped representation of the /// 32-bit argument, Value. inline uint32_t ByteSwap_32(uint32_t Value) { -#if defined(__llvm__) || \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) - return __builtin_bswap32(Value); -#elif defined(_MSC_VER) && !defined(_DEBUG) - return _byteswap_ulong(Value); -#else - uint32_t Byte0 = Value & 0x000000FF; - uint32_t Byte1 = Value & 0x0000FF00; - uint32_t Byte2 = Value & 0x00FF0000; - uint32_t Byte3 = Value & 0xFF000000; - return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); -#endif + return sys::SwapByteOrder_32(Value); } /// ByteSwap_64 - This function returns a byte-swapped representation of the /// 64-bit argument, Value. inline uint64_t ByteSwap_64(uint64_t Value) { -#if defined(__llvm__) || \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) - return __builtin_bswap64(Value); -#elif defined(_MSC_VER) && !defined(_DEBUG) - return _byteswap_uint64(Value); -#else - uint64_t Hi = ByteSwap_32(uint32_t(Value)); - uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); - return (Hi << 32) | Lo; -#endif + return sys::SwapByteOrder_64(Value); } /// CountLeadingZeros_32 - this function performs the platform optimal form of diff --git a/include/llvm/Support/Memory.h b/include/llvm/Support/Memory.h new file mode 100644 index 0000000..9c3f85b --- /dev/null +++ b/include/llvm/Support/Memory.h @@ -0,0 +1,96 @@ +//===- llvm/Support/Memory.h - Memory Support --------------------*- 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::Memory class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_MEMORY_H +#define LLVM_SYSTEM_MEMORY_H + +#include "llvm/Support/DataTypes.h" +#include <string> + +namespace llvm { +namespace sys { + + /// This class encapsulates the notion of a memory block which has an address + /// and a size. It is used by the Memory class (a friend) as the result of + /// various memory allocation operations. + /// @see Memory + /// @brief Memory block abstraction. + class MemoryBlock { + public: + MemoryBlock() : Address(0), Size(0) { } + MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } + void *base() const { return Address; } + size_t size() const { return Size; } + private: + void *Address; ///< Address of first byte of memory area + size_t Size; ///< Size, in bytes of the memory area + friend class Memory; + }; + + /// This class provides various memory handling functions that manipulate + /// MemoryBlock instances. + /// @since 1.4 + /// @brief An abstraction for memory operations. + class Memory { + public: + /// This method allocates a block of Read/Write/Execute memory that is + /// suitable for executing dynamically generated code (e.g. JIT). An + /// attempt to allocate \p NumBytes bytes of virtual memory is made. + /// \p NearBlock may point to an existing allocation in which case + /// an attempt is made to allocate more memory near the existing block. + /// + /// On success, this returns a non-null memory block, otherwise it returns + /// a null memory block and fills in *ErrMsg. + /// + /// @brief Allocate Read/Write/Execute memory. + static MemoryBlock AllocateRWX(size_t NumBytes, + const MemoryBlock *NearBlock, + std::string *ErrMsg = 0); + + /// This method releases a block of Read/Write/Execute memory that was + /// allocated with the AllocateRWX method. It should not be used to + /// release any memory block allocated any other way. + /// + /// On success, this returns false, otherwise it returns true and fills + /// in *ErrMsg. + /// @brief Release Read/Write/Execute memory. + static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = 0); + + + /// InvalidateInstructionCache - Before the JIT can run a block of code + /// that has been emitted it must invalidate the instruction cache on some + /// platforms. + static void InvalidateInstructionCache(const void *Addr, size_t Len); + + /// setExecutable - Before the JIT can run a block of code, it has to be + /// given read and executable privilege. Return true if it is already r-x + /// or the system is able to change its previlege. + static bool setExecutable (MemoryBlock &M, std::string *ErrMsg = 0); + + /// setWritable - When adding to a block of code, the JIT may need + /// to mark a block of code as RW since the protections are on page + /// boundaries, and the JIT internal allocations are not page aligned. + static bool setWritable (MemoryBlock &M, std::string *ErrMsg = 0); + + /// setRangeExecutable - Mark the page containing a range of addresses + /// as executable. + static bool setRangeExecutable(const void *Addr, size_t Size); + + /// setRangeWritable - Mark the page containing a range of addresses + /// as writable. + static bool setRangeWritable(const void *Addr, size_t Size); + }; +} +} + +#endif diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index 8a41aa5..b6243b7 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -15,12 +15,13 @@ #define LLVM_SUPPORT_MEMORYBUFFER_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" -#include <string> -#include <sys/stat.h> +#include "llvm/Support/DataTypes.h" namespace llvm { +class error_code; +template<class T> class OwningPtr; + /// MemoryBuffer - This interface provides simple read-only access to a block /// of memory, and provides simple methods for reading files and standard input /// into a memory buffer. In addition to basic access to the characters in the @@ -47,8 +48,8 @@ public: const char *getBufferEnd() const { return BufferEnd; } size_t getBufferSize() const { return BufferEnd-BufferStart; } - StringRef getBuffer() const { - return StringRef(BufferStart, getBufferSize()); + StringRef getBuffer() const { + return StringRef(BufferStart, getBufferSize()); } /// getBufferIdentifier - Return an identifier for this buffer, typically the @@ -61,23 +62,26 @@ public: /// MemoryBuffer if successful, otherwise returning null. If FileSize is /// specified, this means that the client knows that the file exists and that /// it has the specified size. - static MemoryBuffer *getFile(StringRef Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); - static MemoryBuffer *getFile(const char *Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); + static error_code getFile(StringRef Filename, OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); + static error_code getFile(const char *Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); + + /// getOpenFile - Given an already-open file descriptor, read the file and + /// return a MemoryBuffer. + static error_code getOpenFile(int FD, const char *Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note - /// that EndPtr[0] must be a null byte and be accessible! + /// that InputData must be null terminated. static MemoryBuffer *getMemBuffer(StringRef InputData, StringRef BufferName = ""); /// getMemBufferCopy - Open the specified memory range as a MemoryBuffer, - /// copying the contents and taking ownership of it. This has no requirements - /// on EndPtr[0]. + /// copying the contents and taking ownership of it. InputData does not + /// have to be null terminated. static MemoryBuffer *getMemBufferCopy(StringRef InputData, StringRef BufferName = ""); @@ -95,21 +99,19 @@ public: StringRef BufferName = ""); /// getSTDIN - Read all of stdin into a file buffer, and return it. - /// If an error occurs, this returns null and fills in *ErrStr with a reason. - static MemoryBuffer *getSTDIN(std::string *ErrStr = 0); + /// If an error occurs, this returns null and sets ec. + static error_code getSTDIN(OwningPtr<MemoryBuffer> &result); /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin - /// if the Filename is "-". If an error occurs, this returns null and fills - /// in *ErrStr with a reason. - static MemoryBuffer *getFileOrSTDIN(StringRef Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); - static MemoryBuffer *getFileOrSTDIN(const char *Filename, - std::string *ErrStr = 0, - int64_t FileSize = -1, - struct stat *FileInfo = 0); + /// if the Filename is "-". If an error occurs, this returns null and sets + /// ec. + static error_code getFileOrSTDIN(StringRef Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); + static error_code getFileOrSTDIN(const char *Filename, + OwningPtr<MemoryBuffer> &result, + int64_t FileSize = -1); }; } // end namespace llvm diff --git a/include/llvm/Support/MemoryObject.h b/include/llvm/Support/MemoryObject.h index e193ca2..dec0f13 100644 --- a/include/llvm/Support/MemoryObject.h +++ b/include/llvm/Support/MemoryObject.h @@ -10,7 +10,7 @@ #ifndef MEMORYOBJECT_H #define MEMORYOBJECT_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h new file mode 100644 index 0000000..42ea630 --- /dev/null +++ b/include/llvm/Support/Mutex.h @@ -0,0 +1,154 @@ +//===- llvm/Support/Mutex.h - Mutex Operating System Concept -----*- 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::Mutex class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_MUTEX_H +#define LLVM_SYSTEM_MUTEX_H + +#include "llvm/Support/Threading.h" +#include <cassert> + +namespace llvm +{ + namespace sys + { + /// @brief Platform agnostic Mutex class. + class MutexImpl + { + /// @name Constructors + /// @{ + public: + + /// Initializes the lock but doesn't acquire it. if \p recursive is set + /// to false, the lock will not be recursive which makes it cheaper but + /// also more likely to deadlock (same thread can't acquire more than + /// once). + /// @brief Default Constructor. + explicit MutexImpl(bool recursive = true); + + /// Releases and removes the lock + /// @brief Destructor + ~MutexImpl(); + + /// @} + /// @name Methods + /// @{ + public: + + /// Attempts to unconditionally acquire the lock. If the lock is held by + /// another thread, this method will wait until it can acquire the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock. + bool acquire(); + + /// Attempts to release the lock. If the lock is held by the current + /// thread, the lock is released allowing other threads to acquire the + /// lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock. + bool release(); + + /// Attempts to acquire the lock without blocking. If the lock is not + /// available, this function returns false quickly (without blocking). If + /// the lock is available, it is acquired. + /// @returns false if any kind of error occurs or the lock is not + /// available, true otherwise. + /// @brief Try to acquire the lock. + bool tryacquire(); + + //@} + /// @name Platform Dependent Data + /// @{ + private: + void* data_; ///< We don't know what the data will be + + /// @} + /// @name Do Not Implement + /// @{ + private: + MutexImpl(const MutexImpl & original); + void operator=(const MutexImpl &); + /// @} + }; + + + /// SmartMutex - A mutex with a compile time constant parameter that + /// indicates whether this mutex should become a no-op when we're not + /// running in multithreaded mode. + template<bool mt_only> + class SmartMutex : public MutexImpl { + unsigned acquired; + bool recursive; + public: + explicit SmartMutex(bool rec = true) : + MutexImpl(rec), acquired(0), recursive(rec) { } + + bool acquire() { + if (!mt_only || llvm_is_multithreaded()) { + return MutexImpl::acquire(); + } else { + // Single-threaded debugging code. This would be racy in + // multithreaded mode, but provides not sanity checks in single + // threaded mode. + assert((recursive || acquired == 0) && "Lock already acquired!!"); + ++acquired; + return true; + } + } + + bool release() { + if (!mt_only || llvm_is_multithreaded()) { + return MutexImpl::release(); + } else { + // Single-threaded debugging code. This would be racy in + // multithreaded mode, but provides not sanity checks in single + // threaded mode. + assert(((recursive && acquired) || (acquired == 1)) && + "Lock not acquired before release!"); + --acquired; + return true; + } + } + + bool tryacquire() { + if (!mt_only || llvm_is_multithreaded()) + return MutexImpl::tryacquire(); + else return true; + } + + private: + SmartMutex(const SmartMutex<mt_only> & original); + void operator=(const SmartMutex<mt_only> &); + }; + + /// Mutex - A standard, always enforced mutex. + typedef SmartMutex<false> Mutex; + + template<bool mt_only> + class SmartScopedLock { + SmartMutex<mt_only>& mtx; + + public: + SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) { + mtx.acquire(); + } + + ~SmartScopedLock() { + mtx.release(); + } + }; + + typedef SmartScopedLock<false> ScopedLock; + } +} + +#endif diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h index 9958b97..cd13bfe 100644 --- a/include/llvm/Support/MutexGuard.h +++ b/include/llvm/Support/MutexGuard.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_MUTEXGUARD_H #define LLVM_SUPPORT_MUTEXGUARD_H -#include "llvm/System/Mutex.h" +#include "llvm/Support/Mutex.h" namespace llvm { /// Instances of this class acquire a given Mutex Lock when constructed and diff --git a/include/llvm/Support/NoFolder.h b/include/llvm/Support/NoFolder.h index 01256e1..d7b5b42 100644 --- a/include/llvm/Support/NoFolder.h +++ b/include/llvm/Support/NoFolder.h @@ -15,8 +15,7 @@ // llvm/Analysis/ConstantFolding.h. // // Note: since it is not actually possible to create unfolded constants, this -// class returns values rather than constants. The values do not have names, -// even if names were provided to IRBuilder, which may be confusing. +// class returns instructions rather than constants. // //===----------------------------------------------------------------------===// @@ -30,7 +29,7 @@ namespace llvm { class LLVMContext; -/// NoFolder - Create "constants" (actually, values) with no folding. +/// NoFolder - Create "constants" (actually, instructions) with no folding. class NoFolder { public: explicit NoFolder(LLVMContext &) {} @@ -39,84 +38,87 @@ public: // Binary Operators //===--------------------------------------------------------------------===// - Value *CreateAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateAdd(LHS, RHS); } - Value *CreateNSWAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateNSWAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWAdd(LHS, RHS); } - Value *CreateNUWAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateNUWAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNUWAdd(LHS, RHS); } - Value *CreateFAdd(Constant *LHS, Constant *RHS) const { + Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFAdd(LHS, RHS); } - Value *CreateSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateSub(LHS, RHS); } - Value *CreateNSWSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateNSWSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWSub(LHS, RHS); } - Value *CreateNUWSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateNUWSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNUWSub(LHS, RHS); } - Value *CreateFSub(Constant *LHS, Constant *RHS) const { + Instruction *CreateFSub(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFSub(LHS, RHS); } - Value *CreateMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateMul(LHS, RHS); } - Value *CreateNSWMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateNSWMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNSWMul(LHS, RHS); } - Value *CreateNUWMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateNUWMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateNUWMul(LHS, RHS); } - Value *CreateFMul(Constant *LHS, Constant *RHS) const { + Instruction *CreateFMul(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFMul(LHS, RHS); } - Value *CreateUDiv(Constant *LHS, Constant *RHS) const { + Instruction *CreateUDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateUDiv(LHS, RHS); } - Value *CreateSDiv(Constant *LHS, Constant *RHS) const { + Instruction *CreateExactUDiv(Constant *LHS, Constant *RHS) const { + return BinaryOperator::CreateExactUDiv(LHS, RHS); + } + Instruction *CreateSDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateSDiv(LHS, RHS); } - Value *CreateExactSDiv(Constant *LHS, Constant *RHS) const { + Instruction *CreateExactSDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateExactSDiv(LHS, RHS); } - Value *CreateFDiv(Constant *LHS, Constant *RHS) const { + Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFDiv(LHS, RHS); } - Value *CreateURem(Constant *LHS, Constant *RHS) const { + Instruction *CreateURem(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateURem(LHS, RHS); } - Value *CreateSRem(Constant *LHS, Constant *RHS) const { + Instruction *CreateSRem(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateSRem(LHS, RHS); } - Value *CreateFRem(Constant *LHS, Constant *RHS) const { + Instruction *CreateFRem(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateFRem(LHS, RHS); } - Value *CreateShl(Constant *LHS, Constant *RHS) const { + Instruction *CreateShl(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateShl(LHS, RHS); } - Value *CreateLShr(Constant *LHS, Constant *RHS) const { + Instruction *CreateLShr(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateLShr(LHS, RHS); } - Value *CreateAShr(Constant *LHS, Constant *RHS) const { + Instruction *CreateAShr(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateAShr(LHS, RHS); } - Value *CreateAnd(Constant *LHS, Constant *RHS) const { + Instruction *CreateAnd(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateAnd(LHS, RHS); } - Value *CreateOr(Constant *LHS, Constant *RHS) const { + Instruction *CreateOr(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateOr(LHS, RHS); } - Value *CreateXor(Constant *LHS, Constant *RHS) const { + Instruction *CreateXor(Constant *LHS, Constant *RHS) const { return BinaryOperator::CreateXor(LHS, RHS); } - Value *CreateBinOp(Instruction::BinaryOps Opc, - Constant *LHS, Constant *RHS) const { + Instruction *CreateBinOp(Instruction::BinaryOps Opc, + Constant *LHS, Constant *RHS) const { return BinaryOperator::Create(Opc, LHS, RHS); } @@ -124,16 +126,19 @@ public: // Unary Operators //===--------------------------------------------------------------------===// - Value *CreateNeg(Constant *C) const { + Instruction *CreateNeg(Constant *C) const { return BinaryOperator::CreateNeg(C); } - Value *CreateNSWNeg(Constant *C) const { + Instruction *CreateNSWNeg(Constant *C) const { return BinaryOperator::CreateNSWNeg(C); } - Value *CreateNUWNeg(Constant *C) const { + Instruction *CreateNUWNeg(Constant *C) const { return BinaryOperator::CreateNUWNeg(C); } - Value *CreateNot(Constant *C) const { + Instruction *CreateFNeg(Constant *C) const { + return BinaryOperator::CreateFNeg(C); + } + Instruction *CreateNot(Constant *C) const { return BinaryOperator::CreateNot(C); } @@ -145,8 +150,8 @@ public: unsigned NumIdx) const { return ConstantExpr::getGetElementPtr(C, IdxList, NumIdx); } - Value *CreateGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { + Instruction *CreateGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { return GetElementPtrInst::Create(C, IdxList, IdxList+NumIdx); } @@ -154,8 +159,8 @@ public: unsigned NumIdx) const { return ConstantExpr::getInBoundsGetElementPtr(C, IdxList, NumIdx); } - Value *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, - unsigned NumIdx) const { + Instruction *CreateInBoundsGetElementPtr(Constant *C, Value* const *IdxList, + unsigned NumIdx) const { return GetElementPtrInst::CreateInBounds(C, IdxList, IdxList+NumIdx); } @@ -163,23 +168,51 @@ public: // Cast/Conversion Operators //===--------------------------------------------------------------------===// - Value *CreateCast(Instruction::CastOps Op, Constant *C, + Instruction *CreateCast(Instruction::CastOps Op, Constant *C, const Type *DestTy) const { return CastInst::Create(Op, C, DestTy); } - Value *CreateIntCast(Constant *C, const Type *DestTy, + Instruction *CreatePointerCast(Constant *C, const Type *DestTy) const { + return CastInst::CreatePointerCast(C, DestTy); + } + Instruction *CreateIntCast(Constant *C, const Type *DestTy, bool isSigned) const { return CastInst::CreateIntegerCast(C, DestTy, isSigned); } + Instruction *CreateFPCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateFPCast(C, DestTy); + } + + Instruction *CreateBitCast(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::BitCast, C, DestTy); + } + Instruction *CreateIntToPtr(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::IntToPtr, C, DestTy); + } + Instruction *CreatePtrToInt(Constant *C, const Type *DestTy) const { + return CreateCast(Instruction::PtrToInt, C, DestTy); + } + Instruction *CreateZExtOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateZExtOrBitCast(C, DestTy); + } + Instruction *CreateSExtOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateSExtOrBitCast(C, DestTy); + } + + Instruction *CreateTruncOrBitCast(Constant *C, const Type *DestTy) const { + return CastInst::CreateTruncOrBitCast(C, DestTy); + } //===--------------------------------------------------------------------===// // Compare Instructions //===--------------------------------------------------------------------===// - Value *CreateICmp(CmpInst::Predicate P, Constant *LHS, Constant *RHS) const { + Instruction *CreateICmp(CmpInst::Predicate P, + Constant *LHS, Constant *RHS) const { return new ICmpInst(P, LHS, RHS); } - Value *CreateFCmp(CmpInst::Predicate P, Constant *LHS, Constant *RHS) const { + Instruction *CreateFCmp(CmpInst::Predicate P, + Constant *LHS, Constant *RHS) const { return new FCmpInst(P, LHS, RHS); } @@ -187,30 +220,33 @@ public: // Other Instructions //===--------------------------------------------------------------------===// - Value *CreateSelect(Constant *C, Constant *True, Constant *False) const { + Instruction *CreateSelect(Constant *C, + Constant *True, Constant *False) const { return SelectInst::Create(C, True, False); } - Value *CreateExtractElement(Constant *Vec, Constant *Idx) const { + Instruction *CreateExtractElement(Constant *Vec, Constant *Idx) const { return ExtractElementInst::Create(Vec, Idx); } - Value *CreateInsertElement(Constant *Vec, Constant *NewElt, - Constant *Idx) const { + Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt, + Constant *Idx) const { return InsertElementInst::Create(Vec, NewElt, Idx); } - Value *CreateShuffleVector(Constant *V1, Constant *V2, Constant *Mask) const { + Instruction *CreateShuffleVector(Constant *V1, Constant *V2, + Constant *Mask) const { return new ShuffleVectorInst(V1, V2, Mask); } - Value *CreateExtractValue(Constant *Agg, const unsigned *IdxList, - unsigned NumIdx) const { + Instruction *CreateExtractValue(Constant *Agg, const unsigned *IdxList, + unsigned NumIdx) const { return ExtractValueInst::Create(Agg, IdxList, IdxList+NumIdx); } - Value *CreateInsertValue(Constant *Agg, Constant *Val, - const unsigned *IdxList, unsigned NumIdx) const { + Instruction *CreateInsertValue(Constant *Agg, Constant *Val, + const unsigned *IdxList, + unsigned NumIdx) const { return InsertValueInst::Create(Agg, Val, IdxList, IdxList+NumIdx); } }; diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h new file mode 100644 index 0000000..196eecc --- /dev/null +++ b/include/llvm/Support/Path.h @@ -0,0 +1,16 @@ +//===- llvm/Support/Path.h - Path Operating System Concept ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file currently includes both PathV1 and PathV2 to facilitate moving +// clients over to the new interface. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/PathV1.h" +#include "llvm/Support/PathV2.h" diff --git a/include/llvm/Support/PathV1.h b/include/llvm/Support/PathV1.h new file mode 100644 index 0000000..a1c3f6a --- /dev/null +++ b/include/llvm/Support/PathV1.h @@ -0,0 +1,755 @@ +//===- llvm/Support/PathV1.h - Path Operating System Concept ----*- 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::Path class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PATH_H +#define LLVM_SYSTEM_PATH_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/TimeValue.h" +#include <set> +#include <string> +#include <vector> + +#define LLVM_PATH_DEPRECATED_MSG(replacement) \ + "PathV1 has been deprecated and will be removed as soon as all LLVM and" \ + " Clang clients have been moved over to PathV2. Please use `" #replacement \ + "` from PathV2 instead." + +namespace llvm { +namespace sys { + + /// This structure provides basic file system information about a file. It + /// is patterned after the stat(2) Unix operating system call but made + /// platform independent and eliminates many of the unix-specific fields. + /// However, to support llvm-ar, the mode, user, and group fields are + /// retained. These pertain to unix security and may not have a meaningful + /// value on non-Unix platforms. However, the other fields should + /// always be applicable on all platforms. The structure is filled in by + /// the PathWithStatus class. + /// @brief File status structure + class FileStatus { + public: + uint64_t fileSize; ///< Size of the file in bytes + TimeValue modTime; ///< Time of file's modification + uint32_t mode; ///< Mode of the file, if applicable + uint32_t user; ///< User ID of owner, if applicable + uint32_t group; ///< Group ID of owner, if applicable + uint64_t uniqueID; ///< A number to uniquely ID this file + bool isDir : 1; ///< True if this is a directory. + bool isFile : 1; ///< True if this is a file. + + FileStatus() : fileSize(0), modTime(0,0), mode(0777), user(999), + group(999), uniqueID(0), isDir(false), isFile(false) { } + + TimeValue getTimestamp() const { return modTime; } + uint64_t getSize() const { return fileSize; } + uint32_t getMode() const { return mode; } + uint32_t getUser() const { return user; } + uint32_t getGroup() const { return group; } + uint64_t getUniqueID() const { return uniqueID; } + }; + + /// This class provides an abstraction for the path to a file or directory + /// in the operating system's filesystem and provides various basic operations + /// on it. Note that this class only represents the name of a path to a file + /// or directory which may or may not be valid for a given machine's file + /// system. The class is patterned after the java.io.File class with various + /// extensions and several omissions (not relevant to LLVM). A Path object + /// ensures that the path it encapsulates is syntactically valid for the + /// operating system it is running on but does not ensure correctness for + /// any particular file system. That is, a syntactically valid path might + /// specify path components that do not exist in the file system and using + /// such a Path to act on the file system could produce errors. There is one + /// invalid Path value which is permitted: the empty path. The class should + /// never allow a syntactically invalid non-empty path name to be assigned. + /// Empty paths are required in order to indicate an error result in some + /// situations. If the path is empty, the isValid operation will return + /// false. All operations will fail if isValid is false. Operations that + /// change the path will either return false if it would cause a syntactically + /// invalid path name (in which case the Path object is left unchanged) or + /// throw an std::string exception indicating the error. The methods are + /// grouped into four basic categories: Path Accessors (provide information + /// about the path without accessing disk), Disk Accessors (provide + /// information about the underlying file or directory), Path Mutators + /// (change the path information, not the disk), and Disk Mutators (change + /// the disk file/directory referenced by the path). The Disk Mutator methods + /// all have the word "disk" embedded in their method name to reinforce the + /// notion that the operation modifies the file system. + /// @since 1.4 + /// @brief An abstraction for operating system paths. + class Path { + /// @name Constructors + /// @{ + public: + /// Construct a path to the root directory of the file system. The root + /// directory is a top level directory above which there are no more + /// directories. For example, on UNIX, the root directory is /. On Windows + /// it is file:///. Other operating systems may have different notions of + /// what the root directory is or none at all. In that case, a consistent + /// default root directory will be used. + LLVM_ATTRIBUTE_DEPRECATED(static Path GetRootDirectory(), + LLVM_PATH_DEPRECATED_MSG(NOTHING)); + + /// Construct a path to a unique temporary directory that is created in + /// a "standard" place for the operating system. The directory is + /// guaranteed to be created on exit from this function. If the directory + /// cannot be created, the function will throw an exception. + /// @returns an invalid path (empty) on error + /// @param ErrMsg Optional place for an error message if an error occurs + /// @brief Construct a path to an new, unique, existing temporary + /// directory. + static Path GetTemporaryDirectory(std::string* ErrMsg = 0); + + /// Construct a vector of sys::Path that contains the "standard" system + /// library paths suitable for linking into programs. + /// @brief Construct a path to the system library directory + static void GetSystemLibraryPaths(std::vector<sys::Path>& Paths); + + /// Construct a vector of sys::Path that contains the "standard" bitcode + /// library paths suitable for linking into an llvm program. This function + /// *must* return the value of LLVM_LIB_SEARCH_PATH as well as the value + /// of LLVM_LIBDIR. It also must provide the System library paths as + /// returned by GetSystemLibraryPaths. + /// @see GetSystemLibraryPaths + /// @brief Construct a list of directories in which bitcode could be + /// found. + static void GetBitcodeLibraryPaths(std::vector<sys::Path>& Paths); + + /// Find the path to a library using its short name. Use the system + /// dependent library paths to locate the library. + /// @brief Find a library. + static Path FindLibrary(std::string& short_name); + + /// Construct a path to the default LLVM configuration directory. The + /// implementation must ensure that this is a well-known (same on many + /// systems) directory in which llvm configuration files exist. For + /// example, on Unix, the /etc/llvm directory has been selected. + /// @brief Construct a path to the default LLVM configuration directory + static Path GetLLVMDefaultConfigDir(); + + /// Construct a path to the LLVM installed configuration directory. The + /// implementation must ensure that this refers to the "etc" directory of + /// the LLVM installation. This is the location where configuration files + /// will be located for a particular installation of LLVM on a machine. + /// @brief Construct a path to the LLVM installed configuration directory + static Path GetLLVMConfigDir(); + + /// Construct a path to the current user's home directory. The + /// implementation must use an operating system specific mechanism for + /// determining the user's home directory. For example, the environment + /// variable "HOME" could be used on Unix. If a given operating system + /// does not have the concept of a user's home directory, this static + /// constructor must provide the same result as GetRootDirectory. + /// @brief Construct a path to the current user's "home" directory + static Path GetUserHomeDirectory(); + + /// Construct a path to the current directory for the current process. + /// @returns The current working directory. + /// @brief Returns the current working directory. + static Path GetCurrentDirectory(); + + /// Return the suffix commonly used on file names that contain an + /// executable. + /// @returns The executable file suffix for the current platform. + /// @brief Return the executable file suffix. + static StringRef GetEXESuffix(); + + /// Return the suffix commonly used on file names that contain a shared + /// object, shared archive, or dynamic link library. Such files are + /// linked at runtime into a process and their code images are shared + /// between processes. + /// @returns The dynamic link library suffix for the current platform. + /// @brief Return the dynamic link library suffix. + static StringRef GetDLLSuffix(); + + /// GetMainExecutable - Return the path to the main executable, given the + /// value of argv[0] from program startup and the address of main itself. + /// In extremis, this function may fail and return an empty path. + static Path GetMainExecutable(const char *argv0, void *MainAddr); + + /// This is one of the very few ways in which a path can be constructed + /// with a syntactically invalid name. The only *legal* invalid name is an + /// empty one. Other invalid names are not permitted. Empty paths are + /// provided so that they can be used to indicate null or error results in + /// other lib/System functionality. + /// @brief Construct an empty (and invalid) path. + Path() : path() {} + Path(const Path &that) : path(that.path) {} + + /// This constructor will accept a char* or std::string as a path. No + /// checking is done on this path to determine if it is valid. To + /// determine validity of the path, use the isValid method. + /// @param p The path to assign. + /// @brief Construct a Path from a string. + explicit Path(StringRef p); + + /// This constructor will accept a character range as a path. No checking + /// is done on this path to determine if it is valid. To determine + /// validity of the path, use the isValid method. + /// @param StrStart A pointer to the first character of the path name + /// @param StrLen The length of the path name at StrStart + /// @brief Construct a Path from a string. + Path(const char *StrStart, unsigned StrLen); + + /// @} + /// @name Operators + /// @{ + public: + /// Makes a copy of \p that to \p this. + /// @returns \p this + /// @brief Assignment Operator + Path &operator=(const Path &that) { + path = that.path; + return *this; + } + + /// Makes a copy of \p that to \p this. + /// @param that A StringRef denoting the path + /// @returns \p this + /// @brief Assignment Operator + Path &operator=(StringRef that); + + /// Compares \p this Path with \p that Path for equality. + /// @returns true if \p this and \p that refer to the same thing. + /// @brief Equality Operator + bool operator==(const Path &that) const; + + /// Compares \p this Path with \p that Path for inequality. + /// @returns true if \p this and \p that refer to different things. + /// @brief Inequality Operator + bool operator!=(const Path &that) const { return !(*this == that); } + + /// Determines if \p this Path is less than \p that Path. This is required + /// so that Path objects can be placed into ordered collections (e.g. + /// std::map). The comparison is done lexicographically as defined by + /// the std::string::compare method. + /// @returns true if \p this path is lexicographically less than \p that. + /// @brief Less Than Operator + bool operator<(const Path& that) const; + + /// @} + /// @name Path Accessors + /// @{ + public: + /// This function will use an operating system specific algorithm to + /// determine if the current value of \p this is a syntactically valid + /// path name for the operating system. The path name does not need to + /// exist, validity is simply syntactical. Empty paths are always invalid. + /// @returns true iff the path name is syntactically legal for the + /// host operating system. + /// @brief Determine if a path is syntactically valid or not. + bool isValid() const; + + /// This function determines if the contents of the path name are empty. + /// That is, the path name has a zero length. This does NOT determine if + /// if the file is empty. To get the length of the file itself, Use the + /// PathWithStatus::getFileStatus() method and then the getSize() method + /// on the returned FileStatus object. + /// @returns true iff the path is empty. + /// @brief Determines if the path name is empty (invalid). + bool isEmpty() const { return path.empty(); } + + /// This function returns the last component of the path name. The last + /// component is the file or directory name occurring after the last + /// directory separator. If no directory separator is present, the entire + /// path name is returned (i.e. same as toString). + /// @returns StringRef containing the last component of the path name. + /// @brief Returns the last component of the path name. + LLVM_ATTRIBUTE_DEPRECATED( + StringRef getLast() const, + LLVM_PATH_DEPRECATED_MSG(path::filename)); + + /// This function strips off the path and suffix of the file or directory + /// name and returns just the basename. For example /a/foo.bar would cause + /// this function to return "foo". + /// @returns StringRef containing the basename of the path + /// @brief Get the base name of the path + LLVM_ATTRIBUTE_DEPRECATED(StringRef getBasename() const, + LLVM_PATH_DEPRECATED_MSG(path::stem)); + + /// This function strips off the suffix of the path beginning with the + /// path separator ('/' on Unix, '\' on Windows) and returns the result. + LLVM_ATTRIBUTE_DEPRECATED(StringRef getDirname() const, + LLVM_PATH_DEPRECATED_MSG(path::parent_path)); + + /// This function strips off the path and basename(up to and + /// including the last dot) of the file or directory name and + /// returns just the suffix. For example /a/foo.bar would cause + /// this function to return "bar". + /// @returns StringRef containing the suffix of the path + /// @brief Get the suffix of the path + LLVM_ATTRIBUTE_DEPRECATED(StringRef getSuffix() const, + LLVM_PATH_DEPRECATED_MSG(path::extension)); + + /// Obtain a 'C' string for the path name. + /// @returns a 'C' string containing the path name. + /// @brief Returns the path as a C string. + const char *c_str() const { return path.c_str(); } + const std::string &str() const { return path; } + + + /// size - Return the length in bytes of this path name. + size_t size() const { return path.size(); } + + /// empty - Returns true if the path is empty. + unsigned empty() const { return path.empty(); } + + /// @} + /// @name Disk Accessors + /// @{ + public: + /// This function determines if the path name is absolute, as opposed to + /// relative. + /// @brief Determine if the path is absolute. +//FIXME: LLVM_ATTRIBUTE_DEPRECATED( + bool isAbsolute() const; +//FIXME: LLVMV_PATH_DEPRECATED_MSG(path::is_absolute)); + + /// This function determines if the path name is absolute, as opposed to + /// relative. + /// @brief Determine if the path is absolute. + LLVM_ATTRIBUTE_DEPRECATED( + static bool isAbsolute(const char *NameStart, unsigned NameLen), + LLVM_PATH_DEPRECATED_MSG(path::is_absolute)); + + /// This function opens the file associated with the path name provided by + /// the Path object and reads its magic number. If the magic number at the + /// start of the file matches \p magic, true is returned. In all other + /// cases (file not found, file not accessible, etc.) it returns false. + /// @returns true if the magic number of the file matches \p magic. + /// @brief Determine if file has a specific magic number + LLVM_ATTRIBUTE_DEPRECATED(bool hasMagicNumber(StringRef magic) const, + LLVM_PATH_DEPRECATED_MSG(fs::has_magic)); + + /// This function retrieves the first \p len bytes of the file associated + /// with \p this. These bytes are returned as the "magic number" in the + /// \p Magic parameter. + /// @returns true if the Path is a file and the magic number is retrieved, + /// false otherwise. + /// @brief Get the file's magic number. + bool getMagicNumber(std::string& Magic, unsigned len) const; + + /// This function determines if the path name in the object references an + /// archive file by looking at its magic number. + /// @returns true if the file starts with the magic number for an archive + /// file. + /// @brief Determine if the path references an archive file. + bool isArchive() const; + + /// This function determines if the path name in the object references an + /// LLVM Bitcode file by looking at its magic number. + /// @returns true if the file starts with the magic number for LLVM + /// bitcode files. + /// @brief Determine if the path references a bitcode file. + bool isBitcodeFile() const; + + /// This function determines if the path name in the object references a + /// native Dynamic Library (shared library, shared object) by looking at + /// the file's magic number. The Path object must reference a file, not a + /// directory. + /// @returns true if the file starts with the magic number for a native + /// shared library. + /// @brief Determine if the path references a dynamic library. + bool isDynamicLibrary() const; + + /// This function determines if the path name in the object references a + /// native object file by looking at it's magic number. The term object + /// file is defined as "an organized collection of separate, named + /// sequences of binary data." This covers the obvious file formats such + /// as COFF and ELF, but it also includes llvm ir bitcode, archives, + /// libraries, etc... + /// @returns true if the file starts with the magic number for an object + /// file. + /// @brief Determine if the path references an object file. + bool isObjectFile() const; + + /// This function determines if the path name references an existing file + /// or directory in the file system. + /// @returns true if the pathname references an existing file or + /// directory. + /// @brief Determines if the path is a file or directory in + /// the file system. + LLVM_ATTRIBUTE_DEPRECATED(bool exists() const, + LLVM_PATH_DEPRECATED_MSG(fs::exists)); + + /// This function determines if the path name references an + /// existing directory. + /// @returns true if the pathname references an existing directory. + /// @brief Determines if the path is a directory in the file system. + LLVM_ATTRIBUTE_DEPRECATED(bool isDirectory() const, + LLVM_PATH_DEPRECATED_MSG(fs::is_directory)); + + /// This function determines if the path name references an + /// existing symbolic link. + /// @returns true if the pathname references an existing symlink. + /// @brief Determines if the path is a symlink in the file system. + LLVM_ATTRIBUTE_DEPRECATED(bool isSymLink() const, + LLVM_PATH_DEPRECATED_MSG(fs::is_symlink)); + + /// This function determines if the path name references a readable file + /// or directory in the file system. This function checks for + /// the existence and readability (by the current program) of the file + /// or directory. + /// @returns true if the pathname references a readable file. + /// @brief Determines if the path is a readable file or directory + /// in the file system. + bool canRead() const; + + /// This function determines if the path name references a writable file + /// or directory in the file system. This function checks for the + /// existence and writability (by the current program) of the file or + /// directory. + /// @returns true if the pathname references a writable file. + /// @brief Determines if the path is a writable file or directory + /// in the file system. + bool canWrite() const; + + /// This function checks that what we're trying to work only on a regular + /// file. Check for things like /dev/null, any block special file, or + /// other things that aren't "regular" regular files. + /// @returns true if the file is S_ISREG. + /// @brief Determines if the file is a regular file + bool isRegularFile() const; + + /// This function determines if the path name references an executable + /// file in the file system. This function checks for the existence and + /// executability (by the current program) of the file. + /// @returns true if the pathname references an executable file. + /// @brief Determines if the path is an executable file in the file + /// system. + bool canExecute() const; + + /// This function builds a list of paths that are the names of the + /// files and directories in a directory. + /// @returns true if an error occurs, true otherwise + /// @brief Build a list of directory's contents. + bool getDirectoryContents( + std::set<Path> &paths, ///< The resulting list of file & directory names + std::string* ErrMsg ///< Optional place to return an error message. + ) const; + + /// @} + /// @name Path Mutators + /// @{ + public: + /// The path name is cleared and becomes empty. This is an invalid + /// path name but is the *only* invalid path name. This is provided + /// so that path objects can be used to indicate the lack of a + /// valid path being found. + /// @brief Make the path empty. + void clear() { path.clear(); } + + /// This method sets the Path object to \p unverified_path. This can fail + /// if the \p unverified_path does not pass the syntactic checks of the + /// isValid() method. If verification fails, the Path object remains + /// unchanged and false is returned. Otherwise true is returned and the + /// Path object takes on the path value of \p unverified_path + /// @returns true if the path was set, false otherwise. + /// @param unverified_path The path to be set in Path object. + /// @brief Set a full path from a StringRef + bool set(StringRef unverified_path); + + /// One path component is removed from the Path. If only one component is + /// present in the path, the Path object becomes empty. If the Path object + /// is empty, no change is made. + /// @returns false if the path component could not be removed. + /// @brief Removes the last directory component of the Path. + bool eraseComponent(); + + /// The \p component is added to the end of the Path if it is a legal + /// name for the operating system. A directory separator will be added if + /// needed. + /// @returns false if the path component could not be added. + /// @brief Appends one path component to the Path. + bool appendComponent(StringRef component); + + /// A period and the \p suffix are appended to the end of the pathname. + /// When the \p suffix is empty, no action is performed. + /// @brief Adds a period and the \p suffix to the end of the pathname. + void appendSuffix(StringRef suffix); + + /// The suffix of the filename is erased. The suffix begins with and + /// includes the last . character in the filename after the last directory + /// separator and extends until the end of the name. If no . character is + /// after the last directory separator, then the file name is left + /// unchanged (i.e. it was already without a suffix) but the function + /// returns false. + /// @returns false if there was no suffix to remove, true otherwise. + /// @brief Remove the suffix from a path name. + bool eraseSuffix(); + + /// The current Path name is made unique in the file system. Upon return, + /// the Path will have been changed to make a unique file in the file + /// system or it will not have been changed if the current path name is + /// already unique. + /// @throws std::string if an unrecoverable error occurs. + /// @brief Make the current path name unique in the file system. + bool makeUnique( bool reuse_current /*= true*/, std::string* ErrMsg ); + + /// The current Path name is made absolute by prepending the + /// current working directory if necessary. + LLVM_ATTRIBUTE_DEPRECATED( + void makeAbsolute(), + LLVM_PATH_DEPRECATED_MSG(fs::make_absolute)); + + /// @} + /// @name Disk Mutators + /// @{ + public: + /// This method attempts to make the file referenced by the Path object + /// available for reading so that the canRead() method will return true. + /// @brief Make the file readable; + bool makeReadableOnDisk(std::string* ErrMsg = 0); + + /// This method attempts to make the file referenced by the Path object + /// available for writing so that the canWrite() method will return true. + /// @brief Make the file writable; + bool makeWriteableOnDisk(std::string* ErrMsg = 0); + + /// This method attempts to make the file referenced by the Path object + /// available for execution so that the canExecute() method will return + /// true. + /// @brief Make the file readable; + bool makeExecutableOnDisk(std::string* ErrMsg = 0); + + /// This method allows the last modified time stamp and permission bits + /// to be set on the disk object referenced by the Path. + /// @throws std::string if an error occurs. + /// @returns true on error. + /// @brief Set the status information. + bool setStatusInfoOnDisk(const FileStatus &SI, + std::string *ErrStr = 0) const; + + /// This method attempts to create a directory in the file system with the + /// same name as the Path object. The \p create_parents parameter controls + /// whether intermediate directories are created or not. if \p + /// create_parents is true, then an attempt will be made to create all + /// intermediate directories, as needed. If \p create_parents is false, + /// then only the final directory component of the Path name will be + /// created. The created directory will have no entries. + /// @returns true if the directory could not be created, false otherwise + /// @brief Create the directory this Path refers to. + bool createDirectoryOnDisk( + bool create_parents = false, ///< Determines whether non-existent + ///< directory components other than the last one (the "parents") + ///< are created or not. + std::string* ErrMsg = 0 ///< Optional place to put error messages. + ); + + /// This method attempts to create a file in the file system with the same + /// name as the Path object. The intermediate directories must all exist + /// at the time this method is called. Use createDirectoriesOnDisk to + /// accomplish that. The created file will be empty upon return from this + /// function. + /// @returns true if the file could not be created, false otherwise. + /// @brief Create the file this Path refers to. + bool createFileOnDisk( + std::string* ErrMsg = 0 ///< Optional place to put error messages. + ); + + /// This is like createFile except that it creates a temporary file. A + /// unique temporary file name is generated based on the contents of + /// \p this before the call. The new name is assigned to \p this and the + /// file is created. Note that this will both change the Path object + /// *and* create the corresponding file. This function will ensure that + /// the newly generated temporary file name is unique in the file system. + /// @returns true if the file couldn't be created, false otherwise. + /// @brief Create a unique temporary file + bool createTemporaryFileOnDisk( + bool reuse_current = false, ///< When set to true, this parameter + ///< indicates that if the current file name does not exist then + ///< it will be used without modification. + std::string* ErrMsg = 0 ///< Optional place to put error messages + ); + + /// This method renames the file referenced by \p this as \p newName. The + /// file referenced by \p this must exist. The file referenced by + /// \p newName does not need to exist. + /// @returns true on error, false otherwise + /// @brief Rename one file as another. + bool renamePathOnDisk(const Path& newName, std::string* ErrMsg); + + /// This method attempts to destroy the file or directory named by the + /// last component of the Path. If the Path refers to a directory and the + /// \p destroy_contents is false, an attempt will be made to remove just + /// the directory (the final Path component). If \p destroy_contents is + /// true, an attempt will be made to remove the entire contents of the + /// directory, recursively. If the Path refers to a file, the + /// \p destroy_contents parameter is ignored. + /// @param destroy_contents Indicates whether the contents of a destroyed + /// @param Err An optional string to receive an error message. + /// directory should also be destroyed (recursively). + /// @returns false if the file/directory was destroyed, true on error. + /// @brief Removes the file or directory from the filesystem. + bool eraseFromDisk(bool destroy_contents = false, + std::string *Err = 0) const; + + + /// MapInFilePages - This is a low level system API to map in the file + /// that is currently opened as FD into the current processes' address + /// space for read only access. This function may return null on failure + /// or if the system cannot provide the following constraints: + /// 1) The pages must be valid after the FD is closed, until + /// UnMapFilePages is called. + /// 2) Any padding after the end of the file must be zero filled, if + /// present. + /// 3) The pages must be contiguous. + /// + /// This API is not intended for general use, clients should use + /// MemoryBuffer::getFile instead. + static const char *MapInFilePages(int FD, uint64_t FileSize); + + /// UnMapFilePages - Free pages mapped into the current process by + /// MapInFilePages. + /// + /// This API is not intended for general use, clients should use + /// MemoryBuffer::getFile instead. + static void UnMapFilePages(const char *Base, uint64_t FileSize); + + /// @} + /// @name Data + /// @{ + protected: + // Our win32 implementation relies on this string being mutable. + mutable std::string path; ///< Storage for the path name. + + + /// @} + }; + + /// This class is identical to Path class except it allows you to obtain the + /// file status of the Path as well. The reason for the distinction is one of + /// efficiency. First, the file status requires additional space and the space + /// is incorporated directly into PathWithStatus without an additional malloc. + /// Second, obtaining status information is an expensive operation on most + /// operating systems so we want to be careful and explicit about where we + /// allow this operation in LLVM. + /// @brief Path with file status class. + class PathWithStatus : public Path { + /// @name Constructors + /// @{ + public: + /// @brief Default constructor + PathWithStatus() : Path(), status(), fsIsValid(false) {} + + /// @brief Copy constructor + PathWithStatus(const PathWithStatus &that) + : Path(static_cast<const Path&>(that)), status(that.status), + fsIsValid(that.fsIsValid) {} + + /// This constructor allows construction from a Path object + /// @brief Path constructor + PathWithStatus(const Path &other) + : Path(other), status(), fsIsValid(false) {} + + /// This constructor will accept a char* or std::string as a path. No + /// checking is done on this path to determine if it is valid. To + /// determine validity of the path, use the isValid method. + /// @brief Construct a Path from a string. + explicit PathWithStatus( + StringRef p ///< The path to assign. + ) : Path(p), status(), fsIsValid(false) {} + + /// This constructor will accept a character range as a path. No checking + /// is done on this path to determine if it is valid. To determine + /// validity of the path, use the isValid method. + /// @brief Construct a Path from a string. + explicit PathWithStatus( + const char *StrStart, ///< Pointer to the first character of the path + unsigned StrLen ///< Length of the path. + ) : Path(StrStart, StrLen), status(), fsIsValid(false) {} + + /// Makes a copy of \p that to \p this. + /// @returns \p this + /// @brief Assignment Operator + PathWithStatus &operator=(const PathWithStatus &that) { + static_cast<Path&>(*this) = static_cast<const Path&>(that); + status = that.status; + fsIsValid = that.fsIsValid; + return *this; + } + + /// Makes a copy of \p that to \p this. + /// @returns \p this + /// @brief Assignment Operator + PathWithStatus &operator=(const Path &that) { + static_cast<Path&>(*this) = static_cast<const Path&>(that); + fsIsValid = false; + return *this; + } + + /// @} + /// @name Methods + /// @{ + public: + /// This function returns status information about the file. The type of + /// path (file or directory) is updated to reflect the actual contents + /// of the file system. + /// @returns 0 on failure, with Error explaining why (if non-zero) + /// @returns a pointer to a FileStatus structure on success. + /// @brief Get file status. + const FileStatus *getFileStatus( + bool forceUpdate = false, ///< Force an update from the file system + std::string *Error = 0 ///< Optional place to return an error msg. + ) const; + + /// @} + /// @name Data + /// @{ + private: + mutable FileStatus status; ///< Status information. + mutable bool fsIsValid; ///< Whether we've obtained it or not + + /// @} + }; + + /// This enumeration delineates the kinds of files that LLVM knows about. + enum LLVMFileType { + Unknown_FileType = 0, ///< Unrecognized file + Bitcode_FileType, ///< Bitcode file + Archive_FileType, ///< ar style archive file + ELF_Relocatable_FileType, ///< ELF Relocatable object file + ELF_Executable_FileType, ///< ELF Executable image + ELF_SharedObject_FileType, ///< ELF dynamically linked shared lib + ELF_Core_FileType, ///< ELF core image + Mach_O_Object_FileType, ///< Mach-O Object file + Mach_O_Executable_FileType, ///< Mach-O Executable + Mach_O_FixedVirtualMemorySharedLib_FileType, ///< Mach-O Shared Lib, FVM + Mach_O_Core_FileType, ///< Mach-O Core File + Mach_O_PreloadExecutable_FileType, ///< Mach-O Preloaded Executable + Mach_O_DynamicallyLinkedSharedLib_FileType, ///< Mach-O dynlinked shared lib + Mach_O_DynamicLinker_FileType, ///< The Mach-O dynamic linker + Mach_O_Bundle_FileType, ///< Mach-O Bundle file + Mach_O_DynamicallyLinkedSharedLibStub_FileType, ///< Mach-O Shared lib stub + COFF_FileType ///< COFF object file or lib + }; + + /// This utility function allows any memory block to be examined in order + /// to determine its file type. + LLVMFileType IdentifyFileType(const char*magic, unsigned length); + + /// This function can be used to copy the file specified by Src to the + /// file specified by Dest. If an error occurs, Dest is removed. + /// @returns true if an error occurs, false otherwise + /// @brief Copy one file to another. + bool CopyFile(const Path& Dest, const Path& Src, std::string* ErrMsg); + + /// This is the OS-specific path separator: a colon on Unix or a semicolon + /// on Windows. + extern const char PathSeparator; +} + +} + +#endif diff --git a/include/llvm/Support/PathV2.h b/include/llvm/Support/PathV2.h new file mode 100644 index 0000000..2515633 --- /dev/null +++ b/include/llvm/Support/PathV2.h @@ -0,0 +1,347 @@ +//===- llvm/Support/PathV2.h - Path Operating System Concept ----*- 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::path namespace. It is designed after +// TR2/boost filesystem (v3), but modified to remove exception handling and the +// path class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PATHV2_H +#define LLVM_SUPPORT_PATHV2_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/DataTypes.h" +#include <iterator> + +namespace llvm { +namespace sys { +namespace path { + +/// @name Lexical Component Iterator +/// @{ + +/// @brief Path iterator. +/// +/// This is a bidirectional iterator that iterates over the individual +/// components in \a path. The forward traversal order is as follows: +/// * The root-name element, if present. +/// * The root-directory element, if present. +/// * Each successive filename element, if present. +/// * Dot, if one or more trailing non-root slash characters are present. +/// The backwards traversal order is the reverse of forward traversal. +/// +/// Iteration examples. Each component is separated by ',': +/// / => / +/// /foo => /,foo +/// foo/ => foo,. +/// /foo/bar => /,foo,bar +/// ../ => ..,. +/// C:\foo\bar => C:,/,foo,bar +/// +class const_iterator { + StringRef Path; //< The entire path. + StringRef Component; //< The current component. Not necessarily in Path. + size_t Position; //< The iterators current position within Path. + + // An end iterator has Position = Path.size() + 1. + friend const_iterator begin(StringRef path); + friend const_iterator end(StringRef path); + +public: + typedef const StringRef value_type; + typedef ptrdiff_t difference_type; + typedef value_type &reference; + typedef value_type *pointer; + typedef std::bidirectional_iterator_tag iterator_category; + + reference operator*() const { return Component; } + pointer operator->() const { return &Component; } + const_iterator &operator++(); // preincrement + const_iterator &operator++(int); // postincrement + const_iterator &operator--(); // predecrement + const_iterator &operator--(int); // postdecrement + bool operator==(const const_iterator &RHS) const; + bool operator!=(const const_iterator &RHS) const; + + /// @brief Difference in bytes between this and RHS. + ptrdiff_t operator-(const const_iterator &RHS) const; +}; + +typedef std::reverse_iterator<const_iterator> reverse_iterator; + +/// @brief Get begin iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized with the first component of \a path. +const_iterator begin(StringRef path); + +/// @brief Get end iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized to the end of \a path. +const_iterator end(StringRef path); + +/// @brief Get reverse begin iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized with the first reverse component of \a path. +inline reverse_iterator rbegin(StringRef path) { + return reverse_iterator(end(path)); +} + +/// @brief Get reverse end iterator over \a path. +/// @param path Input path. +/// @returns Iterator initialized to the reverse end of \a path. +inline reverse_iterator rend(StringRef path) { + return reverse_iterator(begin(path)); +} + +/// @} +/// @name Lexical Modifiers +/// @{ + +/// @brief Remove the last component from \a path unless it is the root dir. +/// +/// directory/filename.cpp => directory/ +/// directory/ => directory +/// / => / +/// +/// @param path A path that is modified to not have a file component. +void remove_filename(SmallVectorImpl<char> &path); + +/// @brief Replace the file extension of \a path with \a extension. +/// +/// ./filename.cpp => ./filename.extension +/// ./filename => ./filename.extension +/// ./ => ./.extension +/// +/// @param path A path that has its extension replaced with \a extension. +/// @param extension The extension to be added. It may be empty. It may also +/// optionally start with a '.', if it does not, one will be +/// prepended. +void replace_extension(SmallVectorImpl<char> &path, const Twine &extension); + +/// @brief Append to path. +/// +/// /foo + bar/f => /foo/bar/f +/// /foo/ + bar/f => /foo/bar/f +/// foo + bar/f => foo/bar/f +/// +/// @param path Set to \a path + \a component. +/// @param component The component to be appended to \a path. +void append(SmallVectorImpl<char> &path, const Twine &a, + const Twine &b = "", + const Twine &c = "", + const Twine &d = ""); + +/// @brief Append to path. +/// +/// /foo + [bar,f] => /foo/bar/f +/// /foo/ + [bar,f] => /foo/bar/f +/// foo + [bar,f] => foo/bar/f +/// +/// @param path Set to \a path + [\a begin, \a end). +/// @param begin Start of components to append. +/// @param end One past the end of components to append. +void append(SmallVectorImpl<char> &path, + const_iterator begin, const_iterator end); + +/// @} +/// @name Transforms (or some other better name) +/// @{ + +/// Convert path to the native form. This is used to give paths to users and +/// operating system calls in the platform's normal way. For example, on Windows +/// all '/' are converted to '\'. +/// +/// @param path A path that is transformed to native format. +/// @param result Holds the result of the transformation. +void native(const Twine &path, SmallVectorImpl<char> &result); + +/// @} +/// @name Lexical Observers +/// @{ + +/// @brief Get root name. +/// +/// //net/hello => //net +/// c:/hello => c: (on Windows, on other platforms nothing) +/// /hello => <empty> +/// +/// @param path Input path. +/// @result The root name of \a path if it has one, otherwise "". +const StringRef root_name(StringRef path); + +/// @brief Get root directory. +/// +/// /goo/hello => / +/// c:/hello => / +/// d/file.txt => <empty> +/// +/// @param path Input path. +/// @result The root directory of \a path if it has one, otherwise +/// "". +const StringRef root_directory(StringRef path); + +/// @brief Get root path. +/// +/// Equivalent to root_name + root_directory. +/// +/// @param path Input path. +/// @result The root path of \a path if it has one, otherwise "". +const StringRef root_path(StringRef path); + +/// @brief Get relative path. +/// +/// C:\hello\world => hello\world +/// foo/bar => foo/bar +/// /foo/bar => foo/bar +/// +/// @param path Input path. +/// @result The path starting after root_path if one exists, otherwise "". +const StringRef relative_path(StringRef path); + +/// @brief Get parent path. +/// +/// / => <empty> +/// /foo => / +/// foo/../bar => foo/.. +/// +/// @param path Input path. +/// @result The parent path of \a path if one exists, otherwise "". +const StringRef parent_path(StringRef path); + +/// @brief Get filename. +/// +/// /foo.txt => foo.txt +/// . => . +/// .. => .. +/// / => / +/// +/// @param path Input path. +/// @result The filename part of \a path. This is defined as the last component +/// of \a path. +const StringRef filename(StringRef path); + +/// @brief Get stem. +/// +/// If filename contains a dot but not solely one or two dots, result is the +/// substring of filename ending at (but not including) the last dot. Otherwise +/// it is filename. +/// +/// /foo/bar.txt => bar +/// /foo/bar => bar +/// /foo/.txt => <empty> +/// /foo/. => . +/// /foo/.. => .. +/// +/// @param path Input path. +/// @result The stem of \a path. +const StringRef stem(StringRef path); + +/// @brief Get extension. +/// +/// If filename contains a dot but not solely one or two dots, result is the +/// substring of filename starting at (and including) the last dot, and ending +/// at the end of \a path. Otherwise "". +/// +/// /foo/bar.txt => .txt +/// /foo/bar => <empty> +/// /foo/.txt => .txt +/// +/// @param path Input path. +/// @result The extension of \a path. +const StringRef extension(StringRef path); + +/// @brief Check whether the given char is a path separator on the host OS. +/// +/// @param value a character +/// @result true if \a value is a path separator character on the host OS +bool is_separator(char value); + +/// @brief Has root name? +/// +/// root_name != "" +/// +/// @param path Input path. +/// @result True if the path has a root name, false otherwise. +bool has_root_name(const Twine &path); + +/// @brief Has root directory? +/// +/// root_directory != "" +/// +/// @param path Input path. +/// @result True if the path has a root directory, false otherwise. +bool has_root_directory(const Twine &path); + +/// @brief Has root path? +/// +/// root_path != "" +/// +/// @param path Input path. +/// @result True if the path has a root path, false otherwise. +bool has_root_path(const Twine &path); + +/// @brief Has relative path? +/// +/// relative_path != "" +/// +/// @param path Input path. +/// @result True if the path has a relative path, false otherwise. +bool has_relative_path(const Twine &path); + +/// @brief Has parent path? +/// +/// parent_path != "" +/// +/// @param path Input path. +/// @result True if the path has a parent path, false otherwise. +bool has_parent_path(const Twine &path); + +/// @brief Has filename? +/// +/// filename != "" +/// +/// @param path Input path. +/// @result True if the path has a filename, false otherwise. +bool has_filename(const Twine &path); + +/// @brief Has stem? +/// +/// stem != "" +/// +/// @param path Input path. +/// @result True if the path has a stem, false otherwise. +bool has_stem(const Twine &path); + +/// @brief Has extension? +/// +/// extension != "" +/// +/// @param path Input path. +/// @result True if the path has a extension, false otherwise. +bool has_extension(const Twine &path); + +/// @brief Is path absolute? +/// +/// @param path Input path. +/// @result True if the path is absolute, false if it is not. +bool is_absolute(const Twine &path); + +/// @brief Is path relative? +/// +/// @param path Input path. +/// @result True if the path is relative, false if it is not. +bool is_relative(const Twine &path); + +} // end namespace path +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h index bee6768..948ae51 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/Support/PatternMatch.h @@ -41,18 +41,62 @@ bool match(Val *V, const Pattern &P) { } template<typename Class> -struct leaf_ty { +struct class_match { template<typename ITy> bool match(ITy *V) { return isa<Class>(V); } }; /// m_Value() - Match an arbitrary value and ignore it. -inline leaf_ty<Value> m_Value() { return leaf_ty<Value>(); } +inline class_match<Value> m_Value() { return class_match<Value>(); } /// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. -inline leaf_ty<ConstantInt> m_ConstantInt() { return leaf_ty<ConstantInt>(); } +inline class_match<ConstantInt> m_ConstantInt() { + return class_match<ConstantInt>(); +} +/// m_Undef() - Match an arbitrary undef constant. +inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); } +inline class_match<Constant> m_Constant() { return class_match<Constant>(); } + +struct match_zero { + template<typename ITy> + bool match(ITy *V) { + if (const Constant *C = dyn_cast<Constant>(V)) + return C->isNullValue(); + 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 apint_match { + const APInt *&Res; + apint_match(const APInt *&R) : Res(R) {} + template<typename ITy> + bool match(ITy *V) { + if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { + Res = &CI->getValue(); + return true; + } + if (ConstantVector *CV = dyn_cast<ConstantVector>(V)) + if (ConstantInt *CI = + dyn_cast_or_null<ConstantInt>(CV->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_ty { +struct constantint_match { template<typename ITy> bool match(ITy *V) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { @@ -68,37 +112,82 @@ struct constantint_ty { } }; -/// m_ConstantInt(int64_t) - Match a ConstantInt with a specific value -/// and ignore it. +/// m_ConstantInt<int64_t> - Match a ConstantInt with a specific value. template<int64_t Val> -inline constantint_ty<Val> m_ConstantInt() { - return constantint_ty<Val>(); +inline constantint_match<Val> m_ConstantInt() { + return constantint_match<Val>(); } -struct zero_ty { +/// cst_pred_ty - This helper class is used to match scalar and vector constants +/// that satisfy a specified predicate. +template<typename Predicate> +struct cst_pred_ty : public Predicate { template<typename ITy> bool match(ITy *V) { - if (const Constant *C = dyn_cast<Constant>(V)) - return C->isNullValue(); + if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) + return this->isValue(CI->getValue()); + if (const ConstantVector *CV = dyn_cast<ConstantVector>(V)) + if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue())) + return this->isValue(CI->getValue()); return false; } }; - -/// m_Zero() - Match an arbitrary zero/null constant. -inline zero_ty m_Zero() { return zero_ty(); } - -struct one_ty { + +/// 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> +struct api_pred_ty : public Predicate { + const APInt *&Res; + api_pred_ty(const APInt *&R) : Res(R) {} template<typename ITy> bool match(ITy *V) { - if (const ConstantInt *C = dyn_cast<ConstantInt>(V)) - return C->isOne(); + if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) + if (this->isValue(CI->getValue())) { + Res = &CI->getValue(); + return true; + } + 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; + } return false; } }; + + +struct is_one { + bool isValue(const APInt &C) { return C == 1; } +}; -/// m_One() - Match a an integer 1. -inline one_ty m_One() { return one_ty(); } +/// 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; } + +struct is_sign_bit { + bool isValue(const APInt &C) { return C.isSignBit(); } +}; + +/// m_SignBit() - Match an integer or vector with only the sign bit(s) set. +inline cst_pred_ty<is_sign_bit> m_SignBit() {return cst_pred_ty<is_sign_bit>();} +inline api_pred_ty<is_sign_bit> m_SignBit(const APInt *&V) { return V; } + +struct is_power2 { + bool isValue(const APInt &C) { return C.isPowerOf2(); } +}; + +/// m_Power2() - Match an integer or vector power of 2. +inline cst_pred_ty<is_power2> m_Power2() { return cst_pred_ty<is_power2>(); } +inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { return V; } template<typename Class> struct bind_ty { @@ -121,6 +210,9 @@ inline bind_ty<Value> m_Value(Value *&V) { return V; } /// m_ConstantInt - Match a ConstantInt, capturing the value if we match. 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; } + /// specificval_ty - Match a specified Value*. struct specificval_ty { const Value *Val; @@ -140,8 +232,7 @@ inline specificval_ty m_Specific(const Value *V) { return V; } // Matchers for specific binary operators. // -template<typename LHS_t, typename RHS_t, - unsigned Opcode, typename ConcreteTy = BinaryOperator> +template<typename LHS_t, typename RHS_t, unsigned Opcode> struct BinaryOp_match { LHS_t L; RHS_t R; @@ -151,9 +242,8 @@ struct BinaryOp_match { template<typename OpTy> bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opcode) { - ConcreteTy *I = cast<ConcreteTy>(V); - return I->getOpcode() == Opcode && L.match(I->getOperand(0)) && - R.match(I->getOperand(1)); + BinaryOperator *I = cast<BinaryOperator>(V); + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && @@ -163,193 +253,156 @@ struct BinaryOp_match { }; template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Add> m_Add(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Add> +m_Add(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FAdd> m_FAdd(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FAdd> +m_FAdd(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Sub> m_Sub(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Sub> +m_Sub(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FSub> +m_FSub(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Mul> +m_Mul(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FMul> m_FMul(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FMul> +m_FMul(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::UDiv> +m_UDiv(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::SDiv> +m_SDiv(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FDiv> +m_FDiv(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::URem> m_URem(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::URem> +m_URem(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::SRem> m_SRem(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::SRem> +m_SRem(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FRem> m_FRem(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::FRem> +m_FRem(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::And> m_And(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::And> +m_And(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::And>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Or> m_Or(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Or> +m_Or(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Xor> m_Xor(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Xor> +m_Xor(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Shl> m_Shl(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::Shl> +m_Shl(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::LShr> m_LShr(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::LShr> +m_LShr(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R); } template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::AShr> m_AShr(const LHS &L, - const RHS &R) { +inline BinaryOp_match<LHS, RHS, Instruction::AShr> +m_AShr(const LHS &L, const RHS &R) { return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R); } //===----------------------------------------------------------------------===// -// Matchers for either AShr or LShr .. for convenience +// Class that matches two different binary ops. // -template<typename LHS_t, typename RHS_t, typename ConcreteTy = BinaryOperator> -struct Shr_match { +template<typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2> +struct BinOp2_match { LHS_t L; RHS_t R; - Shr_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} template<typename OpTy> bool match(OpTy *V) { - if (V->getValueID() == Value::InstructionVal + Instruction::LShr || - V->getValueID() == Value::InstructionVal + Instruction::AShr) { - ConcreteTy *I = cast<ConcreteTy>(V); - return (I->getOpcode() == Instruction::AShr || - I->getOpcode() == Instruction::LShr) && - L.match(I->getOperand(0)) && - R.match(I->getOperand(1)); + if (V->getValueID() == Value::InstructionVal + Opc1 || + V->getValueID() == Value::InstructionVal + Opc2) { + BinaryOperator *I = cast<BinaryOperator>(V); + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) - return (CE->getOpcode() == Instruction::LShr || - CE->getOpcode() == Instruction::AShr) && - L.match(CE->getOperand(0)) && - R.match(CE->getOperand(1)); + return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) && + L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; +/// m_Shr - Matches LShr or AShr. template<typename LHS, typename RHS> -inline Shr_match<LHS, RHS> m_Shr(const LHS &L, const RHS &R) { - return Shr_match<LHS, RHS>(L, R); +inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr> +m_Shr(const LHS &L, const RHS &R) { + return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>(L, R); } -//===----------------------------------------------------------------------===// -// Matchers for binary classes -// - -template<typename LHS_t, typename RHS_t, typename Class, typename OpcType> -struct BinaryOpClass_match { - OpcType *Opcode; - LHS_t L; - RHS_t R; - - BinaryOpClass_match(OpcType &Op, const LHS_t &LHS, - const RHS_t &RHS) - : Opcode(&Op), L(LHS), R(RHS) {} - BinaryOpClass_match(const LHS_t &LHS, const RHS_t &RHS) - : Opcode(0), L(LHS), R(RHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (Class *I = dyn_cast<Class>(V)) - if (L.match(I->getOperand(0)) && - R.match(I->getOperand(1))) { - if (Opcode) - *Opcode = I->getOpcode(); - return true; - } -#if 0 // Doesn't handle constantexprs yet! - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) - return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && - R.match(CE->getOperand(1)); -#endif - return false; - } -}; - +/// m_LogicalShift - Matches LShr or Shl. template<typename LHS, typename RHS> -inline BinaryOpClass_match<LHS, RHS, BinaryOperator, Instruction::BinaryOps> -m_Shift(Instruction::BinaryOps &Op, const LHS &L, const RHS &R) { - return BinaryOpClass_match<LHS, RHS, - BinaryOperator, Instruction::BinaryOps>(Op, L, R); +inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl> +m_LogicalShift(const LHS &L, const RHS &R) { + return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>(L, R); } +/// m_IDiv - Matches UDiv and SDiv. template<typename LHS, typename RHS> -inline BinaryOpClass_match<LHS, RHS, BinaryOperator, Instruction::BinaryOps> -m_Shift(const LHS &L, const RHS &R) { - return BinaryOpClass_match<LHS, RHS, - BinaryOperator, Instruction::BinaryOps>(L, R); +inline BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv> +m_IDiv(const LHS &L, const RHS &R) { + return BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>(L, R); } //===----------------------------------------------------------------------===// @@ -362,15 +415,13 @@ struct CmpClass_match { LHS_t L; RHS_t R; - CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, - const RHS_t &RHS) + CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) : Predicate(Pred), L(LHS), R(RHS) {} template<typename OpTy> bool match(OpTy *V) { if (Class *I = dyn_cast<Class>(V)) - if (L.match(I->getOperand(0)) && - R.match(I->getOperand(1))) { + if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { Predicate = I->getPredicate(); return true; } @@ -425,11 +476,9 @@ m_Select(const Cond &C, const LHS &L, const RHS &R) { /// m_SelectCst - This matches a select of two constants, e.g.: /// m_SelectCst<-1, 0>(m_Value(V)) template<int64_t L, int64_t R, typename Cond> -inline SelectClass_match<Cond, constantint_ty<L>, constantint_ty<R> > +inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R> > m_SelectCst(const Cond &C) { - return SelectClass_match<Cond, constantint_ty<L>, - constantint_ty<R> >(C, m_ConstantInt<L>(), - m_ConstantInt<R>()); + return m_Select(C, m_ConstantInt<L>(), m_ConstantInt<R>()); } @@ -507,20 +556,14 @@ struct not_match { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (CE->getOpcode() == Instruction::Xor) return matchIfNot(CE->getOperand(0), CE->getOperand(1)); - if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) - return L.match(ConstantExpr::getNot(CI)); return false; } private: bool matchIfNot(Value *LHS, Value *RHS) { if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) return CI->isAllOnesValue() && L.match(LHS); - if (ConstantInt *CI = dyn_cast<ConstantInt>(LHS)) - return CI->isAllOnesValue() && L.match(RHS); if (ConstantVector *CV = dyn_cast<ConstantVector>(RHS)) return CV->isAllOnesValue() && L.match(LHS); - if (ConstantVector *CV = dyn_cast<ConstantVector>(LHS)) - return CV->isAllOnesValue() && L.match(RHS); return false; } }; @@ -543,17 +586,17 @@ struct neg_match { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (CE->getOpcode() == Instruction::Sub) return matchIfNeg(CE->getOperand(0), CE->getOperand(1)); - if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) - return L.match(ConstantExpr::getNeg(CI)); return false; } private: bool matchIfNeg(Value *LHS, Value *RHS) { - return LHS == ConstantFP::getZeroValueForNegation(LHS->getType()) && - L.match(RHS); + if (ConstantInt *C = dyn_cast<ConstantInt>(LHS)) + return C->isZero() && L.match(RHS); + return false; } }; +/// m_Neg - Match an integer negate. template<typename LHS> inline neg_match<LHS> m_Neg(const LHS &L) { return L; } @@ -572,23 +615,23 @@ struct fneg_match { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) if (CE->getOpcode() == Instruction::FSub) return matchIfFNeg(CE->getOperand(0), CE->getOperand(1)); - if (ConstantFP *CF = dyn_cast<ConstantFP>(V)) - return L.match(ConstantExpr::getFNeg(CF)); return false; } private: bool matchIfFNeg(Value *LHS, Value *RHS) { - return LHS == ConstantFP::getZeroValueForNegation(LHS->getType()) && - L.match(RHS); + if (ConstantFP *C = dyn_cast<ConstantFP>(LHS)) + return C->isNegativeZeroValue() && L.match(RHS); + return false; } }; +/// m_FNeg - Match a floating point negate. template<typename LHS> inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; } //===----------------------------------------------------------------------===// -// Matchers for control flow +// Matchers for control flow. // template<typename Cond_t> @@ -602,12 +645,10 @@ struct brc_match { template<typename OpTy> bool match(OpTy *V) { if (BranchInst *BI = dyn_cast<BranchInst>(V)) - if (BI->isConditional()) { - if (Cond.match(BI->getCondition())) { - T = BI->getSuccessor(0); - F = BI->getSuccessor(1); - return true; - } + if (BI->isConditional() && Cond.match(BI->getCondition())) { + T = BI->getSuccessor(0); + F = BI->getSuccessor(1); + return true; } return false; } diff --git a/include/llvm/Support/PointerLikeTypeTraits.h b/include/llvm/Support/PointerLikeTypeTraits.h index b851404..8370821 100644 --- a/include/llvm/Support/PointerLikeTypeTraits.h +++ b/include/llvm/Support/PointerLikeTypeTraits.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_POINTERLIKETYPETRAITS_H #define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h new file mode 100644 index 0000000..3379922 --- /dev/null +++ b/include/llvm/Support/Process.h @@ -0,0 +1,146 @@ +//===- llvm/Support/Process.h ------------------------------------*- 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::Process class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PROCESS_H +#define LLVM_SYSTEM_PROCESS_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 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); + + /// Resets the terminals colors, or returns an escape sequence to do so. + static const char *ResetColor(); + /// @} + }; +} +} + +#endif diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h new file mode 100644 index 0000000..78a495e --- /dev/null +++ b/include/llvm/Support/Program.h @@ -0,0 +1,157 @@ +//===- llvm/Support/Program.h ------------------------------------*- 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::Program class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PROGRAM_H +#define LLVM_SYSTEM_PROGRAM_H + +#include "llvm/Support/Path.h" + +namespace llvm { +namespace sys { + + // TODO: Add operations to communicate with the process, redirect its I/O, + // etc. + + /// This class provides an abstraction for programs that are executable by the + /// operating system. It provides a platform generic way to find executable + /// programs from the path and to execute them in various ways. The sys::Path + /// class is used to specify the location of the Program. + /// @since 1.4 + /// @brief An abstraction for finding and executing programs. + class Program { + /// Opaque handle for target specific data. + void *Data_; + + // Noncopyable. + Program(const Program& other); + Program& operator=(const Program& other); + + /// @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 + /// invoking program. If Path::executable() does not return true when this + /// function is called then a std::string is thrown. + /// @returns false in case of error, true otherwise. + /// @see FindProgramByName + /// @brief Executes the program with the given set of \p args. + bool Execute + ( const Path& path, ///< sys::Path object providing the path of the + ///< program to be executed. It is presumed this is the result of + ///< the FindProgramByName method. + const char** args, ///< A vector of strings that are passed to the + ///< program. The first element should be the name of the program. + ///< The list *must* be terminated by a null char* entry. + const char ** env = 0, ///< An optional vector of strings to use for + ///< the program's environment. If not provided, the current program's + ///< environment will be used. + const sys::Path** redirects = 0, ///< An optional array of pointers to + ///< Paths. If the array is null, no redirection is done. The array + ///< should have a size of at least three. If the pointer in the array + ///< are not null, then the inferior process's stdin(0), stdout(1), + ///< and stderr(2) will be redirected to the corresponding Paths. + ///< When an empty Path is passed in, the corresponding file + ///< descriptor will be disconnected (ie, /dev/null'd) in a portable + ///< way. + unsigned memoryLimit = 0, ///< If non-zero, this specifies max. amount + ///< of memory can be allocated by process. If memory usage will be + ///< higher limit, the child is killed and this call returns. If zero + ///< - no memory limit. + 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 invoking the + ///< program. + ); + + /// This function waits for the program to exit. This function will block + /// the current program until the invoked program exits. + /// @returns an integer result code indicating the status of the program. + /// A zero or positive value indicates the result code of the program. A + /// negative value is the signal number on which it terminated. + /// @see Execute + /// @brief Waits for the program to exit. + int Wait + ( const Path& path, ///< The path to the child process executable. + unsigned secondsToWait, ///< If non-zero, this specifies the amount + ///< of time to wait for the child process to exit. If the time + ///< expires, the child is killed and this call returns. If zero, + ///< this function will wait until the child finishes or forever if + ///< it doesn't. + std::string* ErrMsg ///< 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 waiting. + ); + + /// This function terminates the program. + /// @returns true if an error occured. + /// @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. + ); + + /// This static constructor (factory) will attempt to locate a program in + /// the operating system's file system using some pre-determined set of + /// locations to search (e.g. the PATH on Unix). Paths with slashes are + /// returned unmodified. + /// @returns A Path object initialized to the path of the program or a + /// Path object that is empty (invalid) if the program could not be found. + /// @brief Construct a Program by finding it by name. + static Path FindProgramByName(const std::string& name); + + // These methods change the specified standard stream (stdin, + // stdout, or stderr) to binary mode. They return true if an error + // occurred + static bool ChangeStdinToBinary(); + static bool ChangeStdoutToBinary(); + static bool ChangeStderrToBinary(); + + /// A convenience function equivalent to Program prg; prg.Execute(..); + /// prg.Wait(..); + /// @see Execute, Wait + static int ExecuteAndWait(const Path& path, + const char** args, + const char ** env = 0, + const sys::Path** redirects = 0, + unsigned secondsToWait = 0, + unsigned memoryLimit = 0, + std::string* ErrMsg = 0); + + /// A convenience function equivalent to Program prg; prg.Execute(..); + /// @see Execute + static void ExecuteNoWait(const Path& path, + const char** args, + const char ** env = 0, + const sys::Path** redirects = 0, + unsigned memoryLimit = 0, + std::string* ErrMsg = 0); + + /// @} + + }; +} +} + +#endif diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h new file mode 100644 index 0000000..0d4cb81 --- /dev/null +++ b/include/llvm/Support/RWMutex.h @@ -0,0 +1,173 @@ +//===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- 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::RWMutex class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_RWMUTEX_H +#define LLVM_SYSTEM_RWMUTEX_H + +#include "llvm/Support/Threading.h" +#include <cassert> + +namespace llvm +{ + namespace sys + { + /// @brief Platform agnostic RWMutex class. + class RWMutexImpl + { + /// @name Constructors + /// @{ + public: + + /// Initializes the lock but doesn't acquire it. + /// @brief Default Constructor. + explicit RWMutexImpl(); + + /// Releases and removes the lock + /// @brief Destructor + ~RWMutexImpl(); + + /// @} + /// @name Methods + /// @{ + public: + + /// Attempts to unconditionally acquire the lock in reader mode. If the + /// lock is held by a writer, this method will wait until it can acquire + /// the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock in reader mode. + bool reader_acquire(); + + /// Attempts to release the lock in reader mode. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock in reader mode. + bool reader_release(); + + /// Attempts to unconditionally acquire the lock in reader mode. If the + /// lock is held by any readers, this method will wait until it can + /// acquire the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock in writer mode. + bool writer_acquire(); + + /// Attempts to release the lock in writer mode. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock in write mode. + bool writer_release(); + + //@} + /// @name Platform Dependent Data + /// @{ + private: + void* data_; ///< We don't know what the data will be + + /// @} + /// @name Do Not Implement + /// @{ + private: + RWMutexImpl(const RWMutexImpl & original); + void operator=(const RWMutexImpl &); + /// @} + }; + + /// SmartMutex - An R/W mutex with a compile time constant parameter that + /// indicates whether this mutex should become a no-op when we're not + /// running in multithreaded mode. + template<bool mt_only> + class SmartRWMutex : public RWMutexImpl { + unsigned readers, writers; + public: + explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { } + + bool reader_acquire() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::reader_acquire(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + ++readers; + return true; + } + + bool reader_release() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::reader_release(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + assert(readers > 0 && "Reader lock not acquired before release!"); + --readers; + return true; + } + + bool writer_acquire() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::writer_acquire(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + assert(writers == 0 && "Writer lock already acquired!"); + ++writers; + return true; + } + + bool writer_release() { + if (!mt_only || llvm_is_multithreaded()) + return RWMutexImpl::writer_release(); + + // Single-threaded debugging code. This would be racy in multithreaded + // mode, but provides not sanity checks in single threaded mode. + assert(writers == 1 && "Writer lock not acquired before release!"); + --writers; + return true; + } + + private: + SmartRWMutex(const SmartRWMutex<mt_only> & original); + void operator=(const SmartRWMutex<mt_only> &); + }; + typedef SmartRWMutex<false> RWMutex; + + /// ScopedReader - RAII acquisition of a reader lock + template<bool mt_only> + struct SmartScopedReader { + SmartRWMutex<mt_only>& mutex; + + explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) { + mutex.reader_acquire(); + } + + ~SmartScopedReader() { + mutex.reader_release(); + } + }; + typedef SmartScopedReader<false> ScopedReader; + + /// ScopedWriter - RAII acquisition of a writer lock + template<bool mt_only> + struct SmartScopedWriter { + SmartRWMutex<mt_only>& mutex; + + explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) { + mutex.writer_acquire(); + } + + ~SmartScopedWriter() { + mutex.writer_release(); + } + }; + typedef SmartScopedWriter<false> ScopedWriter; + } +} + +#endif diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h new file mode 100644 index 0000000..9a84df6 --- /dev/null +++ b/include/llvm/Support/Signals.h @@ -0,0 +1,59 @@ +//===- llvm/Support/Signals.h - Signal Handling support ----------*- 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 some helpful functions for dealing with the possibility of +// unix signals occuring while your program is running. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SIGNALS_H +#define LLVM_SYSTEM_SIGNALS_H + +#include "llvm/Support/Path.h" + +namespace llvm { +namespace sys { + + /// This function runs all the registered interrupt handlers, including the + /// removal of files registered by RemoveFileOnSignal. + void RunInterruptHandlers(); + + /// This function registers signal handlers to ensure that if a signal gets + /// delivered that the named file is removed. + /// @brief Remove a file if a fatal signal occurs. + bool RemoveFileOnSignal(const Path &Filename, std::string* ErrMsg = 0); + + /// This function removes a file from the list of files to be removed on + /// signal delivery. + void DontRemoveFileOnSignal(const Path &Filename); + + /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the + /// process, print a stack trace and then exit. + /// @brief Print a stack trace if a fatal signal occurs. + void PrintStackTraceOnErrorSignal(); + + /// AddSignalHandler - Add a function to be called when an abort/kill signal + /// is delivered to the process. The handler can have a cookie passed to it + /// to identify what instance of the handler it is. + void AddSignalHandler(void (*FnPtr)(void *), void *Cookie); + + /// This function registers a function to be called when the user "interrupts" + /// the program (typically by pressing ctrl-c). When the user interrupts the + /// program, the specified interrupt function is called instead of the program + /// being killed, and the interrupt function automatically disabled. Note + /// that interrupt functions are not allowed to call any non-reentrant + /// functions. An null interrupt function pointer disables the current + /// installed function. Note also that the handler may be executed on a + /// different thread on some platforms. + /// @brief Register a function to be called when ctrl-c is pressed. + void SetInterruptFunction(void (*IF)()); +} // End sys namespace +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/Solaris.h b/include/llvm/Support/Solaris.h new file mode 100644 index 0000000..57eee2c --- /dev/null +++ b/include/llvm/Support/Solaris.h @@ -0,0 +1,40 @@ +/*===- llvm/Support/Solaris.h ------------------------------------*- C++ -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===* + * + * This file contains portability fixes for Solaris hosts. + * + *===----------------------------------------------------------------------===*/ + +#ifndef LLVM_SYSTEM_SOLARIS_H +#define LLVM_SYSTEM_SOLARIS_H + +#include <sys/types.h> +#include <sys/regset.h> + +#undef CS +#undef DS +#undef ES +#undef FS +#undef GS +#undef SS +#undef EAX +#undef ECX +#undef EDX +#undef EBX +#undef ESP +#undef EBP +#undef ESI +#undef EDI +#undef EIP +#undef UESP +#undef EFL +#undef ERR +#undef TRAPNO + +#endif diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 270ab2b..a41a633 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -26,6 +26,7 @@ namespace llvm { class MemoryBuffer; class SourceMgr; class SMDiagnostic; + class Twine; class raw_ostream; /// SourceMgr - This owns the files read by a parser, handles include stacks, @@ -35,8 +36,7 @@ public: /// DiagHandlerTy - Clients that want to handle their own diagnostics in a /// custom way can register a function pointer+context as a diagnostic /// handler. It gets called each time PrintMessage is invoked. - typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context, - unsigned LocCookie); + typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context); private: struct SrcBuffer { /// Buffer - The memory buffer for the file. @@ -60,7 +60,6 @@ private: DiagHandlerTy DiagHandler; void *DiagContext; - unsigned DiagLocCookie; SourceMgr(const SourceMgr&); // DO NOT IMPLEMENT void operator=(const SourceMgr&); // DO NOT IMPLEMENT @@ -73,12 +72,10 @@ public: } /// setDiagHandler - Specify a diagnostic handler to be invoked every time - /// PrintMessage is called. Ctx and Cookie are passed into the handler when - /// it is invoked. - void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0, unsigned Cookie = 0) { + /// PrintMessage is called. Ctx is passed into the handler when it is invoked. + void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0) { DiagHandler = DH; DiagContext = Ctx; - DiagLocCookie = Cookie; } const SrcBuffer &getBufferInfo(unsigned i) const { @@ -125,7 +122,7 @@ public: /// @param Type - If non-null, the kind of message (e.g., "error") which is /// prefixed to the message. /// @param ShowLine - Should the diagnostic show the source line. - void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type, + void PrintMessage(SMLoc Loc, const Twine &Msg, const char *Type, bool ShowLine = true) const; @@ -136,7 +133,7 @@ public: /// prefixed to the message. /// @param ShowLine - Should the diagnostic show the source line. SMDiagnostic GetMessage(SMLoc Loc, - const std::string &Msg, const char *Type, + const Twine &Msg, const char *Type, bool ShowLine = true) const; diff --git a/include/llvm/Support/StableBasicBlockNumbering.h b/include/llvm/Support/StableBasicBlockNumbering.h deleted file mode 100644 index 5e0f87e..0000000 --- a/include/llvm/Support/StableBasicBlockNumbering.h +++ /dev/null @@ -1,59 +0,0 @@ -//===- StableBasicBlockNumbering.h - Provide BB identifiers -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class provides a *stable* numbering of basic blocks that does not depend -// on their address in memory (which is nondeterministic). When requested, this -// class simply provides a unique ID for each basic block in the function -// specified and the inverse mapping. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_STABLEBASICBLOCKNUMBERING_H -#define LLVM_SUPPORT_STABLEBASICBLOCKNUMBERING_H - -#include "llvm/Function.h" -#include "llvm/ADT/UniqueVector.h" - -namespace llvm { - class StableBasicBlockNumbering { - // BBNumbering - Holds the numbering. - UniqueVector<BasicBlock*> BBNumbering; - public: - StableBasicBlockNumbering(Function *F = 0) { - if (F) compute(*F); - } - - /// compute - If we have not computed a numbering for the function yet, do - /// so. - void compute(Function &F) { - if (BBNumbering.empty()) { - for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) - BBNumbering.insert(I); - } - } - - /// getNumber - Return the ID number for the specified BasicBlock. - /// - unsigned getNumber(BasicBlock *BB) const { - unsigned Idx = BBNumbering.idFor(BB); - assert(Idx && "Invalid basic block or numbering not computed!"); - return Idx-1; - } - - /// getBlock - Return the BasicBlock corresponding to a particular ID. - /// - BasicBlock *getBlock(unsigned N) const { - assert(N < BBNumbering.size() && - "Block ID out of range or numbering not computed!"); - return BBNumbering[N+1]; - } - }; -} - -#endif diff --git a/include/llvm/Support/StandardPasses.h b/include/llvm/Support/StandardPasses.h index bb3bddd..d774faf 100644 --- a/include/llvm/Support/StandardPasses.h +++ b/include/llvm/Support/StandardPasses.h @@ -20,20 +20,35 @@ #define LLVM_SUPPORT_STANDARDPASSES_H #include "llvm/PassManager.h" -#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/IPO.h" namespace llvm { + + static inline void createStandardAliasAnalysisPasses(PassManagerBase *PM) { + // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that + // BasicAliasAnalysis wins if they disagree. This is intended to help + // support "obvious" type-punning idioms. + PM->add(createTypeBasedAliasAnalysisPass()); + PM->add(createBasicAliasAnalysisPass()); + } + /// createStandardFunctionPasses - Add the standard list of function passes to /// the provided pass manager. /// /// \arg OptimizationLevel - The optimization level, corresponding to -O0, /// -O1, etc. static inline void createStandardFunctionPasses(PassManagerBase *PM, - unsigned OptimizationLevel); + unsigned OptimizationLevel) { + if (OptimizationLevel > 0) { + createStandardAliasAnalysisPasses(PM); + PM->add(createCFGSimplificationPass()); + PM->add(createScalarReplAggregatesPass()); + PM->add(createEarlyCSEPass()); + } + } /// createStandardModulePasses - Add the standard list of module passes to the /// provided pass manager. @@ -54,43 +69,9 @@ namespace llvm { bool UnrollLoops, bool SimplifyLibCalls, bool HaveExceptions, - Pass *InliningPass); - - /// createStandardLTOPasses - Add the standard list of module passes suitable - /// for link time optimization. - /// - /// Internalize - Run the internalize pass. - /// RunInliner - Use a function inlining pass. - /// VerifyEach - Run the verifier after each pass. - static inline void createStandardLTOPasses(PassManagerBase *PM, - bool Internalize, - bool RunInliner, - bool VerifyEach); - - // Implementations - - static inline void createStandardFunctionPasses(PassManagerBase *PM, - unsigned OptimizationLevel) { - if (OptimizationLevel > 0) { - PM->add(createCFGSimplificationPass()); - if (OptimizationLevel == 1) - PM->add(createPromoteMemoryToRegisterPass()); - else - PM->add(createScalarReplAggregatesPass()); - PM->add(createInstructionCombiningPass()); - } - } - - /// createStandardModulePasses - Add the standard module passes. This is - /// expected to be run after the standard function passes. - static inline void createStandardModulePasses(PassManagerBase *PM, - unsigned OptimizationLevel, - bool OptimizeSize, - bool UnitAtATime, - bool UnrollLoops, - bool SimplifyLibCalls, - bool HaveExceptions, Pass *InliningPass) { + createStandardAliasAnalysisPasses(PM); + if (OptimizationLevel == 0) { if (InliningPass) PM->add(InliningPass); @@ -108,7 +89,7 @@ namespace llvm { // Start of CallGraph SCC passes. if (UnitAtATime && HaveExceptions) - PM->add(createPruneEHPass()); // Remove dead EH info + PM->add(createPruneEHPass()); // Remove dead EH info if (InliningPass) PM->add(InliningPass); if (UnitAtATime) @@ -117,11 +98,13 @@ namespace llvm { PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args // Start of function pass. - PM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas + // Break up aggregate allocas, using SSAUpdater. + PM->add(createScalarReplAggregatesPass(-1, false)); + PM->add(createEarlyCSEPass()); // Catch trivial redundancies if (SimplifyLibCalls) PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations - PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. PM->add(createJumpThreadingPass()); // Thread jumps. + PM->add(createCorrelatedValuePropagationPass()); // Propagate conditionals PM->add(createCFGSimplificationPass()); // Merge & remove BBs PM->add(createInstructionCombiningPass()); // Combine silly seq's @@ -133,6 +116,7 @@ namespace llvm { PM->add(createLoopUnswitchPass(OptimizeSize || OptimizationLevel < 3)); PM->add(createInstructionCombiningPass()); PM->add(createIndVarSimplifyPass()); // Canonicalize indvars + PM->add(createLoopIdiomPass()); // Recognize idioms like memset. PM->add(createLoopDeletionPass()); // Delete dead loops if (UnrollLoops) PM->add(createLoopUnrollPass()); // Unroll small loops @@ -172,10 +156,19 @@ namespace llvm { PM->add(createVerifierPass()); } + /// createStandardLTOPasses - Add the standard list of module passes suitable + /// for link time optimization. + /// + /// Internalize - Run the internalize pass. + /// RunInliner - Use a function inlining pass. + /// VerifyEach - Run the verifier after each pass. static inline void createStandardLTOPasses(PassManagerBase *PM, bool Internalize, bool RunInliner, bool VerifyEach) { + // Provide AliasAnalysis services for optimizations. + createStandardAliasAnalysisPasses(PM); + // Now that composite has been compiled, scan through the module, looking // for a main function. If main is defined, mark all other functions // internal. diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h new file mode 100644 index 0000000..6c0592c --- /dev/null +++ b/include/llvm/Support/SwapByteOrder.h @@ -0,0 +1,101 @@ +//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- 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 generic and optimized functions to swap the byte order of +// an integral type. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SWAP_BYTE_ORDER_H +#define LLVM_SYSTEM_SWAP_BYTE_ORDER_H + +#include "llvm/Support/DataTypes.h" +#include <cstddef> +#include <limits> + +namespace llvm { +namespace sys { + +/// SwapByteOrder_16 - This function returns a byte-swapped representation of +/// the 16-bit argument. +inline uint16_t SwapByteOrder_16(uint16_t value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return _byteswap_ushort(value); +#else + uint16_t Hi = value << 8; + uint16_t Lo = value >> 8; + return Hi | Lo; +#endif +} + +/// SwapByteOrder_32 - This function returns a byte-swapped representation of +/// the 32-bit argument. +inline uint32_t SwapByteOrder_32(uint32_t value) { +#if defined(__llvm__) || \ +(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) + return __builtin_bswap32(value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_ulong(value); +#else + uint32_t Byte0 = value & 0x000000FF; + uint32_t Byte1 = value & 0x0000FF00; + uint32_t Byte2 = value & 0x00FF0000; + uint32_t Byte3 = value & 0xFF000000; + return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); +#endif +} + +/// SwapByteOrder_64 - This function returns a byte-swapped representation of +/// the 64-bit argument. +inline uint64_t SwapByteOrder_64(uint64_t value) { +#if defined(__llvm__) || \ +(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) && !defined(__ICC) + return __builtin_bswap64(value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_uint64(value); +#else + uint64_t Hi = SwapByteOrder_32(uint32_t(value)); + uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32)); + return (Hi << 32) | Lo; +#endif +} + +inline unsigned char SwapByteOrder(unsigned char C) { return C; } +inline signed char SwapByteOrder(signed char C) { return C; } +inline char SwapByteOrder(char C) { return C; } + +inline unsigned short SwapByteOrder(unsigned short C) { return SwapByteOrder_16(C); } +inline signed short SwapByteOrder( signed short C) { return SwapByteOrder_16(C); } + +inline unsigned int SwapByteOrder(unsigned int C) { return SwapByteOrder_32(C); } +inline signed int SwapByteOrder( signed int C) { return SwapByteOrder_32(C); } + +#if __LONG_MAX__ == __INT_MAX__ +inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_32(C); } +inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_32(C); } +#elif __LONG_MAX__ == __LONG_LONG_MAX__ +inline unsigned long SwapByteOrder(unsigned long C) { return SwapByteOrder_64(C); } +inline signed long SwapByteOrder( signed long C) { return SwapByteOrder_64(C); } +#else +#error "Unknown long size!" +#endif + +inline unsigned long long SwapByteOrder(unsigned long long C) { + return SwapByteOrder_64(C); +} +inline signed long long SwapByteOrder(signed long long C) { + return SwapByteOrder_64(C); +} + +} // end namespace sys +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/SystemUtils.h b/include/llvm/Support/SystemUtils.h index 3c182c1..399aee5 100644 --- a/include/llvm/Support/SystemUtils.h +++ b/include/llvm/Support/SystemUtils.h @@ -30,13 +30,14 @@ bool CheckBitcodeOutputToConsole( bool print_warning = true ///< Control whether warnings are printed ); -/// FindExecutable - Find a named executable, giving the argv[0] of program -/// being executed. This allows us to find another LLVM tool if it is built in -/// the same directory. If the executable cannot be found, return an -/// empty string. +/// PrependMainExecutablePath - Prepend the path to the program being executed +/// to \p ExeName, given the value of argv[0] and the address of main() +/// itself. This allows us to find another LLVM tool if it is built in the same +/// directory. An empty string is returned on error; note that this function +/// just mainpulates the path and doesn't check for executability. /// @brief Find a named executable. -sys::Path FindExecutable(const std::string &ExeName, - const char *Argv0, void *MainAddr); +sys::Path PrependMainExecutablePath(const std::string &ExeName, + const char *Argv0, void *MainAddr); } // End llvm namespace diff --git a/include/llvm/Support/TargetFolder.h b/include/llvm/Support/TargetFolder.h index d34f35f..20ca557 100644 --- a/include/llvm/Support/TargetFolder.h +++ b/include/llvm/Support/TargetFolder.h @@ -46,50 +46,32 @@ public: // Binary Operators //===--------------------------------------------------------------------===// - Constant *CreateAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getAdd(LHS, RHS)); - } - Constant *CreateNSWAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNSWAdd(LHS, RHS)); - } - Constant *CreateNUWAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNUWAdd(LHS, RHS)); + Constant *CreateAdd(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW)); } Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFAdd(LHS, RHS)); } - Constant *CreateSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getSub(LHS, RHS)); - } - Constant *CreateNSWSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNSWSub(LHS, RHS)); - } - Constant *CreateNUWSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNUWSub(LHS, RHS)); + Constant *CreateSub(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW)); } Constant *CreateFSub(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFSub(LHS, RHS)); } - Constant *CreateMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getMul(LHS, RHS)); - } - Constant *CreateNSWMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNSWMul(LHS, RHS)); - } - Constant *CreateNUWMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getNUWMul(LHS, RHS)); + Constant *CreateMul(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW)); } Constant *CreateFMul(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFMul(LHS, RHS)); } - Constant *CreateUDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getUDiv(LHS, RHS)); - } - Constant *CreateSDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getSDiv(LHS, RHS)); + Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact)); } - Constant *CreateExactSDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getExactSDiv(LHS, RHS)); + Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact)); } Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFDiv(LHS, RHS)); @@ -103,14 +85,15 @@ public: Constant *CreateFRem(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getFRem(LHS, RHS)); } - Constant *CreateShl(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getShl(LHS, RHS)); + Constant *CreateShl(Constant *LHS, Constant *RHS, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW)); } - Constant *CreateLShr(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getLShr(LHS, RHS)); + Constant *CreateLShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getLShr(LHS, RHS, isExact)); } - Constant *CreateAShr(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getAShr(LHS, RHS)); + Constant *CreateAShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ + return Fold(ConstantExpr::getAShr(LHS, RHS, isExact)); } Constant *CreateAnd(Constant *LHS, Constant *RHS) const { return Fold(ConstantExpr::getAnd(LHS, RHS)); @@ -131,14 +114,9 @@ public: // Unary Operators //===--------------------------------------------------------------------===// - Constant *CreateNeg(Constant *C) const { - return Fold(ConstantExpr::getNeg(C)); - } - Constant *CreateNSWNeg(Constant *C) const { - return Fold(ConstantExpr::getNSWNeg(C)); - } - Constant *CreateNUWNeg(Constant *C) const { - return Fold(ConstantExpr::getNUWNeg(C)); + Constant *CreateNeg(Constant *C, + bool HasNUW = false, bool HasNSW = false) const { + return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW)); } Constant *CreateFNeg(Constant *C) const { return Fold(ConstantExpr::getFNeg(C)); diff --git a/include/llvm/Support/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h new file mode 100644 index 0000000..15350a7 --- /dev/null +++ b/include/llvm/Support/ThreadLocal.h @@ -0,0 +1,54 @@ +//===- llvm/Support/ThreadLocal.h - Thread Local Data ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::ThreadLocal class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_THREAD_LOCAL_H +#define LLVM_SYSTEM_THREAD_LOCAL_H + +#include "llvm/Support/Threading.h" +#include <cassert> + +namespace llvm { + namespace sys { + // ThreadLocalImpl - Common base class of all ThreadLocal instantiations. + // YOU SHOULD NEVER USE THIS DIRECTLY. + class ThreadLocalImpl { + void* data; + public: + ThreadLocalImpl(); + virtual ~ThreadLocalImpl(); + void setInstance(const void* d); + const void* getInstance(); + void removeInstance(); + }; + + /// ThreadLocal - A class used to abstract thread-local storage. It holds, + /// for each thread, a pointer a single object of type T. + template<class T> + class ThreadLocal : public ThreadLocalImpl { + public: + ThreadLocal() : ThreadLocalImpl() { } + + /// get - Fetches a pointer to the object associated with the current + /// thread. If no object has yet been associated, it returns NULL; + T* get() { return static_cast<T*>(getInstance()); } + + // set - Associates a pointer to an object with the current thread. + void set(T* d) { setInstance(d); } + + // erase - Removes the pointer associated with the current thread. + void erase() { removeInstance(); } + }; + } +} + +#endif diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h new file mode 100644 index 0000000..c0e842c --- /dev/null +++ b/include/llvm/Support/Threading.h @@ -0,0 +1,59 @@ +//===-- llvm/Support/Threading.h - Control multithreading mode --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// TThis file defines llvm_start_multithreaded() and friends. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_THREADING_H +#define LLVM_SYSTEM_THREADING_H + +namespace llvm { + /// llvm_start_multithreaded - Allocate and initialize structures needed to + /// make LLVM safe for multithreading. The return value indicates whether + /// multithreaded initialization succeeded. LLVM will still be operational + /// on "failed" return, and will still be safe for hosting threading + /// applications in the JIT, but will not be safe for concurrent calls to the + /// LLVM APIs. + /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. + bool llvm_start_multithreaded(); + + /// llvm_stop_multithreaded - Deallocate structures necessary to make LLVM + /// safe for multithreading. + /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS. + void llvm_stop_multithreaded(); + + /// llvm_is_multithreaded - Check whether LLVM is executing in thread-safe + /// mode or not. + bool llvm_is_multithreaded(); + + /// acquire_global_lock - Acquire the global lock. This is a no-op if called + /// before llvm_start_multithreaded(). + void llvm_acquire_global_lock(); + + /// release_global_lock - Release the global lock. This is a no-op if called + /// before llvm_start_multithreaded(). + void llvm_release_global_lock(); + + /// llvm_execute_on_thread - Execute the given \arg UserFn on a separate + /// thread, passing it the provided \arg UserData. + /// + /// This function does not guarantee that the code will actually be executed + /// on a separate thread or honoring the requested stack size, but tries to do + /// so where system support is available. + /// + /// \param UserFn - The callback to execute. + /// \param UserData - An argument to pass to the callback function. + /// \param RequestedStackSize - If non-zero, a requested size (in bytes) for + /// the thread stack. + void llvm_execute_on_thread(void (*UserFn)(void*), void *UserData, + unsigned RequestedStackSize = 0); +} + +#endif diff --git a/include/llvm/Support/TimeValue.h b/include/llvm/Support/TimeValue.h new file mode 100644 index 0000000..e122711 --- /dev/null +++ b/include/llvm/Support/TimeValue.h @@ -0,0 +1,382 @@ +//===-- TimeValue.h - Declare OS TimeValue Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file declares the operating system TimeValue concept. +// +//===----------------------------------------------------------------------===// + +#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 + /// range of TimeValue spans many hundreds of billions of years both past and + /// present. The precision of TimeValue is to the nanosecond. However, the + /// actual precision of its values will be determined by the resolution of + /// the system clock. The TimeValue class is used in conjunction with several + /// other lib/System interfaces to specify the time at which a call should + /// timeout, etc. + /// @since 1.4 + /// @brief Provides an abstraction for a fixed point in time. + class TimeValue { + + /// @name Constants + /// @{ + public: + + /// A constant TimeValue representing the smallest time + /// value permissable by the class. MinTime is some point + /// in the distant past, about 300 billion years BCE. + /// @brief The smallest possible time value. + static const TimeValue MinTime; + + /// A constant TimeValue representing the largest time + /// value permissable by the class. MaxTime is some point + /// in the distant future, about 300 billion years AD. + /// @brief The largest possible time value. + static const TimeValue MaxTime; + + /// A constant TimeValue representing the base time, + /// or zero time of 00:00:00 (midnight) January 1st, 2000. + /// @brief 00:00:00 Jan 1, 2000 UTC. + static const TimeValue ZeroTime; + + /// A constant TimeValue for the Posix base time which is + /// 00:00:00 (midnight) January 1st, 1970. + /// @brief 00:00:00 Jan 1, 1970 UTC. + static const TimeValue PosixZeroTime; + + /// A constant TimeValue for the Win32 base time which is + /// 00:00:00 (midnight) January 1st, 1601. + /// @brief 00:00:00 Jan 1, 1601 UTC. + static const TimeValue Win32ZeroTime; + + /// @} + /// @name Types + /// @{ + public: + typedef int64_t SecondsType; ///< Type used for representing seconds. + typedef int32_t NanoSecondsType;///< Type used for representing nanoseconds. + + enum TimeConversions { + NANOSECONDS_PER_SECOND = 1000000000, ///< One Billion + MICROSECONDS_PER_SECOND = 1000000, ///< One Million + MILLISECONDS_PER_SECOND = 1000, ///< One Thousand + NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand + NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million + NANOSECONDS_PER_POSIX_TICK = 100, ///< Posix tick is 100 Hz (10ms) + NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 100 Hz (10ms) + }; + + /// @} + /// @name Constructors + /// @{ + public: + /// Caller provides the exact value in seconds and nanoseconds. The + /// \p nanos argument defaults to zero for convenience. + /// @brief Explicit constructor + explicit TimeValue (SecondsType seconds, NanoSecondsType nanos = 0) + : seconds_( seconds ), nanos_( nanos ) { this->normalize(); } + + /// Caller provides the exact value as a double in seconds with the + /// fractional part representing nanoseconds. + /// @brief Double Constructor. + explicit TimeValue( double new_time ) + : seconds_( 0 ) , nanos_ ( 0 ) { + SecondsType integer_part = static_cast<SecondsType>( new_time ); + seconds_ = integer_part; + nanos_ = static_cast<NanoSecondsType>( (new_time - + static_cast<double>(integer_part)) * NANOSECONDS_PER_SECOND ); + this->normalize(); + } + + /// This is a static constructor that returns a TimeValue that represents + /// the current time. + /// @brief Creates a TimeValue with the current time (UTC). + static TimeValue now(); + + /// @} + /// @name Operators + /// @{ + public: + /// Add \p that to \p this. + /// @returns this + /// @brief Incrementing assignment operator. + TimeValue& operator += (const TimeValue& that ) { + this->seconds_ += that.seconds_ ; + this->nanos_ += that.nanos_ ; + this->normalize(); + return *this; + } + + /// Subtract \p that from \p this. + /// @returns this + /// @brief Decrementing assignment operator. + TimeValue& operator -= (const TimeValue &that ) { + this->seconds_ -= that.seconds_ ; + this->nanos_ -= that.nanos_ ; + this->normalize(); + return *this; + } + + /// Determine if \p this is less than \p that. + /// @returns True iff *this < that. + /// @brief True if this < that. + int operator < (const TimeValue &that) const { return that > *this; } + + /// Determine if \p this is greather than \p that. + /// @returns True iff *this > that. + /// @brief True if this > that. + int operator > (const TimeValue &that) const { + if ( this->seconds_ > that.seconds_ ) { + return 1; + } else if ( this->seconds_ == that.seconds_ ) { + if ( this->nanos_ > that.nanos_ ) return 1; + } + return 0; + } + + /// Determine if \p this is less than or equal to \p that. + /// @returns True iff *this <= that. + /// @brief True if this <= that. + int operator <= (const TimeValue &that) const { return that >= *this; } + + /// Determine if \p this is greater than or equal to \p that. + /// @returns True iff *this >= that. + /// @brief True if this >= that. + int operator >= (const TimeValue &that) const { + if ( this->seconds_ > that.seconds_ ) { + return 1; + } else if ( this->seconds_ == that.seconds_ ) { + if ( this->nanos_ >= that.nanos_ ) return 1; + } + return 0; + } + + /// Determines if two TimeValue objects represent the same moment in time. + /// @brief True iff *this == that. + /// @brief True if this == that. + int operator == (const TimeValue &that) const { + return (this->seconds_ == that.seconds_) && + (this->nanos_ == that.nanos_); + } + + /// Determines if two TimeValue objects represent times that are not the + /// same. + /// @return True iff *this != that. + /// @brief True if this != that. + int operator != (const TimeValue &that) const { return !(*this == that); } + + /// Adds two TimeValue objects together. + /// @returns The sum of the two operands as a new TimeValue + /// @brief Addition operator. + friend TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2); + + /// Subtracts two TimeValue objects. + /// @returns The difference of the two operands as a new TimeValue + /// @brief Subtraction operator. + friend TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2); + + /// @} + /// @name Accessors + /// @{ + public: + + /// Returns only the seconds component of the TimeValue. The nanoseconds + /// portion is ignored. No rounding is performed. + /// @brief Retrieve the seconds component + SecondsType seconds() const { return seconds_; } + + /// Returns only the nanoseconds component of the TimeValue. The seconds + /// portion is ignored. + /// @brief Retrieve the nanoseconds component. + NanoSecondsType nanoseconds() const { return nanos_; } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest microsecond (divide by one thousand). + /// @brief Retrieve the fractional part as microseconds; + uint32_t microseconds() const { + return nanos_ / NANOSECONDS_PER_MICROSECOND; + } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest millisecond (divide by one million). + /// @brief Retrieve the fractional part as milliseconds; + uint32_t milliseconds() const { + return nanos_ / NANOSECONDS_PER_MILLISECOND; + } + + /// Returns the TimeValue as a number of microseconds. Note that the value + /// returned can overflow because the range of a uint64_t is smaller than + /// the range of a TimeValue. Nevertheless, this is useful on some operating + /// systems and is therefore provided. + /// @brief Convert to a number of microseconds (can overflow) + uint64_t usec() const { + return seconds_ * MICROSECONDS_PER_SECOND + + ( nanos_ / NANOSECONDS_PER_MICROSECOND ); + } + + /// Returns the TimeValue as a number of milliseconds. Note that the value + /// returned can overflow because the range of a uint64_t is smaller than + /// the range of a TimeValue. Nevertheless, this is useful on some operating + /// systems and is therefore provided. + /// @brief Convert to a number of milliseconds (can overflow) + uint64_t msec() const { + return seconds_ * MILLISECONDS_PER_SECOND + + ( nanos_ / NANOSECONDS_PER_MILLISECOND ); + } + + /// Converts the TimeValue into the corresponding number of "ticks" for + /// Posix, correcting for the difference in Posix zero time. + /// @brief Convert to unix time (100 nanoseconds since 12:00:00a Jan 1,1970) + uint64_t toPosixTime() const { + uint64_t result = seconds_ - PosixZeroTime.seconds_; + result += nanos_ / NANOSECONDS_PER_POSIX_TICK; + return result; + } + + /// Converts the TimeValue into the corresponding number of seconds + /// since the epoch (00:00:00 Jan 1,1970). + uint64_t toEpochTime() const { + return seconds_ - PosixZeroTime.seconds_; + } + + /// 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_; + result += nanos_ / NANOSECONDS_PER_WIN32_TICK; + return result; + } + + /// Provides the seconds and nanoseconds as results in its arguments after + /// 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_; + nanos = nanos_; + } + + /// Provides conversion of the TimeValue into a readable time & date. + /// @returns std::string containing the readable time value + /// @brief Convert time to a string. + std::string str() const; + + /// @} + /// @name Mutators + /// @{ + public: + /// The seconds component of the TimeValue is set to \p sec without + /// modifying the nanoseconds part. This is useful for whole second + /// arithmetic. + /// @brief Set the seconds component. + void seconds (SecondsType sec ) { + this->seconds_ = sec; + this->normalize(); + } + + /// The nanoseconds component of the TimeValue is set to \p nanos without + /// modifying the seconds part. This is useful for basic computations + /// involving just the nanoseconds portion. Note that the TimeValue will be + /// normalized after this call so that the fractional (nanoseconds) portion + /// will have the smallest equivalent value. + /// @brief Set the nanoseconds component using a number of nanoseconds. + void nanoseconds ( NanoSecondsType nanos ) { + this->nanos_ = nanos; + this->normalize(); + } + + /// The seconds component remains unchanged. + /// @brief Set the nanoseconds component using a number of microseconds. + void microseconds ( int32_t micros ) { + this->nanos_ = micros * NANOSECONDS_PER_MICROSECOND; + this->normalize(); + } + + /// The seconds component remains unchanged. + /// @brief Set the nanoseconds component using a number of milliseconds. + void milliseconds ( int32_t millis ) { + this->nanos_ = millis * NANOSECONDS_PER_MILLISECOND; + this->normalize(); + } + + /// @brief Converts from microsecond format to TimeValue format + void usec( int64_t microseconds ) { + this->seconds_ = microseconds / MICROSECONDS_PER_SECOND; + this->nanos_ = NanoSecondsType(microseconds % MICROSECONDS_PER_SECOND) * + NANOSECONDS_PER_MICROSECOND; + this->normalize(); + } + + /// @brief Converts from millisecond format to TimeValue format + void msec( int64_t milliseconds ) { + this->seconds_ = milliseconds / MILLISECONDS_PER_SECOND; + this->nanos_ = NanoSecondsType(milliseconds % MILLISECONDS_PER_SECOND) * + NANOSECONDS_PER_MILLISECOND; + this->normalize(); + } + + /// Converts the \p seconds argument from PosixTime to the corresponding + /// TimeValue and assigns that value to \p this. + /// @brief Convert seconds form PosixTime to TimeValue + void fromEpochTime( SecondsType seconds ) { + seconds_ = seconds + PosixZeroTime.seconds_; + nanos_ = 0; + this->normalize(); + } + + /// Converts the \p win32Time argument from Windows FILETIME to the + /// 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->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; + } + + /// @} + /// @name Implementation + /// @{ + private: + /// This causes the values to be represented so that the fractional + /// part is minimized, possibly incrementing the seconds part. + /// @brief Normalize to canonical form. + void normalize(); + + /// @} + /// @name Data + /// @{ + private: + /// Store the values as a <timeval>. + SecondsType seconds_;///< Stores the seconds part of the TimeVal + NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal + /// @} + + }; + +inline TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2) { + TimeValue sum (tv1.seconds_ + tv2.seconds_, tv1.nanos_ + tv2.nanos_); + sum.normalize (); + return sum; +} + +inline TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2) { + TimeValue difference (tv1.seconds_ - tv2.seconds_, tv1.nanos_ - tv2.nanos_ ); + difference.normalize (); + return difference; +} + +} +} + +#endif diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index f959136..404cb6d 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -15,7 +15,7 @@ #ifndef LLVM_SUPPORT_TIMER_H #define LLVM_SUPPORT_TIMER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/StringRef.h" #include <cassert> #include <string> diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h new file mode 100644 index 0000000..65b182a --- /dev/null +++ b/include/llvm/Support/ToolOutputFile.h @@ -0,0 +1,62 @@ +//===- ToolOutputFile.h - Output files for compiler-like tools -----------===// +// +// 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 tool_output_file class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TOOL_OUTPUT_FILE_H +#define LLVM_SUPPORT_TOOL_OUTPUT_FILE_H + +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// tool_output_file - This class contains a raw_fd_ostream and adds a +/// few extra features commonly needed for compiler-like tool output files: +/// - The file is automatically deleted if the process is killed. +/// - The file is automatically deleted when the tool_output_file +/// object is destroyed unless the client calls keep(). +class tool_output_file { + /// Installer - This class is declared before the raw_fd_ostream so that + /// it is constructed before the raw_fd_ostream is constructed and + /// destructed after the raw_fd_ostream is destructed. It installs + /// cleanups in its constructor and uninstalls them in its destructor. + class CleanupInstaller { + /// Filename - The name of the file. + std::string Filename; + public: + /// Keep - The flag which indicates whether we should not delete the file. + bool Keep; + + explicit CleanupInstaller(const char *filename); + ~CleanupInstaller(); + } Installer; + + /// OS - The contained stream. This is intentionally declared after + /// Installer. + raw_fd_ostream OS; + +public: + /// tool_output_file - This constructor's arguments are passed to + /// to raw_fd_ostream's constructor. + tool_output_file(const char *filename, std::string &ErrorInfo, + unsigned Flags = 0); + + /// os - Return the contained raw_fd_ostream. + raw_fd_ostream &os() { return OS; } + + /// keep - Indicate that the tool's job wrt this output file has been + /// successful and the file should not be deleted. + void keep() { Installer.Keep = true; } +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/Support/TypeBuilder.h b/include/llvm/Support/TypeBuilder.h index 81c2747..ea63da0 100644 --- a/include/llvm/Support/TypeBuilder.h +++ b/include/llvm/Support/TypeBuilder.h @@ -88,6 +88,8 @@ class ieee_double {}; class x86_fp80 {}; class fp128 {}; class ppc_fp128 {}; +// X86 MMX. +class x86_mmx {}; } // namespace types // LLVM doesn't have const or volatile types. @@ -219,6 +221,10 @@ template<bool cross> class TypeBuilder<types::ppc_fp128, cross> { public: static const Type *get(LLVMContext& C) { return Type::getPPC_FP128Ty(C); } }; +template<bool cross> class TypeBuilder<types::x86_mmx, cross> { +public: + static const Type *get(LLVMContext& C) { return Type::getX86_MMXTy(C); } +}; template<bool cross> class TypeBuilder<void, cross> { public: diff --git a/include/llvm/Support/Valgrind.h b/include/llvm/Support/Valgrind.h new file mode 100644 index 0000000..7662eaa --- /dev/null +++ b/include/llvm/Support/Valgrind.h @@ -0,0 +1,32 @@ +//===- llvm/Support/Valgrind.h - Communication with Valgrind -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods for communicating with a valgrind instance this program is running +// under. These are all no-ops unless LLVM was configured on a system with the +// valgrind headers installed and valgrind is controlling this process. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_VALGRIND_H +#define LLVM_SYSTEM_VALGRIND_H + +#include <stddef.h> + +namespace llvm { +namespace sys { + // True if Valgrind is controlling this process. + bool RunningOnValgrind(); + + // Discard valgrind's translation of code in the range [Addr .. Addr + Len). + // Otherwise valgrind may continue to execute the old version of the code. + void ValgrindDiscardTranslations(const void *Addr, size_t Len); +} +} + +#endif diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 39bdbd8..6bfae5e 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -15,7 +15,7 @@ #define LLVM_SUPPORT_RAW_OSTREAM_H #include "llvm/ADT/StringRef.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class format_object_base; @@ -165,7 +165,7 @@ public: } raw_ostream &operator<<(const char *Str) { - // Inline fast path, particulary for constant strings where a sufficiently + // Inline fast path, particularly for constant strings where a sufficiently // smart compiler will simplify strlen. return this->operator<<(StringRef(Str)); @@ -196,7 +196,7 @@ public: /// write_escaped - Output \arg Str, turning '\\', '\t', '\n', '"', and /// anything that doesn't satisfy std::isprint into an escape sequence. - raw_ostream &write_escaped(StringRef Str); + raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); raw_ostream &write(unsigned char C); raw_ostream &write(const char *Ptr, size_t Size); @@ -301,6 +301,10 @@ class raw_fd_ostream : public raw_ostream { /// bool Error; + /// Controls whether the stream should attempt to use atomic writes, when + /// possible. + bool UseAtomicWrites; + uint64_t pos; /// write_impl - See raw_ostream::write_impl. @@ -349,10 +353,7 @@ public: /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If /// ShouldClose is true, this closes the file when the stream is destroyed. - raw_fd_ostream(int fd, bool shouldClose, - bool unbuffered=false) : raw_ostream(unbuffered), FD(fd), - ShouldClose(shouldClose), - Error(false) {} + raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); ~raw_fd_ostream(); @@ -361,9 +362,19 @@ public: void close(); /// seek - Flushes the stream and repositions the underlying file descriptor - /// positition to the offset specified from the beginning of the file. + /// position to the offset specified from the beginning of the file. uint64_t seek(uint64_t off); + /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for + /// individual output routines where possible. + /// + /// Note that because raw_ostream's are typically buffered, this flag is only + /// sensible when used on unbuffered streams which will flush their output + /// immediately. + void SetUseAtomicWrites(bool Value) { + UseAtomicWrites = Value; + } + virtual raw_ostream &changeColor(enum Colors colors, bool bold=false, bool bg=false); virtual raw_ostream &resetColor(); @@ -475,45 +486,6 @@ public: ~raw_null_ostream(); }; -/// tool_output_file - This class contains a raw_fd_ostream and adds a -/// few extra features commonly needed for compiler-like tool output files: -/// - The file is automatically deleted if the process is killed. -/// - The file is automatically deleted when the tool_output_file -/// object is destroyed unless the client calls keep(). -class tool_output_file { - /// Installer - This class is declared before the raw_fd_ostream so that - /// it is constructed before the raw_fd_ostream is constructed and - /// destructed after the raw_fd_ostream is destructed. It installs - /// cleanups in its constructor and uninstalls them in its destructor. - class CleanupInstaller { - /// Filename - The name of the file. - std::string Filename; - public: - /// Keep - The flag which indicates whether we should not delete the file. - bool Keep; - - explicit CleanupInstaller(const char *filename); - ~CleanupInstaller(); - } Installer; - - /// OS - The contained stream. This is intentionally declared after - /// Installer. - raw_fd_ostream OS; - -public: - /// tool_output_file - This constructor's arguments are passed to - /// to raw_fd_ostream's constructor. - tool_output_file(const char *filename, std::string &ErrorInfo, - unsigned Flags = 0); - - /// os - Return the contained raw_fd_ostream. - raw_fd_ostream &os() { return OS; } - - /// keep - Indicate that the tool's job wrt this output file has been - /// successful and the file should not be deleted. - void keep() { Installer.Keep = true; } -}; - } // end llvm namespace #endif diff --git a/include/llvm/Support/system_error.h b/include/llvm/Support/system_error.h new file mode 100644 index 0000000..e5306ec --- /dev/null +++ b/include/llvm/Support/system_error.h @@ -0,0 +1,910 @@ +//===---------------------------- system_error ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This was lifted from libc++ and modified for C++03. This is called +// system_error even though it does not define that class because that's what +// it's called in C++0x. We don't define system_error because it is only used +// for exception handling, which we don't use in LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SYSTEM_ERROR_H +#define LLVM_SYSTEM_SYSTEM_ERROR_H + +/* + system_error synopsis + +namespace std +{ + +class error_category +{ +public: + virtual ~error_category(); + + error_category(const error_category&) = delete; + error_category& operator=(const error_category&) = delete; + + virtual const char* name() const = 0; + virtual error_condition default_error_condition(int ev) const; + virtual bool equivalent(int code, const error_condition& condition) const; + virtual bool equivalent(const error_code& code, int condition) const; + virtual std::string message(int ev) const = 0; + + bool operator==(const error_category& rhs) const; + bool operator!=(const error_category& rhs) const; + bool operator<(const error_category& rhs) const; +}; + +const error_category& generic_category(); +const error_category& system_category(); + +template <class T> struct is_error_code_enum + : public false_type {}; + +template <class T> struct is_error_condition_enum + : public false_type {}; + +class error_code +{ +public: + // constructors: + error_code(); + error_code(int val, const error_category& cat); + template <class ErrorCodeEnum> + error_code(ErrorCodeEnum e); + + // modifiers: + void assign(int val, const error_category& cat); + template <class ErrorCodeEnum> + error_code& operator=(ErrorCodeEnum e); + void clear(); + + // observers: + int value() const; + const error_category& category() const; + error_condition default_error_condition() const; + std::string message() const; + explicit operator bool() const; +}; + +// non-member functions: +bool operator<(const error_code& lhs, const error_code& rhs); +template <class charT, class traits> + basic_ostream<charT,traits>& + operator<<(basic_ostream<charT,traits>& os, const error_code& ec); + +class error_condition +{ +public: + // constructors: + error_condition(); + error_condition(int val, const error_category& cat); + template <class ErrorConditionEnum> + error_condition(ErrorConditionEnum e); + + // modifiers: + void assign(int val, const error_category& cat); + template <class ErrorConditionEnum> + error_condition& operator=(ErrorConditionEnum e); + void clear(); + + // observers: + int value() const; + const error_category& category() const; + std::string message() const; + explicit operator bool() const; +}; + +bool operator<(const error_condition& lhs, const error_condition& rhs); + +class system_error + : public runtime_error +{ +public: + system_error(error_code ec, const std::string& what_arg); + system_error(error_code ec, const char* what_arg); + system_error(error_code ec); + system_error(int ev, const error_category& ecat, const std::string& what_arg); + system_error(int ev, const error_category& ecat, const char* what_arg); + system_error(int ev, const error_category& ecat); + + const error_code& code() const throw(); + const char* what() const throw(); +}; + +enum class errc +{ + address_family_not_supported, // EAFNOSUPPORT + address_in_use, // EADDRINUSE + address_not_available, // EADDRNOTAVAIL + already_connected, // EISCONN + argument_list_too_long, // E2BIG + argument_out_of_domain, // EDOM + bad_address, // EFAULT + bad_file_descriptor, // EBADF + bad_message, // EBADMSG + broken_pipe, // EPIPE + connection_aborted, // ECONNABORTED + connection_already_in_progress, // EALREADY + connection_refused, // ECONNREFUSED + connection_reset, // ECONNRESET + cross_device_link, // EXDEV + destination_address_required, // EDESTADDRREQ + device_or_resource_busy, // EBUSY + directory_not_empty, // ENOTEMPTY + executable_format_error, // ENOEXEC + file_exists, // EEXIST + file_too_large, // EFBIG + filename_too_long, // ENAMETOOLONG + function_not_supported, // ENOSYS + host_unreachable, // EHOSTUNREACH + identifier_removed, // EIDRM + illegal_byte_sequence, // EILSEQ + inappropriate_io_control_operation, // ENOTTY + interrupted, // EINTR + invalid_argument, // EINVAL + invalid_seek, // ESPIPE + io_error, // EIO + is_a_directory, // EISDIR + message_size, // EMSGSIZE + network_down, // ENETDOWN + network_reset, // ENETRESET + network_unreachable, // ENETUNREACH + no_buffer_space, // ENOBUFS + no_child_process, // ECHILD + no_link, // ENOLINK + no_lock_available, // ENOLCK + no_message_available, // ENODATA + no_message, // ENOMSG + no_protocol_option, // ENOPROTOOPT + no_space_on_device, // ENOSPC + no_stream_resources, // ENOSR + no_such_device_or_address, // ENXIO + no_such_device, // ENODEV + no_such_file_or_directory, // ENOENT + no_such_process, // ESRCH + not_a_directory, // ENOTDIR + not_a_socket, // ENOTSOCK + not_a_stream, // ENOSTR + not_connected, // ENOTCONN + not_enough_memory, // ENOMEM + not_supported, // ENOTSUP + operation_canceled, // ECANCELED + operation_in_progress, // EINPROGRESS + operation_not_permitted, // EPERM + operation_not_supported, // EOPNOTSUPP + operation_would_block, // EWOULDBLOCK + owner_dead, // EOWNERDEAD + permission_denied, // EACCES + protocol_error, // EPROTO + protocol_not_supported, // EPROTONOSUPPORT + read_only_file_system, // EROFS + resource_deadlock_would_occur, // EDEADLK + resource_unavailable_try_again, // EAGAIN + result_out_of_range, // ERANGE + state_not_recoverable, // ENOTRECOVERABLE + stream_timeout, // ETIME + text_file_busy, // ETXTBSY + timed_out, // ETIMEDOUT + too_many_files_open_in_system, // ENFILE + too_many_files_open, // EMFILE + too_many_links, // EMLINK + too_many_symbolic_link_levels, // ELOOP + value_too_large, // EOVERFLOW + wrong_protocol_type // EPROTOTYPE +}; + +template <> struct is_error_condition_enum<errc> : true_type { } + +error_code make_error_code(errc e); +error_condition make_error_condition(errc e); + +// Comparison operators: +bool operator==(const error_code& lhs, const error_code& rhs); +bool operator==(const error_code& lhs, const error_condition& rhs); +bool operator==(const error_condition& lhs, const error_code& rhs); +bool operator==(const error_condition& lhs, const error_condition& rhs); +bool operator!=(const error_code& lhs, const error_code& rhs); +bool operator!=(const error_code& lhs, const error_condition& rhs); +bool operator!=(const error_condition& lhs, const error_code& rhs); +bool operator!=(const error_condition& lhs, const error_condition& rhs); + +template <> struct hash<std::error_code>; + +} // std + +*/ + +#include "llvm/Config/config.h" +#include "llvm/Support/type_traits.h" +#include <cerrno> +#include <string> + +// This must be here instead of a .inc file because it is used in the definition +// of the enum values below. +#ifdef LLVM_ON_WIN32 + + // The following numbers were taken from VS2010. +# ifndef EAFNOSUPPORT +# define EAFNOSUPPORT 102 +# endif +# ifndef EADDRINUSE +# define EADDRINUSE 100 +# endif +# ifndef EADDRNOTAVAIL +# define EADDRNOTAVAIL 101 +# endif +# ifndef EISCONN +# define EISCONN 113 +# endif +# ifndef E2BIG +# define E2BIG 7 +# endif +# ifndef EDOM +# define EDOM 33 +# endif +# ifndef EFAULT +# define EFAULT 14 +# endif +# ifndef EBADF +# define EBADF 9 +# endif +# ifndef EBADMSG +# define EBADMSG 104 +# endif +# ifndef EPIPE +# define EPIPE 32 +# endif +# ifndef ECONNABORTED +# define ECONNABORTED 106 +# endif +# ifndef EALREADY +# define EALREADY 103 +# endif +# ifndef ECONNREFUSED +# define ECONNREFUSED 107 +# endif +# ifndef ECONNRESET +# define ECONNRESET 108 +# endif +# ifndef EXDEV +# define EXDEV 18 +# endif +# ifndef EDESTADDRREQ +# define EDESTADDRREQ 109 +# endif +# ifndef EBUSY +# define EBUSY 16 +# endif +# ifndef ENOTEMPTY +# define ENOTEMPTY 41 +# endif +# ifndef ENOEXEC +# define ENOEXEC 8 +# endif +# ifndef EEXIST +# define EEXIST 17 +# endif +# ifndef EFBIG +# define EFBIG 27 +# endif +# ifndef ENAMETOOLONG +# define ENAMETOOLONG 38 +# endif +# ifndef ENOSYS +# define ENOSYS 40 +# endif +# ifndef EHOSTUNREACH +# define EHOSTUNREACH 110 +# endif +# ifndef EIDRM +# define EIDRM 111 +# endif +# ifndef EILSEQ +# define EILSEQ 42 +# endif +# ifndef ENOTTY +# define ENOTTY 25 +# endif +# ifndef EINTR +# define EINTR 4 +# endif +# ifndef EINVAL +# define EINVAL 22 +# endif +# ifndef ESPIPE +# define ESPIPE 29 +# endif +# ifndef EIO +# define EIO 5 +# endif +# ifndef EISDIR +# define EISDIR 21 +# endif +# ifndef EMSGSIZE +# define EMSGSIZE 115 +# endif +# ifndef ENETDOWN +# define ENETDOWN 116 +# endif +# ifndef ENETRESET +# define ENETRESET 117 +# endif +# ifndef ENETUNREACH +# define ENETUNREACH 118 +# endif +# ifndef ENOBUFS +# define ENOBUFS 119 +# endif +# ifndef ECHILD +# define ECHILD 10 +# endif +# ifndef ENOLINK +# define ENOLINK 121 +# endif +# ifndef ENOLCK +# define ENOLCK 39 +# endif +# ifndef ENODATA +# define ENODATA 120 +# endif +# ifndef ENOMSG +# define ENOMSG 122 +# endif +# ifndef ENOPROTOOPT +# define ENOPROTOOPT 123 +# endif +# ifndef ENOSPC +# define ENOSPC 28 +# endif +# ifndef ENOSR +# define ENOSR 124 +# endif +# ifndef ENXIO +# define ENXIO 6 +# endif +# ifndef ENODEV +# define ENODEV 19 +# endif +# ifndef ENOENT +# define ENOENT 2 +# endif +# ifndef ESRCH +# define ESRCH 3 +# endif +# ifndef ENOTDIR +# define ENOTDIR 20 +# endif +# ifndef ENOTSOCK +# define ENOTSOCK 128 +# endif +# ifndef ENOSTR +# define ENOSTR 125 +# endif +# ifndef ENOTCONN +# define ENOTCONN 126 +# endif +# ifndef ENOMEM +# define ENOMEM 12 +# endif +# ifndef ENOTSUP +# define ENOTSUP 129 +# endif +# ifndef ECANCELED +# define ECANCELED 105 +# endif +# ifndef EINPROGRESS +# define EINPROGRESS 112 +# endif +# ifndef EPERM +# define EPERM 1 +# endif +# ifndef EOPNOTSUPP +# define EOPNOTSUPP 130 +# endif +# ifndef EWOULDBLOCK +# define EWOULDBLOCK 140 +# endif +# ifndef EOWNERDEAD +# define EOWNERDEAD 133 +# endif +# ifndef EACCES +# define EACCES 13 +# endif +# ifndef EPROTO +# define EPROTO 134 +# endif +# ifndef EPROTONOSUPPORT +# define EPROTONOSUPPORT 135 +# endif +# ifndef EROFS +# define EROFS 30 +# endif +# ifndef EDEADLK +# define EDEADLK 36 +# endif +# ifndef EAGAIN +# define EAGAIN 11 +# endif +# ifndef ERANGE +# define ERANGE 34 +# endif +# ifndef ENOTRECOVERABLE +# define ENOTRECOVERABLE 127 +# endif +# ifndef ETIME +# define ETIME 137 +# endif +# ifndef ETXTBSY +# define ETXTBSY 139 +# endif +# ifndef ETIMEDOUT +# define ETIMEDOUT 138 +# endif +# ifndef ENFILE +# define ENFILE 23 +# endif +# ifndef EMFILE +# define EMFILE 24 +# endif +# ifndef EMLINK +# define EMLINK 31 +# endif +# ifndef ELOOP +# define ELOOP 114 +# endif +# ifndef EOVERFLOW +# define EOVERFLOW 132 +# endif +# ifndef EPROTOTYPE +# define EPROTOTYPE 136 +# endif +#endif + +namespace llvm { + +template <class T, T v> +struct integral_constant { + typedef T value_type; + static const value_type value = v; + typedef integral_constant<T,v> type; + operator value_type() { return value; } +}; + +typedef integral_constant<bool, true> true_type; +typedef integral_constant<bool, false> false_type; + +// is_error_code_enum + +template <class Tp> struct is_error_code_enum : public false_type {}; + +// is_error_condition_enum + +template <class Tp> struct is_error_condition_enum : public false_type {}; + +// Some error codes are not present on all platforms, so we provide equivalents +// for them: + +//enum class errc +struct errc { +enum _ { + success = 0, + address_family_not_supported = EAFNOSUPPORT, + address_in_use = EADDRINUSE, + address_not_available = EADDRNOTAVAIL, + already_connected = EISCONN, + argument_list_too_long = E2BIG, + argument_out_of_domain = EDOM, + bad_address = EFAULT, + bad_file_descriptor = EBADF, +#ifdef EBADMSG + bad_message = EBADMSG, +#else + bad_message = EINVAL, +#endif + broken_pipe = EPIPE, + connection_aborted = ECONNABORTED, + connection_already_in_progress = EALREADY, + connection_refused = ECONNREFUSED, + connection_reset = ECONNRESET, + cross_device_link = EXDEV, + destination_address_required = EDESTADDRREQ, + device_or_resource_busy = EBUSY, + directory_not_empty = ENOTEMPTY, + executable_format_error = ENOEXEC, + file_exists = EEXIST, + file_too_large = EFBIG, + filename_too_long = ENAMETOOLONG, + function_not_supported = ENOSYS, + host_unreachable = EHOSTUNREACH, + identifier_removed = EIDRM, + illegal_byte_sequence = EILSEQ, + inappropriate_io_control_operation = ENOTTY, + interrupted = EINTR, + invalid_argument = EINVAL, + invalid_seek = ESPIPE, + io_error = EIO, + is_a_directory = EISDIR, + message_size = EMSGSIZE, + network_down = ENETDOWN, + network_reset = ENETRESET, + network_unreachable = ENETUNREACH, + no_buffer_space = ENOBUFS, + no_child_process = ECHILD, +#ifdef ENOLINK + no_link = ENOLINK, +#else + no_link = EINVAL, +#endif + no_lock_available = ENOLCK, +#ifdef ENODATA + no_message_available = ENODATA, +#else + no_message_available = ENOMSG, +#endif + no_message = ENOMSG, + no_protocol_option = ENOPROTOOPT, + no_space_on_device = ENOSPC, +#ifdef ENOSR + no_stream_resources = ENOSR, +#else + no_stream_resources = ENOMEM, +#endif + no_such_device_or_address = ENXIO, + no_such_device = ENODEV, + no_such_file_or_directory = ENOENT, + no_such_process = ESRCH, + not_a_directory = ENOTDIR, + not_a_socket = ENOTSOCK, +#ifdef ENOSTR + not_a_stream = ENOSTR, +#else + not_a_stream = EINVAL, +#endif + not_connected = ENOTCONN, + not_enough_memory = ENOMEM, + not_supported = ENOTSUP, +#ifdef ECANCELED + operation_canceled = ECANCELED, +#else + operation_canceled = EINVAL, +#endif + operation_in_progress = EINPROGRESS, + operation_not_permitted = EPERM, + operation_not_supported = EOPNOTSUPP, + operation_would_block = EWOULDBLOCK, +#ifdef EOWNERDEAD + owner_dead = EOWNERDEAD, +#else + owner_dead = EINVAL, +#endif + permission_denied = EACCES, +#ifdef EPROTO + protocol_error = EPROTO, +#else + protocol_error = EINVAL, +#endif + protocol_not_supported = EPROTONOSUPPORT, + read_only_file_system = EROFS, + resource_deadlock_would_occur = EDEADLK, + resource_unavailable_try_again = EAGAIN, + result_out_of_range = ERANGE, +#ifdef ENOTRECOVERABLE + state_not_recoverable = ENOTRECOVERABLE, +#else + state_not_recoverable = EINVAL, +#endif +#ifdef ETIME + stream_timeout = ETIME, +#else + stream_timeout = ETIMEDOUT, +#endif + text_file_busy = ETXTBSY, + timed_out = ETIMEDOUT, + too_many_files_open_in_system = ENFILE, + too_many_files_open = EMFILE, + too_many_links = EMLINK, + too_many_symbolic_link_levels = ELOOP, + value_too_large = EOVERFLOW, + wrong_protocol_type = EPROTOTYPE +}; + + _ v_; + + errc(_ v) : v_(v) {} + operator int() const {return v_;} +}; + +template <> struct is_error_condition_enum<errc> : true_type { }; + +template <> struct is_error_condition_enum<errc::_> : true_type { }; + +class error_condition; +class error_code; + +// class error_category + +class _do_message; + +class error_category +{ +public: + virtual ~error_category(); + +private: + error_category(); + error_category(const error_category&);// = delete; + error_category& operator=(const error_category&);// = delete; + +public: + virtual const char* name() const = 0; + virtual error_condition default_error_condition(int _ev) const; + virtual bool equivalent(int _code, const error_condition& _condition) const; + virtual bool equivalent(const error_code& _code, int _condition) const; + virtual std::string message(int _ev) const = 0; + + bool operator==(const error_category& _rhs) const {return this == &_rhs;} + + bool operator!=(const error_category& _rhs) const {return !(*this == _rhs);} + + bool operator< (const error_category& _rhs) const {return this < &_rhs;} + + friend class _do_message; +}; + +class _do_message : public error_category +{ +public: + virtual std::string message(int ev) const; +}; + +const error_category& generic_category(); +const error_category& system_category(); + +/// Get the error_category used for errno values from POSIX functions. This is +/// the same as the system_category on POISIX systems, but is the same as the +/// generic_category on Windows. +const error_category& posix_category(); + +class error_condition +{ + int _val_; + const error_category* _cat_; +public: + error_condition() : _val_(0), _cat_(&generic_category()) {} + + error_condition(int _val, const error_category& _cat) + : _val_(_val), _cat_(&_cat) {} + + template <class E> + error_condition(E _e, typename enable_if_c< + is_error_condition_enum<E>::value + >::type* = 0) + {*this = make_error_condition(_e);} + + void assign(int _val, const error_category& _cat) { + _val_ = _val; + _cat_ = &_cat; + } + + template <class E> + typename enable_if_c + < + is_error_condition_enum<E>::value, + error_condition& + >::type + operator=(E _e) + {*this = make_error_condition(_e); return *this;} + + void clear() { + _val_ = 0; + _cat_ = &generic_category(); + } + + int value() const {return _val_;} + + const error_category& category() const {return *_cat_;} + std::string message() const; + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + operator unspecified_bool_type() const { // true if error + return _val_ == 0 ? 0 : unspecified_bool_true; + } +}; + +inline error_condition make_error_condition(errc _e) { + return error_condition(static_cast<int>(_e), generic_category()); +} + +inline bool operator<(const error_condition& _x, const error_condition& _y) { + return _x.category() < _y.category() + || (_x.category() == _y.category() && _x.value() < _y.value()); +} + +// error_code + +class error_code { + int _val_; + const error_category* _cat_; +public: + error_code() : _val_(0), _cat_(&system_category()) {} + + error_code(int _val, const error_category& _cat) + : _val_(_val), _cat_(&_cat) {} + + template <class E> + error_code(E _e, typename enable_if_c< + is_error_code_enum<E>::value + >::type* = 0) { + *this = make_error_code(_e); + } + + void assign(int _val, const error_category& _cat) { + _val_ = _val; + _cat_ = &_cat; + } + + template <class E> + typename enable_if_c + < + is_error_code_enum<E>::value, + error_code& + >::type + operator=(E _e) + {*this = make_error_code(_e); return *this;} + + void clear() { + _val_ = 0; + _cat_ = &system_category(); + } + + int value() const {return _val_;} + + const error_category& category() const {return *_cat_;} + + error_condition default_error_condition() const + {return _cat_->default_error_condition(_val_);} + + std::string message() const; + + typedef void (*unspecified_bool_type)(); + static void unspecified_bool_true() {} + + operator unspecified_bool_type() const { // true if error + return _val_ == 0 ? 0 : unspecified_bool_true; + } +}; + +inline error_code make_error_code(errc _e) { + return error_code(static_cast<int>(_e), generic_category()); +} + +inline bool operator<(const error_code& _x, const error_code& _y) { + return _x.category() < _y.category() + || (_x.category() == _y.category() && _x.value() < _y.value()); +} + +inline bool operator==(const error_code& _x, const error_code& _y) { + return _x.category() == _y.category() && _x.value() == _y.value(); +} + +inline bool operator==(const error_code& _x, const error_condition& _y) { + return _x.category().equivalent(_x.value(), _y) + || _y.category().equivalent(_x, _y.value()); +} + +inline bool operator==(const error_condition& _x, const error_code& _y) { + return _y == _x; +} + +inline bool operator==(const error_condition& _x, const error_condition& _y) { + return _x.category() == _y.category() && _x.value() == _y.value(); +} + +inline bool operator!=(const error_code& _x, const error_code& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_code& _x, const error_condition& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_condition& _x, const error_code& _y) { + return !(_x == _y); +} + +inline bool operator!=(const error_condition& _x, const error_condition& _y) { + return !(_x == _y); +} + +// Windows errors. + +// To construct an error_code after an API error: +// +// error_code( ::GetLastError(), system_category() ) +struct windows_error { +enum _ { + success = 0, + // These names and values are based on Windows WinError.h + // This is not a complete list. Add to this list if you need to explicitly + // check for it. + invalid_function = 1, // ERROR_INVALID_FUNCTION, + file_not_found = 2, // ERROR_FILE_NOT_FOUND, + path_not_found = 3, // ERROR_PATH_NOT_FOUND, + too_many_open_files = 4, // ERROR_TOO_MANY_OPEN_FILES, + access_denied = 5, // ERROR_ACCESS_DENIED, + invalid_handle = 6, // ERROR_INVALID_HANDLE, + arena_trashed = 7, // ERROR_ARENA_TRASHED, + not_enough_memory = 8, // ERROR_NOT_ENOUGH_MEMORY, + invalid_block = 9, // ERROR_INVALID_BLOCK, + bad_environment = 10, // ERROR_BAD_ENVIRONMENT, + bad_format = 11, // ERROR_BAD_FORMAT, + invalid_access = 12, // ERROR_INVALID_ACCESS, + outofmemory = 14, // ERROR_OUTOFMEMORY, + invalid_drive = 15, // ERROR_INVALID_DRIVE, + current_directory = 16, // ERROR_CURRENT_DIRECTORY, + not_same_device = 17, // ERROR_NOT_SAME_DEVICE, + no_more_files = 18, // ERROR_NO_MORE_FILES, + write_protect = 19, // ERROR_WRITE_PROTECT, + bad_unit = 20, // ERROR_BAD_UNIT, + not_ready = 21, // ERROR_NOT_READY, + bad_command = 22, // ERROR_BAD_COMMAND, + crc = 23, // ERROR_CRC, + bad_length = 24, // ERROR_BAD_LENGTH, + seek = 25, // ERROR_SEEK, + not_dos_disk = 26, // ERROR_NOT_DOS_DISK, + sector_not_found = 27, // ERROR_SECTOR_NOT_FOUND, + out_of_paper = 28, // ERROR_OUT_OF_PAPER, + write_fault = 29, // ERROR_WRITE_FAULT, + read_fault = 30, // ERROR_READ_FAULT, + gen_failure = 31, // ERROR_GEN_FAILURE, + sharing_violation = 32, // ERROR_SHARING_VIOLATION, + lock_violation = 33, // ERROR_LOCK_VIOLATION, + wrong_disk = 34, // ERROR_WRONG_DISK, + sharing_buffer_exceeded = 36, // ERROR_SHARING_BUFFER_EXCEEDED, + handle_eof = 38, // ERROR_HANDLE_EOF, + handle_disk_full = 39, // ERROR_HANDLE_DISK_FULL, + rem_not_list = 51, // ERROR_REM_NOT_LIST, + dup_name = 52, // ERROR_DUP_NAME, + bad_net_path = 53, // ERROR_BAD_NETPATH, + network_busy = 54, // ERROR_NETWORK_BUSY, + file_exists = 80, // ERROR_FILE_EXISTS, + cannot_make = 82, // ERROR_CANNOT_MAKE, + broken_pipe = 109, // ERROR_BROKEN_PIPE, + open_failed = 110, // ERROR_OPEN_FAILED, + buffer_overflow = 111, // ERROR_BUFFER_OVERFLOW, + disk_full = 112, // ERROR_DISK_FULL, + insufficient_buffer = 122, // ERROR_INSUFFICIENT_BUFFER, + lock_failed = 167, // ERROR_LOCK_FAILED, + busy = 170, // ERROR_BUSY, + cancel_violation = 173, // ERROR_CANCEL_VIOLATION, + already_exists = 183 // ERROR_ALREADY_EXISTS +}; + _ v_; + + windows_error(_ v) : v_(v) {} + explicit windows_error(int v) : v_(_(v)) {} + operator int() const {return v_;} +}; + + +template <> struct is_error_code_enum<windows_error> : true_type { }; + +template <> struct is_error_code_enum<windows_error::_> : true_type { }; + +inline error_code make_error_code(windows_error e) { + return error_code(static_cast<int>(e), system_category()); +} + +} // end namespace llvm + +#endif |