diff options
author | Stephen Hines <srhines@google.com> | 2014-07-21 00:45:20 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-07-21 00:45:20 -0700 |
commit | c6a4f5e819217e1e12c458aed8e7b122e23a3a58 (patch) | |
tree | 81b7dd2bb4370a392f31d332a566c903b5744764 /include/llvm/Support | |
parent | 19c6fbb3e8aaf74093afa08013134b61fa08f245 (diff) | |
download | external_llvm-c6a4f5e819217e1e12c458aed8e7b122e23a3a58.zip external_llvm-c6a4f5e819217e1e12c458aed8e7b122e23a3a58.tar.gz external_llvm-c6a4f5e819217e1e12c458aed8e7b122e23a3a58.tar.bz2 |
Update LLVM for rebase to r212749.
Includes a cherry-pick of:
r212948 - fixes a small issue with atomic calls
Change-Id: Ib97bd980b59f18142a69506400911a6009d9df18
Diffstat (limited to 'include/llvm/Support')
40 files changed, 2016 insertions, 1551 deletions
diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h index 1631200..f63e0a6 100644 --- a/include/llvm/Support/ARMBuildAttributes.h +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -159,6 +159,11 @@ enum { AddressDirect = 1, // Address imported data directly AddressGOT = 2, // Address imported data indirectly (via GOT) + // Tag_ABI_PCS_wchar_t, (=18), uleb128 + WCharProhibited = 0, // wchar_t is not used + WCharWidth2Bytes = 2, // sizeof(wchar_t) == 2 + WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4 + // Tag_ABI_FP_denormal, (=20), uleb128 PreserveFPSign = 2, // sign when flushed-to-zero is preserved @@ -166,6 +171,16 @@ enum { AllowRTABI = 2, // numbers, infinities, and one quiet NaN (see [RTABI]) AllowIEE754 = 3, // this code to use all the IEEE 754-defined FP encodings + // Tag_ABI_enum_size, (=26), uleb128 + EnumProhibited = 0, // The user prohibited the use of enums when building + // this entity. + EnumSmallest = 1, // Enum is smallest container big enough to hold all + // values. + Enum32Bit = 2, // Enum is at least 32 bits. + Enum32BitABI = 3, // Every enumeration visible across an ABI-complying + // interface contains a value needing 32 bits to encode + // it; other enums can be containerized. + // Tag_ABI_HardFP_use, (=27), uleb128 HardFPImplied = 0, // FP use should be implied by Tag_FP_arch HardFPSinglePrecision = 1, // Single-precision only diff --git a/include/llvm/Support/ARMWinEH.h b/include/llvm/Support/ARMWinEH.h new file mode 100644 index 0000000..78deb8d --- /dev/null +++ b/include/llvm/Support/ARMWinEH.h @@ -0,0 +1,384 @@ +//===-- llvm/Support/WinARMEH.h - Windows on ARM EH Constants ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WINARMEH_H +#define LLVM_SUPPORT_WINARMEH_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace ARM { +namespace WinEH { +enum class RuntimeFunctionFlag { + RFF_Unpacked, /// unpacked entry + RFF_Packed, /// packed entry + RFF_PackedFragment, /// packed entry representing a fragment + RFF_Reserved, /// reserved +}; + +enum class ReturnType { + RT_POP, /// return via pop {pc} (L flag must be set) + RT_B, /// 16-bit branch + RT_BW, /// 32-bit branch + RT_NoEpilogue, /// no epilogue (fragment) +}; + +/// RuntimeFunction - An entry in the table of procedure data (.pdata) +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +---------------------------------------------------------------+ +/// | Function Start RVA | +/// +-------------------+-+-+-+-----+-+---+---------------------+---+ +/// | Stack Adjust |C|L|R| Reg |H|Ret| Function Length |Flg| +/// +-------------------+-+-+-+-----+-+---+---------------------+---+ +/// +/// Flag : 2-bit field with the following meanings: +/// - 00 = packed unwind data not used; reamining bits point to .xdata record +/// - 01 = packed unwind data +/// - 10 = packed unwind data, function assumed to have no prologue; useful +/// for function fragments that are discontiguous with the start of the +/// function +/// - 11 = reserved +/// Function Length : 11-bit field providing the length of the entire function +/// in bytes, divided by 2; if the function is greater than +/// 4KB, a full .xdata record must be used instead +/// Ret : 2-bit field indicating how the function returns +/// - 00 = return via pop {pc} (the L bit must be set) +/// - 01 = return via 16-bit branch +/// - 10 = return via 32-bit branch +/// - 11 = no epilogue; useful for function fragments that may only contain a +/// prologue but the epilogue is elsewhere +/// H : 1-bit flag indicating whether the function "homes" the integer parameter +/// registers (r0-r3), allocating 16-bytes on the stack +/// Reg : 3-bit field indicating the index of the last saved non-volatile +/// register. If the R bit is set to 0, then only integer registers are +/// saved (r4-rN, where N is 4 + Reg). If the R bit is set to 1, then +/// only floating-point registers are being saved (d8-dN, where N is +/// 8 + Reg). The special case of the R bit being set to 1 and Reg equal +/// to 7 indicates that no registers are saved. +/// R : 1-bit flag indicating whether the non-volatile registers are integer or +/// floating-point. 0 indicates integer, 1 indicates floating-point. The +/// special case of the R-flag being set and Reg being set to 7 indicates +/// that no non-volatile registers are saved. +/// L : 1-bit flag indicating whether the function saves/restores the link +/// register (LR) +/// C : 1-bit flag indicating whether the function includes extra instructions +/// to setup a frame chain for fast walking. If this flag is set, r11 is +/// implicitly added to the list of saved non-volatile integer registers. +/// Stack Adjust : 10-bit field indicating the number of bytes of stack that are +/// allocated for this function. Only values between 0x000 and +/// 0x3f3 can be directly encoded. If the value is 0x3f4 or +/// greater, then the low 4 bits have special meaning as follows: +/// - Bit 0-1 +/// indicate the number of words' of adjustment (1-4), minus 1 +/// - Bit 2 +/// indicates if the prologue combined adjustment into push +/// - Bit 3 +/// indicates if the epilogue combined adjustment into pop +/// +/// RESTRICTIONS: +/// - IF C is SET: +/// + L flag must be set since frame chaining requires r11 and lr +/// + r11 must NOT be included in the set of registers described by Reg +/// - IF Ret is 0: +/// + L flag must be set + +// NOTE: RuntimeFunction is meant to be a simple class that provides raw access +// to all fields in the structure. The accessor methods reflect the names of +// the bitfields that they correspond to. Although some obvious simplifications +// are possible via merging of methods, it would prevent the use of this class +// to fully inspect the contents of the data structure which is particularly +// useful for scenarios such as llvm-readobj to aid in testing. + +class RuntimeFunction { +public: + const support::ulittle32_t BeginAddress; + const support::ulittle32_t UnwindData; + + RuntimeFunction(const support::ulittle32_t *Data) + : BeginAddress(Data[0]), UnwindData(Data[1]) {} + + RuntimeFunction(const support::ulittle32_t BeginAddress, + const support::ulittle32_t UnwindData) + : BeginAddress(BeginAddress), UnwindData(UnwindData) {} + + RuntimeFunctionFlag Flag() const { + return RuntimeFunctionFlag(UnwindData & 0x3); + } + + uint32_t ExceptionInformationRVA() const { + assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked && + "unpacked form required for this operation"); + return (UnwindData & ~0x3); + } + + uint32_t PackedUnwindData() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return (UnwindData & ~0x3); + } + uint32_t FunctionLength() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return (((UnwindData & 0x00001ffc) >> 2) << 1); + } + ReturnType Ret() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + assert(((UnwindData & 0x00006000) || L()) && "L must be set to 1"); + return ReturnType((UnwindData & 0x00006000) >> 13); + } + bool H() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00008000) >> 15); + } + uint8_t Reg() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00070000) >> 16); + } + bool R() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00080000) >> 19); + } + bool L() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0x00100000) >> 20); + } + bool C() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + assert(((~UnwindData & 0x00200000) || L()) && + "L flag must be set, chaining requires r11 and LR"); + assert(((~UnwindData & 0x00200000) || (Reg() < 7) || R()) && + "r11 must not be included in Reg; C implies r11"); + return ((UnwindData & 0x00200000) >> 21); + } + uint16_t StackAdjust() const { + assert((Flag() == RuntimeFunctionFlag::RFF_Packed || + Flag() == RuntimeFunctionFlag::RFF_PackedFragment) && + "packed form required for this operation"); + return ((UnwindData & 0xffc00000) >> 22); + } +}; + +/// PrologueFolding - pseudo-flag derived from Stack Adjust indicating that the +/// prologue has stack adjustment combined into the push +inline bool PrologueFolding(const RuntimeFunction &RF) { + return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x4); +} +/// Epilogue - pseudo-flag derived from Stack Adjust indicating that the +/// epilogue has stack adjustment combined into the pop +inline bool EpilogueFolding(const RuntimeFunction &RF) { + return RF.StackAdjust() >= 0x3f4 && (RF.StackAdjust() & 0x8); +} +/// StackAdjustment - calculated stack adjustment in words. The stack +/// adjustment should be determined via this function to account for the special +/// handling the special encoding when the value is >= 0x3f4. +inline uint16_t StackAdjustment(const RuntimeFunction &RF) { + uint16_t Adjustment = RF.StackAdjust(); + if (Adjustment >= 0x3f4) + return (Adjustment & 0x3) ? ((Adjustment & 0x3) << 2) - 1 : 0; + return Adjustment; +} + +/// SavedRegisterMask - Utility function to calculate the set of saved general +/// purpose (r0-r15) and VFP (d0-d31) registers. +std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF); + +/// ExceptionDataRecord - An entry in the table of exception data (.xdata) +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +-------+---------+-+-+-+---+-----------------------------------+ +/// | C Wrd | Epi Cnt |F|E|X|Ver| Function Length | +/// +-------+--------+'-'-'-'---'---+-------------------------------+ +/// | Reserved |Ex. Code Words| (Extended Epilogue Count) | +/// +-------+--------+--------------+-------------------------------+ +/// +/// Function Length : 18-bit field indicating the total length of the function +/// in bytes divided by 2. If a function is larger than +/// 512KB, then multiple pdata and xdata records must be used. +/// Vers : 2-bit field describing the version of the remaining structure. Only +/// version 0 is currently defined (values 1-3 are not permitted). +/// X : 1-bit field indicating the presence of exception data +/// E : 1-bit field indicating that the single epilogue is packed into the +/// header +/// F : 1-bit field indicating that the record describes a function fragment +/// (implies that no prologue is present, and prologue processing should be +/// skipped) +/// Epilogue Count : 5-bit field that differs in meaning based on the E field. +/// +/// If E is set, then this field specifies the index of the +/// first unwind code describing the (only) epilogue. +/// +/// Otherwise, this field indicates the number of exception +/// scopes. If more than 31 scopes exist, then this field and +/// the Code Words field must both be set to 0 to indicate that +/// an extension word is required. +/// Code Words : 4-bit field that species the number of 32-bit words needed to +/// contain all the unwind codes. If more than 15 words (63 code +/// bytes) are required, then this field and the Epilogue Count +/// field must both be set to 0 to indicate that an extension word +/// is required. +/// Extended Epilogue Count, Extended Code Words : +/// Valid only if Epilog Count and Code Words are both +/// set to 0. Provides an 8-bit extended code word +/// count and 16-bits for epilogue count +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +----------------+------+---+---+-------------------------------+ +/// | Ep Start Idx | Cond |Res| Epilogue Start Offset | +/// +----------------+------+---+-----------------------------------+ +/// +/// If the E bit is unset in the header, the header is followed by a series of +/// epilogue scopes, which are sorted by their offset. +/// +/// Epilogue Start Offset: 18-bit field encoding the offset of epilogue relative +/// to the start of the function in bytes divided by two +/// Res : 2-bit field reserved for future expansion (must be set to 0) +/// Condition : 4-bit field providing the condition under which the epilogue is +/// executed. Unconditional epilogues should set this field to 0xe. +/// Epilogues must be entirely conditional or unconditional, and in +/// Thumb-2 mode. The epilogue beings with the first instruction +/// after the IT opcode. +/// Epilogue Start Index : 8-bit field indicating the byte index of the first +/// unwind code describing the epilogue +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +---------------+---------------+---------------+---------------+ +/// | Unwind Code 3 | Unwind Code 2 | Unwind Code 1 | Unwind Code 0 | +/// +---------------+---------------+---------------+---------------+ +/// +/// Following the epilogue scopes, the byte code describing the unwinding +/// follows. This is padded to align up to word alignment. Bytes are stored in +/// little endian. +/// +/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 +/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +/// +---------------------------------------------------------------+ +/// | Exception Handler RVA (requires X = 1) | +/// +---------------------------------------------------------------+ +/// | (possibly followed by data required for exception handler) | +/// +---------------------------------------------------------------+ +/// +/// If the X bit is set in the header, the unwind byte code is followed by the +/// exception handler information. This constants of one Exception Handler RVA +/// which is the address to the exception handler, followed immediately by the +/// variable length data associated with the exception handler. +/// + +struct EpilogueScope { + const support::ulittle32_t ES; + + EpilogueScope(const support::ulittle32_t Data) : ES(Data) {} + uint32_t EpilogueStartOffset() const { + return (ES & 0x0003ffff); + } + uint8_t Res() const { + return ((ES & 0x000c0000) >> 18); + } + uint8_t Condition() const { + return ((ES & 0x00f00000) >> 20); + } + uint8_t EpilogueStartIndex() const { + return ((ES & 0xff000000) >> 24); + } +}; + +struct ExceptionDataRecord; +inline size_t HeaderWords(const ExceptionDataRecord &XR); + +struct ExceptionDataRecord { + const support::ulittle32_t *Data; + + ExceptionDataRecord(const support::ulittle32_t *Data) : Data(Data) {} + + uint32_t FunctionLength() const { + return (Data[0] & 0x0003ffff); + } + + uint8_t Vers() const { + return (Data[0] & 0x000C0000) >> 18; + } + + bool X() const { + return ((Data[0] & 0x00100000) >> 20); + } + + bool E() const { + return ((Data[0] & 0x00200000) >> 21); + } + + bool F() const { + return ((Data[0] & 0x00400000) >> 22); + } + + uint8_t EpilogueCount() const { + if (HeaderWords(*this) == 1) + return (Data[0] & 0x0f800000) >> 23; + return Data[1] & 0x0000ffff; + } + + uint8_t CodeWords() const { + if (HeaderWords(*this) == 1) + return (Data[0] & 0xf0000000) >> 28; + return (Data[1] & 0x00ff0000) >> 16; + } + + ArrayRef<support::ulittle32_t> EpilogueScopes() const { + assert(E() == 0 && "epilogue scopes are only present when the E bit is 0"); + size_t Offset = HeaderWords(*this); + return ArrayRef<support::ulittle32_t>(&Data[Offset], EpilogueCount()); + } + + ArrayRef<support::ulittle8_t> UnwindByteCode() const { + const size_t Offset = HeaderWords(*this) + + (E() ? 0 : EpilogueCount()); + const support::ulittle8_t *ByteCode = + reinterpret_cast<const support::ulittle8_t *>(&Data[Offset]); + return ArrayRef<support::ulittle8_t>(ByteCode, + CodeWords() * sizeof(uint32_t)); + } + + uint32_t ExceptionHandlerRVA() const { + assert(X() && "Exception Handler RVA is only valid if the X bit is set"); + return Data[HeaderWords(*this) + EpilogueCount() + CodeWords()]; + } + + uint32_t ExceptionHandlerParameter() const { + assert(X() && "Exception Handler RVA is only valid if the X bit is set"); + return Data[HeaderWords(*this) + EpilogueCount() + CodeWords() + 1]; + } +}; + +inline size_t HeaderWords(const ExceptionDataRecord &XR) { + return (XR.Data[0] & 0xff800000) ? 1 : 2; +} +} +} +} + +#endif + diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index f0e5c7d..e09ef07 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -553,7 +553,8 @@ namespace COFF { IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040, /// Code integrity checks are enforced. IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080, - IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, ///< Image is NX compatible. + ///< Image is NX compatible. + IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, /// Isolation aware, but do not isolate the image. IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200, /// Does not use structured exception handling (SEH). No SEH handler may be @@ -561,7 +562,12 @@ namespace COFF { IMAGE_DLL_CHARACTERISTICS_NO_SEH = 0x0400, /// Do not bind the image. IMAGE_DLL_CHARACTERISTICS_NO_BIND = 0x0800, - IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000, ///< A WDM driver. + ///< Image should execute in an AppContainer. + IMAGE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000, + ///< A WDM driver. + IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000, + ///< Image supports Control Flow Guard. + IMAGE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000, /// Terminal Server aware. IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 }; diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 1edcd45..25bf32a 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -61,6 +61,12 @@ #define LLVM_MSC_PREREQ(version) 0 #endif +#ifndef _MSC_VER +#define LLVM_NOEXCEPT noexcept +#else +#define LLVM_NOEXCEPT +#endif + /// \brief Does the compiler support r-value reference *this? /// /// Sadly, this is separate from just r-value reference support because GCC diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h index 2820366..a184d0d 100644 --- a/include/llvm/Support/ConvertUTF.h +++ b/include/llvm/Support/ConvertUTF.h @@ -136,7 +136,19 @@ ConversionResult ConvertUTF8toUTF16 ( const UTF8** sourceStart, const UTF8* sourceEnd, UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); -ConversionResult ConvertUTF8toUTF32 ( +/** + * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an + * incomplete code unit sequence, returns \c sourceExhausted. + */ +ConversionResult ConvertUTF8toUTF32Partial( + const UTF8** sourceStart, const UTF8* sourceEnd, + UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); + +/** + * Convert a partial UTF8 sequence to UTF32. If the sequence ends in an + * incomplete code unit sequence, returns \c sourceIllegal. + */ +ConversionResult ConvertUTF8toUTF32( const UTF8** sourceStart, const UTF8* sourceEnd, UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index c132373..3869ebd 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -87,6 +87,9 @@ public: /// requested stack size). /// /// See RunSafely() and llvm_execute_on_thread(). + /// + /// On Darwin, if PRIO_DARWIN_BG is set on the calling thread, it will be + /// propagated to the new thread as well. bool RunSafelyOnThread(function_ref<void()>, unsigned RequestedStackSize = 0); bool RunSafelyOnThread(void (*Fn)(void*), void *UserData, unsigned RequestedStackSize = 0) { diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake index a26070c..1f0c8eb 100644 --- a/include/llvm/Support/DataTypes.h.cmake +++ b/include/llvm/Support/DataTypes.h.cmake @@ -37,6 +37,16 @@ #include <math.h> #endif +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#else +#error "Compiler must provide an implementation of stdint.h" +#endif + #ifndef _MSC_VER /* Note that this header's correct operation depends on __STDC_LIMIT_MACROS @@ -55,14 +65,6 @@ /* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ #include <sys/types.h> -#ifdef HAVE_INTTYPES_H -#include <inttypes.h> -#endif - -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif - #ifdef _AIX #include "llvm/Support/AIXDataTypesFix.h" #endif @@ -77,11 +79,6 @@ typedef u_int64_t uint64_t; #endif #else /* _MSC_VER */ -/* Visual C++ doesn't provide standard integer headers, but it does provide - built-in data types. */ -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif #include <stdlib.h> #include <stddef.h> #include <sys/types.h> @@ -90,93 +87,21 @@ typedef u_int64_t uint64_t; #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; + #if defined(_WIN64) - typedef signed __int64 ssize_t; +typedef signed __int64 ssize_t; #else - typedef signed int ssize_t; -#endif -#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 -/* MSC treats -2147483648 as -(2147483648U). */ -# define INT32_MIN (-INT32_MAX - 1) -#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 - -#ifndef PRId64 -# define PRId64 "I64d" -#endif -#ifndef PRIi64 -# define PRIi64 "I64i" -#endif -#ifndef PRIo64 -# define PRIo64 "I64o" -#endif -#ifndef PRIu64 -# define PRIu64 "I64u" -#endif -#ifndef PRIx64 -# define PRIx64 "I64x" -#endif -#ifndef PRIX64 -# define PRIX64 "I64X" -#endif +typedef signed int ssize_t; +#endif /* _WIN64 */ + +#ifndef HAVE_INTTYPES_H +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#endif /* HAVE_INTTYPES_H */ #endif /* _MSC_VER */ diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in index 7fc9b72..09cfcdf 100644 --- a/include/llvm/Support/DataTypes.h.in +++ b/include/llvm/Support/DataTypes.h.in @@ -37,6 +37,16 @@ #include <math.h> #endif +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#else +#error "Compiler must provide an implementation of stdint.h" +#endif + #ifndef _MSC_VER /* Note that this header's correct operation depends on __STDC_LIMIT_MACROS @@ -55,14 +65,6 @@ /* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ #include <sys/types.h> -#ifdef HAVE_INTTYPES_H -#include <inttypes.h> -#endif - -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif - #ifdef _AIX #include "llvm/Support/AIXDataTypesFix.h" #endif @@ -77,8 +79,6 @@ typedef u_int64_t uint64_t; #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> @@ -87,94 +87,21 @@ typedef u_int64_t uint64_t; #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; + #if defined(_WIN64) - typedef signed __int64 ssize_t; +typedef signed __int64 ssize_t; #else - typedef signed int ssize_t; -#endif - -#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 -/* MSC treats -2147483648 as -(2147483648U). */ -# define INT32_MIN (-INT32_MAX - 1) -#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 - -#ifndef PRId64 -# define PRId64 "I64d" -#endif -#ifndef PRIi64 -# define PRIi64 "I64i" -#endif -#ifndef PRIo64 -# define PRIo64 "I64o" -#endif -#ifndef PRIu64 -# define PRIu64 "I64u" -#endif -#ifndef PRIx64 -# define PRIx64 "I64x" -#endif -#ifndef PRIX64 -# define PRIX64 "I64X" -#endif +typedef signed int ssize_t; +#endif /* _WIN64 */ + +#ifndef HAVE_INTTYPES_H +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#endif /* HAVE_INTTYPES_H */ #endif /* _MSC_VER */ diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index ca31644..cd9f756 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -57,7 +57,6 @@ enum LLVMConstants : uint32_t { DW_TAG_user_base = 0x1000, // Recommended base for user tags. DWARF_VERSION = 4, // Default dwarf version we output. - DW_CIE_VERSION = 1, // Common frame information version. DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes. DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames. DW_ARANGES_VERSION = 2 // Section version number for .debug_aranges. diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 0b3e55b..67cc651 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -124,6 +124,8 @@ enum { }; // Machine architectures +// See current registered ELF machine architectures at: +// http://www.uxsglobal.com/developers/gabi/latest/ch4.eheader.html enum { EM_NONE = 0, // No machine EM_M32 = 1, // AT&T WE 32100 @@ -287,7 +289,26 @@ enum { EM_RL78 = 197, // Renesas RL78 family EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor EM_78KOR = 199, // Renesas 78KOR family - EM_56800EX = 200 // Freescale 56800EX Digital Signal Controller (DSC) + EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller (DSC) + EM_BA1 = 201, // Beyond BA1 CPU architecture + EM_BA2 = 202, // Beyond BA2 CPU architecture + EM_XCORE = 203, // XMOS xCORE processor family + EM_MCHP_PIC = 204, // Microchip 8-bit PIC(r) family + EM_INTEL205 = 205, // Reserved by Intel + EM_INTEL206 = 206, // Reserved by Intel + EM_INTEL207 = 207, // Reserved by Intel + EM_INTEL208 = 208, // Reserved by Intel + EM_INTEL209 = 209, // Reserved by Intel + EM_KM32 = 210, // KM211 KM32 32-bit processor + EM_KMX32 = 211, // KM211 KMX32 32-bit processor + EM_KMX16 = 212, // KM211 KMX16 16-bit processor + EM_KMX8 = 213, // KM211 KMX8 8-bit processor + EM_KVARC = 214, // KM211 KVARC processor + EM_CDP = 215, // Paneve CDP architecture family + EM_COGE = 216, // Cognitive Smart Memory Processor + EM_COOL = 217, // iCelero CoolEngine + EM_NORC = 218, // Nanoradio Optimized RISC + EM_CSR_KALIMBA = 219 // CSR Kalimba architecture family }; // Object file classes. @@ -1278,6 +1299,7 @@ enum : unsigned { SHT_MIPS_REGINFO = 0x70000006, // Register usage information SHT_MIPS_OPTIONS = 0x7000000d, // General options + SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. @@ -1595,7 +1617,8 @@ enum { // MIPS program header types. PT_MIPS_REGINFO = 0x70000000, // Register usage information. PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. - PT_MIPS_OPTIONS = 0x70000002 // Options segment. + PT_MIPS_OPTIONS = 0x70000002, // Options segment. + PT_MIPS_ABIFLAGS = 0x70000003 // Abiflags segment. }; // Segment flag bits. diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 2c5ab74..455d0fc 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -38,7 +38,7 @@ namespace endian { template<typename value_type, endianness endian> inline value_type byte_swap(value_type value) { if (endian != native && sys::IsBigEndianHost != (endian == big)) - return sys::SwapByteOrder(value); + sys::swapByteOrder(value); return value; } diff --git a/include/llvm/Support/Errc.h b/include/llvm/Support/Errc.h new file mode 100644 index 0000000..80bfe2a --- /dev/null +++ b/include/llvm/Support/Errc.h @@ -0,0 +1,86 @@ +//===- llvm/Support/Errc.h - Defines the llvm::errc enum --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// While std::error_code works OK on all platforms we use, there are some +// some problems with std::errc that can be avoided by using our own +// enumeration: +// +// * std::errc is a namespace in some implementations. That meas that ADL +// doesn't work and it is sometimes necessary to write std::make_error_code +// or in templates: +// using std::make_error_code; +// make_error_code(...); +// +// with this enum it is safe to always just use make_error_code. +// +// * Some implementations define fewer names than others. This header has +// the intersection of all the ones we support. +// +// * std::errc is just marked with is_error_condition_enum. This means that +// common patters like AnErrorCode == errc::no_such_file_or_directory take +// 4 virtual calls instead of two comparisons. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERRC_H +#define LLVM_SUPPORT_ERRC_H + +#include <system_error> + +namespace llvm { +enum class errc { + argument_list_too_long = int(std::errc::argument_list_too_long), + argument_out_of_domain = int(std::errc::argument_out_of_domain), + bad_address = int(std::errc::bad_address), + bad_file_descriptor = int(std::errc::bad_file_descriptor), + broken_pipe = int(std::errc::broken_pipe), + device_or_resource_busy = int(std::errc::device_or_resource_busy), + directory_not_empty = int(std::errc::directory_not_empty), + executable_format_error = int(std::errc::executable_format_error), + file_exists = int(std::errc::file_exists), + file_too_large = int(std::errc::file_too_large), + filename_too_long = int(std::errc::filename_too_long), + function_not_supported = int(std::errc::function_not_supported), + illegal_byte_sequence = int(std::errc::illegal_byte_sequence), + inappropriate_io_control_operation = + int(std::errc::inappropriate_io_control_operation), + interrupted = int(std::errc::interrupted), + invalid_argument = int(std::errc::invalid_argument), + invalid_seek = int(std::errc::invalid_seek), + io_error = int(std::errc::io_error), + is_a_directory = int(std::errc::is_a_directory), + no_child_process = int(std::errc::no_child_process), + no_lock_available = int(std::errc::no_lock_available), + no_space_on_device = int(std::errc::no_space_on_device), + no_such_device_or_address = int(std::errc::no_such_device_or_address), + no_such_device = int(std::errc::no_such_device), + no_such_file_or_directory = int(std::errc::no_such_file_or_directory), + no_such_process = int(std::errc::no_such_process), + not_a_directory = int(std::errc::not_a_directory), + not_enough_memory = int(std::errc::not_enough_memory), + operation_not_permitted = int(std::errc::operation_not_permitted), + permission_denied = int(std::errc::permission_denied), + read_only_file_system = int(std::errc::read_only_file_system), + resource_deadlock_would_occur = int(std::errc::resource_deadlock_would_occur), + resource_unavailable_try_again = + int(std::errc::resource_unavailable_try_again), + result_out_of_range = int(std::errc::result_out_of_range), + too_many_files_open_in_system = int(std::errc::too_many_files_open_in_system), + too_many_files_open = int(std::errc::too_many_files_open), + too_many_links = int(std::errc::too_many_links) +}; + +inline std::error_code make_error_code(errc E) { + return std::error_code(static_cast<int>(E), std::generic_category()); +} +} + +namespace std { +template <> struct is_error_code_enum<llvm::errc> : std::true_type {}; +} +#endif diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h index ac3a4d8..9afd52d 100644 --- a/include/llvm/Support/ErrorHandling.h +++ b/include/llvm/Support/ErrorHandling.h @@ -30,9 +30,6 @@ namespace llvm { /// install_fatal_error_handler - Installs a new error handler to be used /// whenever a serious (non-recoverable) error is encountered by LLVM. /// - /// If you are using llvm_start_multithreaded, you should register the handler - /// before doing that. - /// /// If no error handler is installed the default is to print the error message /// to stderr, and call exit(1). If an error handler is installed then it is /// the handler's responsibility to log the message, it will no longer be @@ -50,8 +47,6 @@ namespace llvm { void *user_data = nullptr); /// Restores default error handling behaviour. - /// This must not be called between llvm_start_multithreaded() and - /// llvm_stop_multithreaded(). void remove_fatal_error_handler(); /// ScopedFatalErrorHandler - This is a simple helper class which just diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index becd957..0742a2d 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -18,8 +18,8 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/AlignOf.h" -#include "llvm/Support/system_error.h" #include <cassert> +#include <system_error> #include <type_traits> namespace llvm { @@ -94,15 +94,16 @@ private: public: template <class E> - ErrorOr(E ErrorCode, typename std::enable_if<is_error_code_enum<E>::value || - is_error_condition_enum<E>::value, - void *>::type = 0) + ErrorOr(E ErrorCode, + typename std::enable_if<std::is_error_code_enum<E>::value || + std::is_error_condition_enum<E>::value, + void *>::type = 0) : HasError(true) { - new (getErrorStorage()) error_code(make_error_code(ErrorCode)); + new (getErrorStorage()) std::error_code(make_error_code(ErrorCode)); } - ErrorOr(llvm::error_code EC) : HasError(true) { - new (getErrorStorage()) error_code(EC); + ErrorOr(std::error_code EC) : HasError(true) { + new (getErrorStorage()) std::error_code(EC); } ErrorOr(T Val) : HasError(false) { @@ -162,8 +163,8 @@ public: reference get() { return *getStorage(); } const_reference get() const { return const_cast<ErrorOr<T> >(this)->get(); } - error_code getError() const { - return HasError ? *getErrorStorage() : error_code::success(); + std::error_code getError() const { + return HasError ? *getErrorStorage() : std::error_code(); } pointer operator ->() { @@ -184,7 +185,7 @@ private: } else { // Get other's error. HasError = true; - new (getErrorStorage()) error_code(Other.getError()); + new (getErrorStorage()) std::error_code(Other.getError()); } } @@ -216,7 +217,7 @@ private: } else { // Get other's error. HasError = true; - new (getErrorStorage()) error_code(Other.getError()); + new (getErrorStorage()) std::error_code(Other.getError()); } } @@ -247,28 +248,29 @@ private: return reinterpret_cast<const storage_type*>(TStorage.buffer); } - error_code *getErrorStorage() { + std::error_code *getErrorStorage() { assert(HasError && "Cannot get error when a value exists!"); - return reinterpret_cast<error_code*>(ErrorStorage.buffer); + return reinterpret_cast<std::error_code *>(ErrorStorage.buffer); } - const error_code *getErrorStorage() const { + const std::error_code *getErrorStorage() const { return const_cast<ErrorOr<T> *>(this)->getErrorStorage(); } union { AlignedCharArrayUnion<storage_type> TStorage; - AlignedCharArrayUnion<error_code> ErrorStorage; + AlignedCharArrayUnion<std::error_code> ErrorStorage; }; bool HasError : 1; }; -template<class T, class E> -typename std::enable_if<is_error_code_enum<E>::value || - is_error_condition_enum<E>::value, bool>::type -operator ==(ErrorOr<T> &Err, E Code) { - return error_code(Err) == Code; +template <class T, class E> +typename std::enable_if<std::is_error_code_enum<E>::value || + std::is_error_condition_enum<E>::value, + bool>::type +operator==(ErrorOr<T> &Err, E Code) { + return std::error_code(Err) == Code; } } // end namespace llvm diff --git a/include/llvm/Support/FEnv.h b/include/llvm/Support/FEnv.h deleted file mode 100644 index 8560ee0..0000000 --- a/include/llvm/Support/FEnv.h +++ /dev/null @@ -1,56 +0,0 @@ -//===- 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_SUPPORT_FENV_H -#define LLVM_SUPPORT_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() { -#if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT - 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; -#if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT && HAVE_DECL_FE_INEXACT - 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/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index a8a48fa..0a9a979 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -20,8 +20,6 @@ #include "llvm/Support/FileSystem.h" namespace llvm { -class error_code; - /// FileOutputBuffer - This interface provides simple way to create an in-memory /// buffer which will be written to a file. During the lifetime of these /// objects, the content or existence of the specified file is undefined. That @@ -39,9 +37,9 @@ public: /// Factory method to create an OutputBuffer object which manages a read/write /// buffer of the specified size. When committed, the buffer will be written /// to the file at the specified path. - static error_code create(StringRef FilePath, size_t Size, - std::unique_ptr<FileOutputBuffer> &Result, - unsigned Flags = 0); + static std::error_code create(StringRef FilePath, size_t Size, + std::unique_ptr<FileOutputBuffer> &Result, + unsigned Flags = 0); /// Returns a pointer to the start of the buffer. uint8_t *getBufferStart() { @@ -68,7 +66,7 @@ public: /// is called, the file is deleted in the destructor. The optional parameter /// is used if it turns out you want the file size to be smaller than /// initially requested. - error_code commit(int64_t NewSmallerSize = -1); + std::error_code commit(int64_t NewSmallerSize = -1); /// If this object was previously committed, the destructor just deletes /// this object. If this object was not committed, the destructor diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 806a3e3..556701c 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -33,11 +33,11 @@ #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TimeValue.h" -#include "llvm/Support/system_error.h" #include <ctime> #include <iterator> #include <stack> #include <string> +#include <system_error> #include <tuple> #include <vector> @@ -49,26 +49,18 @@ namespace llvm { namespace sys { namespace fs { -/// An "enum class" enumeration for the file system's view of the type. -struct file_type { - enum Impl { - status_error, - file_not_found, - regular_file, - directory_file, - symlink_file, - block_file, - character_file, - fifo_file, - socket_file, - type_unknown - }; - - file_type(Impl V) : V(V) {} - operator Impl() const { return V; } - -private: - Impl V; +/// An enumeration for the file system's view of the type. +enum class file_type { + status_error, + file_not_found, + regular_file, + directory_file, + symlink_file, + block_file, + character_file, + fifo_file, + socket_file, + type_unknown }; /// space_info - Self explanatory. @@ -142,7 +134,7 @@ public: }; /// file_status - Represents the result of a call to stat and friends. It has -/// a platform specific member to store the result. +/// a platform-specific member to store the result. class file_status { #if defined(LLVM_ON_UNIX) @@ -281,8 +273,8 @@ private: /// /// @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); +/// platform-specific error_code. +std::error_code make_absolute(SmallVectorImpl<char> &path); /// @brief Normalize path separators in \a Path /// @@ -290,7 +282,7 @@ error_code make_absolute(SmallVectorImpl<char> &path); /// This is particularly useful when cross-compiling Windows on Linux, but is /// safe to invoke on Windows, which accepts both characters as a path /// separator. -error_code normalize_separators(SmallVectorImpl<char> &Path); +std::error_code normalize_separators(SmallVectorImpl<char> &Path); /// @brief Create all the non-existent directories in path. /// @@ -298,7 +290,8 @@ error_code normalize_separators(SmallVectorImpl<char> &Path); /// @returns errc::success if is_directory(path), otherwise a platform /// specific error_code. If IgnoreExisting is false, also returns /// error if the directory already existed. -error_code create_directories(const Twine &path, bool IgnoreExisting = true); +std::error_code create_directories(const Twine &path, + bool IgnoreExisting = true); /// @brief Create the directory in path. /// @@ -306,7 +299,7 @@ error_code create_directories(const Twine &path, bool IgnoreExisting = true); /// @returns errc::success if is_directory(path), otherwise a platform /// specific error_code. If IgnoreExisting is false, also returns /// error if the directory already existed. -error_code create_directory(const Twine &path, bool IgnoreExisting = true); +std::error_code create_directory(const Twine &path, bool IgnoreExisting = true); /// @brief Create a link from \a from to \a to. /// @@ -319,36 +312,42 @@ error_code create_directory(const Twine &path, bool IgnoreExisting = true); /// @param from The path to hard link from. This is created. /// @returns errc::success if the link was created, otherwise a platform /// specific error_code. -error_code create_link(const Twine &to, const Twine &from); +std::error_code create_link(const Twine &to, const Twine &from); /// @brief Get the current path. /// /// @param result Holds the current path on return. /// @returns errc::success if the current path has been stored in result, -/// otherwise a platform specific error_code. -error_code current_path(SmallVectorImpl<char> &result); +/// otherwise a platform-specific error_code. +std::error_code current_path(SmallVectorImpl<char> &result); /// @brief Remove path. Equivalent to POSIX remove(). /// /// @param path Input path. /// @returns errc::success if path has been removed or didn't exist, otherwise a -/// platform specific error code. If IgnoreNonExisting is false, also +/// platform-specific error code. If IgnoreNonExisting is false, also /// returns error if the file didn't exist. -error_code remove(const Twine &path, bool IgnoreNonExisting = true); +std::error_code remove(const Twine &path, bool IgnoreNonExisting = true); /// @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); +std::error_code rename(const Twine &from, const Twine &to); + +/// @brief Copy the contents of \a From to \a To. +/// +/// @param From The path to copy from. +/// @param To The path to copy to. This is created. +std::error_code copy_file(const Twine &From, const Twine &To); /// @brief Resize path to size. File is resized as if by POSIX truncate(). /// /// @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); +/// platform-specific error_code. +std::error_code resize_file(const Twine &path, uint64_t size); /// @} /// @name Physical Observers @@ -367,8 +366,8 @@ bool exists(file_status status); /// @param result Set to true if the file represented by status exists, false if /// it does not. Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code exists(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code exists(const Twine &path, bool &result); /// @brief Simpler version of exists for clients that don't need to /// differentiate between an error and false. @@ -409,8 +408,8 @@ bool equivalent(file_status A, file_status B); /// @param result Set to true if stat(A) and stat(B) have the same device and /// inode (or equivalent). /// @returns 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); +/// platform-specific error_code. +std::error_code equivalent(const Twine &A, const Twine &B, bool &result); /// @brief Simpler version of equivalent for clients that don't need to /// differentiate between an error and false. @@ -431,8 +430,8 @@ bool is_directory(file_status status); /// @param result Set to true if \a path is a directory, false if it is not. /// Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_directory(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code is_directory(const Twine &path, bool &result); /// @brief Simpler version of is_directory for clients that don't need to /// differentiate between an error and false. @@ -453,8 +452,8 @@ bool is_regular_file(file_status status); /// @param result Set to true if \a path is a regular file, false if it is not. /// Undefined otherwise. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_regular_file(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code is_regular_file(const Twine &path, bool &result); /// @brief Simpler version of is_regular_file for clients that don't need to /// differentiate between an error and false. @@ -479,41 +478,41 @@ bool is_other(file_status status); /// @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. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_other(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code is_other(const Twine &path, bool &result); /// @brief Get file status as if by POSIX stat(). /// /// @param path Input path. /// @param result Set to the file status. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code status(const Twine &path, file_status &result); +/// platform-specific error_code. +std::error_code status(const Twine &path, file_status &result); /// @brief A version for when a file descriptor is already available. -error_code status(int FD, file_status &Result); +std::error_code status(int FD, file_status &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. -inline error_code file_size(const Twine &Path, uint64_t &Result) { +/// platform-specific error_code. +inline std::error_code file_size(const Twine &Path, uint64_t &Result) { file_status Status; - error_code EC = status(Path, Status); + std::error_code EC = status(Path, Status); if (EC) return EC; Result = Status.getSize(); - return error_code::success(); + return std::error_code(); } /// @brief Set the file modification and access time. /// /// @returns errc::success if the file times were successfully set, otherwise a -/// platform specific error_code or errc::not_supported on platforms -/// where the functionality isn't available. -error_code setLastModificationAndAccessTime(int FD, TimeValue Time); +/// platform-specific error_code or errc::function_not_supported on +/// platforms where the functionality isn't available. +std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); /// @brief Is status available? /// @@ -526,8 +525,8 @@ bool status_known(file_status s); /// @param path Input path. /// @param result Set to true if status() != status_error. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code status_known(const Twine &path, bool &result); +/// platform-specific error_code. +std::error_code status_known(const Twine &path, bool &result); /// @brief Create a uniquely named file. /// @@ -549,14 +548,14 @@ error_code status_known(const Twine &path, bool &result); /// @param ResultFD Set to the opened file's file descriptor. /// @param ResultPath Set to the opened file's absolute path. /// @returns errc::success if Result{FD,Path} have been successfully set, -/// otherwise a platform specific error_code. -error_code createUniqueFile(const Twine &Model, int &ResultFD, - SmallVectorImpl<char> &ResultPath, - unsigned Mode = all_read | all_write); +/// otherwise a platform-specific error_code. +std::error_code createUniqueFile(const Twine &Model, int &ResultFD, + SmallVectorImpl<char> &ResultPath, + unsigned Mode = all_read | all_write); /// @brief Simpler version for clients that don't want an open file. -error_code createUniqueFile(const Twine &Model, - SmallVectorImpl<char> &ResultPath); +std::error_code createUniqueFile(const Twine &Model, + SmallVectorImpl<char> &ResultPath); /// @brief Create a file in the system temporary directory. /// @@ -566,16 +565,16 @@ error_code createUniqueFile(const Twine &Model, /// /// This should be used for things like a temporary .s that is removed after /// running the assembler. -error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, - int &ResultFD, - SmallVectorImpl<char> &ResultPath); +std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + int &ResultFD, + SmallVectorImpl<char> &ResultPath); /// @brief Simpler version for clients that don't want an open file. -error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, - SmallVectorImpl<char> &ResultPath); +std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + SmallVectorImpl<char> &ResultPath); -error_code createUniqueDirectory(const Twine &Prefix, - SmallVectorImpl<char> &ResultPath); +std::error_code createUniqueDirectory(const Twine &Prefix, + SmallVectorImpl<char> &ResultPath); enum OpenFlags : unsigned { F_None = 0, @@ -606,31 +605,10 @@ inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { return A; } -error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags, - unsigned Mode = 0666); +std::error_code openFileForWrite(const Twine &Name, int &ResultFD, + OpenFlags Flags, unsigned Mode = 0666); -error_code openFileForRead(const Twine &Name, int &ResultFD); - -/// @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. -/// @returns 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. -/// @returns 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); +std::error_code openFileForRead(const Twine &Name, int &ResultFD); /// @brief Identify the type of a binary file based on how magical it is. file_magic identify_magic(StringRef magic); @@ -640,10 +618,10 @@ file_magic identify_magic(StringRef magic); /// @param path Input path. /// @param result Set to the type of file, or file_magic::unknown. /// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code identify_magic(const Twine &path, file_magic &result); +/// platform-specific error_code. +std::error_code identify_magic(const Twine &path, file_magic &result); -error_code getUniqueID(const Twine Path, UniqueID &Result); +std::error_code getUniqueID(const Twine Path, UniqueID &Result); /// This class represents a memory mapped file. It is based on /// boost::iostreams::mapped_file. @@ -660,7 +638,7 @@ public: }; private: - /// Platform specific mapping state. + /// Platform-specific mapping state. mapmode Mode; uint64_t Size; void *Mapping; @@ -670,7 +648,7 @@ private: void *FileMappingHandle; #endif - error_code init(int FD, bool CloseFD, uint64_t Offset); + std::error_code init(int FD, bool CloseFD, uint64_t Offset); public: typedef char char_type; @@ -692,21 +670,14 @@ public: /// mapped_file_region::alignment(). /// \param ec This is set to errc::success if the map was constructed /// successfully. Otherwise it is set to a platform dependent error. - mapped_file_region(const Twine &path, - mapmode mode, - uint64_t length, - uint64_t offset, - error_code &ec); + mapped_file_region(const Twine &path, mapmode mode, uint64_t length, + uint64_t offset, std::error_code &ec); /// \param fd An open file descriptor to map. mapped_file_region takes /// ownership if closefd is true. It must have been opended in the correct /// mode. - mapped_file_region(int fd, - bool closefd, - mapmode mode, - uint64_t length, - uint64_t offset, - error_code &ec); + mapped_file_region(int fd, bool closefd, mapmode mode, uint64_t length, + uint64_t offset, std::error_code &ec); ~mapped_file_region(); @@ -722,30 +693,6 @@ public: static int alignment(); }; -/// @brief Memory maps the contents of a file -/// -/// @param path Path to file to map. -/// @param file_offset Byte offset in file where mapping should begin. -/// @param size Byte length of range of the file to map. -/// @param map_writable If true, the file will be mapped in r/w such -/// that changes to the mapped buffer will be flushed back -/// to the file. If false, the file will be mapped read-only -/// and the buffer will be read-only. -/// @param result Set to the start address of the mapped buffer. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, - bool map_writable, void *&result); - - -/// @brief Memory unmaps the contents of a file -/// -/// @param base Pointer to the start of the buffer. -/// @param size Byte length of the range to unmmap. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code unmap_file_pages(void *base, size_t size); - /// 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. @@ -777,7 +724,7 @@ public: void replace_filename(const Twine &filename, file_status st = file_status()); const std::string &path() const { return Path; } - error_code status(file_status &result) const; + std::error_code 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); } @@ -790,9 +737,9 @@ public: namespace detail { struct DirIterState; - error_code directory_iterator_construct(DirIterState&, StringRef); - error_code directory_iterator_increment(DirIterState&); - error_code directory_iterator_destruct(DirIterState&); + std::error_code directory_iterator_construct(DirIterState &, StringRef); + std::error_code directory_iterator_increment(DirIterState &); + std::error_code directory_iterator_destruct(DirIterState &); /// DirIterState - Keeps state for the directory_iterator. It is reference /// counted in order to preserve InputIterator semantics on copy. @@ -816,14 +763,14 @@ class directory_iterator { IntrusiveRefCntPtr<detail::DirIterState> State; public: - explicit directory_iterator(const Twine &path, error_code &ec) { + explicit directory_iterator(const Twine &path, std::error_code &ec) { State = new detail::DirIterState; SmallString<128> path_storage; ec = detail::directory_iterator_construct(*State, path.toStringRef(path_storage)); } - explicit directory_iterator(const directory_entry &de, error_code &ec) { + explicit directory_iterator(const directory_entry &de, std::error_code &ec) { State = new detail::DirIterState; ec = detail::directory_iterator_construct(*State, de.path()); } @@ -832,7 +779,7 @@ public: directory_iterator() : State(nullptr) {} // No operator++ because we need error_code. - directory_iterator &increment(error_code &ec) { + directory_iterator &increment(std::error_code &ec) { ec = directory_iterator_increment(*State); return *this; } @@ -878,14 +825,14 @@ class recursive_directory_iterator { public: recursive_directory_iterator() {} - explicit recursive_directory_iterator(const Twine &path, error_code &ec) - : State(new detail::RecDirIterState) { + explicit recursive_directory_iterator(const Twine &path, std::error_code &ec) + : State(new detail::RecDirIterState) { State->Stack.push(directory_iterator(path, ec)); if (State->Stack.top() == directory_iterator()) State.reset(); } // No operator++ because we need error_code. - recursive_directory_iterator &increment(error_code &ec) { + recursive_directory_iterator &increment(std::error_code &ec) { const directory_iterator end_itr; if (State->HasNoPushRequest) @@ -934,7 +881,7 @@ public: assert(State->Level > 0 && "Cannot pop an iterator with level < 1"); const directory_iterator end_itr; - error_code ec; + std::error_code ec; do { if (ec) report_fatal_error("Error incrementing directory iterator."); diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index a62801f..b713cc7 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -36,23 +36,23 @@ namespace llvm { -/// format_object_base - This is a helper class used for handling formatted -/// output. It is the abstract base class of a templated derived class. +/// This is a helper class used for handling formatted output. It is the +/// abstract base class of a templated derived class. class format_object_base { protected: const char *Fmt; virtual void home(); // Out of line virtual method. - /// snprint - Call snprintf() for this object, on the given buffer and size. + /// Call snprintf() for this object, on the given buffer and size. virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; public: format_object_base(const char *fmt) : Fmt(fmt) {} virtual ~format_object_base() {} - /// print - Format the object into the specified buffer. On success, this - /// returns the length of the formatted string. If the buffer is too small, - /// this returns a length to retry with, which will be larger than BufferSize. + /// Format the object into the specified buffer. On success, this returns + /// the length of the formatted string. If the buffer is too small, this + /// returns a length to retry with, which will be larger than BufferSize. unsigned print(char *Buffer, unsigned BufferSize) const { assert(BufferSize && "Invalid buffer size!"); @@ -61,21 +61,23 @@ public: // VC++ and old GlibC return negative on overflow, just double the size. if (N < 0) - return BufferSize*2; + return BufferSize * 2; - // Other impls yield number of bytes needed, not including the final '\0'. + // Other implementations yield number of bytes needed, not including the + // final '\0'. if (unsigned(N) >= BufferSize) - return N+1; + return N + 1; // Otherwise N is the length of output (not including the final '\0'). return N; } }; -/// format_object1 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. +/// These are templated helper classes used by the format function that +/// capture the object to be formated and the format string. When actually +/// printed, this synthesizes the string into a temporary buffer provided and +/// returns whether or not it is big enough. + template <typename T> class format_object1 : public format_object_base { T Val; @@ -89,10 +91,6 @@ public: } }; -/// format_object2 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template <typename T1, typename T2> class format_object2 : public format_object_base { T1 Val1; @@ -107,10 +105,6 @@ public: } }; -/// format_object3 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template <typename T1, typename T2, typename T3> class format_object3 : public format_object_base { T1 Val1; @@ -126,10 +120,6 @@ public: } }; -/// format_object4 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template <typename T1, typename T2, typename T3, typename T4> class format_object4 : public format_object_base { T1 Val1; @@ -147,10 +137,6 @@ public: } }; -/// format_object5 - This is a templated helper class used by the format -/// function that captures the object to be formated and the format string. When -/// actually printed, this synthesizes the string into a temporary buffer -/// provided and returns whether or not it is big enough. template <typename T1, typename T2, typename T3, typename T4, typename T5> class format_object5 : public format_object_base { T1 Val1; @@ -170,47 +156,52 @@ public: } }; -/// This is a helper function that is used to produce formatted output. +template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6> +class format_object6 : public format_object_base { + T1 Val1; + T2 Val2; + T3 Val3; + T4 Val4; + T5 Val5; + T6 Val6; +public: + format_object6(const char *Fmt, const T1 &Val1, const T2 &Val2, + const T3 &Val3, const T4 &Val4, const T5 &Val5, const T6 &Val6) + : format_object_base(Fmt), Val1(Val1), Val2(Val2), Val3(Val3), Val4(Val4), + Val5(Val5), Val6(Val6) { } + + int snprint(char *Buffer, unsigned BufferSize) const override { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5, Val6); + } +}; + +/// These are helper functions used to produce formatted output. They use +/// template type deduction to construct the appropriate instance of the +/// format_object class to simplify their construction. /// /// This is typically used like: /// \code /// OS << format("%0.4f", myfloat) << '\n'; /// \endcode + template <typename T> inline format_object1<T> format(const char *Fmt, const T &Val) { return format_object1<T>(Fmt, Val); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template <typename T1, typename T2> inline format_object2<T1, T2> format(const char *Fmt, const T1 &Val1, const T2 &Val2) { return format_object2<T1, T2>(Fmt, Val1, Val2); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template <typename T1, typename T2, typename T3> inline format_object3<T1, T2, T3> format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3) { return format_object3<T1, T2, T3>(Fmt, Val1, Val2, Val3); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template <typename T1, typename T2, typename T3, typename T4> inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, @@ -218,12 +209,6 @@ inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4); } -/// This is a helper function that is used to produce formatted output. -/// -/// This is typically used like: -/// \code -/// OS << format("%0.4f", myfloat) << '\n'; -/// \endcode template <typename T1, typename T2, typename T3, typename T4, typename T5> inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1, const T2 &Val2, const T3 &Val3, @@ -231,6 +216,15 @@ inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1, return format_object5<T1, T2, T3, T4, T5>(Fmt, Val1, Val2, Val3, Val4, Val5); } +template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6> +inline format_object6<T1, T2, T3, T4, T5, T6> +format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, + const T4 &Val4, const T5 &Val5, const T6 &Val6) { + return format_object6<T1, T2, T3, T4, T5, T6>(Fmt, Val1, Val2, Val3, Val4, + Val5, Val6); +} + } // end namespace llvm #endif diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h index e344220..876ab6e 100644 --- a/include/llvm/Support/GenericDomTree.h +++ b/include/llvm/Support/GenericDomTree.h @@ -330,6 +330,10 @@ public: return DomTreeNodes.lookup(BB); } + inline DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { + return getNode(BB); + } + /// getRootNode - This returns the entry node for the CFG of the function. If /// this tree represents the post-dominance relations for a function, however, /// this root may be a node with the block == NULL. This is the case when diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index 539673a..2f02aa7 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -50,7 +50,7 @@ namespace GraphProgram { }; } -void DisplayGraph(StringRef Filename, bool wait = true, +bool DisplayGraph(StringRef Filename, bool wait = true, GraphProgram::Name program = GraphProgram::DOT); template<typename GraphType> diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index 523a781..61c65da 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -12,11 +12,10 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/system_error.h" +#include <system_error> #include <utility> // for std::pair namespace llvm { - /// \brief Class that manages the creation of a lock file to aid /// implicit coordination between different processes. /// @@ -56,7 +55,7 @@ private: SmallString<128> UniqueLockFileName; Optional<std::pair<std::string, int> > Owner; - Optional<error_code> Error; + Optional<std::error_code> Error; LockFileManager(const LockFileManager &) LLVM_DELETED_FUNCTION; LockFileManager &operator=(const LockFileManager &) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index 2a0fc7b..bd4dc2f 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -360,11 +360,28 @@ namespace llvm { enum { // Constant masks for the "n_desc" field in llvm::MachO::nlist and // llvm::MachO::nlist_64 + // The low 3 bits are the for the REFERENCE_TYPE. + REFERENCE_TYPE = 0x7, + REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0, + REFERENCE_FLAG_UNDEFINED_LAZY = 1, + REFERENCE_FLAG_DEFINED = 2, + REFERENCE_FLAG_PRIVATE_DEFINED = 3, + REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4, + REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5, + // Flag bits (some overlap with the library ordinal bits). N_ARM_THUMB_DEF = 0x0008u, + REFERENCED_DYNAMICALLY = 0x0010u, N_NO_DEAD_STRIP = 0x0020u, N_WEAK_REF = 0x0040u, N_WEAK_DEF = 0x0080u, - N_SYMBOL_RESOLVER = 0x0100u + N_SYMBOL_RESOLVER = 0x0100u, + N_ALT_ENTRY = 0x0200u, + // For undefined symbols coming from libraries, see GET_LIBRARY_ORDINAL() + // as these are in the top 8 bits. + SELF_LIBRARY_ORDINAL = 0x0, + MAX_LIBRARY_ORDINAL = 0xfd, + DYNAMIC_LOOKUP_ORDINAL = 0xfe, + EXECUTABLE_ORDINAL = 0xff }; enum StabType { @@ -998,8 +1015,8 @@ namespace llvm { enum : uint32_t { // Capability bits used in the definition of cpusubtype. - CPU_SUB_TYPE_MASK = 0xff000000, // Mask for architecture bits - CPU_SUB_TYPE_LIB64 = 0x80000000, // 64 bit libraries + CPU_SUBTYPE_MASK = 0xff000000, // Mask for architecture bits + CPU_SUBTYPE_LIB64 = 0x80000000, // 64 bit libraries // Special CPU subtype constants. CPU_SUBTYPE_MULTIPLE = ~0u diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index 1bb8cea..d8fbfeb 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -103,9 +103,6 @@ void llvm_shutdown(); /// llvm_shutdown() when it is destroyed. struct llvm_shutdown_obj { llvm_shutdown_obj() { } - explicit llvm_shutdown_obj(bool multithreaded) { - if (multithreaded) llvm_start_multithreaded(); - } ~llvm_shutdown_obj() { llvm_shutdown(); } }; diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index f1f7b4f..0abba62 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -230,6 +230,9 @@ static const unsigned char BitReverseTable256[256] = { #define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) #define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) R6(0), R6(2), R6(1), R6(3) +#undef R2 +#undef R4 +#undef R6 }; /// \brief Reverse the bits in \p Val. @@ -258,6 +261,12 @@ inline uint32_t Lo_32(uint64_t Value) { return static_cast<uint32_t>(Value); } +/// Make_64 - This functions makes a 64-bit integer from a high / low pair of +/// 32-bit integers. +inline uint64_t Make_64(uint32_t High, uint32_t Low) { + return ((uint64_t)High << 32) | (uint64_t)Low; +} + /// isInt - Checks if an integer fits into the given bit width. template<unsigned N> inline bool isInt(int64_t x) { diff --git a/include/llvm/Support/Memory.h b/include/llvm/Support/Memory.h index 0996adb..b4305cb 100644 --- a/include/llvm/Support/Memory.h +++ b/include/llvm/Support/Memory.h @@ -15,8 +15,8 @@ #define LLVM_SUPPORT_MEMORY_H #include "llvm/Support/DataTypes.h" -#include "llvm/Support/system_error.h" #include <string> +#include <system_error> namespace llvm { namespace sys { @@ -77,7 +77,7 @@ namespace sys { static MemoryBlock allocateMappedMemory(size_t NumBytes, const MemoryBlock *const NearBlock, unsigned Flags, - error_code &EC); + std::error_code &EC); /// This method releases a block of memory that was allocated with the /// allocateMappedMemory method. It should not be used to release any @@ -88,7 +88,7 @@ namespace sys { /// describing the failure if an error occurred. /// /// @brief Release mapped memory. - static error_code releaseMappedMemory(MemoryBlock &Block); + static std::error_code releaseMappedMemory(MemoryBlock &Block); /// This method sets the protection flags for a block of memory to the /// state specified by /p Flags. The behavior is not specified if the @@ -105,8 +105,8 @@ namespace sys { /// describing the failure if an error occurred. /// /// @brief Set memory protection state. - static error_code protectMappedMemory(const MemoryBlock &Block, - unsigned Flags); + static std::error_code protectMappedMemory(const MemoryBlock &Block, + unsigned Flags); /// This method allocates a block of Read/Write/Execute memory that is /// suitable for executing dynamically generated code (e.g. JIT). An diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index 5810c47..147be47 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -19,12 +19,11 @@ #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorOr.h" #include <memory> +#include <system_error> namespace llvm { - -class error_code; - /// 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 @@ -62,19 +61,17 @@ public: return "Unknown buffer"; } - /// getFile - Open the specified file as a MemoryBuffer, returning a new - /// 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. + /// Open the specified file as a MemoryBuffer, returning a new 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. /// /// \param IsVolatileSize Set to true to indicate that the file size may be /// changing, e.g. when libclang tries to parse while the user is /// editing/updating the file. - static error_code getFile(Twine Filename, - std::unique_ptr<MemoryBuffer> &Result, - int64_t FileSize = -1, - bool RequiresNullTerminator = true, - bool IsVolatileSize = false); + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getFile(Twine Filename, int64_t FileSize = -1, + bool RequiresNullTerminator = true, bool IsVolatileSize = false); /// Given an already-open file descriptor, map some slice of it into a /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. @@ -83,10 +80,9 @@ public: /// \param IsVolatileSize Set to true to indicate that the file size may be /// changing, e.g. when libclang tries to parse while the user is /// editing/updating the file. - static error_code getOpenFileSlice(int FD, const char *Filename, - std::unique_ptr<MemoryBuffer> &Result, - uint64_t MapSize, int64_t Offset, - bool IsVolatileSize = false); + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getOpenFileSlice(int FD, const char *Filename, uint64_t MapSize, + int64_t Offset, bool IsVolatileSize = false); /// Given an already-open file descriptor, read the file and return a /// MemoryBuffer. @@ -94,11 +90,9 @@ public: /// \param IsVolatileSize Set to true to indicate that the file size may be /// changing, e.g. when libclang tries to parse while the user is /// editing/updating the file. - static error_code getOpenFile(int FD, const char *Filename, - std::unique_ptr<MemoryBuffer> &Result, - uint64_t FileSize, - bool RequiresNullTerminator = true, - bool IsVolatileSize = false); + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getOpenFile(int FD, const char *Filename, uint64_t FileSize, + bool RequiresNullTerminator = true, bool IsVolatileSize = false); /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note /// that InputData must be null terminated if RequiresNullTerminator is true. @@ -125,17 +119,13 @@ public: static MemoryBuffer *getNewUninitMemBuffer(size_t Size, StringRef BufferName = ""); - /// getSTDIN - Read all of stdin into a file buffer, and return it. - /// If an error occurs, this returns null and sets ec. - static error_code getSTDIN(std::unique_ptr<MemoryBuffer> &Result); - + /// Read all of stdin into a file buffer, and return it. + static ErrorOr<std::unique_ptr<MemoryBuffer>> getSTDIN(); - /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin - /// if the Filename is "-". If an error occurs, this returns null and sets - /// ec. - static error_code getFileOrSTDIN(StringRef Filename, - std::unique_ptr<MemoryBuffer> &Result, - int64_t FileSize = -1); + /// Open the specified file as a MemoryBuffer, or open stdin if the Filename + /// is "-". + static ErrorOr<std::unique_ptr<MemoryBuffer>> + getFileOrSTDIN(StringRef Filename, int64_t FileSize = -1); //===--------------------------------------------------------------------===// // Provided for performance analysis. diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index 7f6441e..30973de 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -31,7 +31,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/TimeValue.h" -#include "llvm/Support/system_error.h" +#include <system_error> namespace llvm { class StringRef; @@ -171,10 +171,17 @@ public: // string. \arg Name is assumed to be in UTF-8 encoding too. static Optional<std::string> GetEnv(StringRef name); + /// This function searches for an existing file in the list of directories + /// in a PATH like environment variable, and returns the first file found, + /// according to the order of the entries in the PATH like environment + /// variable. + static Optional<std::string> FindInEnvPath(const std::string& EnvName, + const std::string& FileName); + /// This function returns a SmallVector containing the arguments passed from /// the operating system to the program. This function expects to be handed /// the vector passed in from main. - static error_code + static std::error_code GetArgumentVector(SmallVectorImpl<const char *> &Args, ArrayRef<const char *> ArgsFromMain, SpecificBumpPtrAllocator<char> &ArgAllocator); diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 9160b7d..51279a9 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -16,10 +16,9 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Path.h" -#include "llvm/Support/system_error.h" +#include <system_error> namespace llvm { -class error_code; namespace sys { /// This is the OS-specific separator for PATH like environment variables: @@ -67,8 +66,8 @@ struct ProcessInfo { // These functions change the specified standard stream (stdin or stdout) to // binary mode. They return errc::success if the specified stream // was changed. Otherwise a platform dependent error is returned. - error_code ChangeStdinToBinary(); - error_code ChangeStdoutToBinary(); + std::error_code ChangeStdinToBinary(); + std::error_code ChangeStdoutToBinary(); /// This function executes the program using the arguments provided. The /// invoked program will inherit the stdin, stdout, and stderr file diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h new file mode 100644 index 0000000..cadc713 --- /dev/null +++ b/include/llvm/Support/RandomNumberGenerator.h @@ -0,0 +1,57 @@ +//==- llvm/Support/RandomNumberGenerator.h - RNG for diversity ---*- 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 an abstraction for random number generation (RNG). +// Note that the current implementation is not cryptographically secure +// as it uses the C++11 <random> facilities. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RANDOMNUMBERGENERATOR_H_ +#define LLVM_SUPPORT_RANDOMNUMBERGENERATOR_H_ + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" // Needed for uint64_t on Windows. +#include <random> + +namespace llvm { + +/// A random number generator. +/// Instances of this class should not be shared across threads. +class RandomNumberGenerator { +public: + /// Seeds and salts the underlying RNG engine. The salt of type StringRef + /// is passed into the constructor. The seed can be set on the command + /// line via -rng-seed=<uint64>. + /// The reason for the salt is to ensure different random streams even if + /// the same seed is used for multiple invocations of the compiler. + /// A good salt value should add additional entropy and be constant across + /// different machines (i.e., no paths) to allow for reproducible builds. + /// An instance of this class can be retrieved from the current Module. + /// \see Module::getRNG + RandomNumberGenerator(StringRef Salt); + + /// Returns a random number in the range [0, Max). + uint64_t next(uint64_t Max); + +private: + // 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000 + // http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine + std::mt19937_64 Generator; + + // Noncopyable. + RandomNumberGenerator(const RandomNumberGenerator &other) + LLVM_DELETED_FUNCTION; + RandomNumberGenerator & + operator=(const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION; +}; +} + +#endif diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h new file mode 100644 index 0000000..2bd7e74 --- /dev/null +++ b/include/llvm/Support/ScaledNumber.h @@ -0,0 +1,897 @@ +//===- llvm/Support/ScaledNumber.h - Support for scaled numbers -*- 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 functions (and a class) useful for working with scaled +// numbers -- in particular, pairs of integers where one represents digits and +// another represents a scale. The functions are helpers and live in the +// namespace ScaledNumbers. The class ScaledNumber is useful for modelling +// certain cost metrics that need simple, integer-like semantics that are easy +// to reason about. +// +// These might remind you of soft-floats. If you want one of those, you're in +// the wrong place. Look at include/llvm/ADT/APFloat.h instead. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SCALEDNUMBER_H +#define LLVM_SUPPORT_SCALEDNUMBER_H + +#include "llvm/Support/MathExtras.h" + +#include <algorithm> +#include <cstdint> +#include <limits> +#include <string> +#include <tuple> +#include <utility> + +namespace llvm { +namespace ScaledNumbers { + +/// \brief Maximum scale; same as APFloat for easy debug printing. +const int32_t MaxScale = 16383; + +/// \brief Maximum scale; same as APFloat for easy debug printing. +const int32_t MinScale = -16382; + +/// \brief Get the width of a number. +template <class DigitsT> inline int getWidth() { return sizeof(DigitsT) * 8; } + +/// \brief Conditionally round up a scaled number. +/// +/// Given \c Digits and \c Scale, round up iff \c ShouldRound is \c true. +/// Always returns \c Scale unless there's an overflow, in which case it +/// returns \c 1+Scale. +/// +/// \pre adding 1 to \c Scale will not overflow INT16_MAX. +template <class DigitsT> +inline std::pair<DigitsT, int16_t> getRounded(DigitsT Digits, int16_t Scale, + bool ShouldRound) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + if (ShouldRound) + if (!++Digits) + // Overflow. + return std::make_pair(DigitsT(1) << (getWidth<DigitsT>() - 1), Scale + 1); + return std::make_pair(Digits, Scale); +} + +/// \brief Convenience helper for 32-bit rounding. +inline std::pair<uint32_t, int16_t> getRounded32(uint32_t Digits, int16_t Scale, + bool ShouldRound) { + return getRounded(Digits, Scale, ShouldRound); +} + +/// \brief Convenience helper for 64-bit rounding. +inline std::pair<uint64_t, int16_t> getRounded64(uint64_t Digits, int16_t Scale, + bool ShouldRound) { + return getRounded(Digits, Scale, ShouldRound); +} + +/// \brief Adjust a 64-bit scaled number down to the appropriate width. +/// +/// \pre Adding 64 to \c Scale will not overflow INT16_MAX. +template <class DigitsT> +inline std::pair<DigitsT, int16_t> getAdjusted(uint64_t Digits, + int16_t Scale = 0) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + const int Width = getWidth<DigitsT>(); + if (Width == 64 || Digits <= std::numeric_limits<DigitsT>::max()) + return std::make_pair(Digits, Scale); + + // Shift right and round. + int Shift = 64 - Width - countLeadingZeros(Digits); + return getRounded<DigitsT>(Digits >> Shift, Scale + Shift, + Digits & (UINT64_C(1) << (Shift - 1))); +} + +/// \brief Convenience helper for adjusting to 32 bits. +inline std::pair<uint32_t, int16_t> getAdjusted32(uint64_t Digits, + int16_t Scale = 0) { + return getAdjusted<uint32_t>(Digits, Scale); +} + +/// \brief Convenience helper for adjusting to 64 bits. +inline std::pair<uint64_t, int16_t> getAdjusted64(uint64_t Digits, + int16_t Scale = 0) { + return getAdjusted<uint64_t>(Digits, Scale); +} + +/// \brief Multiply two 64-bit integers to create a 64-bit scaled number. +/// +/// Implemented with four 64-bit integer multiplies. +std::pair<uint64_t, int16_t> multiply64(uint64_t LHS, uint64_t RHS); + +/// \brief Multiply two 32-bit integers to create a 32-bit scaled number. +/// +/// Implemented with one 64-bit integer multiply. +template <class DigitsT> +inline std::pair<DigitsT, int16_t> getProduct(DigitsT LHS, DigitsT RHS) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + if (getWidth<DigitsT>() <= 32 || (LHS <= UINT32_MAX && RHS <= UINT32_MAX)) + return getAdjusted<DigitsT>(uint64_t(LHS) * RHS); + + return multiply64(LHS, RHS); +} + +/// \brief Convenience helper for 32-bit product. +inline std::pair<uint32_t, int16_t> getProduct32(uint32_t LHS, uint32_t RHS) { + return getProduct(LHS, RHS); +} + +/// \brief Convenience helper for 64-bit product. +inline std::pair<uint64_t, int16_t> getProduct64(uint64_t LHS, uint64_t RHS) { + return getProduct(LHS, RHS); +} + +/// \brief Divide two 64-bit integers to create a 64-bit scaled number. +/// +/// Implemented with long division. +/// +/// \pre \c Dividend and \c Divisor are non-zero. +std::pair<uint64_t, int16_t> divide64(uint64_t Dividend, uint64_t Divisor); + +/// \brief Divide two 32-bit integers to create a 32-bit scaled number. +/// +/// Implemented with one 64-bit integer divide/remainder pair. +/// +/// \pre \c Dividend and \c Divisor are non-zero. +std::pair<uint32_t, int16_t> divide32(uint32_t Dividend, uint32_t Divisor); + +/// \brief Divide two 32-bit numbers to create a 32-bit scaled number. +/// +/// Implemented with one 64-bit integer divide/remainder pair. +/// +/// Returns \c (DigitsT_MAX, MaxScale) for divide-by-zero (0 for 0/0). +template <class DigitsT> +std::pair<DigitsT, int16_t> getQuotient(DigitsT Dividend, DigitsT Divisor) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + static_assert(sizeof(DigitsT) == 4 || sizeof(DigitsT) == 8, + "expected 32-bit or 64-bit digits"); + + // Check for zero. + if (!Dividend) + return std::make_pair(0, 0); + if (!Divisor) + return std::make_pair(std::numeric_limits<DigitsT>::max(), MaxScale); + + if (getWidth<DigitsT>() == 64) + return divide64(Dividend, Divisor); + return divide32(Dividend, Divisor); +} + +/// \brief Convenience helper for 32-bit quotient. +inline std::pair<uint32_t, int16_t> getQuotient32(uint32_t Dividend, + uint32_t Divisor) { + return getQuotient(Dividend, Divisor); +} + +/// \brief Convenience helper for 64-bit quotient. +inline std::pair<uint64_t, int16_t> getQuotient64(uint64_t Dividend, + uint64_t Divisor) { + return getQuotient(Dividend, Divisor); +} + +/// \brief Implementation of getLg() and friends. +/// +/// Returns the rounded lg of \c Digits*2^Scale and an int specifying whether +/// this was rounded up (1), down (-1), or exact (0). +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template <class DigitsT> +inline std::pair<int32_t, int> getLgImpl(DigitsT Digits, int16_t Scale) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + if (!Digits) + return std::make_pair(INT32_MIN, 0); + + // Get the floor of the lg of Digits. + int32_t LocalFloor = sizeof(Digits) * 8 - countLeadingZeros(Digits) - 1; + + // Get the actual floor. + int32_t Floor = Scale + LocalFloor; + if (Digits == UINT64_C(1) << LocalFloor) + return std::make_pair(Floor, 0); + + // Round based on the next digit. + assert(LocalFloor >= 1); + bool Round = Digits & UINT64_C(1) << (LocalFloor - 1); + return std::make_pair(Floor + Round, Round ? 1 : -1); +} + +/// \brief Get the lg (rounded) of a scaled number. +/// +/// Get the lg of \c Digits*2^Scale. +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template <class DigitsT> int32_t getLg(DigitsT Digits, int16_t Scale) { + return getLgImpl(Digits, Scale).first; +} + +/// \brief Get the lg floor of a scaled number. +/// +/// Get the floor of the lg of \c Digits*2^Scale. +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template <class DigitsT> int32_t getLgFloor(DigitsT Digits, int16_t Scale) { + auto Lg = getLgImpl(Digits, Scale); + return Lg.first - (Lg.second > 0); +} + +/// \brief Get the lg ceiling of a scaled number. +/// +/// Get the ceiling of the lg of \c Digits*2^Scale. +/// +/// Returns \c INT32_MIN when \c Digits is zero. +template <class DigitsT> int32_t getLgCeiling(DigitsT Digits, int16_t Scale) { + auto Lg = getLgImpl(Digits, Scale); + return Lg.first + (Lg.second < 0); +} + +/// \brief Implementation for comparing scaled numbers. +/// +/// Compare two 64-bit numbers with different scales. Given that the scale of +/// \c L is higher than that of \c R by \c ScaleDiff, compare them. Return -1, +/// 1, and 0 for less than, greater than, and equal, respectively. +/// +/// \pre 0 <= ScaleDiff < 64. +int compareImpl(uint64_t L, uint64_t R, int ScaleDiff); + +/// \brief Compare two scaled numbers. +/// +/// Compare two scaled numbers. Returns 0 for equal, -1 for less than, and 1 +/// for greater than. +template <class DigitsT> +int compare(DigitsT LDigits, int16_t LScale, DigitsT RDigits, int16_t RScale) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + // Check for zero. + if (!LDigits) + return RDigits ? -1 : 0; + if (!RDigits) + return 1; + + // Check for the scale. Use getLgFloor to be sure that the scale difference + // is always lower than 64. + int32_t lgL = getLgFloor(LDigits, LScale), lgR = getLgFloor(RDigits, RScale); + if (lgL != lgR) + return lgL < lgR ? -1 : 1; + + // Compare digits. + if (LScale < RScale) + return compareImpl(LDigits, RDigits, RScale - LScale); + + return -compareImpl(RDigits, LDigits, LScale - RScale); +} + +/// \brief Match scales of two numbers. +/// +/// Given two scaled numbers, match up their scales. Change the digits and +/// scales in place. Shift the digits as necessary to form equivalent numbers, +/// losing precision only when necessary. +/// +/// If the output value of \c LDigits (\c RDigits) is \c 0, the output value of +/// \c LScale (\c RScale) is unspecified. +/// +/// As a convenience, returns the matching scale. If the output value of one +/// number is zero, returns the scale of the other. If both are zero, which +/// scale is returned is unspecifed. +template <class DigitsT> +int16_t matchScales(DigitsT &LDigits, int16_t &LScale, DigitsT &RDigits, + int16_t &RScale) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + if (LScale < RScale) + // Swap arguments. + return matchScales(RDigits, RScale, LDigits, LScale); + if (!LDigits) + return RScale; + if (!RDigits || LScale == RScale) + return LScale; + + // Now LScale > RScale. Get the difference. + int32_t ScaleDiff = int32_t(LScale) - RScale; + if (ScaleDiff >= 2 * getWidth<DigitsT>()) { + // Don't bother shifting. RDigits will get zero-ed out anyway. + RDigits = 0; + return LScale; + } + + // Shift LDigits left as much as possible, then shift RDigits right. + int32_t ShiftL = std::min<int32_t>(countLeadingZeros(LDigits), ScaleDiff); + assert(ShiftL < getWidth<DigitsT>() && "can't shift more than width"); + + int32_t ShiftR = ScaleDiff - ShiftL; + if (ShiftR >= getWidth<DigitsT>()) { + // Don't bother shifting. RDigits will get zero-ed out anyway. + RDigits = 0; + return LScale; + } + + LDigits <<= ShiftL; + RDigits >>= ShiftR; + + LScale -= ShiftL; + RScale += ShiftR; + assert(LScale == RScale && "scales should match"); + return LScale; +} + +/// \brief Get the sum of two scaled numbers. +/// +/// Get the sum of two scaled numbers with as much precision as possible. +/// +/// \pre Adding 1 to \c LScale (or \c RScale) will not overflow INT16_MAX. +template <class DigitsT> +std::pair<DigitsT, int16_t> getSum(DigitsT LDigits, int16_t LScale, + DigitsT RDigits, int16_t RScale) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + // Check inputs up front. This is only relevent if addition overflows, but + // testing here should catch more bugs. + assert(LScale < INT16_MAX && "scale too large"); + assert(RScale < INT16_MAX && "scale too large"); + + // Normalize digits to match scales. + int16_t Scale = matchScales(LDigits, LScale, RDigits, RScale); + + // Compute sum. + DigitsT Sum = LDigits + RDigits; + if (Sum >= RDigits) + return std::make_pair(Sum, Scale); + + // Adjust sum after arithmetic overflow. + DigitsT HighBit = DigitsT(1) << (getWidth<DigitsT>() - 1); + return std::make_pair(HighBit | Sum >> 1, Scale + 1); +} + +/// \brief Convenience helper for 32-bit sum. +inline std::pair<uint32_t, int16_t> getSum32(uint32_t LDigits, int16_t LScale, + uint32_t RDigits, int16_t RScale) { + return getSum(LDigits, LScale, RDigits, RScale); +} + +/// \brief Convenience helper for 64-bit sum. +inline std::pair<uint64_t, int16_t> getSum64(uint64_t LDigits, int16_t LScale, + uint64_t RDigits, int16_t RScale) { + return getSum(LDigits, LScale, RDigits, RScale); +} + +/// \brief Get the difference of two scaled numbers. +/// +/// Get LHS minus RHS with as much precision as possible. +/// +/// Returns \c (0, 0) if the RHS is larger than the LHS. +template <class DigitsT> +std::pair<DigitsT, int16_t> getDifference(DigitsT LDigits, int16_t LScale, + DigitsT RDigits, int16_t RScale) { + static_assert(!std::numeric_limits<DigitsT>::is_signed, "expected unsigned"); + + // Normalize digits to match scales. + const DigitsT SavedRDigits = RDigits; + const int16_t SavedRScale = RScale; + matchScales(LDigits, LScale, RDigits, RScale); + + // Compute difference. + if (LDigits <= RDigits) + return std::make_pair(0, 0); + if (RDigits || !SavedRDigits) + return std::make_pair(LDigits - RDigits, LScale); + + // Check if RDigits just barely lost its last bit. E.g., for 32-bit: + // + // 1*2^32 - 1*2^0 == 0xffffffff != 1*2^32 + const auto RLgFloor = getLgFloor(SavedRDigits, SavedRScale); + if (!compare(LDigits, LScale, DigitsT(1), RLgFloor + getWidth<DigitsT>())) + return std::make_pair(std::numeric_limits<DigitsT>::max(), RLgFloor); + + return std::make_pair(LDigits, LScale); +} + +/// \brief Convenience helper for 32-bit difference. +inline std::pair<uint32_t, int16_t> getDifference32(uint32_t LDigits, + int16_t LScale, + uint32_t RDigits, + int16_t RScale) { + return getDifference(LDigits, LScale, RDigits, RScale); +} + +/// \brief Convenience helper for 64-bit difference. +inline std::pair<uint64_t, int16_t> getDifference64(uint64_t LDigits, + int16_t LScale, + uint64_t RDigits, + int16_t RScale) { + return getDifference(LDigits, LScale, RDigits, RScale); +} + +} // end namespace ScaledNumbers +} // end namespace llvm + +namespace llvm { + +class raw_ostream; +class ScaledNumberBase { +public: + static const int DefaultPrecision = 10; + + static void dump(uint64_t D, int16_t E, int Width); + static raw_ostream &print(raw_ostream &OS, uint64_t D, int16_t E, int Width, + unsigned Precision); + static std::string toString(uint64_t D, int16_t E, int Width, + unsigned Precision); + static int countLeadingZeros32(uint32_t N) { return countLeadingZeros(N); } + static int countLeadingZeros64(uint64_t N) { return countLeadingZeros(N); } + static uint64_t getHalf(uint64_t N) { return (N >> 1) + (N & 1); } + + static std::pair<uint64_t, bool> splitSigned(int64_t N) { + if (N >= 0) + return std::make_pair(N, false); + uint64_t Unsigned = N == INT64_MIN ? UINT64_C(1) << 63 : uint64_t(-N); + return std::make_pair(Unsigned, true); + } + static int64_t joinSigned(uint64_t U, bool IsNeg) { + if (U > uint64_t(INT64_MAX)) + return IsNeg ? INT64_MIN : INT64_MAX; + return IsNeg ? -int64_t(U) : int64_t(U); + } +}; + +/// \brief Simple representation of a scaled number. +/// +/// ScaledNumber is a number represented by digits and a scale. It uses simple +/// saturation arithmetic and every operation is well-defined for every value. +/// It's somewhat similar in behaviour to a soft-float, but is *not* a +/// replacement for one. If you're doing numerics, look at \a APFloat instead. +/// Nevertheless, we've found these semantics useful for modelling certain cost +/// metrics. +/// +/// The number is split into a signed scale and unsigned digits. The number +/// represented is \c getDigits()*2^getScale(). In this way, the digits are +/// much like the mantissa in the x87 long double, but there is no canonical +/// form so the same number can be represented by many bit representations. +/// +/// ScaledNumber is templated on the underlying integer type for digits, which +/// is expected to be unsigned. +/// +/// Unlike APFloat, ScaledNumber does not model architecture floating point +/// behaviour -- while this might make it a little faster and easier to reason +/// about, it certainly makes it more dangerous for general numerics. +/// +/// ScaledNumber is totally ordered. However, there is no canonical form, so +/// there are multiple representations of most scalars. E.g.: +/// +/// ScaledNumber(8u, 0) == ScaledNumber(4u, 1) +/// ScaledNumber(4u, 1) == ScaledNumber(2u, 2) +/// ScaledNumber(2u, 2) == ScaledNumber(1u, 3) +/// +/// ScaledNumber implements most arithmetic operations. Precision is kept +/// where possible. Uses simple saturation arithmetic, so that operations +/// saturate to 0.0 or getLargest() rather than under or overflowing. It has +/// some extra arithmetic for unit inversion. 0.0/0.0 is defined to be 0.0. +/// Any other division by 0.0 is defined to be getLargest(). +/// +/// As a convenience for modifying the exponent, left and right shifting are +/// both implemented, and both interpret negative shifts as positive shifts in +/// the opposite direction. +/// +/// Scales are limited to the range accepted by x87 long double. This makes +/// it trivial to add functionality to convert to APFloat (this is already +/// relied on for the implementation of printing). +/// +/// Possible (and conflicting) future directions: +/// +/// 1. Turn this into a wrapper around \a APFloat. +/// 2. Share the algorithm implementations with \a APFloat. +/// 3. Allow \a ScaledNumber to represent a signed number. +template <class DigitsT> class ScaledNumber : ScaledNumberBase { +public: + static_assert(!std::numeric_limits<DigitsT>::is_signed, + "only unsigned floats supported"); + + typedef DigitsT DigitsType; + +private: + typedef std::numeric_limits<DigitsType> DigitsLimits; + + static const int Width = sizeof(DigitsType) * 8; + static_assert(Width <= 64, "invalid integer width for digits"); + +private: + DigitsType Digits; + int16_t Scale; + +public: + ScaledNumber() : Digits(0), Scale(0) {} + + ScaledNumber(DigitsType Digits, int16_t Scale) + : Digits(Digits), Scale(Scale) {} + +private: + ScaledNumber(const std::pair<uint64_t, int16_t> &X) + : Digits(X.first), Scale(X.second) {} + +public: + static ScaledNumber getZero() { return ScaledNumber(0, 0); } + static ScaledNumber getOne() { return ScaledNumber(1, 0); } + static ScaledNumber getLargest() { + return ScaledNumber(DigitsLimits::max(), ScaledNumbers::MaxScale); + } + static ScaledNumber get(uint64_t N) { return adjustToWidth(N, 0); } + static ScaledNumber getInverse(uint64_t N) { + return get(N).invert(); + } + static ScaledNumber getFraction(DigitsType N, DigitsType D) { + return getQuotient(N, D); + } + + int16_t getScale() const { return Scale; } + DigitsType getDigits() const { return Digits; } + + /// \brief Convert to the given integer type. + /// + /// Convert to \c IntT using simple saturating arithmetic, truncating if + /// necessary. + template <class IntT> IntT toInt() const; + + bool isZero() const { return !Digits; } + bool isLargest() const { return *this == getLargest(); } + bool isOne() const { + if (Scale > 0 || Scale <= -Width) + return false; + return Digits == DigitsType(1) << -Scale; + } + + /// \brief The log base 2, rounded. + /// + /// Get the lg of the scalar. lg 0 is defined to be INT32_MIN. + int32_t lg() const { return ScaledNumbers::getLg(Digits, Scale); } + + /// \brief The log base 2, rounded towards INT32_MIN. + /// + /// Get the lg floor. lg 0 is defined to be INT32_MIN. + int32_t lgFloor() const { return ScaledNumbers::getLgFloor(Digits, Scale); } + + /// \brief The log base 2, rounded towards INT32_MAX. + /// + /// Get the lg ceiling. lg 0 is defined to be INT32_MIN. + int32_t lgCeiling() const { + return ScaledNumbers::getLgCeiling(Digits, Scale); + } + + bool operator==(const ScaledNumber &X) const { return compare(X) == 0; } + bool operator<(const ScaledNumber &X) const { return compare(X) < 0; } + bool operator!=(const ScaledNumber &X) const { return compare(X) != 0; } + bool operator>(const ScaledNumber &X) const { return compare(X) > 0; } + bool operator<=(const ScaledNumber &X) const { return compare(X) <= 0; } + bool operator>=(const ScaledNumber &X) const { return compare(X) >= 0; } + + bool operator!() const { return isZero(); } + + /// \brief Convert to a decimal representation in a string. + /// + /// Convert to a string. Uses scientific notation for very large/small + /// numbers. Scientific notation is used roughly for numbers outside of the + /// range 2^-64 through 2^64. + /// + /// \c Precision indicates the number of decimal digits of precision to use; + /// 0 requests the maximum available. + /// + /// As a special case to make debugging easier, if the number is small enough + /// to convert without scientific notation and has more than \c Precision + /// digits before the decimal place, it's printed accurately to the first + /// digit past zero. E.g., assuming 10 digits of precision: + /// + /// 98765432198.7654... => 98765432198.8 + /// 8765432198.7654... => 8765432198.8 + /// 765432198.7654... => 765432198.8 + /// 65432198.7654... => 65432198.77 + /// 5432198.7654... => 5432198.765 + std::string toString(unsigned Precision = DefaultPrecision) { + return ScaledNumberBase::toString(Digits, Scale, Width, Precision); + } + + /// \brief Print a decimal representation. + /// + /// Print a string. See toString for documentation. + raw_ostream &print(raw_ostream &OS, + unsigned Precision = DefaultPrecision) const { + return ScaledNumberBase::print(OS, Digits, Scale, Width, Precision); + } + void dump() const { return ScaledNumberBase::dump(Digits, Scale, Width); } + + ScaledNumber &operator+=(const ScaledNumber &X) { + std::tie(Digits, Scale) = + ScaledNumbers::getSum(Digits, Scale, X.Digits, X.Scale); + // Check for exponent past MaxScale. + if (Scale > ScaledNumbers::MaxScale) + *this = getLargest(); + return *this; + } + ScaledNumber &operator-=(const ScaledNumber &X) { + std::tie(Digits, Scale) = + ScaledNumbers::getDifference(Digits, Scale, X.Digits, X.Scale); + return *this; + } + ScaledNumber &operator*=(const ScaledNumber &X); + ScaledNumber &operator/=(const ScaledNumber &X); + ScaledNumber &operator<<=(int16_t Shift) { + shiftLeft(Shift); + return *this; + } + ScaledNumber &operator>>=(int16_t Shift) { + shiftRight(Shift); + return *this; + } + +private: + void shiftLeft(int32_t Shift); + void shiftRight(int32_t Shift); + + /// \brief Adjust two floats to have matching exponents. + /// + /// Adjust \c this and \c X to have matching exponents. Returns the new \c X + /// by value. Does nothing if \a isZero() for either. + /// + /// The value that compares smaller will lose precision, and possibly become + /// \a isZero(). + ScaledNumber matchScales(ScaledNumber X) { + ScaledNumbers::matchScales(Digits, Scale, X.Digits, X.Scale); + return X; + } + +public: + /// \brief Scale a large number accurately. + /// + /// Scale N (multiply it by this). Uses full precision multiplication, even + /// if Width is smaller than 64, so information is not lost. + uint64_t scale(uint64_t N) const; + uint64_t scaleByInverse(uint64_t N) const { + // TODO: implement directly, rather than relying on inverse. Inverse is + // expensive. + return inverse().scale(N); + } + int64_t scale(int64_t N) const { + std::pair<uint64_t, bool> Unsigned = splitSigned(N); + return joinSigned(scale(Unsigned.first), Unsigned.second); + } + int64_t scaleByInverse(int64_t N) const { + std::pair<uint64_t, bool> Unsigned = splitSigned(N); + return joinSigned(scaleByInverse(Unsigned.first), Unsigned.second); + } + + int compare(const ScaledNumber &X) const { + return ScaledNumbers::compare(Digits, Scale, X.Digits, X.Scale); + } + int compareTo(uint64_t N) const { + ScaledNumber Scaled = get(N); + int Compare = compare(Scaled); + if (Width == 64 || Compare != 0) + return Compare; + + // Check for precision loss. We know *this == RoundTrip. + uint64_t RoundTrip = Scaled.template toInt<uint64_t>(); + return N == RoundTrip ? 0 : RoundTrip < N ? -1 : 1; + } + int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); } + + ScaledNumber &invert() { return *this = ScaledNumber::get(1) / *this; } + ScaledNumber inverse() const { return ScaledNumber(*this).invert(); } + +private: + static ScaledNumber getProduct(DigitsType LHS, DigitsType RHS) { + return ScaledNumbers::getProduct(LHS, RHS); + } + static ScaledNumber getQuotient(DigitsType Dividend, DigitsType Divisor) { + return ScaledNumbers::getQuotient(Dividend, Divisor); + } + + static int countLeadingZerosWidth(DigitsType Digits) { + if (Width == 64) + return countLeadingZeros64(Digits); + if (Width == 32) + return countLeadingZeros32(Digits); + return countLeadingZeros32(Digits) + Width - 32; + } + + /// \brief Adjust a number to width, rounding up if necessary. + /// + /// Should only be called for \c Shift close to zero. + /// + /// \pre Shift >= MinScale && Shift + 64 <= MaxScale. + static ScaledNumber adjustToWidth(uint64_t N, int32_t Shift) { + assert(Shift >= ScaledNumbers::MinScale && "Shift should be close to 0"); + assert(Shift <= ScaledNumbers::MaxScale - 64 && + "Shift should be close to 0"); + auto Adjusted = ScaledNumbers::getAdjusted<DigitsT>(N, Shift); + return Adjusted; + } + + static ScaledNumber getRounded(ScaledNumber P, bool Round) { + // Saturate. + if (P.isLargest()) + return P; + + return ScaledNumbers::getRounded(P.Digits, P.Scale, Round); + } +}; + +#define SCALED_NUMBER_BOP(op, base) \ + template <class DigitsT> \ + ScaledNumber<DigitsT> operator op(const ScaledNumber<DigitsT> &L, \ + const ScaledNumber<DigitsT> &R) { \ + return ScaledNumber<DigitsT>(L) base R; \ + } +SCALED_NUMBER_BOP(+, += ) +SCALED_NUMBER_BOP(-, -= ) +SCALED_NUMBER_BOP(*, *= ) +SCALED_NUMBER_BOP(/, /= ) +SCALED_NUMBER_BOP(<<, <<= ) +SCALED_NUMBER_BOP(>>, >>= ) +#undef SCALED_NUMBER_BOP + +template <class DigitsT> +raw_ostream &operator<<(raw_ostream &OS, const ScaledNumber<DigitsT> &X) { + return X.print(OS, 10); +} + +#define SCALED_NUMBER_COMPARE_TO_TYPE(op, T1, T2) \ + template <class DigitsT> \ + bool operator op(const ScaledNumber<DigitsT> &L, T1 R) { \ + return L.compareTo(T2(R)) op 0; \ + } \ + template <class DigitsT> \ + bool operator op(T1 L, const ScaledNumber<DigitsT> &R) { \ + return 0 op R.compareTo(T2(L)); \ + } +#define SCALED_NUMBER_COMPARE_TO(op) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, uint64_t, uint64_t) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, uint32_t, uint64_t) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, int64_t, int64_t) \ + SCALED_NUMBER_COMPARE_TO_TYPE(op, int32_t, int64_t) +SCALED_NUMBER_COMPARE_TO(< ) +SCALED_NUMBER_COMPARE_TO(> ) +SCALED_NUMBER_COMPARE_TO(== ) +SCALED_NUMBER_COMPARE_TO(!= ) +SCALED_NUMBER_COMPARE_TO(<= ) +SCALED_NUMBER_COMPARE_TO(>= ) +#undef SCALED_NUMBER_COMPARE_TO +#undef SCALED_NUMBER_COMPARE_TO_TYPE + +template <class DigitsT> +uint64_t ScaledNumber<DigitsT>::scale(uint64_t N) const { + if (Width == 64 || N <= DigitsLimits::max()) + return (get(N) * *this).template toInt<uint64_t>(); + + // Defer to the 64-bit version. + return ScaledNumber<uint64_t>(Digits, Scale).scale(N); +} + +template <class DigitsT> +template <class IntT> +IntT ScaledNumber<DigitsT>::toInt() const { + typedef std::numeric_limits<IntT> Limits; + if (*this < 1) + return 0; + if (*this >= Limits::max()) + return Limits::max(); + + IntT N = Digits; + if (Scale > 0) { + assert(size_t(Scale) < sizeof(IntT) * 8); + return N << Scale; + } + if (Scale < 0) { + assert(size_t(-Scale) < sizeof(IntT) * 8); + return N >> -Scale; + } + return N; +} + +template <class DigitsT> +ScaledNumber<DigitsT> &ScaledNumber<DigitsT>:: +operator*=(const ScaledNumber &X) { + if (isZero()) + return *this; + if (X.isZero()) + return *this = X; + + // Save the exponents. + int32_t Scales = int32_t(Scale) + int32_t(X.Scale); + + // Get the raw product. + *this = getProduct(Digits, X.Digits); + + // Combine with exponents. + return *this <<= Scales; +} +template <class DigitsT> +ScaledNumber<DigitsT> &ScaledNumber<DigitsT>:: +operator/=(const ScaledNumber &X) { + if (isZero()) + return *this; + if (X.isZero()) + return *this = getLargest(); + + // Save the exponents. + int32_t Scales = int32_t(Scale) - int32_t(X.Scale); + + // Get the raw quotient. + *this = getQuotient(Digits, X.Digits); + + // Combine with exponents. + return *this <<= Scales; +} +template <class DigitsT> void ScaledNumber<DigitsT>::shiftLeft(int32_t Shift) { + if (!Shift || isZero()) + return; + assert(Shift != INT32_MIN); + if (Shift < 0) { + shiftRight(-Shift); + return; + } + + // Shift as much as we can in the exponent. + int32_t ScaleShift = std::min(Shift, ScaledNumbers::MaxScale - Scale); + Scale += ScaleShift; + if (ScaleShift == Shift) + return; + + // Check this late, since it's rare. + if (isLargest()) + return; + + // Shift the digits themselves. + Shift -= ScaleShift; + if (Shift > countLeadingZerosWidth(Digits)) { + // Saturate. + *this = getLargest(); + return; + } + + Digits <<= Shift; + return; +} + +template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) { + if (!Shift || isZero()) + return; + assert(Shift != INT32_MIN); + if (Shift < 0) { + shiftLeft(-Shift); + return; + } + + // Shift as much as we can in the exponent. + int32_t ScaleShift = std::min(Shift, Scale - ScaledNumbers::MinScale); + Scale -= ScaleShift; + if (ScaleShift == Shift) + return; + + // Shift the digits themselves. + Shift -= ScaleShift; + if (Shift >= Width) { + // Saturate. + *this = getZero(); + return; + } + + Digits >>= Shift; + return; +} + +template <typename T> struct isPodLike; +template <typename T> struct isPodLike<ScaledNumber<T>> { + static const bool value = true; +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 39f896d..4717553 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -30,7 +30,7 @@ namespace llvm { class Twine; class raw_ostream; -/// SourceMgr - This owns the files read by a parser, handles include stacks, +/// This owns the files read by a parser, handles include stacks, /// and handles diagnostic wrangling. class SourceMgr { public: @@ -40,34 +40,34 @@ public: DK_Note }; - /// 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. + /// 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); private: struct SrcBuffer { - /// Buffer - The memory buffer for the file. + /// The memory buffer for the file. MemoryBuffer *Buffer; - /// IncludeLoc - This is the location of the parent include, or null if at - /// the top level. + /// This is the location of the parent include, or null if at the top level. SMLoc IncludeLoc; }; - /// Buffers - This is all of the buffers that we are reading from. + /// This is all of the buffers that we are reading from. std::vector<SrcBuffer> Buffers; - // IncludeDirectories - This is the list of directories we should search for - // include files in. + // This is the list of directories we should search for include files in. std::vector<std::string> IncludeDirectories; - /// LineNoCache - This is a cache for line number queries, its implementation - /// is really private to SourceMgr.cpp. + /// This is a cache for line number queries, its implementation is really + /// private to SourceMgr.cpp. mutable void *LineNoCache; DiagHandlerTy DiagHandler; void *DiagContext; + bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); } + SourceMgr(const SourceMgr&) LLVM_DELETED_FUNCTION; void operator=(const SourceMgr&) LLVM_DELETED_FUNCTION; public: @@ -79,8 +79,8 @@ public: IncludeDirectories = Dirs; } - /// setDiagHandler - Specify a diagnostic handler to be invoked every time - /// PrintMessage is called. Ctx is passed into the handler when it is invoked. + /// Specify a diagnostic handler to be invoked every time PrintMessage is + /// called. \p Ctx is passed into the handler when it is invoked. void setDiagHandler(DiagHandlerTy DH, void *Ctx = nullptr) { DiagHandler = DH; DiagContext = Ctx; @@ -90,60 +90,67 @@ public: void *getDiagContext() const { return DiagContext; } const SrcBuffer &getBufferInfo(unsigned i) const { - assert(i < Buffers.size() && "Invalid Buffer ID!"); - return Buffers[i]; + assert(isValidBufferID(i)); + return Buffers[i - 1]; } const MemoryBuffer *getMemoryBuffer(unsigned i) const { - assert(i < Buffers.size() && "Invalid Buffer ID!"); - return Buffers[i].Buffer; + assert(isValidBufferID(i)); + return Buffers[i - 1].Buffer; } - size_t getNumBuffers() const { + unsigned getNumBuffers() const { return Buffers.size(); } + unsigned getMainFileID() const { + assert(getNumBuffers()); + return 1; + } + SMLoc getParentIncludeLoc(unsigned i) const { - assert(i < Buffers.size() && "Invalid Buffer ID!"); - return Buffers[i].IncludeLoc; + assert(isValidBufferID(i)); + return Buffers[i - 1].IncludeLoc; } - /// AddNewSourceBuffer - Add a new source buffer to this source manager. This - /// takes ownership of the memory buffer. - size_t AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { + /// Add a new source buffer to this source manager. This takes ownership of + /// the memory buffer. + unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { SrcBuffer NB; NB.Buffer = F; NB.IncludeLoc = IncludeLoc; Buffers.push_back(NB); - return Buffers.size() - 1; + return Buffers.size(); } - /// AddIncludeFile - Search for a file with the specified name in the current - /// directory or in one of the IncludeDirs. If no file is found, this returns - /// ~0, otherwise it returns the buffer ID of the stacked file. - /// The full path to the included file can be found in IncludedFile. - size_t AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, - std::string &IncludedFile); + /// Search for a file with the specified name in the current directory or in + /// one of the IncludeDirs. + /// + /// If no file is found, this returns 0, otherwise it returns the buffer ID + /// of the stacked file. The full path to the included file can be found in + /// \p IncludedFile. + unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, + std::string &IncludedFile); - /// FindBufferContainingLoc - Return the ID of the buffer containing the - /// specified location, returning -1 if not found. - int FindBufferContainingLoc(SMLoc Loc) const; + /// Return the ID of the buffer containing the specified location. + /// + /// 0 is returned if the buffer is not found. + unsigned FindBufferContainingLoc(SMLoc Loc) const; - /// FindLineNumber - Find the line number for the specified location in the - /// specified file. This is not a fast method. - unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const { + /// Find the line number for the specified location in the specified file. + /// This is not a fast method. + unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const { return getLineAndColumn(Loc, BufferID).first; } - /// getLineAndColumn - Find the line and column number for the specified - /// location in the specified file. This is not a fast method. - std::pair<unsigned, unsigned> - getLineAndColumn(SMLoc Loc, int BufferID = -1) const; + /// Find the line and column number for the specified location in the + /// specified file. This is not a fast method. + std::pair<unsigned, unsigned> getLineAndColumn(SMLoc Loc, + unsigned BufferID = 0) const; - /// PrintMessage - Emit a message about the specified location with the - /// specified string. + /// Emit a message about the specified location with the specified string. /// - /// @param ShowColors - Display colored messages if output is a terminal and + /// \param ShowColors Display colored messages if output is a terminal and /// the default error handler is used. void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, @@ -157,21 +164,28 @@ public: ArrayRef<SMFixIt> FixIts = None, bool ShowColors = true) const; - /// GetMessage - Return an SMDiagnostic at the specified location with the - /// specified string. + /// Emits a manually-constructed diagnostic to the given output stream. + /// + /// \param ShowColors Display colored messages if output is a terminal and + /// the default error handler is used. + void PrintMessage(raw_ostream &OS, const SMDiagnostic &Diagnostic, + bool ShowColors = true) const; + + /// Return an SMDiagnostic at the specified location with the specified + /// string. /// - /// @param Msg If non-null, the kind of message (e.g., "error") which is + /// \param Msg If non-null, the kind of message (e.g., "error") which is /// prefixed to the message. SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef<SMRange> Ranges = None, ArrayRef<SMFixIt> FixIts = None) const; - /// PrintIncludeStack - Prints the names of included files and the line of the - /// file they were included from. A diagnostic handler can use this before - /// printing its custom formatted message. + /// Prints the names of included files and the line of the file they were + /// included from. A diagnostic handler can use this before printing its + /// custom formatted message. /// - /// @param IncludeLoc - The line of the include. - /// @param OS the raw_ostream to print on. + /// \param IncludeLoc The location of the include. + /// \param OS the raw_ostream to print on. void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; }; @@ -208,8 +222,8 @@ public: }; -/// SMDiagnostic - Instances of this class encapsulate one diagnostic report, -/// allowing printing to a raw_ostream as a caret diagnostic. +/// Instances of this class encapsulate one diagnostic report, allowing +/// printing to a raw_ostream as a caret diagnostic. class SMDiagnostic { const SourceMgr *SM; SMLoc Loc; diff --git a/include/llvm/Support/SpecialCaseList.h b/include/llvm/Support/SpecialCaseList.h new file mode 100644 index 0000000..098b9c7 --- /dev/null +++ b/include/llvm/Support/SpecialCaseList.h @@ -0,0 +1,96 @@ +//===-- SpecialCaseList.h - special case list for sanitizers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// +// +// This is a utility class used to parse user-provided text files with +// "special case lists" for code sanitizers. Such files are used to +// define "ABI list" for DataFlowSanitizer and blacklists for another sanitizers +// like AddressSanitizer or UndefinedBehaviorSanitizer. +// +// Empty lines and lines starting with "#" are ignored. All the rest lines +// should have the form: +// section:wildcard_expression[=category] +// If category is not specified, it is assumed to be empty string. +// Definitions of "section" and "category" are sanitizer-specific. For example, +// sanitizer blacklists support sections "src", "fun" and "global". +// Wildcard expressions define, respectively, source files, functions or +// globals which shouldn't be instrumented. +// Examples of categories: +// "functional": used in DFSan to list functions with pure functional +// semantics. +// "init": used in ASan blacklist to disable initialization-order bugs +// detection for certain globals or source files. +// Full special case list file example: +// --- +// # Blacklisted items: +// fun:*_ZN4base6subtle* +// global:*global_with_bad_access_or_initialization* +// global:*global_with_initialization_issues*=init +// type:*Namespace::ClassName*=init +// src:file_with_tricky_code.cc +// src:ignore-global-initializers-issues.cc=init +// +// # Functions with pure functional semantics: +// fun:cos=functional +// fun:sin=functional +// --- +// Note that the wild card is in fact an llvm::Regex, but * is automatically +// replaced with .* +// This is similar to the "ignore" feature of ThreadSanitizer. +// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SPECIALCASELIST_H +#define LLVM_SUPPORT_SPECIALCASELIST_H + +#include "llvm/ADT/StringMap.h" + +namespace llvm { +class MemoryBuffer; +class Regex; +class StringRef; + +class SpecialCaseList { + public: + /// Parses the special case list from a file. If Path is empty, returns + /// an empty special case list. On failure, returns 0 and writes an error + /// message to string. + static SpecialCaseList *create(const StringRef Path, std::string &Error); + /// Parses the special case list from a memory buffer. On failure, returns + /// 0 and writes an error message to string. + static SpecialCaseList *create(const MemoryBuffer *MB, std::string &Error); + /// Parses the special case list from a file. On failure, reports a fatal + /// error. + static SpecialCaseList *createOrDie(const StringRef Path); + + ~SpecialCaseList(); + + /// Returns true, if special case list contains a line + /// \code + /// @Section:<E>=@Category + /// \endcode + /// and @Query satisfies a wildcard expression <E>. + bool inSection(const StringRef Section, const StringRef Query, + const StringRef Category = StringRef()) const; + + private: + SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION; + SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION; + + struct Entry; + StringMap<StringMap<Entry> > Entries; + + SpecialCaseList(); + /// Parses just-constructed SpecialCaseList entries from a memory buffer. + bool parse(const MemoryBuffer *MB, std::string &Error); +}; + +} // namespace llvm + +#endif // LLVM_SUPPORT_SPECIALCASELIST_H + diff --git a/include/llvm/Support/StreamableMemoryObject.h b/include/llvm/Support/StreamableMemoryObject.h index 9c9e55c..6e71ad4 100644 --- a/include/llvm/Support/StreamableMemoryObject.h +++ b/include/llvm/Support/StreamableMemoryObject.h @@ -13,6 +13,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/DataStream.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryObject.h" #include <cassert> #include <memory> @@ -115,7 +116,7 @@ public: // requiring that the bitcode size be known, or otherwise ensuring that // the memory doesn't go away/get reallocated, but it's // not currently necessary. Users that need the pointer don't stream. - assert(0 && "getPointer in streaming memory objects not allowed"); + llvm_unreachable("getPointer in streaming memory objects not allowed"); return nullptr; } bool isValidAddress(uint64_t address) const override; @@ -154,8 +155,8 @@ private: kChunkSize); BytesRead += bytes; if (bytes < kChunkSize) { - if (ObjectSize && BytesRead < Pos) - assert(0 && "Unexpected short read fetching bitcode"); + assert((!ObjectSize || BytesRead >= Pos) && + "Unexpected short read fetching bitcode"); if (BytesRead <= Pos) { // reached EOF/ran out of bytes ObjectSize = BytesRead; EOFReached = true; diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h index 7e1394c..3e04653 100644 --- a/include/llvm/Support/StringPool.h +++ b/include/llvm/Support/StringPool.h @@ -29,6 +29,7 @@ #ifndef LLVM_SUPPORT_STRINGPOOL_H #define LLVM_SUPPORT_STRINGPOOL_H +#include "llvm/Support/Compiler.h" #include "llvm/ADT/StringMap.h" #include <cassert> #include <new> @@ -128,10 +129,10 @@ namespace llvm { } inline const char *operator*() const { return begin(); } - inline operator bool() const { return S != nullptr; } + inline LLVM_EXPLICIT operator bool() const { return S != nullptr; } - inline bool operator==(const PooledStringPtr &That) { return S == That.S; } - inline bool operator!=(const PooledStringPtr &That) { return S != That.S; } + inline bool operator==(const PooledStringPtr &That) const { return S == That.S; } + inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; } }; } // End llvm namespace diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index e65f9cc..340954f 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -68,33 +68,38 @@ inline uint64_t SwapByteOrder_64(uint64_t value) { #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 char getSwappedBytes(unsigned char C) { return C; } +inline signed char getSwappedBytes(signed char C) { return C; } +inline char getSwappedBytes(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 short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); } +inline signed short getSwappedBytes( 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); } +inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); } +inline signed int getSwappedBytes( 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); } +inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); } +inline signed long getSwappedBytes( 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); } +inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); } +inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); } #else #error "Unknown long size!" #endif -inline unsigned long long SwapByteOrder(unsigned long long C) { +inline unsigned long long getSwappedBytes(unsigned long long C) { return SwapByteOrder_64(C); } -inline signed long long SwapByteOrder(signed long long C) { +inline signed long long getSwappedBytes(signed long long C) { return SwapByteOrder_64(C); } +template<typename T> +inline void swapByteOrder(T &Value) { + Value = getSwappedBytes(Value); +} + } // end namespace sys } // end namespace llvm diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index fcdc604..5d5b86a 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -51,6 +51,7 @@ namespace llvm { class raw_ostream; class formatted_raw_ostream; + MCStreamer *createNullStreamer(MCContext &Ctx); MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, @@ -139,6 +140,7 @@ namespace llvm { MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); + typedef MCStreamer *(*NullStreamerCtorTy)(MCContext &Ctx); typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT, MCContext &Ctx); typedef MCSymbolizer *(*MCSymbolizerCtorTy)(StringRef TT, @@ -225,6 +227,10 @@ namespace llvm { /// AsmStreamer, if registered (default = llvm::createAsmStreamer). AsmStreamerCtorTy AsmStreamerCtorFn; + /// Construction function for this target's NullStreamer, if registered + /// (default = llvm::createNullStreamer). + NullStreamerCtorTy NullStreamerCtorFn; + /// MCRelocationInfoCtorFn - Construction function for this target's /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo) MCRelocationInfoCtorTy MCRelocationInfoCtorFn; @@ -235,8 +241,8 @@ namespace llvm { public: Target() - : AsmStreamerCtorFn(nullptr), MCRelocationInfoCtorFn(nullptr), - MCSymbolizerCtorFn(nullptr) {} + : AsmStreamerCtorFn(nullptr), NullStreamerCtorFn(nullptr), + MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {} /// @name Target Information /// @{ @@ -447,6 +453,12 @@ namespace llvm { InstPrint, CE, TAB, ShowInst); } + MCStreamer *createNullStreamer(MCContext &Ctx) const { + if (NullStreamerCtorFn) + return NullStreamerCtorFn(Ctx); + return llvm::createNullStreamer(Ctx); + } + /// createMCRelocationInfo - Create a target specific MCRelocationInfo. /// /// \param TT The target triple. @@ -553,13 +565,6 @@ namespace llvm { Triple &TheTriple, std::string &Error); - /// getClosestTargetForJIT - Pick the best target that is compatible with - /// the current host. If no close target can be found, this returns null - /// and sets the Error string to a reason. - /// - /// Maintained for compatibility through 2.6. - static const Target *getClosestTargetForJIT(std::string &Error); - /// @} /// @name Target Registration /// @{ @@ -780,6 +785,10 @@ namespace llvm { T.AsmStreamerCtorFn = Fn; } + static void RegisterNullStreamer(Target &T, Target::NullStreamerCtorTy Fn) { + T.NullStreamerCtorFn = Fn; + } + /// RegisterMCRelocationInfo - Register an MCRelocationInfo /// implementation for the given target. /// diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h index a7e8774..7e87584 100644 --- a/include/llvm/Support/Threading.h +++ b/include/llvm/Support/Threading.h @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// TThis file defines llvm_start_multithreaded() and friends. +// This file declares helper functions for running LLVM in a multi-threaded +// environment. // //===----------------------------------------------------------------------===// @@ -15,32 +16,10 @@ #define LLVM_SUPPORT_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. + /// Returns true if LLVM is compiled with support for multi-threading, and + /// false otherwise. 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 \p UserFn on a separate /// thread, passing it the provided \p UserData. /// diff --git a/include/llvm/Support/WindowsError.h b/include/llvm/Support/WindowsError.h new file mode 100644 index 0000000..0e909a0 --- /dev/null +++ b/include/llvm/Support/WindowsError.h @@ -0,0 +1,19 @@ +//===-- WindowsError.h - Support for mapping windows errors to posix-------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_WINDOWS_ERROR_H +#define LLVM_SUPPORT_WINDOWS_ERROR_H + +#include <system_error> + +namespace llvm { +std::error_code mapWindowsError(unsigned EV); +} + +#endif diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 4ee05ed..a23faf6 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -24,7 +24,7 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/YAMLParser.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" +#include <system_error> namespace llvm { namespace yaml { @@ -880,7 +880,7 @@ public: ~Input(); // Check if there was an syntax or semantic error during parsing. - llvm::error_code error(); + std::error_code error(); private: bool outputting() override; @@ -982,13 +982,13 @@ public: // These are only used by operator>>. They could be private // if those templated things could be made friends. bool setCurrentDocument(); - void nextDocument(); + bool nextDocument(); private: llvm::SourceMgr SrcMgr; // must be before Strm std::unique_ptr<llvm::yaml::Stream> Strm; std::unique_ptr<HNode> TopNode; - llvm::error_code EC; + std::error_code EC; llvm::BumpPtrAllocator StringAllocator; llvm::yaml::document_iterator DocIterator; std::vector<bool> BitValuesUsed; diff --git a/include/llvm/Support/system_error.h b/include/llvm/Support/system_error.h deleted file mode 100644 index aa5e9f7..0000000 --- a/include/llvm/Support/system_error.h +++ /dev/null @@ -1,901 +0,0 @@ -//===---------------------------- system_error ------------------*- C++ -*-===// -// -// 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_SUPPORT_SYSTEM_ERROR_H -#define LLVM_SUPPORT_SYSTEM_ERROR_H - -#include "llvm/Support/Compiler.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 std::false_type {}; - -template <class T> struct is_error_condition_enum - : public std::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> : std::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/llvm-config.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 { - -// is_error_code_enum - -template <class Tp> struct is_error_code_enum : public std::false_type {}; - -// is_error_condition_enum - -template <class Tp> struct is_error_condition_enum : public std::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> : std::true_type { }; - -template <> struct is_error_condition_enum<errc::_> : std::true_type { }; - -class error_condition; -class error_code; - -// class error_category - -class _do_message; - -class error_category -{ -public: - virtual ~error_category(); - - error_category(); -private: - error_category(const error_category&) LLVM_DELETED_FUNCTION; - error_category& operator=(const error_category&) LLVM_DELETED_FUNCTION; - -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: - std::string message(int ev) const override; -}; - -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 POSIX 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 std::enable_if< - 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 std::enable_if<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 ? nullptr : 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()) {} - - static error_code success() { - return error_code(); - } - - error_code(int _val, const error_category& _cat) - : _val_(_val), _cat_(&_cat) {} - - template <class E> - error_code(E _e, typename std::enable_if< - 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 std::enable_if<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 ? nullptr : 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> : std::true_type { }; - -template <> struct is_error_code_enum<windows_error::_> : std::true_type { }; - -inline error_code make_error_code(windows_error e) { - return error_code(static_cast<int>(e), system_category()); -} - -} // end namespace llvm - -#endif |