diff options
author | dim <dim@FreeBSD.org> | 2014-11-24 17:02:24 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-11-24 17:02:24 +0000 |
commit | 2c8643c6396b0a3db33430cf9380e70bbb9efce0 (patch) | |
tree | 4df130b28021d86e13bf4565ef58c1c5a5e093b4 /contrib/llvm/include/llvm/Support | |
parent | 678318cd20f7db4e6c6b85d83fe00fa327b04fca (diff) | |
parent | e27feadae0885aa074df58ebfda2e7a7f7a7d590 (diff) | |
download | FreeBSD-src-2c8643c6396b0a3db33430cf9380e70bbb9efce0.zip FreeBSD-src-2c8643c6396b0a3db33430cf9380e70bbb9efce0.tar.gz |
Merge llvm 3.5.0 release from ^/vendor/llvm/dist, resolve conflicts, and
preserve our customizations, where necessary.
Diffstat (limited to 'contrib/llvm/include/llvm/Support')
97 files changed, 6168 insertions, 6870 deletions
diff --git a/contrib/llvm/include/llvm/Support/ARMBuildAttributes.h b/contrib/llvm/include/llvm/Support/ARMBuildAttributes.h new file mode 100644 index 0000000..f63e0a6 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/ARMBuildAttributes.h @@ -0,0 +1,217 @@ +//===-- ARMBuildAttributes.h - ARM Build Attributes -------------*- 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 enumerations and support routines for ARM build attributes +// as defined in ARM ABI addenda document (ABI release 2.08). +// +// ELF for the ARM Architecture r2.09 - November 30, 2012 +// +// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H +#define LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H + +namespace llvm { +class StringRef; + +namespace ARMBuildAttrs { + +enum SpecialAttr { + // This is for the .cpu asm attr. It translates into one or more + // AttrType (below) entries in the .ARM.attributes section in the ELF. + SEL_CPU +}; + +enum AttrType { + // Rest correspond to ELF/.ARM.attributes + File = 1, + CPU_raw_name = 4, + CPU_name = 5, + CPU_arch = 6, + CPU_arch_profile = 7, + ARM_ISA_use = 8, + THUMB_ISA_use = 9, + FP_arch = 10, + WMMX_arch = 11, + Advanced_SIMD_arch = 12, + PCS_config = 13, + ABI_PCS_R9_use = 14, + ABI_PCS_RW_data = 15, + ABI_PCS_RO_data = 16, + ABI_PCS_GOT_use = 17, + ABI_PCS_wchar_t = 18, + ABI_FP_rounding = 19, + ABI_FP_denormal = 20, + ABI_FP_exceptions = 21, + ABI_FP_user_exceptions = 22, + ABI_FP_number_model = 23, + ABI_align_needed = 24, + ABI_align_preserved = 25, + ABI_enum_size = 26, + ABI_HardFP_use = 27, + ABI_VFP_args = 28, + ABI_WMMX_args = 29, + ABI_optimization_goals = 30, + ABI_FP_optimization_goals = 31, + compatibility = 32, + CPU_unaligned_access = 34, + FP_HP_extension = 36, + ABI_FP_16bit_format = 38, + MPextension_use = 42, // recoded from 70 (ABI r2.08) + DIV_use = 44, + also_compatible_with = 65, + conformance = 67, + Virtualization_use = 68, + + /// Legacy Tags + Section = 2, // deprecated (ABI r2.09) + Symbol = 3, // deprecated (ABI r2.09) + ABI_align8_needed = 24, // renamed to ABI_align_needed (ABI r2.09) + ABI_align8_preserved = 25, // renamed to ABI_align_preserved (ABI r2.09) + nodefaults = 64, // deprecated (ABI r2.09) + T2EE_use = 66, // deprecated (ABI r2.09) + MPextension_use_old = 70 // recoded to MPextension_use (ABI r2.08) +}; + +StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix = true); +StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true); +int AttrTypeFromString(StringRef Tag); + +// Magic numbers for .ARM.attributes +enum AttrMagic { + Format_Version = 0x41 +}; + +// Legal Values for CPU_arch, (=6), uleb128 +enum CPUArch { + Pre_v4 = 0, + v4 = 1, // e.g. SA110 + v4T = 2, // e.g. ARM7TDMI + v5T = 3, // e.g. ARM9TDMI + v5TE = 4, // e.g. ARM946E_S + v5TEJ = 5, // e.g. ARM926EJ_S + v6 = 6, // e.g. ARM1136J_S + v6KZ = 7, // e.g. ARM1176JZ_S + v6T2 = 8, // e.g. ARM1156T2F_S + v6K = 9, // e.g. ARM1136J_S + v7 = 10, // e.g. Cortex A8, Cortex M3 + v6_M = 11, // e.g. Cortex M1 + v6S_M = 12, // v6_M with the System extensions + v7E_M = 13, // v7_M with DSP extensions + v8 = 14 // v8, AArch32 +}; + +enum CPUArchProfile { // (=7), uleb128 + Not_Applicable = 0, // pre v7, or cross-profile code + ApplicationProfile = (0x41), // 'A' (e.g. for Cortex A8) + RealTimeProfile = (0x52), // 'R' (e.g. for Cortex R4) + MicroControllerProfile = (0x4D), // 'M' (e.g. for Cortex M3) + SystemProfile = (0x53) // 'S' Application or real-time profile +}; + +// The following have a lot of common use cases +enum { + Not_Allowed = 0, + Allowed = 1, + + // Tag_ARM_ISA_use (=8), uleb128 + + // Tag_THUMB_ISA_use, (=9), uleb128 + AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions) + + // Tag_FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10) + AllowFPv2 = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA) + AllowFPv3A = 3, // v3 FP ISA permitted (implies use of the v2 FP ISA) + AllowFPv3B = 4, // v3 FP ISA permitted, but only D0-D15, S0-S31 + AllowFPv4A = 5, // v4 FP ISA permitted (implies use of v3 FP ISA) + AllowFPv4B = 6, // v4 FP ISA was permitted, but only D0-D15, S0-S31 + AllowFPARMv8A = 7, // Use of the ARM v8-A FP ISA was permitted + AllowFPARMv8B = 8, // Use of the ARM v8-A FP ISA was permitted, but only + // D0-D15, S0-S31 + + // Tag_WMMX_arch, (=11), uleb128 + AllowWMMXv1 = 1, // The user permitted this entity to use WMMX v1 + AllowWMMXv2 = 2, // The user permitted this entity to use WMMX v2 + + // Tag_Advanced_SIMD_arch, (=12), uleb128 + AllowNeon = 1, // SIMDv1 was permitted + AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations) + AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted + + // Tag_ABI_PCS_RW_data, (=15), uleb128 + AddressRWPCRel = 1, // Address RW static data PC-relative + AddressRWSBRel = 2, // Address RW static data SB-relative + AddressRWNone = 3, // No RW static data permitted + + // Tag_ABI_PCS_RO_data, (=14), uleb128 + AddressROPCRel = 1, // Address RO static data PC-relative + AddressRONone = 2, // No RO static data permitted + + // Tag_ABI_PCS_GOT_use, (=17), uleb128 + 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 + + // Tag_ABI_FP_number_model, (=23), uleb128 + 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 + + // Tag_ABI_VFP_args, (=28), uleb128 + BaseAAPCS = 0, + HardFPAAPCS = 1, + + // Tag_FP_HP_extension, (=36), uleb128 + AllowHPFP = 1, // Allow use of Half Precision FP + + // Tag_MPextension_use, (=42), uleb128 + AllowMP = 1, // Allow use of MP extensions + + // Tag_DIV_use, (=44), uleb128 + // Note: AllowDIVExt must be emitted if and only if the permission to use + // hardware divide cannot be conveyed using AllowDIVIfExists or DisallowDIV + AllowDIVIfExists = 0, // Allow hardware divide if available in arch, or no + // info exists. + DisallowDIV = 1, // Hardware divide explicitly disallowed. + AllowDIVExt = 2, // Allow hardware divide as optional architecture + // extension above the base arch specified by + // Tag_CPU_arch and Tag_CPU_arch_profile. + + // Tag_Virtualization_use, (=68), uleb128 + AllowTZ = 1, + AllowVirtualization = 2, + AllowTZVirtualization = 3 +}; + +} // namespace ARMBuildAttrs +} // namespace llvm + +#endif // LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H diff --git a/contrib/llvm/include/llvm/Support/ARMEHABI.h b/contrib/llvm/include/llvm/Support/ARMEHABI.h new file mode 100644 index 0000000..c7ac54a --- /dev/null +++ b/contrib/llvm/include/llvm/Support/ARMEHABI.h @@ -0,0 +1,134 @@ +//===--- ARMEHABI.h - ARM Exception Handling ABI ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the constants for the ARM unwind opcodes and exception +// handling table entry kinds. +// +// The enumerations and constants in this file reflect the ARM EHABI +// Specification as published by ARM. +// +// Exception Handling ABI for the ARM Architecture r2.09 - November 30, 2012 +// +// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ARM_EHABI_H +#define LLVM_SUPPORT_ARM_EHABI_H + +namespace llvm { +namespace ARM { +namespace EHABI { + /// ARM exception handling table entry kinds + enum EHTEntryKind { + EHT_GENERIC = 0x00, + EHT_COMPACT = 0x80 + }; + + enum { + /// Special entry for the function never unwind + EXIDX_CANTUNWIND = 0x1 + }; + + /// ARM-defined frame unwinding opcodes + enum UnwindOpcodes { + // Format: 00xxxxxx + // Purpose: vsp = vsp + ((x << 2) + 4) + UNWIND_OPCODE_INC_VSP = 0x00, + + // Format: 01xxxxxx + // Purpose: vsp = vsp - ((x << 2) + 4) + UNWIND_OPCODE_DEC_VSP = 0x40, + + // Format: 10000000 00000000 + // Purpose: refuse to unwind + UNWIND_OPCODE_REFUSE = 0x8000, + + // Format: 1000xxxx xxxxxxxx + // Purpose: pop r[15:12], r[11:4] + // Constraint: x != 0 + UNWIND_OPCODE_POP_REG_MASK_R4 = 0x8000, + + // Format: 1001xxxx + // Purpose: vsp = r[x] + // Constraint: x != 13 && x != 15 + UNWIND_OPCODE_SET_VSP = 0x90, + + // Format: 10100xxx + // Purpose: pop r[(4+x):4] + UNWIND_OPCODE_POP_REG_RANGE_R4 = 0xa0, + + // Format: 10101xxx + // Purpose: pop r14, r[(4+x):4] + UNWIND_OPCODE_POP_REG_RANGE_R4_R14 = 0xa8, + + // Format: 10110000 + // Purpose: finish + UNWIND_OPCODE_FINISH = 0xb0, + + // Format: 10110001 0000xxxx + // Purpose: pop r[3:0] + // Constraint: x != 0 + UNWIND_OPCODE_POP_REG_MASK = 0xb100, + + // Format: 10110010 x(uleb128) + // Purpose: vsp = vsp + ((x << 2) + 0x204) + UNWIND_OPCODE_INC_VSP_ULEB128 = 0xb2, + + // Format: 10110011 xxxxyyyy + // Purpose: pop d[(x+y):x] + UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDX = 0xb300, + + // Format: 10111xxx + // Purpose: pop d[(8+x):8] + UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDX_D8 = 0xb8, + + // Format: 11000xxx + // Purpose: pop wR[(10+x):10] + UNWIND_OPCODE_POP_WIRELESS_MMX_REG_RANGE_WR10 = 0xc0, + + // Format: 11000110 xxxxyyyy + // Purpose: pop wR[(x+y):x] + UNWIND_OPCODE_POP_WIRELESS_MMX_REG_RANGE = 0xc600, + + // Format: 11000111 0000xxxx + // Purpose: pop wCGR[3:0] + // Constraint: x != 0 + UNWIND_OPCODE_POP_WIRELESS_MMX_REG_MASK = 0xc700, + + // Format: 11001000 xxxxyyyy + // Purpose: pop d[(16+x+y):(16+x)] + UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D16 = 0xc800, + + // Format: 11001001 xxxxyyyy + // Purpose: pop d[(x+y):x] + UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD = 0xc900, + + // Format: 11010xxx + // Purpose: pop d[(8+x):8] + UNWIND_OPCODE_POP_VFP_REG_RANGE_FSTMFDD_D8 = 0xd0 + }; + + /// ARM-defined Personality Routine Index + enum PersonalityRoutineIndex { + // To make the exception handling table become more compact, ARM defined + // several personality routines in EHABI. There are 3 different + // personality routines in ARM EHABI currently. It is possible to have 16 + // pre-defined personality routines at most. + AEABI_UNWIND_CPP_PR0 = 0, + AEABI_UNWIND_CPP_PR1 = 1, + AEABI_UNWIND_CPP_PR2 = 2, + + NUM_PERSONALITY_INDEX + }; +} +} +} + +#endif // ARM_UNWIND_OP_H diff --git a/contrib/llvm/include/llvm/Support/ARMWinEH.h b/contrib/llvm/include/llvm/Support/ARMWinEH.h new file mode 100644 index 0000000..78deb8d --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/include/llvm/Support/AlignOf.h b/contrib/llvm/include/llvm/Support/AlignOf.h index bba3424..061d5ac 100644 --- a/contrib/llvm/include/llvm/Support/AlignOf.h +++ b/contrib/llvm/include/llvm/Support/AlignOf.h @@ -170,19 +170,22 @@ LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128) namespace detail { template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char, - typename T5 = char, typename T6 = char, typename T7 = char> + typename T5 = char, typename T6 = char, typename T7 = char, + typename T8 = char, typename T9 = char, typename T10 = char> class AlignerImpl { - T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; + T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10; AlignerImpl(); // Never defined or instantiated. }; template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char, - typename T5 = char, typename T6 = char, typename T7 = char> + typename T5 = char, typename T6 = char, typename T7 = char, + typename T8 = char, typename T9 = char, typename T10 = char> union SizerImpl { char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)], - arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)]; + arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)], + arr9[sizeof(T9)], arr10[sizeof(T10)]; }; } // end namespace detail @@ -195,10 +198,13 @@ union SizerImpl { /// be added at the cost of more boiler plate. template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char, - typename T5 = char, typename T6 = char, typename T7 = char> + typename T5 = char, typename T6 = char, typename T7 = char, + typename T8 = char, typename T9 = char, typename T10 = char> struct AlignedCharArrayUnion : llvm::AlignedCharArray< - AlignOf<detail::AlignerImpl<T1, T2, T3, T4, T5, T6, T7> >::Alignment, - sizeof(detail::SizerImpl<T1, T2, T3, T4, T5, T6, T7>)> { + AlignOf<detail::AlignerImpl<T1, T2, T3, T4, T5, + T6, T7, T8, T9, T10> >::Alignment, + sizeof(detail::SizerImpl<T1, T2, T3, T4, T5, + T6, T7, T8, T9, T10>)> { }; } // end namespace llvm #endif diff --git a/contrib/llvm/include/llvm/Support/Allocator.h b/contrib/llvm/include/llvm/Support/Allocator.h index 397f50f..7a7e4c0 100644 --- a/contrib/llvm/include/llvm/Support/Allocator.h +++ b/contrib/llvm/include/llvm/Support/Allocator.h @@ -6,227 +6,408 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the MallocAllocator and BumpPtrAllocator interfaces. -// +/// \file +/// +/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both +/// of these conform to an LLVM "Allocator" concept which consists of an +/// Allocate method accepting a size and alignment, and a Deallocate accepting +/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of +/// Allocate and Deallocate for setting size and alignment based on the final +/// type. These overloads are typically provided by a base class template \c +/// AllocatorBase. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_ALLOCATOR_H #define LLVM_SUPPORT_ALLOCATOR_H +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Memory.h" #include <algorithm> #include <cassert> #include <cstddef> #include <cstdlib> namespace llvm { -template <typename T> struct ReferenceAdder { typedef T& result; }; -template <typename T> struct ReferenceAdder<T&> { typedef T result; }; -class MallocAllocator { +/// \brief CRTP base class providing obvious overloads for the core \c +/// Allocate() methods of LLVM-style allocators. +/// +/// This base class both documents the full public interface exposed by all +/// LLVM-style allocators, and redirects all of the overloads to a single core +/// set of methods which the derived class must define. +template <typename DerivedT> class AllocatorBase { public: - MallocAllocator() {} - ~MallocAllocator() {} + /// \brief Allocate \a Size bytes of \a Alignment aligned memory. This method + /// must be implemented by \c DerivedT. + void *Allocate(size_t Size, size_t Alignment) { +#ifdef __clang__ + static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>( + &AllocatorBase::Allocate) != + static_cast<void *(DerivedT::*)(size_t, size_t)>( + &DerivedT::Allocate), + "Class derives from AllocatorBase without implementing the " + "core Allocate(size_t, size_t) overload!"); +#endif + return static_cast<DerivedT *>(this)->Allocate(Size, Alignment); + } + + /// \brief Deallocate \a Ptr to \a Size bytes of memory allocated by this + /// allocator. + void Deallocate(const void *Ptr, size_t Size) { +#ifdef __clang__ + static_assert(static_cast<void (AllocatorBase::*)(const void *, size_t)>( + &AllocatorBase::Deallocate) != + static_cast<void (DerivedT::*)(const void *, size_t)>( + &DerivedT::Deallocate), + "Class derives from AllocatorBase without implementing the " + "core Deallocate(void *) overload!"); +#endif + return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size); + } + + // The rest of these methods are helpers that redirect to one of the above + // core methods. + + /// \brief Allocate space for a sequence of objects without constructing them. + template <typename T> T *Allocate(size_t Num = 1) { + return static_cast<T *>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment)); + } + /// \brief Deallocate space for a sequence of objects without constructing them. + template <typename T> + typename std::enable_if< + !std::is_same<typename std::remove_cv<T>::type, void>::value, void>::type + Deallocate(T *Ptr, size_t Num = 1) { + Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T)); + } +}; + +class MallocAllocator : public AllocatorBase<MallocAllocator> { +public: void Reset() {} void *Allocate(size_t Size, size_t /*Alignment*/) { return malloc(Size); } - template <typename T> - T *Allocate() { return static_cast<T*>(malloc(sizeof(T))); } + // Pull in base class overloads. + using AllocatorBase<MallocAllocator>::Allocate; - template <typename T> - T *Allocate(size_t Num) { - return static_cast<T*>(malloc(sizeof(T)*Num)); + void Deallocate(const void *Ptr, size_t /*Size*/) { + free(const_cast<void *>(Ptr)); } - void Deallocate(const void *Ptr) { free(const_cast<void*>(Ptr)); } + // Pull in base class overloads. + using AllocatorBase<MallocAllocator>::Deallocate; void PrintStats() const {} }; -/// MemSlab - This structure lives at the beginning of every slab allocated by -/// the bump allocator. -class MemSlab { +namespace detail { + +// We call out to an external function to actually print the message as the +// printing code uses Allocator.h in its implementation. +void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, + size_t TotalMemory); +} // End namespace detail. + +/// \brief Allocate memory in an ever growing pool, as if by bump-pointer. +/// +/// This isn't strictly a bump-pointer allocator as it uses backing slabs of +/// memory rather than relying on boundless contiguous heap. However, it has +/// bump-pointer semantics in that is a monotonically growing pool of memory +/// where every allocation is found by merely allocating the next N bytes in +/// the slab, or the next N bytes in the next slab. +/// +/// Note that this also has a threshold for forcing allocations above a certain +/// size into their own slab. +/// +/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator +/// object, which wraps malloc, to allocate memory, but it can be changed to +/// use a custom allocator. +template <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096, + size_t SizeThreshold = SlabSize> +class BumpPtrAllocatorImpl + : public AllocatorBase< + BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>> { public: - size_t Size; - MemSlab *NextPtr; -}; + static_assert(SizeThreshold <= SlabSize, + "The SizeThreshold must be at most the SlabSize to ensure " + "that objects larger than a slab go into their own memory " + "allocation."); -/// SlabAllocator - This class can be used to parameterize the underlying -/// allocation strategy for the bump allocator. In particular, this is used -/// by the JIT to allocate contiguous swathes of executable memory. The -/// interface uses MemSlab's instead of void *'s so that the allocator -/// doesn't have to remember the size of the pointer it allocated. -class SlabAllocator { -public: - virtual ~SlabAllocator(); - virtual MemSlab *Allocate(size_t Size) = 0; - virtual void Deallocate(MemSlab *Slab) = 0; -}; + BumpPtrAllocatorImpl() + : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {} + template <typename T> + BumpPtrAllocatorImpl(T &&Allocator) + : CurPtr(nullptr), End(nullptr), BytesAllocated(0), + Allocator(std::forward<T &&>(Allocator)) {} + + // Manually implement a move constructor as we must clear the old allocators + // slabs as a matter of correctness. + BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) + : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), + CustomSizedSlabs(std::move(Old.CustomSizedSlabs)), + BytesAllocated(Old.BytesAllocated), + Allocator(std::move(Old.Allocator)) { + Old.CurPtr = Old.End = nullptr; + Old.BytesAllocated = 0; + Old.Slabs.clear(); + Old.CustomSizedSlabs.clear(); + } -/// MallocSlabAllocator - The default slab allocator for the bump allocator -/// is an adapter class for MallocAllocator that just forwards the method -/// calls and translates the arguments. -class MallocSlabAllocator : public SlabAllocator { - /// Allocator - The underlying allocator that we forward to. - /// - MallocAllocator Allocator; + ~BumpPtrAllocatorImpl() { + DeallocateSlabs(Slabs.begin(), Slabs.end()); + DeallocateCustomSizedSlabs(); + } -public: - MallocSlabAllocator() : Allocator() { } - virtual ~MallocSlabAllocator(); - virtual MemSlab *Allocate(size_t Size) LLVM_OVERRIDE; - virtual void Deallocate(MemSlab *Slab) LLVM_OVERRIDE; -}; + BumpPtrAllocatorImpl &operator=(BumpPtrAllocatorImpl &&RHS) { + DeallocateSlabs(Slabs.begin(), Slabs.end()); + DeallocateCustomSizedSlabs(); + + CurPtr = RHS.CurPtr; + End = RHS.End; + BytesAllocated = RHS.BytesAllocated; + Slabs = std::move(RHS.Slabs); + CustomSizedSlabs = std::move(RHS.CustomSizedSlabs); + Allocator = std::move(RHS.Allocator); + + RHS.CurPtr = RHS.End = nullptr; + RHS.BytesAllocated = 0; + RHS.Slabs.clear(); + RHS.CustomSizedSlabs.clear(); + return *this; + } -/// BumpPtrAllocator - This allocator is useful for containers that need -/// very simple memory allocation strategies. In particular, this just keeps -/// allocating memory, and never deletes it until the entire block is dead. This -/// makes allocation speedy, but must only be used when the trade-off is ok. -class BumpPtrAllocator { - BumpPtrAllocator(const BumpPtrAllocator &) LLVM_DELETED_FUNCTION; - void operator=(const BumpPtrAllocator &) LLVM_DELETED_FUNCTION; + /// \brief Deallocate all but the current slab and reset the current pointer + /// to the beginning of it, freeing all memory allocated so far. + void Reset() { + if (Slabs.empty()) + return; + + // Reset the state. + BytesAllocated = 0; + CurPtr = (char *)Slabs.front(); + End = CurPtr + SlabSize; + + // Deallocate all but the first slab, and all custome sized slabs. + DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); + Slabs.erase(std::next(Slabs.begin()), Slabs.end()); + DeallocateCustomSizedSlabs(); + CustomSizedSlabs.clear(); + } - /// SlabSize - Allocate data into slabs of this size unless we get an - /// allocation above SizeThreshold. - size_t SlabSize; + /// \brief Allocate space at the specified alignment. + void *Allocate(size_t Size, size_t Alignment) { + if (!CurPtr) // Start a new slab if we haven't allocated one already. + StartNewSlab(); + + // Keep track of how many bytes we've allocated. + BytesAllocated += Size; + + // 0-byte alignment means 1-byte alignment. + if (Alignment == 0) + Alignment = 1; + + // Allocate the aligned space, going forwards from CurPtr. + char *Ptr = alignPtr(CurPtr, Alignment); + + // Check if we can hold it. + if (Ptr + Size <= End) { + CurPtr = Ptr + Size; + // Update the allocation point of this memory block in MemorySanitizer. + // Without this, MemorySanitizer messages for values originated from here + // will point to the allocation of the entire slab. + __msan_allocated_memory(Ptr, Size); + return Ptr; + } - /// SizeThreshold - For any allocation larger than this threshold, we should - /// allocate a separate slab. - size_t SizeThreshold; + // If Size is really big, allocate a separate slab for it. + size_t PaddedSize = Size + Alignment - 1; + if (PaddedSize > SizeThreshold) { + void *NewSlab = Allocator.Allocate(PaddedSize, 0); + CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize)); - /// \brief the default allocator used if one is not provided - MallocSlabAllocator DefaultSlabAllocator; + Ptr = alignPtr((char *)NewSlab, Alignment); + assert((uintptr_t)Ptr + Size <= (uintptr_t)NewSlab + PaddedSize); + __msan_allocated_memory(Ptr, Size); + return Ptr; + } - /// Allocator - The underlying allocator we use to get slabs of memory. This - /// defaults to MallocSlabAllocator, which wraps malloc, but it could be - /// changed to use a custom allocator. - SlabAllocator &Allocator; + // Otherwise, start a new slab and try again. + StartNewSlab(); + Ptr = alignPtr(CurPtr, Alignment); + CurPtr = Ptr + Size; + assert(CurPtr <= End && "Unable to allocate memory!"); + __msan_allocated_memory(Ptr, Size); + return Ptr; + } - /// CurSlab - The slab that we are currently allocating into. - /// - MemSlab *CurSlab; + // Pull in base class overloads. + using AllocatorBase<BumpPtrAllocatorImpl>::Allocate; - /// CurPtr - The current pointer into the current slab. This points to the - /// next free byte in the slab. - char *CurPtr; + void Deallocate(const void * /*Ptr*/, size_t /*Size*/) {} - /// End - The end of the current slab. - /// - char *End; + // Pull in base class overloads. + using AllocatorBase<BumpPtrAllocatorImpl>::Deallocate; - /// BytesAllocated - This field tracks how many bytes we've allocated, so - /// that we can compute how much space was wasted. - size_t BytesAllocated; + size_t GetNumSlabs() const { return Slabs.size() + CustomSizedSlabs.size(); } - /// AlignPtr - Align Ptr to Alignment bytes, rounding up. Alignment should - /// be a power of two. This method rounds up, so AlignPtr(7, 4) == 8 and - /// AlignPtr(8, 4) == 8. - static char *AlignPtr(char *Ptr, size_t Alignment); + size_t getTotalMemory() const { + size_t TotalMemory = 0; + for (auto I = Slabs.begin(), E = Slabs.end(); I != E; ++I) + TotalMemory += computeSlabSize(std::distance(Slabs.begin(), I)); + for (auto &PtrAndSize : CustomSizedSlabs) + TotalMemory += PtrAndSize.second; + return TotalMemory; + } - /// StartNewSlab - Allocate a new slab and move the bump pointers over into - /// the new slab. Modifies CurPtr and End. - void StartNewSlab(); + void PrintStats() const { + detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated, + getTotalMemory()); + } - /// DeallocateSlabs - Deallocate all memory slabs after and including this - /// one. - void DeallocateSlabs(MemSlab *Slab); +private: + /// \brief The current pointer into the current slab. + /// + /// This points to the next free byte in the slab. + char *CurPtr; - template<typename T> friend class SpecificBumpPtrAllocator; -public: - BumpPtrAllocator(size_t size = 4096, size_t threshold = 4096); - BumpPtrAllocator(size_t size, size_t threshold, SlabAllocator &allocator); - ~BumpPtrAllocator(); + /// \brief The end of the current slab. + char *End; - /// Reset - Deallocate all but the current slab and reset the current pointer - /// to the beginning of it, freeing all memory allocated so far. - void Reset(); + /// \brief The slabs allocated so far. + SmallVector<void *, 4> Slabs; - /// Allocate - Allocate space at the specified alignment. - /// - void *Allocate(size_t Size, size_t Alignment); + /// \brief Custom-sized slabs allocated for too-large allocation requests. + SmallVector<std::pair<void *, size_t>, 0> CustomSizedSlabs; - /// Allocate space, but do not construct, one object. + /// \brief How many bytes we've allocated. /// - template <typename T> - T *Allocate() { - return static_cast<T*>(Allocate(sizeof(T),AlignOf<T>::Alignment)); - } + /// Used so that we can compute how much space was wasted. + size_t BytesAllocated; - /// Allocate space for an array of objects. This does not construct the - /// objects though. - template <typename T> - T *Allocate(size_t Num) { - return static_cast<T*>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment)); + /// \brief The allocator instance we use to get slabs of memory. + AllocatorT Allocator; + + static size_t computeSlabSize(unsigned SlabIdx) { + // Scale the actual allocated slab size based on the number of slabs + // allocated. Every 128 slabs allocated, we double the allocated size to + // reduce allocation frequency, but saturate at multiplying the slab size by + // 2^30. + return SlabSize * ((size_t)1 << std::min<size_t>(30, SlabIdx / 128)); } - /// Allocate space for a specific count of elements and with a specified - /// alignment. - template <typename T> - T *Allocate(size_t Num, size_t Alignment) { - // Round EltSize up to the specified alignment. - size_t EltSize = (sizeof(T)+Alignment-1)&(-Alignment); - return static_cast<T*>(Allocate(Num * EltSize, Alignment)); + /// \brief Allocate a new slab and move the bump pointers over into the new + /// slab, modifying CurPtr and End. + void StartNewSlab() { + size_t AllocatedSlabSize = computeSlabSize(Slabs.size()); + + void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0); + Slabs.push_back(NewSlab); + CurPtr = (char *)(NewSlab); + End = ((char *)NewSlab) + AllocatedSlabSize; } - void Deallocate(const void * /*Ptr*/) {} + /// \brief Deallocate a sequence of slabs. + void DeallocateSlabs(SmallVectorImpl<void *>::iterator I, + SmallVectorImpl<void *>::iterator E) { + for (; I != E; ++I) { + size_t AllocatedSlabSize = + computeSlabSize(std::distance(Slabs.begin(), I)); +#ifndef NDEBUG + // Poison the memory so stale pointers crash sooner. Note we must + // preserve the Size and NextPtr fields at the beginning. + sys::Memory::setRangeWritable(*I, AllocatedSlabSize); + memset(*I, 0xCD, AllocatedSlabSize); +#endif + Allocator.Deallocate(*I, AllocatedSlabSize); + } + } - unsigned GetNumSlabs() const; + /// \brief Deallocate all memory for custom sized slabs. + void DeallocateCustomSizedSlabs() { + for (auto &PtrAndSize : CustomSizedSlabs) { + void *Ptr = PtrAndSize.first; + size_t Size = PtrAndSize.second; +#ifndef NDEBUG + // Poison the memory so stale pointers crash sooner. Note we must + // preserve the Size and NextPtr fields at the beginning. + sys::Memory::setRangeWritable(Ptr, Size); + memset(Ptr, 0xCD, Size); +#endif + Allocator.Deallocate(Ptr, Size); + } + } - void PrintStats() const; - - /// Compute the total physical memory allocated by this allocator. - size_t getTotalMemory() const; + template <typename T> friend class SpecificBumpPtrAllocator; }; -/// SpecificBumpPtrAllocator - Same as BumpPtrAllocator but allows only -/// elements of one type to be allocated. This allows calling the destructor -/// in DestroyAll() and when the allocator is destroyed. -template <typename T> -class SpecificBumpPtrAllocator { +/// \brief The standard BumpPtrAllocator which just uses the default template +/// paramaters. +typedef BumpPtrAllocatorImpl<> BumpPtrAllocator; + +/// \brief A BumpPtrAllocator that allows only elements of a specific type to be +/// allocated. +/// +/// This allows calling the destructor in DestroyAll() and when the allocator is +/// destroyed. +template <typename T> class SpecificBumpPtrAllocator { BumpPtrAllocator Allocator; -public: - SpecificBumpPtrAllocator(size_t size = 4096, size_t threshold = 4096) - : Allocator(size, threshold) {} - SpecificBumpPtrAllocator(size_t size, size_t threshold, - SlabAllocator &allocator) - : Allocator(size, threshold, allocator) {} - ~SpecificBumpPtrAllocator() { - DestroyAll(); +public: + SpecificBumpPtrAllocator() : Allocator() {} + SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old) + : Allocator(std::move(Old.Allocator)) {} + ~SpecificBumpPtrAllocator() { DestroyAll(); } + + SpecificBumpPtrAllocator &operator=(SpecificBumpPtrAllocator &&RHS) { + Allocator = std::move(RHS.Allocator); + return *this; } /// Call the destructor of each allocated object and deallocate all but the /// current slab and reset the current pointer to the beginning of it, freeing /// all memory allocated so far. void DestroyAll() { - MemSlab *Slab = Allocator.CurSlab; - while (Slab) { - char *End = Slab == Allocator.CurSlab ? Allocator.CurPtr : - (char *)Slab + Slab->Size; - for (char *Ptr = (char*)(Slab+1); Ptr < End; Ptr += sizeof(T)) { - Ptr = Allocator.AlignPtr(Ptr, alignOf<T>()); - if (Ptr + sizeof(T) <= End) - reinterpret_cast<T*>(Ptr)->~T(); - } - Slab = Slab->NextPtr; + auto DestroyElements = [](char *Begin, char *End) { + assert(Begin == alignPtr(Begin, alignOf<T>())); + for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T)) + reinterpret_cast<T *>(Ptr)->~T(); + }; + + for (auto I = Allocator.Slabs.begin(), E = Allocator.Slabs.end(); I != E; + ++I) { + size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize( + std::distance(Allocator.Slabs.begin(), I)); + char *Begin = alignPtr((char *)*I, alignOf<T>()); + char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr + : (char *)*I + AllocatedSlabSize; + + DestroyElements(Begin, End); + } + + for (auto &PtrAndSize : Allocator.CustomSizedSlabs) { + void *Ptr = PtrAndSize.first; + size_t Size = PtrAndSize.second; + DestroyElements(alignPtr((char *)Ptr, alignOf<T>()), (char *)Ptr + Size); } + Allocator.Reset(); } - /// Allocate space for a specific count of elements. - T *Allocate(size_t num = 1) { - return Allocator.Allocate<T>(num); - } + /// \brief Allocate space for an array of objects without constructing them. + T *Allocate(size_t num = 1) { return Allocator.Allocate<T>(num); } }; } // end namespace llvm -inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) { +template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold> +void *operator new(size_t Size, + llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, + SizeThreshold> &Allocator) { struct S { char c; union { @@ -236,10 +417,13 @@ inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) { void *P; } x; }; - return Allocator.Allocate(Size, std::min((size_t)llvm::NextPowerOf2(Size), - offsetof(S, x))); + return Allocator.Allocate( + Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x))); } -inline void operator delete(void *, llvm::BumpPtrAllocator &) {} +template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold> +void operator delete( + void *, llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold> &) { +} #endif // LLVM_SUPPORT_ALLOCATOR_H diff --git a/contrib/llvm/include/llvm/Support/ArrayRecycler.h b/contrib/llvm/include/llvm/Support/ArrayRecycler.h index c7e0cba..36f644a 100644 --- a/contrib/llvm/include/llvm/Support/ArrayRecycler.h +++ b/contrib/llvm/include/llvm/Support/ArrayRecycler.h @@ -16,12 +16,11 @@ #define LLVM_SUPPORT_ARRAYRECYCLER_H #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/MathExtras.h" namespace llvm { -class BumpPtrAllocator; - /// Recycle small arrays allocated from a BumpPtrAllocator. /// /// Arrays are allocated in a small number of fixed sizes. For each supported @@ -35,6 +34,9 @@ class ArrayRecycler { FreeList *Next; }; + static_assert(Align >= AlignOf<FreeList>::Alignment, "Object underaligned"); + static_assert(sizeof(T) >= sizeof(FreeList), "Objects are too small"); + // Keep a free list for each array size. SmallVector<FreeList*, 8> Bucket; @@ -42,10 +44,10 @@ class ArrayRecycler { // Return NULL if no entries are available. T *pop(unsigned Idx) { if (Idx >= Bucket.size()) - return 0; + return nullptr; FreeList *Entry = Bucket[Idx]; if (!Entry) - return 0; + return nullptr; Bucket[Idx] = Entry->Next; return reinterpret_cast<T*>(Entry); } @@ -53,8 +55,6 @@ class ArrayRecycler { // Add an entry to the free list at Bucket[Idx]. void push(unsigned Idx, T *Ptr) { assert(Ptr && "Cannot recycle NULL pointer"); - assert(sizeof(T) >= sizeof(FreeList) && "Objects are too small"); - assert(Align >= AlignOf<FreeList>::Alignment && "Object underaligned"); FreeList *Entry = reinterpret_cast<FreeList*>(Ptr); if (Idx >= Bucket.size()) Bucket.resize(size_t(Idx) + 1); diff --git a/contrib/llvm/include/llvm/Support/BlockFrequency.h b/contrib/llvm/include/llvm/Support/BlockFrequency.h index 21879e7..4304a25 100644 --- a/contrib/llvm/include/llvm/Support/BlockFrequency.h +++ b/contrib/llvm/include/llvm/Support/BlockFrequency.h @@ -23,21 +23,11 @@ class BranchProbability; // This class represents Block Frequency as a 64-bit value. class BlockFrequency { - uint64_t Frequency; - static const int64_t ENTRY_FREQ = 1 << 14; - - /// \brief Scale the given BlockFrequency by N/D. Return the remainder from - /// the division by D. Upon overflow, the routine will saturate and - /// additionally will return the remainder set to D. - uint32_t scale(uint32_t N, uint32_t D); public: BlockFrequency(uint64_t Freq = 0) : Frequency(Freq) { } - /// \brief Returns the frequency of the entry block of the function. - static uint64_t getEntryFrequency() { return ENTRY_FREQ; } - /// \brief Returns the maximum possible frequency, the saturation value. static uint64_t getMaxFrequency() { return -1ULL; } @@ -59,9 +49,8 @@ public: BlockFrequency &operator+=(const BlockFrequency &Freq); const BlockFrequency operator+(const BlockFrequency &Freq) const; - /// \brief Scale the given BlockFrequency by N/D. Return the remainder from - /// the division by D. Upon overflow, the routine will saturate. - uint32_t scale(const BranchProbability &Prob); + /// \brief Shift block frequency to the right by count digits saturating to 1. + BlockFrequency &operator>>=(const unsigned count); bool operator<(const BlockFrequency &RHS) const { return Frequency < RHS.Frequency; @@ -78,12 +67,8 @@ public: bool operator>=(const BlockFrequency &RHS) const { return Frequency >= RHS.Frequency; } - - void print(raw_ostream &OS) const; }; -raw_ostream &operator<<(raw_ostream &OS, const BlockFrequency &Freq); - } #endif diff --git a/contrib/llvm/include/llvm/Support/BranchProbability.h b/contrib/llvm/include/llvm/Support/BranchProbability.h index eedf692..9aab6ac 100644 --- a/contrib/llvm/include/llvm/Support/BranchProbability.h +++ b/contrib/llvm/include/llvm/Support/BranchProbability.h @@ -46,10 +46,26 @@ public: return BranchProbability(D - N, D); } - void print(raw_ostream &OS) const; + raw_ostream &print(raw_ostream &OS) const; void dump() const; + /// \brief Scale a large integer. + /// + /// Scales \c Num. Guarantees full precision. Returns the floor of the + /// result. + /// + /// \return \c Num times \c this. + uint64_t scale(uint64_t Num) const; + + /// \brief Scale a large integer by the inverse. + /// + /// Scales \c Num by the inverse of \c this. Guarantees full precision. + /// Returns the floor of the result. + /// + /// \return \c Num divided by \c this. + uint64_t scaleByInverse(uint64_t Num) const; + bool operator==(BranchProbability RHS) const { return (uint64_t)N * RHS.D == (uint64_t)D * RHS.N; } @@ -59,18 +75,14 @@ public: bool operator<(BranchProbability RHS) const { return (uint64_t)N * RHS.D < (uint64_t)D * RHS.N; } - bool operator>(BranchProbability RHS) const { - return RHS < *this; - } - bool operator<=(BranchProbability RHS) const { - return (uint64_t)N * RHS.D <= (uint64_t)D * RHS.N; - } - bool operator>=(BranchProbability RHS) const { - return RHS <= *this; - } + bool operator>(BranchProbability RHS) const { return RHS < *this; } + bool operator<=(BranchProbability RHS) const { return !(RHS < *this); } + bool operator>=(BranchProbability RHS) const { return !(*this < RHS); } }; -raw_ostream &operator<<(raw_ostream &OS, const BranchProbability &Prob); +inline raw_ostream &operator<<(raw_ostream &OS, const BranchProbability &Prob) { + return Prob.print(OS); +} } diff --git a/contrib/llvm/include/llvm/Support/CFG.h b/contrib/llvm/include/llvm/Support/CFG.h deleted file mode 100644 index 74ec726..0000000 --- a/contrib/llvm/include/llvm/Support/CFG.h +++ /dev/null @@ -1,365 +0,0 @@ -//===-- llvm/Support/CFG.h - Process LLVM structures as graphs --*- 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 specializations of GraphTraits that allow Function and -// BasicBlock graphs to be treated as proper graphs for generic algorithms. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_CFG_H -#define LLVM_SUPPORT_CFG_H - -#include "llvm/ADT/GraphTraits.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstrTypes.h" - -namespace llvm { - -//===----------------------------------------------------------------------===// -// BasicBlock pred_iterator definition -//===----------------------------------------------------------------------===// - -template <class Ptr, class USE_iterator> // Predecessor Iterator -class PredIterator : public std::iterator<std::forward_iterator_tag, - Ptr, ptrdiff_t, Ptr*, Ptr*> { - typedef std::iterator<std::forward_iterator_tag, Ptr, ptrdiff_t, Ptr*, - Ptr*> super; - typedef PredIterator<Ptr, USE_iterator> Self; - USE_iterator It; - - inline void advancePastNonTerminators() { - // Loop to ignore non terminator uses (for example BlockAddresses). - while (!It.atEnd() && !isa<TerminatorInst>(*It)) - ++It; - } - -public: - typedef typename super::pointer pointer; - typedef typename super::reference reference; - - PredIterator() {} - explicit inline PredIterator(Ptr *bb) : It(bb->use_begin()) { - advancePastNonTerminators(); - } - inline PredIterator(Ptr *bb, bool) : It(bb->use_end()) {} - - inline bool operator==(const Self& x) const { return It == x.It; } - inline bool operator!=(const Self& x) const { return !operator==(x); } - - inline reference operator*() const { - assert(!It.atEnd() && "pred_iterator out of range!"); - return cast<TerminatorInst>(*It)->getParent(); - } - inline pointer *operator->() const { return &operator*(); } - - inline Self& operator++() { // Preincrement - assert(!It.atEnd() && "pred_iterator out of range!"); - ++It; advancePastNonTerminators(); - return *this; - } - - inline Self operator++(int) { // Postincrement - Self tmp = *this; ++*this; return tmp; - } - - /// getOperandNo - Return the operand number in the predecessor's - /// terminator of the successor. - unsigned getOperandNo() const { - return It.getOperandNo(); - } - - /// getUse - Return the operand Use in the predecessor's terminator - /// of the successor. - Use &getUse() const { - return It.getUse(); - } -}; - -typedef PredIterator<BasicBlock, Value::use_iterator> pred_iterator; -typedef PredIterator<const BasicBlock, - Value::const_use_iterator> const_pred_iterator; - -inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } -inline const_pred_iterator pred_begin(const BasicBlock *BB) { - return const_pred_iterator(BB); -} -inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} -inline const_pred_iterator pred_end(const BasicBlock *BB) { - return const_pred_iterator(BB, true); -} - - - -//===----------------------------------------------------------------------===// -// BasicBlock succ_iterator definition -//===----------------------------------------------------------------------===// - -template <class Term_, class BB_> // Successor Iterator -class SuccIterator : public std::iterator<std::bidirectional_iterator_tag, - BB_, ptrdiff_t, BB_*, BB_*> { - const Term_ Term; - unsigned idx; - typedef std::iterator<std::bidirectional_iterator_tag, BB_, ptrdiff_t, BB_*, - BB_*> super; - typedef SuccIterator<Term_, BB_> Self; - - inline bool index_is_valid(int idx) { - return idx >= 0 && (unsigned) idx < Term->getNumSuccessors(); - } - -public: - typedef typename super::pointer pointer; - typedef typename super::reference reference; - // TODO: This can be random access iterator, only operator[] missing. - - explicit inline SuccIterator(Term_ T) : Term(T), idx(0) {// begin iterator - } - inline SuccIterator(Term_ T, bool) // end iterator - : Term(T) { - if (Term) - idx = Term->getNumSuccessors(); - else - // Term == NULL happens, if a basic block is not fully constructed and - // consequently getTerminator() returns NULL. In this case we construct a - // SuccIterator which describes a basic block that has zero successors. - // Defining SuccIterator for incomplete and malformed CFGs is especially - // useful for debugging. - idx = 0; - } - - inline const Self &operator=(const Self &I) { - assert(Term == I.Term &&"Cannot assign iterators to two different blocks!"); - idx = I.idx; - return *this; - } - - /// getSuccessorIndex - This is used to interface between code that wants to - /// operate on terminator instructions directly. - unsigned getSuccessorIndex() const { return idx; } - - inline bool operator==(const Self& x) const { return idx == x.idx; } - inline bool operator!=(const Self& x) const { return !operator==(x); } - - inline reference operator*() const { return Term->getSuccessor(idx); } - inline pointer operator->() const { return operator*(); } - - inline Self& operator++() { ++idx; return *this; } // Preincrement - - inline Self operator++(int) { // Postincrement - Self tmp = *this; ++*this; return tmp; - } - - inline Self& operator--() { --idx; return *this; } // Predecrement - inline Self operator--(int) { // Postdecrement - Self tmp = *this; --*this; return tmp; - } - - inline bool operator<(const Self& x) const { - assert(Term == x.Term && "Cannot compare iterators of different blocks!"); - return idx < x.idx; - } - - inline bool operator<=(const Self& x) const { - assert(Term == x.Term && "Cannot compare iterators of different blocks!"); - return idx <= x.idx; - } - inline bool operator>=(const Self& x) const { - assert(Term == x.Term && "Cannot compare iterators of different blocks!"); - return idx >= x.idx; - } - - inline bool operator>(const Self& x) const { - assert(Term == x.Term && "Cannot compare iterators of different blocks!"); - return idx > x.idx; - } - - inline Self& operator+=(int Right) { - unsigned new_idx = idx + Right; - assert(index_is_valid(new_idx) && "Iterator index out of bound"); - idx = new_idx; - return *this; - } - - inline Self operator+(int Right) { - Self tmp = *this; - tmp += Right; - return tmp; - } - - inline Self& operator-=(int Right) { - return operator+=(-Right); - } - - inline Self operator-(int Right) { - return operator+(-Right); - } - - inline int operator-(const Self& x) { - assert(Term == x.Term && "Cannot work on iterators of different blocks!"); - int distance = idx - x.idx; - return distance; - } - - // This works for read access, however write access is difficult as changes - // to Term are only possible with Term->setSuccessor(idx). Pointers that can - // be modified are not available. - // - // inline pointer operator[](int offset) { - // Self tmp = *this; - // tmp += offset; - // return tmp.operator*(); - // } - - /// Get the source BB of this iterator. - inline BB_ *getSource() { - assert(Term && "Source not available, if basic block was malformed"); - return Term->getParent(); - } -}; - -typedef SuccIterator<TerminatorInst*, BasicBlock> succ_iterator; -typedef SuccIterator<const TerminatorInst*, - const BasicBlock> succ_const_iterator; - -inline succ_iterator succ_begin(BasicBlock *BB) { - return succ_iterator(BB->getTerminator()); -} -inline succ_const_iterator succ_begin(const BasicBlock *BB) { - return succ_const_iterator(BB->getTerminator()); -} -inline succ_iterator succ_end(BasicBlock *BB) { - return succ_iterator(BB->getTerminator(), true); -} -inline succ_const_iterator succ_end(const BasicBlock *BB) { - return succ_const_iterator(BB->getTerminator(), true); -} - -template <typename T, typename U> struct isPodLike<SuccIterator<T, U> > { - static const bool value = isPodLike<T>::value; -}; - - - -//===--------------------------------------------------------------------===// -// GraphTraits specializations for basic block graphs (CFGs) -//===--------------------------------------------------------------------===// - -// Provide specializations of GraphTraits to be able to treat a function as a -// graph of basic blocks... - -template <> struct GraphTraits<BasicBlock*> { - typedef BasicBlock NodeType; - typedef succ_iterator ChildIteratorType; - - static NodeType *getEntryNode(BasicBlock *BB) { return BB; } - static inline ChildIteratorType child_begin(NodeType *N) { - return succ_begin(N); - } - static inline ChildIteratorType child_end(NodeType *N) { - return succ_end(N); - } -}; - -template <> struct GraphTraits<const BasicBlock*> { - typedef const BasicBlock NodeType; - typedef succ_const_iterator ChildIteratorType; - - static NodeType *getEntryNode(const BasicBlock *BB) { return BB; } - - static inline ChildIteratorType child_begin(NodeType *N) { - return succ_begin(N); - } - static inline ChildIteratorType child_end(NodeType *N) { - return succ_end(N); - } -}; - -// Provide specializations of GraphTraits to be able to treat a function as a -// graph of basic blocks... and to walk it in inverse order. Inverse order for -// a function is considered to be when traversing the predecessor edges of a BB -// instead of the successor edges. -// -template <> struct GraphTraits<Inverse<BasicBlock*> > { - typedef BasicBlock NodeType; - typedef pred_iterator ChildIteratorType; - static NodeType *getEntryNode(Inverse<BasicBlock *> G) { return G.Graph; } - static inline ChildIteratorType child_begin(NodeType *N) { - return pred_begin(N); - } - static inline ChildIteratorType child_end(NodeType *N) { - return pred_end(N); - } -}; - -template <> struct GraphTraits<Inverse<const BasicBlock*> > { - typedef const BasicBlock NodeType; - typedef const_pred_iterator ChildIteratorType; - static NodeType *getEntryNode(Inverse<const BasicBlock*> G) { - return G.Graph; - } - static inline ChildIteratorType child_begin(NodeType *N) { - return pred_begin(N); - } - static inline ChildIteratorType child_end(NodeType *N) { - return pred_end(N); - } -}; - - - -//===--------------------------------------------------------------------===// -// GraphTraits specializations for function basic block graphs (CFGs) -//===--------------------------------------------------------------------===// - -// Provide specializations of GraphTraits to be able to treat a function as a -// graph of basic blocks... these are the same as the basic block iterators, -// except that the root node is implicitly the first node of the function. -// -template <> struct GraphTraits<Function*> : public GraphTraits<BasicBlock*> { - static NodeType *getEntryNode(Function *F) { return &F->getEntryBlock(); } - - // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - typedef Function::iterator nodes_iterator; - static nodes_iterator nodes_begin(Function *F) { return F->begin(); } - static nodes_iterator nodes_end (Function *F) { return F->end(); } - static size_t size (Function *F) { return F->size(); } -}; -template <> struct GraphTraits<const Function*> : - public GraphTraits<const BasicBlock*> { - static NodeType *getEntryNode(const Function *F) {return &F->getEntryBlock();} - - // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - typedef Function::const_iterator nodes_iterator; - static nodes_iterator nodes_begin(const Function *F) { return F->begin(); } - static nodes_iterator nodes_end (const Function *F) { return F->end(); } - static size_t size (const Function *F) { return F->size(); } -}; - - -// Provide specializations of GraphTraits to be able to treat a function as a -// graph of basic blocks... and to walk it in inverse order. Inverse order for -// a function is considered to be when traversing the predecessor edges of a BB -// instead of the successor edges. -// -template <> struct GraphTraits<Inverse<Function*> > : - public GraphTraits<Inverse<BasicBlock*> > { - static NodeType *getEntryNode(Inverse<Function*> G) { - return &G.Graph->getEntryBlock(); - } -}; -template <> struct GraphTraits<Inverse<const Function*> > : - public GraphTraits<Inverse<const BasicBlock*> > { - static NodeType *getEntryNode(Inverse<const Function *> G) { - return &G.Graph->getEntryBlock(); - } -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Support/COFF.h b/contrib/llvm/include/llvm/Support/COFF.h index 9cc3989..e09ef07 100644 --- a/contrib/llvm/include/llvm/Support/COFF.h +++ b/contrib/llvm/include/llvm/Support/COFF.h @@ -30,6 +30,9 @@ namespace llvm { namespace COFF { + // The maximum number of sections that a COFF object can have (inclusive). + const int MaxNumberOfSections = 65299; + // The PE signature bytes that follows the DOS stub header. static const char PEMagic[] = { 'P', 'E', '\0', '\0' }; @@ -59,7 +62,7 @@ namespace COFF { IMAGE_FILE_MACHINE_AM33 = 0x13, IMAGE_FILE_MACHINE_AMD64 = 0x8664, IMAGE_FILE_MACHINE_ARM = 0x1C0, - IMAGE_FILE_MACHINE_ARMV7 = 0x1C4, + IMAGE_FILE_MACHINE_ARMNT = 0x1C4, IMAGE_FILE_MACHINE_EBC = 0xEBC, IMAGE_FILE_MACHINE_I386 = 0x14C, IMAGE_FILE_MACHINE_IA64 = 0x200, @@ -138,8 +141,8 @@ namespace COFF { }; enum SymbolSectionNumber { - IMAGE_SYM_DEBUG = -2, - IMAGE_SYM_ABSOLUTE = -1, + IMAGE_SYM_DEBUG = 0xFFFE, + IMAGE_SYM_ABSOLUTE = 0xFFFF, IMAGE_SYM_UNDEFINED = 0 }; @@ -209,6 +212,10 @@ namespace COFF { SCT_COMPLEX_TYPE_SHIFT = 4 }; + enum AuxSymbolType { + IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF = 1 + }; + struct section { char Name[NameSize]; uint32_t VirtualSize; @@ -222,7 +229,7 @@ namespace COFF { uint32_t Characteristics; }; - enum SectionCharacteristics LLVM_ENUM_INT_TYPE(uint32_t) { + enum SectionCharacteristics : uint32_t { SC_Invalid = 0xffffffff, IMAGE_SCN_TYPE_NO_PAD = 0x00000008, @@ -268,7 +275,7 @@ namespace COFF { uint16_t Type; }; - enum RelocationTypeX86 { + enum RelocationTypeI386 { IMAGE_REL_I386_ABSOLUTE = 0x0000, IMAGE_REL_I386_DIR16 = 0x0001, IMAGE_REL_I386_REL16 = 0x0002, @@ -279,8 +286,10 @@ namespace COFF { IMAGE_REL_I386_SECREL = 0x000B, IMAGE_REL_I386_TOKEN = 0x000C, IMAGE_REL_I386_SECREL7 = 0x000D, - IMAGE_REL_I386_REL32 = 0x0014, + IMAGE_REL_I386_REL32 = 0x0014 + }; + enum RelocationTypeAMD64 { IMAGE_REL_AMD64_ABSOLUTE = 0x0000, IMAGE_REL_AMD64_ADDR64 = 0x0001, IMAGE_REL_AMD64_ADDR32 = 0x0002, @@ -334,7 +343,7 @@ namespace COFF { uint32_t TotalSize; uint32_t PointerToLinenumber; uint32_t PointerToNextFunction; - uint8_t unused[2]; + char unused[2]; }; struct AuxiliarybfAndefSymbol { @@ -369,7 +378,14 @@ namespace COFF { uint32_t CheckSum; uint16_t Number; uint8_t Selection; - uint8_t unused[3]; + char unused[3]; + }; + + struct AuxiliaryCLRToken { + uint8_t AuxType; + uint8_t unused1; + uint32_t SymbolTableIndex; + char unused2[12]; }; union Auxiliary { @@ -450,7 +466,12 @@ namespace COFF { uint32_t AddressOfNewExeHeader; }; - struct PEHeader { + struct PE32Header { + enum { + PE32 = 0x10b, + PE32_PLUS = 0x20b + }; + uint16_t Magic; uint8_t MajorLinkerVersion; uint8_t MinorLinkerVersion; @@ -460,7 +481,7 @@ namespace COFF { uint32_t AddressOfEntryPoint; // RVA uint32_t BaseOfCode; // RVA uint32_t BaseOfData; // RVA - uint64_t ImageBase; + uint32_t ImageBase; uint32_t SectionAlignment; uint32_t FileAlignment; uint16_t MajorOperatingSystemVersion; @@ -475,10 +496,10 @@ namespace COFF { uint32_t CheckSum; uint16_t Subsystem; uint16_t DLLCharacteristics; - uint64_t SizeOfStackReserve; - uint64_t SizeOfStackCommit; - uint64_t SizeOfHeapReserve; - uint64_t SizeOfHeapCommit; + uint32_t SizeOfStackReserve; + uint32_t SizeOfStackCommit; + uint32_t SizeOfHeapReserve; + uint32_t SizeOfHeapCommit; uint32_t LoaderFlags; uint32_t NumberOfRvaAndSize; }; @@ -526,11 +547,14 @@ namespace COFF { }; enum DLLCharacteristics { + /// ASLR with 64 bit address space. + IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020, /// DLL can be relocated at load time. 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 @@ -538,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 }; @@ -611,6 +640,17 @@ namespace COFF { } }; + enum CodeViewLineTableIdentifiers { + DEBUG_SECTION_MAGIC = 0x4, + DEBUG_LINE_TABLE_SUBSECTION = 0xF2, + DEBUG_STRING_TABLE_SUBSECTION = 0xF3, + DEBUG_INDEX_SUBSECTION = 0xF4 + }; + + inline bool isReservedSectionNumber(int N) { + return N == IMAGE_SYM_UNDEFINED || N > MaxNumberOfSections; + } + } // End namespace COFF. } // End namespace llvm. diff --git a/contrib/llvm/include/llvm/Support/CallSite.h b/contrib/llvm/include/llvm/Support/CallSite.h deleted file mode 100644 index 2a1c5ca..0000000 --- a/contrib/llvm/include/llvm/Support/CallSite.h +++ /dev/null @@ -1,330 +0,0 @@ -//===-- llvm/Support/CallSite.h - Abstract Call & Invoke instrs -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the CallSite class, which is a handy wrapper for code that -// wants to treat Call and Invoke instructions in a generic way. When in non- -// mutation context (e.g. an analysis) ImmutableCallSite should be used. -// Finally, when some degree of customization is necessary between these two -// extremes, CallSiteBase<> can be supplied with fine-tuned parameters. -// -// NOTE: These classes are supposed to have "value semantics". So they should be -// passed by value, not by reference; they should not be "new"ed or "delete"d. -// They are efficiently copyable, assignable and constructable, with cost -// equivalent to copying a pointer (notice that they have only a single data -// member). The internal representation carries a flag which indicates which of -// the two variants is enclosed. This allows for cheaper checks when various -// accessors of CallSite are employed. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_CALLSITE_H -#define LLVM_SUPPORT_CALLSITE_H - -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/Instructions.h" - -namespace llvm { - -class CallInst; -class InvokeInst; - -template <typename FunTy = const Function, - typename ValTy = const Value, - typename UserTy = const User, - typename InstrTy = const Instruction, - typename CallTy = const CallInst, - typename InvokeTy = const InvokeInst, - typename IterTy = User::const_op_iterator> -class CallSiteBase { -protected: - PointerIntPair<InstrTy*, 1, bool> I; -public: - CallSiteBase() : I(0, false) {} - CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } - CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } - CallSiteBase(ValTy *II) { *this = get(II); } -protected: - /// CallSiteBase::get - This static method is sort of like a constructor. It - /// will create an appropriate call site for a Call or Invoke instruction, but - /// it can also create a null initialized CallSiteBase object for something - /// which is NOT a call site. - /// - static CallSiteBase get(ValTy *V) { - if (InstrTy *II = dyn_cast<InstrTy>(V)) { - if (II->getOpcode() == Instruction::Call) - return CallSiteBase(static_cast<CallTy*>(II)); - else if (II->getOpcode() == Instruction::Invoke) - return CallSiteBase(static_cast<InvokeTy*>(II)); - } - return CallSiteBase(); - } -public: - /// isCall - true if a CallInst is enclosed. - /// Note that !isCall() does not mean it is an InvokeInst enclosed, - /// it also could signify a NULL Instruction pointer. - bool isCall() const { return I.getInt(); } - - /// isInvoke - true if a InvokeInst is enclosed. - /// - bool isInvoke() const { return getInstruction() && !I.getInt(); } - - InstrTy *getInstruction() const { return I.getPointer(); } - InstrTy *operator->() const { return I.getPointer(); } - LLVM_EXPLICIT operator bool() const { return I.getPointer(); } - - /// getCalledValue - Return the pointer to function that is being called. - /// - ValTy *getCalledValue() const { - assert(getInstruction() && "Not a call or invoke instruction!"); - return *getCallee(); - } - - /// getCalledFunction - Return the function being called if this is a direct - /// call, otherwise return null (if it's an indirect call). - /// - FunTy *getCalledFunction() const { - return dyn_cast<FunTy>(getCalledValue()); - } - - /// setCalledFunction - Set the callee to the specified value. - /// - void setCalledFunction(Value *V) { - assert(getInstruction() && "Not a call or invoke instruction!"); - *getCallee() = V; - } - - /// isCallee - Determine whether the passed iterator points to the - /// callee operand's Use. - /// - bool isCallee(value_use_iterator<UserTy> UI) const { - return getCallee() == &UI.getUse(); - } - - ValTy *getArgument(unsigned ArgNo) const { - assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); - return *(arg_begin() + ArgNo); - } - - void setArgument(unsigned ArgNo, Value* newVal) { - assert(getInstruction() && "Not a call or invoke instruction!"); - assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); - getInstruction()->setOperand(ArgNo, newVal); - } - - /// Given a value use iterator, returns the argument that corresponds to it. - /// Iterator must actually correspond to an argument. - unsigned getArgumentNo(value_use_iterator<UserTy> I) const { - assert(getInstruction() && "Not a call or invoke instruction!"); - assert(arg_begin() <= &I.getUse() && &I.getUse() < arg_end() - && "Argument # out of range!"); - return &I.getUse() - arg_begin(); - } - - /// arg_iterator - The type of iterator to use when looping over actual - /// arguments at this call site. - typedef IterTy arg_iterator; - - /// arg_begin/arg_end - Return iterators corresponding to the actual argument - /// list for a call site. - IterTy arg_begin() const { - assert(getInstruction() && "Not a call or invoke instruction!"); - // Skip non-arguments - return (*this)->op_begin(); - } - - IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); } - bool arg_empty() const { return arg_end() == arg_begin(); } - unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } - - /// getType - Return the type of the instruction that generated this call site - /// - Type *getType() const { return (*this)->getType(); } - - /// getCaller - Return the caller function for this call site - /// - FunTy *getCaller() const { return (*this)->getParent()->getParent(); } - -#define CALLSITE_DELEGATE_GETTER(METHOD) \ - InstrTy *II = getInstruction(); \ - return isCall() \ - ? cast<CallInst>(II)->METHOD \ - : cast<InvokeInst>(II)->METHOD - -#define CALLSITE_DELEGATE_SETTER(METHOD) \ - InstrTy *II = getInstruction(); \ - if (isCall()) \ - cast<CallInst>(II)->METHOD; \ - else \ - cast<InvokeInst>(II)->METHOD - - /// getCallingConv/setCallingConv - get or set the calling convention of the - /// call. - CallingConv::ID getCallingConv() const { - CALLSITE_DELEGATE_GETTER(getCallingConv()); - } - void setCallingConv(CallingConv::ID CC) { - CALLSITE_DELEGATE_SETTER(setCallingConv(CC)); - } - - /// getAttributes/setAttributes - get or set the parameter attributes of - /// the call. - const AttributeSet &getAttributes() const { - CALLSITE_DELEGATE_GETTER(getAttributes()); - } - void setAttributes(const AttributeSet &PAL) { - CALLSITE_DELEGATE_SETTER(setAttributes(PAL)); - } - - /// \brief Return true if this function has the given attribute. - bool hasFnAttr(Attribute::AttrKind A) const { - CALLSITE_DELEGATE_GETTER(hasFnAttr(A)); - } - - /// \brief Return true if the call or the callee has the given attribute. - bool paramHasAttr(unsigned i, Attribute::AttrKind A) const { - CALLSITE_DELEGATE_GETTER(paramHasAttr(i, A)); - } - - /// @brief Extract the alignment for a call or parameter (0=unknown). - uint16_t getParamAlignment(uint16_t i) const { - CALLSITE_DELEGATE_GETTER(getParamAlignment(i)); - } - - /// \brief Return true if the call should not be treated as a call to a - /// builtin. - bool isNoBuiltin() const { - CALLSITE_DELEGATE_GETTER(isNoBuiltin()); - } - - /// @brief Return true if the call should not be inlined. - bool isNoInline() const { - CALLSITE_DELEGATE_GETTER(isNoInline()); - } - void setIsNoInline(bool Value = true) { - CALLSITE_DELEGATE_SETTER(setIsNoInline(Value)); - } - - /// @brief Determine if the call does not access memory. - bool doesNotAccessMemory() const { - CALLSITE_DELEGATE_GETTER(doesNotAccessMemory()); - } - void setDoesNotAccessMemory() { - CALLSITE_DELEGATE_SETTER(setDoesNotAccessMemory()); - } - - /// @brief Determine if the call does not access or only reads memory. - bool onlyReadsMemory() const { - CALLSITE_DELEGATE_GETTER(onlyReadsMemory()); - } - void setOnlyReadsMemory() { - CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory()); - } - - /// @brief Determine if the call cannot return. - bool doesNotReturn() const { - CALLSITE_DELEGATE_GETTER(doesNotReturn()); - } - void setDoesNotReturn() { - CALLSITE_DELEGATE_SETTER(setDoesNotReturn()); - } - - /// @brief Determine if the call cannot unwind. - bool doesNotThrow() const { - CALLSITE_DELEGATE_GETTER(doesNotThrow()); - } - void setDoesNotThrow() { - CALLSITE_DELEGATE_SETTER(setDoesNotThrow()); - } - -#undef CALLSITE_DELEGATE_GETTER -#undef CALLSITE_DELEGATE_SETTER - - /// @brief Determine whether this argument is not captured. - bool doesNotCapture(unsigned ArgNo) const { - return paramHasAttr(ArgNo + 1, Attribute::NoCapture); - } - - /// @brief Determine whether this argument is passed by value. - bool isByValArgument(unsigned ArgNo) const { - return paramHasAttr(ArgNo + 1, Attribute::ByVal); - } - - bool doesNotAccessMemory(unsigned ArgNo) const { - return paramHasAttr(ArgNo + 1, Attribute::ReadNone); - } - - bool onlyReadsMemory(unsigned ArgNo) const { - return paramHasAttr(ArgNo + 1, Attribute::ReadOnly) || - paramHasAttr(ArgNo + 1, Attribute::ReadNone); - } - - /// hasArgument - Returns true if this CallSite passes the given Value* as an - /// argument to the called function. - bool hasArgument(const Value *Arg) const { - for (arg_iterator AI = this->arg_begin(), E = this->arg_end(); AI != E; - ++AI) - if (AI->get() == Arg) - return true; - return false; - } - -private: - unsigned getArgumentEndOffset() const { - if (isCall()) - return 1; // Skip Callee - else - return 3; // Skip BB, BB, Callee - } - - IterTy getCallee() const { - if (isCall()) // Skip Callee - return cast<CallInst>(getInstruction())->op_end() - 1; - else // Skip BB, BB, Callee - return cast<InvokeInst>(getInstruction())->op_end() - 3; - } -}; - -class CallSite : public CallSiteBase<Function, Value, User, Instruction, - CallInst, InvokeInst, User::op_iterator> { - typedef CallSiteBase<Function, Value, User, Instruction, - CallInst, InvokeInst, User::op_iterator> Base; -public: - CallSite() {} - CallSite(Base B) : Base(B) {} - CallSite(Value* V) : Base(V) {} - CallSite(CallInst *CI) : Base(CI) {} - CallSite(InvokeInst *II) : Base(II) {} - CallSite(Instruction *II) : Base(II) {} - - bool operator==(const CallSite &CS) const { return I == CS.I; } - bool operator!=(const CallSite &CS) const { return I != CS.I; } - bool operator<(const CallSite &CS) const { - return getInstruction() < CS.getInstruction(); - } - -private: - User::op_iterator getCallee() const; -}; - -/// ImmutableCallSite - establish a view to a call site for examination -class ImmutableCallSite : public CallSiteBase<> { - typedef CallSiteBase<> Base; -public: - ImmutableCallSite(const Value* V) : Base(V) {} - ImmutableCallSite(const CallInst *CI) : Base(CI) {} - ImmutableCallSite(const InvokeInst *II) : Base(II) {} - ImmutableCallSite(const Instruction *II) : Base(II) {} - ImmutableCallSite(CallSite CS) : Base(CS.getInstruction()) {} -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Support/Casting.h b/contrib/llvm/include/llvm/Support/Casting.h index d70acbf..beed31a 100644 --- a/contrib/llvm/include/llvm/Support/Casting.h +++ b/contrib/llvm/include/llvm/Support/Casting.h @@ -15,6 +15,7 @@ #ifndef LLVM_SUPPORT_CASTING_H #define LLVM_SUPPORT_CASTING_H +#include "llvm/Support/Compiler.h" #include "llvm/Support/type_traits.h" #include <cassert> @@ -58,11 +59,8 @@ struct isa_impl { /// \brief Always allow upcasts, and perform no dynamic check for them. template <typename To, typename From> -struct isa_impl<To, From, - typename enable_if< - llvm::is_base_of<To, From> - >::type - > { +struct isa_impl< + To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> { static inline bool doit(const From &) { return true; } }; @@ -131,7 +129,7 @@ struct isa_impl_wrap<To, FromTy, FromTy> { // if (isa<Type>(myVal)) { ... } // template <class X, class Y> -inline bool isa(const Y &Val) { +LLVM_ATTRIBUTE_UNUSED_RESULT inline bool isa(const Y &Val) { return isa_impl_wrap<X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val); } @@ -208,7 +206,7 @@ template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { template <class X> struct is_simple_type { static const bool value = - is_same<X, typename simplify_type<X>::SimpleType>::value; + std::is_same<X, typename simplify_type<X>::SimpleType>::value; }; // cast<X> - Return the argument parameter cast to the specified type. This @@ -219,8 +217,8 @@ template <class X> struct is_simple_type { // cast<Instruction>(myVal)->getParent() // template <class X, class Y> -inline typename enable_if_c<!is_simple_type<Y>::value, - typename cast_retty<X, const Y>::ret_type>::type +inline typename std::enable_if<!is_simple_type<Y>::value, + typename cast_retty<X, const Y>::ret_type>::type cast(const Y &Val) { assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); return cast_convert_val< @@ -245,8 +243,9 @@ inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) { // accepted. // template <class X, class Y> -inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { - if (Val == 0) return 0; +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +cast_or_null(Y *Val) { + if (!Val) return nullptr; assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); return cast<X>(Val); } @@ -261,28 +260,31 @@ inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { // template <class X, class Y> -inline typename enable_if_c<!is_simple_type<Y>::value, - typename cast_retty<X, const Y>::ret_type>::type +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type dyn_cast(const Y &Val) { - return isa<X>(Val) ? cast<X>(Val) : 0; + return isa<X>(Val) ? cast<X>(Val) : nullptr; } template <class X, class Y> -inline typename cast_retty<X, Y>::ret_type dyn_cast(Y &Val) { - return isa<X>(Val) ? cast<X>(Val) : 0; +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y>::ret_type +dyn_cast(Y &Val) { + return isa<X>(Val) ? cast<X>(Val) : nullptr; } template <class X, class Y> -inline typename cast_retty<X, Y *>::ret_type dyn_cast(Y *Val) { - return isa<X>(Val) ? cast<X>(Val) : 0; +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +dyn_cast(Y *Val) { + return isa<X>(Val) ? cast<X>(Val) : nullptr; } // dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null // value is accepted. // template <class X, class Y> -inline typename cast_retty<X, Y*>::ret_type dyn_cast_or_null(Y *Val) { - return (Val && isa<X>(Val)) ? cast<X>(Val) : 0; +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type +dyn_cast_or_null(Y *Val) { + return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr; } } // End llvm namespace diff --git a/contrib/llvm/include/llvm/Support/CommandLine.h b/contrib/llvm/include/llvm/Support/CommandLine.h index 4efb6a6..fdd90120 100644 --- a/contrib/llvm/include/llvm/Support/CommandLine.h +++ b/contrib/llvm/include/llvm/Support/CommandLine.h @@ -21,10 +21,9 @@ #define LLVM_SUPPORT_COMMANDLINE_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Twine.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/type_traits.h" #include <cassert> #include <climits> #include <cstdarg> @@ -42,14 +41,14 @@ namespace cl { // ParseCommandLineOptions - Command line option processing entry point. // void ParseCommandLineOptions(int argc, const char * const *argv, - const char *Overview = 0); + const char *Overview = nullptr); //===----------------------------------------------------------------------===// // ParseEnvironmentOptions - Environment variable option processing alternate // entry point. // void ParseEnvironmentOptions(const char *progName, const char *envvar, - const char *Overview = 0); + const char *Overview = nullptr); ///===---------------------------------------------------------------------===// /// SetVersionPrinter - Override the default (LLVM specific) version printer @@ -147,10 +146,10 @@ private: const char *const Description; void registerCategory(); public: - OptionCategory(const char *const Name, const char *const Description = 0) + OptionCategory(const char *const Name, const char *const Description = nullptr) : Name(Name), Description(Description) { registerCategory(); } - const char *getName() { return Name; } - const char *getDescription() { return Description; } + const char *getName() const { return Name; } + const char *getDescription() const { return Description; } }; // The general Option Category (used as default category). @@ -239,7 +238,7 @@ protected: enum OptionHidden Hidden) : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), - Position(0), AdditionalVals(0), NextRegistered(0), + Position(0), AdditionalVals(0), NextRegistered(nullptr), ArgStr(""), HelpStr(""), ValueStr(""), Category(&GeneralCategory) { } @@ -249,6 +248,12 @@ public: // void addArgument(); + /// Unregisters this option from the CommandLine system. + /// + /// This option must have been the last option registered. + /// For testing purposes only. + void removeArgument(); + Option *getNextRegisteredOption() const { return NextRegistered; } // Return the width of the option tag for printing... @@ -265,8 +270,8 @@ public: // addOccurrence - Wrapper around handleOccurrence that enforces Flags. // - bool addOccurrence(unsigned pos, StringRef ArgName, - StringRef Value, bool MultiArg = false); + virtual bool addOccurrence(unsigned pos, StringRef ArgName, + StringRef Value, bool MultiArg = false); // Prints option name followed by message. Always returns true. bool error(const Twine &Message, StringRef ArgName = StringRef()); @@ -374,7 +379,9 @@ struct OptionValueBase : public GenericOptionValue { bool compare(const DataType &/*V*/) const { return false; } - virtual bool compare(const GenericOptionValue& /*V*/) const { return false; } + bool compare(const GenericOptionValue& /*V*/) const override { + return false; + } }; // Simple copy of the option value. @@ -398,7 +405,7 @@ public: return Valid && (Value != V); } - virtual bool compare(const GenericOptionValue &V) const { + bool compare(const GenericOptionValue &V) const override { const OptionValueCopy<DataType> &VC = static_cast< const OptionValueCopy<DataType>& >(V); if (!VC.hasValue()) return false; @@ -414,7 +421,7 @@ struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> { // Top-level option class. template<class DataType> -struct OptionValue : OptionValueBase<DataType, is_class<DataType>::value> { +struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> { OptionValue() {} OptionValue(const DataType& V) { @@ -444,7 +451,7 @@ struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> { return *this; } private: - virtual void anchor(); + void anchor() override; }; template<> @@ -461,7 +468,7 @@ struct OptionValue<std::string> : OptionValueCopy<std::string> { return *this; } private: - virtual void anchor(); + void anchor() override; }; //===----------------------------------------------------------------------===// @@ -640,14 +647,14 @@ public: typedef DataType parser_data_type; // Implement virtual functions needed by generic_parser_base - unsigned getNumOptions() const { return unsigned(Values.size()); } - const char *getOption(unsigned N) const { return Values[N].Name; } - const char *getDescription(unsigned N) const { + unsigned getNumOptions() const override { return unsigned(Values.size()); } + const char *getOption(unsigned N) const override { return Values[N].Name; } + const char *getDescription(unsigned N) const override { return Values[N].HelpStr; } // getOptionValue - Return the value of option name N. - virtual const GenericOptionValue &getOptionValue(unsigned N) const { + const GenericOptionValue &getOptionValue(unsigned N) const override { return Values[N].V; } @@ -756,13 +763,13 @@ public: } // getValueName - Do not print =<value> at all. - virtual const char *getValueName() const { return 0; } + const char *getValueName() const override { return nullptr; } void printOptionDiff(const Option &O, bool V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>); @@ -780,13 +787,13 @@ public: } // getValueName - Do not print =<value> at all. - virtual const char *getValueName() const { return 0; } + const char *getValueName() const override { return nullptr; } void printOptionDiff(const Option &O, boolOrDefault V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>); @@ -801,13 +808,13 @@ public: bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "int"; } + const char *getValueName() const override { return "int"; } void printOptionDiff(const Option &O, int V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<int>); @@ -823,13 +830,13 @@ public: bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "uint"; } + const char *getValueName() const override { return "uint"; } void printOptionDiff(const Option &O, unsigned V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>); @@ -845,13 +852,13 @@ public: unsigned long long &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "uint"; } + const char *getValueName() const override { return "uint"; } void printOptionDiff(const Option &O, unsigned long long V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>); @@ -866,13 +873,13 @@ public: bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "number"; } + const char *getValueName() const override { return "number"; } void printOptionDiff(const Option &O, double V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<double>); @@ -887,13 +894,13 @@ public: bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "number"; } + const char *getValueName() const override { return "number"; } void printOptionDiff(const Option &O, float V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<float>); @@ -911,13 +918,13 @@ public: } // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "string"; } + const char *getValueName() const override { return "string"; } void printOptionDiff(const Option &O, StringRef V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<std::string>); @@ -935,13 +942,13 @@ public: } // getValueName - Overload in subclass to provide a better default value. - virtual const char *getValueName() const { return "char"; } + const char *getValueName() const override { return "char"; } void printOptionDiff(const Option &O, char V, OptVal Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. - virtual void anchor(); + void anchor() override; }; EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<char>); @@ -1020,8 +1027,8 @@ template<> struct applicator<const char*> { }; template<> struct applicator<NumOccurrencesFlag> { - static void opt(NumOccurrencesFlag NO, Option &O) { - O.setNumOccurrencesFlag(NO); + static void opt(NumOccurrencesFlag N, Option &O) { + O.setNumOccurrencesFlag(N); } }; template<> struct applicator<ValueExpected> { @@ -1055,13 +1062,13 @@ class opt_storage { DataType *Location; // Where to store the object... OptionValue<DataType> Default; - void check() const { - assert(Location != 0 && "cl::location(...) not specified for a command " + void check_location() const { + assert(Location && "cl::location(...) not specified for a command " "line option with external storage, " "or cl::init specified before cl::location()!!"); } public: - opt_storage() : Location(0) {} + opt_storage() : Location(nullptr) {} bool setLocation(Option &O, DataType &L) { if (Location) @@ -1073,14 +1080,14 @@ public: template<class T> void setValue(const T &V, bool initial = false) { - check(); + check_location(); *Location = V; if (initial) Default = V; } - DataType &getValue() { check(); return *Location; } - const DataType &getValue() const { check(); return *Location; } + DataType &getValue() { check_location(); return *Location; } + const DataType &getValue() const { check_location(); return *Location; } operator DataType() const { return this->getValue(); } @@ -1148,11 +1155,11 @@ template <class DataType, bool ExternalStorage = false, class ParserClass = parser<DataType> > class opt : public Option, public opt_storage<DataType, ExternalStorage, - is_class<DataType>::value> { + std::is_class<DataType>::value> { ParserClass Parser; - virtual bool handleOccurrence(unsigned pos, StringRef ArgName, - StringRef Arg) { + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { typename ParserClass::parser_data_type Val = typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) @@ -1162,20 +1169,20 @@ class opt : public Option, return false; } - virtual enum ValueExpected getValueExpectedFlagDefault() const { + enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - virtual void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) { + void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } // Forward printing stuff to the parser... - virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} - virtual void printOptionInfo(size_t GlobalWidth) const { + size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } - virtual void printOptionValue(size_t GlobalWidth, bool Force) const { + void printOptionValue(size_t GlobalWidth, bool Force) const override { if (Force || this->getDefault().compare(this->getValue())) { cl::printOptionDiff<ParserClass>( *this, Parser, this->getValue(), this->getDefault(), GlobalWidth); @@ -1322,14 +1329,15 @@ class list : public Option, public list_storage<DataType, Storage> { std::vector<unsigned> Positions; ParserClass Parser; - virtual enum ValueExpected getValueExpectedFlagDefault() const { + enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - virtual void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) { + void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } - virtual bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg){ + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { typename ParserClass::parser_data_type Val = typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) @@ -1341,13 +1349,14 @@ class list : public Option, public list_storage<DataType, Storage> { } // Forward printing stuff to the parser... - virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} - virtual void printOptionInfo(size_t GlobalWidth) const { + size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: list options don't currently store their default value. - virtual void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const {} + void printOptionValue(size_t /*GlobalWidth*/, + bool /*Force*/) const override {} void done() { addArgument(); @@ -1460,7 +1469,7 @@ class bits_storage { } public: - bits_storage() : Location(0) {} + bits_storage() : Location(nullptr) {} bool setLocation(Option &O, unsigned &L) { if (Location) @@ -1524,14 +1533,15 @@ class bits : public Option, public bits_storage<DataType, Storage> { std::vector<unsigned> Positions; ParserClass Parser; - virtual enum ValueExpected getValueExpectedFlagDefault() const { + enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - virtual void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) { + void getExtraOptionNames(SmallVectorImpl<const char*> &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } - virtual bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg){ + bool handleOccurrence(unsigned pos, StringRef ArgName, + StringRef Arg) override { typename ParserClass::parser_data_type Val = typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) @@ -1543,13 +1553,14 @@ class bits : public Option, public bits_storage<DataType, Storage> { } // Forward printing stuff to the parser... - virtual size_t getOptionWidth() const {return Parser.getOptionWidth(*this);} - virtual void printOptionInfo(size_t GlobalWidth) const { + size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: bits options don't currently store their default values. - virtual void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const {} + void printOptionValue(size_t /*GlobalWidth*/, + bool /*Force*/) const override {} void done() { addArgument(); @@ -1634,22 +1645,30 @@ public: class alias : public Option { Option *AliasFor; - virtual bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Arg) LLVM_OVERRIDE { + bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, + StringRef Arg) override { return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); } + bool addOccurrence(unsigned pos, StringRef /*ArgName*/, + StringRef Value, bool MultiArg = false) override { + return AliasFor->addOccurrence(pos, AliasFor->ArgStr, Value, MultiArg); + } // Handle printing stuff... - virtual size_t getOptionWidth() const LLVM_OVERRIDE; - virtual void printOptionInfo(size_t GlobalWidth) const LLVM_OVERRIDE; + size_t getOptionWidth() const override; + void printOptionInfo(size_t GlobalWidth) const override; // Aliases do not need to print their values. - virtual void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const LLVM_OVERRIDE {} + void printOptionValue(size_t /*GlobalWidth*/, + bool /*Force*/) const override {} + + ValueExpected getValueExpectedFlagDefault() const override { + return AliasFor->getValueExpectedFlag(); + } void done() { if (!hasArgStr()) error("cl::alias must have argument name specified!"); - if (AliasFor == 0) + if (!AliasFor) error("cl::alias must have an cl::aliasopt(option) specified!"); addArgument(); } @@ -1662,27 +1681,28 @@ public: // One option... template<class M0t> - explicit alias(const M0t &M0) : Option(Optional, Hidden), AliasFor(0) { + explicit alias(const M0t &M0) : Option(Optional, Hidden), AliasFor(nullptr) { apply(M0, this); done(); } // Two options... template<class M0t, class M1t> - alias(const M0t &M0, const M1t &M1) : Option(Optional, Hidden), AliasFor(0) { + alias(const M0t &M0, const M1t &M1) + : Option(Optional, Hidden), AliasFor(nullptr) { apply(M0, this); apply(M1, this); done(); } // Three options... template<class M0t, class M1t, class M2t> alias(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional, Hidden), AliasFor(0) { + : Option(Optional, Hidden), AliasFor(nullptr) { apply(M0, this); apply(M1, this); apply(M2, this); done(); } // Four options... template<class M0t, class M1t, class M2t, class M3t> alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(Optional, Hidden), AliasFor(0) { + : Option(Optional, Hidden), AliasFor(nullptr) { apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); done(); } diff --git a/contrib/llvm/include/llvm/Support/Compiler.h b/contrib/llvm/include/llvm/Support/Compiler.h index 860f43e..25bf32a 100644 --- a/contrib/llvm/include/llvm/Support/Compiler.h +++ b/contrib/llvm/include/llvm/Support/Compiler.h @@ -21,6 +21,10 @@ # define __has_feature(x) 0 #endif +#ifndef __has_extension +# define __has_extension(x) 0 +#endif + #ifndef __has_attribute # define __has_attribute(x) 0 #endif @@ -40,15 +44,27 @@ # endif #endif -/// \brief Does the compiler support r-value references? -/// This implies that <utility> provides the one-argument std::move; it -/// does not imply the existence of any other C++ library features. -#if (__has_feature(cxx_rvalue_references) \ - || defined(__GXX_EXPERIMENTAL_CXX0X__) \ - || (defined(_MSC_VER) && _MSC_VER >= 1600)) -#define LLVM_HAS_RVALUE_REFERENCES 1 +/// \macro LLVM_MSC_PREREQ +/// \brief Is the compiler MSVC of at least the specified version? +/// The common \param version values to check for are: +/// * 1700: Microsoft Visual Studio 2012 / 11.0 +/// * 1800: Microsoft Visual Studio 2013 / 12.0 +#ifdef _MSC_VER +#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version)) + +// We require at least MSVC 2012. +#if !LLVM_MSC_PREREQ(1700) +#error LLVM requires at least MSVC 2012. +#endif + #else -#define LLVM_HAS_RVALUE_REFERENCES 0 +#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? @@ -63,51 +79,16 @@ #define LLVM_HAS_RVALUE_REFERENCE_THIS 0 #endif -/// \macro LLVM_HAS_CXX11_TYPETRAITS -/// \brief Does the compiler have the C++11 type traits. -/// -/// #include <type_traits> -/// -/// * enable_if -/// * {true,false}_type -/// * is_constructible -/// * etc... -#if defined(__GXX_EXPERIMENTAL_CXX0X__) \ - || (defined(_MSC_VER) && _MSC_VER >= 1700) -#define LLVM_HAS_CXX11_TYPETRAITS 1 -#else -#define LLVM_HAS_CXX11_TYPETRAITS 0 -#endif - -/// \macro LLVM_HAS_CXX11_STDLIB -/// \brief Does the compiler have the C++11 standard library. -/// -/// Implies LLVM_HAS_RVALUE_REFERENCES, LLVM_HAS_CXX11_TYPETRAITS -#if defined(__GXX_EXPERIMENTAL_CXX0X__) \ - || (defined(_MSC_VER) && _MSC_VER >= 1700) -#define LLVM_HAS_CXX11_STDLIB 1 -#else -#define LLVM_HAS_CXX11_STDLIB 0 -#endif - /// \macro LLVM_HAS_VARIADIC_TEMPLATES /// \brief Does this compiler support variadic templates. /// /// Implies LLVM_HAS_RVALUE_REFERENCES and the existence of std::forward. -#if __has_feature(cxx_variadic_templates) +#if __has_feature(cxx_variadic_templates) || LLVM_MSC_PREREQ(1800) # define LLVM_HAS_VARIADIC_TEMPLATES 1 #else # define LLVM_HAS_VARIADIC_TEMPLATES 0 #endif -/// llvm_move - Expands to ::std::move if the compiler supports -/// r-value references; otherwise, expands to the argument. -#if LLVM_HAS_RVALUE_REFERENCES -#define llvm_move(value) (::std::move(value)) -#else -#define llvm_move(value) (value) -#endif - /// Expands to '&' if r-value references are supported. /// /// This can be used to provide l-value/r-value overrides of member functions. @@ -129,32 +110,13 @@ /// public: /// ... /// }; -#if (__has_feature(cxx_deleted_functions) \ - || defined(__GXX_EXPERIMENTAL_CXX0X__)) - // No version of MSVC currently supports this. +#if __has_feature(cxx_deleted_functions) || \ + defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800) #define LLVM_DELETED_FUNCTION = delete #else #define LLVM_DELETED_FUNCTION #endif -/// LLVM_FINAL - Expands to 'final' if the compiler supports it. -/// Use to mark classes or virtual methods as final. -#if __has_feature(cxx_override_control) \ - || (defined(_MSC_VER) && _MSC_VER >= 1700) -#define LLVM_FINAL final -#else -#define LLVM_FINAL -#endif - -/// LLVM_OVERRIDE - Expands to 'override' if the compiler supports it. -/// Use to mark virtual methods as overriding a base class method. -#if __has_feature(cxx_override_control) \ - || (defined(_MSC_VER) && _MSC_VER >= 1700) -#define LLVM_OVERRIDE override -#else -#define LLVM_OVERRIDE -#endif - #if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define LLVM_CONSTEXPR constexpr #else @@ -335,19 +297,15 @@ # define LLVM_FUNCTION_NAME __func__ #endif -#if defined(HAVE_SANITIZER_MSAN_INTERFACE_H) -# include <sanitizer/msan_interface.h> -#else -# define __msan_allocated_memory(p, size) -# define __msan_unpoison(p, size) -#endif - /// \macro LLVM_MEMORY_SANITIZER_BUILD /// \brief Whether LLVM itself is built with MemorySanitizer instrumentation. #if __has_feature(memory_sanitizer) # define LLVM_MEMORY_SANITIZER_BUILD 1 +# include <sanitizer/msan_interface.h> #else # define LLVM_MEMORY_SANITIZER_BUILD 0 +# define __msan_allocated_memory(p, size) +# define __msan_unpoison(p, size) #endif /// \macro LLVM_ADDRESS_SANITIZER_BUILD @@ -374,41 +332,30 @@ /// \macro LLVM_EXPLICIT /// \brief Expands to explicit on compilers which support explicit conversion /// operators. Otherwise expands to nothing. -#if (__has_feature(cxx_explicit_conversions) \ - || defined(__GXX_EXPERIMENTAL_CXX0X__)) +#if __has_feature(cxx_explicit_conversions) || \ + defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800) #define LLVM_EXPLICIT explicit #else #define LLVM_EXPLICIT #endif -/// \macro LLVM_STATIC_ASSERT -/// \brief Expands to C/C++'s static_assert on compilers which support it. -#if __has_feature(cxx_static_assert) -# define LLVM_STATIC_ASSERT(expr, msg) static_assert(expr, msg) -#elif __has_feature(c_static_assert) -# define LLVM_STATIC_ASSERT(expr, msg) _Static_assert(expr, msg) -#else -# define LLVM_STATIC_ASSERT(expr, msg) -#endif - -/// \macro LLVM_ENUM_INT_TYPE -/// \brief Expands to colon followed by the given integral type on compilers -/// which support C++11 strong enums. This can be used to make enums unsigned -/// with MSVC. -#if __has_feature(cxx_strong_enums) -# define LLVM_ENUM_INT_TYPE(intty) : intty -#elif defined(_MSC_VER) && _MSC_VER >= 1600 // Added in MSVC 2010. -# define LLVM_ENUM_INT_TYPE(intty) : intty -#else -# define LLVM_ENUM_INT_TYPE(intty) -#endif - /// \brief Does the compiler support generalized initializers (using braced -/// lists and std::initializer_list). -#if __has_feature(cxx_generalized_initializers) +/// lists and std::initializer_list). While clang may claim it supports general +/// initializers, if we're using MSVC's headers, we might not have a usable +/// std::initializer list type from the STL. Disable this for now. +#if __has_feature(cxx_generalized_initializers) && !defined(_MSC_VER) #define LLVM_HAS_INITIALIZER_LISTS 1 #else #define LLVM_HAS_INITIALIZER_LISTS 0 #endif +/// \brief Mark debug helper function definitions like dump() that should not be +/// stripped from debug builds. +// FIXME: Move this to a private config.h as it's not usable in public headers. +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED +#else +#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE +#endif + #endif diff --git a/contrib/llvm/include/llvm/Support/Compression.h b/contrib/llvm/include/llvm/Support/Compression.h index bef9146..8152b60 100644 --- a/contrib/llvm/include/llvm/Support/Compression.h +++ b/contrib/llvm/include/llvm/Support/Compression.h @@ -15,11 +15,11 @@ #define LLVM_SUPPORT_COMPRESSION_H #include "llvm/Support/DataTypes.h" +#include <memory> +#include "llvm/ADT/SmallVector.h" namespace llvm { -class MemoryBuffer; -template<typename T> class OwningPtr; class StringRef; namespace zlib { @@ -33,21 +33,20 @@ enum CompressionLevel { enum Status { StatusOK, - StatusUnsupported, // zlib is unavaliable - StatusOutOfMemory, // there was not enough memory - StatusBufferTooShort, // there was not enough room in the output buffer - StatusInvalidArg, // invalid input parameter - StatusInvalidData // data was corrupted or incomplete + StatusUnsupported, // zlib is unavailable + StatusOutOfMemory, // there was not enough memory + StatusBufferTooShort, // there was not enough room in the output buffer + StatusInvalidArg, // invalid input parameter + StatusInvalidData // data was corrupted or incomplete }; bool isAvailable(); -Status compress(StringRef InputBuffer, - OwningPtr<MemoryBuffer> &CompressedBuffer, +Status compress(StringRef InputBuffer, SmallVectorImpl<char> &CompressedBuffer, CompressionLevel Level = DefaultCompression); Status uncompress(StringRef InputBuffer, - OwningPtr<MemoryBuffer> &UncompressedBuffer, + SmallVectorImpl<char> &UncompressedBuffer, size_t UncompressedSize); uint32_t crc32(StringRef Buffer); diff --git a/contrib/llvm/include/llvm/Support/ConstantFolder.h b/contrib/llvm/include/llvm/Support/ConstantFolder.h deleted file mode 100644 index 4aad952..0000000 --- a/contrib/llvm/include/llvm/Support/ConstantFolder.h +++ /dev/null @@ -1,238 +0,0 @@ -//===-- llvm/Support/ConstantFolder.h - Constant folding helper -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the ConstantFolder class, a helper for IRBuilder. -// It provides IRBuilder with a set of methods for creating constants -// with minimal folding. For general constant creation and folding, -// use ConstantExpr and the routines in llvm/Analysis/ConstantFolding.h. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_CONSTANTFOLDER_H -#define LLVM_SUPPORT_CONSTANTFOLDER_H - -#include "llvm/IR/Constants.h" -#include "llvm/IR/InstrTypes.h" - -namespace llvm { - -/// ConstantFolder - Create constants with minimum, target independent, folding. -class ConstantFolder { -public: - explicit ConstantFolder() {} - - //===--------------------------------------------------------------------===// - // Binary Operators - //===--------------------------------------------------------------------===// - - Constant *CreateAdd(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - return ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW); - } - Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getFAdd(LHS, RHS); - } - Constant *CreateSub(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - return ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW); - } - Constant *CreateFSub(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getFSub(LHS, RHS); - } - Constant *CreateMul(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - return ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW); - } - Constant *CreateFMul(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getFMul(LHS, RHS); - } - Constant *CreateUDiv(Constant *LHS, Constant *RHS, - bool isExact = false) const { - return ConstantExpr::getUDiv(LHS, RHS, isExact); - } - Constant *CreateSDiv(Constant *LHS, Constant *RHS, - bool isExact = false) const { - return ConstantExpr::getSDiv(LHS, RHS, isExact); - } - Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getFDiv(LHS, RHS); - } - Constant *CreateURem(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getURem(LHS, RHS); - } - Constant *CreateSRem(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getSRem(LHS, RHS); - } - Constant *CreateFRem(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getFRem(LHS, RHS); - } - Constant *CreateShl(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - return ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW); - } - Constant *CreateLShr(Constant *LHS, Constant *RHS, - bool isExact = false) const { - return ConstantExpr::getLShr(LHS, RHS, isExact); - } - Constant *CreateAShr(Constant *LHS, Constant *RHS, - bool isExact = false) const { - return ConstantExpr::getAShr(LHS, RHS, isExact); - } - Constant *CreateAnd(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getAnd(LHS, RHS); - } - Constant *CreateOr(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getOr(LHS, RHS); - } - Constant *CreateXor(Constant *LHS, Constant *RHS) const { - return ConstantExpr::getXor(LHS, RHS); - } - - Constant *CreateBinOp(Instruction::BinaryOps Opc, - Constant *LHS, Constant *RHS) const { - return ConstantExpr::get(Opc, LHS, RHS); - } - - //===--------------------------------------------------------------------===// - // Unary Operators - //===--------------------------------------------------------------------===// - - Constant *CreateNeg(Constant *C, - bool HasNUW = false, bool HasNSW = false) const { - return ConstantExpr::getNeg(C, HasNUW, HasNSW); - } - Constant *CreateFNeg(Constant *C) const { - return ConstantExpr::getFNeg(C); - } - Constant *CreateNot(Constant *C) const { - return ConstantExpr::getNot(C); - } - - //===--------------------------------------------------------------------===// - // Memory Instructions - //===--------------------------------------------------------------------===// - - Constant *CreateGetElementPtr(Constant *C, - ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); - } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { - // This form of the function only exists to avoid ambiguous overload - // warnings about whether to convert Idx to ArrayRef<Constant *> or - // ArrayRef<Value *>. - return ConstantExpr::getGetElementPtr(C, Idx); - } - Constant *CreateGetElementPtr(Constant *C, - ArrayRef<Value *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); - } - - Constant *CreateInBoundsGetElementPtr(Constant *C, - ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); - } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { - // This form of the function only exists to avoid ambiguous overload - // warnings about whether to convert Idx to ArrayRef<Constant *> or - // ArrayRef<Value *>. - return ConstantExpr::getInBoundsGetElementPtr(C, Idx); - } - Constant *CreateInBoundsGetElementPtr(Constant *C, - ArrayRef<Value *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); - } - - //===--------------------------------------------------------------------===// - // Cast/Conversion Operators - //===--------------------------------------------------------------------===// - - Constant *CreateCast(Instruction::CastOps Op, Constant *C, - Type *DestTy) const { - return ConstantExpr::getCast(Op, C, DestTy); - } - Constant *CreatePointerCast(Constant *C, Type *DestTy) const { - return ConstantExpr::getPointerCast(C, DestTy); - } - Constant *CreateIntCast(Constant *C, Type *DestTy, - bool isSigned) const { - return ConstantExpr::getIntegerCast(C, DestTy, isSigned); - } - Constant *CreateFPCast(Constant *C, Type *DestTy) const { - return ConstantExpr::getFPCast(C, DestTy); - } - - Constant *CreateBitCast(Constant *C, Type *DestTy) const { - return CreateCast(Instruction::BitCast, C, DestTy); - } - Constant *CreateIntToPtr(Constant *C, Type *DestTy) const { - return CreateCast(Instruction::IntToPtr, C, DestTy); - } - Constant *CreatePtrToInt(Constant *C, Type *DestTy) const { - return CreateCast(Instruction::PtrToInt, C, DestTy); - } - Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const { - return ConstantExpr::getZExtOrBitCast(C, DestTy); - } - Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const { - return ConstantExpr::getSExtOrBitCast(C, DestTy); - } - - Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const { - return ConstantExpr::getTruncOrBitCast(C, DestTy); - } - - //===--------------------------------------------------------------------===// - // Compare Instructions - //===--------------------------------------------------------------------===// - - Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS, - Constant *RHS) const { - return ConstantExpr::getCompare(P, LHS, RHS); - } - Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, - Constant *RHS) const { - return ConstantExpr::getCompare(P, LHS, RHS); - } - - //===--------------------------------------------------------------------===// - // Other Instructions - //===--------------------------------------------------------------------===// - - Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const { - return ConstantExpr::getSelect(C, True, False); - } - - Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const { - return ConstantExpr::getExtractElement(Vec, Idx); - } - - Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, - Constant *Idx) const { - return ConstantExpr::getInsertElement(Vec, NewElt, Idx); - } - - Constant *CreateShuffleVector(Constant *V1, Constant *V2, - Constant *Mask) const { - return ConstantExpr::getShuffleVector(V1, V2, Mask); - } - - Constant *CreateExtractValue(Constant *Agg, - ArrayRef<unsigned> IdxList) const { - return ConstantExpr::getExtractValue(Agg, IdxList); - } - - Constant *CreateInsertValue(Constant *Agg, Constant *Val, - ArrayRef<unsigned> IdxList) const { - return ConstantExpr::getInsertValue(Agg, Val, IdxList); - } -}; - -} - -#endif diff --git a/contrib/llvm/include/llvm/Support/ConstantRange.h b/contrib/llvm/include/llvm/Support/ConstantRange.h deleted file mode 100644 index f757c6e..0000000 --- a/contrib/llvm/include/llvm/Support/ConstantRange.h +++ /dev/null @@ -1,277 +0,0 @@ -//===-- llvm/Support/ConstantRange.h - Represent a range --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Represent a range of possible values that may occur when the program is run -// for an integral value. This keeps track of a lower and upper bound for the -// constant, which MAY wrap around the end of the numeric range. To do this, it -// keeps track of a [lower, upper) bound, which specifies an interval just like -// STL iterators. When used with boolean values, the following are important -// ranges: : -// -// [F, F) = {} = Empty set -// [T, F) = {T} -// [F, T) = {F} -// [T, T) = {F, T} = Full set -// -// The other integral ranges use min/max values for special range values. For -// example, for 8-bit types, it uses: -// [0, 0) = {} = Empty set -// [255, 255) = {0..255} = Full Set -// -// Note that ConstantRange can be used to represent either signed or -// unsigned ranges. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_CONSTANTRANGE_H -#define LLVM_SUPPORT_CONSTANTRANGE_H - -#include "llvm/ADT/APInt.h" -#include "llvm/Support/DataTypes.h" - -namespace llvm { - -/// ConstantRange - This class represents an range of values. -/// -class ConstantRange { - APInt Lower, Upper; - -#if LLVM_HAS_RVALUE_REFERENCES - // If we have move semantics, pass APInts by value and move them into place. - typedef APInt APIntMoveTy; -#else - // Otherwise pass by const ref to save one copy. - typedef const APInt &APIntMoveTy; -#endif - -public: - /// Initialize a full (the default) or empty set for the specified bit width. - /// - explicit ConstantRange(uint32_t BitWidth, bool isFullSet = true); - - /// Initialize a range to hold the single specified value. - /// - ConstantRange(APIntMoveTy Value); - - /// @brief Initialize a range of values explicitly. This will assert out if - /// Lower==Upper and Lower != Min or Max value for its type. It will also - /// assert out if the two APInt's are not the same bit width. - ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper); - - /// makeICmpRegion - Produce the smallest range that contains all values that - /// might satisfy the comparison specified by Pred when compared to any value - /// contained within Other. - /// - /// Solves for range X in 'for all x in X, there exists a y in Y such that - /// icmp op x, y is true'. Every value that might make the comparison true - /// is included in the resulting range. - static ConstantRange makeICmpRegion(unsigned Pred, - const ConstantRange &Other); - - /// getLower - Return the lower value for this range... - /// - const APInt &getLower() const { return Lower; } - - /// getUpper - Return the upper value for this range... - /// - const APInt &getUpper() const { return Upper; } - - /// getBitWidth - get the bit width of this ConstantRange - /// - uint32_t getBitWidth() const { return Lower.getBitWidth(); } - - /// isFullSet - Return true if this set contains all of the elements possible - /// for this data-type - /// - bool isFullSet() const; - - /// isEmptySet - Return true if this set contains no members. - /// - bool isEmptySet() const; - - /// isWrappedSet - Return true if this set wraps around the top of the range, - /// for example: [100, 8) - /// - bool isWrappedSet() const; - - /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of - /// its bitwidth, for example: i8 [120, 140). - /// - bool isSignWrappedSet() const; - - /// contains - Return true if the specified value is in the set. - /// - bool contains(const APInt &Val) const; - - /// contains - Return true if the other range is a subset of this one. - /// - bool contains(const ConstantRange &CR) const; - - /// getSingleElement - If this set contains a single element, return it, - /// otherwise return null. - /// - const APInt *getSingleElement() const { - if (Upper == Lower + 1) - return &Lower; - return 0; - } - - /// isSingleElement - Return true if this set contains exactly one member. - /// - bool isSingleElement() const { return getSingleElement() != 0; } - - /// getSetSize - Return the number of elements in this set. - /// - APInt getSetSize() const; - - /// getUnsignedMax - Return the largest unsigned value contained in the - /// ConstantRange. - /// - APInt getUnsignedMax() const; - - /// getUnsignedMin - Return the smallest unsigned value contained in the - /// ConstantRange. - /// - APInt getUnsignedMin() const; - - /// getSignedMax - Return the largest signed value contained in the - /// ConstantRange. - /// - APInt getSignedMax() const; - - /// getSignedMin - Return the smallest signed value contained in the - /// ConstantRange. - /// - APInt getSignedMin() const; - - /// operator== - Return true if this range is equal to another range. - /// - bool operator==(const ConstantRange &CR) const { - return Lower == CR.Lower && Upper == CR.Upper; - } - bool operator!=(const ConstantRange &CR) const { - return !operator==(CR); - } - - /// subtract - Subtract the specified constant from the endpoints of this - /// constant range. - ConstantRange subtract(const APInt &CI) const; - - /// \brief Subtract the specified range from this range (aka relative - /// complement of the sets). - ConstantRange difference(const ConstantRange &CR) const; - - /// intersectWith - Return the range that results from the intersection of - /// this range with another range. The resultant range is guaranteed to - /// include all elements contained in both input ranges, and to have the - /// smallest possible set size that does so. Because there may be two - /// intersections with the same set size, A.intersectWith(B) might not - /// be equal to B.intersectWith(A). - /// - ConstantRange intersectWith(const ConstantRange &CR) const; - - /// unionWith - Return the range that results from the union of this range - /// with another range. The resultant range is guaranteed to include the - /// elements of both sets, but may contain more. For example, [3, 9) union - /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included - /// in either set before. - /// - ConstantRange unionWith(const ConstantRange &CR) const; - - /// zeroExtend - Return a new range in the specified integer type, which must - /// be strictly larger than the current type. The returned range will - /// correspond to the possible range of values if the source range had been - /// zero extended to BitWidth. - ConstantRange zeroExtend(uint32_t BitWidth) const; - - /// signExtend - Return a new range in the specified integer type, which must - /// be strictly larger than the current type. The returned range will - /// correspond to the possible range of values if the source range had been - /// sign extended to BitWidth. - ConstantRange signExtend(uint32_t BitWidth) const; - - /// truncate - Return a new range in the specified integer type, which must be - /// strictly smaller than the current type. The returned range will - /// correspond to the possible range of values if the source range had been - /// truncated to the specified type. - ConstantRange truncate(uint32_t BitWidth) const; - - /// zextOrTrunc - make this range have the bit width given by \p BitWidth. The - /// value is zero extended, truncated, or left alone to make it that width. - ConstantRange zextOrTrunc(uint32_t BitWidth) const; - - /// sextOrTrunc - make this range have the bit width given by \p BitWidth. The - /// value is sign extended, truncated, or left alone to make it that width. - ConstantRange sextOrTrunc(uint32_t BitWidth) const; - - /// add - Return a new range representing the possible values resulting - /// from an addition of a value in this range and a value in \p Other. - ConstantRange add(const ConstantRange &Other) const; - - /// sub - Return a new range representing the possible values resulting - /// from a subtraction of a value in this range and a value in \p Other. - ConstantRange sub(const ConstantRange &Other) const; - - /// multiply - Return a new range representing the possible values resulting - /// from a multiplication of a value in this range and a value in \p Other. - /// TODO: This isn't fully implemented yet. - ConstantRange multiply(const ConstantRange &Other) const; - - /// smax - Return a new range representing the possible values resulting - /// from a signed maximum of a value in this range and a value in \p Other. - ConstantRange smax(const ConstantRange &Other) const; - - /// umax - Return a new range representing the possible values resulting - /// from an unsigned maximum of a value in this range and a value in \p Other. - ConstantRange umax(const ConstantRange &Other) const; - - /// udiv - Return a new range representing the possible values resulting - /// from an unsigned division of a value in this range and a value in - /// \p Other. - ConstantRange udiv(const ConstantRange &Other) const; - - /// binaryAnd - return a new range representing the possible values resulting - /// from a binary-and of a value in this range by a value in \p Other. - ConstantRange binaryAnd(const ConstantRange &Other) const; - - /// binaryOr - return a new range representing the possible values resulting - /// from a binary-or of a value in this range by a value in \p Other. - ConstantRange binaryOr(const ConstantRange &Other) const; - - /// shl - Return a new range representing the possible values resulting - /// from a left shift of a value in this range by a value in \p Other. - /// TODO: This isn't fully implemented yet. - ConstantRange shl(const ConstantRange &Other) const; - - /// lshr - Return a new range representing the possible values resulting - /// from a logical right shift of a value in this range and a value in - /// \p Other. - ConstantRange lshr(const ConstantRange &Other) const; - - /// inverse - Return a new range that is the logical not of the current set. - /// - ConstantRange inverse() const; - - /// print - Print out the bounds to a stream... - /// - void print(raw_ostream &OS) const; - - /// dump - Allow printing from a debugger easily... - /// - void dump() const; -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const ConstantRange &CR) { - CR.print(OS); - return OS; -} - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Support/ConvertUTF.h b/contrib/llvm/include/llvm/Support/ConvertUTF.h index 2820366..a184d0d 100644 --- a/contrib/llvm/include/llvm/Support/ConvertUTF.h +++ b/contrib/llvm/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/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h b/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h index 4c0a5e2..3869ebd 100644 --- a/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h +++ b/contrib/llvm/include/llvm/Support/CrashRecoveryContext.h @@ -12,11 +12,13 @@ #include <string> +#include "llvm/ADT/STLExtras.h" + namespace llvm { class StringRef; class CrashRecoveryContextCleanup; - + /// \brief Crash recovery helper object. /// /// This class implements support for running operations in a safe context so @@ -47,9 +49,9 @@ class CrashRecoveryContext { CrashRecoveryContextCleanup *head; public: - CrashRecoveryContext() : Impl(0), head(0) {} + CrashRecoveryContext() : Impl(nullptr), head(nullptr) {} ~CrashRecoveryContext(); - + void registerCleanup(CrashRecoveryContextCleanup *cleanup); void unregisterCleanup(CrashRecoveryContextCleanup *cleanup); @@ -75,15 +77,24 @@ public: /// make as little assumptions as possible about the program state when /// RunSafely has returned false. Clients can use getBacktrace() to retrieve /// the backtrace of the crash on failures. - bool RunSafely(void (*Fn)(void*), void *UserData); + bool RunSafely(function_ref<void()> Fn); + bool RunSafely(void (*Fn)(void*), void *UserData) { + return RunSafely([&]() { Fn(UserData); }); + } /// \brief Execute the provide callback function (with the given arguments) in /// a protected context which is run in another thread (optionally with a /// requested stack size). /// /// See RunSafely() and llvm_execute_on_thread(). + /// + /// 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); + unsigned RequestedStackSize = 0) { + return RunSafelyOnThread([&]() { Fn(UserData); }, RequestedStackSize); + } /// \brief Explicitly trigger a crash recovery in the current process, and /// return failure from RunSafely(). This function does not return. diff --git a/contrib/llvm/include/llvm/Support/DataFlow.h b/contrib/llvm/include/llvm/Support/DataFlow.h deleted file mode 100644 index a09ccaa..0000000 --- a/contrib/llvm/include/llvm/Support/DataFlow.h +++ /dev/null @@ -1,103 +0,0 @@ -//===-- llvm/Support/DataFlow.h - dataflow as graphs ------------*- 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 specializations of GraphTraits that allows Use-Def and -// Def-Use relations to be treated as proper graphs for generic algorithms. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_DATAFLOW_H -#define LLVM_SUPPORT_DATAFLOW_H - -#include "llvm/ADT/GraphTraits.h" -#include "llvm/IR/User.h" - -namespace llvm { - -//===----------------------------------------------------------------------===// -// Provide specializations of GraphTraits to be able to treat def-use/use-def -// chains as graphs - -template <> struct GraphTraits<const Value*> { - typedef const Value NodeType; - typedef Value::const_use_iterator ChildIteratorType; - - static NodeType *getEntryNode(const Value *G) { - return G; - } - - static inline ChildIteratorType child_begin(NodeType *N) { - return N->use_begin(); - } - - static inline ChildIteratorType child_end(NodeType *N) { - return N->use_end(); - } -}; - -template <> struct GraphTraits<Value*> { - typedef Value NodeType; - typedef Value::use_iterator ChildIteratorType; - - static NodeType *getEntryNode(Value *G) { - return G; - } - - static inline ChildIteratorType child_begin(NodeType *N) { - return N->use_begin(); - } - - static inline ChildIteratorType child_end(NodeType *N) { - return N->use_end(); - } -}; - -template <> struct GraphTraits<Inverse<const User*> > { - typedef const Value NodeType; - typedef User::const_op_iterator ChildIteratorType; - - static NodeType *getEntryNode(Inverse<const User*> G) { - return G.Graph; - } - - static inline ChildIteratorType child_begin(NodeType *N) { - if (const User *U = dyn_cast<User>(N)) - return U->op_begin(); - return NULL; - } - - static inline ChildIteratorType child_end(NodeType *N) { - if(const User *U = dyn_cast<User>(N)) - return U->op_end(); - return NULL; - } -}; - -template <> struct GraphTraits<Inverse<User*> > { - typedef Value NodeType; - typedef User::op_iterator ChildIteratorType; - - static NodeType *getEntryNode(Inverse<User*> G) { - return G.Graph; - } - - static inline ChildIteratorType child_begin(NodeType *N) { - if (User *U = dyn_cast<User>(N)) - return U->op_begin(); - return NULL; - } - - static inline ChildIteratorType child_end(NodeType *N) { - if (User *U = dyn_cast<User>(N)) - return U->op_end(); - return NULL; - } -}; - -} -#endif diff --git a/contrib/llvm/include/llvm/Support/DataTypes.h.in b/contrib/llvm/include/llvm/Support/DataTypes.h.in index 7fc9b72..09cfcdf 100644 --- a/contrib/llvm/include/llvm/Support/DataTypes.h.in +++ b/contrib/llvm/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/contrib/llvm/include/llvm/Support/Debug.h b/contrib/llvm/include/llvm/Support/Debug.h index 2702408..e93e6ca3 100644 --- a/contrib/llvm/include/llvm/Support/Debug.h +++ b/contrib/llvm/include/llvm/Support/Debug.h @@ -13,10 +13,12 @@ // // In particular, just wrap your code with the DEBUG() macro, and it will be // enabled automatically if you specify '-debug' on the command-line. -// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify -// that your debug code belongs to class "foo". Then, on the command line, you -// can specify '-debug-only=foo' to enable JUST the debug information for the -// foo class. +// Alternatively, you can also define the DEBUG_TYPE macro to "foo" specify +// that your debug code belongs to class "foo". Be careful that you only do +// this after including Debug.h and not around any #include of headers. Headers +// should define and undef the macro acround the code that needs to use the +// DEBUG() macro. Then, on the command line, you can specify '-debug-only=foo' +// to enable JUST the debug information for the foo class. // // When compiling without assertions, the -debug-* options and all code in // DEBUG() statements disappears, so it does not affect the runtime of the code. @@ -30,12 +32,6 @@ namespace llvm { -/// DEBUG_TYPE macro - Files can specify a DEBUG_TYPE as a string, which causes -/// all of their DEBUG statements to be activatable with -debug-only=thatstring. -#ifndef DEBUG_TYPE -#define DEBUG_TYPE "" -#endif - #ifndef NDEBUG /// DebugFlag - This boolean is set to true if the '-debug' command line option /// is specified. This should probably not be referenced directly, instead, use diff --git a/contrib/llvm/include/llvm/Support/DebugLoc.h b/contrib/llvm/include/llvm/Support/DebugLoc.h deleted file mode 100644 index 05f31d7..0000000 --- a/contrib/llvm/include/llvm/Support/DebugLoc.h +++ /dev/null @@ -1,114 +0,0 @@ -//===---- llvm/Support/DebugLoc.h - Debug Location Information --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a number of light weight data structures used -// to describe and track debug location information. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_DEBUGLOC_H -#define LLVM_SUPPORT_DEBUGLOC_H - -#include "llvm/Support/DataTypes.h"
- -namespace llvm { - template <typename T> struct DenseMapInfo; - class MDNode; - class LLVMContext; - - /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, - /// and MachineInstr to compactly encode file/line/scope information for an - /// operation. - class DebugLoc { - friend struct DenseMapInfo<DebugLoc>; - - /// getEmptyKey() - A private constructor that returns an unknown that is - /// not equal to the tombstone key or DebugLoc(). - static DebugLoc getEmptyKey() { - DebugLoc DL; - DL.LineCol = 1; - return DL; - } - - /// getTombstoneKey() - A private constructor that returns an unknown that - /// is not equal to the empty key or DebugLoc(). - static DebugLoc getTombstoneKey() { - DebugLoc DL; - DL.LineCol = 2; - return DL; - } - - /// LineCol - This 32-bit value encodes the line and column number for the - /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 - /// for either means unknown. - uint32_t LineCol; - - /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information, - /// decoded by LLVMContext. 0 is unknown. - int ScopeIdx; - public: - DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown. - - /// get - Get a new DebugLoc that corresponds to the specified line/col - /// scope/inline location. - static DebugLoc get(unsigned Line, unsigned Col, - MDNode *Scope, MDNode *InlinedAt = 0); - - /// getFromDILocation - Translate the DILocation quad into a DebugLoc. - static DebugLoc getFromDILocation(MDNode *N); - - /// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. - static DebugLoc getFromDILexicalBlock(MDNode *N); - - /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return ScopeIdx == 0; } - - unsigned getLine() const { - return (LineCol << 8) >> 8; // Mask out column. - } - - unsigned getCol() const { - return LineCol >> 24; - } - - /// getScope - This returns the scope pointer for this DebugLoc, or null if - /// invalid. - MDNode *getScope(const LLVMContext &Ctx) const; - - /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or - /// null if invalid or not present. - MDNode *getInlinedAt(const LLVMContext &Ctx) const; - - /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. - void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, - const LLVMContext &Ctx) const; - - - /// getAsMDNode - This method converts the compressed DebugLoc node into a - /// DILocation compatible MDNode. - MDNode *getAsMDNode(const LLVMContext &Ctx) const; - - bool operator==(const DebugLoc &DL) const { - return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx; - } - bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } - - void dump(const LLVMContext &Ctx) const; - }; - - template <> - struct DenseMapInfo<DebugLoc> { - static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); } - static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); } - static unsigned getHashValue(const DebugLoc &Key); - static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; } - }; -} // end namespace llvm - -#endif /* LLVM_SUPPORT_DEBUGLOC_H */ diff --git a/contrib/llvm/include/llvm/Support/Disassembler.h b/contrib/llvm/include/llvm/Support/Disassembler.h deleted file mode 100644 index 6d1cc0f..0000000 --- a/contrib/llvm/include/llvm/Support/Disassembler.h +++ /dev/null @@ -1,35 +0,0 @@ -//===- llvm/Support/Disassembler.h ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the necessary glue to call external disassembler -// libraries. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SYSTEM_DISASSEMBLER_H -#define LLVM_SYSTEM_DISASSEMBLER_H - -#include "llvm/Support/DataTypes.h" -#include <string> - -namespace llvm { -namespace sys { - -/// This function returns true, if there is possible to use some external -/// disassembler library. False otherwise. -bool hasDisassembler(); - -/// This function provides some "glue" code to call external disassembler -/// libraries. -std::string disassembleBuffer(uint8_t* start, size_t length, uint64_t pc = 0); - -} -} - -#endif // LLVM_SYSTEM_DISASSEMBLER_H diff --git a/contrib/llvm/include/llvm/Support/Dwarf.h b/contrib/llvm/include/llvm/Support/Dwarf.h index 23bbd1c..cd9f756 100644 --- a/contrib/llvm/include/llvm/Support/Dwarf.h +++ b/contrib/llvm/include/llvm/Support/Dwarf.h @@ -24,7 +24,7 @@ namespace llvm { //===----------------------------------------------------------------------===// // Debug info constants. -enum LLVM_ENUM_INT_TYPE(uint32_t) { +enum : uint32_t { LLVMDebugVersion = (12 << 16), // Current version of debug information. LLVMDebugVersion11 = (11 << 16), // Constant for version 11. LLVMDebugVersion10 = (10 << 16), // Constant for version 10. @@ -41,13 +41,13 @@ namespace dwarf { //===----------------------------------------------------------------------===// // Dwarf constants as gleaned from the DWARF Debugging Information Format V.4 -// reference manual http://dwarf.freestandards.org. +// reference manual http://www.dwarfstd.org/. // // Do not mix the following two enumerations sets. DW_TAG_invalid changes the // enumeration base type. -enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) { +enum LLVMConstants : uint32_t { // llvm mock tags DW_TAG_invalid = ~0U, // Tag for invalid results. @@ -57,7 +57,6 @@ enum LLVMConstants LLVM_ENUM_INT_TYPE(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. @@ -68,7 +67,7 @@ enum LLVMConstants LLVM_ENUM_INT_TYPE(uint32_t) { const uint32_t DW_CIE_ID = UINT32_MAX; const uint64_t DW64_CIE_ID = UINT64_MAX; -enum Tag LLVM_ENUM_INT_TYPE(uint16_t) { +enum Tag : uint16_t { DW_TAG_array_type = 0x01, DW_TAG_class_type = 0x02, DW_TAG_entry_point = 0x03, @@ -129,6 +128,12 @@ enum Tag LLVM_ENUM_INT_TYPE(uint16_t) { DW_TAG_type_unit = 0x41, DW_TAG_rvalue_reference_type = 0x42, DW_TAG_template_alias = 0x43, + + // New in DWARF 5: + DW_TAG_coarray_type = 0x44, + DW_TAG_generic_subrange = 0x45, + DW_TAG_dynamic_type = 0x46, + DW_TAG_MIPS_loop = 0x4081, DW_TAG_format_label = 0x4101, DW_TAG_function_template = 0x4102, @@ -169,7 +174,7 @@ inline bool isType(Tag T) { } } -enum Attribute LLVM_ENUM_INT_TYPE(uint16_t) { +enum Attribute : uint16_t { // Attributes DW_AT_sibling = 0x01, DW_AT_location = 0x02, @@ -264,6 +269,18 @@ enum Attribute LLVM_ENUM_INT_TYPE(uint16_t) { DW_AT_enum_class = 0x6d, DW_AT_linkage_name = 0x6e, + // New in DWARF 5: + DW_AT_string_length_bit_size = 0x6f, + DW_AT_string_length_byte_size = 0x70, + DW_AT_rank = 0x71, + DW_AT_str_offsets_base = 0x72, + DW_AT_addr_base = 0x73, + DW_AT_ranges_base = 0x74, + DW_AT_dwo_id = 0x75, + DW_AT_dwo_name = 0x76, + DW_AT_reference = 0x77, + DW_AT_rvalue_reference = 0x78, + DW_AT_lo_user = 0x2000, DW_AT_hi_user = 0x3fff, @@ -323,7 +340,7 @@ enum Attribute LLVM_ENUM_INT_TYPE(uint16_t) { DW_AT_APPLE_property = 0x3fed }; -enum Form LLVM_ENUM_INT_TYPE(uint16_t) { +enum Form : uint16_t { // Attribute form encodings DW_FORM_addr = 0x01, DW_FORM_block2 = 0x03, @@ -605,7 +622,16 @@ enum SourceLanguage { DW_LANG_ObjC_plus_plus = 0x0011, DW_LANG_UPC = 0x0012, DW_LANG_D = 0x0013, + // New in DWARF 5: DW_LANG_Python = 0x0014, + DW_LANG_OpenCL = 0x0015, + DW_LANG_Go = 0x0016, + DW_LANG_Modula3 = 0x0017, + DW_LANG_Haskell = 0x0018, + DW_LANG_C_plus_plus_03 = 0x0019, + DW_LANG_C_plus_plus_11 = 0x001a, + DW_LANG_OCaml = 0x001b, + DW_LANG_lo_user = 0x8000, DW_LANG_Mips_Assembler = 0x8001, DW_LANG_hi_user = 0xffff @@ -744,6 +770,15 @@ enum Constants { DW_EH_PE_indirect = 0x80 }; +// Constants for debug_loc.dwo in the DWARF5 Split Debug Info Proposal +enum LocationListEntry : unsigned char { + DW_LLE_end_of_list_entry, + DW_LLE_base_address_selection_entry, + DW_LLE_start_end_entry, + DW_LLE_start_length_entry, + DW_LLE_offset_pair_entry +}; + enum ApplePropertyAttributes { // Apple Objective-C Property Attributes DW_APPLE_PROPERTY_readonly = 0x01, diff --git a/contrib/llvm/include/llvm/Support/DynamicLibrary.h b/contrib/llvm/include/llvm/Support/DynamicLibrary.h index 1e2d16c..de47be6 100644 --- a/contrib/llvm/include/llvm/Support/DynamicLibrary.h +++ b/contrib/llvm/include/llvm/Support/DynamicLibrary.h @@ -65,7 +65,7 @@ namespace sys { /// It is safe to call this function multiple times for the same library. /// @brief Open a dynamic library permanently. static DynamicLibrary getPermanentLibrary(const char *filename, - std::string *errMsg = 0); + std::string *errMsg = nullptr); /// This function permanently loads the dynamic library at the given path. /// Use this instead of getPermanentLibrary() when you won't need to get @@ -73,7 +73,7 @@ namespace sys { /// /// It is safe to call this function multiple times for the same library. static bool LoadLibraryPermanently(const char *Filename, - std::string *ErrMsg = 0) { + std::string *ErrMsg = nullptr) { return !getPermanentLibrary(Filename, ErrMsg).isValid(); } diff --git a/contrib/llvm/include/llvm/Support/ELF.h b/contrib/llvm/include/llvm/Support/ELF.h index 541410f..42abe89 100644 --- a/contrib/llvm/include/llvm/Support/ELF.h +++ b/contrib/llvm/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. @@ -475,6 +496,37 @@ enum { R_PPC_REL16_HA = 252 }; +// Specific e_flags for PPC64 +enum { + // e_flags bits specifying ABI: + // 1 for original ABI using function descriptors, + // 2 for revised ABI without function descriptors, + // 0 for unspecified or not using any features affected by the differences. + EF_PPC64_ABI = 3 +}; + +// Special values for the st_other field in the symbol table entry for PPC64. +enum { + STO_PPC64_LOCAL_BIT = 5, + STO_PPC64_LOCAL_MASK = (7 << STO_PPC64_LOCAL_BIT) +}; +static inline int64_t +decodePPC64LocalEntryOffset(unsigned Other) { + unsigned Val = (Other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT; + return ((1 << Val) >> 2) << 2; +} +static inline unsigned +encodePPC64LocalEntryOffset(int64_t Offset) { + unsigned Val = (Offset >= 4 * 4 + ? (Offset >= 8 * 4 + ? (Offset >= 16 * 4 ? 6 : 5) + : 4) + : (Offset >= 2 * 4 + ? 3 + : (Offset >= 1 * 4 ? 2 : 0))); + return Val << STO_PPC64_LOCAL_BIT; +} + // ELF Relocation types for PPC64 enum { R_PPC64_NONE = 0, @@ -652,7 +704,7 @@ enum { }; // ARM Specific e_flags -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { EF_ARM_SOFT_FLOAT = 0x00000200U, EF_ARM_VFP_FLOAT = 0x00000400U, EF_ARM_EABI_UNKNOWN = 0x00000000U, @@ -802,10 +854,13 @@ enum { }; // Mips Specific e_flags -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions EF_MIPS_PIC = 0x00000002, // Position independent code EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code + EF_MIPS_ABI2 = 0x00000020, + EF_MIPS_32BITMODE = 0x00000100, + EF_MIPS_NAN2008 = 0x00000400, // Uses IEE 754-2008 NaN encoding EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI //ARCH_ASE @@ -822,11 +877,12 @@ enum LLVM_ENUM_INT_TYPE(unsigned) { EF_MIPS_ARCH_64 = 0x60000000, // MIPS64 instruction set per linux not elf.h EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2 EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2 + EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6 + EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6 EF_MIPS_ARCH = 0xf0000000 // Mask for applying EF_MIPS_ARCH_ variant }; // ELF Relocation types for Mips -// . enum { R_MIPS_NONE = 0, R_MIPS_16 = 1, @@ -838,7 +894,6 @@ enum { R_MIPS_GPREL16 = 7, R_MIPS_LITERAL = 8, R_MIPS_GOT16 = 9, - R_MIPS_GOT = 9, R_MIPS_PC16 = 10, R_MIPS_CALL16 = 11, R_MIPS_GPREL32 = 12, @@ -880,6 +935,15 @@ enum { R_MIPS_TLS_TPREL_HI16 = 49, R_MIPS_TLS_TPREL_LO16 = 50, R_MIPS_GLOB_DAT = 51, + R_MIPS_PC21_S2 = 60, + R_MIPS_PC26_S2 = 61, + R_MIPS_PC18_S3 = 62, + R_MIPS_PC19_S2 = 63, + R_MIPS_PCHI16 = 64, + R_MIPS_PCLO16 = 65, + R_MIPS16_GOT16 = 102, + R_MIPS16_HI16 = 104, + R_MIPS16_LO16 = 105, R_MIPS_COPY = 126, R_MIPS_JUMP_SLOT = 127, R_MICROMIPS_26_S1 = 133, @@ -891,16 +955,23 @@ enum { R_MICROMIPS_GOT_DISP = 145, R_MICROMIPS_GOT_PAGE = 146, R_MICROMIPS_GOT_OFST = 147, + R_MICROMIPS_TLS_GD = 162, + R_MICROMIPS_TLS_LDM = 163, R_MICROMIPS_TLS_DTPREL_HI16 = 164, R_MICROMIPS_TLS_DTPREL_LO16 = 165, R_MICROMIPS_TLS_TPREL_HI16 = 169, R_MICROMIPS_TLS_TPREL_LO16 = 170, - R_MIPS_NUM = 218 + R_MIPS_NUM = 218, + R_MIPS_PC32 = 248 }; // Special values for the st_other field in the symbol table entry for MIPS. enum { - STO_MIPS_MICROMIPS = 0x80 // MIPS Specific ISA for MicroMips + STO_MIPS_OPTIONAL = 0x04, // Symbol whose definition is optional + STO_MIPS_PLT = 0x08, // PLT entry related dynamic table record + STO_MIPS_PIC = 0x20, // PIC func in an object mixes PIC/non-PIC + STO_MIPS_MICROMIPS = 0x80, // MIPS Specific ISA for MicroMips + STO_MIPS_MIPS16 = 0xf0 // MIPS Specific ISA for Mips16 }; // Hexagon Specific e_flags @@ -1219,7 +1290,7 @@ enum { }; // Section types. -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { SHT_NULL = 0, // No associated section (inactive entry). SHT_PROGBITS = 1, // Program-defined contents. SHT_SYMTAB = 2, // Symbol table. @@ -1260,6 +1331,7 @@ enum LLVM_ENUM_INT_TYPE(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. @@ -1267,7 +1339,7 @@ enum LLVM_ENUM_INT_TYPE(unsigned) { }; // Section flags. -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { // Section data should be writable during execution. SHF_WRITE = 0x1, @@ -1359,7 +1431,7 @@ enum LLVM_ENUM_INT_TYPE(unsigned) { }; // Section Group Flags -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { GRP_COMDAT = 0x1, GRP_MASKOS = 0x0ff00000, GRP_MASKPROC = 0xf0000000 @@ -1577,11 +1649,12 @@ 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. -enum LLVM_ENUM_INT_TYPE(unsigned) { +enum : unsigned { PF_X = 1, // Execute PF_W = 2, // Write PF_R = 4, // Read @@ -1655,6 +1728,7 @@ enum { DT_LOPROC = 0x70000000, // Start of processor specific tags. DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags. + DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table. DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count. DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. diff --git a/contrib/llvm/include/llvm/Support/Endian.h b/contrib/llvm/include/llvm/Support/Endian.h index 0d35849..455d0fc 100644 --- a/contrib/llvm/include/llvm/Support/Endian.h +++ b/contrib/llvm/include/llvm/Support/Endian.h @@ -17,7 +17,6 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Host.h" #include "llvm/Support/SwapByteOrder.h" -#include "llvm/Support/type_traits.h" namespace llvm { namespace support { @@ -35,13 +34,15 @@ namespace detail { } // end namespace detail namespace endian { +/// Swap the bytes of value to match the given endianness. 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; } +/// Read a value of a particular endianness from memory. template<typename value_type, endianness endian, std::size_t alignment> @@ -55,6 +56,16 @@ inline value_type read(const void *memory) { return byte_swap<value_type, endian>(ret); } +/// Read a value of a particular endianness from a buffer, and increment the +/// buffer past that value. +template<typename value_type, endianness endian, std::size_t alignment> +inline value_type readNext(const unsigned char *&memory) { + value_type ret = read<value_type, endian, alignment>(memory); + memory += sizeof(value_type); + return ret; +} + +/// Write a value to memory with a particular endianness. template<typename value_type, endianness endian, std::size_t alignment> diff --git a/contrib/llvm/include/llvm/Support/EndianStream.h b/contrib/llvm/include/llvm/Support/EndianStream.h new file mode 100644 index 0000000..89c66d3 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/EndianStream.h @@ -0,0 +1,39 @@ +//===- EndianStream.h - Stream ops with endian specific data ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines utilities for operating on streams that have endian +// specific data. +// +//===----------------------------------------------------------------------===// + +#ifndef _LLVM_SUPPORT_ENDIAN_STREAM_H_ +#define _LLVM_SUPPORT_ENDIAN_STREAM_H_ + +#include <llvm/Support/Endian.h> +#include <llvm/Support/raw_ostream.h> + +namespace llvm { +namespace support { + +namespace endian { +/// Adapter to write values to a stream in a particular byte order. +template <endianness endian> struct Writer { + raw_ostream &OS; + Writer(raw_ostream &OS) : OS(OS) {} + template <typename value_type> void write(value_type Val) { + Val = byte_swap<value_type, endian>(Val); + OS.write((const char *)&Val, sizeof(value_type)); + } +}; +} // end namespace endian + +} // end namespace support +} // end namespace llvm + +#endif // _LLVM_SUPPORT_ENDIAN_STREAM_H_ diff --git a/contrib/llvm/include/llvm/Support/Errc.h b/contrib/llvm/include/llvm/Support/Errc.h new file mode 100644 index 0000000..80bfe2a --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/include/llvm/Support/ErrorHandling.h b/contrib/llvm/include/llvm/Support/ErrorHandling.h index b948d97..9afd52d 100644 --- a/contrib/llvm/include/llvm/Support/ErrorHandling.h +++ b/contrib/llvm/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 @@ -47,11 +44,9 @@ namespace llvm { /// \param user_data - An argument which will be passed to the install error /// handler. void install_fatal_error_handler(fatal_error_handler_t handler, - void *user_data = 0); + 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 @@ -59,7 +54,7 @@ namespace llvm { /// remove_fatal_error_handler in its destructor. struct ScopedFatalErrorHandler { explicit ScopedFatalErrorHandler(fatal_error_handler_t handler, - void *user_data = 0) { + void *user_data = nullptr) { install_fatal_error_handler(handler, user_data); } @@ -86,9 +81,9 @@ namespace llvm { /// This function calls abort(), and prints the optional message to stderr. /// Use the llvm_unreachable macro (that adds location info), instead of /// calling this function directly. - LLVM_ATTRIBUTE_NORETURN void llvm_unreachable_internal(const char *msg=0, - const char *file=0, - unsigned line=0); + LLVM_ATTRIBUTE_NORETURN void + llvm_unreachable_internal(const char *msg=nullptr, const char *file=nullptr, + unsigned line=0); } /// Marks that the current location is not supposed to be reachable. diff --git a/contrib/llvm/include/llvm/Support/ErrorOr.h b/contrib/llvm/include/llvm/Support/ErrorOr.h index d5b11cb..0742a2d 100644 --- a/contrib/llvm/include/llvm/Support/ErrorOr.h +++ b/contrib/llvm/include/llvm/Support/ErrorOr.h @@ -18,16 +18,11 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/AlignOf.h" -#include "llvm/Support/system_error.h" -#include "llvm/Support/type_traits.h" - #include <cassert> -#if LLVM_HAS_CXX11_TYPETRAITS +#include <system_error> #include <type_traits> -#endif namespace llvm { -#if LLVM_HAS_CXX11_TYPETRAITS && LLVM_HAS_RVALUE_REFERENCES template<class T, class V> typename std::enable_if< std::is_constructible<T, V>::value , typename std::remove_reference<V>::type>::type && @@ -41,12 +36,6 @@ typename std::enable_if< !std::is_constructible<T, V>::value moveIfMoveConstructible(V &Val) { return Val; } -#else -template<class T, class V> -V &moveIfMoveConstructible(V &Val) { - return Val; -} -#endif /// \brief Stores a reference that can be changed. template <typename T> @@ -71,11 +60,10 @@ public: /// It is used like the following. /// \code /// ErrorOr<Buffer> getBuffer(); -/// void handleError(error_code ec); /// /// auto buffer = getBuffer(); -/// if (!buffer) -/// handleError(buffer); +/// if (error_code ec = buffer.getError()) +/// return ec; /// buffer->write("adena"); /// \endcode /// @@ -93,35 +81,33 @@ public: template<class T> class ErrorOr { template <class OtherT> friend class ErrorOr; - static const bool isRef = is_reference<T>::value; - typedef ReferenceStorage<typename remove_reference<T>::type> wrap; + static const bool isRef = std::is_reference<T>::value; + typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap; public: - typedef typename - conditional< isRef - , wrap - , T - >::type storage_type; + typedef typename std::conditional<isRef, wrap, T>::type storage_type; private: - typedef typename remove_reference<T>::type &reference; - typedef typename remove_reference<T>::type *pointer; + typedef typename std::remove_reference<T>::type &reference; + typedef const typename std::remove_reference<T>::type &const_reference; + typedef typename std::remove_reference<T>::type *pointer; public: template <class E> - ErrorOr(E ErrorCode, typename enable_if_c<is_error_code_enum<E>::value || - is_error_condition_enum<E>::value, - void *>::type = 0) + 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 (getError()) error_code(make_error_code(ErrorCode)); + new (getErrorStorage()) std::error_code(make_error_code(ErrorCode)); } - ErrorOr(llvm::error_code EC) : HasError(true) { - new (getError()) error_code(EC); + ErrorOr(std::error_code EC) : HasError(true) { + new (getErrorStorage()) std::error_code(EC); } ErrorOr(T Val) : HasError(false) { - new (get()) storage_type(moveIfMoveConstructible<storage_type>(Val)); + new (getStorage()) storage_type(moveIfMoveConstructible<storage_type>(Val)); } ErrorOr(const ErrorOr &Other) { @@ -144,7 +130,6 @@ public: return *this; } -#if LLVM_HAS_RVALUE_REFERENCES ErrorOr(ErrorOr &&Other) { moveConstruct(std::move(Other)); } @@ -164,31 +149,30 @@ public: moveAssign(std::move(Other)); return *this; } -#endif ~ErrorOr() { if (!HasError) - get()->~storage_type(); + getStorage()->~storage_type(); } - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} - /// \brief Return false if there is an error. - operator unspecified_bool_type() const { - return HasError ? 0 : unspecified_bool_true; + LLVM_EXPLICIT operator bool() const { + return !HasError; } - operator llvm::error_code() const { - return HasError ? *getError() : llvm::error_code::success(); + reference get() { return *getStorage(); } + const_reference get() const { return const_cast<ErrorOr<T> >(this)->get(); } + + std::error_code getError() const { + return HasError ? *getErrorStorage() : std::error_code(); } pointer operator ->() { - return toPointer(get()); + return toPointer(getStorage()); } reference operator *() { - return *get(); + return *getStorage(); } private: @@ -197,11 +181,11 @@ private: if (!Other.HasError) { // Get the other value. HasError = false; - new (get()) storage_type(*Other.get()); + new (getStorage()) storage_type(*Other.getStorage()); } else { // Get other's error. HasError = true; - new (getError()) error_code(Other); + new (getErrorStorage()) std::error_code(Other.getError()); } } @@ -224,17 +208,16 @@ private: new (this) ErrorOr(Other); } -#if LLVM_HAS_RVALUE_REFERENCES template <class OtherT> void moveConstruct(ErrorOr<OtherT> &&Other) { if (!Other.HasError) { // Get the other value. HasError = false; - new (get()) storage_type(std::move(*Other.get())); + new (getStorage()) storage_type(std::move(*Other.getStorage())); } else { // Get other's error. HasError = true; - new (getError()) error_code(Other); + new (getErrorStorage()) std::error_code(Other.getError()); } } @@ -246,7 +229,6 @@ private: this->~ErrorOr(); new (this) ErrorOr(std::move(Other)); } -#endif pointer toPointer(pointer Val) { return Val; @@ -256,38 +238,39 @@ private: return &Val->get(); } - storage_type *get() { + storage_type *getStorage() { assert(!HasError && "Cannot get value when an error exists!"); return reinterpret_cast<storage_type*>(TStorage.buffer); } - const storage_type *get() const { + const storage_type *getStorage() const { assert(!HasError && "Cannot get value when an error exists!"); return reinterpret_cast<const storage_type*>(TStorage.buffer); } - error_code *getError() { + 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 *getError() const { - return const_cast<ErrorOr<T> *>(this)->getError(); + 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 enable_if_c<is_error_code_enum<E>::value || - is_error_condition_enum<E>::value, bool>::type -operator ==(ErrorOr<T> &Err, E Code) { - return error_code(Err) == Code; +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/contrib/llvm/include/llvm/Support/FEnv.h b/contrib/llvm/include/llvm/Support/FEnv.h deleted file mode 100644 index 8560ee0..0000000 --- a/contrib/llvm/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/contrib/llvm/include/llvm/Support/FileOutputBuffer.h b/contrib/llvm/include/llvm/Support/FileOutputBuffer.h index cbc9c46..0a9a979 100644 --- a/contrib/llvm/include/llvm/Support/FileOutputBuffer.h +++ b/contrib/llvm/include/llvm/Support/FileOutputBuffer.h @@ -14,15 +14,12 @@ #ifndef LLVM_SUPPORT_FILEOUTPUTBUFFER_H #define LLVM_SUPPORT_FILEOUTPUTBUFFER_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/FileSystem.h" namespace llvm { -class error_code; - /// 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 @@ -40,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, - OwningPtr<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() { @@ -69,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 @@ -83,7 +80,7 @@ private: FileOutputBuffer(llvm::sys::fs::mapped_file_region *R, StringRef Path, StringRef TempPath); - OwningPtr<llvm::sys::fs::mapped_file_region> Region; + std::unique_ptr<llvm::sys::fs::mapped_file_region> Region; SmallString<128> FinalPath; SmallString<128> TempPath; }; diff --git a/contrib/llvm/include/llvm/Support/FileSystem.h b/contrib/llvm/include/llvm/Support/FileSystem.h index d301f84..556701c 100644 --- a/contrib/llvm/include/llvm/Support/FileSystem.h +++ b/contrib/llvm/include/llvm/Support/FileSystem.h @@ -28,17 +28,17 @@ #define LLVM_SUPPORT_FILESYSTEM_H #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #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> #ifdef HAVE_SYS_STAT_H @@ -49,28 +49,18 @@ namespace llvm { namespace sys { namespace fs { -/// file_type - An "enum class" enumeration for the file system's view of the -/// type. -struct file_type { - enum _ { - status_error, - file_not_found, - regular_file, - directory_file, - symlink_file, - block_file, - character_file, - fifo_file, - socket_file, - type_unknown - }; - - file_type(_ v) : v_(v) {} - explicit file_type(int v) : v_(_(v)) {} - operator int() const {return v_;} - -private: - int v_; +/// 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. @@ -137,15 +127,14 @@ public: } bool operator!=(const UniqueID &Other) const { return !(*this == Other); } bool operator<(const UniqueID &Other) const { - return Device < Other.Device || - (Device == Other.Device && File < Other.File); + return std::tie(Device, File) < std::tie(Other.Device, Other.File); } uint64_t getDevice() const { return Device; } uint64_t getFile() const { return File; } }; /// 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) @@ -168,15 +157,30 @@ class file_status file_type Type; perms Perms; public: - file_status() : Type(file_type::status_error) {} - file_status(file_type Type) : Type(Type) {} - #if defined(LLVM_ON_UNIX) + file_status() : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), + fs_st_uid(0), fs_st_gid(0), fs_st_size(0), + Type(file_type::status_error), Perms(perms_not_known) {} + + file_status(file_type Type) : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), + fs_st_uid(0), fs_st_gid(0), fs_st_size(0), Type(Type), + Perms(perms_not_known) {} + file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t MTime, uid_t UID, gid_t GID, off_t Size) : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_mtime(MTime), fs_st_uid(UID), fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {} #elif defined(LLVM_ON_WIN32) + file_status() : LastWriteTimeHigh(0), LastWriteTimeLow(0), + VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), + FileIndexHigh(0), FileIndexLow(0), Type(file_type::status_error), + Perms(perms_not_known) {} + + file_status(file_type Type) : LastWriteTimeHigh(0), LastWriteTimeLow(0), + VolumeSerialNumber(0), FileSizeHigh(0), FileSizeLow(0), + FileIndexHigh(0), FileIndexLow(0), Type(Type), + Perms(perms_not_known) {} + file_status(file_type Type, uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber, uint32_t FileSizeHigh, uint32_t FileSizeLow, @@ -269,107 +273,81 @@ 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 +/// +/// If the path contains any '\' separators, they are transformed into '/'. +/// 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. +std::error_code normalize_separators(SmallVectorImpl<char> &Path); /// @brief Create all the non-existent directories in path. /// /// @param path Directories to create. -/// @param existed Set to true if \a path already existed, false otherwise. -/// @returns errc::success if is_directory(path) and existed have been set, -/// otherwise a platform specific error_code. -error_code create_directories(const Twine &path, bool &existed); - -/// @brief Convenience function for clients that don't need to know if the -/// directory existed or not. -inline error_code create_directories(const Twine &Path) { - bool Existed; - return create_directories(Path, Existed); -} +/// @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. +std::error_code create_directories(const Twine &path, + bool IgnoreExisting = true); /// @brief Create the directory in path. /// /// @param path Directory to create. -/// @param existed Set to true if \a path already existed, false otherwise. -/// @returns errc::success if is_directory(path) and existed have been set, -/// otherwise a platform specific error_code. -error_code create_directory(const Twine &path, bool &existed); - -/// @brief Convenience function for clients that don't need to know if the -/// directory existed or not. -inline error_code create_directory(const Twine &Path) { - bool Existed; - return create_directory(Path, Existed); -} +/// @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. +std::error_code create_directory(const Twine &path, bool IgnoreExisting = true); -/// @brief Create a hard link from \a from to \a to. +/// @brief Create a link from \a from to \a to. +/// +/// The link may be a soft or a hard link, depending on the platform. The caller +/// may not assume which one. Currently on windows it creates a hard link since +/// soft links require extra privileges. On unix, it creates a soft link since +/// hard links don't work on SMB file systems. /// /// @param to The path to hard link to. /// @param from The path to hard link from. This is created. -/// @returns errc::success if exists(to) && exists(from) && equivalent(to, from) -/// , otherwise a platform specific error_code. -error_code create_hard_link(const Twine &to, const Twine &from); - -/// @brief Create a symbolic link from \a from to \a to. -/// -/// @param to The path to symbolically link to. -/// @param from The path to symbolically link from. This is created. -/// @returns errc::success if exists(to) && exists(from) && is_symlink(from), -/// otherwise a platform specific error_code. -error_code create_symlink(const Twine &to, const Twine &from); +/// @returns errc::success if the link was created, otherwise a platform +/// specific error_code. +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. -/// @param existed Set to true if \a path existed, false if it did not. -/// undefined otherwise. -/// @returns errc::success if path has been removed and existed has been -/// successfully set, otherwise a platform specific error_code. -error_code remove(const Twine &path, bool &existed); - -/// @brief Convenience function for clients that don't need to know if the file -/// existed or not. -inline error_code remove(const Twine &Path) { - bool Existed; - return remove(Path, Existed); -} - -/// @brief Recursively remove all files below \a path, then \a path. Files are -/// removed as if by POSIX remove(). -/// -/// @param path Input path. -/// @param num_removed Number of files removed. -/// @returns errc::success if path has been removed and num_removed has been -/// successfully set, otherwise a platform specific error_code. -error_code remove_all(const Twine &path, uint32_t &num_removed); - -/// @brief Convenience function for clients that don't need to know how many -/// files were removed. -inline error_code remove_all(const Twine &Path) { - uint32_t Removed; - return remove_all(Path, Removed); -} +/// @returns errc::success if path has been removed or didn't exist, otherwise a +/// platform-specific error code. If IgnoreNonExisting is false, also +/// returns error if the file didn't exist. +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 @@ -388,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. @@ -430,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. @@ -452,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. @@ -474,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. @@ -490,8 +468,7 @@ inline bool is_regular_file(const Twine &Path) { /// directory, regular file, or symlink? /// /// @param status A file_status previously returned from status. -/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) && -/// !is_symlink(s) +/// @returns exists(s) && !is_regular_file(s) && !is_directory(s) bool is_other(file_status status); /// @brief Is path something that exists but is not a directory, @@ -501,51 +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); - -/// @brief Does status represent a symlink? -/// -/// @param status A file_status previously returned from stat. -/// @returns status.type() == symlink_file. -bool is_symlink(file_status status); - -/// @brief Is path a symlink? -/// -/// @param path Input path. -/// @param result Set to true if \a path is a symlink, false if it is not. -/// Undefined otherwise. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code is_symlink(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(); } -error_code setLastModificationAndAccessTime(int FD, TimeValue Time); +/// @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::function_not_supported on +/// platforms where the functionality isn't available. +std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time); /// @brief Is status available? /// @@ -558,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. /// @@ -581,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. /// @@ -598,18 +565,18 @@ 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 { +enum OpenFlags : unsigned { F_None = 0, /// F_Excl - When opening a file, this flag makes raw_fd_ostream @@ -621,9 +588,12 @@ enum OpenFlags { /// with F_Excl. F_Append = 2, - /// F_Binary - The file should be opened in binary mode on platforms that - /// make this distinction. - F_Binary = 4 + /// The file should be opened in text mode on platforms that make this + /// distinction. + F_Text = 4, + + /// Open the file for read and write. + F_RW = 8 }; inline OpenFlags operator|(OpenFlags A, OpenFlags B) { @@ -635,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); @@ -669,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. @@ -689,7 +638,7 @@ public: }; private: - /// Platform specific mapping state. + /// Platform-specific mapping state. mapmode Mode; uint64_t Size; void *Mapping; @@ -699,15 +648,13 @@ 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; -#if LLVM_HAS_RVALUE_REFERENCES mapped_file_region(mapped_file_region&&); mapped_file_region &operator =(mapped_file_region&&); -#endif /// Construct a mapped_file_region at \a path starting at \a offset of length /// \a length and with access \a mode. @@ -723,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(); @@ -753,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. @@ -808,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); } @@ -821,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. @@ -847,23 +763,23 @@ 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()); } /// Construct end iterator. - directory_iterator() : State(0) {} + 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; } @@ -874,9 +790,9 @@ public: bool operator==(const directory_iterator &RHS) const { if (State == RHS.State) return true; - if (RHS.State == 0) + if (!RHS.State) return State->CurrentEntry == directory_entry(); - if (State == 0) + if (!State) return RHS.State->CurrentEntry == directory_entry(); return State->CurrentEntry == RHS.State->CurrentEntry; } @@ -909,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) @@ -965,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/contrib/llvm/include/llvm/Support/FileUtilities.h b/contrib/llvm/include/llvm/Support/FileUtilities.h index 79c59e4..3f2f176 100644 --- a/contrib/llvm/include/llvm/Support/FileUtilities.h +++ b/contrib/llvm/include/llvm/Support/FileUtilities.h @@ -30,7 +30,7 @@ namespace llvm { int DiffFilesWithTolerance(StringRef FileA, StringRef FileB, double AbsTol, double RelTol, - std::string *Error = 0); + std::string *Error = nullptr); /// FileRemover - This class is a simple object meant to be stack allocated. @@ -51,8 +51,7 @@ namespace llvm { ~FileRemover() { if (DeleteIt) { // Ignore problems deleting the file. - bool existed; - sys::fs::remove(Filename.str(), existed); + sys::fs::remove(Filename.str()); } } @@ -62,8 +61,7 @@ namespace llvm { void setFile(const Twine& filename, bool deleteIt = true) { if (DeleteIt) { // Ignore problems deleting the file. - bool existed; - sys::fs::remove(Filename.str(), existed); + sys::fs::remove(Filename.str()); } Filename.clear(); diff --git a/contrib/llvm/include/llvm/Support/Format.h b/contrib/llvm/include/llvm/Support/Format.h index aaa54e1..b713cc7 100644 --- a/contrib/llvm/include/llvm/Support/Format.h +++ b/contrib/llvm/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; @@ -84,15 +86,11 @@ public: : format_object_base(fmt), Val(val) { } - virtual int snprint(char *Buffer, unsigned BufferSize) const { + int snprint(char *Buffer, unsigned BufferSize) const override { return snprintf(Buffer, BufferSize, Fmt, Val); } }; -/// 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; @@ -102,15 +100,11 @@ public: : format_object_base(fmt), Val1(val1), Val2(val2) { } - virtual int snprint(char *Buffer, unsigned BufferSize) const { + int snprint(char *Buffer, unsigned BufferSize) const override { return snprintf(Buffer, BufferSize, Fmt, Val1, Val2); } }; -/// 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; @@ -121,15 +115,11 @@ public: : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) { } - virtual int snprint(char *Buffer, unsigned BufferSize) const { + int snprint(char *Buffer, unsigned BufferSize) const override { return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3); } }; -/// 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; @@ -142,15 +132,11 @@ public: : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) { } - virtual int snprint(char *Buffer, unsigned BufferSize) const { + int snprint(char *Buffer, unsigned BufferSize) const override { return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4); } }; -/// 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; @@ -165,52 +151,57 @@ public: Val5(val5) { } - virtual int snprint(char *Buffer, unsigned BufferSize) const { + int snprint(char *Buffer, unsigned BufferSize) const override { return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5); } }; -/// 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/contrib/llvm/include/llvm/Support/FormattedStream.h b/contrib/llvm/include/llvm/Support/FormattedStream.h index df1f218..8137daa 100644 --- a/contrib/llvm/include/llvm/Support/FormattedStream.h +++ b/contrib/llvm/include/llvm/Support/FormattedStream.h @@ -57,11 +57,11 @@ private: /// const char *Scanned; - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, /// not counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE { + uint64_t current_pos() const override { // Our current position in the stream is all the contents which have been // written to the underlying stream (*not* the current position of the // underlying stream). @@ -85,12 +85,12 @@ public: /// underneath it. /// formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) - : raw_ostream(), TheStream(0), DeleteStream(false), Position(0, 0) { + : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { setStream(Stream, Delete); } explicit formatted_raw_ostream() - : raw_ostream(), TheStream(0), DeleteStream(false), Position(0, 0) { - Scanned = 0; + : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { + Scanned = nullptr; } ~formatted_raw_ostream() { @@ -114,7 +114,7 @@ public: SetUnbuffered(); TheStream->SetUnbuffered(); - Scanned = 0; + Scanned = nullptr; } /// PadToColumn - Align the output to some column number. If the current @@ -129,25 +129,23 @@ public: /// getLine - Return the line number unsigned getLine() { return Position.second; } - - raw_ostream &resetColor() { + + raw_ostream &resetColor() override { TheStream->resetColor(); return *this; } - - raw_ostream &reverseColor() { + + raw_ostream &reverseColor() override { TheStream->reverseColor(); return *this; } - - raw_ostream &changeColor(enum Colors Color, - bool Bold, - bool BG) { + + raw_ostream &changeColor(enum Colors Color, bool Bold, bool BG) override { TheStream->changeColor(Color, Bold, BG); return *this; } - - bool is_displayed() const { + + bool is_displayed() const override { return TheStream->is_displayed(); } diff --git a/contrib/llvm/include/llvm/Support/GCOV.h b/contrib/llvm/include/llvm/Support/GCOV.h index 0aa716a..0cb6cfd 100644 --- a/contrib/llvm/include/llvm/Support/GCOV.h +++ b/contrib/llvm/include/llvm/Support/GCOV.h @@ -1,4 +1,4 @@ -//===-- llvm/Support/GCOV.h - LLVM coverage tool ----------------*- C++ -*-===// +//===- GCOV.h - LLVM coverage tool ----------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This header provides the interface to read and write coverage files that +// This header provides the interface to read and write coverage files that // use 'gcov' format. // //===----------------------------------------------------------------------===// @@ -16,6 +16,7 @@ #define LLVM_SUPPORT_GCOV_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/MemoryBuffer.h" @@ -28,36 +29,71 @@ class GCOVBlock; class FileInfo; namespace GCOV { - enum GCOVFormat { - InvalidGCOV, - GCNO_402, - GCNO_404, - GCDA_402, - GCDA_404 + enum GCOVVersion { + V402, + V404 }; } // end GCOV namespace +/// GCOVOptions - A struct for passing gcov options between functions. +struct GCOVOptions { + GCOVOptions(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N) + : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), + PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {} + + bool AllBlocks; + bool BranchInfo; + bool BranchCount; + bool FuncCoverage; + bool PreservePaths; + bool UncondBranch; + bool LongFileNames; + bool NoOutput; +}; + /// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific /// read operations. class GCOVBuffer { public: GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {} - /// readGCOVFormat - Read GCOV signature at the beginning of buffer. - GCOV::GCOVFormat readGCOVFormat() { - StringRef Magic = Buffer->getBuffer().slice(0, 12); - Cursor = 12; - if (Magic == "oncg*404MVLL") - return GCOV::GCNO_404; - else if (Magic == "oncg*204MVLL") - return GCOV::GCNO_402; - else if (Magic == "adcg*404MVLL") - return GCOV::GCDA_404; - else if (Magic == "adcg*204MVLL") - return GCOV::GCDA_402; - - Cursor = 0; - return GCOV::InvalidGCOV; + /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer. + bool readGCNOFormat() { + StringRef File = Buffer->getBuffer().slice(0, 4); + if (File != "oncg") { + errs() << "Unexpected file type: " << File << ".\n"; + return false; + } + Cursor = 4; + return true; + } + + /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer. + bool readGCDAFormat() { + StringRef File = Buffer->getBuffer().slice(0, 4); + if (File != "adcg") { + errs() << "Unexpected file type: " << File << ".\n"; + return false; + } + Cursor = 4; + return true; + } + + /// readGCOVVersion - Read GCOV version. + bool readGCOVVersion(GCOV::GCOVVersion &Version) { + StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4); + if (VersionStr == "*204") { + Cursor += 4; + Version = GCOV::V402; + return true; + } + if (VersionStr == "*404") { + Cursor += 4; + Version = GCOV::V404; + return true; + } + errs() << "Unexpected version: " << VersionStr << ".\n"; + return false; } /// readFunctionTag - If cursor points to a function tag then increment the @@ -170,8 +206,11 @@ public: } bool readString(StringRef &Str) { - uint32_t Len; - if (!readInt(Len)) return false; + uint32_t Len = 0; + // Keep reading until we find a non-zero length. This emulates gcov's + // behaviour, which appears to do the same. + while (Len == 0) + if (!readInt(Len)) return false; Len *= 4; if (Buffer->getBuffer().size() < Cursor+Len) { errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n"; @@ -193,67 +232,196 @@ private: /// (.gcno and .gcda). class GCOVFile { public: - GCOVFile() : Functions(), RunCount(0), ProgramCount(0) {} - ~GCOVFile(); - bool read(GCOVBuffer &Buffer); - void dump(); + GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0), + ProgramCount(0) {} + bool readGCNO(GCOVBuffer &Buffer); + bool readGCDA(GCOVBuffer &Buffer); + uint32_t getChecksum() const { return Checksum; } + void dump() const; void collectLineCounts(FileInfo &FI); private: - SmallVector<GCOVFunction *, 16> Functions; + bool GCNOInitialized; + GCOV::GCOVVersion Version; + uint32_t Checksum; + SmallVector<std::unique_ptr<GCOVFunction>, 16> Functions; uint32_t RunCount; uint32_t ProgramCount; }; +/// GCOVEdge - Collects edge information. +struct GCOVEdge { + GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D), Count(0) {} + + GCOVBlock &Src; + GCOVBlock &Dst; + uint64_t Count; +}; + /// GCOVFunction - Collects function information. class GCOVFunction { public: - GCOVFunction() : Ident(0), LineNumber(0) {} - ~GCOVFunction(); - bool read(GCOVBuffer &Buffer, GCOV::GCOVFormat Format); + typedef SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator + BlockIterator; + + GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {} + bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); + bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); + StringRef getName() const { return Name; } StringRef getFilename() const { return Filename; } - void dump(); + size_t getNumBlocks() const { return Blocks.size(); } + uint64_t getEntryCount() const; + uint64_t getExitCount() const; + + BlockIterator block_begin() const { return Blocks.begin(); } + BlockIterator block_end() const { return Blocks.end(); } + + void dump() const; void collectLineCounts(FileInfo &FI); private: + GCOVFile &Parent; uint32_t Ident; + uint32_t Checksum; uint32_t LineNumber; StringRef Name; StringRef Filename; - SmallVector<GCOVBlock *, 16> Blocks; + SmallVector<std::unique_ptr<GCOVBlock>, 16> Blocks; + SmallVector<std::unique_ptr<GCOVEdge>, 16> Edges; }; /// GCOVBlock - Collects block information. class GCOVBlock { + struct EdgeWeight { + EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {} + + GCOVBlock *Dst; + uint64_t Count; + }; + + struct SortDstEdgesFunctor { + bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) { + return E1->Dst.Number < E2->Dst.Number; + } + }; public: - GCOVBlock(GCOVFunction &P, uint32_t N) : - Parent(P), Number(N), Counter(0), Edges(), Lines() {} + typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator; + + GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0), + DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {} ~GCOVBlock(); - void addEdge(uint32_t N) { Edges.push_back(N); } + const GCOVFunction &getParent() const { return Parent; } void addLine(uint32_t N) { Lines.push_back(N); } - void addCount(uint64_t N) { Counter += N; } - size_t getNumEdges() { return Edges.size(); } - void dump(); + uint32_t getLastLine() const { return Lines.back(); } + void addCount(size_t DstEdgeNo, uint64_t N); + uint64_t getCount() const { return Counter; } + + void addSrcEdge(GCOVEdge *Edge) { + assert(&Edge->Dst == this); // up to caller to ensure edge is valid + SrcEdges.push_back(Edge); + } + void addDstEdge(GCOVEdge *Edge) { + assert(&Edge->Src == this); // up to caller to ensure edge is valid + // Check if adding this edge causes list to become unsorted. + if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number) + DstEdgesAreSorted = false; + DstEdges.push_back(Edge); + } + size_t getNumSrcEdges() const { return SrcEdges.size(); } + size_t getNumDstEdges() const { return DstEdges.size(); } + void sortDstEdges(); + + EdgeIterator src_begin() const { return SrcEdges.begin(); } + EdgeIterator src_end() const { return SrcEdges.end(); } + EdgeIterator dst_begin() const { return DstEdges.begin(); } + EdgeIterator dst_end() const { return DstEdges.end(); } + + void dump() const; void collectLineCounts(FileInfo &FI); private: GCOVFunction &Parent; uint32_t Number; uint64_t Counter; - SmallVector<uint32_t, 16> Edges; + bool DstEdgesAreSorted; + SmallVector<GCOVEdge *, 16> SrcEdges; + SmallVector<GCOVEdge *, 16> DstEdges; SmallVector<uint32_t, 16> Lines; }; -typedef DenseMap<uint32_t, uint64_t> LineCounts; class FileInfo { + // It is unlikely--but possible--for multiple functions to be on the same line. + // Therefore this typedef allows LineData.Functions to store multiple functions + // per instance. This is rare, however, so optimize for the common case. + typedef SmallVector<const GCOVFunction *, 1> FunctionVector; + typedef DenseMap<uint32_t, FunctionVector> FunctionLines; + typedef SmallVector<const GCOVBlock *, 4> BlockVector; + typedef DenseMap<uint32_t, BlockVector> BlockLines; + + struct LineData { + LineData() : LastLine(0) {} + BlockLines Blocks; + FunctionLines Functions; + uint32_t LastLine; + }; + + struct GCOVCoverage { + GCOVCoverage(StringRef Name) : + Name(Name), LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0), + BranchesTaken(0) {} + + StringRef Name; + + uint32_t LogicalLines; + uint32_t LinesExec; + + uint32_t Branches; + uint32_t BranchesExec; + uint32_t BranchesTaken; + }; public: - void addLineCount(StringRef Filename, uint32_t Line, uint64_t Count) { - LineInfo[Filename][Line-1] += Count; + FileInfo(const GCOVOptions &Options) : + Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {} + + void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) { + if (Line > LineInfo[Filename].LastLine) + LineInfo[Filename].LastLine = Line; + LineInfo[Filename].Blocks[Line-1].push_back(Block); + } + void addFunctionLine(StringRef Filename, uint32_t Line, + const GCOVFunction *Function) { + if (Line > LineInfo[Filename].LastLine) + LineInfo[Filename].LastLine = Line; + LineInfo[Filename].Functions[Line-1].push_back(Function); } void setRunCount(uint32_t Runs) { RunCount = Runs; } void setProgramCount(uint32_t Programs) { ProgramCount = Programs; } - void print(raw_fd_ostream &OS, StringRef gcnoFile, StringRef gcdaFile); + void print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile); + private: - StringMap<LineCounts> LineInfo; + std::string getCoveragePath(StringRef Filename, StringRef MainFilename); + std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath); + void printFunctionSummary(raw_ostream &OS, + const FunctionVector &Funcs) const; + void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, + uint32_t LineIndex, uint32_t &BlockNo) const; + void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, + GCOVCoverage &Coverage, uint32_t &EdgeNo); + void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, + uint64_t Count) const; + + void printCoverage(const GCOVCoverage &Coverage) const; + void printFuncCoverage() const; + void printFileCoverage() const; + + const GCOVOptions &Options; + StringMap<LineData> LineInfo; uint32_t RunCount; uint32_t ProgramCount; + + typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> + FileCoverageList; + typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap; + + FileCoverageList FileCoverages; + FuncCoverageMap FuncCoverages; }; } diff --git a/contrib/llvm/include/llvm/Support/GenericDomTree.h b/contrib/llvm/include/llvm/Support/GenericDomTree.h new file mode 100644 index 0000000..876ab6e --- /dev/null +++ b/contrib/llvm/include/llvm/Support/GenericDomTree.h @@ -0,0 +1,736 @@ +//===- GenericDomTree.h - Generic dominator trees for graphs ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file defines a set of templates that efficiently compute a dominator +/// tree over a generic graph. This is used typically in LLVM for fast +/// dominance queries on the CFG, but is fully generic w.r.t. the underlying +/// graph types. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_GENERIC_DOM_TREE_H +#define LLVM_SUPPORT_GENERIC_DOM_TREE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// DominatorBase - Base class that other, more interesting dominator analyses +/// inherit from. +/// +template <class NodeT> +class DominatorBase { +protected: + std::vector<NodeT*> Roots; + const bool IsPostDominators; + inline explicit DominatorBase(bool isPostDom) : + Roots(), IsPostDominators(isPostDom) {} +public: + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector<NodeT*> &getRoots() const { return Roots; } + + /// isPostDominator - Returns true if analysis based of postdoms + /// + bool isPostDominator() const { return IsPostDominators; } +}; + + +//===----------------------------------------------------------------------===// +// DomTreeNodeBase - Dominator Tree Node +template<class NodeT> class DominatorTreeBase; +struct PostDominatorTree; + +template <class NodeT> +class DomTreeNodeBase { + NodeT *TheBB; + DomTreeNodeBase<NodeT> *IDom; + std::vector<DomTreeNodeBase<NodeT> *> Children; + mutable int DFSNumIn, DFSNumOut; + + template<class N> friend class DominatorTreeBase; + friend struct PostDominatorTree; +public: + typedef typename std::vector<DomTreeNodeBase<NodeT> *>::iterator iterator; + typedef typename std::vector<DomTreeNodeBase<NodeT> *>::const_iterator + const_iterator; + + iterator begin() { return Children.begin(); } + iterator end() { return Children.end(); } + const_iterator begin() const { return Children.begin(); } + const_iterator end() const { return Children.end(); } + + NodeT *getBlock() const { return TheBB; } + DomTreeNodeBase<NodeT> *getIDom() const { return IDom; } + const std::vector<DomTreeNodeBase<NodeT>*> &getChildren() const { + return Children; + } + + DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom) + : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) { } + + DomTreeNodeBase<NodeT> *addChild(DomTreeNodeBase<NodeT> *C) { + Children.push_back(C); + return C; + } + + size_t getNumChildren() const { + return Children.size(); + } + + void clearAllChildren() { + Children.clear(); + } + + bool compare(const DomTreeNodeBase<NodeT> *Other) const { + if (getNumChildren() != Other->getNumChildren()) + return true; + + SmallPtrSet<const NodeT *, 4> OtherChildren; + for (const_iterator I = Other->begin(), E = Other->end(); I != E; ++I) { + const NodeT *Nd = (*I)->getBlock(); + OtherChildren.insert(Nd); + } + + for (const_iterator I = begin(), E = end(); I != E; ++I) { + const NodeT *N = (*I)->getBlock(); + if (OtherChildren.count(N) == 0) + return true; + } + return false; + } + + void setIDom(DomTreeNodeBase<NodeT> *NewIDom) { + assert(IDom && "No immediate dominator?"); + if (IDom != NewIDom) { + typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I = + std::find(IDom->Children.begin(), IDom->Children.end(), this); + assert(I != IDom->Children.end() && + "Not in immediate dominator children set!"); + // I am no longer your child... + IDom->Children.erase(I); + + // Switch to new dominator + IDom = NewIDom; + IDom->Children.push_back(this); + } + } + + /// getDFSNumIn/getDFSNumOut - These are an internal implementation detail, do + /// not call them. + unsigned getDFSNumIn() const { return DFSNumIn; } + unsigned getDFSNumOut() const { return DFSNumOut; } +private: + // Return true if this node is dominated by other. Use this only if DFS info + // is valid. + bool DominatedBy(const DomTreeNodeBase<NodeT> *other) const { + return this->DFSNumIn >= other->DFSNumIn && + this->DFSNumOut <= other->DFSNumOut; + } +}; + +template<class NodeT> +inline raw_ostream &operator<<(raw_ostream &o, + const DomTreeNodeBase<NodeT> *Node) { + if (Node->getBlock()) + Node->getBlock()->printAsOperand(o, false); + else + o << " <<exit node>>"; + + o << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "}"; + + return o << "\n"; +} + +template<class NodeT> +inline void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &o, + unsigned Lev) { + o.indent(2*Lev) << "[" << Lev << "] " << N; + for (typename DomTreeNodeBase<NodeT>::const_iterator I = N->begin(), + E = N->end(); I != E; ++I) + PrintDomTree<NodeT>(*I, o, Lev+1); +} + +//===----------------------------------------------------------------------===// +/// DominatorTree - Calculate the immediate dominator tree for a function. +/// + +template<class FuncT, class N> +void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT, + FuncT& F); + +template<class NodeT> +class DominatorTreeBase : public DominatorBase<NodeT> { + bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A, + const DomTreeNodeBase<NodeT> *B) const { + assert(A != B); + assert(isReachableFromEntry(B)); + assert(isReachableFromEntry(A)); + + const DomTreeNodeBase<NodeT> *IDom; + while ((IDom = B->getIDom()) != nullptr && IDom != A && IDom != B) + B = IDom; // Walk up the tree + return IDom != nullptr; + } + +protected: + typedef DenseMap<NodeT*, DomTreeNodeBase<NodeT>*> DomTreeNodeMapType; + DomTreeNodeMapType DomTreeNodes; + DomTreeNodeBase<NodeT> *RootNode; + + mutable bool DFSInfoValid; + mutable unsigned int SlowQueries; + // Information record used during immediate dominators computation. + struct InfoRec { + unsigned DFSNum; + unsigned Parent; + unsigned Semi; + NodeT *Label; + + InfoRec() : DFSNum(0), Parent(0), Semi(0), Label(nullptr) {} + }; + + DenseMap<NodeT*, NodeT*> IDoms; + + // Vertex - Map the DFS number to the NodeT* + std::vector<NodeT*> Vertex; + + // Info - Collection of information used during the computation of idoms. + DenseMap<NodeT*, InfoRec> Info; + + void reset() { + for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(), + E = DomTreeNodes.end(); I != E; ++I) + delete I->second; + DomTreeNodes.clear(); + IDoms.clear(); + this->Roots.clear(); + Vertex.clear(); + RootNode = nullptr; + } + + // NewBB is split and now it has one successor. Update dominator tree to + // reflect this change. + template<class N, class GraphT> + void Split(DominatorTreeBase<typename GraphT::NodeType>& DT, + typename GraphT::NodeType* NewBB) { + assert(std::distance(GraphT::child_begin(NewBB), + GraphT::child_end(NewBB)) == 1 && + "NewBB should have a single successor!"); + typename GraphT::NodeType* NewBBSucc = *GraphT::child_begin(NewBB); + + std::vector<typename GraphT::NodeType*> PredBlocks; + typedef GraphTraits<Inverse<N> > InvTraits; + for (typename InvTraits::ChildIteratorType PI = + InvTraits::child_begin(NewBB), + PE = InvTraits::child_end(NewBB); PI != PE; ++PI) + PredBlocks.push_back(*PI); + + assert(!PredBlocks.empty() && "No predblocks?"); + + bool NewBBDominatesNewBBSucc = true; + for (typename InvTraits::ChildIteratorType PI = + InvTraits::child_begin(NewBBSucc), + E = InvTraits::child_end(NewBBSucc); PI != E; ++PI) { + typename InvTraits::NodeType *ND = *PI; + if (ND != NewBB && !DT.dominates(NewBBSucc, ND) && + DT.isReachableFromEntry(ND)) { + NewBBDominatesNewBBSucc = false; + break; + } + } + + // Find NewBB's immediate dominator and create new dominator tree node for + // NewBB. + NodeT *NewBBIDom = nullptr; + unsigned i = 0; + for (i = 0; i < PredBlocks.size(); ++i) + if (DT.isReachableFromEntry(PredBlocks[i])) { + NewBBIDom = PredBlocks[i]; + break; + } + + // It's possible that none of the predecessors of NewBB are reachable; + // in that case, NewBB itself is unreachable, so nothing needs to be + // changed. + if (!NewBBIDom) + return; + + for (i = i + 1; i < PredBlocks.size(); ++i) { + if (DT.isReachableFromEntry(PredBlocks[i])) + NewBBIDom = DT.findNearestCommonDominator(NewBBIDom, PredBlocks[i]); + } + + // Create the new dominator tree node... and set the idom of NewBB. + DomTreeNodeBase<NodeT> *NewBBNode = DT.addNewBlock(NewBB, NewBBIDom); + + // If NewBB strictly dominates other blocks, then it is now the immediate + // dominator of NewBBSucc. Update the dominator tree as appropriate. + if (NewBBDominatesNewBBSucc) { + DomTreeNodeBase<NodeT> *NewBBSuccNode = DT.getNode(NewBBSucc); + DT.changeImmediateDominator(NewBBSuccNode, NewBBNode); + } + } + +public: + explicit DominatorTreeBase(bool isPostDom) + : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {} + virtual ~DominatorTreeBase() { reset(); } + + /// compare - Return false if the other dominator tree base matches this + /// dominator tree base. Otherwise return true. + bool compare(const DominatorTreeBase &Other) const { + + const DomTreeNodeMapType &OtherDomTreeNodes = Other.DomTreeNodes; + if (DomTreeNodes.size() != OtherDomTreeNodes.size()) + return true; + + for (typename DomTreeNodeMapType::const_iterator + I = this->DomTreeNodes.begin(), + E = this->DomTreeNodes.end(); I != E; ++I) { + NodeT *BB = I->first; + typename DomTreeNodeMapType::const_iterator OI = OtherDomTreeNodes.find(BB); + if (OI == OtherDomTreeNodes.end()) + return true; + + DomTreeNodeBase<NodeT>* MyNd = I->second; + DomTreeNodeBase<NodeT>* OtherNd = OI->second; + + if (MyNd->compare(OtherNd)) + return true; + } + + return false; + } + + virtual void releaseMemory() { reset(); } + + /// getNode - return the (Post)DominatorTree node for the specified basic + /// block. This is the same as using operator[] on this class. + /// + inline DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const { + 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 + /// there are multiple exit nodes from a particular function. Consumers of + /// post-dominance information must be capable of dealing with this + /// possibility. + /// + DomTreeNodeBase<NodeT> *getRootNode() { return RootNode; } + const DomTreeNodeBase<NodeT> *getRootNode() const { return RootNode; } + + /// Get all nodes dominated by R, including R itself. + void getDescendants(NodeT *R, SmallVectorImpl<NodeT *> &Result) const { + Result.clear(); + const DomTreeNodeBase<NodeT> *RN = getNode(R); + if (!RN) + return; // If R is unreachable, it will not be present in the DOM tree. + SmallVector<const DomTreeNodeBase<NodeT> *, 8> WL; + WL.push_back(RN); + + while (!WL.empty()) { + const DomTreeNodeBase<NodeT> *N = WL.pop_back_val(); + Result.push_back(N->getBlock()); + WL.append(N->begin(), N->end()); + } + } + + /// properlyDominates - Returns true iff A dominates B and A != B. + /// Note that this is not a constant time operation! + /// + bool properlyDominates(const DomTreeNodeBase<NodeT> *A, + const DomTreeNodeBase<NodeT> *B) const { + if (!A || !B) + return false; + if (A == B) + return false; + return dominates(A, B); + } + + bool properlyDominates(const NodeT *A, const NodeT *B) const; + + /// isReachableFromEntry - Return true if A is dominated by the entry + /// block of the function containing it. + bool isReachableFromEntry(const NodeT* A) const { + assert(!this->isPostDominator() && + "This is not implemented for post dominators"); + return isReachableFromEntry(getNode(const_cast<NodeT *>(A))); + } + + inline bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const { + return A; + } + + /// dominates - Returns true iff A dominates B. Note that this is not a + /// constant time operation! + /// + inline bool dominates(const DomTreeNodeBase<NodeT> *A, + const DomTreeNodeBase<NodeT> *B) const { + // A node trivially dominates itself. + if (B == A) + return true; + + // An unreachable node is dominated by anything. + if (!isReachableFromEntry(B)) + return true; + + // And dominates nothing. + if (!isReachableFromEntry(A)) + return false; + + // Compare the result of the tree walk and the dfs numbers, if expensive + // checks are enabled. +#ifdef XDEBUG + assert((!DFSInfoValid || + (dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) && + "Tree walk disagrees with dfs numbers!"); +#endif + + if (DFSInfoValid) + return B->DominatedBy(A); + + // If we end up with too many slow queries, just update the + // DFS numbers on the theory that we are going to keep querying. + SlowQueries++; + if (SlowQueries > 32) { + updateDFSNumbers(); + return B->DominatedBy(A); + } + + return dominatedBySlowTreeWalk(A, B); + } + + bool dominates(const NodeT *A, const NodeT *B) const; + + NodeT *getRoot() const { + assert(this->Roots.size() == 1 && "Should always have entry node!"); + return this->Roots[0]; + } + + /// findNearestCommonDominator - Find nearest common dominator basic block + /// for basic block A and B. If there is no such block then return NULL. + NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) { + assert(A->getParent() == B->getParent() && + "Two blocks are not in same function"); + + // If either A or B is a entry block then it is nearest common dominator + // (for forward-dominators). + if (!this->isPostDominator()) { + NodeT &Entry = A->getParent()->front(); + if (A == &Entry || B == &Entry) + return &Entry; + } + + // If B dominates A then B is nearest common dominator. + if (dominates(B, A)) + return B; + + // If A dominates B then A is nearest common dominator. + if (dominates(A, B)) + return A; + + DomTreeNodeBase<NodeT> *NodeA = getNode(A); + DomTreeNodeBase<NodeT> *NodeB = getNode(B); + + // If we have DFS info, then we can avoid all allocations by just querying + // it from each IDom. Note that because we call 'dominates' twice above, we + // expect to call through this code at most 16 times in a row without + // building valid DFS information. This is important as below is a *very* + // slow tree walk. + if (DFSInfoValid) { + DomTreeNodeBase<NodeT> *IDomA = NodeA->getIDom(); + while (IDomA) { + if (NodeB->DominatedBy(IDomA)) + return IDomA->getBlock(); + IDomA = IDomA->getIDom(); + } + return nullptr; + } + + // Collect NodeA dominators set. + SmallPtrSet<DomTreeNodeBase<NodeT>*, 16> NodeADoms; + NodeADoms.insert(NodeA); + DomTreeNodeBase<NodeT> *IDomA = NodeA->getIDom(); + while (IDomA) { + NodeADoms.insert(IDomA); + IDomA = IDomA->getIDom(); + } + + // Walk NodeB immediate dominators chain and find common dominator node. + DomTreeNodeBase<NodeT> *IDomB = NodeB->getIDom(); + while (IDomB) { + if (NodeADoms.count(IDomB) != 0) + return IDomB->getBlock(); + + IDomB = IDomB->getIDom(); + } + + return nullptr; + } + + const NodeT *findNearestCommonDominator(const NodeT *A, const NodeT *B) { + // Cast away the const qualifiers here. This is ok since + // const is re-introduced on the return type. + return findNearestCommonDominator(const_cast<NodeT *>(A), + const_cast<NodeT *>(B)); + } + + //===--------------------------------------------------------------------===// + // API to update (Post)DominatorTree information based on modifications to + // the CFG... + + /// addNewBlock - Add a new node to the dominator tree information. This + /// creates a new node as a child of DomBB dominator node,linking it into + /// the children list of the immediate dominator. + DomTreeNodeBase<NodeT> *addNewBlock(NodeT *BB, NodeT *DomBB) { + assert(getNode(BB) == nullptr && "Block already in dominator tree!"); + DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB); + assert(IDomNode && "Not immediate dominator specified for block!"); + DFSInfoValid = false; + return DomTreeNodes[BB] = + IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode)); + } + + /// changeImmediateDominator - This method is used to update the dominator + /// tree information when a node's immediate dominator changes. + /// + void changeImmediateDominator(DomTreeNodeBase<NodeT> *N, + DomTreeNodeBase<NodeT> *NewIDom) { + assert(N && NewIDom && "Cannot change null node pointers!"); + DFSInfoValid = false; + N->setIDom(NewIDom); + } + + void changeImmediateDominator(NodeT *BB, NodeT *NewBB) { + changeImmediateDominator(getNode(BB), getNode(NewBB)); + } + + /// eraseNode - Removes a node from the dominator tree. Block must not + /// dominate any other blocks. Removes node from its immediate dominator's + /// children list. Deletes dominator node associated with basic block BB. + void eraseNode(NodeT *BB) { + DomTreeNodeBase<NodeT> *Node = getNode(BB); + assert(Node && "Removing node that isn't in dominator tree."); + assert(Node->getChildren().empty() && "Node is not a leaf node."); + + // Remove node from immediate dominator's children list. + DomTreeNodeBase<NodeT> *IDom = Node->getIDom(); + if (IDom) { + typename std::vector<DomTreeNodeBase<NodeT>*>::iterator I = + std::find(IDom->Children.begin(), IDom->Children.end(), Node); + assert(I != IDom->Children.end() && + "Not in immediate dominator children set!"); + // I am no longer your child... + IDom->Children.erase(I); + } + + DomTreeNodes.erase(BB); + delete Node; + } + + /// removeNode - Removes a node from the dominator tree. Block must not + /// dominate any other blocks. Invalidates any node pointing to removed + /// block. + void removeNode(NodeT *BB) { + assert(getNode(BB) && "Removing node that isn't in dominator tree."); + DomTreeNodes.erase(BB); + } + + /// splitBlock - BB is split and now it has one successor. Update dominator + /// tree to reflect this change. + void splitBlock(NodeT* NewBB) { + if (this->IsPostDominators) + this->Split<Inverse<NodeT*>, GraphTraits<Inverse<NodeT*> > >(*this, NewBB); + else + this->Split<NodeT*, GraphTraits<NodeT*> >(*this, NewBB); + } + + /// print - Convert to human readable form + /// + void print(raw_ostream &o) const { + o << "=============================--------------------------------\n"; + if (this->isPostDominator()) + o << "Inorder PostDominator Tree: "; + else + o << "Inorder Dominator Tree: "; + if (!this->DFSInfoValid) + o << "DFSNumbers invalid: " << SlowQueries << " slow queries."; + o << "\n"; + + // The postdom tree can have a null root if there are no returns. + if (getRootNode()) + PrintDomTree<NodeT>(getRootNode(), o, 1); + } + +protected: + template<class GraphT> + friend typename GraphT::NodeType* Eval( + DominatorTreeBase<typename GraphT::NodeType>& DT, + typename GraphT::NodeType* V, + unsigned LastLinked); + + template<class GraphT> + friend unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, + typename GraphT::NodeType* V, + unsigned N); + + template<class FuncT, class N> + friend void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType>& DT, + FuncT& F); + + /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking + /// dominator tree in dfs order. + void updateDFSNumbers() const { + unsigned DFSNum = 0; + + SmallVector<std::pair<const DomTreeNodeBase<NodeT>*, + typename DomTreeNodeBase<NodeT>::const_iterator>, 32> WorkStack; + + const DomTreeNodeBase<NodeT> *ThisRoot = getRootNode(); + + if (!ThisRoot) + return; + + // Even in the case of multiple exits that form the post dominator root + // nodes, do not iterate over all exits, but start from the virtual root + // node. Otherwise bbs, that are not post dominated by any exit but by the + // virtual root node, will never be assigned a DFS number. + WorkStack.push_back(std::make_pair(ThisRoot, ThisRoot->begin())); + ThisRoot->DFSNumIn = DFSNum++; + + while (!WorkStack.empty()) { + const DomTreeNodeBase<NodeT> *Node = WorkStack.back().first; + typename DomTreeNodeBase<NodeT>::const_iterator ChildIt = + WorkStack.back().second; + + // If we visited all of the children of this node, "recurse" back up the + // stack setting the DFOutNum. + if (ChildIt == Node->end()) { + Node->DFSNumOut = DFSNum++; + WorkStack.pop_back(); + } else { + // Otherwise, recursively visit this child. + const DomTreeNodeBase<NodeT> *Child = *ChildIt; + ++WorkStack.back().second; + + WorkStack.push_back(std::make_pair(Child, Child->begin())); + Child->DFSNumIn = DFSNum++; + } + } + + SlowQueries = 0; + DFSInfoValid = true; + } + + DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) { + if (DomTreeNodeBase<NodeT> *Node = getNode(BB)) + return Node; + + // Haven't calculated this node yet? Get or calculate the node for the + // immediate dominator. + NodeT *IDom = getIDom(BB); + + assert(IDom || this->DomTreeNodes[nullptr]); + DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom); + + // Add a new tree node for this NodeT, and link it as a child of + // IDomNode + DomTreeNodeBase<NodeT> *C = new DomTreeNodeBase<NodeT>(BB, IDomNode); + return this->DomTreeNodes[BB] = IDomNode->addChild(C); + } + + inline NodeT *getIDom(NodeT *BB) const { + return IDoms.lookup(BB); + } + + inline void addRoot(NodeT* BB) { + this->Roots.push_back(BB); + } + +public: + /// recalculate - compute a dominator tree for the given function + template<class FT> + void recalculate(FT& F) { + typedef GraphTraits<FT*> TraitsTy; + reset(); + this->Vertex.push_back(nullptr); + + if (!this->IsPostDominators) { + // Initialize root + NodeT *entry = TraitsTy::getEntryNode(&F); + this->Roots.push_back(entry); + this->IDoms[entry] = nullptr; + this->DomTreeNodes[entry] = nullptr; + + Calculate<FT, NodeT*>(*this, F); + } else { + // Initialize the roots list + for (typename TraitsTy::nodes_iterator I = TraitsTy::nodes_begin(&F), + E = TraitsTy::nodes_end(&F); I != E; ++I) { + if (TraitsTy::child_begin(I) == TraitsTy::child_end(I)) + addRoot(I); + + // Prepopulate maps so that we don't get iterator invalidation issues later. + this->IDoms[I] = nullptr; + this->DomTreeNodes[I] = nullptr; + } + + Calculate<FT, Inverse<NodeT*> >(*this, F); + } + } +}; + +// These two functions are declared out of line as a workaround for building +// with old (< r147295) versions of clang because of pr11642. +template<class NodeT> +bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) const { + if (A == B) + return true; + + // Cast away the const qualifiers here. This is ok since + // this function doesn't actually return the values returned + // from getNode. + return dominates(getNode(const_cast<NodeT *>(A)), + getNode(const_cast<NodeT *>(B))); +} +template<class NodeT> +bool +DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) const { + if (A == B) + return false; + + // Cast away the const qualifiers here. This is ok since + // this function doesn't actually return the values returned + // from getNode. + return dominates(getNode(const_cast<NodeT *>(A)), + getNode(const_cast<NodeT *>(B))); +} + +} + +#endif diff --git a/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h b/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h new file mode 100644 index 0000000..bcba5e0 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/GenericDomTreeConstruction.h @@ -0,0 +1,289 @@ +//===- GenericDomTreeConstruction.h - Dominator Calculation ------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Generic dominator tree construction - This file provides routines to +/// construct immediate dominator information for a flow-graph based on the +/// algorithm described in this document: +/// +/// A Fast Algorithm for Finding Dominators in a Flowgraph +/// T. Lengauer & R. Tarjan, ACM TOPLAS July 1979, pgs 121-141. +/// +/// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns +/// out that the theoretically slower O(n*log(n)) implementation is actually +/// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs. +/// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_SUPPORT_GENERIC_DOM_TREE_CONSTRUCTION_H +#define LLVM_SUPPORT_GENERIC_DOM_TREE_CONSTRUCTION_H + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/GenericDomTree.h" + +namespace llvm { + +template<class GraphT> +unsigned DFSPass(DominatorTreeBase<typename GraphT::NodeType>& DT, + typename GraphT::NodeType* V, unsigned N) { + // This is more understandable as a recursive algorithm, but we can't use the + // recursive algorithm due to stack depth issues. Keep it here for + // documentation purposes. +#if 0 + InfoRec &VInfo = DT.Info[DT.Roots[i]]; + VInfo.DFSNum = VInfo.Semi = ++N; + VInfo.Label = V; + + Vertex.push_back(V); // Vertex[n] = V; + + for (succ_iterator SI = succ_begin(V), E = succ_end(V); SI != E; ++SI) { + InfoRec &SuccVInfo = DT.Info[*SI]; + if (SuccVInfo.Semi == 0) { + SuccVInfo.Parent = V; + N = DTDFSPass(DT, *SI, N); + } + } +#else + bool IsChildOfArtificialExit = (N != 0); + + SmallVector<std::pair<typename GraphT::NodeType*, + typename GraphT::ChildIteratorType>, 32> Worklist; + Worklist.push_back(std::make_pair(V, GraphT::child_begin(V))); + while (!Worklist.empty()) { + typename GraphT::NodeType* BB = Worklist.back().first; + typename GraphT::ChildIteratorType NextSucc = Worklist.back().second; + + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &BBInfo = + DT.Info[BB]; + + // First time we visited this BB? + if (NextSucc == GraphT::child_begin(BB)) { + BBInfo.DFSNum = BBInfo.Semi = ++N; + BBInfo.Label = BB; + + DT.Vertex.push_back(BB); // Vertex[n] = V; + + if (IsChildOfArtificialExit) + BBInfo.Parent = 1; + + IsChildOfArtificialExit = false; + } + + // store the DFS number of the current BB - the reference to BBInfo might + // get invalidated when processing the successors. + unsigned BBDFSNum = BBInfo.DFSNum; + + // If we are done with this block, remove it from the worklist. + if (NextSucc == GraphT::child_end(BB)) { + Worklist.pop_back(); + continue; + } + + // Increment the successor number for the next time we get to it. + ++Worklist.back().second; + + // Visit the successor next, if it isn't already visited. + typename GraphT::NodeType* Succ = *NextSucc; + + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &SuccVInfo = + DT.Info[Succ]; + if (SuccVInfo.Semi == 0) { + SuccVInfo.Parent = BBDFSNum; + Worklist.push_back(std::make_pair(Succ, GraphT::child_begin(Succ))); + } + } +#endif + return N; +} + +template<class GraphT> +typename GraphT::NodeType* +Eval(DominatorTreeBase<typename GraphT::NodeType>& DT, + typename GraphT::NodeType *VIn, unsigned LastLinked) { + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInInfo = + DT.Info[VIn]; + if (VInInfo.DFSNum < LastLinked) + return VIn; + + SmallVector<typename GraphT::NodeType*, 32> Work; + SmallPtrSet<typename GraphT::NodeType*, 32> Visited; + + if (VInInfo.Parent >= LastLinked) + Work.push_back(VIn); + + while (!Work.empty()) { + typename GraphT::NodeType* V = Work.back(); + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo = + DT.Info[V]; + typename GraphT::NodeType* VAncestor = DT.Vertex[VInfo.Parent]; + + // Process Ancestor first + if (Visited.insert(VAncestor) && VInfo.Parent >= LastLinked) { + Work.push_back(VAncestor); + continue; + } + Work.pop_back(); + + // Update VInfo based on Ancestor info + if (VInfo.Parent < LastLinked) + continue; + + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VAInfo = + DT.Info[VAncestor]; + typename GraphT::NodeType* VAncestorLabel = VAInfo.Label; + typename GraphT::NodeType* VLabel = VInfo.Label; + if (DT.Info[VAncestorLabel].Semi < DT.Info[VLabel].Semi) + VInfo.Label = VAncestorLabel; + VInfo.Parent = VAInfo.Parent; + } + + return VInInfo.Label; +} + +template<class FuncT, class NodeT> +void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, + FuncT& F) { + typedef GraphTraits<NodeT> GraphT; + + unsigned N = 0; + bool MultipleRoots = (DT.Roots.size() > 1); + if (MultipleRoots) { + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &BBInfo = + DT.Info[nullptr]; + BBInfo.DFSNum = BBInfo.Semi = ++N; + BBInfo.Label = nullptr; + + DT.Vertex.push_back(nullptr); // Vertex[n] = V; + } + + // Step #1: Number blocks in depth-first order and initialize variables used + // in later stages of the algorithm. + for (unsigned i = 0, e = static_cast<unsigned>(DT.Roots.size()); + i != e; ++i) + N = DFSPass<GraphT>(DT, DT.Roots[i], N); + + // it might be that some blocks did not get a DFS number (e.g., blocks of + // infinite loops). In these cases an artificial exit node is required. + MultipleRoots |= (DT.isPostDominator() && N != GraphTraits<FuncT*>::size(&F)); + + // When naively implemented, the Lengauer-Tarjan algorithm requires a separate + // bucket for each vertex. However, this is unnecessary, because each vertex + // is only placed into a single bucket (that of its semidominator), and each + // vertex's bucket is processed before it is added to any bucket itself. + // + // Instead of using a bucket per vertex, we use a single array Buckets that + // has two purposes. Before the vertex V with preorder number i is processed, + // Buckets[i] stores the index of the first element in V's bucket. After V's + // bucket is processed, Buckets[i] stores the index of the next element in the + // bucket containing V, if any. + SmallVector<unsigned, 32> Buckets; + Buckets.resize(N + 1); + for (unsigned i = 1; i <= N; ++i) + Buckets[i] = i; + + for (unsigned i = N; i >= 2; --i) { + typename GraphT::NodeType* W = DT.Vertex[i]; + typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &WInfo = + DT.Info[W]; + + // Step #2: Implicitly define the immediate dominator of vertices + for (unsigned j = i; Buckets[j] != i; j = Buckets[j]) { + typename GraphT::NodeType* V = DT.Vertex[Buckets[j]]; + typename GraphT::NodeType* U = Eval<GraphT>(DT, V, i + 1); + DT.IDoms[V] = DT.Info[U].Semi < i ? U : W; + } + + // Step #3: Calculate the semidominators of all vertices + + // initialize the semi dominator to point to the parent node + WInfo.Semi = WInfo.Parent; + typedef GraphTraits<Inverse<NodeT> > InvTraits; + for (typename InvTraits::ChildIteratorType CI = + InvTraits::child_begin(W), + E = InvTraits::child_end(W); CI != E; ++CI) { + typename InvTraits::NodeType *N = *CI; + if (DT.Info.count(N)) { // Only if this predecessor is reachable! + unsigned SemiU = DT.Info[Eval<GraphT>(DT, N, i + 1)].Semi; + if (SemiU < WInfo.Semi) + WInfo.Semi = SemiU; + } + } + + // If V is a non-root vertex and sdom(V) = parent(V), then idom(V) is + // necessarily parent(V). In this case, set idom(V) here and avoid placing + // V into a bucket. + if (WInfo.Semi == WInfo.Parent) { + DT.IDoms[W] = DT.Vertex[WInfo.Parent]; + } else { + Buckets[i] = Buckets[WInfo.Semi]; + Buckets[WInfo.Semi] = i; + } + } + + if (N >= 1) { + typename GraphT::NodeType* Root = DT.Vertex[1]; + for (unsigned j = 1; Buckets[j] != 1; j = Buckets[j]) { + typename GraphT::NodeType* V = DT.Vertex[Buckets[j]]; + DT.IDoms[V] = Root; + } + } + + // Step #4: Explicitly define the immediate dominator of each vertex + for (unsigned i = 2; i <= N; ++i) { + typename GraphT::NodeType* W = DT.Vertex[i]; + typename GraphT::NodeType*& WIDom = DT.IDoms[W]; + if (WIDom != DT.Vertex[DT.Info[W].Semi]) + WIDom = DT.IDoms[WIDom]; + } + + if (DT.Roots.empty()) return; + + // Add a node for the root. This node might be the actual root, if there is + // one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0) + // which postdominates all real exits if there are multiple exit blocks, or + // an infinite loop. + typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : nullptr; + + DT.DomTreeNodes[Root] = DT.RootNode = + new DomTreeNodeBase<typename GraphT::NodeType>(Root, nullptr); + + // Loop over all of the reachable blocks in the function... + for (unsigned i = 2; i <= N; ++i) { + typename GraphT::NodeType* W = DT.Vertex[i]; + + DomTreeNodeBase<typename GraphT::NodeType> *BBNode = DT.DomTreeNodes[W]; + if (BBNode) continue; // Haven't calculated this node yet? + + typename GraphT::NodeType* ImmDom = DT.getIDom(W); + + assert(ImmDom || DT.DomTreeNodes[nullptr]); + + // Get or calculate the node for the immediate dominator + DomTreeNodeBase<typename GraphT::NodeType> *IDomNode = + DT.getNodeForBlock(ImmDom); + + // Add a new tree node for this BasicBlock, and link it as a child of + // IDomNode + DomTreeNodeBase<typename GraphT::NodeType> *C = + new DomTreeNodeBase<typename GraphT::NodeType>(W, IDomNode); + DT.DomTreeNodes[W] = IDomNode->addChild(C); + } + + // Free temporary memory used to construct idom's + DT.IDoms.clear(); + DT.Info.clear(); + std::vector<typename GraphT::NodeType*>().swap(DT.Vertex); + + DT.updateDFSNumbers(); +} + +} + +#endif diff --git a/contrib/llvm/include/llvm/Support/GetElementPtrTypeIterator.h b/contrib/llvm/include/llvm/Support/GetElementPtrTypeIterator.h deleted file mode 100644 index aacb531..0000000 --- a/contrib/llvm/include/llvm/Support/GetElementPtrTypeIterator.h +++ /dev/null @@ -1,113 +0,0 @@ -//===- llvm/Support/GetElementPtrTypeIterator.h -----------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements an iterator for walking through the types indexed by -// getelementptr instructions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_GETELEMENTPTRTYPEITERATOR_H -#define LLVM_SUPPORT_GETELEMENTPTRTYPEITERATOR_H - -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/User.h" - -namespace llvm { - template<typename ItTy = User::const_op_iterator> - class generic_gep_type_iterator - : public std::iterator<std::forward_iterator_tag, Type *, ptrdiff_t> { - typedef std::iterator<std::forward_iterator_tag, - Type *, ptrdiff_t> super; - - ItTy OpIt; - Type *CurTy; - generic_gep_type_iterator() {} - public: - - static generic_gep_type_iterator begin(Type *Ty, ItTy It) { - generic_gep_type_iterator I; - I.CurTy = Ty; - I.OpIt = It; - return I; - } - static generic_gep_type_iterator end(ItTy It) { - generic_gep_type_iterator I; - I.CurTy = 0; - I.OpIt = It; - return I; - } - - bool operator==(const generic_gep_type_iterator& x) const { - return OpIt == x.OpIt; - } - bool operator!=(const generic_gep_type_iterator& x) const { - return !operator==(x); - } - - Type *operator*() const { - return CurTy; - } - - Type *getIndexedType() const { - CompositeType *CT = cast<CompositeType>(CurTy); - return CT->getTypeAtIndex(getOperand()); - } - - // This is a non-standard operator->. It allows you to call methods on the - // current type directly. - Type *operator->() const { return operator*(); } - - Value *getOperand() const { return *OpIt; } - - generic_gep_type_iterator& operator++() { // Preincrement - if (CompositeType *CT = dyn_cast<CompositeType>(CurTy)) { - CurTy = CT->getTypeAtIndex(getOperand()); - } else { - CurTy = 0; - } - ++OpIt; - return *this; - } - - generic_gep_type_iterator operator++(int) { // Postincrement - generic_gep_type_iterator tmp = *this; ++*this; return tmp; - } - }; - - typedef generic_gep_type_iterator<> gep_type_iterator; - - inline gep_type_iterator gep_type_begin(const User *GEP) { - return gep_type_iterator::begin - (GEP->getOperand(0)->getType()->getScalarType(), GEP->op_begin()+1); - } - inline gep_type_iterator gep_type_end(const User *GEP) { - return gep_type_iterator::end(GEP->op_end()); - } - inline gep_type_iterator gep_type_begin(const User &GEP) { - return gep_type_iterator::begin - (GEP.getOperand(0)->getType()->getScalarType(), GEP.op_begin()+1); - } - inline gep_type_iterator gep_type_end(const User &GEP) { - return gep_type_iterator::end(GEP.op_end()); - } - - template<typename T> - inline generic_gep_type_iterator<const T *> - gep_type_begin(Type *Op0, ArrayRef<T> A) { - return generic_gep_type_iterator<const T *>::begin(Op0, A.begin()); - } - - template<typename T> - inline generic_gep_type_iterator<const T *> - gep_type_end(Type * /*Op0*/, ArrayRef<T> A) { - return generic_gep_type_iterator<const T *>::end(A.end()); - } -} // end namespace llvm - -#endif diff --git a/contrib/llvm/include/llvm/Support/GraphWriter.h b/contrib/llvm/include/llvm/Support/GraphWriter.h index 62547dd..2f02aa7 100644 --- a/contrib/llvm/include/llvm/Support/GraphWriter.h +++ b/contrib/llvm/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> @@ -259,8 +259,8 @@ public: /// emitSimpleNode - Outputs a simple (non-record) node void emitSimpleNode(const void *ID, const std::string &Attr, - const std::string &Label, unsigned NumEdgeSources = 0, - const std::vector<std::string> *EdgeSourceLabels = 0) { + const std::string &Label, unsigned NumEdgeSources = 0, + const std::vector<std::string> *EdgeSourceLabels = nullptr) { O << "\tNode" << ID << "[ "; if (!Attr.empty()) O << Attr << ","; @@ -325,7 +325,10 @@ template <typename GraphType> std::string WriteGraph(const GraphType &G, const Twine &Name, bool ShortNames = false, const Twine &Title = "") { int FD; - std::string Filename = createGraphFilename(Name, FD); + // Windows can't always handle long paths, so limit the length of the name. + std::string N = Name.str(); + N = N.substr(0, std::min<std::size_t>(N.size(), 140)); + std::string Filename = createGraphFilename(N, FD); raw_fd_ostream O(FD, /*shouldClose=*/ true); if (FD == -1) { diff --git a/contrib/llvm/include/llvm/Support/Host.h b/contrib/llvm/include/llvm/Support/Host.h index 28c4cc7..8f4bf3c 100644 --- a/contrib/llvm/include/llvm/Support/Host.h +++ b/contrib/llvm/include/llvm/Support/Host.h @@ -55,7 +55,7 @@ namespace sys { /// target which matches the host. /// /// \return - The host CPU name, or empty if the CPU could not be determined. - std::string getHostCPUName(); + StringRef getHostCPUName(); /// getHostCPUFeatures - Get the LLVM names for the host CPU features. /// The particular format of the names are target dependent, and suitable for diff --git a/contrib/llvm/include/llvm/Support/InstIterator.h b/contrib/llvm/include/llvm/Support/InstIterator.h deleted file mode 100644 index ac936a1..0000000 --- a/contrib/llvm/include/llvm/Support/InstIterator.h +++ /dev/null @@ -1,147 +0,0 @@ -//===- llvm/Support/InstIterator.h - Classes for inst iteration -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains definitions of two iterators for iterating over the -// instructions in a function. This is effectively a wrapper around a two level -// iterator that can probably be genericized later. -// -// Note that this iterator gets invalidated any time that basic blocks or -// instructions are moved around. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_INSTITERATOR_H -#define LLVM_SUPPORT_INSTITERATOR_H - -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Function.h" - -namespace llvm { - -// This class implements inst_begin() & inst_end() for -// inst_iterator and const_inst_iterator's. -// -template <class _BB_t, class _BB_i_t, class _BI_t, class _II_t> -class InstIterator { - typedef _BB_t BBty; - typedef _BB_i_t BBIty; - typedef _BI_t BIty; - typedef _II_t IIty; - _BB_t *BBs; // BasicBlocksType - _BB_i_t BB; // BasicBlocksType::iterator - _BI_t BI; // BasicBlock::iterator -public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef IIty value_type; - typedef signed difference_type; - typedef IIty* pointer; - typedef IIty& reference; - - // Default constructor - InstIterator() {} - - // Copy constructor... - template<typename A, typename B, typename C, typename D> - InstIterator(const InstIterator<A,B,C,D> &II) - : BBs(II.BBs), BB(II.BB), BI(II.BI) {} - - template<typename A, typename B, typename C, typename D> - InstIterator(InstIterator<A,B,C,D> &II) - : BBs(II.BBs), BB(II.BB), BI(II.BI) {} - - template<class M> InstIterator(M &m) - : BBs(&m.getBasicBlockList()), BB(BBs->begin()) { // begin ctor - if (BB != BBs->end()) { - BI = BB->begin(); - advanceToNextBB(); - } - } - - template<class M> InstIterator(M &m, bool) - : BBs(&m.getBasicBlockList()), BB(BBs->end()) { // end ctor - } - - // Accessors to get at the underlying iterators... - inline BBIty &getBasicBlockIterator() { return BB; } - inline BIty &getInstructionIterator() { return BI; } - - inline reference operator*() const { return *BI; } - inline pointer operator->() const { return &operator*(); } - - inline bool operator==(const InstIterator &y) const { - return BB == y.BB && (BB == BBs->end() || BI == y.BI); - } - inline bool operator!=(const InstIterator& y) const { - return !operator==(y); - } - - InstIterator& operator++() { - ++BI; - advanceToNextBB(); - return *this; - } - inline InstIterator operator++(int) { - InstIterator tmp = *this; ++*this; return tmp; - } - - InstIterator& operator--() { - while (BB == BBs->end() || BI == BB->begin()) { - --BB; - BI = BB->end(); - } - --BI; - return *this; - } - inline InstIterator operator--(int) { - InstIterator tmp = *this; --*this; return tmp; - } - - inline bool atEnd() const { return BB == BBs->end(); } - -private: - inline void advanceToNextBB() { - // The only way that the II could be broken is if it is now pointing to - // the end() of the current BasicBlock and there are successor BBs. - while (BI == BB->end()) { - ++BB; - if (BB == BBs->end()) break; - BI = BB->begin(); - } - } -}; - - -typedef InstIterator<iplist<BasicBlock>, - Function::iterator, BasicBlock::iterator, - Instruction> inst_iterator; -typedef InstIterator<const iplist<BasicBlock>, - Function::const_iterator, - BasicBlock::const_iterator, - const Instruction> const_inst_iterator; - -inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } -inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } -inline const_inst_iterator inst_begin(const Function *F) { - return const_inst_iterator(*F); -} -inline const_inst_iterator inst_end(const Function *F) { - return const_inst_iterator(*F, true); -} -inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } -inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } -inline const_inst_iterator inst_begin(const Function &F) { - return const_inst_iterator(F); -} -inline const_inst_iterator inst_end(const Function &F) { - return const_inst_iterator(F, true); -} - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Support/LEB128.h b/contrib/llvm/include/llvm/Support/LEB128.h index 3d73792..ea76c9b 100644 --- a/contrib/llvm/include/llvm/Support/LEB128.h +++ b/contrib/llvm/include/llvm/Support/LEB128.h @@ -77,7 +77,7 @@ inline unsigned encodeULEB128(uint64_t Value, uint8_t *p, /// Utility function to decode a ULEB128 value. -inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = 0) { +inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = nullptr) { const uint8_t *orig_p = p; uint64_t Value = 0; unsigned Shift = 0; @@ -90,6 +90,12 @@ inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = 0) { return Value; } +/// Utility function to get the size of the ULEB128-encoded value. +extern unsigned getULEB128Size(uint64_t Value); + +/// Utility function to get the size of the SLEB128-encoded value. +extern unsigned getSLEB128Size(int64_t Value); + } // namespace llvm #endif // LLVM_SYSTEM_LEB128_H diff --git a/contrib/llvm/include/llvm/Support/LeakDetector.h b/contrib/llvm/include/llvm/Support/LeakDetector.h deleted file mode 100644 index 501a9db..0000000 --- a/contrib/llvm/include/llvm/Support/LeakDetector.h +++ /dev/null @@ -1,92 +0,0 @@ -//===-- llvm/Support/LeakDetector.h - Provide leak detection ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a class that can be used to provide very simple memory leak -// checks for an API. Basically LLVM uses this to make sure that Instructions, -// for example, are deleted when they are supposed to be, and not leaked away. -// -// When compiling with NDEBUG (Release build), this class does nothing, thus -// adding no checking overhead to release builds. Note that this class is -// implemented in a very simple way, requiring completely manual manipulation -// and checking for garbage, but this is intentional: users should not be using -// this API, only other APIs should. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_LEAKDETECTOR_H -#define LLVM_SUPPORT_LEAKDETECTOR_H - -#include <string> - -namespace llvm { - -class LLVMContext; -class Value; - -struct LeakDetector { - /// addGarbageObject - Add a pointer to the internal set of "garbage" object - /// pointers. This should be called when objects are created, or if they are - /// taken out of an owning collection. - /// - static void addGarbageObject(void *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - - /// removeGarbageObject - Remove a pointer from our internal representation of - /// our "garbage" objects. This should be called when an object is added to - /// an "owning" collection. - /// - static void removeGarbageObject(void *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - - /// checkForGarbage - Traverse the internal representation of garbage - /// pointers. If there are any pointers that have been add'ed, but not - /// remove'd, big obnoxious warnings about memory leaks are issued. - /// - /// The specified message will be printed indicating when the check was - /// performed. - /// - static void checkForGarbage(LLVMContext &C, const std::string &Message) { -#ifndef NDEBUG - checkForGarbageImpl(C, Message); -#endif - } - - /// Overload the normal methods to work better with Value*'s because they are - /// by far the most common in LLVM. This does not affect the actual - /// functioning of this class, it just makes the warning messages nicer. - /// - static void addGarbageObject(const Value *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - static void removeGarbageObject(const Value *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - -private: - // If we are debugging, the actual implementations will be called... - static void addGarbageObjectImpl(const Value *Object); - static void removeGarbageObjectImpl(const Value *Object); - static void addGarbageObjectImpl(void *Object); - static void removeGarbageObjectImpl(void *Object); - static void checkForGarbageImpl(LLVMContext &C, const std::string &Message); -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Support/LineIterator.h b/contrib/llvm/include/llvm/Support/LineIterator.h new file mode 100644 index 0000000..2a58262 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/LineIterator.h @@ -0,0 +1,85 @@ +//===- LineIterator.h - Iterator to read a text buffer's lines --*- 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_LINEITERATOR_H__ +#define LLVM_SUPPORT_LINEITERATOR_H__ + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include <iterator> + +namespace llvm { + +class MemoryBuffer; + +/// \brief A forward iterator which reads non-blank text lines from a buffer. +/// +/// This class provides a forward iterator interface for reading one line at +/// a time from a buffer. When default constructed the iterator will be the +/// "end" iterator. +/// +/// The iterator also is aware of what line number it is currently processing +/// and can strip comment lines given the comment-starting character. +/// +/// Note that this iterator requires the buffer to be nul terminated. +class line_iterator + : public std::iterator<std::forward_iterator_tag, StringRef> { + const MemoryBuffer *Buffer; + char CommentMarker; + + unsigned LineNumber; + StringRef CurrentLine; + +public: + /// \brief Default construct an "end" iterator. + line_iterator() : Buffer(nullptr) {} + + /// \brief Construct a new iterator around some memory buffer. + explicit line_iterator(const MemoryBuffer &Buffer, char CommentMarker = '\0'); + + /// \brief Return true if we've reached EOF or are an "end" iterator. + bool is_at_eof() const { return !Buffer; } + + /// \brief Return true if we're an "end" iterator or have reached EOF. + bool is_at_end() const { return is_at_eof(); } + + /// \brief Return the current line number. May return any number at EOF. + int64_t line_number() const { return LineNumber; } + + /// \brief Advance to the next (non-empty, non-comment) line. + line_iterator &operator++() { + advance(); + return *this; + } + line_iterator operator++(int) { + line_iterator tmp(*this); + advance(); + return tmp; + } + + /// \brief Get the current line as a \c StringRef. + StringRef operator*() const { return CurrentLine; } + const StringRef *operator->() const { return &CurrentLine; } + + friend bool operator==(const line_iterator &LHS, const line_iterator &RHS) { + return LHS.Buffer == RHS.Buffer && + LHS.CurrentLine.begin() == RHS.CurrentLine.begin(); + } + + friend bool operator!=(const line_iterator &LHS, const line_iterator &RHS) { + return !(LHS == RHS); + } + +private: + /// \brief Advance the iterator to the next line. + void advance(); +}; +} + +#endif // LLVM_SUPPORT_LINEITERATOR_H__ diff --git a/contrib/llvm/include/llvm/Support/LockFileManager.h b/contrib/llvm/include/llvm/Support/LockFileManager.h index 9df8675..61c65da 100644 --- a/contrib/llvm/include/llvm/Support/LockFileManager.h +++ b/contrib/llvm/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. /// @@ -40,13 +39,23 @@ public: LFS_Error }; + /// \brief Describes the result of waiting for the owner to release the lock. + enum WaitForUnlockResult { + /// \brief The lock was released successfully. + Res_Success, + /// \brief Owner died while holding the lock. + Res_OwnerDied, + /// \brief Reached timeout while waiting for the owner to release the lock. + Res_Timeout + }; + private: SmallString<128> FileName; SmallString<128> LockFileName; 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; @@ -67,7 +76,7 @@ public: operator LockFileState() const { return getState(); } /// \brief For a shared lock, wait until the owner releases the lock. - void waitForUnlock(); + WaitForUnlockResult waitForUnlock(); }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Support/MD5.h b/contrib/llvm/include/llvm/Support/MD5.h index b2b8c2d..4eb8507 100644 --- a/contrib/llvm/include/llvm/Support/MD5.h +++ b/contrib/llvm/include/llvm/Support/MD5.h @@ -28,13 +28,12 @@ #ifndef LLVM_SYSTEM_MD5_H #define LLVM_SYSTEM_MD5_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/DataTypes.h" namespace llvm { -template <typename T> class ArrayRef; - class MD5 { // Any 32-bit or wider unsigned integer data type will do. typedef uint32_t MD5_u32plus; diff --git a/contrib/llvm/include/llvm/Support/MachO.h b/contrib/llvm/include/llvm/Support/MachO.h index 897a611..90df1f4 100644 --- a/contrib/llvm/include/llvm/Support/MachO.h +++ b/contrib/llvm/include/llvm/Support/MachO.h @@ -21,7 +21,7 @@ namespace llvm { namespace MachO { // Enums from <mach-o/loader.h> - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Constants for the "magic" field in llvm::MachO::mach_header and // llvm::MachO::mach_header_64 MH_MAGIC = 0xFEEDFACEu, @@ -76,12 +76,12 @@ namespace llvm { MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u }; - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Flags for the "cmd" field in llvm::MachO::load_command LC_REQ_DYLD = 0x80000000u }; - enum LoadCommandType LLVM_ENUM_INT_TYPE(uint32_t) { + enum LoadCommandType : uint32_t { // Constants for the "cmd" field in llvm::MachO::load_command LC_SEGMENT = 0x00000001u, LC_SYMTAB = 0x00000002u, @@ -128,10 +128,11 @@ namespace llvm { LC_SOURCE_VERSION = 0x0000002Au, LC_DYLIB_CODE_SIGN_DRS = 0x0000002Bu, // 0x0000002Cu, - LC_LINKER_OPTIONS = 0x0000002Du + LC_LINKER_OPTIONS = 0x0000002Du, + LC_LINKER_OPTIMIZATION_HINT = 0x0000002Eu }; - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Constant bits for the "flags" field in llvm::MachO::segment_command SG_HIGHVM = 0x1u, SG_FVMLIB = 0x2u, @@ -147,48 +148,100 @@ namespace llvm { SECTION_ATTRIBUTES_SYS = 0x00ffff00u // SECTION_ATTRIBUTES_SYS }; - enum SectionType { + /// These are the section type and attributes fields. A MachO section can + /// have only one Type, but can have any of the attributes specified. + enum SectionType : uint32_t { // Constant masks for the "flags[7:0]" field in llvm::MachO::section and // llvm::MachO::section_64 (mask "flags" with SECTION_TYPE) + + /// S_REGULAR - Regular section. S_REGULAR = 0x00u, + /// S_ZEROFILL - Zero fill on demand section. S_ZEROFILL = 0x01u, + /// S_CSTRING_LITERALS - Section with literal C strings. S_CSTRING_LITERALS = 0x02u, + /// S_4BYTE_LITERALS - Section with 4 byte literals. S_4BYTE_LITERALS = 0x03u, + /// S_8BYTE_LITERALS - Section with 8 byte literals. S_8BYTE_LITERALS = 0x04u, + /// S_LITERAL_POINTERS - Section with pointers to literals. S_LITERAL_POINTERS = 0x05u, + /// S_NON_LAZY_SYMBOL_POINTERS - Section with non-lazy symbol pointers. S_NON_LAZY_SYMBOL_POINTERS = 0x06u, + /// S_LAZY_SYMBOL_POINTERS - Section with lazy symbol pointers. S_LAZY_SYMBOL_POINTERS = 0x07u, + /// S_SYMBOL_STUBS - Section with symbol stubs, byte size of stub in + /// the Reserved2 field. S_SYMBOL_STUBS = 0x08u, + /// S_MOD_INIT_FUNC_POINTERS - Section with only function pointers for + /// initialization. S_MOD_INIT_FUNC_POINTERS = 0x09u, + /// S_MOD_TERM_FUNC_POINTERS - Section with only function pointers for + /// termination. S_MOD_TERM_FUNC_POINTERS = 0x0au, + /// S_COALESCED - Section contains symbols that are to be coalesced. S_COALESCED = 0x0bu, + /// S_GB_ZEROFILL - Zero fill on demand section (that can be larger than 4 + /// gigabytes). S_GB_ZEROFILL = 0x0cu, + /// S_INTERPOSING - Section with only pairs of function pointers for + /// interposing. S_INTERPOSING = 0x0du, + /// S_16BYTE_LITERALS - Section with only 16 byte literals. S_16BYTE_LITERALS = 0x0eu, + /// S_DTRACE_DOF - Section contains DTrace Object Format. S_DTRACE_DOF = 0x0fu, + /// S_LAZY_DYLIB_SYMBOL_POINTERS - Section with lazy symbol pointers to + /// lazy loaded dylibs. S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10u, + /// S_THREAD_LOCAL_REGULAR - Thread local data section. S_THREAD_LOCAL_REGULAR = 0x11u, + /// S_THREAD_LOCAL_ZEROFILL - Thread local zerofill section. S_THREAD_LOCAL_ZEROFILL = 0x12u, + /// S_THREAD_LOCAL_VARIABLES - Section with thread local variable + /// structure data. S_THREAD_LOCAL_VARIABLES = 0x13u, + /// S_THREAD_LOCAL_VARIABLE_POINTERS - Section with pointers to thread + /// local structures. S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14u, - S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15u + /// S_THREAD_LOCAL_INIT_FUNCTION_POINTERS - Section with thread local + /// variable initialization pointers to functions. + S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15u, + + LAST_KNOWN_SECTION_TYPE = S_THREAD_LOCAL_INIT_FUNCTION_POINTERS }; - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Constant masks for the "flags[31:24]" field in llvm::MachO::section and // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_USR) + + /// S_ATTR_PURE_INSTRUCTIONS - Section contains only true machine + /// instructions. S_ATTR_PURE_INSTRUCTIONS = 0x80000000u, + /// S_ATTR_NO_TOC - Section contains coalesced symbols that are not to be + /// in a ranlib table of contents. S_ATTR_NO_TOC = 0x40000000u, + /// S_ATTR_STRIP_STATIC_SYMS - Ok to strip static symbols in this section + /// in files with the MY_DYLDLINK flag. S_ATTR_STRIP_STATIC_SYMS = 0x20000000u, + /// S_ATTR_NO_DEAD_STRIP - No dead stripping. S_ATTR_NO_DEAD_STRIP = 0x10000000u, + /// S_ATTR_LIVE_SUPPORT - Blocks are live if they reference live blocks. S_ATTR_LIVE_SUPPORT = 0x08000000u, + /// S_ATTR_SELF_MODIFYING_CODE - Used with i386 code stubs written on by + /// dyld. S_ATTR_SELF_MODIFYING_CODE = 0x04000000u, + /// S_ATTR_DEBUG - A debug section. S_ATTR_DEBUG = 0x02000000u, // Constant masks for the "flags[23:8]" field in llvm::MachO::section and // llvm::MachO::section_64 (mask "flags" with SECTION_ATTRIBUTES_SYS) + + /// S_ATTR_SOME_INSTRUCTIONS - Section contains some machine instructions. S_ATTR_SOME_INSTRUCTIONS = 0x00000400u, + /// S_ATTR_EXT_RELOC - Section has external relocation entries. S_ATTR_EXT_RELOC = 0x00000200u, + /// S_ATTR_LOC_RELOC - Section has local relocation entries. S_ATTR_LOC_RELOC = 0x00000100u, // Constant masks for the value of an indirect symbol in an indirect @@ -307,22 +360,41 @@ 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 { // Constant values for the "n_type" field in llvm::MachO::nlist and - // llvm::MachO::nlist_64 when "(n_type & NlistMaskStab) != 0" + // llvm::MachO::nlist_64 when "(n_type & N_STAB) != 0" N_GSYM = 0x20u, N_FNAME = 0x22u, N_FUN = 0x24u, N_STSYM = 0x26u, N_LCSYM = 0x28u, N_BNSYM = 0x2Eu, + N_PC = 0x30u, + N_AST = 0x32u, N_OPT = 0x3Cu, N_RSYM = 0x40u, N_SLINE = 0x44u, @@ -348,7 +420,7 @@ namespace llvm { N_LENG = 0xFEu }; - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Constant values for the r_symbolnum field in an // llvm::MachO::relocation_info structure when r_extern is 0. R_ABS = 0, @@ -403,6 +475,34 @@ namespace llvm { ARM_RELOC_HALF = 8, ARM_RELOC_HALF_SECTDIFF = 9, + // Constant values for the r_type field in an ARM64 architecture + // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info + // structure. + + // For pointers. + ARM64_RELOC_UNSIGNED = 0, + // Must be followed by an ARM64_RELOC_UNSIGNED + ARM64_RELOC_SUBTRACTOR = 1, + // A B/BL instruction with 26-bit displacement. + ARM64_RELOC_BRANCH26 = 2, + // PC-rel distance to page of target. + ARM64_RELOC_PAGE21 = 3, + // Offset within page, scaled by r_length. + ARM64_RELOC_PAGEOFF12 = 4, + // PC-rel distance to page of GOT slot. + ARM64_RELOC_GOT_LOAD_PAGE21 = 5, + // Offset within page of GOT slot, scaled by r_length. + ARM64_RELOC_GOT_LOAD_PAGEOFF12 = 6, + // For pointers to GOT slots. + ARM64_RELOC_POINTER_TO_GOT = 7, + // PC-rel distance to page of TLVP slot. + ARM64_RELOC_TLVP_LOAD_PAGE21 = 8, + // Offset within page of TLVP slot, scaled by r_length. + ARM64_RELOC_TLVP_LOAD_PAGEOFF12 = 9, + // Must be followed by ARM64_RELOC_PAGE21 or ARM64_RELOC_PAGEOFF12. + ARM64_RELOC_ADDEND = 10, + + // Constant values for the r_type field in an x86_64 architecture // llvm::MachO::relocation_info or llvm::MachO::scattered_relocation_info // structure @@ -739,9 +839,10 @@ namespace llvm { }; struct version_min_command { - uint32_t cmd; - uint32_t cmdsize; - uint32_t version; + uint32_t cmd; // LC_VERSION_MIN_MACOSX or + // LC_VERSION_MIN_IPHONEOS + uint32_t cmdsize; // sizeof(struct version_min_command) + uint32_t version; // X.Y.Z is encoded in nibbles xxxx.yy.zz uint32_t reserved; }; @@ -858,6 +959,13 @@ namespace llvm { }; // Structs from <mach-o/nlist.h> + struct nlist_base { + uint32_t n_strx; + uint8_t n_type; + uint8_t n_sect; + uint16_t n_desc; + }; + struct nlist { uint32_t n_strx; uint8_t n_type; @@ -874,6 +982,206 @@ namespace llvm { uint64_t n_value; }; + + // Byte order swapping functions for MachO structs + + inline void swapStruct(mach_header &mh) { + sys::swapByteOrder(mh.magic); + sys::swapByteOrder(mh.cputype); + sys::swapByteOrder(mh.cpusubtype); + sys::swapByteOrder(mh.filetype); + sys::swapByteOrder(mh.ncmds); + sys::swapByteOrder(mh.sizeofcmds); + sys::swapByteOrder(mh.flags); + } + + inline void swapStruct(mach_header_64 &H) { + sys::swapByteOrder(H.magic); + sys::swapByteOrder(H.cputype); + sys::swapByteOrder(H.cpusubtype); + sys::swapByteOrder(H.filetype); + sys::swapByteOrder(H.ncmds); + sys::swapByteOrder(H.sizeofcmds); + sys::swapByteOrder(H.flags); + sys::swapByteOrder(H.reserved); + } + + inline void swapStruct(load_command &lc) { + sys::swapByteOrder(lc.cmd); + sys::swapByteOrder(lc.cmdsize); + } + + inline void swapStruct(symtab_command &lc) { + sys::swapByteOrder(lc.cmd); + sys::swapByteOrder(lc.cmdsize); + sys::swapByteOrder(lc.symoff); + sys::swapByteOrder(lc.nsyms); + sys::swapByteOrder(lc.stroff); + sys::swapByteOrder(lc.strsize); + } + + inline void swapStruct(segment_command_64 &seg) { + sys::swapByteOrder(seg.cmd); + sys::swapByteOrder(seg.cmdsize); + sys::swapByteOrder(seg.vmaddr); + sys::swapByteOrder(seg.vmsize); + sys::swapByteOrder(seg.fileoff); + sys::swapByteOrder(seg.filesize); + sys::swapByteOrder(seg.maxprot); + sys::swapByteOrder(seg.initprot); + sys::swapByteOrder(seg.nsects); + sys::swapByteOrder(seg.flags); + } + + inline void swapStruct(segment_command &seg) { + sys::swapByteOrder(seg.cmd); + sys::swapByteOrder(seg.cmdsize); + sys::swapByteOrder(seg.vmaddr); + sys::swapByteOrder(seg.vmsize); + sys::swapByteOrder(seg.fileoff); + sys::swapByteOrder(seg.filesize); + sys::swapByteOrder(seg.maxprot); + sys::swapByteOrder(seg.initprot); + sys::swapByteOrder(seg.nsects); + sys::swapByteOrder(seg.flags); + } + + inline void swapStruct(section_64 §) { + sys::swapByteOrder(sect.addr); + sys::swapByteOrder(sect.size); + sys::swapByteOrder(sect.offset); + sys::swapByteOrder(sect.align); + sys::swapByteOrder(sect.reloff); + sys::swapByteOrder(sect.nreloc); + sys::swapByteOrder(sect.flags); + sys::swapByteOrder(sect.reserved1); + sys::swapByteOrder(sect.reserved2); + } + + inline void swapStruct(section §) { + sys::swapByteOrder(sect.addr); + sys::swapByteOrder(sect.size); + sys::swapByteOrder(sect.offset); + sys::swapByteOrder(sect.align); + sys::swapByteOrder(sect.reloff); + sys::swapByteOrder(sect.nreloc); + sys::swapByteOrder(sect.flags); + sys::swapByteOrder(sect.reserved1); + sys::swapByteOrder(sect.reserved2); + } + + inline void swapStruct(dyld_info_command &info) { + sys::swapByteOrder(info.cmd); + sys::swapByteOrder(info.cmdsize); + sys::swapByteOrder(info.rebase_off); + sys::swapByteOrder(info.rebase_size); + sys::swapByteOrder(info.bind_off); + sys::swapByteOrder(info.bind_size); + sys::swapByteOrder(info.weak_bind_off); + sys::swapByteOrder(info.weak_bind_size); + sys::swapByteOrder(info.lazy_bind_off); + sys::swapByteOrder(info.lazy_bind_size); + sys::swapByteOrder(info.export_off); + sys::swapByteOrder(info.export_size); + } + + inline void swapStruct(dylib_command &d) { + sys::swapByteOrder(d.cmd); + sys::swapByteOrder(d.cmdsize); + sys::swapByteOrder(d.dylib.name); + sys::swapByteOrder(d.dylib.timestamp); + sys::swapByteOrder(d.dylib.current_version); + sys::swapByteOrder(d.dylib.compatibility_version); + } + + inline void swapStruct(dylinker_command &d) { + sys::swapByteOrder(d.cmd); + sys::swapByteOrder(d.cmdsize); + sys::swapByteOrder(d.name); + } + + inline void swapStruct(entry_point_command &e) { + sys::swapByteOrder(e.cmd); + sys::swapByteOrder(e.cmdsize); + sys::swapByteOrder(e.entryoff); + sys::swapByteOrder(e.stacksize); + } + + inline void swapStruct(dysymtab_command &dst) { + sys::swapByteOrder(dst.cmd); + sys::swapByteOrder(dst.cmdsize); + sys::swapByteOrder(dst.ilocalsym); + sys::swapByteOrder(dst.nlocalsym); + sys::swapByteOrder(dst.iextdefsym); + sys::swapByteOrder(dst.nextdefsym); + sys::swapByteOrder(dst.iundefsym); + sys::swapByteOrder(dst.nundefsym); + sys::swapByteOrder(dst.tocoff); + sys::swapByteOrder(dst.ntoc); + sys::swapByteOrder(dst.modtaboff); + sys::swapByteOrder(dst.nmodtab); + sys::swapByteOrder(dst.extrefsymoff); + sys::swapByteOrder(dst.nextrefsyms); + sys::swapByteOrder(dst.indirectsymoff); + sys::swapByteOrder(dst.nindirectsyms); + sys::swapByteOrder(dst.extreloff); + sys::swapByteOrder(dst.nextrel); + sys::swapByteOrder(dst.locreloff); + sys::swapByteOrder(dst.nlocrel); + } + + inline void swapStruct(any_relocation_info &reloc) { + sys::swapByteOrder(reloc.r_word0); + sys::swapByteOrder(reloc.r_word1); + } + + inline void swapStruct(nlist_base &S) { + sys::swapByteOrder(S.n_strx); + sys::swapByteOrder(S.n_desc); + } + + inline void swapStruct(nlist &sym) { + sys::swapByteOrder(sym.n_strx); + sys::swapByteOrder(sym.n_desc); + sys::swapByteOrder(sym.n_value); + } + + inline void swapStruct(nlist_64 &sym) { + sys::swapByteOrder(sym.n_strx); + sys::swapByteOrder(sym.n_desc); + sys::swapByteOrder(sym.n_value); + } + + inline void swapStruct(linkedit_data_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.dataoff); + sys::swapByteOrder(C.datasize); + } + + inline void swapStruct(linker_options_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.count); + } + + inline void swapStruct(version_min_command&C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.version); + sys::swapByteOrder(C.reserved); + } + + inline void swapStruct(data_in_code_entry &C) { + sys::swapByteOrder(C.offset); + sys::swapByteOrder(C.length); + sys::swapByteOrder(C.kind); + } + + inline void swapStruct(uint32_t &C) { + sys::swapByteOrder(C); + } + // Get/Set functions from <mach-o/nlist.h> static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) { @@ -893,7 +1201,7 @@ namespace llvm { } // Enums from <mach/machine.h> - enum LLVM_ENUM_INT_TYPE(uint32_t) { + enum : uint32_t { // Capability bits used in the definition of cpu_type. CPU_ARCH_MASK = 0xff000000, // Mask for architecture bits CPU_ARCH_ABI64 = 0x01000000 // 64 bit ABI @@ -908,15 +1216,16 @@ namespace llvm { /* CPU_TYPE_MIPS = 8, */ CPU_TYPE_MC98000 = 10, // Old Motorola PowerPC CPU_TYPE_ARM = 12, + CPU_TYPE_ARM64 = CPU_TYPE_ARM | CPU_ARCH_ABI64, CPU_TYPE_SPARC = 14, CPU_TYPE_POWERPC = 18, CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | CPU_ARCH_ABI64 }; - enum LLVM_ENUM_INT_TYPE(uint32_t) { + 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 @@ -973,7 +1282,7 @@ namespace llvm { CPU_SUBTYPE_ARM_V5TEJ = 7, CPU_SUBTYPE_ARM_XSCALE = 8, CPU_SUBTYPE_ARM_V7 = 9, - CPU_SUBTYPE_ARM_V7F = 10, + // unused ARM_V7F = 10, CPU_SUBTYPE_ARM_V7S = 11, CPU_SUBTYPE_ARM_V7K = 12, CPU_SUBTYPE_ARM_V6M = 14, @@ -981,6 +1290,10 @@ namespace llvm { CPU_SUBTYPE_ARM_V7EM = 16 }; + enum CPUSubTypeARM64 { + CPU_SUBTYPE_ARM64_ALL = 0 + }; + enum CPUSubTypeSPARC { CPU_SUBTYPE_SPARC_ALL = 0 }; diff --git a/contrib/llvm/include/llvm/Support/ManagedStatic.h b/contrib/llvm/include/llvm/Support/ManagedStatic.h index 5587618..d8fbfeb 100644 --- a/contrib/llvm/include/llvm/Support/ManagedStatic.h +++ b/contrib/llvm/include/llvm/Support/ManagedStatic.h @@ -47,7 +47,7 @@ protected: void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const; public: /// isConstructed - Return true if this object has not been created yet. - bool isConstructed() const { return Ptr != 0; } + bool isConstructed() const { return Ptr != nullptr; } void destroy() const; }; @@ -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/contrib/llvm/include/llvm/Support/MathExtras.h b/contrib/llvm/include/llvm/Support/MathExtras.h index ff41608..0abba62 100644 --- a/contrib/llvm/include/llvm/Support/MathExtras.h +++ b/contrib/llvm/include/llvm/Support/MathExtras.h @@ -16,9 +16,9 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/SwapByteOrder.h" -#include "llvm/Support/type_traits.h" - +#include <cassert> #include <cstring> +#include <type_traits> #ifdef _MSC_VER #include <intrin.h> @@ -44,8 +44,8 @@ enum ZeroBehavior { /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are /// valid arguments. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, std::size_t>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, std::size_t>::type countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { (void)ZB; @@ -71,8 +71,8 @@ countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { // Disable signed. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, std::size_t>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, std::size_t>::type countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) LLVM_DELETED_FUNCTION; #if __GNUC__ >= 4 || _MSC_VER @@ -115,8 +115,8 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are /// valid arguments. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, std::size_t>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, std::size_t>::type countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { (void)ZB; @@ -137,8 +137,8 @@ countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { // Disable signed. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, std::size_t>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, std::size_t>::type countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) LLVM_DELETED_FUNCTION; #if __GNUC__ >= 4 || _MSC_VER @@ -181,8 +181,8 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, T>::type findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits<T>::max(); @@ -192,8 +192,8 @@ findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { // Disable signed. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, T>::type findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION; /// \brief Get the index of the last set bit starting from the least @@ -204,8 +204,8 @@ findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION; /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, T>::type findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits<T>::max(); @@ -218,8 +218,8 @@ findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { // Disable signed. template <typename T> -typename enable_if_c<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, T>::type +typename std::enable_if<std::numeric_limits<T>::is_integer && + std::numeric_limits<T>::is_signed, T>::type findLastSet(T Val, ZeroBehavior ZB = ZB_Max) LLVM_DELETED_FUNCTION; /// \brief Macro compressed bit reversal table for 256 bits. @@ -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) { @@ -541,6 +550,18 @@ inline uint64_t MinAlign(uint64_t A, uint64_t B) { return (A | B) & (1 + ~(A | B)); } +/// \brief Aligns \c Ptr to \c Alignment bytes, rounding up. +/// +/// Alignment should be a power of two. This method rounds up, so +/// AlignPtr(7, 4) == 8 and AlignPtr(8, 4) == 8. +inline char *alignPtr(char *Ptr, size_t Alignment) { + assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && + "Alignment is not a power of two!"); + + return (char *)(((uintptr_t)Ptr + Alignment - 1) & + ~(uintptr_t)(Alignment - 1)); +} + /// NextPowerOf2 - Returns the next power of two (in 64-bits) /// that is strictly greater than A. Returns zero on overflow. inline uint64_t NextPowerOf2(uint64_t A) { @@ -553,6 +574,13 @@ inline uint64_t NextPowerOf2(uint64_t A) { return A + 1; } +/// Returns the power of two which is less than or equal to the given value. +/// Essentially, it is a floor operation across the domain of powers of two. +inline uint64_t PowerOf2Floor(uint64_t A) { + if (!A) return 0; + return 1ull << (63 - countLeadingZeros(A, ZB_Undefined)); +} + /// Returns the next integer (mod 2**64) that is greater than or equal to /// \p Value and is a multiple of \p Align. \p Align must be non-zero. /// diff --git a/contrib/llvm/include/llvm/Support/Memory.h b/contrib/llvm/include/llvm/Support/Memory.h index a08c796..b4305cb 100644 --- a/contrib/llvm/include/llvm/Support/Memory.h +++ b/contrib/llvm/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 { @@ -28,7 +28,7 @@ namespace sys { /// @brief Memory block abstraction. class MemoryBlock { public: - MemoryBlock() : Address(0), Size(0) { } + MemoryBlock() : Address(nullptr), Size(0) { } MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { } void *base() const { return Address; } size_t size() const { return Size; } @@ -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,14 +88,14 @@ 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 /// memory was not allocated using the allocateMappedMemory method. /// \p Block describes the memory block to be protected. /// \p Flags specifies the new protection state to be assigned to the block. - /// \p ErrMsg [out] returns a string describing any error that occured. + /// \p ErrMsg [out] returns a string describing any error that occurred. /// /// If \p Flags is MF_WRITE, the actual behavior varies /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and 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 @@ -120,7 +120,7 @@ namespace sys { /// @brief Allocate Read/Write/Execute memory. static MemoryBlock AllocateRWX(size_t NumBytes, const MemoryBlock *NearBlock, - std::string *ErrMsg = 0); + std::string *ErrMsg = nullptr); /// This method releases a block of Read/Write/Execute memory that was /// allocated with the AllocateRWX method. It should not be used to @@ -129,7 +129,7 @@ namespace sys { /// On success, this returns false, otherwise it returns true and fills /// in *ErrMsg. /// @brief Release Read/Write/Execute memory. - static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = 0); + static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = nullptr); /// InvalidateInstructionCache - Before the JIT can run a block of code @@ -140,12 +140,12 @@ namespace sys { /// setExecutable - Before the JIT can run a block of code, it has to be /// given read and executable privilege. Return true if it is already r-x /// or the system is able to change its previlege. - static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = 0); + static bool setExecutable(MemoryBlock &M, std::string *ErrMsg = nullptr); /// setWritable - When adding to a block of code, the JIT may need /// to mark a block of code as RW since the protections are on page /// boundaries, and the JIT internal allocations are not page aligned. - static bool setWritable(MemoryBlock &M, std::string *ErrMsg = 0); + static bool setWritable(MemoryBlock &M, std::string *ErrMsg = nullptr); /// setRangeExecutable - Mark the page containing a range of addresses /// as executable. diff --git a/contrib/llvm/include/llvm/Support/MemoryBuffer.h b/contrib/llvm/include/llvm/Support/MemoryBuffer.h index ff22fb6..147be47 100644 --- a/contrib/llvm/include/llvm/Support/MemoryBuffer.h +++ b/contrib/llvm/include/llvm/Support/MemoryBuffer.h @@ -14,17 +14,16 @@ #ifndef LLVM_SUPPORT_MEMORYBUFFER_H #define LLVM_SUPPORT_MEMORYBUFFER_H +#include "llvm-c/Support.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" -#include "llvm-c/Core.h" +#include "llvm/Support/ErrorOr.h" +#include <memory> +#include <system_error> namespace llvm { - -class error_code; -template<class T> class OwningPtr; - /// MemoryBuffer - This interface provides simple read-only access to a block /// of memory, and provides simple methods for reading files and standard input /// into a memory buffer. In addition to basic access to the characters in the @@ -62,27 +61,38 @@ 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. - static error_code getFile(Twine Filename, OwningPtr<MemoryBuffer> &result, - int64_t FileSize = -1, - bool RequiresNullTerminator = true); + /// 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 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. /// Since this is in the middle of a file, the buffer is not null terminated. - static error_code getOpenFileSlice(int FD, const char *Filename, - OwningPtr<MemoryBuffer> &Result, - uint64_t MapSize, int64_t Offset); + /// + /// \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 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. - static error_code getOpenFile(int FD, const char *Filename, - OwningPtr<MemoryBuffer> &Result, - uint64_t FileSize, - bool RequiresNullTerminator = true); + /// + /// \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 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. @@ -109,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(OwningPtr<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, - OwningPtr<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/contrib/llvm/include/llvm/Support/NoFolder.h b/contrib/llvm/include/llvm/Support/NoFolder.h deleted file mode 100644 index ecfbbaa..0000000 --- a/contrib/llvm/include/llvm/Support/NoFolder.h +++ /dev/null @@ -1,298 +0,0 @@ -//======-- llvm/Support/NoFolder.h - Constant folding helper -*- C++ -*-======// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the NoFolder class, a helper for IRBuilder. It provides -// IRBuilder with a set of methods for creating unfolded constants. This is -// useful for learners trying to understand how LLVM IR works, and who don't -// want details to be hidden by the constant folder. For general constant -// creation and folding, use ConstantExpr and the routines in -// llvm/Analysis/ConstantFolding.h. -// -// Note: since it is not actually possible to create unfolded constants, this -// class returns instructions rather than constants. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_NOFOLDER_H -#define LLVM_SUPPORT_NOFOLDER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Instructions.h" - -namespace llvm { - -/// NoFolder - Create "constants" (actually, instructions) with no folding. -class NoFolder { -public: - explicit NoFolder() {} - - //===--------------------------------------------------------------------===// - // Binary Operators - //===--------------------------------------------------------------------===// - - Instruction *CreateAdd(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - BinaryOperator *BO = BinaryOperator::CreateAdd(LHS, RHS); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - Instruction *CreateNSWAdd(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateNSWAdd(LHS, RHS); - } - Instruction *CreateNUWAdd(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateNUWAdd(LHS, RHS); - } - Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateFAdd(LHS, RHS); - } - Instruction *CreateSub(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - Instruction *CreateNSWSub(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateNSWSub(LHS, RHS); - } - Instruction *CreateNUWSub(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateNUWSub(LHS, RHS); - } - Instruction *CreateFSub(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateFSub(LHS, RHS); - } - Instruction *CreateMul(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - Instruction *CreateNSWMul(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateNSWMul(LHS, RHS); - } - Instruction *CreateNUWMul(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateNUWMul(LHS, RHS); - } - Instruction *CreateFMul(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateFMul(LHS, RHS); - } - Instruction *CreateUDiv(Constant *LHS, Constant *RHS, - bool isExact = false) const { - if (!isExact) - return BinaryOperator::CreateUDiv(LHS, RHS); - return BinaryOperator::CreateExactUDiv(LHS, RHS); - } - Instruction *CreateExactUDiv(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateExactUDiv(LHS, RHS); - } - Instruction *CreateSDiv(Constant *LHS, Constant *RHS, - bool isExact = false) const { - if (!isExact) - return BinaryOperator::CreateSDiv(LHS, RHS); - return BinaryOperator::CreateExactSDiv(LHS, RHS); - } - Instruction *CreateExactSDiv(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateExactSDiv(LHS, RHS); - } - Instruction *CreateFDiv(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateFDiv(LHS, RHS); - } - Instruction *CreateURem(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateURem(LHS, RHS); - } - Instruction *CreateSRem(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateSRem(LHS, RHS); - } - Instruction *CreateFRem(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateFRem(LHS, RHS); - } - Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false, - bool HasNSW = false) const { - BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - Instruction *CreateLShr(Constant *LHS, Constant *RHS, - bool isExact = false) const { - if (!isExact) - return BinaryOperator::CreateLShr(LHS, RHS); - return BinaryOperator::CreateExactLShr(LHS, RHS); - } - Instruction *CreateAShr(Constant *LHS, Constant *RHS, - bool isExact = false) const { - if (!isExact) - return BinaryOperator::CreateAShr(LHS, RHS); - return BinaryOperator::CreateExactAShr(LHS, RHS); - } - Instruction *CreateAnd(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateAnd(LHS, RHS); - } - Instruction *CreateOr(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateOr(LHS, RHS); - } - Instruction *CreateXor(Constant *LHS, Constant *RHS) const { - return BinaryOperator::CreateXor(LHS, RHS); - } - - Instruction *CreateBinOp(Instruction::BinaryOps Opc, - Constant *LHS, Constant *RHS) const { - return BinaryOperator::Create(Opc, LHS, RHS); - } - - //===--------------------------------------------------------------------===// - // Unary Operators - //===--------------------------------------------------------------------===// - - Instruction *CreateNeg(Constant *C, - bool HasNUW = false, bool HasNSW = false) const { - BinaryOperator *BO = BinaryOperator::CreateNeg(C); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - Instruction *CreateNSWNeg(Constant *C) const { - return BinaryOperator::CreateNSWNeg(C); - } - Instruction *CreateNUWNeg(Constant *C) const { - return BinaryOperator::CreateNUWNeg(C); - } - Instruction *CreateFNeg(Constant *C) const { - return BinaryOperator::CreateFNeg(C); - } - Instruction *CreateNot(Constant *C) const { - return BinaryOperator::CreateNot(C); - } - - //===--------------------------------------------------------------------===// - // Memory Instructions - //===--------------------------------------------------------------------===// - - Constant *CreateGetElementPtr(Constant *C, - ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); - } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { - // This form of the function only exists to avoid ambiguous overload - // warnings about whether to convert Idx to ArrayRef<Constant *> or - // ArrayRef<Value *>. - return ConstantExpr::getGetElementPtr(C, Idx); - } - Instruction *CreateGetElementPtr(Constant *C, - ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::Create(C, IdxList); - } - - Constant *CreateInBoundsGetElementPtr(Constant *C, - ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); - } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { - // This form of the function only exists to avoid ambiguous overload - // warnings about whether to convert Idx to ArrayRef<Constant *> or - // ArrayRef<Value *>. - return ConstantExpr::getInBoundsGetElementPtr(C, Idx); - } - Instruction *CreateInBoundsGetElementPtr(Constant *C, - ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::CreateInBounds(C, IdxList); - } - - //===--------------------------------------------------------------------===// - // Cast/Conversion Operators - //===--------------------------------------------------------------------===// - - Instruction *CreateCast(Instruction::CastOps Op, Constant *C, - Type *DestTy) const { - return CastInst::Create(Op, C, DestTy); - } - Instruction *CreatePointerCast(Constant *C, Type *DestTy) const { - return CastInst::CreatePointerCast(C, DestTy); - } - Instruction *CreateIntCast(Constant *C, Type *DestTy, - bool isSigned) const { - return CastInst::CreateIntegerCast(C, DestTy, isSigned); - } - Instruction *CreateFPCast(Constant *C, Type *DestTy) const { - return CastInst::CreateFPCast(C, DestTy); - } - - Instruction *CreateBitCast(Constant *C, Type *DestTy) const { - return CreateCast(Instruction::BitCast, C, DestTy); - } - Instruction *CreateIntToPtr(Constant *C, Type *DestTy) const { - return CreateCast(Instruction::IntToPtr, C, DestTy); - } - Instruction *CreatePtrToInt(Constant *C, Type *DestTy) const { - return CreateCast(Instruction::PtrToInt, C, DestTy); - } - Instruction *CreateZExtOrBitCast(Constant *C, Type *DestTy) const { - return CastInst::CreateZExtOrBitCast(C, DestTy); - } - Instruction *CreateSExtOrBitCast(Constant *C, Type *DestTy) const { - return CastInst::CreateSExtOrBitCast(C, DestTy); - } - - Instruction *CreateTruncOrBitCast(Constant *C, Type *DestTy) const { - return CastInst::CreateTruncOrBitCast(C, DestTy); - } - - //===--------------------------------------------------------------------===// - // Compare Instructions - //===--------------------------------------------------------------------===// - - Instruction *CreateICmp(CmpInst::Predicate P, - Constant *LHS, Constant *RHS) const { - return new ICmpInst(P, LHS, RHS); - } - Instruction *CreateFCmp(CmpInst::Predicate P, - Constant *LHS, Constant *RHS) const { - return new FCmpInst(P, LHS, RHS); - } - - //===--------------------------------------------------------------------===// - // Other Instructions - //===--------------------------------------------------------------------===// - - Instruction *CreateSelect(Constant *C, - Constant *True, Constant *False) const { - return SelectInst::Create(C, True, False); - } - - Instruction *CreateExtractElement(Constant *Vec, Constant *Idx) const { - return ExtractElementInst::Create(Vec, Idx); - } - - Instruction *CreateInsertElement(Constant *Vec, Constant *NewElt, - Constant *Idx) const { - return InsertElementInst::Create(Vec, NewElt, Idx); - } - - Instruction *CreateShuffleVector(Constant *V1, Constant *V2, - Constant *Mask) const { - return new ShuffleVectorInst(V1, V2, Mask); - } - - Instruction *CreateExtractValue(Constant *Agg, - ArrayRef<unsigned> IdxList) const { - return ExtractValueInst::Create(Agg, IdxList); - } - - Instruction *CreateInsertValue(Constant *Agg, Constant *Val, - ArrayRef<unsigned> IdxList) const { - return InsertValueInst::Create(Agg, Val, IdxList); - } -}; - -} - -#endif diff --git a/contrib/llvm/include/llvm/Support/OnDiskHashTable.h b/contrib/llvm/include/llvm/Support/OnDiskHashTable.h new file mode 100644 index 0000000..f6d43a4 --- /dev/null +++ b/contrib/llvm/include/llvm/Support/OnDiskHashTable.h @@ -0,0 +1,571 @@ +//===--- OnDiskHashTable.h - On-Disk Hash Table Implementation --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines facilities for reading and writing on-disk hash tables. +/// +//===----------------------------------------------------------------------===// +#ifndef LLVM_SUPPORT_ON_DISK_HASH_TABLE_H +#define LLVM_SUPPORT_ON_DISK_HASH_TABLE_H + +#include "llvm/Support/Allocator.h" +#include "llvm/Support/AlignOf.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdlib> + +namespace llvm { + +/// \brief Generates an on disk hash table. +/// +/// This needs an \c Info that handles storing values into the hash table's +/// payload and computes the hash for a given key. This should provide the +/// following interface: +/// +/// \code +/// class ExampleInfo { +/// public: +/// typedef ExampleKey key_type; // Must be copy constructible +/// typedef ExampleKey &key_type_ref; +/// typedef ExampleData data_type; // Must be copy constructible +/// typedef ExampleData &data_type_ref; +/// typedef uint32_t hash_value_type; // The type the hash function returns. +/// typedef uint32_t offset_type; // The type for offsets into the table. +/// +/// /// Calculate the hash for Key +/// static hash_value_type ComputeHash(key_type_ref Key); +/// /// Return the lengths, in bytes, of the given Key/Data pair. +/// static std::pair<offset_type, offset_type> +/// EmitKeyDataLength(raw_ostream &Out, key_type_ref Key, data_type_ref Data); +/// /// Write Key to Out. KeyLen is the length from EmitKeyDataLength. +/// static void EmitKey(raw_ostream &Out, key_type_ref Key, +/// offset_type KeyLen); +/// /// Write Data to Out. DataLen is the length from EmitKeyDataLength. +/// static void EmitData(raw_ostream &Out, key_type_ref Key, +/// data_type_ref Data, offset_type DataLen); +/// }; +/// \endcode +template <typename Info> class OnDiskChainedHashTableGenerator { + /// \brief A single item in the hash table. + class Item { + public: + typename Info::key_type Key; + typename Info::data_type Data; + Item *Next; + const typename Info::hash_value_type Hash; + + Item(typename Info::key_type_ref Key, typename Info::data_type_ref Data, + Info &InfoObj) + : Key(Key), Data(Data), Next(nullptr), Hash(InfoObj.ComputeHash(Key)) {} + }; + + typedef typename Info::offset_type offset_type; + offset_type NumBuckets; + offset_type NumEntries; + llvm::SpecificBumpPtrAllocator<Item> BA; + + /// \brief A linked list of values in a particular hash bucket. + class Bucket { + public: + offset_type Off; + Item *Head; + unsigned Length; + + Bucket() {} + }; + + Bucket *Buckets; + +private: + /// \brief Insert an item into the appropriate hash bucket. + void insert(Bucket *Buckets, size_t Size, Item *E) { + Bucket &B = Buckets[E->Hash & (Size - 1)]; + E->Next = B.Head; + ++B.Length; + B.Head = E; + } + + /// \brief Resize the hash table, moving the old entries into the new buckets. + void resize(size_t NewSize) { + Bucket *NewBuckets = (Bucket *)std::calloc(NewSize, sizeof(Bucket)); + // Populate NewBuckets with the old entries. + for (size_t I = 0; I < NumBuckets; ++I) + for (Item *E = Buckets[I].Head; E;) { + Item *N = E->Next; + E->Next = nullptr; + insert(NewBuckets, NewSize, E); + E = N; + } + + free(Buckets); + NumBuckets = NewSize; + Buckets = NewBuckets; + } + +public: + /// \brief Insert an entry into the table. + void insert(typename Info::key_type_ref Key, + typename Info::data_type_ref Data) { + Info InfoObj; + insert(Key, Data, InfoObj); + } + + /// \brief Insert an entry into the table. + /// + /// Uses the provided Info instead of a stack allocated one. + void insert(typename Info::key_type_ref Key, + typename Info::data_type_ref Data, Info &InfoObj) { + + ++NumEntries; + if (4 * NumEntries >= 3 * NumBuckets) + resize(NumBuckets * 2); + insert(Buckets, NumBuckets, new (BA.Allocate()) Item(Key, Data, InfoObj)); + } + + /// \brief Emit the table to Out, which must not be at offset 0. + offset_type Emit(raw_ostream &Out) { + Info InfoObj; + return Emit(Out, InfoObj); + } + + /// \brief Emit the table to Out, which must not be at offset 0. + /// + /// Uses the provided Info instead of a stack allocated one. + offset_type Emit(raw_ostream &Out, Info &InfoObj) { + using namespace llvm::support; + endian::Writer<little> LE(Out); + + // Emit the payload of the table. + for (offset_type I = 0; I < NumBuckets; ++I) { + Bucket &B = Buckets[I]; + if (!B.Head) + continue; + + // Store the offset for the data of this bucket. + B.Off = Out.tell(); + assert(B.Off && "Cannot write a bucket at offset 0. Please add padding."); + + // Write out the number of items in the bucket. + LE.write<uint16_t>(B.Length); + assert(B.Length != 0 && "Bucket has a head but zero length?"); + + // Write out the entries in the bucket. + for (Item *I = B.Head; I; I = I->Next) { + LE.write<typename Info::hash_value_type>(I->Hash); + const std::pair<offset_type, offset_type> &Len = + InfoObj.EmitKeyDataLength(Out, I->Key, I->Data); + InfoObj.EmitKey(Out, I->Key, Len.first); + InfoObj.EmitData(Out, I->Key, I->Data, Len.second); + } + } + + // Pad with zeros so that we can start the hashtable at an aligned address. + offset_type TableOff = Out.tell(); + uint64_t N = llvm::OffsetToAlignment(TableOff, alignOf<offset_type>()); + TableOff += N; + while (N--) + LE.write<uint8_t>(0); + + // Emit the hashtable itself. + LE.write<offset_type>(NumBuckets); + LE.write<offset_type>(NumEntries); + for (offset_type I = 0; I < NumBuckets; ++I) + LE.write<offset_type>(Buckets[I].Off); + + return TableOff; + } + + OnDiskChainedHashTableGenerator() { + NumEntries = 0; + NumBuckets = 64; + // Note that we do not need to run the constructors of the individual + // Bucket objects since 'calloc' returns bytes that are all 0. + Buckets = (Bucket *)std::calloc(NumBuckets, sizeof(Bucket)); + } + + ~OnDiskChainedHashTableGenerator() { std::free(Buckets); } +}; + +/// \brief Provides lookup on an on disk hash table. +/// +/// This needs an \c Info that handles reading values from the hash table's +/// payload and computes the hash for a given key. This should provide the +/// following interface: +/// +/// \code +/// class ExampleLookupInfo { +/// public: +/// typedef ExampleData data_type; +/// typedef ExampleInternalKey internal_key_type; // The stored key type. +/// typedef ExampleKey external_key_type; // The type to pass to find(). +/// typedef uint32_t hash_value_type; // The type the hash function returns. +/// typedef uint32_t offset_type; // The type for offsets into the table. +/// +/// /// Compare two keys for equality. +/// static bool EqualKey(internal_key_type &Key1, internal_key_type &Key2); +/// /// Calculate the hash for the given key. +/// static hash_value_type ComputeHash(internal_key_type &IKey); +/// /// Translate from the semantic type of a key in the hash table to the +/// /// type that is actually stored and used for hashing and comparisons. +/// /// The internal and external types are often the same, in which case this +/// /// can simply return the passed in value. +/// static const internal_key_type &GetInternalKey(external_key_type &EKey); +/// /// Read the key and data length from Buffer, leaving it pointing at the +/// /// following byte. +/// static std::pair<offset_type, offset_type> +/// ReadKeyDataLength(const unsigned char *&Buffer); +/// /// Read the key from Buffer, given the KeyLen as reported from +/// /// ReadKeyDataLength. +/// const internal_key_type &ReadKey(const unsigned char *Buffer, +/// offset_type KeyLen); +/// /// Read the data for Key from Buffer, given the DataLen as reported from +/// /// ReadKeyDataLength. +/// data_type ReadData(StringRef Key, const unsigned char *Buffer, +/// offset_type DataLen); +/// }; +/// \endcode +template <typename Info> class OnDiskChainedHashTable { + const typename Info::offset_type NumBuckets; + const typename Info::offset_type NumEntries; + const unsigned char *const Buckets; + const unsigned char *const Base; + Info InfoObj; + +public: + typedef typename Info::internal_key_type internal_key_type; + typedef typename Info::external_key_type external_key_type; + typedef typename Info::data_type data_type; + typedef typename Info::hash_value_type hash_value_type; + typedef typename Info::offset_type offset_type; + + OnDiskChainedHashTable(offset_type NumBuckets, offset_type NumEntries, + const unsigned char *Buckets, + const unsigned char *Base, + const Info &InfoObj = Info()) + : NumBuckets(NumBuckets), NumEntries(NumEntries), Buckets(Buckets), + Base(Base), InfoObj(InfoObj) { + assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 && + "'buckets' must have a 4-byte alignment"); + } + + offset_type getNumBuckets() const { return NumBuckets; } + offset_type getNumEntries() const { return NumEntries; } + const unsigned char *getBase() const { return Base; } + const unsigned char *getBuckets() const { return Buckets; } + + bool isEmpty() const { return NumEntries == 0; } + + class iterator { + internal_key_type Key; + const unsigned char *const Data; + const offset_type Len; + Info *InfoObj; + + public: + iterator() : Data(nullptr), Len(0) {} + iterator(const internal_key_type K, const unsigned char *D, offset_type L, + Info *InfoObj) + : Key(K), Data(D), Len(L), InfoObj(InfoObj) {} + + data_type operator*() const { return InfoObj->ReadData(Key, Data, Len); } + bool operator==(const iterator &X) const { return X.Data == Data; } + bool operator!=(const iterator &X) const { return X.Data != Data; } + }; + + /// \brief Look up the stored data for a particular key. + iterator find(const external_key_type &EKey, Info *InfoPtr = 0) { + if (!InfoPtr) + InfoPtr = &InfoObj; + + using namespace llvm::support; + const internal_key_type &IKey = InfoObj.GetInternalKey(EKey); + hash_value_type KeyHash = InfoObj.ComputeHash(IKey); + + // Each bucket is just an offset into the hash table file. + offset_type Idx = KeyHash & (NumBuckets - 1); + const unsigned char *Bucket = Buckets + sizeof(offset_type) * Idx; + + offset_type Offset = endian::readNext<offset_type, little, aligned>(Bucket); + if (Offset == 0) + return iterator(); // Empty bucket. + const unsigned char *Items = Base + Offset; + + // 'Items' starts with a 16-bit unsigned integer representing the + // number of items in this bucket. + unsigned Len = endian::readNext<uint16_t, little, unaligned>(Items); + + for (unsigned i = 0; i < Len; ++i) { + // Read the hash. + hash_value_type ItemHash = + endian::readNext<hash_value_type, little, unaligned>(Items); + + // Determine the length of the key and the data. + const std::pair<offset_type, offset_type> &L = + Info::ReadKeyDataLength(Items); + offset_type ItemLen = L.first + L.second; + + // Compare the hashes. If they are not the same, skip the entry entirely. + if (ItemHash != KeyHash) { + Items += ItemLen; + continue; + } + + // Read the key. + const internal_key_type &X = + InfoPtr->ReadKey((const unsigned char *const)Items, L.first); + + // If the key doesn't match just skip reading the value. + if (!InfoPtr->EqualKey(X, IKey)) { + Items += ItemLen; + continue; + } + + // The key matches! + return iterator(X, Items + L.first, L.second, InfoPtr); + } + + return iterator(); + } + + iterator end() const { return iterator(); } + + Info &getInfoObj() { return InfoObj; } + + /// \brief Create the hash table. + /// + /// \param Buckets is the beginning of the hash table itself, which follows + /// the payload of entire structure. This is the value returned by + /// OnDiskHashTableGenerator::Emit. + /// + /// \param Base is the point from which all offsets into the structure are + /// based. This is offset 0 in the stream that was used when Emitting the + /// table. + static OnDiskChainedHashTable *Create(const unsigned char *Buckets, + const unsigned char *const Base, + const Info &InfoObj = Info()) { + using namespace llvm::support; + assert(Buckets > Base); + assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 && + "buckets should be 4-byte aligned."); + + offset_type NumBuckets = + endian::readNext<offset_type, little, aligned>(Buckets); + offset_type NumEntries = + endian::readNext<offset_type, little, aligned>(Buckets); + return new OnDiskChainedHashTable<Info>(NumBuckets, NumEntries, Buckets, + Base, InfoObj); + } +}; + +/// \brief Provides lookup and iteration over an on disk hash table. +/// +/// \copydetails llvm::OnDiskChainedHashTable +template <typename Info> +class OnDiskIterableChainedHashTable : public OnDiskChainedHashTable<Info> { + const unsigned char *Payload; + +public: + typedef OnDiskChainedHashTable<Info> base_type; + typedef typename base_type::internal_key_type internal_key_type; + typedef typename base_type::external_key_type external_key_type; + typedef typename base_type::data_type data_type; + typedef typename base_type::hash_value_type hash_value_type; + typedef typename base_type::offset_type offset_type; + + OnDiskIterableChainedHashTable(offset_type NumBuckets, offset_type NumEntries, + const unsigned char *Buckets, + const unsigned char *Payload, + const unsigned char *Base, + const Info &InfoObj = Info()) + : base_type(NumBuckets, NumEntries, Buckets, Base, InfoObj), + Payload(Payload) {} + + /// \brief Iterates over all of the keys in the table. + class key_iterator { + const unsigned char *Ptr; + offset_type NumItemsInBucketLeft; + offset_type NumEntriesLeft; + Info *InfoObj; + + public: + typedef external_key_type value_type; + + key_iterator(const unsigned char *const Ptr, offset_type NumEntries, + Info *InfoObj) + : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries), + InfoObj(InfoObj) {} + key_iterator() + : Ptr(nullptr), NumItemsInBucketLeft(0), NumEntriesLeft(0), + InfoObj(0) {} + + friend bool operator==(const key_iterator &X, const key_iterator &Y) { + return X.NumEntriesLeft == Y.NumEntriesLeft; + } + friend bool operator!=(const key_iterator &X, const key_iterator &Y) { + return X.NumEntriesLeft != Y.NumEntriesLeft; + } + + key_iterator &operator++() { // Preincrement + using namespace llvm::support; + if (!NumItemsInBucketLeft) { + // 'Items' starts with a 16-bit unsigned integer representing the + // number of items in this bucket. + NumItemsInBucketLeft = + endian::readNext<uint16_t, little, unaligned>(Ptr); + } + Ptr += sizeof(hash_value_type); // Skip the hash. + // Determine the length of the key and the data. + const std::pair<offset_type, offset_type> &L = + Info::ReadKeyDataLength(Ptr); + Ptr += L.first + L.second; + assert(NumItemsInBucketLeft); + --NumItemsInBucketLeft; + assert(NumEntriesLeft); + --NumEntriesLeft; + return *this; + } + key_iterator operator++(int) { // Postincrement + key_iterator tmp = *this; ++*this; return tmp; + } + + value_type operator*() const { + const unsigned char *LocalPtr = Ptr; + if (!NumItemsInBucketLeft) + LocalPtr += 2; // number of items in bucket + LocalPtr += sizeof(hash_value_type); // Skip the hash. + + // Determine the length of the key and the data. + const std::pair<offset_type, offset_type> &L = + Info::ReadKeyDataLength(LocalPtr); + + // Read the key. + const internal_key_type &Key = InfoObj->ReadKey(LocalPtr, L.first); + return InfoObj->GetExternalKey(Key); + } + }; + + key_iterator key_begin() { + return key_iterator(Payload, this->getNumEntries(), &this->getInfoObj()); + } + key_iterator key_end() { return key_iterator(); } + + iterator_range<key_iterator> keys() { + return make_range(key_begin(), key_end()); + } + + /// \brief Iterates over all the entries in the table, returning the data. + class data_iterator { + const unsigned char *Ptr; + offset_type NumItemsInBucketLeft; + offset_type NumEntriesLeft; + Info *InfoObj; + + public: + typedef data_type value_type; + + data_iterator(const unsigned char *const Ptr, offset_type NumEntries, + Info *InfoObj) + : Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries), + InfoObj(InfoObj) {} + data_iterator() + : Ptr(nullptr), NumItemsInBucketLeft(0), NumEntriesLeft(0), + InfoObj(nullptr) {} + + bool operator==(const data_iterator &X) const { + return X.NumEntriesLeft == NumEntriesLeft; + } + bool operator!=(const data_iterator &X) const { + return X.NumEntriesLeft != NumEntriesLeft; + } + + data_iterator &operator++() { // Preincrement + using namespace llvm::support; + if (!NumItemsInBucketLeft) { + // 'Items' starts with a 16-bit unsigned integer representing the + // number of items in this bucket. + NumItemsInBucketLeft = + endian::readNext<uint16_t, little, unaligned>(Ptr); + } + Ptr += sizeof(hash_value_type); // Skip the hash. + // Determine the length of the key and the data. + const std::pair<offset_type, offset_type> &L = + Info::ReadKeyDataLength(Ptr); + Ptr += L.first + L.second; + assert(NumItemsInBucketLeft); + --NumItemsInBucketLeft; + assert(NumEntriesLeft); + --NumEntriesLeft; + return *this; + } + data_iterator operator++(int) { // Postincrement + data_iterator tmp = *this; ++*this; return tmp; + } + + value_type operator*() const { + const unsigned char *LocalPtr = Ptr; + if (!NumItemsInBucketLeft) + LocalPtr += 2; // number of items in bucket + LocalPtr += sizeof(hash_value_type); // Skip the hash. + + // Determine the length of the key and the data. + const std::pair<offset_type, offset_type> &L = + Info::ReadKeyDataLength(LocalPtr); + + // Read the key. + const internal_key_type &Key = InfoObj->ReadKey(LocalPtr, L.first); + return InfoObj->ReadData(Key, LocalPtr + L.first, L.second); + } + }; + + data_iterator data_begin() { + return data_iterator(Payload, this->getNumEntries(), &this->getInfoObj()); + } + data_iterator data_end() { return data_iterator(); } + + iterator_range<data_iterator> data() { + return make_range(data_begin(), data_end()); + } + + /// \brief Create the hash table. + /// + /// \param Buckets is the beginning of the hash table itself, which follows + /// the payload of entire structure. This is the value returned by + /// OnDiskHashTableGenerator::Emit. + /// + /// \param Payload is the beginning of the data contained in the table. This + /// is Base plus any padding or header data that was stored, ie, the offset + /// that the stream was at when calling Emit. + /// + /// \param Base is the point from which all offsets into the structure are + /// based. This is offset 0 in the stream that was used when Emitting the + /// table. + static OnDiskIterableChainedHashTable * + Create(const unsigned char *Buckets, const unsigned char *const Payload, + const unsigned char *const Base, const Info &InfoObj = Info()) { + using namespace llvm::support; + assert(Buckets > Base); + assert((reinterpret_cast<uintptr_t>(Buckets) & 0x3) == 0 && + "buckets should be 4-byte aligned."); + + offset_type NumBuckets = + endian::readNext<offset_type, little, aligned>(Buckets); + offset_type NumEntries = + endian::readNext<offset_type, little, aligned>(Buckets); + return new OnDiskIterableChainedHashTable<Info>( + NumBuckets, NumEntries, Buckets, Payload, Base, InfoObj); + } +}; + +} // end namespace llvm + +#endif // LLVM_SUPPORT_ON_DISK_HASH_TABLE_H diff --git a/contrib/llvm/include/llvm/Support/PassNameParser.h b/contrib/llvm/include/llvm/Support/PassNameParser.h deleted file mode 100644 index c0914b1..0000000 --- a/contrib/llvm/include/llvm/Support/PassNameParser.h +++ /dev/null @@ -1,136 +0,0 @@ -//===- llvm/Support/PassNameParser.h ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the PassNameParser and FilteredPassNameParser<> classes, -// which are used to add command line arguments to a utility for all of the -// passes that have been registered into the system. -// -// The PassNameParser class adds ALL passes linked into the system (that are -// creatable) as command line arguments to the tool (when instantiated with the -// appropriate command line option template). The FilteredPassNameParser<> -// template is used for the same purposes as PassNameParser, except that it only -// includes passes that have a PassType that are compatible with the filter -// (which is the template argument). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_PASSNAMEPARSER_H -#define LLVM_SUPPORT_PASSNAMEPARSER_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Pass.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include <cstring> - -namespace llvm { - -//===----------------------------------------------------------------------===// -// PassNameParser class - Make use of the pass registration mechanism to -// automatically add a command line argument to opt for each pass. -// -class PassNameParser : public PassRegistrationListener, - public cl::parser<const PassInfo*> { - cl::Option *Opt; -public: - PassNameParser() : Opt(0) {} - virtual ~PassNameParser(); - - void initialize(cl::Option &O) { - Opt = &O; - cl::parser<const PassInfo*>::initialize(O); - - // Add all of the passes to the map that got initialized before 'this' did. - enumeratePasses(); - } - - // ignorablePassImpl - Can be overriden in subclasses to refine the list of - // which passes we want to include. - // - virtual bool ignorablePassImpl(const PassInfo *P) const { return false; } - - inline bool ignorablePass(const PassInfo *P) const { - // Ignore non-selectable and non-constructible passes! Ignore - // non-optimizations. - return P->getPassArgument() == 0 || *P->getPassArgument() == 0 || - P->getNormalCtor() == 0 || ignorablePassImpl(P); - } - - // Implement the PassRegistrationListener callbacks used to populate our map - // - virtual void passRegistered(const PassInfo *P) { - if (ignorablePass(P) || !Opt) return; - if (findOption(P->getPassArgument()) != getNumOptions()) { - errs() << "Two passes with the same argument (-" - << P->getPassArgument() << ") attempted to be registered!\n"; - llvm_unreachable(0); - } - addLiteralOption(P->getPassArgument(), P, P->getPassName()); - } - virtual void passEnumerate(const PassInfo *P) { passRegistered(P); } - - // printOptionInfo - Print out information about this option. Override the - // default implementation to sort the table before we print... - virtual void printOptionInfo(const cl::Option &O, size_t GlobalWidth) const { - PassNameParser *PNP = const_cast<PassNameParser*>(this); - array_pod_sort(PNP->Values.begin(), PNP->Values.end(), ValLessThan); - cl::parser<const PassInfo*>::printOptionInfo(O, GlobalWidth); - } - -private: - // ValLessThan - Provide a sorting comparator for Values elements... - static int ValLessThan(const PassNameParser::OptionInfo *VT1, - const PassNameParser::OptionInfo *VT2) { - return std::strcmp(VT1->Name, VT2->Name); - } -}; - -///===----------------------------------------------------------------------===// -/// FilteredPassNameParser class - Make use of the pass registration -/// mechanism to automatically add a command line argument to opt for -/// each pass that satisfies a filter criteria. Filter should return -/// true for passes to be registered as command-line options. -/// -template<typename Filter> -class FilteredPassNameParser : public PassNameParser { -private: - Filter filter; - -public: - bool ignorablePassImpl(const PassInfo *P) const { return !filter(*P); } -}; - -///===----------------------------------------------------------------------===// -/// PassArgFilter - A filter for use with PassNameFilterParser that only -/// accepts a Pass whose Arg matches certain strings. -/// -/// Use like this: -/// -/// extern const char AllowedPassArgs[] = "-anders_aa -dse"; -/// -/// static cl::list< -/// const PassInfo*, -/// bool, -/// FilteredPassNameParser<PassArgFilter<AllowedPassArgs> > > -/// PassList(cl::desc("Passes available:")); -/// -/// Only the -anders_aa and -dse options will be available to the user. -/// -template<const char *Args> -class PassArgFilter { -public: - bool operator()(const PassInfo &P) const { - return(std::strstr(Args, P.getPassArgument())); - } -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Support/Path.h b/contrib/llvm/include/llvm/Support/Path.h index b2afe1b..cf821f0 100644 --- a/contrib/llvm/include/llvm/Support/Path.h +++ b/contrib/llvm/include/llvm/Support/Path.h @@ -295,6 +295,11 @@ const StringRef extension(StringRef path); /// @result true if \a value is a path separator character on the host OS bool is_separator(char value); +/// @brief Return the preferred separator for this platform. +/// +/// @result StringRef of the preferred separator, null-terminated. +const StringRef get_separator(); + /// @brief Get the typical temporary directory for the system, e.g., /// "/var/tmp" or "C:/TEMP" /// @@ -306,6 +311,12 @@ bool is_separator(char value); /// @param result Holds the resulting path name. void system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result); +/// @brief Get the user's home directory. +/// +/// @param result Holds the resulting path name. +/// @result True if a home directory is set, false otherwise. +bool home_directory(SmallVectorImpl<char> &result); + /// @brief Has root name? /// /// root_name != "" diff --git a/contrib/llvm/include/llvm/Support/PatternMatch.h b/contrib/llvm/include/llvm/Support/PatternMatch.h deleted file mode 100644 index 240bb81..0000000 --- a/contrib/llvm/include/llvm/Support/PatternMatch.h +++ /dev/null @@ -1,1121 +0,0 @@ -//===-- llvm/Support/PatternMatch.h - Match on the LLVM IR ------*- 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 a simple and efficient mechanism for performing general -// tree-based pattern matches on the LLVM IR. The power of these routines is -// that it allows you to write concise patterns that are expressive and easy to -// understand. The other major advantage of this is that it allows you to -// trivially capture/bind elements in the pattern to variables. For example, -// you can do something like this: -// -// Value *Exp = ... -// Value *X, *Y; ConstantInt *C1, *C2; // (X & C1) | (Y & C2) -// if (match(Exp, m_Or(m_And(m_Value(X), m_ConstantInt(C1)), -// m_And(m_Value(Y), m_ConstantInt(C2))))) { -// ... Pattern is matched and variables are bound ... -// } -// -// This is primarily useful to things like the instruction combiner, but can -// also be useful for static analysis tools or code generators. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_PATTERNMATCH_H -#define LLVM_SUPPORT_PATTERNMATCH_H - -#include "llvm/IR/Constants.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Operator.h" -#include "llvm/Support/CallSite.h" - -namespace llvm { -namespace PatternMatch { - -template<typename Val, typename Pattern> -bool match(Val *V, const Pattern &P) { - return const_cast<Pattern&>(P).match(V); -} - - -template<typename SubPattern_t> -struct OneUse_match { - SubPattern_t SubPattern; - - OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} - - template<typename OpTy> - bool match(OpTy *V) { - return V->hasOneUse() && SubPattern.match(V); - } -}; - -template<typename T> -inline OneUse_match<T> m_OneUse(const T &SubPattern) { return SubPattern; } - - -template<typename Class> -struct class_match { - template<typename ITy> - bool match(ITy *V) { return isa<Class>(V); } -}; - -/// m_Value() - Match an arbitrary value and ignore it. -inline class_match<Value> m_Value() { return class_match<Value>(); } -/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. -inline class_match<ConstantInt> m_ConstantInt() { - return class_match<ConstantInt>(); -} -/// m_Undef() - Match an arbitrary undef constant. -inline class_match<UndefValue> m_Undef() { return class_match<UndefValue>(); } - -inline class_match<Constant> m_Constant() { return class_match<Constant>(); } - -/// Matching combinators -template<typename LTy, typename RTy> -struct match_combine_or { - LTy L; - RTy R; - - match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } - - template<typename ITy> - bool match(ITy *V) { - if (L.match(V)) - return true; - if (R.match(V)) - return true; - return false; - } -}; - -template<typename LTy, typename RTy> -struct match_combine_and { - LTy L; - RTy R; - - match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } - - template<typename ITy> - bool match(ITy *V) { - if (L.match(V)) - if (R.match(V)) - return true; - return false; - } -}; - -/// Combine two pattern matchers matching L || R -template<typename LTy, typename RTy> -inline match_combine_or<LTy, RTy> m_CombineOr(const LTy &L, const RTy &R) { - return match_combine_or<LTy, RTy>(L, R); -} - -/// Combine two pattern matchers matching L && R -template<typename LTy, typename RTy> -inline match_combine_and<LTy, RTy> m_CombineAnd(const LTy &L, const RTy &R) { - return match_combine_and<LTy, RTy>(L, R); -} - -struct match_zero { - template<typename ITy> - bool match(ITy *V) { - if (const Constant *C = dyn_cast<Constant>(V)) - return C->isNullValue(); - return false; - } -}; - -/// m_Zero() - Match an arbitrary zero/null constant. This includes -/// zero_initializer for vectors and ConstantPointerNull for pointers. -inline match_zero m_Zero() { return match_zero(); } - -struct match_neg_zero { - template<typename ITy> - bool match(ITy *V) { - if (const Constant *C = dyn_cast<Constant>(V)) - return C->isNegativeZeroValue(); - return false; - } -}; - -/// m_NegZero() - Match an arbitrary zero/null constant. This includes -/// zero_initializer for vectors and ConstantPointerNull for pointers. For -/// floating point constants, this will match negative zero but not positive -/// zero -inline match_neg_zero m_NegZero() { return match_neg_zero(); } - -/// m_AnyZero() - Match an arbitrary zero/null constant. This includes -/// zero_initializer for vectors and ConstantPointerNull for pointers. For -/// floating point constants, this will match negative zero and positive zero -inline match_combine_or<match_zero, match_neg_zero> m_AnyZero() { - return m_CombineOr(m_Zero(), m_NegZero()); -} - -struct apint_match { - const APInt *&Res; - apint_match(const APInt *&R) : Res(R) {} - template<typename ITy> - bool match(ITy *V) { - if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { - Res = &CI->getValue(); - return true; - } - if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast<Constant>(V)) - if (ConstantInt *CI = - dyn_cast_or_null<ConstantInt>(C->getSplatValue())) { - Res = &CI->getValue(); - return true; - } - return false; - } -}; - -/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the -/// specified pointer to the contained APInt. -inline apint_match m_APInt(const APInt *&Res) { return Res; } - - -template<int64_t Val> -struct constantint_match { - template<typename ITy> - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { - const APInt &CIV = CI->getValue(); - if (Val >= 0) - return CIV == static_cast<uint64_t>(Val); - // If Val is negative, and CI is shorter than it, truncate to the right - // number of bits. If it is larger, then we have to sign extend. Just - // compare their negated values. - return -CIV == -Val; - } - return false; - } -}; - -/// m_ConstantInt<int64_t> - Match a ConstantInt with a specific value. -template<int64_t Val> -inline constantint_match<Val> m_ConstantInt() { - return constantint_match<Val>(); -} - -/// cst_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate. -template<typename Predicate> -struct cst_pred_ty : public Predicate { - template<typename ITy> - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) - return this->isValue(CI->getValue()); - if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast<Constant>(V)) - if (const ConstantInt *CI = - dyn_cast_or_null<ConstantInt>(C->getSplatValue())) - return this->isValue(CI->getValue()); - return false; - } -}; - -/// api_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate, and bind them to an APInt. -template<typename Predicate> -struct api_pred_ty : public Predicate { - const APInt *&Res; - api_pred_ty(const APInt *&R) : Res(R) {} - template<typename ITy> - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) - if (this->isValue(CI->getValue())) { - Res = &CI->getValue(); - return true; - } - if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast<Constant>(V)) - if (ConstantInt *CI = dyn_cast_or_null<ConstantInt>(C->getSplatValue())) - if (this->isValue(CI->getValue())) { - Res = &CI->getValue(); - return true; - } - - return false; - } -}; - - -struct is_one { - bool isValue(const APInt &C) { return C == 1; } -}; - -/// m_One() - Match an integer 1 or a vector with all elements equal to 1. -inline cst_pred_ty<is_one> m_One() { return cst_pred_ty<is_one>(); } -inline api_pred_ty<is_one> m_One(const APInt *&V) { return V; } - -struct is_all_ones { - bool isValue(const APInt &C) { return C.isAllOnesValue(); } -}; - -/// m_AllOnes() - Match an integer or vector with all bits set to true. -inline cst_pred_ty<is_all_ones> m_AllOnes() {return cst_pred_ty<is_all_ones>();} -inline api_pred_ty<is_all_ones> m_AllOnes(const APInt *&V) { return V; } - -struct is_sign_bit { - bool isValue(const APInt &C) { return C.isSignBit(); } -}; - -/// m_SignBit() - Match an integer or vector with only the sign bit(s) set. -inline cst_pred_ty<is_sign_bit> m_SignBit() {return cst_pred_ty<is_sign_bit>();} -inline api_pred_ty<is_sign_bit> m_SignBit(const APInt *&V) { return V; } - -struct is_power2 { - bool isValue(const APInt &C) { return C.isPowerOf2(); } -}; - -/// m_Power2() - Match an integer or vector power of 2. -inline cst_pred_ty<is_power2> m_Power2() { return cst_pred_ty<is_power2>(); } -inline api_pred_ty<is_power2> m_Power2(const APInt *&V) { return V; } - -template<typename Class> -struct bind_ty { - Class *&VR; - bind_ty(Class *&V) : VR(V) {} - - template<typename ITy> - bool match(ITy *V) { - if (Class *CV = dyn_cast<Class>(V)) { - VR = CV; - return true; - } - return false; - } -}; - -/// m_Value - Match a value, capturing it if we match. -inline bind_ty<Value> m_Value(Value *&V) { return V; } - -/// m_ConstantInt - Match a ConstantInt, capturing the value if we match. -inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; } - -/// m_Constant - Match a Constant, capturing the value if we match. -inline bind_ty<Constant> m_Constant(Constant *&C) { return C; } - -/// m_ConstantFP - Match a ConstantFP, capturing the value if we match. -inline bind_ty<ConstantFP> m_ConstantFP(ConstantFP *&C) { return C; } - -/// specificval_ty - Match a specified Value*. -struct specificval_ty { - const Value *Val; - specificval_ty(const Value *V) : Val(V) {} - - template<typename ITy> - bool match(ITy *V) { - return V == Val; - } -}; - -/// m_Specific - Match if we have a specific specified value. -inline specificval_ty m_Specific(const Value *V) { return V; } - -/// Match a specified floating point value or vector of all elements of that -/// value. -struct specific_fpval { - double Val; - specific_fpval(double V) : Val(V) {} - - template<typename ITy> - bool match(ITy *V) { - if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V)) - return CFP->isExactlyValue(Val); - if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast<Constant>(V)) - if (ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(C->getSplatValue())) - return CFP->isExactlyValue(Val); - return false; - } -}; - -/// Match a specific floating point value or vector with all elements equal to -/// the value. -inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } - -/// Match a float 1.0 or vector with all elements equal to 1.0. -inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } - -struct bind_const_intval_ty { - uint64_t &VR; - bind_const_intval_ty(uint64_t &V) : VR(V) {} - - template<typename ITy> - bool match(ITy *V) { - if (ConstantInt *CV = dyn_cast<ConstantInt>(V)) - if (CV->getBitWidth() <= 64) { - VR = CV->getZExtValue(); - return true; - } - return false; - } -}; - -/// m_ConstantInt - Match a ConstantInt and bind to its value. This does not -/// match ConstantInts wider than 64-bits. -inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; } - -//===----------------------------------------------------------------------===// -// Matchers for specific binary operators. -// - -template<typename LHS_t, typename RHS_t, unsigned Opcode> -struct BinaryOp_match { - LHS_t L; - RHS_t R; - - BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (V->getValueID() == Value::InstructionVal + Opcode) { - BinaryOperator *I = cast<BinaryOperator>(V); - return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); - } - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) - return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && - R.match(CE->getOperand(1)); - return false; - } -}; - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Add> -m_Add(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FAdd> -m_FAdd(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Sub> -m_Sub(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FSub> -m_FSub(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Mul> -m_Mul(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FMul> -m_FMul(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::UDiv> -m_UDiv(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::SDiv> -m_SDiv(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FDiv> -m_FDiv(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::URem> -m_URem(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::SRem> -m_SRem(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::FRem> -m_FRem(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::And> -m_And(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::And>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Or> -m_Or(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Xor> -m_Xor(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::Shl> -m_Shl(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::LShr> -m_LShr(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R); -} - -template<typename LHS, typename RHS> -inline BinaryOp_match<LHS, RHS, Instruction::AShr> -m_AShr(const LHS &L, const RHS &R) { - return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R); -} - -//===----------------------------------------------------------------------===// -// Class that matches two different binary ops. -// -template<typename LHS_t, typename RHS_t, unsigned Opc1, unsigned Opc2> -struct BinOp2_match { - LHS_t L; - RHS_t R; - - BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (V->getValueID() == Value::InstructionVal + Opc1 || - V->getValueID() == Value::InstructionVal + Opc2) { - BinaryOperator *I = cast<BinaryOperator>(V); - return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); - } - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) - return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) && - L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); - return false; - } -}; - -/// m_Shr - Matches LShr or AShr. -template<typename LHS, typename RHS> -inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr> -m_Shr(const LHS &L, const RHS &R) { - return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::AShr>(L, R); -} - -/// m_LogicalShift - Matches LShr or Shl. -template<typename LHS, typename RHS> -inline BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl> -m_LogicalShift(const LHS &L, const RHS &R) { - return BinOp2_match<LHS, RHS, Instruction::LShr, Instruction::Shl>(L, R); -} - -/// m_IDiv - Matches UDiv and SDiv. -template<typename LHS, typename RHS> -inline BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv> -m_IDiv(const LHS &L, const RHS &R) { - return BinOp2_match<LHS, RHS, Instruction::SDiv, Instruction::UDiv>(L, R); -} - -//===----------------------------------------------------------------------===// -// Class that matches exact binary ops. -// -template<typename SubPattern_t> -struct Exact_match { - SubPattern_t SubPattern; - - Exact_match(const SubPattern_t &SP) : SubPattern(SP) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (PossiblyExactOperator *PEO = dyn_cast<PossiblyExactOperator>(V)) - return PEO->isExact() && SubPattern.match(V); - return false; - } -}; - -template<typename T> -inline Exact_match<T> m_Exact(const T &SubPattern) { return SubPattern; } - -//===----------------------------------------------------------------------===// -// Matchers for CmpInst classes -// - -template<typename LHS_t, typename RHS_t, typename Class, typename PredicateTy> -struct CmpClass_match { - PredicateTy &Predicate; - LHS_t L; - RHS_t R; - - CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) - : Predicate(Pred), L(LHS), R(RHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (Class *I = dyn_cast<Class>(V)) - if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { - Predicate = I->getPredicate(); - return true; - } - return false; - } -}; - -template<typename LHS, typename RHS> -inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate> -m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match<LHS, RHS, - ICmpInst, ICmpInst::Predicate>(Pred, L, R); -} - -template<typename LHS, typename RHS> -inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate> -m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match<LHS, RHS, - FCmpInst, FCmpInst::Predicate>(Pred, L, R); -} - -//===----------------------------------------------------------------------===// -// Matchers for SelectInst classes -// - -template<typename Cond_t, typename LHS_t, typename RHS_t> -struct SelectClass_match { - Cond_t C; - LHS_t L; - RHS_t R; - - SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, - const RHS_t &RHS) - : C(Cond), L(LHS), R(RHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (SelectInst *I = dyn_cast<SelectInst>(V)) - return C.match(I->getOperand(0)) && - L.match(I->getOperand(1)) && - R.match(I->getOperand(2)); - return false; - } -}; - -template<typename Cond, typename LHS, typename RHS> -inline SelectClass_match<Cond, LHS, RHS> -m_Select(const Cond &C, const LHS &L, const RHS &R) { - return SelectClass_match<Cond, LHS, RHS>(C, L, R); -} - -/// m_SelectCst - This matches a select of two constants, e.g.: -/// m_SelectCst<-1, 0>(m_Value(V)) -template<int64_t L, int64_t R, typename Cond> -inline SelectClass_match<Cond, constantint_match<L>, constantint_match<R> > -m_SelectCst(const Cond &C) { - return m_Select(C, m_ConstantInt<L>(), m_ConstantInt<R>()); -} - - -//===----------------------------------------------------------------------===// -// Matchers for CastInst classes -// - -template<typename Op_t, unsigned Opcode> -struct CastClass_match { - Op_t Op; - - CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (Operator *O = dyn_cast<Operator>(V)) - return O->getOpcode() == Opcode && Op.match(O->getOperand(0)); - return false; - } -}; - -/// m_BitCast -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::BitCast> -m_BitCast(const OpTy &Op) { - return CastClass_match<OpTy, Instruction::BitCast>(Op); -} - -/// m_PtrToInt -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::PtrToInt> -m_PtrToInt(const OpTy &Op) { - return CastClass_match<OpTy, Instruction::PtrToInt>(Op); -} - -/// m_Trunc -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::Trunc> -m_Trunc(const OpTy &Op) { - return CastClass_match<OpTy, Instruction::Trunc>(Op); -} - -/// m_SExt -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::SExt> -m_SExt(const OpTy &Op) { - return CastClass_match<OpTy, Instruction::SExt>(Op); -} - -/// m_ZExt -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::ZExt> -m_ZExt(const OpTy &Op) { - return CastClass_match<OpTy, Instruction::ZExt>(Op); -} - -/// m_UIToFP -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::UIToFP> -m_UIToFP(const OpTy &Op) { - return CastClass_match<OpTy, Instruction::UIToFP>(Op); -} - -/// m_SIToFP -template<typename OpTy> -inline CastClass_match<OpTy, Instruction::SIToFP> -m_SIToFP(const OpTy &Op) { - return CastClass_match<OpTy, Instruction::SIToFP>(Op); -} - -//===----------------------------------------------------------------------===// -// Matchers for unary operators -// - -template<typename LHS_t> -struct not_match { - LHS_t L; - - not_match(const LHS_t &LHS) : L(LHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (Operator *O = dyn_cast<Operator>(V)) - if (O->getOpcode() == Instruction::Xor) - return matchIfNot(O->getOperand(0), O->getOperand(1)); - return false; - } -private: - bool matchIfNot(Value *LHS, Value *RHS) { - return (isa<ConstantInt>(RHS) || isa<ConstantDataVector>(RHS) || - // FIXME: Remove CV. - isa<ConstantVector>(RHS)) && - cast<Constant>(RHS)->isAllOnesValue() && - L.match(LHS); - } -}; - -template<typename LHS> -inline not_match<LHS> m_Not(const LHS &L) { return L; } - - -template<typename LHS_t> -struct neg_match { - LHS_t L; - - neg_match(const LHS_t &LHS) : L(LHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (Operator *O = dyn_cast<Operator>(V)) - if (O->getOpcode() == Instruction::Sub) - return matchIfNeg(O->getOperand(0), O->getOperand(1)); - return false; - } -private: - bool matchIfNeg(Value *LHS, Value *RHS) { - return ((isa<ConstantInt>(LHS) && cast<ConstantInt>(LHS)->isZero()) || - isa<ConstantAggregateZero>(LHS)) && - L.match(RHS); - } -}; - -/// m_Neg - Match an integer negate. -template<typename LHS> -inline neg_match<LHS> m_Neg(const LHS &L) { return L; } - - -template<typename LHS_t> -struct fneg_match { - LHS_t L; - - fneg_match(const LHS_t &LHS) : L(LHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - if (Operator *O = dyn_cast<Operator>(V)) - if (O->getOpcode() == Instruction::FSub) - return matchIfFNeg(O->getOperand(0), O->getOperand(1)); - return false; - } -private: - bool matchIfFNeg(Value *LHS, Value *RHS) { - if (ConstantFP *C = dyn_cast<ConstantFP>(LHS)) - return C->isNegativeZeroValue() && L.match(RHS); - return false; - } -}; - -/// m_FNeg - Match a floating point negate. -template<typename LHS> -inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; } - - -//===----------------------------------------------------------------------===// -// Matchers for control flow. -// - -struct br_match { - BasicBlock *&Succ; - br_match(BasicBlock *&Succ) - : Succ(Succ) { - } - - template<typename OpTy> - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast<BranchInst>(V)) - if (BI->isUnconditional()) { - Succ = BI->getSuccessor(0); - return true; - } - return false; - } -}; - -inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); } - -template<typename Cond_t> -struct brc_match { - Cond_t Cond; - BasicBlock *&T, *&F; - brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f) - : Cond(C), T(t), F(f) { - } - - template<typename OpTy> - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast<BranchInst>(V)) - if (BI->isConditional() && Cond.match(BI->getCondition())) { - T = BI->getSuccessor(0); - F = BI->getSuccessor(1); - return true; - } - return false; - } -}; - -template<typename Cond_t> -inline brc_match<Cond_t> m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) { - return brc_match<Cond_t>(C, T, F); -} - - -//===----------------------------------------------------------------------===// -// Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y). -// - -template<typename CmpInst_t, typename LHS_t, typename RHS_t, typename Pred_t> -struct MaxMin_match { - LHS_t L; - RHS_t R; - - MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) - : L(LHS), R(RHS) {} - - template<typename OpTy> - bool match(OpTy *V) { - // Look for "(x pred y) ? x : y" or "(x pred y) ? y : x". - SelectInst *SI = dyn_cast<SelectInst>(V); - if (!SI) - return false; - CmpInst_t *Cmp = dyn_cast<CmpInst_t>(SI->getCondition()); - if (!Cmp) - return false; - // At this point we have a select conditioned on a comparison. Check that - // it is the values returned by the select that are being compared. - Value *TrueVal = SI->getTrueValue(); - Value *FalseVal = SI->getFalseValue(); - Value *LHS = Cmp->getOperand(0); - Value *RHS = Cmp->getOperand(1); - if ((TrueVal != LHS || FalseVal != RHS) && - (TrueVal != RHS || FalseVal != LHS)) - return false; - typename CmpInst_t::Predicate Pred = LHS == TrueVal ? - Cmp->getPredicate() : Cmp->getSwappedPredicate(); - // Does "(x pred y) ? x : y" represent the desired max/min operation? - if (!Pred_t::match(Pred)) - return false; - // It does! Bind the operands. - return L.match(LHS) && R.match(RHS); - } -}; - -/// smax_pred_ty - Helper class for identifying signed max predicates. -struct smax_pred_ty { - static bool match(ICmpInst::Predicate Pred) { - return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE; - } -}; - -/// smin_pred_ty - Helper class for identifying signed min predicates. -struct smin_pred_ty { - static bool match(ICmpInst::Predicate Pred) { - return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE; - } -}; - -/// umax_pred_ty - Helper class for identifying unsigned max predicates. -struct umax_pred_ty { - static bool match(ICmpInst::Predicate Pred) { - return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE; - } -}; - -/// umin_pred_ty - Helper class for identifying unsigned min predicates. -struct umin_pred_ty { - static bool match(ICmpInst::Predicate Pred) { - return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE; - } -}; - -/// ofmax_pred_ty - Helper class for identifying ordered max predicates. -struct ofmax_pred_ty { - static bool match(FCmpInst::Predicate Pred) { - return Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_OGE; - } -}; - -/// ofmin_pred_ty - Helper class for identifying ordered min predicates. -struct ofmin_pred_ty { - static bool match(FCmpInst::Predicate Pred) { - return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE; - } -}; - -/// ufmax_pred_ty - Helper class for identifying unordered max predicates. -struct ufmax_pred_ty { - static bool match(FCmpInst::Predicate Pred) { - return Pred == CmpInst::FCMP_UGT || Pred == CmpInst::FCMP_UGE; - } -}; - -/// ufmin_pred_ty - Helper class for identifying unordered min predicates. -struct ufmin_pred_ty { - static bool match(FCmpInst::Predicate Pred) { - return Pred == CmpInst::FCMP_ULT || Pred == CmpInst::FCMP_ULE; - } -}; - -template<typename LHS, typename RHS> -inline MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty> -m_SMax(const LHS &L, const RHS &R) { - return MaxMin_match<ICmpInst, LHS, RHS, smax_pred_ty>(L, R); -} - -template<typename LHS, typename RHS> -inline MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty> -m_SMin(const LHS &L, const RHS &R) { - return MaxMin_match<ICmpInst, LHS, RHS, smin_pred_ty>(L, R); -} - -template<typename LHS, typename RHS> -inline MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty> -m_UMax(const LHS &L, const RHS &R) { - return MaxMin_match<ICmpInst, LHS, RHS, umax_pred_ty>(L, R); -} - -template<typename LHS, typename RHS> -inline MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty> -m_UMin(const LHS &L, const RHS &R) { - return MaxMin_match<ICmpInst, LHS, RHS, umin_pred_ty>(L, R); -} - -/// \brief Match an 'ordered' floating point maximum function. -/// Floating point has one special value 'NaN'. Therefore, there is no total -/// order. However, if we can ignore the 'NaN' value (for example, because of a -/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'maximum' -/// semantics. In the presence of 'NaN' we have to preserve the original -/// select(fcmp(ogt/ge, L, R), L, R) semantics matched by this predicate. -/// -/// max(L, R) iff L and R are not NaN -/// m_OrdFMax(L, R) = R iff L or R are NaN -template<typename LHS, typename RHS> -inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty> -m_OrdFMax(const LHS &L, const RHS &R) { - return MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty>(L, R); -} - -/// \brief Match an 'ordered' floating point minimum function. -/// Floating point has one special value 'NaN'. Therefore, there is no total -/// order. However, if we can ignore the 'NaN' value (for example, because of a -/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum' -/// semantics. In the presence of 'NaN' we have to preserve the original -/// select(fcmp(olt/le, L, R), L, R) semantics matched by this predicate. -/// -/// max(L, R) iff L and R are not NaN -/// m_OrdFMin(L, R) = R iff L or R are NaN -template<typename LHS, typename RHS> -inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> -m_OrdFMin(const LHS &L, const RHS &R) { - return MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty>(L, R); -} - -/// \brief Match an 'unordered' floating point maximum function. -/// Floating point has one special value 'NaN'. Therefore, there is no total -/// order. However, if we can ignore the 'NaN' value (for example, because of a -/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'maximum' -/// semantics. In the presence of 'NaN' we have to preserve the original -/// select(fcmp(ugt/ge, L, R), L, R) semantics matched by this predicate. -/// -/// max(L, R) iff L and R are not NaN -/// m_UnordFMin(L, R) = L iff L or R are NaN -template<typename LHS, typename RHS> -inline MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty> -m_UnordFMax(const LHS &L, const RHS &R) { - return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R); -} - -/// \brief Match an 'unordered' floating point minimum function. -/// Floating point has one special value 'NaN'. Therefore, there is no total -/// order. However, if we can ignore the 'NaN' value (for example, because of a -/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum' -/// semantics. In the presence of 'NaN' we have to preserve the original -/// select(fcmp(ult/le, L, R), L, R) semantics matched by this predicate. -/// -/// max(L, R) iff L and R are not NaN -/// m_UnordFMin(L, R) = L iff L or R are NaN -template<typename LHS, typename RHS> -inline MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty> -m_UnordFMin(const LHS &L, const RHS &R) { - return MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R); -} - -template<typename Opnd_t> -struct Argument_match { - unsigned OpI; - Opnd_t Val; - Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) { } - - template<typename OpTy> - bool match(OpTy *V) { - CallSite CS(V); - return CS.isCall() && Val.match(CS.getArgument(OpI)); - } -}; - -/// Match an argument -template<unsigned OpI, typename Opnd_t> -inline Argument_match<Opnd_t> m_Argument(const Opnd_t &Op) { - return Argument_match<Opnd_t>(OpI, Op); -} - -/// Intrinsic matchers. -struct IntrinsicID_match { - unsigned ID; - IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) { } - - template<typename OpTy> - bool match(OpTy *V) { - IntrinsicInst *II = dyn_cast<IntrinsicInst>(V); - return II && II->getIntrinsicID() == ID; - } -}; - -/// Intrinsic matches are combinations of ID matchers, and argument -/// matchers. Higher arity matcher are defined recursively in terms of and-ing -/// them with lower arity matchers. Here's some convenient typedefs for up to -/// several arguments, and more can be added as needed -template <typename T0 = void, typename T1 = void, typename T2 = void, - typename T3 = void, typename T4 = void, typename T5 = void, - typename T6 = void, typename T7 = void, typename T8 = void, - typename T9 = void, typename T10 = void> struct m_Intrinsic_Ty; -template <typename T0> -struct m_Intrinsic_Ty<T0> { - typedef match_combine_and<IntrinsicID_match, Argument_match<T0> > Ty; -}; -template <typename T0, typename T1> -struct m_Intrinsic_Ty<T0, T1> { - typedef match_combine_and<typename m_Intrinsic_Ty<T0>::Ty, - Argument_match<T1> > Ty; -}; -template <typename T0, typename T1, typename T2> -struct m_Intrinsic_Ty<T0, T1, T2> { - typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1>::Ty, - Argument_match<T2> > Ty; -}; -template <typename T0, typename T1, typename T2, typename T3> -struct m_Intrinsic_Ty<T0, T1, T2, T3> { - typedef match_combine_and<typename m_Intrinsic_Ty<T0, T1, T2>::Ty, - Argument_match<T3> > Ty; -}; - -/// Match intrinsic calls like this: -/// m_Intrinsic<Intrinsic::fabs>(m_Value(X)) -template <Intrinsic::ID IntrID> -inline IntrinsicID_match -m_Intrinsic() { return IntrinsicID_match(IntrID); } - -template<Intrinsic::ID IntrID, typename T0> -inline typename m_Intrinsic_Ty<T0>::Ty -m_Intrinsic(const T0 &Op0) { - return m_CombineAnd(m_Intrinsic<IntrID>(), m_Argument<0>(Op0)); -} - -template<Intrinsic::ID IntrID, typename T0, typename T1> -inline typename m_Intrinsic_Ty<T0, T1>::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1) { - return m_CombineAnd(m_Intrinsic<IntrID>(Op0), m_Argument<1>(Op1)); -} - -template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2> -inline typename m_Intrinsic_Ty<T0, T1, T2>::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) { - return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1), m_Argument<2>(Op2)); -} - -template<Intrinsic::ID IntrID, typename T0, typename T1, typename T2, typename T3> -inline typename m_Intrinsic_Ty<T0, T1, T2, T3>::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) { - return m_CombineAnd(m_Intrinsic<IntrID>(Op0, Op1, Op2), m_Argument<3>(Op3)); -} - -// Helper intrinsic matching specializations -template<typename Opnd0> -inline typename m_Intrinsic_Ty<Opnd0>::Ty -m_BSwap(const Opnd0 &Op0) { - return m_Intrinsic<Intrinsic::bswap>(Op0); -} - -} // end namespace PatternMatch -} // end namespace llvm - -#endif diff --git a/contrib/llvm/include/llvm/Support/PredIteratorCache.h b/contrib/llvm/include/llvm/Support/PredIteratorCache.h deleted file mode 100644 index c5fb780..0000000 --- a/contrib/llvm/include/llvm/Support/PredIteratorCache.h +++ /dev/null @@ -1,70 +0,0 @@ -//===- llvm/Support/PredIteratorCache.h - pred_iterator Cache ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PredIteratorCache class. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/CFG.h" - -#ifndef LLVM_SUPPORT_PREDITERATORCACHE_H -#define LLVM_SUPPORT_PREDITERATORCACHE_H - -namespace llvm { - - /// PredIteratorCache - This class is an extremely trivial cache for - /// predecessor iterator queries. This is useful for code that repeatedly - /// wants the predecessor list for the same blocks. - class PredIteratorCache { - /// BlockToPredsMap - Pointer to null-terminated list. - DenseMap<BasicBlock*, BasicBlock**> BlockToPredsMap; - DenseMap<BasicBlock*, unsigned> BlockToPredCountMap; - - /// Memory - This is the space that holds cached preds. - BumpPtrAllocator Memory; - public: - - /// GetPreds - Get a cached list for the null-terminated predecessor list of - /// the specified block. This can be used in a loop like this: - /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) - /// use(*PI); - /// instead of: - /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) - BasicBlock **GetPreds(BasicBlock *BB) { - BasicBlock **&Entry = BlockToPredsMap[BB]; - if (Entry) return Entry; - - SmallVector<BasicBlock*, 32> PredCache(pred_begin(BB), pred_end(BB)); - PredCache.push_back(0); // null terminator. - - BlockToPredCountMap[BB] = PredCache.size()-1; - - Entry = Memory.Allocate<BasicBlock*>(PredCache.size()); - std::copy(PredCache.begin(), PredCache.end(), Entry); - return Entry; - } - - unsigned GetNumPreds(BasicBlock *BB) { - GetPreds(BB); - return BlockToPredCountMap[BB]; - } - - /// clear - Remove all information. - void clear() { - BlockToPredsMap.clear(); - BlockToPredCountMap.clear(); - Memory.Reset(); - } - }; -} // end namespace llvm - -#endif diff --git a/contrib/llvm/include/llvm/Support/PrettyStackTrace.h b/contrib/llvm/include/llvm/Support/PrettyStackTrace.h index 4f68fca2..914141a 100644 --- a/contrib/llvm/include/llvm/Support/PrettyStackTrace.h +++ b/contrib/llvm/include/llvm/Support/PrettyStackTrace.h @@ -50,7 +50,7 @@ namespace llvm { const char *Str; public: PrettyStackTraceString(const char *str) : Str(str) {} - virtual void print(raw_ostream &OS) const LLVM_OVERRIDE; + void print(raw_ostream &OS) const override; }; /// PrettyStackTraceProgram - This object prints a specified program arguments @@ -63,7 +63,7 @@ namespace llvm { : ArgC(argc), ArgV(argv) { EnablePrettyStackTrace(); } - virtual void print(raw_ostream &OS) const LLVM_OVERRIDE; + void print(raw_ostream &OS) const override; }; } // end namespace llvm diff --git a/contrib/llvm/include/llvm/Support/Process.h b/contrib/llvm/include/llvm/Support/Process.h index 2172036..30973de 100644 --- a/contrib/llvm/include/llvm/Support/Process.h +++ b/contrib/llvm/include/llvm/Support/Process.h @@ -29,9 +29,9 @@ #include "llvm/ADT/Optional.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/system_error.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/TimeValue.h" +#include <system_error> namespace llvm { class StringRef; @@ -110,10 +110,10 @@ class self_process : public process { virtual ~self_process(); public: - virtual id_type get_id(); - virtual TimeValue get_user_time() const; - virtual TimeValue get_system_time() const; - virtual TimeValue get_wall_time() const; + id_type get_id() override; + TimeValue get_user_time() const override; + TimeValue get_system_time() const override; + TimeValue get_wall_time() const override; /// \name Process configuration (sysconf on POSIX) /// @{ @@ -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/contrib/llvm/include/llvm/Support/Program.h b/contrib/llvm/include/llvm/Support/Program.h index 00571a4..51279a9 100644 --- a/contrib/llvm/include/llvm/Support/Program.h +++ b/contrib/llvm/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: @@ -52,27 +51,31 @@ struct ProcessInfo { ProcessInfo(); }; - /// This static constructor (factory) will attempt to locate a program in - /// the operating system's file system using some pre-determined set of - /// locations to search (e.g. the PATH on Unix). Paths with slashes are - /// returned unmodified. - /// @returns A Path object initialized to the path of the program or a - /// Path object that is empty (invalid) if the program could not be found. - /// @brief Construct a Program by finding it by name. + /// This function attempts to locate a program in the operating + /// system's file system using some pre-determined set of locations to search + /// (e.g. the PATH on Unix). Paths with slashes are returned unmodified. + /// + /// It does not perform hashing as a shell would but instead stats each PATH + /// entry individually so should generally be avoided. Core LLVM library + /// functions and options should instead require fully specified paths. + /// + /// @returns A string containing the path of the program or an empty string if + /// the program could not be found. std::string FindProgramByName(const std::string& name); - // These functions change the specified standard stream (stdin, stdout, or - // stderr) to binary mode. They return errc::success if the specified stream + // 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(); - error_code ChangeStderrToBinary(); + 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 /// descriptors, the environment and other configuration settings of the /// invoking program. - /// This function waits the program to finish. + /// This function waits for the program to finish, so should be avoided in + /// library functions that aren't expected to block. Consider using + /// ExecuteNoWait() instead. /// @returns an integer result code indicating the status of the program. /// A zero or positive value indicates the result code of the program. /// -1 indicates failure to execute @@ -83,11 +86,11 @@ struct ProcessInfo { const char **args, ///< A vector of strings that are passed to the ///< program. The first element should be the name of the program. ///< The list *must* be terminated by a null char* entry. - const char **env = 0, ///< An optional vector of strings to use for + const char **env = nullptr, ///< An optional vector of strings to use for ///< the program's environment. If not provided, the current program's ///< environment will be used. - const StringRef **redirects = 0, ///< An optional array of pointers to - ///< paths. If the array is null, no redirection is done. The array + const StringRef **redirects = nullptr, ///< An optional array of pointers + ///< to paths. If the array is null, no redirection is done. The array ///< should have a size of at least three. The inferior process's ///< stdin(0), stdout(1), and stderr(2) will be redirected to the ///< corresponding paths. @@ -103,11 +106,11 @@ struct ProcessInfo { ///< of memory can be allocated by process. If memory usage will be ///< higher limit, the child is killed and this call returns. If zero ///< - no memory limit. - std::string *ErrMsg = 0, ///< If non-zero, provides a pointer to a string - ///< instance in which error messages will be returned. If the string - ///< is non-empty upon return an error occurred while invoking the + std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a + ///< string instance in which error messages will be returned. If the + ///< string is non-empty upon return an error occurred while invoking the ///< program. - bool *ExecutionFailed = 0); + bool *ExecutionFailed = nullptr); /// Similar to ExecuteAndWait, but returns immediately. /// @returns The \see ProcessInfo of the newly launced process. @@ -115,9 +118,9 @@ struct ProcessInfo { /// Wait until the process finished execution or win32 CloseHandle() API on /// ProcessInfo.ProcessHandle to avoid memory leaks. ProcessInfo - ExecuteNoWait(StringRef Program, const char **args, const char **env = 0, - const StringRef **redirects = 0, unsigned memoryLimit = 0, - std::string *ErrMsg = 0, bool *ExecutionFailed = 0); + ExecuteNoWait(StringRef Program, const char **args, const char **env = nullptr, + const StringRef **redirects = nullptr, unsigned memoryLimit = 0, + std::string *ErrMsg = nullptr, bool *ExecutionFailed = nullptr); /// Return true if the given arguments fit within system-specific /// argument length limits. @@ -138,9 +141,9 @@ struct ProcessInfo { ///< will perform a non-blocking wait on the child process. bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits ///< until child has terminated. - std::string *ErrMsg = 0 ///< If non-zero, provides a pointer to a string - ///< instance in which error messages will be returned. If the string - ///< is non-empty upon return an error occurred while invoking the + std::string *ErrMsg = nullptr ///< If non-zero, provides a pointer to a + ///< string instance in which error messages will be returned. If the + ///< string is non-empty upon return an error occurred while invoking the ///< program. ); } diff --git a/contrib/llvm/include/llvm/Support/RandomNumberGenerator.h b/contrib/llvm/include/llvm/Support/RandomNumberGenerator.h new file mode 100644 index 0000000..cadc713 --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/include/llvm/Support/Recycler.h b/contrib/llvm/include/llvm/Support/Recycler.h index bcc561d..e97f36a 100644 --- a/contrib/llvm/include/llvm/Support/Recycler.h +++ b/contrib/llvm/include/llvm/Support/Recycler.h @@ -17,13 +17,12 @@ #include "llvm/ADT/ilist.h" #include "llvm/Support/AlignOf.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/ErrorHandling.h" #include <cassert> namespace llvm { -class BumpPtrAllocator; - /// PrintRecyclingAllocatorStats - Helper for RecyclingAllocator for /// printing statistics. /// @@ -100,10 +99,10 @@ public: template<class SubClass, class AllocatorType> SubClass *Allocate(AllocatorType &Allocator) { - assert(sizeof(SubClass) <= Size && - "Recycler allocation size is less than object size!"); - assert(AlignOf<SubClass>::Alignment <= Align && - "Recycler allocation alignment is less than object alignment!"); + static_assert(AlignOf<SubClass>::Alignment <= Align, + "Recycler allocation alignment is less than object align!"); + static_assert(sizeof(SubClass) <= Size, + "Recycler allocation size is less than object size!"); return !FreeList.empty() ? reinterpret_cast<SubClass *>(FreeList.remove(FreeList.begin())) : static_cast<SubClass *>(Allocator.Allocate(Size, Align)); diff --git a/contrib/llvm/include/llvm/Support/Regex.h b/contrib/llvm/include/llvm/Support/Regex.h index 3d071be..bf533ca 100644 --- a/contrib/llvm/include/llvm/Support/Regex.h +++ b/contrib/llvm/include/llvm/Support/Regex.h @@ -17,6 +17,7 @@ #ifndef LLVM_SUPPORT_REGEX_H #define LLVM_SUPPORT_REGEX_H +#include "llvm/Support/Compiler.h" #include <string> struct llvm_regex; @@ -45,6 +46,17 @@ namespace llvm { /// Compiles the given regular expression \p Regex. Regex(StringRef Regex, unsigned Flags = NoFlags); + Regex(const Regex &) LLVM_DELETED_FUNCTION; + Regex &operator=(Regex regex) { + std::swap(preg, regex.preg); + std::swap(error, regex.error); + return *this; + } + Regex(Regex &®ex) { + preg = regex.preg; + error = regex.error; + regex.preg = nullptr; + } ~Regex(); /// isValid - returns the error encountered during regex compilation, or @@ -63,7 +75,7 @@ namespace llvm { /// the first group is always the entire pattern. /// /// This returns true on a successful match. - bool match(StringRef String, SmallVectorImpl<StringRef> *Matches = 0); + bool match(StringRef String, SmallVectorImpl<StringRef> *Matches = nullptr); /// sub - Return the result of replacing the first match of the regex in /// \p String with the \p Repl string. Backreferences like "\0" in the @@ -75,12 +87,16 @@ namespace llvm { /// \param Error If non-null, any errors in the substitution (invalid /// backreferences, trailing backslashes) will be recorded as a non-empty /// string. - std::string sub(StringRef Repl, StringRef String, std::string *Error = 0); + std::string sub(StringRef Repl, StringRef String, + std::string *Error = nullptr); /// \brief If this function returns true, ^Str$ is an extended regular /// expression that matches Str and only Str. static bool isLiteralERE(StringRef Str); + /// \brief Turn String into a regex by escaping its special characters. + static std::string escape(StringRef String); + private: struct llvm_regex *preg; int error; diff --git a/contrib/llvm/include/llvm/Support/Registry.h b/contrib/llvm/include/llvm/Support/Registry.h index 073becd..b0c2e89 100644 --- a/contrib/llvm/include/llvm/Support/Registry.h +++ b/contrib/llvm/include/llvm/Support/Registry.h @@ -14,24 +14,27 @@ #ifndef LLVM_SUPPORT_REGISTRY_H #define LLVM_SUPPORT_REGISTRY_H +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" +#include <memory> + namespace llvm { /// A simple registry entry which provides only a name, description, and /// no-argument constructor. template <typename T> class SimpleRegistryEntry { const char *Name, *Desc; - T *(*Ctor)(); + std::unique_ptr<T> (*Ctor)(); public: - SimpleRegistryEntry(const char *N, const char *D, T *(*C)()) + SimpleRegistryEntry(const char *N, const char *D, std::unique_ptr<T> (*C)()) : Name(N), Desc(D), Ctor(C) {} const char *getName() const { return Name; } const char *getDesc() const { return Desc; } - T *instantiate() const { return Ctor(); } + std::unique_ptr<T> instantiate() const { return Ctor(); } }; @@ -88,7 +91,7 @@ namespace llvm { const entry& Val; public: - node(const entry& V) : Next(0), Val(V) { + node(const entry& V) : Next(nullptr), Val(V) { if (Tail) Tail->Next = this; else @@ -116,7 +119,7 @@ namespace llvm { }; static iterator begin() { return iterator(Head); } - static iterator end() { return iterator(0); } + static iterator end() { return iterator(nullptr); } /// Abstract base class for registry listeners, which are informed when new @@ -195,7 +198,7 @@ namespace llvm { entry Entry; node Node; - static T *CtorFn() { return new V(); } + static std::unique_ptr<T> CtorFn() { return make_unique<V>(); } public: Add(const char *Name, const char *Desc) diff --git a/contrib/llvm/include/llvm/Support/SMLoc.h b/contrib/llvm/include/llvm/Support/SMLoc.h index 0906471..d5b4c57 100644 --- a/contrib/llvm/include/llvm/Support/SMLoc.h +++ b/contrib/llvm/include/llvm/Support/SMLoc.h @@ -23,9 +23,9 @@ namespace llvm { class SMLoc { const char *Ptr; public: - SMLoc() : Ptr(0) {} + SMLoc() : Ptr(nullptr) {} - bool isValid() const { return Ptr != 0; } + bool isValid() const { return Ptr != nullptr; } bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; } bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; } diff --git a/contrib/llvm/include/llvm/Support/SaveAndRestore.h b/contrib/llvm/include/llvm/Support/SaveAndRestore.h index 6330bec..ef154ac 100644 --- a/contrib/llvm/include/llvm/Support/SaveAndRestore.h +++ b/contrib/llvm/include/llvm/Support/SaveAndRestore.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file provides utility classes that uses RAII to save and restore -// values. -// +/// +/// \file +/// This file provides utility classes that use RAII to save and restore +/// values. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_SAVEANDRESTORE_H @@ -17,31 +18,32 @@ namespace llvm { -// SaveAndRestore - A utility class that uses RAII to save and restore -// the value of a variable. -template<typename T> -struct SaveAndRestore { - SaveAndRestore(T& x) : X(x), old_value(x) {} - SaveAndRestore(T& x, const T &new_value) : X(x), old_value(x) { - X = new_value; +/// A utility class that uses RAII to save and restore the value of a variable. +template <typename T> struct SaveAndRestore { + SaveAndRestore(T &X) : X(X), OldValue(X) {} + SaveAndRestore(T &X, const T &NewValue) : X(X), OldValue(X) { + X = NewValue; } - ~SaveAndRestore() { X = old_value; } - T get() { return old_value; } + ~SaveAndRestore() { X = OldValue; } + T get() { return OldValue; } + private: - T& X; - T old_value; + T &X; + T OldValue; }; -// SaveOr - Similar to SaveAndRestore. Operates only on bools; the old -// value of a variable is saved, and during the dstor the old value is -// or'ed with the new value. +/// Similar to \c SaveAndRestore. Operates only on bools; the old value of a +/// variable is saved, and during the dstor the old value is or'ed with the new +/// value. struct SaveOr { - SaveOr(bool& x) : X(x), old_value(x) { x = false; } - ~SaveOr() { X |= old_value; } + SaveOr(bool &X) : X(X), OldValue(X) { X = false; } + ~SaveOr() { X |= OldValue; } + private: - bool& X; - const bool old_value; + bool &X; + const bool OldValue; }; -} +} // namespace llvm + #endif diff --git a/contrib/llvm/include/llvm/Support/ScaledNumber.h b/contrib/llvm/include/llvm/Support/ScaledNumber.h new file mode 100644 index 0000000..2bd7e74 --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/include/llvm/Support/Signals.h b/contrib/llvm/include/llvm/Support/Signals.h index 58ed175..6cbc1f6 100644 --- a/contrib/llvm/include/llvm/Support/Signals.h +++ b/contrib/llvm/include/llvm/Support/Signals.h @@ -28,7 +28,7 @@ namespace sys { /// This function registers signal handlers to ensure that if a signal gets /// delivered that the named file is removed. /// @brief Remove a file if a fatal signal occurs. - bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = 0); + bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = nullptr); /// This function removes a file from the list of files to be removed on /// signal delivery. diff --git a/contrib/llvm/include/llvm/Support/SourceMgr.h b/contrib/llvm/include/llvm/Support/SourceMgr.h index dd48974..4717553 100644 --- a/contrib/llvm/include/llvm/Support/SourceMgr.h +++ b/contrib/llvm/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,47 +40,48 @@ 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: - SourceMgr() : LineNoCache(0), DiagHandler(0), DiagContext(0) {} + SourceMgr() + : LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {} ~SourceMgr(); void setIncludeDirs(const std::vector<std::string> &Dirs) { 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. - void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0) { + /// 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; } @@ -89,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, @@ -156,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; }; @@ -207,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; @@ -222,10 +237,10 @@ class SMDiagnostic { public: // Null diagnostic. SMDiagnostic() - : SM(0), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} + : SM(nullptr), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} // Diagnostic with no location (e.g. file not found, command line arg error). SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg) - : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), + : SM(nullptr), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {} // Diagnostic with a location. diff --git a/contrib/llvm/include/llvm/Support/SpecialCaseList.h b/contrib/llvm/include/llvm/Support/SpecialCaseList.h new file mode 100644 index 0000000..098b9c7 --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/include/llvm/Support/StreamableMemoryObject.h b/contrib/llvm/include/llvm/Support/StreamableMemoryObject.h index e823d48..6e71ad4 100644 --- a/contrib/llvm/include/llvm/Support/StreamableMemoryObject.h +++ b/contrib/llvm/include/llvm/Support/StreamableMemoryObject.h @@ -11,10 +11,12 @@ #ifndef LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H #define LLVM_SUPPORT_STREAMABLEMEMORYOBJECT_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataStream.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryObject.h" +#include <cassert> +#include <memory> #include <vector> namespace llvm { @@ -38,7 +40,7 @@ class StreamableMemoryObject : public MemoryObject { /// getBase - Returns the lowest valid address in the region. /// /// @result - The lowest valid address. - virtual uint64_t getBase() const LLVM_OVERRIDE = 0; + uint64_t getBase() const override = 0; /// getExtent - Returns the size of the region in bytes. (The region is /// contiguous, so the highest valid address of the region @@ -46,7 +48,7 @@ class StreamableMemoryObject : public MemoryObject { /// May block until all bytes in the stream have been read /// /// @result - The size of the region. - virtual uint64_t getExtent() const LLVM_OVERRIDE = 0; + uint64_t getExtent() const override = 0; /// readByte - Tries to read a single byte from the region. /// May block until (address - base) bytes have been read @@ -54,7 +56,7 @@ class StreamableMemoryObject : public MemoryObject { /// @param ptr - A pointer to a byte to be filled in. Must be non-NULL. /// @result - 0 if successful; -1 if not. Failure may be due to a /// bounds violation or an implementation-specific error. - virtual int readByte(uint64_t address, uint8_t *ptr) const LLVM_OVERRIDE = 0; + int readByte(uint64_t address, uint8_t *ptr) const override = 0; /// readBytes - Tries to read a contiguous range of bytes from the /// region, up to the end of the region. @@ -70,9 +72,8 @@ class StreamableMemoryObject : public MemoryObject { /// and large enough to hold size bytes. /// @result - 0 if successful; -1 if not. Failure may be due to a /// bounds violation or an implementation-specific error. - virtual int readBytes(uint64_t address, - uint64_t size, - uint8_t *buf) const LLVM_OVERRIDE = 0; + int readBytes(uint64_t address, uint64_t size, + uint8_t *buf) const override = 0; /// getPointer - Ensures that the requested data is in memory, and returns /// A pointer to it. More efficient than using readBytes if the @@ -105,23 +106,21 @@ class StreamableMemoryObject : public MemoryObject { class StreamingMemoryObject : public StreamableMemoryObject { public: StreamingMemoryObject(DataStreamer *streamer); - virtual uint64_t getBase() const LLVM_OVERRIDE { return 0; } - virtual uint64_t getExtent() const LLVM_OVERRIDE; - virtual int readByte(uint64_t address, uint8_t *ptr) const LLVM_OVERRIDE; - virtual int readBytes(uint64_t address, - uint64_t size, - uint8_t *buf) const LLVM_OVERRIDE; - virtual const uint8_t *getPointer(uint64_t address, - uint64_t size) const LLVM_OVERRIDE { + uint64_t getBase() const override { return 0; } + uint64_t getExtent() const override; + int readByte(uint64_t address, uint8_t *ptr) const override; + int readBytes(uint64_t address, uint64_t size, + uint8_t *buf) const override; + const uint8_t *getPointer(uint64_t address, uint64_t size) const override { // This could be fixed by ensuring the bytes are fetched and making a copy, // 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"); - return NULL; + llvm_unreachable("getPointer in streaming memory objects not allowed"); + return nullptr; } - virtual bool isValidAddress(uint64_t address) const LLVM_OVERRIDE; - virtual bool isObjectEnd(uint64_t address) const LLVM_OVERRIDE; + bool isValidAddress(uint64_t address) const override; + bool isObjectEnd(uint64_t address) const override; /// Drop s bytes from the front of the stream, pushing the positions of the /// remaining bytes down by s. This is used to skip past the bitcode header, @@ -137,7 +136,7 @@ public: private: const static uint32_t kChunkSize = 4096 * 4; mutable std::vector<unsigned char> Bytes; - OwningPtr<DataStreamer> Streamer; + std::unique_ptr<DataStreamer> Streamer; mutable size_t BytesRead; // Bytes read from stream size_t BytesSkipped;// Bytes skipped at start of stream (e.g. wrapper/header) mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached @@ -156,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/contrib/llvm/include/llvm/Support/StringPool.h b/contrib/llvm/include/llvm/Support/StringPool.h index 71adbc5..3e04653 100644 --- a/contrib/llvm/include/llvm/Support/StringPool.h +++ b/contrib/llvm/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> @@ -48,7 +49,7 @@ namespace llvm { unsigned Refcount; ///< Number of referencing PooledStringPtrs. public: - PooledString() : Pool(0), Refcount(0) { } + PooledString() : Pool(nullptr), Refcount(0) { } }; friend class PooledStringPtr; @@ -81,7 +82,7 @@ namespace llvm { entry_t *S; public: - PooledStringPtr() : S(0) {} + PooledStringPtr() : S(nullptr) {} explicit PooledStringPtr(entry_t *E) : S(E) { if (S) ++S->getValue().Refcount; @@ -107,7 +108,7 @@ namespace llvm { S->getValue().Pool->InternTable.remove(S); S->Destroy(); } - S = 0; + S = nullptr; } ~PooledStringPtr() { clear(); } @@ -128,10 +129,10 @@ namespace llvm { } inline const char *operator*() const { return begin(); } - inline operator bool() const { return S != 0; } + 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/contrib/llvm/include/llvm/Support/StringRefMemoryObject.h b/contrib/llvm/include/llvm/Support/StringRefMemoryObject.h index 994fa34..8a349ea 100644 --- a/contrib/llvm/include/llvm/Support/StringRefMemoryObject.h +++ b/contrib/llvm/include/llvm/Support/StringRefMemoryObject.h @@ -29,11 +29,11 @@ public: StringRefMemoryObject(StringRef Bytes, uint64_t Base = 0) : Bytes(Bytes), Base(Base) {} - uint64_t getBase() const LLVM_OVERRIDE { return Base; } - uint64_t getExtent() const LLVM_OVERRIDE { return Bytes.size(); } + uint64_t getBase() const override { return Base; } + uint64_t getExtent() const override { return Bytes.size(); } - int readByte(uint64_t Addr, uint8_t *Byte) const LLVM_OVERRIDE; - int readBytes(uint64_t Addr, uint64_t Size, uint8_t *Buf) const LLVM_OVERRIDE; + int readByte(uint64_t Addr, uint8_t *Byte) const override; + int readBytes(uint64_t Addr, uint64_t Size, uint8_t *Buf) const override; }; } diff --git a/contrib/llvm/include/llvm/Support/SwapByteOrder.h b/contrib/llvm/include/llvm/Support/SwapByteOrder.h index e65f9cc..340954f 100644 --- a/contrib/llvm/include/llvm/Support/SwapByteOrder.h +++ b/contrib/llvm/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/contrib/llvm/include/llvm/Support/TargetFolder.h b/contrib/llvm/include/llvm/Support/TargetFolder.h deleted file mode 100644 index 5c1978d..0000000 --- a/contrib/llvm/include/llvm/Support/TargetFolder.h +++ /dev/null @@ -1,262 +0,0 @@ -//====-- llvm/Support/TargetFolder.h - Constant folding helper -*- C++ -*-====// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the TargetFolder class, a helper for IRBuilder. -// It provides IRBuilder with a set of methods for creating constants with -// target dependent folding, in addition to the same target-independent -// folding that the ConstantFolder class provides. For general constant -// creation and folding, use ConstantExpr and the routines in -// llvm/Analysis/ConstantFolding.h. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_TARGETFOLDER_H -#define LLVM_SUPPORT_TARGETFOLDER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Analysis/ConstantFolding.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/InstrTypes.h" - -namespace llvm { - -class DataLayout; - -/// TargetFolder - Create constants with target dependent folding. -class TargetFolder { - const DataLayout *TD; - - /// Fold - Fold the constant using target specific information. - Constant *Fold(Constant *C) const { - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) - if (Constant *CF = ConstantFoldConstantExpression(CE, TD)) - return CF; - return C; - } - -public: - explicit TargetFolder(const DataLayout *TheTD) : TD(TheTD) {} - - //===--------------------------------------------------------------------===// - // Binary Operators - //===--------------------------------------------------------------------===// - - Constant *CreateAdd(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - return Fold(ConstantExpr::getAdd(LHS, RHS, HasNUW, HasNSW)); - } - Constant *CreateFAdd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getFAdd(LHS, RHS)); - } - Constant *CreateSub(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - return Fold(ConstantExpr::getSub(LHS, RHS, HasNUW, HasNSW)); - } - Constant *CreateFSub(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getFSub(LHS, RHS)); - } - Constant *CreateMul(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - return Fold(ConstantExpr::getMul(LHS, RHS, HasNUW, HasNSW)); - } - Constant *CreateFMul(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getFMul(LHS, RHS)); - } - Constant *CreateUDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ - return Fold(ConstantExpr::getUDiv(LHS, RHS, isExact)); - } - Constant *CreateSDiv(Constant *LHS, Constant *RHS, bool isExact = false)const{ - return Fold(ConstantExpr::getSDiv(LHS, RHS, isExact)); - } - Constant *CreateFDiv(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getFDiv(LHS, RHS)); - } - Constant *CreateURem(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getURem(LHS, RHS)); - } - Constant *CreateSRem(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getSRem(LHS, RHS)); - } - Constant *CreateFRem(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getFRem(LHS, RHS)); - } - Constant *CreateShl(Constant *LHS, Constant *RHS, - bool HasNUW = false, bool HasNSW = false) const { - return Fold(ConstantExpr::getShl(LHS, RHS, HasNUW, HasNSW)); - } - Constant *CreateLShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ - return Fold(ConstantExpr::getLShr(LHS, RHS, isExact)); - } - Constant *CreateAShr(Constant *LHS, Constant *RHS, bool isExact = false)const{ - return Fold(ConstantExpr::getAShr(LHS, RHS, isExact)); - } - Constant *CreateAnd(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getAnd(LHS, RHS)); - } - Constant *CreateOr(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getOr(LHS, RHS)); - } - Constant *CreateXor(Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::getXor(LHS, RHS)); - } - - Constant *CreateBinOp(Instruction::BinaryOps Opc, - Constant *LHS, Constant *RHS) const { - return Fold(ConstantExpr::get(Opc, LHS, RHS)); - } - - //===--------------------------------------------------------------------===// - // Unary Operators - //===--------------------------------------------------------------------===// - - Constant *CreateNeg(Constant *C, - bool HasNUW = false, bool HasNSW = false) const { - return Fold(ConstantExpr::getNeg(C, HasNUW, HasNSW)); - } - Constant *CreateFNeg(Constant *C) const { - return Fold(ConstantExpr::getFNeg(C)); - } - Constant *CreateNot(Constant *C) const { - return Fold(ConstantExpr::getNot(C)); - } - - //===--------------------------------------------------------------------===// - // Memory Instructions - //===--------------------------------------------------------------------===// - - Constant *CreateGetElementPtr(Constant *C, - ArrayRef<Constant *> IdxList) const { - return Fold(ConstantExpr::getGetElementPtr(C, IdxList)); - } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { - // This form of the function only exists to avoid ambiguous overload - // warnings about whether to convert Idx to ArrayRef<Constant *> or - // ArrayRef<Value *>. - return Fold(ConstantExpr::getGetElementPtr(C, Idx)); - } - Constant *CreateGetElementPtr(Constant *C, - ArrayRef<Value *> IdxList) const { - return Fold(ConstantExpr::getGetElementPtr(C, IdxList)); - } - - Constant *CreateInBoundsGetElementPtr(Constant *C, - ArrayRef<Constant *> IdxList) const { - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList)); - } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { - // This form of the function only exists to avoid ambiguous overload - // warnings about whether to convert Idx to ArrayRef<Constant *> or - // ArrayRef<Value *>. - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, Idx)); - } - Constant *CreateInBoundsGetElementPtr(Constant *C, - ArrayRef<Value *> IdxList) const { - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList)); - } - - //===--------------------------------------------------------------------===// - // Cast/Conversion Operators - //===--------------------------------------------------------------------===// - - Constant *CreateCast(Instruction::CastOps Op, Constant *C, - Type *DestTy) const { - if (C->getType() == DestTy) - return C; // avoid calling Fold - return Fold(ConstantExpr::getCast(Op, C, DestTy)); - } - Constant *CreateIntCast(Constant *C, Type *DestTy, - bool isSigned) const { - if (C->getType() == DestTy) - return C; // avoid calling Fold - return Fold(ConstantExpr::getIntegerCast(C, DestTy, isSigned)); - } - Constant *CreatePointerCast(Constant *C, Type *DestTy) const { - if (C->getType() == DestTy) - return C; // avoid calling Fold - return Fold(ConstantExpr::getPointerCast(C, DestTy)); - } - Constant *CreateFPCast(Constant *C, Type *DestTy) const { - if (C->getType() == DestTy) - return C; // avoid calling Fold - return Fold(ConstantExpr::getFPCast(C, DestTy)); - } - Constant *CreateBitCast(Constant *C, Type *DestTy) const { - return CreateCast(Instruction::BitCast, C, DestTy); - } - Constant *CreateIntToPtr(Constant *C, Type *DestTy) const { - return CreateCast(Instruction::IntToPtr, C, DestTy); - } - Constant *CreatePtrToInt(Constant *C, Type *DestTy) const { - return CreateCast(Instruction::PtrToInt, C, DestTy); - } - Constant *CreateZExtOrBitCast(Constant *C, Type *DestTy) const { - if (C->getType() == DestTy) - return C; // avoid calling Fold - return Fold(ConstantExpr::getZExtOrBitCast(C, DestTy)); - } - Constant *CreateSExtOrBitCast(Constant *C, Type *DestTy) const { - if (C->getType() == DestTy) - return C; // avoid calling Fold - return Fold(ConstantExpr::getSExtOrBitCast(C, DestTy)); - } - Constant *CreateTruncOrBitCast(Constant *C, Type *DestTy) const { - if (C->getType() == DestTy) - return C; // avoid calling Fold - return Fold(ConstantExpr::getTruncOrBitCast(C, DestTy)); - } - - //===--------------------------------------------------------------------===// - // Compare Instructions - //===--------------------------------------------------------------------===// - - Constant *CreateICmp(CmpInst::Predicate P, Constant *LHS, - Constant *RHS) const { - return Fold(ConstantExpr::getCompare(P, LHS, RHS)); - } - Constant *CreateFCmp(CmpInst::Predicate P, Constant *LHS, - Constant *RHS) const { - return Fold(ConstantExpr::getCompare(P, LHS, RHS)); - } - - //===--------------------------------------------------------------------===// - // Other Instructions - //===--------------------------------------------------------------------===// - - Constant *CreateSelect(Constant *C, Constant *True, Constant *False) const { - return Fold(ConstantExpr::getSelect(C, True, False)); - } - - Constant *CreateExtractElement(Constant *Vec, Constant *Idx) const { - return Fold(ConstantExpr::getExtractElement(Vec, Idx)); - } - - Constant *CreateInsertElement(Constant *Vec, Constant *NewElt, - Constant *Idx) const { - return Fold(ConstantExpr::getInsertElement(Vec, NewElt, Idx)); - } - - Constant *CreateShuffleVector(Constant *V1, Constant *V2, - Constant *Mask) const { - return Fold(ConstantExpr::getShuffleVector(V1, V2, Mask)); - } - - Constant *CreateExtractValue(Constant *Agg, - ArrayRef<unsigned> IdxList) const { - return Fold(ConstantExpr::getExtractValue(Agg, IdxList)); - } - - Constant *CreateInsertValue(Constant *Agg, Constant *Val, - ArrayRef<unsigned> IdxList) const { - return Fold(ConstantExpr::getInsertValue(Agg, Val, IdxList)); - } -}; - -} - -#endif diff --git a/contrib/llvm/include/llvm/Support/TargetRegistry.h b/contrib/llvm/include/llvm/Support/TargetRegistry.h index 9ecee3b..5d5b86a 100644 --- a/contrib/llvm/include/llvm/Support/TargetRegistry.h +++ b/contrib/llvm/include/llvm/Support/TargetRegistry.h @@ -19,9 +19,9 @@ #ifndef LLVM_SUPPORT_TARGETREGISTRY_H #define LLVM_SUPPORT_TARGETREGISTRY_H +#include "llvm-c/Disassembler.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" -#include "llvm-c/Disassembler.h" #include <cassert> #include <string> @@ -45,17 +45,15 @@ namespace llvm { class MCSymbolizer; class MCRelocationInfo; class MCTargetAsmParser; + class MCTargetOptions; class TargetMachine; - class MCTargetStreamer; class TargetOptions; class raw_ostream; class formatted_raw_ostream; - MCStreamer *createAsmStreamer(MCContext &Ctx, - MCTargetStreamer *TargetStreamer, - formatted_raw_ostream &OS, bool isVerboseAsm, - bool useLoc, bool useCFI, - bool useDwarfDirectory, + MCStreamer *createNullStreamer(MCContext &Ctx); + MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); @@ -79,7 +77,7 @@ namespace llvm { public: friend struct TargetRegistry; - typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT); + typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch); typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI, StringRef TT); @@ -107,11 +105,14 @@ namespace llvm { const MCRegisterInfo &MRI, StringRef TT, StringRef CPU); - typedef MCTargetAsmParser *(*MCAsmParserCtorTy)(MCSubtargetInfo &STI, - MCAsmParser &P, - const MCInstrInfo &MII); + typedef MCTargetAsmParser *(*MCAsmParserCtorTy)( + MCSubtargetInfo &STI, + MCAsmParser &P, + const MCInstrInfo &MII, + const MCTargetOptions &Options); typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, - const MCSubtargetInfo &STI); + const MCSubtargetInfo &STI, + MCContext &Ctx); typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, @@ -128,18 +129,18 @@ namespace llvm { MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, + const MCSubtargetInfo &STI, bool RelaxAll, bool NoExecStack); typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, - bool useLoc, - bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); + typedef MCStreamer *(*NullStreamerCtorTy)(MCContext &Ctx); typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT, MCContext &Ctx); typedef MCSymbolizer *(*MCSymbolizerCtorTy)(StringRef TT, @@ -154,9 +155,8 @@ namespace llvm { /// TargetRegistry. Target *Next; - /// TripleMatchQualityFn - The target function for rating the match quality - /// of a triple. - TripleMatchQualityFnTy TripleMatchQualityFn; + /// The target function for checking if an architecture is supported. + ArchMatchFnTy ArchMatchFn; /// Name - The target name. const char *Name; @@ -227,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; @@ -237,8 +241,8 @@ namespace llvm { public: Target() - : AsmStreamerCtorFn(0), MCRelocationInfoCtorFn(0), - MCSymbolizerCtorFn(0) {} + : AsmStreamerCtorFn(nullptr), NullStreamerCtorFn(nullptr), + MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {} /// @name Target Information /// @{ @@ -260,10 +264,10 @@ namespace llvm { bool hasJIT() const { return HasJIT; } /// hasTargetMachine - Check if this target supports code generation. - bool hasTargetMachine() const { return TargetMachineCtorFn != 0; } + bool hasTargetMachine() const { return TargetMachineCtorFn != nullptr; } /// hasMCAsmBackend - Check if this target supports .o generation. - bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != 0; } + bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != nullptr; } /// @} /// @name Feature Constructors @@ -279,7 +283,7 @@ namespace llvm { MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI, StringRef Triple) const { if (!MCAsmInfoCtorFn) - return 0; + return nullptr; return MCAsmInfoCtorFn(MRI, Triple); } @@ -289,7 +293,7 @@ namespace llvm { CodeModel::Model CM, CodeGenOpt::Level OL) const { if (!MCCodeGenInfoCtorFn) - return 0; + return nullptr; return MCCodeGenInfoCtorFn(Triple, RM, CM, OL); } @@ -297,7 +301,7 @@ namespace llvm { /// MCInstrInfo *createMCInstrInfo() const { if (!MCInstrInfoCtorFn) - return 0; + return nullptr; return MCInstrInfoCtorFn(); } @@ -305,7 +309,7 @@ namespace llvm { /// MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const { if (!MCInstrAnalysisCtorFn) - return 0; + return nullptr; return MCInstrAnalysisCtorFn(Info); } @@ -313,7 +317,7 @@ namespace llvm { /// MCRegisterInfo *createMCRegInfo(StringRef Triple) const { if (!MCRegInfoCtorFn) - return 0; + return nullptr; return MCRegInfoCtorFn(Triple); } @@ -329,7 +333,7 @@ namespace llvm { MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU, StringRef Features) const { if (!MCSubtargetInfoCtorFn) - return 0; + return nullptr; return MCSubtargetInfoCtorFn(Triple, CPU, Features); } @@ -346,7 +350,7 @@ namespace llvm { CodeModel::Model CM = CodeModel::Default, CodeGenOpt::Level OL = CodeGenOpt::Default) const { if (!TargetMachineCtorFn) - return 0; + return nullptr; return TargetMachineCtorFn(*this, Triple, CPU, Features, Options, RM, CM, OL); } @@ -357,7 +361,7 @@ namespace llvm { MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI, StringRef Triple, StringRef CPU) const { if (!MCAsmBackendCtorFn) - return 0; + return nullptr; return MCAsmBackendCtorFn(*this, MRI, Triple, CPU); } @@ -365,26 +369,29 @@ namespace llvm { /// /// \param Parser The target independent parser implementation to use for /// parsing and lexing. - MCTargetAsmParser *createMCAsmParser(MCSubtargetInfo &STI, - MCAsmParser &Parser, - const MCInstrInfo &MII) const { + MCTargetAsmParser *createMCAsmParser( + MCSubtargetInfo &STI, + MCAsmParser &Parser, + const MCInstrInfo &MII, + const MCTargetOptions &Options) const { if (!MCAsmParserCtorFn) - return 0; - return MCAsmParserCtorFn(STI, Parser, MII); + return nullptr; + return MCAsmParserCtorFn(STI, Parser, MII, Options); } /// createAsmPrinter - Create a target specific assembly printer pass. This /// takes ownership of the MCStreamer object. AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{ if (!AsmPrinterCtorFn) - return 0; + return nullptr; return AsmPrinterCtorFn(TM, Streamer); } - MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI) const { + MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI, + MCContext &Ctx) const { if (!MCDisassemblerCtorFn) - return 0; - return MCDisassemblerCtorFn(*this, STI); + return nullptr; + return MCDisassemblerCtorFn(*this, STI, Ctx); } MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, @@ -393,7 +400,7 @@ namespace llvm { const MCRegisterInfo &MRI, const MCSubtargetInfo &STI) const { if (!MCInstPrinterCtorFn) - return 0; + return nullptr; return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, MII, MRI, STI); } @@ -404,7 +411,7 @@ namespace llvm { const MCSubtargetInfo &STI, MCContext &Ctx) const { if (!MCCodeEmitterCtorFn) - return 0; + return nullptr; return MCCodeEmitterCtorFn(II, MRI, STI, Ctx); } @@ -421,11 +428,12 @@ namespace llvm { MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter, + const MCSubtargetInfo &STI, bool RelaxAll, bool NoExecStack) const { if (!MCObjectStreamerCtorFn) - return 0; - return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, + return nullptr; + return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, STI, RelaxAll, NoExecStack); } @@ -433,20 +441,22 @@ namespace llvm { MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, bool isVerboseAsm, - bool useLoc, - bool useCFI, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) const { if (AsmStreamerCtorFn) - return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useLoc, useCFI, - useDwarfDirectory, InstPrint, CE, TAB, - ShowInst); - return llvm::createAsmStreamer(Ctx, 0, OS, isVerboseAsm, useLoc, useCFI, - useDwarfDirectory, InstPrint, CE, TAB, - ShowInst); + return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useDwarfDirectory, + InstPrint, CE, TAB, ShowInst); + return llvm::createAsmStreamer(Ctx, OS, isVerboseAsm, useDwarfDirectory, + InstPrint, CE, TAB, ShowInst); + } + + MCStreamer *createNullStreamer(MCContext &Ctx) const { + if (NullStreamerCtorFn) + return NullStreamerCtorFn(Ctx); + return llvm::createNullStreamer(Ctx); } /// createMCRelocationInfo - Create a target specific MCRelocationInfo. @@ -490,8 +500,7 @@ namespace llvm { explicit iterator(Target *T) : Current(T) {} friend struct TargetRegistry; public: - iterator(const iterator &I) : Current(I.Current) {} - iterator() : Current(0) {} + iterator() : Current(nullptr) {} bool operator==(const iterator &x) const { return Current == x.Current; @@ -556,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 /// @{ @@ -578,14 +580,13 @@ namespace llvm { /// @param Name - The target name. This should be a static string. /// @param ShortDesc - A short target description. This should be a static /// string. - /// @param TQualityFn - The triple match quality computation function for - /// this target. + /// @param ArchMatchFn - The arch match checking function for this target. /// @param HasJIT - Whether the target supports JIT code /// generation. static void RegisterTarget(Target &T, const char *Name, const char *ShortDesc, - Target::TripleMatchQualityFnTy TQualityFn, + Target::ArchMatchFnTy ArchMatchFn, bool HasJIT = false); /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the @@ -784,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. /// @@ -831,15 +836,11 @@ namespace llvm { bool HasJIT = false> struct RegisterTarget { RegisterTarget(Target &T, const char *Name, const char *Desc) { - TargetRegistry::RegisterTarget(T, Name, Desc, - &getTripleMatchQuality, - HasJIT); + TargetRegistry::RegisterTarget(T, Name, Desc, &getArchMatch, HasJIT); } - static unsigned getTripleMatchQuality(const std::string &TT) { - if (Triple(TT).getArch() == TargetArchType) - return 20; - return 0; + static bool getArchMatch(Triple::ArchType Arch) { + return Arch == TargetArchType; } }; @@ -1107,8 +1108,9 @@ namespace llvm { private: static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P, - const MCInstrInfo &MII) { - return new MCAsmParserImpl(STI, P, MII); + const MCInstrInfo &MII, + const MCTargetOptions &Options) { + return new MCAsmParserImpl(STI, P, MII, Options); } }; diff --git a/contrib/llvm/include/llvm/Support/Threading.h b/contrib/llvm/include/llvm/Support/Threading.h index a7e8774..7e87584 100644 --- a/contrib/llvm/include/llvm/Support/Threading.h +++ b/contrib/llvm/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/contrib/llvm/include/llvm/Support/TimeValue.h b/contrib/llvm/include/llvm/Support/TimeValue.h index 2785408..ee0e286 100644 --- a/contrib/llvm/include/llvm/Support/TimeValue.h +++ b/contrib/llvm/include/llvm/Support/TimeValue.h @@ -74,8 +74,7 @@ namespace sys { MILLISECONDS_PER_SECOND = 1000, ///< One Thousand NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million - NANOSECONDS_PER_POSIX_TICK = 100, ///< Posix tick is 100 Hz (10ms) - NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 100 Hz (10ms) + NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 10^7 Hz (10ns) }; /// @} @@ -236,15 +235,6 @@ namespace sys { ( nanos_ / NANOSECONDS_PER_MILLISECOND ); } - /// Converts the TimeValue into the corresponding number of "ticks" for - /// Posix, correcting for the difference in Posix zero time. - /// @brief Convert to unix time (100 nanoseconds since 12:00:00a Jan 1,1970) - uint64_t toPosixTime() const { - uint64_t result = seconds_ - PosixZeroTimeSeconds; - result += nanos_ / NANOSECONDS_PER_POSIX_TICK; - return result; - } - /// Converts the TimeValue into the corresponding number of seconds /// since the epoch (00:00:00 Jan 1,1970). uint64_t toEpochTime() const { diff --git a/contrib/llvm/include/llvm/Support/Timer.h b/contrib/llvm/include/llvm/Support/Timer.h index d009d7f..45c1828 100644 --- a/contrib/llvm/include/llvm/Support/Timer.h +++ b/contrib/llvm/include/llvm/Support/Timer.h @@ -85,24 +85,24 @@ class Timer { Timer **Prev, *Next; // Doubly linked list of timers in the group. public: - explicit Timer(StringRef N) : TG(0) { init(N); } - Timer(StringRef N, TimerGroup &tg) : TG(0) { init(N, tg); } - Timer(const Timer &RHS) : TG(0) { - assert(RHS.TG == 0 && "Can only copy uninitialized timers"); + explicit Timer(StringRef N) : TG(nullptr) { init(N); } + Timer(StringRef N, TimerGroup &tg) : TG(nullptr) { init(N, tg); } + Timer(const Timer &RHS) : TG(nullptr) { + assert(!RHS.TG && "Can only copy uninitialized timers"); } const Timer &operator=(const Timer &T) { - assert(TG == 0 && T.TG == 0 && "Can only assign uninit timers"); + assert(!TG && !T.TG && "Can only assign uninit timers"); return *this; } ~Timer(); // Create an uninitialized timer, client must use 'init'. - explicit Timer() : TG(0) {} + explicit Timer() : TG(nullptr) {} void init(StringRef N); void init(StringRef N, TimerGroup &tg); const std::string &getName() const { return Name; } - bool isInitialized() const { return TG != 0; } + bool isInitialized() const { return TG != nullptr; } /// startTimer - Start the timer running. Time between calls to /// startTimer/stopTimer is counted by the Timer class. Note that these calls diff --git a/contrib/llvm/include/llvm/Support/ToolOutputFile.h b/contrib/llvm/include/llvm/Support/ToolOutputFile.h index a2191ad..88f8ccc 100644 --- a/contrib/llvm/include/llvm/Support/ToolOutputFile.h +++ b/contrib/llvm/include/llvm/Support/ToolOutputFile.h @@ -47,7 +47,7 @@ public: /// tool_output_file - This constructor's arguments are passed to /// to raw_fd_ostream's constructor. tool_output_file(const char *filename, std::string &ErrorInfo, - sys::fs::OpenFlags Flags = sys::fs::F_None); + sys::fs::OpenFlags Flags); tool_output_file(const char *Filename, int FD); diff --git a/contrib/llvm/include/llvm/Support/Unicode.h b/contrib/llvm/include/llvm/Support/Unicode.h index e6a52c4..f668a5b 100644 --- a/contrib/llvm/include/llvm/Support/Unicode.h +++ b/contrib/llvm/include/llvm/Support/Unicode.h @@ -12,6 +12,9 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_SUPPORT_UNICODE_H +#define LLVM_SUPPORT_UNICODE_H + #include "llvm/ADT/StringRef.h" namespace llvm { @@ -60,3 +63,5 @@ int columnWidthUTF8(StringRef Text); } // namespace unicode } // namespace sys } // namespace llvm + +#endif diff --git a/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h b/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h index 86faa38..79137bf 100644 --- a/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h +++ b/contrib/llvm/include/llvm/Support/UnicodeCharRanges.h @@ -16,12 +16,13 @@ #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" #include "llvm/Support/raw_ostream.h" - #include <algorithm> namespace llvm { namespace sys { +#define DEBUG_TYPE "unicode" + /// \brief Represents a closed range of Unicode code points [Lower, Upper]. struct UnicodeCharRange { uint32_t Lower; @@ -40,7 +41,7 @@ inline bool operator<(UnicodeCharRange Range, uint32_t Value) { /// array. class UnicodeCharSet { public: - typedef llvm::ArrayRef<UnicodeCharRange> CharRanges; + typedef ArrayRef<UnicodeCharRange> CharRanges; /// \brief Constructs a UnicodeCharSet instance from an array of /// UnicodeCharRanges. @@ -67,17 +68,17 @@ private: for (CharRanges::const_iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { if (I != Ranges.begin() && Prev >= I->Lower) { - DEBUG(llvm::dbgs() << "Upper bound 0x"); - DEBUG(llvm::dbgs().write_hex(Prev)); - DEBUG(llvm::dbgs() << " should be less than succeeding lower bound 0x"); - DEBUG(llvm::dbgs().write_hex(I->Lower) << "\n"); + DEBUG(dbgs() << "Upper bound 0x"); + DEBUG(dbgs().write_hex(Prev)); + DEBUG(dbgs() << " should be less than succeeding lower bound 0x"); + DEBUG(dbgs().write_hex(I->Lower) << "\n"); return false; } if (I->Upper < I->Lower) { - DEBUG(llvm::dbgs() << "Upper bound 0x"); - DEBUG(llvm::dbgs().write_hex(I->Lower)); - DEBUG(llvm::dbgs() << " should not be less than lower bound 0x"); - DEBUG(llvm::dbgs().write_hex(I->Upper) << "\n"); + DEBUG(dbgs() << "Upper bound 0x"); + DEBUG(dbgs().write_hex(I->Lower)); + DEBUG(dbgs() << " should not be less than lower bound 0x"); + DEBUG(dbgs().write_hex(I->Upper) << "\n"); return false; } Prev = I->Upper; @@ -89,6 +90,8 @@ private: const CharRanges Ranges; }; +#undef DEBUG_TYPE // "unicode" + } // namespace sys } // namespace llvm diff --git a/contrib/llvm/include/llvm/Support/Valgrind.h b/contrib/llvm/include/llvm/Support/Valgrind.h index 7ae40af..cebf75c 100644 --- a/contrib/llvm/include/llvm/Support/Valgrind.h +++ b/contrib/llvm/include/llvm/Support/Valgrind.h @@ -24,12 +24,10 @@ // tsan (Thread Sanitizer) is a valgrind-based tool that detects these exact // functions by name. extern "C" { -LLVM_ATTRIBUTE_WEAK void AnnotateHappensAfter(const char *file, int line, - const volatile void *cv); -LLVM_ATTRIBUTE_WEAK void AnnotateHappensBefore(const char *file, int line, - const volatile void *cv); -LLVM_ATTRIBUTE_WEAK void AnnotateIgnoreWritesBegin(const char *file, int line); -LLVM_ATTRIBUTE_WEAK void AnnotateIgnoreWritesEnd(const char *file, int line); +void AnnotateHappensAfter(const char *file, int line, const volatile void *cv); +void AnnotateHappensBefore(const char *file, int line, const volatile void *cv); +void AnnotateIgnoreWritesBegin(const char *file, int line); +void AnnotateIgnoreWritesEnd(const char *file, int line); } #endif diff --git a/contrib/llvm/include/llvm/Support/ValueHandle.h b/contrib/llvm/include/llvm/Support/ValueHandle.h deleted file mode 100644 index bc02ba3..0000000 --- a/contrib/llvm/include/llvm/Support/ValueHandle.h +++ /dev/null @@ -1,380 +0,0 @@ -//===- llvm/Support/ValueHandle.h - Value Smart Pointer classes -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the ValueHandle class and its sub-classes. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_VALUEHANDLE_H -#define LLVM_SUPPORT_VALUEHANDLE_H - -#include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/IR/Value.h" - -namespace llvm { -class ValueHandleBase; -template<typename From> struct simplify_type; - -// ValueHandleBase** is only 4-byte aligned. -template<> -class PointerLikeTypeTraits<ValueHandleBase**> { -public: - static inline void *getAsVoidPointer(ValueHandleBase** P) { return P; } - static inline ValueHandleBase **getFromVoidPointer(void *P) { - return static_cast<ValueHandleBase**>(P); - } - enum { NumLowBitsAvailable = 2 }; -}; - -/// ValueHandleBase - This is the common base class of value handles. -/// ValueHandle's are smart pointers to Value's that have special behavior when -/// the value is deleted or ReplaceAllUsesWith'd. See the specific handles -/// below for details. -/// -class ValueHandleBase { - friend class Value; -protected: - /// HandleBaseKind - This indicates what sub class the handle actually is. - /// This is to avoid having a vtable for the light-weight handle pointers. The - /// fully general Callback version does have a vtable. - enum HandleBaseKind { - Assert, - Callback, - Tracking, - Weak - }; - -private: - PointerIntPair<ValueHandleBase**, 2, HandleBaseKind> PrevPair; - ValueHandleBase *Next; - - // A subclass may want to store some information along with the value - // pointer. Allow them to do this by making the value pointer a pointer-int - // pair. The 'setValPtrInt' and 'getValPtrInt' methods below give them this - // access. - PointerIntPair<Value*, 2> VP; - - ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; -public: - explicit ValueHandleBase(HandleBaseKind Kind) - : PrevPair(0, Kind), Next(0), VP(0, 0) {} - ValueHandleBase(HandleBaseKind Kind, Value *V) - : PrevPair(0, Kind), Next(0), VP(V, 0) { - if (isValid(VP.getPointer())) - AddToUseList(); - } - ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) - : PrevPair(0, Kind), Next(0), VP(RHS.VP) { - if (isValid(VP.getPointer())) - AddToExistingUseList(RHS.getPrevPtr()); - } - ~ValueHandleBase() { - if (isValid(VP.getPointer())) - RemoveFromUseList(); - } - - Value *operator=(Value *RHS) { - if (VP.getPointer() == RHS) return RHS; - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS); - if (isValid(VP.getPointer())) AddToUseList(); - return RHS; - } - - Value *operator=(const ValueHandleBase &RHS) { - if (VP.getPointer() == RHS.VP.getPointer()) return RHS.VP.getPointer(); - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS.VP.getPointer()); - if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr()); - return VP.getPointer(); - } - - Value *operator->() const { return getValPtr(); } - Value &operator*() const { return *getValPtr(); } - -protected: - Value *getValPtr() const { return VP.getPointer(); } - - void setValPtrInt(unsigned K) { VP.setInt(K); } - unsigned getValPtrInt() const { return VP.getInt(); } - - static bool isValid(Value *V) { - return V && - V != DenseMapInfo<Value *>::getEmptyKey() && - V != DenseMapInfo<Value *>::getTombstoneKey(); - } - -public: - // Callbacks made from Value. - static void ValueIsDeleted(Value *V); - static void ValueIsRAUWd(Value *Old, Value *New); - -private: - // Internal implementation details. - ValueHandleBase **getPrevPtr() const { return PrevPair.getPointer(); } - HandleBaseKind getKind() const { return PrevPair.getInt(); } - void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } - - /// AddToExistingUseList - Add this ValueHandle to the use list for VP, where - /// List is the address of either the head of the list or a Next node within - /// the existing use list. - void AddToExistingUseList(ValueHandleBase **List); - - /// AddToExistingUseListAfter - Add this ValueHandle to the use list after - /// Node. - void AddToExistingUseListAfter(ValueHandleBase *Node); - - /// AddToUseList - Add this ValueHandle to the use list for VP. - void AddToUseList(); - /// RemoveFromUseList - Remove this ValueHandle from its current use list. - void RemoveFromUseList(); -}; - -/// WeakVH - This is a value handle that tries hard to point to a Value, even -/// across RAUW operations, but will null itself out if the value is destroyed. -/// this is useful for advisory sorts of information, but should not be used as -/// the key of a map (since the map would have to rearrange itself when the -/// pointer changes). -class WeakVH : public ValueHandleBase { -public: - WeakVH() : ValueHandleBase(Weak) {} - WeakVH(Value *P) : ValueHandleBase(Weak, P) {} - WeakVH(const WeakVH &RHS) - : ValueHandleBase(Weak, RHS) {} - - Value *operator=(Value *RHS) { - return ValueHandleBase::operator=(RHS); - } - Value *operator=(const ValueHandleBase &RHS) { - return ValueHandleBase::operator=(RHS); - } - - operator Value*() const { - return getValPtr(); - } -}; - -// Specialize simplify_type to allow WeakVH to participate in -// dyn_cast, isa, etc. -template<> struct simplify_type<WeakVH> { - typedef Value* SimpleType; - static SimpleType getSimplifiedValue(WeakVH &WVH) { - return WVH; - } -}; - -/// AssertingVH - This is a Value Handle that points to a value and asserts out -/// if the value is destroyed while the handle is still live. This is very -/// useful for catching dangling pointer bugs and other things which can be -/// non-obvious. One particularly useful place to use this is as the Key of a -/// map. Dangling pointer bugs often lead to really subtle bugs that only occur -/// if another object happens to get allocated to the same address as the old -/// one. Using an AssertingVH ensures that an assert is triggered as soon as -/// the bad delete occurs. -/// -/// Note that an AssertingVH handle does *not* follow values across RAUW -/// operations. This means that RAUW's need to explicitly update the -/// AssertingVH's as it moves. This is required because in non-assert mode this -/// class turns into a trivial wrapper around a pointer. -template <typename ValueTy> -class AssertingVH -#ifndef NDEBUG - : public ValueHandleBase -#endif - { - -#ifndef NDEBUG - ValueTy *getValPtr() const { - return static_cast<ValueTy*>(ValueHandleBase::getValPtr()); - } - void setValPtr(ValueTy *P) { - ValueHandleBase::operator=(GetAsValue(P)); - } -#else - ValueTy *ThePtr; - ValueTy *getValPtr() const { return ThePtr; } - void setValPtr(ValueTy *P) { ThePtr = P; } -#endif - - // Convert a ValueTy*, which may be const, to the type the base - // class expects. - static Value *GetAsValue(Value *V) { return V; } - static Value *GetAsValue(const Value *V) { return const_cast<Value*>(V); } - -public: -#ifndef NDEBUG - AssertingVH() : ValueHandleBase(Assert) {} - AssertingVH(ValueTy *P) : ValueHandleBase(Assert, GetAsValue(P)) {} - AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} -#else - AssertingVH() : ThePtr(0) {} - AssertingVH(ValueTy *P) : ThePtr(P) {} -#endif - - operator ValueTy*() const { - return getValPtr(); - } - - ValueTy *operator=(ValueTy *RHS) { - setValPtr(RHS); - return getValPtr(); - } - ValueTy *operator=(const AssertingVH<ValueTy> &RHS) { - setValPtr(RHS.getValPtr()); - return getValPtr(); - } - - ValueTy *operator->() const { return getValPtr(); } - ValueTy &operator*() const { return *getValPtr(); } -}; - -// Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. -template<typename T> -struct DenseMapInfo<AssertingVH<T> > { - typedef DenseMapInfo<T*> PointerInfo; - static inline AssertingVH<T> getEmptyKey() { - return AssertingVH<T>(PointerInfo::getEmptyKey()); - } - static inline T* getTombstoneKey() { - return AssertingVH<T>(PointerInfo::getTombstoneKey()); - } - static unsigned getHashValue(const AssertingVH<T> &Val) { - return PointerInfo::getHashValue(Val); - } - static bool isEqual(const AssertingVH<T> &LHS, const AssertingVH<T> &RHS) { - return LHS == RHS; - } -}; - -template <typename T> -struct isPodLike<AssertingVH<T> > { -#ifdef NDEBUG - static const bool value = true; -#else - static const bool value = false; -#endif -}; - - -/// TrackingVH - This is a value handle that tracks a Value (or Value subclass), -/// even across RAUW operations. -/// -/// TrackingVH is designed for situations where a client needs to hold a handle -/// to a Value (or subclass) across some operations which may move that value, -/// but should never destroy it or replace it with some unacceptable type. -/// -/// It is an error to do anything with a TrackingVH whose value has been -/// destroyed, except to destruct it. -/// -/// It is an error to attempt to replace a value with one of a type which is -/// incompatible with any of its outstanding TrackingVHs. -template<typename ValueTy> -class TrackingVH : public ValueHandleBase { - void CheckValidity() const { - Value *VP = ValueHandleBase::getValPtr(); - - // Null is always ok. - if (!VP) return; - - // Check that this value is valid (i.e., it hasn't been deleted). We - // explicitly delay this check until access to avoid requiring clients to be - // unnecessarily careful w.r.t. destruction. - assert(ValueHandleBase::isValid(VP) && "Tracked Value was deleted!"); - - // Check that the value is a member of the correct subclass. We would like - // to check this property on assignment for better debugging, but we don't - // want to require a virtual interface on this VH. Instead we allow RAUW to - // replace this value with a value of an invalid type, and check it here. - assert(isa<ValueTy>(VP) && - "Tracked Value was replaced by one with an invalid type!"); - } - - ValueTy *getValPtr() const { - CheckValidity(); - return (ValueTy*)ValueHandleBase::getValPtr(); - } - void setValPtr(ValueTy *P) { - CheckValidity(); - ValueHandleBase::operator=(GetAsValue(P)); - } - - // Convert a ValueTy*, which may be const, to the type the base - // class expects. - static Value *GetAsValue(Value *V) { return V; } - static Value *GetAsValue(const Value *V) { return const_cast<Value*>(V); } - -public: - TrackingVH() : ValueHandleBase(Tracking) {} - TrackingVH(ValueTy *P) : ValueHandleBase(Tracking, GetAsValue(P)) {} - TrackingVH(const TrackingVH &RHS) : ValueHandleBase(Tracking, RHS) {} - - operator ValueTy*() const { - return getValPtr(); - } - - ValueTy *operator=(ValueTy *RHS) { - setValPtr(RHS); - return getValPtr(); - } - ValueTy *operator=(const TrackingVH<ValueTy> &RHS) { - setValPtr(RHS.getValPtr()); - return getValPtr(); - } - - ValueTy *operator->() const { return getValPtr(); } - ValueTy &operator*() const { return *getValPtr(); } -}; - -/// CallbackVH - This is a value handle that allows subclasses to define -/// callbacks that run when the underlying Value has RAUW called on it or is -/// destroyed. This class can be used as the key of a map, as long as the user -/// takes it out of the map before calling setValPtr() (since the map has to -/// rearrange itself when the pointer changes). Unlike ValueHandleBase, this -/// class has a vtable and a virtual destructor. -class CallbackVH : public ValueHandleBase { - virtual void anchor(); -protected: - CallbackVH(const CallbackVH &RHS) - : ValueHandleBase(Callback, RHS) {} - - virtual ~CallbackVH() {} - - void setValPtr(Value *P) { - ValueHandleBase::operator=(P); - } - -public: - CallbackVH() : ValueHandleBase(Callback) {} - CallbackVH(Value *P) : ValueHandleBase(Callback, P) {} - - operator Value*() const { - return getValPtr(); - } - - /// Called when this->getValPtr() is destroyed, inside ~Value(), so you may - /// call any non-virtual Value method on getValPtr(), but no subclass methods. - /// If WeakVH were implemented as a CallbackVH, it would use this method to - /// call setValPtr(NULL). AssertingVH would use this method to cause an - /// assertion failure. - /// - /// All implementations must remove the reference from this object to the - /// Value that's being destroyed. - virtual void deleted() { setValPtr(NULL); } - - /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, - /// _before_ any of the uses have actually been replaced. If WeakVH were - /// implemented as a CallbackVH, it would use this method to call - /// setValPtr(new_value). AssertingVH would do nothing in this method. - virtual void allUsesReplacedWith(Value *) {} -}; - -} // End llvm namespace - -#endif diff --git a/contrib/llvm/include/llvm/Support/Win64EH.h b/contrib/llvm/include/llvm/Support/Win64EH.h index ecce713..7ca218e 100644 --- a/contrib/llvm/include/llvm/Support/Win64EH.h +++ b/contrib/llvm/include/llvm/Support/Win64EH.h @@ -108,17 +108,19 @@ struct UnwindInfo { /// \brief Return pointer to language specific data part of UnwindInfo. const void *getLanguageSpecificData() const { - return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes+1) & ~1]); + return reinterpret_cast<const void *>(&UnwindCodes[(NumCodes + 1) & ~1]); } /// \brief Return image-relative offset of language-specific exception handler. uint32_t getLanguageSpecificHandlerOffset() const { - return *reinterpret_cast<const uint32_t *>(getLanguageSpecificData()); + return *reinterpret_cast<const support::ulittle32_t *>( + getLanguageSpecificData()); } /// \brief Set image-relative offset of language-specific exception handler. void setLanguageSpecificHandlerOffset(uint32_t offset) { - *reinterpret_cast<uint32_t *>(getLanguageSpecificData()) = offset; + *reinterpret_cast<support::ulittle32_t *>(getLanguageSpecificData()) = + offset; } /// \brief Return pointer to exception-specific data. diff --git a/contrib/llvm/include/llvm/Support/WindowsError.h b/contrib/llvm/include/llvm/Support/WindowsError.h new file mode 100644 index 0000000..0e909a0 --- /dev/null +++ b/contrib/llvm/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/contrib/llvm/include/llvm/Support/YAMLParser.h b/contrib/llvm/include/llvm/Support/YAMLParser.h index 7020449..c39874c 100644 --- a/contrib/llvm/include/llvm/Support/YAMLParser.h +++ b/contrib/llvm/include/llvm/Support/YAMLParser.h @@ -38,14 +38,12 @@ #ifndef LLVM_SUPPORT_YAMLPARSER_H #define LLVM_SUPPORT_YAMLPARSER_H -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/SMLoc.h" - -#include <map> #include <limits> +#include <map> #include <utility> namespace llvm { @@ -62,26 +60,26 @@ class Node; class Scanner; struct Token; -/// @brief Dump all the tokens in this stream to OS. -/// @returns true if there was an error, false otherwise. +/// \brief Dump all the tokens in this stream to OS. +/// \returns true if there was an error, false otherwise. bool dumpTokens(StringRef Input, raw_ostream &); -/// @brief Scans all tokens in input without outputting anything. This is used +/// \brief Scans all tokens in input without outputting anything. This is used /// for benchmarking the tokenizer. -/// @returns true if there was an error, false otherwise. +/// \returns true if there was an error, false otherwise. bool scanTokens(StringRef Input); -/// @brief Escape \a Input for a double quoted scalar. +/// \brief Escape \a Input for a double quoted scalar. std::string escape(StringRef Input); -/// @brief This class represents a YAML stream potentially containing multiple +/// \brief This class represents a YAML stream potentially containing multiple /// documents. class Stream { public: - /// @brief This keeps a reference to the string referenced by \p Input. + /// \brief This keeps a reference to the string referenced by \p Input. Stream(StringRef Input, SourceMgr &); - /// @brief This takes ownership of \p InputBuffer. + /// \brief This takes ownership of \p InputBuffer. Stream(MemoryBuffer *InputBuffer, SourceMgr &); ~Stream(); @@ -97,15 +95,16 @@ public: void printError(Node *N, const Twine &Msg); private: - OwningPtr<Scanner> scanner; - OwningPtr<Document> CurrentDoc; + std::unique_ptr<Scanner> scanner; + std::unique_ptr<Document> CurrentDoc; friend class Document; }; -/// @brief Abstract base class for all Nodes. +/// \brief Abstract base class for all Nodes. class Node { - virtual void anchor(); + virtual void anchor(); + public: enum NodeKind { NK_Null, @@ -116,10 +115,10 @@ public: NK_Alias }; - Node(unsigned int Type, OwningPtr<Document> &, StringRef Anchor, + Node(unsigned int Type, std::unique_ptr<Document> &, StringRef Anchor, StringRef Tag); - /// @brief Get the value of the anchor attached to this node. If it does not + /// \brief Get the value of the anchor attached to this node. If it does not /// have one, getAnchor().size() will be 0. StringRef getAnchor() const { return Anchor; } @@ -146,18 +145,17 @@ public: unsigned int getType() const { return TypeID; } - void *operator new ( size_t Size - , BumpPtrAllocator &Alloc - , size_t Alignment = 16) throw() { + void *operator new(size_t Size, BumpPtrAllocator &Alloc, + size_t Alignment = 16) throw() { return Alloc.Allocate(Size, Alignment); } - void operator delete(void *Ptr, BumpPtrAllocator &Alloc, size_t) throw() { - Alloc.Deallocate(Ptr); + void operator delete(void *Ptr, BumpPtrAllocator &Alloc, size_t Size) throw() { + Alloc.Deallocate(Ptr, Size); } protected: - OwningPtr<Document> &Doc; + std::unique_ptr<Document> &Doc; SMRange SourceRange; void operator delete(void *) throw() {} @@ -171,30 +169,30 @@ private: StringRef Tag; }; -/// @brief A null value. +/// \brief A null value. /// /// Example: /// !!null null class NullNode : public Node { - virtual void anchor(); + void anchor() override; + public: - NullNode(OwningPtr<Document> &D) + NullNode(std::unique_ptr<Document> &D) : Node(NK_Null, D, StringRef(), StringRef()) {} - static inline bool classof(const Node *N) { - return N->getType() == NK_Null; - } + static inline bool classof(const Node *N) { return N->getType() == NK_Null; } }; -/// @brief A scalar node is an opaque datum that can be presented as a +/// \brief A scalar node is an opaque datum that can be presented as a /// series of zero or more Unicode scalar values. /// /// Example: /// Adena class ScalarNode : public Node { - virtual void anchor(); + void anchor() override; + public: - ScalarNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, + ScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, StringRef Val) : Node(NK_Scalar, D, Anchor, Tag), Value(Val) { SMLoc Start = SMLoc::getFromPointer(Val.begin()); @@ -207,9 +205,9 @@ public: // utf8). StringRef getRawValue() const { return Value; } - /// @brief Gets the value of this node as a StringRef. + /// \brief Gets the value of this node as a StringRef. /// - /// @param Storage is used to store the content of the returned StringRef iff + /// \param Storage is used to store the content of the returned StringRef iff /// it requires any modification from how it appeared in the source. /// This happens with escaped characters and multi-line literals. StringRef getValue(SmallVectorImpl<char> &Storage) const; @@ -221,12 +219,12 @@ public: private: StringRef Value; - StringRef unescapeDoubleQuoted( StringRef UnquotedValue - , StringRef::size_type Start - , SmallVectorImpl<char> &Storage) const; + StringRef unescapeDoubleQuoted(StringRef UnquotedValue, + StringRef::size_type Start, + SmallVectorImpl<char> &Storage) const; }; -/// @brief A key and value pair. While not technically a Node under the YAML +/// \brief A key and value pair. While not technically a Node under the YAML /// representation graph, it is easier to treat them this way. /// /// TODO: Consider making this not a child of Node. @@ -234,29 +232,28 @@ private: /// Example: /// Section: .text class KeyValueNode : public Node { - virtual void anchor(); + void anchor() override; + public: - KeyValueNode(OwningPtr<Document> &D) - : Node(NK_KeyValue, D, StringRef(), StringRef()) - , Key(0) - , Value(0) - {} + KeyValueNode(std::unique_ptr<Document> &D) + : Node(NK_KeyValue, D, StringRef(), StringRef()), Key(nullptr), + Value(nullptr) {} - /// @brief Parse and return the key. + /// \brief Parse and return the key. /// /// This may be called multiple times. /// - /// @returns The key, or nullptr if failed() == true. + /// \returns The key, or nullptr if failed() == true. Node *getKey(); - /// @brief Parse and return the value. + /// \brief Parse and return the value. /// /// This may be called multiple times. /// - /// @returns The value, or nullptr if failed() == true. + /// \returns The value, or nullptr if failed() == true. Node *getValue(); - virtual void skip() LLVM_OVERRIDE { + void skip() override { getKey()->skip(); getValue()->skip(); } @@ -270,47 +267,47 @@ private: Node *Value; }; -/// @brief This is an iterator abstraction over YAML collections shared by both +/// \brief This is an iterator abstraction over YAML collections shared by both /// sequences and maps. /// /// BaseT must have a ValueT* member named CurrentEntry and a member function /// increment() which must set CurrentEntry to 0 to create an end iterator. template <class BaseT, class ValueT> class basic_collection_iterator - : public std::iterator<std::forward_iterator_tag, ValueT> { + : public std::iterator<std::forward_iterator_tag, ValueT> { public: - basic_collection_iterator() : Base(0) {} + basic_collection_iterator() : Base(nullptr) {} basic_collection_iterator(BaseT *B) : Base(B) {} - ValueT *operator ->() const { + ValueT *operator->() const { assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); return Base->CurrentEntry; } - ValueT &operator *() const { + ValueT &operator*() const { assert(Base && Base->CurrentEntry && "Attempted to dereference end iterator!"); return *Base->CurrentEntry; } - operator ValueT*() const { + operator ValueT *() const { assert(Base && Base->CurrentEntry && "Attempted to access end iterator!"); return Base->CurrentEntry; } - bool operator !=(const basic_collection_iterator &Other) const { - if(Base != Other.Base) + bool operator!=(const basic_collection_iterator &Other) const { + if (Base != Other.Base) return true; - return (Base && Other.Base) && Base->CurrentEntry - != Other.Base->CurrentEntry; + return (Base && Other.Base) && + Base->CurrentEntry != Other.Base->CurrentEntry; } basic_collection_iterator &operator++() { assert(Base && "Attempted to advance iterator past end!"); Base->increment(); // Create an end iterator. - if (Base->CurrentEntry == 0) - Base = 0; + if (!Base->CurrentEntry) + Base = nullptr; return *this; } @@ -328,17 +325,16 @@ typename CollectionType::iterator begin(CollectionType &C) { return ret; } -template <class CollectionType> -void skip(CollectionType &C) { +template <class CollectionType> void skip(CollectionType &C) { // TODO: support skipping from the middle of a parsed collection ;/ assert((C.IsAtBeginning || C.IsAtEnd) && "Cannot skip mid parse!"); if (C.IsAtBeginning) - for (typename CollectionType::iterator i = begin(C), e = C.end(); - i != e; ++i) + for (typename CollectionType::iterator i = begin(C), e = C.end(); i != e; + ++i) i->skip(); } -/// @brief Represents a YAML map created from either a block map for a flow map. +/// \brief Represents a YAML map created from either a block map for a flow map. /// /// This parses the YAML stream as increment() is called. /// @@ -346,7 +342,8 @@ void skip(CollectionType &C) { /// Name: _main /// Scope: Global class MappingNode : public Node { - virtual void anchor(); + void anchor() override; + public: enum MappingType { MT_Block, @@ -354,25 +351,21 @@ public: MT_Inline ///< An inline mapping node is used for "[key: value]". }; - MappingNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, + MappingNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, MappingType MT) : Node(NK_Mapping, D, Anchor, Tag), Type(MT), IsAtBeginning(true), - IsAtEnd(false), CurrentEntry(0) {} + IsAtEnd(false), CurrentEntry(nullptr) {} friend class basic_collection_iterator<MappingNode, KeyValueNode>; typedef basic_collection_iterator<MappingNode, KeyValueNode> iterator; template <class T> friend typename T::iterator yaml::begin(T &); template <class T> friend void yaml::skip(T &); - iterator begin() { - return yaml::begin(*this); - } + iterator begin() { return yaml::begin(*this); } iterator end() { return iterator(); } - virtual void skip() LLVM_OVERRIDE { - yaml::skip(*this); - } + void skip() override { yaml::skip(*this); } static inline bool classof(const Node *N) { return N->getType() == NK_Mapping; @@ -387,7 +380,7 @@ private: void increment(); }; -/// @brief Represents a YAML sequence created from either a block sequence for a +/// \brief Represents a YAML sequence created from either a block sequence for a /// flow sequence. /// /// This parses the YAML stream as increment() is called. @@ -396,7 +389,8 @@ private: /// - Hello /// - World class SequenceNode : public Node { - virtual void anchor(); + void anchor() override; + public: enum SequenceType { ST_Block, @@ -411,12 +405,12 @@ public: ST_Indentless }; - SequenceNode(OwningPtr<Document> &D, StringRef Anchor, StringRef Tag, + SequenceNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, SequenceType ST) : Node(NK_Sequence, D, Anchor, Tag), SeqType(ST), IsAtBeginning(true), IsAtEnd(false), WasPreviousTokenFlowEntry(true), // Start with an imaginary ','. - CurrentEntry(0) {} + CurrentEntry(nullptr) {} friend class basic_collection_iterator<SequenceNode, Node>; typedef basic_collection_iterator<SequenceNode, Node> iterator; @@ -425,15 +419,11 @@ public: void increment(); - iterator begin() { - return yaml::begin(*this); - } + iterator begin() { return yaml::begin(*this); } iterator end() { return iterator(); } - virtual void skip() LLVM_OVERRIDE { - yaml::skip(*this); - } + void skip() override { yaml::skip(*this); } static inline bool classof(const Node *N) { return N->getType() == NK_Sequence; @@ -447,63 +437,60 @@ private: Node *CurrentEntry; }; -/// @brief Represents an alias to a Node with an anchor. +/// \brief Represents an alias to a Node with an anchor. /// /// Example: /// *AnchorName class AliasNode : public Node { - virtual void anchor(); + void anchor() override; + public: - AliasNode(OwningPtr<Document> &D, StringRef Val) - : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} + AliasNode(std::unique_ptr<Document> &D, StringRef Val) + : Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {} StringRef getName() const { return Name; } Node *getTarget(); - static inline bool classof(const Node *N) { - return N->getType() == NK_Alias; - } + static inline bool classof(const Node *N) { return N->getType() == NK_Alias; } private: StringRef Name; }; -/// @brief A YAML Stream is a sequence of Documents. A document contains a root +/// \brief A YAML Stream is a sequence of Documents. A document contains a root /// node. class Document { public: - /// @brief Root for parsing a node. Returns a single node. + /// \brief Root for parsing a node. Returns a single node. Node *parseBlockNode(); Document(Stream &ParentStream); - /// @brief Finish parsing the current document and return true if there are + /// \brief Finish parsing the current document and return true if there are /// more. Return false otherwise. bool skip(); - /// @brief Parse and return the root level node. + /// \brief Parse and return the root level node. Node *getRoot() { if (Root) return Root; return Root = parseBlockNode(); } - const std::map<StringRef, StringRef> &getTagMap() const { - return TagMap; - } + const std::map<StringRef, StringRef> &getTagMap() const { return TagMap; } private: friend class Node; friend class document_iterator; - /// @brief Stream to read tokens from. + /// \brief Stream to read tokens from. Stream &stream; - /// @brief Used to allocate nodes to. All are destroyed without calling their + /// \brief Used to allocate nodes to. All are destroyed without calling their /// destructor when the document is destroyed. BumpPtrAllocator NodeAllocator; - /// @brief The root node. Used to support skipping a partially parsed + /// \brief The root node. Used to support skipping a partially parsed /// document. Node *Root; @@ -515,7 +502,7 @@ private: void setError(const Twine &Message, Token &Location) const; bool failed() const; - /// @brief Parse %BLAH directives and return true if any were encountered. + /// \brief Parse %BLAH directives and return true if any were encountered. bool parseDirectives(); /// \brief Parse %YAML @@ -524,30 +511,28 @@ private: /// \brief Parse %TAG void parseTAGDirective(); - /// @brief Consume the next token and error if it is not \a TK. + /// \brief Consume the next token and error if it is not \a TK. bool expectToken(int TK); }; -/// @brief Iterator abstraction for Documents over a Stream. +/// \brief Iterator abstraction for Documents over a Stream. class document_iterator { public: - document_iterator() : Doc(0) {} - document_iterator(OwningPtr<Document> &D) : Doc(&D) {} + document_iterator() : Doc(nullptr) {} + document_iterator(std::unique_ptr<Document> &D) : Doc(&D) {} - bool operator ==(const document_iterator &Other) { + bool operator==(const document_iterator &Other) { if (isAtEnd() || Other.isAtEnd()) return isAtEnd() && Other.isAtEnd(); return Doc == Other.Doc; } - bool operator !=(const document_iterator &Other) { - return !(*this == Other); - } + bool operator!=(const document_iterator &Other) { return !(*this == Other); } - document_iterator operator ++() { - assert(Doc != 0 && "incrementing iterator past the end."); + document_iterator operator++() { + assert(Doc && "incrementing iterator past the end."); if (!(*Doc)->skip()) { - Doc->reset(0); + Doc->reset(nullptr); } else { Stream &S = (*Doc)->stream; Doc->reset(new Document(S)); @@ -555,23 +540,18 @@ public: return *this; } - Document &operator *() { - return *Doc->get(); - } + Document &operator*() { return *Doc->get(); } - OwningPtr<Document> &operator ->() { - return *Doc; - } + std::unique_ptr<Document> &operator->() { return *Doc; } private: - bool isAtEnd() const { - return !Doc || !*Doc; - } + bool isAtEnd() const { return !Doc || !*Doc; } - OwningPtr<Document> *Doc; + std::unique_ptr<Document> *Doc; }; -} -} +} // End namespace yaml. + +} // End namespace llvm. #endif diff --git a/contrib/llvm/include/llvm/Support/YAMLTraits.h b/contrib/llvm/include/llvm/Support/YAMLTraits.h index c19eb23..a23faf6 100644 --- a/contrib/llvm/include/llvm/Support/YAMLTraits.h +++ b/contrib/llvm/include/llvm/Support/YAMLTraits.h @@ -1,4 +1,4 @@ -//===- llvm/Supporrt/YAMLTraits.h -------------------------------*- C++ -*-===// +//===- llvm/Support/YAMLTraits.h --------------------------------*- C++ -*-===// // // The LLVM Linker // @@ -13,19 +13,18 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Regex.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/YAMLParser.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" -#include "llvm/Support/type_traits.h" - +#include <system_error> namespace llvm { namespace yaml { @@ -34,7 +33,7 @@ namespace yaml { /// This class should be specialized by any type that needs to be converted /// to/from a YAML mapping. For example: /// -/// struct ScalarBitSetTraits<MyStruct> { +/// struct MappingTraits<MyStruct> { /// static void mapping(IO &io, MyStruct &s) { /// io.mapRequired("name", s.name); /// io.mapRequired("size", s.size); @@ -45,6 +44,8 @@ template<class T> struct MappingTraits { // Must provide: // static void mapping(IO &io, T &fields); + // Optionally may provide: + // static StringRef validate(IO &io, T &fields); }; @@ -98,6 +99,7 @@ struct ScalarBitSetTraits { /// // return empty string on success, or error string /// return StringRef(); /// } +/// static bool mustQuote(StringRef) { return true; } /// }; template<typename T> struct ScalarTraits { @@ -109,6 +111,9 @@ struct ScalarTraits { // Function to convert a string to a value. Returns the empty // StringRef on success or an error string if string is malformed: //static StringRef input(StringRef scalar, void *ctxt, T &value); + // + // Function to determine if the value should be quoted. + //static bool mustQuote(StringRef); }; @@ -171,7 +176,8 @@ struct has_ScalarEnumerationTraits static double test(...); public: - static bool const value = (sizeof(test<ScalarEnumerationTraits<T> >(0)) == 1); + static bool const value = + (sizeof(test<ScalarEnumerationTraits<T> >(nullptr)) == 1); }; @@ -188,7 +194,7 @@ struct has_ScalarBitSetTraits static double test(...); public: - static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(0)) == 1); + static bool const value = (sizeof(test<ScalarBitSetTraits<T> >(nullptr)) == 1); }; @@ -198,16 +204,19 @@ struct has_ScalarTraits { typedef StringRef (*Signature_input)(StringRef, void*, T&); typedef void (*Signature_output)(const T&, void*, llvm::raw_ostream&); + typedef bool (*Signature_mustQuote)(StringRef); template <typename U> - static char test(SameType<Signature_input, &U::input>*, - SameType<Signature_output, &U::output>*); + static char test(SameType<Signature_input, &U::input> *, + SameType<Signature_output, &U::output> *, + SameType<Signature_mustQuote, &U::mustQuote> *); template <typename U> static double test(...); public: - static bool const value = (sizeof(test<ScalarTraits<T> >(0,0)) == 1); + static bool const value = + (sizeof(test<ScalarTraits<T>>(nullptr, nullptr, nullptr)) == 1); }; @@ -224,9 +233,26 @@ struct has_MappingTraits static double test(...); public: - static bool const value = (sizeof(test<MappingTraits<T> >(0)) == 1); + static bool const value = (sizeof(test<MappingTraits<T> >(nullptr)) == 1); }; +// Test if MappingTraits<T>::validate() is defined on type T. +template <class T> +struct has_MappingValidateTraits +{ + typedef StringRef (*Signature_validate)(class IO&, T&); + + template <typename U> + static char test(SameType<Signature_validate, &U::validate>*); + + template <typename U> + static double test(...); + +public: + static bool const value = (sizeof(test<MappingTraits<T> >(nullptr)) == 1); +}; + + // Test if SequenceTraits<T> is defined on type T. template <class T> @@ -241,14 +267,14 @@ struct has_SequenceMethodTraits static double test(...); public: - static bool const value = (sizeof(test<SequenceTraits<T> >(0)) == 1); + static bool const value = (sizeof(test<SequenceTraits<T> >(nullptr)) == 1); }; // has_FlowTraits<int> will cause an error with some compilers because // it subclasses int. Using this wrapper only instantiates the // real has_FlowTraits only if the template type is a class. -template <typename T, bool Enabled = llvm::is_class<T>::value> +template <typename T, bool Enabled = std::is_class<T>::value> class has_FlowTraits { public: @@ -271,14 +297,14 @@ struct has_FlowTraits<T, true> static char (&f(...))[2]; public: - static bool const value = sizeof(f<Derived>(0)) == 2; + static bool const value = sizeof(f<Derived>(nullptr)) == 2; }; // Test if SequenceTraits<T> is defined on type T template<typename T> -struct has_SequenceTraits : public llvm::integral_constant<bool, +struct has_SequenceTraits : public std::integral_constant<bool, has_SequenceMethodTraits<T>::value > { }; @@ -295,14 +321,88 @@ struct has_DocumentListTraits static double test(...); public: - static bool const value = (sizeof(test<DocumentListTraits<T> >(0)) == 1); + static bool const value = (sizeof(test<DocumentListTraits<T> >(nullptr))==1); }; +inline bool isNumber(StringRef S) { + static const char OctalChars[] = "01234567"; + if (S.startswith("0") && + S.drop_front().find_first_not_of(OctalChars) == StringRef::npos) + return true; + + if (S.startswith("0o") && + S.drop_front(2).find_first_not_of(OctalChars) == StringRef::npos) + return true; + + static const char HexChars[] = "0123456789abcdefABCDEF"; + if (S.startswith("0x") && + S.drop_front(2).find_first_not_of(HexChars) == StringRef::npos) + return true; + + static const char DecChars[] = "0123456789"; + if (S.find_first_not_of(DecChars) == StringRef::npos) + return true; + if (S.equals(".inf") || S.equals(".Inf") || S.equals(".INF")) + return true; + + Regex FloatMatcher("^(\\.[0-9]+|[0-9]+(\\.[0-9]*)?)([eE][-+]?[0-9]+)?$"); + if (FloatMatcher.match(S)) + return true; + + return false; +} + +inline bool isNumeric(StringRef S) { + if ((S.front() == '-' || S.front() == '+') && isNumber(S.drop_front())) + return true; + + if (isNumber(S)) + return true; + + if (S.equals(".nan") || S.equals(".NaN") || S.equals(".NAN")) + return true; + + return false; +} + +inline bool isNull(StringRef S) { + return S.equals("null") || S.equals("Null") || S.equals("NULL") || + S.equals("~"); +} + +inline bool isBool(StringRef S) { + return S.equals("true") || S.equals("True") || S.equals("TRUE") || + S.equals("false") || S.equals("False") || S.equals("FALSE"); +} + +inline bool needsQuotes(StringRef S) { + if (S.empty()) + return true; + if (isspace(S.front()) || isspace(S.back())) + return true; + if (S.front() == ',') + return true; + + static const char ScalarSafeChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-/^., \t"; + if (S.find_first_not_of(ScalarSafeChars) != StringRef::npos) + return true; + + if (isNull(S)) + return true; + if (isBool(S)) + return true; + if (isNumeric(S)) + return true; + + return false; +} template<typename T> -struct missingTraits : public llvm::integral_constant<bool, +struct missingTraits : public std::integral_constant<bool, !has_ScalarEnumerationTraits<T>::value && !has_ScalarBitSetTraits<T>::value && !has_ScalarTraits<T>::value @@ -310,15 +410,23 @@ struct missingTraits : public llvm::integral_constant<bool, && !has_SequenceTraits<T>::value && !has_DocumentListTraits<T>::value > {}; +template<typename T> +struct validatedMappingTraits : public std::integral_constant<bool, + has_MappingTraits<T>::value + && has_MappingValidateTraits<T>::value> {}; +template<typename T> +struct unvalidatedMappingTraits : public std::integral_constant<bool, + has_MappingTraits<T>::value + && !has_MappingValidateTraits<T>::value> {}; // Base class for Input and Output. class IO { public: - IO(void *Ctxt=NULL); + IO(void *Ctxt=nullptr); virtual ~IO(); - virtual bool outputting() const = 0; + virtual bool outputting() = 0; virtual unsigned beginSequence() = 0; virtual bool preflightElement(unsigned, void *&) = 0; @@ -345,7 +453,7 @@ public: virtual bool bitSetMatch(const char*, bool) = 0; virtual void endBitSetScalar() = 0; - virtual void scalarString(StringRef &) = 0; + virtual void scalarString(StringRef &, bool) = 0; virtual void setError(const Twine &) = 0; @@ -379,6 +487,19 @@ public: } } + template <typename T> + void maskedBitSetCase(T &Val, const char *Str, T ConstVal, T Mask) { + if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) + Val = Val | ConstVal; + } + + template <typename T> + void maskedBitSetCase(T &Val, const char *Str, uint32_t ConstVal, + uint32_t Mask) { + if (bitSetMatch(Str, outputting() && (Val & Mask) == ConstVal)) + Val = Val | ConstVal; + } + void *getContext(); void setContext(void *); @@ -388,7 +509,7 @@ public: } template <typename T> - typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type + typename std::enable_if<has_SequenceTraits<T>::value,void>::type mapOptional(const char* Key, T& Val) { // omit key/value instead of outputting empty sequence if ( this->canElideEmptySequence() && !(Val.begin() != Val.end()) ) @@ -397,7 +518,12 @@ public: } template <typename T> - typename llvm::enable_if_c<!has_SequenceTraits<T>::value,void>::type + void mapOptional(const char* Key, Optional<T> &Val) { + processKeyWithDefault(Key, Val, Optional<T>(), /*Required=*/false); + } + + template <typename T> + typename std::enable_if<!has_SequenceTraits<T>::value,void>::type mapOptional(const char* Key, T& Val) { this->processKey(Key, Val, false); } @@ -409,6 +535,26 @@ public: private: template <typename T> + void processKeyWithDefault(const char *Key, Optional<T> &Val, + const Optional<T> &DefaultValue, bool Required) { + assert(DefaultValue.hasValue() == false && + "Optional<T> shouldn't have a value!"); + void *SaveInfo; + bool UseDefault; + const bool sameAsDefault = outputting() && !Val.hasValue(); + if (!outputting() && !Val.hasValue()) + Val = T(); + if (this->preflightKey(Key, Required, sameAsDefault, UseDefault, + SaveInfo)) { + yamlize(*this, Val.getValue(), Required); + this->postflightKey(SaveInfo); + } else { + if (UseDefault) + Val = DefaultValue; + } + } + + template <typename T> void processKeyWithDefault(const char *Key, T &Val, const T& DefaultValue, bool Required) { void *SaveInfo; @@ -442,7 +588,7 @@ private: template<typename T> -typename llvm::enable_if_c<has_ScalarEnumerationTraits<T>::value,void>::type +typename std::enable_if<has_ScalarEnumerationTraits<T>::value,void>::type yamlize(IO &io, T &Val, bool) { io.beginEnumScalar(); ScalarEnumerationTraits<T>::enumeration(io, Val); @@ -450,7 +596,7 @@ yamlize(IO &io, T &Val, bool) { } template<typename T> -typename llvm::enable_if_c<has_ScalarBitSetTraits<T>::value,void>::type +typename std::enable_if<has_ScalarBitSetTraits<T>::value,void>::type yamlize(IO &io, T &Val, bool) { bool DoClear; if ( io.beginBitSetScalar(DoClear) ) { @@ -463,18 +609,18 @@ yamlize(IO &io, T &Val, bool) { template<typename T> -typename llvm::enable_if_c<has_ScalarTraits<T>::value,void>::type +typename std::enable_if<has_ScalarTraits<T>::value,void>::type yamlize(IO &io, T &Val, bool) { if ( io.outputting() ) { std::string Storage; llvm::raw_string_ostream Buffer(Storage); ScalarTraits<T>::output(Val, io.getContext(), Buffer); StringRef Str = Buffer.str(); - io.scalarString(Str); + io.scalarString(Str, ScalarTraits<T>::mustQuote(Str)); } else { StringRef Str; - io.scalarString(Str); + io.scalarString(Str, ScalarTraits<T>::mustQuote(Str)); StringRef Result = ScalarTraits<T>::input(Str, io.getContext(), Val); if ( !Result.empty() ) { io.setError(llvm::Twine(Result)); @@ -484,21 +630,41 @@ yamlize(IO &io, T &Val, bool) { template<typename T> -typename llvm::enable_if_c<has_MappingTraits<T>::value, void>::type +typename std::enable_if<validatedMappingTraits<T>::value, void>::type yamlize(IO &io, T &Val, bool) { io.beginMapping(); + if (io.outputting()) { + StringRef Err = MappingTraits<T>::validate(io, Val); + if (!Err.empty()) { + llvm::errs() << Err << "\n"; + assert(Err.empty() && "invalid struct trying to be written as yaml"); + } + } MappingTraits<T>::mapping(io, Val); + if (!io.outputting()) { + StringRef Err = MappingTraits<T>::validate(io, Val); + if (!Err.empty()) + io.setError(Err); + } io.endMapping(); } template<typename T> -typename llvm::enable_if_c<missingTraits<T>::value, void>::type +typename std::enable_if<unvalidatedMappingTraits<T>::value, void>::type +yamlize(IO &io, T &Val, bool) { + io.beginMapping(); + MappingTraits<T>::mapping(io, Val); + io.endMapping(); +} + +template<typename T> +typename std::enable_if<missingTraits<T>::value, void>::type yamlize(IO &io, T &Val, bool) { char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; } template<typename T> -typename llvm::enable_if_c<has_SequenceTraits<T>::value,void>::type +typename std::enable_if<has_SequenceTraits<T>::value,void>::type yamlize(IO &io, T &Seq, bool) { if ( has_FlowTraits< SequenceTraits<T> >::value ) { unsigned incnt = io.beginFlowSequence(); @@ -531,72 +697,91 @@ template<> struct ScalarTraits<bool> { static void output(const bool &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, bool &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<StringRef> { static void output(const StringRef &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, StringRef &); + static bool mustQuote(StringRef S) { return needsQuotes(S); } +}; + +template<> +struct ScalarTraits<std::string> { + static void output(const std::string &, void*, llvm::raw_ostream &); + static StringRef input(StringRef, void*, std::string &); + static bool mustQuote(StringRef S) { return needsQuotes(S); } }; template<> struct ScalarTraits<uint8_t> { static void output(const uint8_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, uint8_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<uint16_t> { static void output(const uint16_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, uint16_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<uint32_t> { static void output(const uint32_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, uint32_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<uint64_t> { static void output(const uint64_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, uint64_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<int8_t> { static void output(const int8_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, int8_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<int16_t> { static void output(const int16_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, int16_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<int32_t> { static void output(const int32_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, int32_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<int64_t> { static void output(const int64_t &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, int64_t &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<float> { static void output(const float &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, float &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<double> { static void output(const double &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, double &); + static bool mustQuote(StringRef) { return false; } }; @@ -606,7 +791,7 @@ struct ScalarTraits<double> { template <typename TNorm, typename TFinal> struct MappingNormalization { MappingNormalization(IO &i_o, TFinal &Obj) - : io(i_o), BufPtr(NULL), Result(Obj) { + : io(i_o), BufPtr(nullptr), Result(Obj) { if ( io.outputting() ) { BufPtr = new (&Buffer) TNorm(io, Obj); } @@ -689,40 +874,38 @@ public: // user-data. The DiagHandler can be specified to provide // alternative error reporting. Input(StringRef InputContent, - void *Ctxt = NULL, - SourceMgr::DiagHandlerTy DiagHandler = NULL, - void *DiagHandlerCtxt = NULL); + void *Ctxt = nullptr, + SourceMgr::DiagHandlerTy DiagHandler = nullptr, + void *DiagHandlerCtxt = nullptr); ~Input(); // Check if there was an syntax or semantic error during parsing. - llvm::error_code error(); - - static bool classof(const IO *io) { return !io->outputting(); } + std::error_code error(); private: - virtual bool outputting() const; - virtual bool mapTag(StringRef, bool); - virtual void beginMapping(); - virtual void endMapping(); - virtual bool preflightKey(const char *, bool, bool, bool &, void *&); - virtual void postflightKey(void *); - virtual unsigned beginSequence(); - virtual void endSequence(); - virtual bool preflightElement(unsigned index, void *&); - virtual void postflightElement(void *); - virtual unsigned beginFlowSequence(); - virtual bool preflightFlowElement(unsigned , void *&); - virtual void postflightFlowElement(void *); - virtual void endFlowSequence(); - virtual void beginEnumScalar(); - virtual bool matchEnumScalar(const char*, bool); - virtual void endEnumScalar(); - virtual bool beginBitSetScalar(bool &); - virtual bool bitSetMatch(const char *, bool ); - virtual void endBitSetScalar(); - virtual void scalarString(StringRef &); - virtual void setError(const Twine &message); - virtual bool canElideEmptySequence(); + bool outputting() override; + bool mapTag(StringRef, bool) override; + void beginMapping() override; + void endMapping() override; + bool preflightKey(const char *, bool, bool, bool &, void *&) override; + void postflightKey(void *) override; + unsigned beginSequence() override; + void endSequence() override; + bool preflightElement(unsigned index, void *&) override; + void postflightElement(void *) override; + unsigned beginFlowSequence() override; + bool preflightFlowElement(unsigned , void *&) override; + void postflightFlowElement(void *) override; + void endFlowSequence() override; + void beginEnumScalar() override; + bool matchEnumScalar(const char*, bool) override; + void endEnumScalar() override; + bool beginBitSetScalar(bool &) override; + bool bitSetMatch(const char *, bool ) override; + void endBitSetScalar() override; + void scalarString(StringRef &, bool) override; + void setError(const Twine &message) override; + bool canElideEmptySequence() override; class HNode { virtual void anchor(); @@ -735,7 +918,7 @@ private: }; class EmptyHNode : public HNode { - virtual void anchor(); + void anchor() override; public: EmptyHNode(Node *n) : HNode(n) { } static inline bool classof(const HNode *n) { @@ -745,7 +928,7 @@ private: }; class ScalarHNode : public HNode { - virtual void anchor(); + void anchor() override; public: ScalarHNode(Node *n, StringRef s) : HNode(n), _value(s) { } @@ -799,18 +982,18 @@ 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 - OwningPtr<llvm::yaml::Stream> Strm; - OwningPtr<HNode> TopNode; - llvm::error_code EC; - llvm::BumpPtrAllocator StringAllocator; - llvm::yaml::document_iterator DocIterator; - std::vector<bool> BitValuesUsed; - HNode *CurrentNode; - bool ScalarMatchFound; + llvm::SourceMgr SrcMgr; // must be before Strm + std::unique_ptr<llvm::yaml::Stream> Strm; + std::unique_ptr<HNode> TopNode; + std::error_code EC; + llvm::BumpPtrAllocator StringAllocator; + llvm::yaml::document_iterator DocIterator; + std::vector<bool> BitValuesUsed; + HNode *CurrentNode; + bool ScalarMatchFound; }; @@ -822,34 +1005,32 @@ private: /// class Output : public IO { public: - Output(llvm::raw_ostream &, void *Ctxt=NULL); + Output(llvm::raw_ostream &, void *Ctxt=nullptr); virtual ~Output(); - static bool classof(const IO *io) { return io->outputting(); } - - virtual bool outputting() const; - virtual bool mapTag(StringRef, bool); - virtual void beginMapping(); - virtual void endMapping(); - virtual bool preflightKey(const char *key, bool, bool, bool &, void *&); - virtual void postflightKey(void *); - virtual unsigned beginSequence(); - virtual void endSequence(); - virtual bool preflightElement(unsigned, void *&); - virtual void postflightElement(void *); - virtual unsigned beginFlowSequence(); - virtual bool preflightFlowElement(unsigned, void *&); - virtual void postflightFlowElement(void *); - virtual void endFlowSequence(); - virtual void beginEnumScalar(); - virtual bool matchEnumScalar(const char*, bool); - virtual void endEnumScalar(); - virtual bool beginBitSetScalar(bool &); - virtual bool bitSetMatch(const char *, bool ); - virtual void endBitSetScalar(); - virtual void scalarString(StringRef &); - virtual void setError(const Twine &message); - virtual bool canElideEmptySequence(); + bool outputting() override; + bool mapTag(StringRef, bool) override; + void beginMapping() override; + void endMapping() override; + bool preflightKey(const char *key, bool, bool, bool &, void *&) override; + void postflightKey(void *) override; + unsigned beginSequence() override; + void endSequence() override; + bool preflightElement(unsigned, void *&) override; + void postflightElement(void *) override; + unsigned beginFlowSequence() override; + bool preflightFlowElement(unsigned, void *&) override; + void postflightFlowElement(void *) override; + void endFlowSequence() override; + void beginEnumScalar() override; + bool matchEnumScalar(const char*, bool) override; + void endEnumScalar() override; + bool beginBitSetScalar(bool &) override; + bool bitSetMatch(const char *, bool ) override; + void endBitSetScalar() override; + void scalarString(StringRef &, bool) override; + void setError(const Twine &message) override; + bool canElideEmptySequence() override; public: // These are only used by operator<<. They could be private // if that templated operator could be made a friend. @@ -918,31 +1099,35 @@ template<> struct ScalarTraits<Hex8> { static void output(const Hex8 &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, Hex8 &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<Hex16> { static void output(const Hex16 &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, Hex16 &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<Hex32> { static void output(const Hex32 &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, Hex32 &); + static bool mustQuote(StringRef) { return false; } }; template<> struct ScalarTraits<Hex64> { static void output(const Hex64 &, void*, llvm::raw_ostream &); static StringRef input(StringRef, void*, Hex64 &); + static bool mustQuote(StringRef) { return false; } }; // Define non-member operator>> so that Input can stream in a document list. template <typename T> inline -typename llvm::enable_if_c<has_DocumentListTraits<T>::value,Input &>::type +typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type operator>>(Input &yin, T &docList) { int i = 0; while ( yin.setCurrentDocument() ) { @@ -958,7 +1143,7 @@ operator>>(Input &yin, T &docList) { // Define non-member operator>> so that Input can stream in a map as a document. template <typename T> inline -typename llvm::enable_if_c<has_MappingTraits<T>::value,Input &>::type +typename std::enable_if<has_MappingTraits<T>::value, Input &>::type operator>>(Input &yin, T &docMap) { yin.setCurrentDocument(); yamlize(yin, docMap, true); @@ -969,7 +1154,7 @@ operator>>(Input &yin, T &docMap) { // a document. template <typename T> inline -typename llvm::enable_if_c<has_SequenceTraits<T>::value,Input &>::type +typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type operator>>(Input &yin, T &docSeq) { if (yin.setCurrentDocument()) yamlize(yin, docSeq, true); @@ -979,7 +1164,7 @@ operator>>(Input &yin, T &docSeq) { // Provide better error message about types missing a trait specialization template <typename T> inline -typename llvm::enable_if_c<missingTraits<T>::value,Input &>::type +typename std::enable_if<missingTraits<T>::value, Input &>::type operator>>(Input &yin, T &docSeq) { char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; return yin; @@ -989,7 +1174,7 @@ operator>>(Input &yin, T &docSeq) { // Define non-member operator<< so that Output can stream out document list. template <typename T> inline -typename llvm::enable_if_c<has_DocumentListTraits<T>::value,Output &>::type +typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type operator<<(Output &yout, T &docList) { yout.beginDocuments(); const size_t count = DocumentListTraits<T>::size(yout, docList); @@ -1006,7 +1191,7 @@ operator<<(Output &yout, T &docList) { // Define non-member operator<< so that Output can stream out a map. template <typename T> inline -typename llvm::enable_if_c<has_MappingTraits<T>::value,Output &>::type +typename std::enable_if<has_MappingTraits<T>::value, Output &>::type operator<<(Output &yout, T &map) { yout.beginDocuments(); if ( yout.preflightDocument(0) ) { @@ -1020,7 +1205,7 @@ operator<<(Output &yout, T &map) { // Define non-member operator<< so that Output can stream out a sequence. template <typename T> inline -typename llvm::enable_if_c<has_SequenceTraits<T>::value,Output &>::type +typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type operator<<(Output &yout, T &seq) { yout.beginDocuments(); if ( yout.preflightDocument(0) ) { @@ -1034,7 +1219,7 @@ operator<<(Output &yout, T &seq) { // Provide better error message about types missing a trait specialization template <typename T> inline -typename llvm::enable_if_c<missingTraits<T>::value,Output &>::type +typename std::enable_if<missingTraits<T>::value, Output &>::type operator<<(Output &yout, T &seq) { char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; return yout; @@ -1075,6 +1260,7 @@ operator<<(Output &yout, T &seq) { return seq.size(); \ } \ static _type& element(IO &io, std::vector<_type> &seq, size_t index) {\ + (void)flow; /* Remove this workaround after PR17897 is fixed */ \ if ( index >= seq.size() ) \ seq.resize(index+1); \ return seq[index]; \ diff --git a/contrib/llvm/include/llvm/Support/circular_raw_ostream.h b/contrib/llvm/include/llvm/Support/circular_raw_ostream.h index 9000306..ee7b89f 100644 --- a/contrib/llvm/include/llvm/Support/circular_raw_ostream.h +++ b/contrib/llvm/include/llvm/Support/circular_raw_ostream.h @@ -81,12 +81,12 @@ namespace llvm Filled = false; } - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, /// not counting the bytes currently in the buffer. /// - virtual uint64_t current_pos() const LLVM_OVERRIDE { + uint64_t current_pos() const override { // This has the same effect as calling TheStream.current_pos(), // but that interface is private. return TheStream->tell() - TheStream->GetNumBytesInBuffer(); @@ -109,10 +109,10 @@ namespace llvm circular_raw_ostream(raw_ostream &Stream, const char *Header, size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) : raw_ostream(/*unbuffered*/true), - TheStream(0), + TheStream(nullptr), OwnsStream(Owns), BufferSize(BuffSize), - BufferArray(0), + BufferArray(nullptr), Filled(false), Banner(Header) { if (BufferSize != 0) @@ -122,9 +122,9 @@ namespace llvm } explicit circular_raw_ostream() : raw_ostream(/*unbuffered*/true), - TheStream(0), + TheStream(nullptr), OwnsStream(REFERENCE_ONLY), - BufferArray(0), + BufferArray(nullptr), Filled(false), Banner("") { Cur = BufferArray; diff --git a/contrib/llvm/include/llvm/Support/raw_os_ostream.h b/contrib/llvm/include/llvm/Support/raw_os_ostream.h index 4385721..04cf3b6 100644 --- a/contrib/llvm/include/llvm/Support/raw_os_ostream.h +++ b/contrib/llvm/include/llvm/Support/raw_os_ostream.h @@ -26,11 +26,11 @@ class raw_os_ostream : public raw_ostream { std::ostream &OS; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE; + uint64_t current_pos() const override; public: raw_os_ostream(std::ostream &O) : OS(O) {} diff --git a/contrib/llvm/include/llvm/Support/raw_ostream.h b/contrib/llvm/include/llvm/Support/raw_ostream.h index ec7e06b..34fbe08 100644 --- a/contrib/llvm/include/llvm/Support/raw_ostream.h +++ b/contrib/llvm/include/llvm/Support/raw_ostream.h @@ -17,13 +17,18 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/FileSystem.h" namespace llvm { class format_object_base; template <typename T> class SmallVectorImpl; + namespace sys { + namespace fs { + enum OpenFlags : unsigned; + } + } + /// raw_ostream - This class implements an extremely fast bulk output stream /// that can *only* output to a stream. It does not support seeking, reopening, /// rewinding, line buffered disciplines etc. It is a simple buffer that outputs @@ -76,7 +81,7 @@ public: explicit raw_ostream(bool unbuffered=false) : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { // Start out ready to flush. - OutBufStart = OutBufEnd = OutBufCur = 0; + OutBufStart = OutBufEnd = OutBufCur = nullptr; } virtual ~raw_ostream(); @@ -102,7 +107,7 @@ public: size_t GetBufferSize() const { // If we're supposed to be buffered but haven't actually gotten around // to allocating the buffer yet, return the value that would be used. - if (BufferMode != Unbuffered && OutBufStart == 0) + if (BufferMode != Unbuffered && OutBufStart == nullptr) return preferred_buffer_size(); // Otherwise just return the size of the allocated buffer. @@ -115,7 +120,7 @@ public: /// set to unbuffered. void SetUnbuffered() { flush(); - SetBufferAndMode(0, 0, Unbuffered); + SetBufferAndMode(nullptr, 0, Unbuffered); } size_t GetNumBytesInBuffer() const { @@ -157,7 +162,7 @@ public: size_t Size = Str.size(); // Make sure we can use the fast path. - if (OutBufCur+Size > OutBufEnd) + if (Size > (size_t)(OutBufEnd - OutBufCur)) return write(Str.data(), Size); memcpy(OutBufCur, Str.data(), Size); @@ -322,14 +327,14 @@ class raw_fd_ostream : public raw_ostream { uint64_t pos; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE { return pos; } + uint64_t current_pos() const override { return pos; } /// preferred_buffer_size - Determine an efficient buffer size. - virtual size_t preferred_buffer_size() const LLVM_OVERRIDE; + size_t preferred_buffer_size() const override; /// error_detected - Set the flag indicating that an output error has /// been encountered. @@ -347,7 +352,7 @@ public: /// file descriptor when it is done (this is necessary to detect /// output errors). raw_fd_ostream(const char *Filename, std::string &ErrorInfo, - sys::fs::OpenFlags Flags = sys::fs::F_None); + sys::fs::OpenFlags Flags); /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If /// ShouldClose is true, this closes the file when the stream is destroyed. @@ -373,15 +378,15 @@ public: UseAtomicWrites = Value; } - virtual raw_ostream &changeColor(enum Colors colors, bool bold=false, - bool bg=false) LLVM_OVERRIDE; - virtual raw_ostream &resetColor() LLVM_OVERRIDE; + raw_ostream &changeColor(enum Colors colors, bool bold=false, + bool bg=false) override; + raw_ostream &resetColor() override; - virtual raw_ostream &reverseColor() LLVM_OVERRIDE; + raw_ostream &reverseColor() override; - virtual bool is_displayed() const LLVM_OVERRIDE; + bool is_displayed() const override; - virtual bool has_colors() const LLVM_OVERRIDE; + bool has_colors() const override; /// has_error - Return the value of the flag in this raw_fd_ostream indicating /// whether an output error has been encountered. @@ -427,11 +432,11 @@ class raw_string_ostream : public raw_ostream { std::string &OS; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE { return OS.size(); } + uint64_t current_pos() const override { return OS.size(); } public: explicit raw_string_ostream(std::string &O) : OS(O) {} ~raw_string_ostream(); @@ -451,11 +456,11 @@ class raw_svector_ostream : public raw_ostream { SmallVectorImpl<char> &OS; /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t Size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t Size) override; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE; + uint64_t current_pos() const override; public: /// Construct a new raw_svector_ostream. /// @@ -477,11 +482,11 @@ public: /// raw_null_ostream - A raw_ostream that discards all output. class raw_null_ostream : public raw_ostream { /// write_impl - See raw_ostream::write_impl. - virtual void write_impl(const char *Ptr, size_t size) LLVM_OVERRIDE; + void write_impl(const char *Ptr, size_t size) override; /// current_pos - Return the current position within the stream, not /// counting the bytes currently in the buffer. - virtual uint64_t current_pos() const LLVM_OVERRIDE; + uint64_t current_pos() const override; public: explicit raw_null_ostream() {} diff --git a/contrib/llvm/include/llvm/Support/system_error.h b/contrib/llvm/include/llvm/Support/system_error.h deleted file mode 100644 index 43dace6..0000000 --- a/contrib/llvm/include/llvm/Support/system_error.h +++ /dev/null @@ -1,905 +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 false_type {}; - -template <class T> struct is_error_condition_enum - : public false_type {}; - -class error_code -{ -public: - // constructors: - error_code(); - error_code(int val, const error_category& cat); - template <class ErrorCodeEnum> - error_code(ErrorCodeEnum e); - - // modifiers: - void assign(int val, const error_category& cat); - template <class ErrorCodeEnum> - error_code& operator=(ErrorCodeEnum e); - void clear(); - - // observers: - int value() const; - const error_category& category() const; - error_condition default_error_condition() const; - std::string message() const; - explicit operator bool() const; -}; - -// non-member functions: -bool operator<(const error_code& lhs, const error_code& rhs); -template <class charT, class traits> - basic_ostream<charT,traits>& - operator<<(basic_ostream<charT,traits>& os, const error_code& ec); - -class error_condition -{ -public: - // constructors: - error_condition(); - error_condition(int val, const error_category& cat); - template <class ErrorConditionEnum> - error_condition(ErrorConditionEnum e); - - // modifiers: - void assign(int val, const error_category& cat); - template <class ErrorConditionEnum> - error_condition& operator=(ErrorConditionEnum e); - void clear(); - - // observers: - int value() const; - const error_category& category() const; - std::string message() const; - explicit operator bool() const; -}; - -bool operator<(const error_condition& lhs, const error_condition& rhs); - -class system_error - : public runtime_error -{ -public: - system_error(error_code ec, const std::string& what_arg); - system_error(error_code ec, const char* what_arg); - system_error(error_code ec); - system_error(int ev, const error_category& ecat, const std::string& what_arg); - system_error(int ev, const error_category& ecat, const char* what_arg); - system_error(int ev, const error_category& ecat); - - const error_code& code() const throw(); - const char* what() const throw(); -}; - -enum class errc -{ - address_family_not_supported, // EAFNOSUPPORT - address_in_use, // EADDRINUSE - address_not_available, // EADDRNOTAVAIL - already_connected, // EISCONN - argument_list_too_long, // E2BIG - argument_out_of_domain, // EDOM - bad_address, // EFAULT - bad_file_descriptor, // EBADF - bad_message, // EBADMSG - broken_pipe, // EPIPE - connection_aborted, // ECONNABORTED - connection_already_in_progress, // EALREADY - connection_refused, // ECONNREFUSED - connection_reset, // ECONNRESET - cross_device_link, // EXDEV - destination_address_required, // EDESTADDRREQ - device_or_resource_busy, // EBUSY - directory_not_empty, // ENOTEMPTY - executable_format_error, // ENOEXEC - file_exists, // EEXIST - file_too_large, // EFBIG - filename_too_long, // ENAMETOOLONG - function_not_supported, // ENOSYS - host_unreachable, // EHOSTUNREACH - identifier_removed, // EIDRM - illegal_byte_sequence, // EILSEQ - inappropriate_io_control_operation, // ENOTTY - interrupted, // EINTR - invalid_argument, // EINVAL - invalid_seek, // ESPIPE - io_error, // EIO - is_a_directory, // EISDIR - message_size, // EMSGSIZE - network_down, // ENETDOWN - network_reset, // ENETRESET - network_unreachable, // ENETUNREACH - no_buffer_space, // ENOBUFS - no_child_process, // ECHILD - no_link, // ENOLINK - no_lock_available, // ENOLCK - no_message_available, // ENODATA - no_message, // ENOMSG - no_protocol_option, // ENOPROTOOPT - no_space_on_device, // ENOSPC - no_stream_resources, // ENOSR - no_such_device_or_address, // ENXIO - no_such_device, // ENODEV - no_such_file_or_directory, // ENOENT - no_such_process, // ESRCH - not_a_directory, // ENOTDIR - not_a_socket, // ENOTSOCK - not_a_stream, // ENOSTR - not_connected, // ENOTCONN - not_enough_memory, // ENOMEM - not_supported, // ENOTSUP - operation_canceled, // ECANCELED - operation_in_progress, // EINPROGRESS - operation_not_permitted, // EPERM - operation_not_supported, // EOPNOTSUPP - operation_would_block, // EWOULDBLOCK - owner_dead, // EOWNERDEAD - permission_denied, // EACCES - protocol_error, // EPROTO - protocol_not_supported, // EPROTONOSUPPORT - read_only_file_system, // EROFS - resource_deadlock_would_occur, // EDEADLK - resource_unavailable_try_again, // EAGAIN - result_out_of_range, // ERANGE - state_not_recoverable, // ENOTRECOVERABLE - stream_timeout, // ETIME - text_file_busy, // ETXTBSY - timed_out, // ETIMEDOUT - too_many_files_open_in_system, // ENFILE - too_many_files_open, // EMFILE - too_many_links, // EMLINK - too_many_symbolic_link_levels, // ELOOP - value_too_large, // EOVERFLOW - wrong_protocol_type // EPROTOTYPE -}; - -template <> struct is_error_condition_enum<errc> : true_type { } - -error_code make_error_code(errc e); -error_condition make_error_condition(errc e); - -// Comparison operators: -bool operator==(const error_code& lhs, const error_code& rhs); -bool operator==(const error_code& lhs, const error_condition& rhs); -bool operator==(const error_condition& lhs, const error_code& rhs); -bool operator==(const error_condition& lhs, const error_condition& rhs); -bool operator!=(const error_code& lhs, const error_code& rhs); -bool operator!=(const error_code& lhs, const error_condition& rhs); -bool operator!=(const error_condition& lhs, const error_code& rhs); -bool operator!=(const error_condition& lhs, const error_condition& rhs); - -template <> struct hash<std::error_code>; - -} // std - -*/ - -#include "llvm/Config/llvm-config.h" -#include "llvm/Support/type_traits.h" -#include <cerrno> -#include <string> - -// This must be here instead of a .inc file because it is used in the definition -// of the enum values below. -#ifdef LLVM_ON_WIN32 - - // The following numbers were taken from VS2010. -# ifndef EAFNOSUPPORT -# define EAFNOSUPPORT 102 -# endif -# ifndef EADDRINUSE -# define EADDRINUSE 100 -# endif -# ifndef EADDRNOTAVAIL -# define EADDRNOTAVAIL 101 -# endif -# ifndef EISCONN -# define EISCONN 113 -# endif -# ifndef E2BIG -# define E2BIG 7 -# endif -# ifndef EDOM -# define EDOM 33 -# endif -# ifndef EFAULT -# define EFAULT 14 -# endif -# ifndef EBADF -# define EBADF 9 -# endif -# ifndef EBADMSG -# define EBADMSG 104 -# endif -# ifndef EPIPE -# define EPIPE 32 -# endif -# ifndef ECONNABORTED -# define ECONNABORTED 106 -# endif -# ifndef EALREADY -# define EALREADY 103 -# endif -# ifndef ECONNREFUSED -# define ECONNREFUSED 107 -# endif -# ifndef ECONNRESET -# define ECONNRESET 108 -# endif -# ifndef EXDEV -# define EXDEV 18 -# endif -# ifndef EDESTADDRREQ -# define EDESTADDRREQ 109 -# endif -# ifndef EBUSY -# define EBUSY 16 -# endif -# ifndef ENOTEMPTY -# define ENOTEMPTY 41 -# endif -# ifndef ENOEXEC -# define ENOEXEC 8 -# endif -# ifndef EEXIST -# define EEXIST 17 -# endif -# ifndef EFBIG -# define EFBIG 27 -# endif -# ifndef ENAMETOOLONG -# define ENAMETOOLONG 38 -# endif -# ifndef ENOSYS -# define ENOSYS 40 -# endif -# ifndef EHOSTUNREACH -# define EHOSTUNREACH 110 -# endif -# ifndef EIDRM -# define EIDRM 111 -# endif -# ifndef EILSEQ -# define EILSEQ 42 -# endif -# ifndef ENOTTY -# define ENOTTY 25 -# endif -# ifndef EINTR -# define EINTR 4 -# endif -# ifndef EINVAL -# define EINVAL 22 -# endif -# ifndef ESPIPE -# define ESPIPE 29 -# endif -# ifndef EIO -# define EIO 5 -# endif -# ifndef EISDIR -# define EISDIR 21 -# endif -# ifndef EMSGSIZE -# define EMSGSIZE 115 -# endif -# ifndef ENETDOWN -# define ENETDOWN 116 -# endif -# ifndef ENETRESET -# define ENETRESET 117 -# endif -# ifndef ENETUNREACH -# define ENETUNREACH 118 -# endif -# ifndef ENOBUFS -# define ENOBUFS 119 -# endif -# ifndef ECHILD -# define ECHILD 10 -# endif -# ifndef ENOLINK -# define ENOLINK 121 -# endif -# ifndef ENOLCK -# define ENOLCK 39 -# endif -# ifndef ENODATA -# define ENODATA 120 -# endif -# ifndef ENOMSG -# define ENOMSG 122 -# endif -# ifndef ENOPROTOOPT -# define ENOPROTOOPT 123 -# endif -# ifndef ENOSPC -# define ENOSPC 28 -# endif -# ifndef ENOSR -# define ENOSR 124 -# endif -# ifndef ENXIO -# define ENXIO 6 -# endif -# ifndef ENODEV -# define ENODEV 19 -# endif -# ifndef ENOENT -# define ENOENT 2 -# endif -# ifndef ESRCH -# define ESRCH 3 -# endif -# ifndef ENOTDIR -# define ENOTDIR 20 -# endif -# ifndef ENOTSOCK -# define ENOTSOCK 128 -# endif -# ifndef ENOSTR -# define ENOSTR 125 -# endif -# ifndef ENOTCONN -# define ENOTCONN 126 -# endif -# ifndef ENOMEM -# define ENOMEM 12 -# endif -# ifndef ENOTSUP -# define ENOTSUP 129 -# endif -# ifndef ECANCELED -# define ECANCELED 105 -# endif -# ifndef EINPROGRESS -# define EINPROGRESS 112 -# endif -# ifndef EPERM -# define EPERM 1 -# endif -# ifndef EOPNOTSUPP -# define EOPNOTSUPP 130 -# endif -# ifndef EWOULDBLOCK -# define EWOULDBLOCK 140 -# endif -# ifndef EOWNERDEAD -# define EOWNERDEAD 133 -# endif -# ifndef EACCES -# define EACCES 13 -# endif -# ifndef EPROTO -# define EPROTO 134 -# endif -# ifndef EPROTONOSUPPORT -# define EPROTONOSUPPORT 135 -# endif -# ifndef EROFS -# define EROFS 30 -# endif -# ifndef EDEADLK -# define EDEADLK 36 -# endif -# ifndef EAGAIN -# define EAGAIN 11 -# endif -# ifndef ERANGE -# define ERANGE 34 -# endif -# ifndef ENOTRECOVERABLE -# define ENOTRECOVERABLE 127 -# endif -# ifndef ETIME -# define ETIME 137 -# endif -# ifndef ETXTBSY -# define ETXTBSY 139 -# endif -# ifndef ETIMEDOUT -# define ETIMEDOUT 138 -# endif -# ifndef ENFILE -# define ENFILE 23 -# endif -# ifndef EMFILE -# define EMFILE 24 -# endif -# ifndef EMLINK -# define EMLINK 31 -# endif -# ifndef ELOOP -# define ELOOP 114 -# endif -# ifndef EOVERFLOW -# define EOVERFLOW 132 -# endif -# ifndef EPROTOTYPE -# define EPROTOTYPE 136 -# endif -#endif - -namespace llvm { - -// is_error_code_enum - -template <class Tp> struct is_error_code_enum : public false_type {}; - -// is_error_condition_enum - -template <class Tp> struct is_error_condition_enum : public false_type {}; - -// Some error codes are not present on all platforms, so we provide equivalents -// for them: - -//enum class errc -struct errc { -enum _ { - success = 0, - address_family_not_supported = EAFNOSUPPORT, - address_in_use = EADDRINUSE, - address_not_available = EADDRNOTAVAIL, - already_connected = EISCONN, - argument_list_too_long = E2BIG, - argument_out_of_domain = EDOM, - bad_address = EFAULT, - bad_file_descriptor = EBADF, -#ifdef EBADMSG - bad_message = EBADMSG, -#else - bad_message = EINVAL, -#endif - broken_pipe = EPIPE, - connection_aborted = ECONNABORTED, - connection_already_in_progress = EALREADY, - connection_refused = ECONNREFUSED, - connection_reset = ECONNRESET, - cross_device_link = EXDEV, - destination_address_required = EDESTADDRREQ, - device_or_resource_busy = EBUSY, - directory_not_empty = ENOTEMPTY, - executable_format_error = ENOEXEC, - file_exists = EEXIST, - file_too_large = EFBIG, - filename_too_long = ENAMETOOLONG, - function_not_supported = ENOSYS, - host_unreachable = EHOSTUNREACH, - identifier_removed = EIDRM, - illegal_byte_sequence = EILSEQ, - inappropriate_io_control_operation = ENOTTY, - interrupted = EINTR, - invalid_argument = EINVAL, - invalid_seek = ESPIPE, - io_error = EIO, - is_a_directory = EISDIR, - message_size = EMSGSIZE, - network_down = ENETDOWN, - network_reset = ENETRESET, - network_unreachable = ENETUNREACH, - no_buffer_space = ENOBUFS, - no_child_process = ECHILD, -#ifdef ENOLINK - no_link = ENOLINK, -#else - no_link = EINVAL, -#endif - no_lock_available = ENOLCK, -#ifdef ENODATA - no_message_available = ENODATA, -#else - no_message_available = ENOMSG, -#endif - no_message = ENOMSG, - no_protocol_option = ENOPROTOOPT, - no_space_on_device = ENOSPC, -#ifdef ENOSR - no_stream_resources = ENOSR, -#else - no_stream_resources = ENOMEM, -#endif - no_such_device_or_address = ENXIO, - no_such_device = ENODEV, - no_such_file_or_directory = ENOENT, - no_such_process = ESRCH, - not_a_directory = ENOTDIR, - not_a_socket = ENOTSOCK, -#ifdef ENOSTR - not_a_stream = ENOSTR, -#else - not_a_stream = EINVAL, -#endif - not_connected = ENOTCONN, - not_enough_memory = ENOMEM, - not_supported = ENOTSUP, -#ifdef ECANCELED - operation_canceled = ECANCELED, -#else - operation_canceled = EINVAL, -#endif - operation_in_progress = EINPROGRESS, - operation_not_permitted = EPERM, - operation_not_supported = EOPNOTSUPP, - operation_would_block = EWOULDBLOCK, -#ifdef EOWNERDEAD - owner_dead = EOWNERDEAD, -#else - owner_dead = EINVAL, -#endif - permission_denied = EACCES, -#ifdef EPROTO - protocol_error = EPROTO, -#else - protocol_error = EINVAL, -#endif - protocol_not_supported = EPROTONOSUPPORT, - read_only_file_system = EROFS, - resource_deadlock_would_occur = EDEADLK, - resource_unavailable_try_again = EAGAIN, - result_out_of_range = ERANGE, -#ifdef ENOTRECOVERABLE - state_not_recoverable = ENOTRECOVERABLE, -#else - state_not_recoverable = EINVAL, -#endif -#ifdef ETIME - stream_timeout = ETIME, -#else - stream_timeout = ETIMEDOUT, -#endif - text_file_busy = ETXTBSY, - timed_out = ETIMEDOUT, - too_many_files_open_in_system = ENFILE, - too_many_files_open = EMFILE, - too_many_links = EMLINK, - too_many_symbolic_link_levels = ELOOP, - value_too_large = EOVERFLOW, - wrong_protocol_type = EPROTOTYPE -}; - - _ v_; - - errc(_ v) : v_(v) {} - operator int() const {return v_;} -}; - -template <> struct is_error_condition_enum<errc> : true_type { }; - -template <> struct is_error_condition_enum<errc::_> : true_type { }; - -class error_condition; -class error_code; - -// class error_category - -class _do_message; - -class error_category -{ -public: - virtual ~error_category(); - -private: - error_category(); - error_category(const error_category&) 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: - virtual std::string message(int ev) const LLVM_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 enable_if_c< - is_error_condition_enum<E>::value - >::type* = 0) - {*this = make_error_condition(_e);} - - void assign(int _val, const error_category& _cat) { - _val_ = _val; - _cat_ = &_cat; - } - - template <class E> - typename enable_if_c - < - is_error_condition_enum<E>::value, - error_condition& - >::type - operator=(E _e) - {*this = make_error_condition(_e); return *this;} - - void clear() { - _val_ = 0; - _cat_ = &generic_category(); - } - - int value() const {return _val_;} - - const error_category& category() const {return *_cat_;} - std::string message() const; - - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} - - operator unspecified_bool_type() const { // true if error - return _val_ == 0 ? 0 : unspecified_bool_true; - } -}; - -inline error_condition make_error_condition(errc _e) { - return error_condition(static_cast<int>(_e), generic_category()); -} - -inline bool operator<(const error_condition& _x, const error_condition& _y) { - return _x.category() < _y.category() - || (_x.category() == _y.category() && _x.value() < _y.value()); -} - -// error_code - -class error_code { - int _val_; - const error_category* _cat_; -public: - error_code() : _val_(0), _cat_(&system_category()) {} - - 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 enable_if_c< - is_error_code_enum<E>::value - >::type* = 0) { - *this = make_error_code(_e); - } - - void assign(int _val, const error_category& _cat) { - _val_ = _val; - _cat_ = &_cat; - } - - template <class E> - typename enable_if_c - < - is_error_code_enum<E>::value, - error_code& - >::type - operator=(E _e) - {*this = make_error_code(_e); return *this;} - - void clear() { - _val_ = 0; - _cat_ = &system_category(); - } - - int value() const {return _val_;} - - const error_category& category() const {return *_cat_;} - - error_condition default_error_condition() const - {return _cat_->default_error_condition(_val_);} - - std::string message() const; - - typedef void (*unspecified_bool_type)(); - static void unspecified_bool_true() {} - - operator unspecified_bool_type() const { // true if error - return _val_ == 0 ? 0 : unspecified_bool_true; - } -}; - -inline error_code make_error_code(errc _e) { - return error_code(static_cast<int>(_e), generic_category()); -} - -inline bool operator<(const error_code& _x, const error_code& _y) { - return _x.category() < _y.category() - || (_x.category() == _y.category() && _x.value() < _y.value()); -} - -inline bool operator==(const error_code& _x, const error_code& _y) { - return _x.category() == _y.category() && _x.value() == _y.value(); -} - -inline bool operator==(const error_code& _x, const error_condition& _y) { - return _x.category().equivalent(_x.value(), _y) - || _y.category().equivalent(_x, _y.value()); -} - -inline bool operator==(const error_condition& _x, const error_code& _y) { - return _y == _x; -} - -inline bool operator==(const error_condition& _x, const error_condition& _y) { - return _x.category() == _y.category() && _x.value() == _y.value(); -} - -inline bool operator!=(const error_code& _x, const error_code& _y) { - return !(_x == _y); -} - -inline bool operator!=(const error_code& _x, const error_condition& _y) { - return !(_x == _y); -} - -inline bool operator!=(const error_condition& _x, const error_code& _y) { - return !(_x == _y); -} - -inline bool operator!=(const error_condition& _x, const error_condition& _y) { - return !(_x == _y); -} - -// Windows errors. - -// To construct an error_code after an API error: -// -// error_code( ::GetLastError(), system_category() ) -struct windows_error { -enum _ { - success = 0, - // These names and values are based on Windows WinError.h - // This is not a complete list. Add to this list if you need to explicitly - // check for it. - invalid_function = 1, // ERROR_INVALID_FUNCTION, - file_not_found = 2, // ERROR_FILE_NOT_FOUND, - path_not_found = 3, // ERROR_PATH_NOT_FOUND, - too_many_open_files = 4, // ERROR_TOO_MANY_OPEN_FILES, - access_denied = 5, // ERROR_ACCESS_DENIED, - invalid_handle = 6, // ERROR_INVALID_HANDLE, - arena_trashed = 7, // ERROR_ARENA_TRASHED, - not_enough_memory = 8, // ERROR_NOT_ENOUGH_MEMORY, - invalid_block = 9, // ERROR_INVALID_BLOCK, - bad_environment = 10, // ERROR_BAD_ENVIRONMENT, - bad_format = 11, // ERROR_BAD_FORMAT, - invalid_access = 12, // ERROR_INVALID_ACCESS, - outofmemory = 14, // ERROR_OUTOFMEMORY, - invalid_drive = 15, // ERROR_INVALID_DRIVE, - current_directory = 16, // ERROR_CURRENT_DIRECTORY, - not_same_device = 17, // ERROR_NOT_SAME_DEVICE, - no_more_files = 18, // ERROR_NO_MORE_FILES, - write_protect = 19, // ERROR_WRITE_PROTECT, - bad_unit = 20, // ERROR_BAD_UNIT, - not_ready = 21, // ERROR_NOT_READY, - bad_command = 22, // ERROR_BAD_COMMAND, - crc = 23, // ERROR_CRC, - bad_length = 24, // ERROR_BAD_LENGTH, - seek = 25, // ERROR_SEEK, - not_dos_disk = 26, // ERROR_NOT_DOS_DISK, - sector_not_found = 27, // ERROR_SECTOR_NOT_FOUND, - out_of_paper = 28, // ERROR_OUT_OF_PAPER, - write_fault = 29, // ERROR_WRITE_FAULT, - read_fault = 30, // ERROR_READ_FAULT, - gen_failure = 31, // ERROR_GEN_FAILURE, - sharing_violation = 32, // ERROR_SHARING_VIOLATION, - lock_violation = 33, // ERROR_LOCK_VIOLATION, - wrong_disk = 34, // ERROR_WRONG_DISK, - sharing_buffer_exceeded = 36, // ERROR_SHARING_BUFFER_EXCEEDED, - handle_eof = 38, // ERROR_HANDLE_EOF, - handle_disk_full = 39, // ERROR_HANDLE_DISK_FULL, - rem_not_list = 51, // ERROR_REM_NOT_LIST, - dup_name = 52, // ERROR_DUP_NAME, - bad_net_path = 53, // ERROR_BAD_NETPATH, - network_busy = 54, // ERROR_NETWORK_BUSY, - file_exists = 80, // ERROR_FILE_EXISTS, - cannot_make = 82, // ERROR_CANNOT_MAKE, - broken_pipe = 109, // ERROR_BROKEN_PIPE, - open_failed = 110, // ERROR_OPEN_FAILED, - buffer_overflow = 111, // ERROR_BUFFER_OVERFLOW, - disk_full = 112, // ERROR_DISK_FULL, - insufficient_buffer = 122, // ERROR_INSUFFICIENT_BUFFER, - lock_failed = 167, // ERROR_LOCK_FAILED, - busy = 170, // ERROR_BUSY, - cancel_violation = 173, // ERROR_CANCEL_VIOLATION, - already_exists = 183 // ERROR_ALREADY_EXISTS -}; - _ v_; - - windows_error(_ v) : v_(v) {} - explicit windows_error(int v) : v_(_(v)) {} - operator int() const {return v_;} -}; - - -template <> struct is_error_code_enum<windows_error> : true_type { }; - -template <> struct is_error_code_enum<windows_error::_> : true_type { }; - -inline error_code make_error_code(windows_error e) { - return error_code(static_cast<int>(e), system_category()); -} - -} // end namespace llvm - -#endif diff --git a/contrib/llvm/include/llvm/Support/type_traits.h b/contrib/llvm/include/llvm/Support/type_traits.h index 906e97c..70953a9 100644 --- a/contrib/llvm/include/llvm/Support/type_traits.h +++ b/contrib/llvm/include/llvm/Support/type_traits.h @@ -7,18 +7,14 @@ // //===----------------------------------------------------------------------===// // -// This file provides a template class that determines if a type is a class or -// not. The basic mechanism, based on using the pointer to member function of -// a zero argument to a function was "boosted" from the boost type_traits -// library. See http://www.boost.org/ for all the gory details. +// This file provides useful additions to the standard type_traits library. // //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_TYPE_TRAITS_H #define LLVM_SUPPORT_TYPE_TRAITS_H -#include "llvm/Support/DataTypes.h" -#include <cstddef> +#include <type_traits> #include <utility> #ifndef __has_feature @@ -26,40 +22,8 @@ #define __has_feature(x) 0 #endif -// This is actually the conforming implementation which works with abstract -// classes. However, enough compilers have trouble with it that most will use -// the one in boost/type_traits/object_traits.hpp. This implementation actually -// works with VC7.0, but other interactions seem to fail when we use it. - namespace llvm { - -namespace dont_use -{ - // These two functions should never be used. They are helpers to - // the is_class template below. They cannot be located inside - // is_class because doing so causes at least GCC to think that - // the value of the "value" enumerator is not constant. Placing - // them out here (for some strange reason) allows the sizeof - // operator against them to magically be constant. This is - // important to make the is_class<T>::value idiom zero cost. it - // evaluates to a constant 1 or 0 depending on whether the - // parameter T is a class or not (respectively). - template<typename T> char is_class_helper(void(T::*)()); - template<typename T> double is_class_helper(...); -} -template <typename T> -struct is_class -{ - // is_class<> metafunction due to Paul Mensonides (leavings@attbi.com). For - // more details: - // http://groups.google.com/groups?hl=en&selm=000001c1cc83%24e154d5e0%247772e50c%40c161550a&rnum=1 -public: - static const bool value = - sizeof(char) == sizeof(dont_use::is_class_helper<T>(0)); -}; - - /// isPodLike - This is a type trait that is used to determine whether a given /// type can be copied around with memcpy instead of running ctors etc. template <typename T> @@ -71,7 +35,7 @@ struct isPodLike { #else // If we don't know anything else, we can (at least) assume that all non-class // types are PODs. - static const bool value = !is_class<T>::value; + static const bool value = !std::is_class<T>::value; #endif }; @@ -80,161 +44,45 @@ template<typename T, typename U> struct isPodLike<std::pair<T, U> > { static const bool value = isPodLike<T>::value && isPodLike<U>::value; }; - - -template <class T, T v> -struct integral_constant { - typedef T value_type; - static const value_type value = v; - typedef integral_constant<T,v> type; - operator value_type() { return value; } -}; - -typedef integral_constant<bool, true> true_type; -typedef integral_constant<bool, false> false_type; - -/// \brief Metafunction that determines whether the two given types are -/// equivalent. -template<typename T, typename U> struct is_same : public false_type {}; -template<typename T> struct is_same<T, T> : public true_type {}; - -/// \brief Metafunction that removes const qualification from a type. -template <typename T> struct remove_const { typedef T type; }; -template <typename T> struct remove_const<const T> { typedef T type; }; - -/// \brief Metafunction that removes volatile qualification from a type. -template <typename T> struct remove_volatile { typedef T type; }; -template <typename T> struct remove_volatile<volatile T> { typedef T type; }; - -/// \brief Metafunction that removes both const and volatile qualification from -/// a type. -template <typename T> struct remove_cv { - typedef typename remove_const<typename remove_volatile<T>::type>::type type; -}; - -/// \brief Helper to implement is_integral metafunction. -template <typename T> struct is_integral_impl : false_type {}; -template <> struct is_integral_impl< bool> : true_type {}; -template <> struct is_integral_impl< char> : true_type {}; -template <> struct is_integral_impl< signed char> : true_type {}; -template <> struct is_integral_impl<unsigned char> : true_type {}; -template <> struct is_integral_impl< wchar_t> : true_type {}; -template <> struct is_integral_impl< short> : true_type {}; -template <> struct is_integral_impl<unsigned short> : true_type {}; -template <> struct is_integral_impl< int> : true_type {}; -template <> struct is_integral_impl<unsigned int> : true_type {}; -template <> struct is_integral_impl< long> : true_type {}; -template <> struct is_integral_impl<unsigned long> : true_type {}; -template <> struct is_integral_impl< long long> : true_type {}; -template <> struct is_integral_impl<unsigned long long> : true_type {}; - -/// \brief Metafunction that determines whether the given type is an integral -/// type. -template <typename T> -struct is_integral : is_integral_impl<T> {}; - -/// \brief Metafunction to remove reference from a type. -template <typename T> struct remove_reference { typedef T type; }; -template <typename T> struct remove_reference<T&> { typedef T type; }; - -/// \brief Metafunction that determines whether the given type is a pointer -/// type. -template <typename T> struct is_pointer : false_type {}; -template <typename T> struct is_pointer<T*> : true_type {}; -template <typename T> struct is_pointer<T* const> : true_type {}; -template <typename T> struct is_pointer<T* volatile> : true_type {}; -template <typename T> struct is_pointer<T* const volatile> : true_type {}; - -/// \brief Metafunction that determines wheather the given type is a reference. -template <typename T> struct is_reference : false_type {}; -template <typename T> struct is_reference<T&> : true_type {}; /// \brief Metafunction that determines whether the given type is either an /// integral type or an enumeration type. /// -/// Note that this accepts potentially more integral types than we whitelist -/// above for is_integral because it is based on merely being convertible -/// implicitly to an integral type. +/// Note that this accepts potentially more integral types than is_integral +/// because it is based on merely being convertible implicitly to an integral +/// type. template <typename T> class is_integral_or_enum { - // Provide an overload which can be called with anything implicitly - // convertible to an unsigned long long. This should catch integer types and - // enumeration types at least. We blacklist classes with conversion operators - // below. - static double check_int_convertible(unsigned long long); - static char check_int_convertible(...); - - typedef typename remove_reference<T>::type UnderlyingT; - static UnderlyingT &nonce_instance; + typedef typename std::remove_reference<T>::type UnderlyingT; public: - static const bool - value = (!is_class<UnderlyingT>::value && !is_pointer<UnderlyingT>::value && - !is_same<UnderlyingT, float>::value && - !is_same<UnderlyingT, double>::value && - sizeof(char) != sizeof(check_int_convertible(nonce_instance))); -}; - -// enable_if_c - Enable/disable a template based on a metafunction -template<bool Cond, typename T = void> -struct enable_if_c { - typedef T type; -}; - -template<typename T> struct enable_if_c<false, T> { }; - -// enable_if - Enable/disable a template based on a metafunction -template<typename Cond, typename T = void> -struct enable_if : public enable_if_c<Cond::value, T> { }; - -namespace dont_use { - template<typename Base> char base_of_helper(const volatile Base*); - template<typename Base> double base_of_helper(...); -} - -/// is_base_of - Metafunction to determine whether one type is a base class of -/// (or identical to) another type. -template<typename Base, typename Derived> -struct is_base_of { - static const bool value - = is_class<Base>::value && is_class<Derived>::value && - sizeof(char) == sizeof(dont_use::base_of_helper<Base>((Derived*)0)); + static const bool value = + !std::is_class<UnderlyingT>::value && // Filter conversion operators. + !std::is_pointer<UnderlyingT>::value && + !std::is_floating_point<UnderlyingT>::value && + std::is_convertible<UnderlyingT, unsigned long long>::value; }; -// remove_pointer - Metafunction to turn Foo* into Foo. Defined in -// C++0x [meta.trans.ptr]. -template <typename T> struct remove_pointer { typedef T type; }; -template <typename T> struct remove_pointer<T*> { typedef T type; }; -template <typename T> struct remove_pointer<T*const> { typedef T type; }; -template <typename T> struct remove_pointer<T*volatile> { typedef T type; }; -template <typename T> struct remove_pointer<T*const volatile> { - typedef T type; }; - -// If T is a pointer, just return it. If it is not, return T&. +/// \brief If T is a pointer, just return it. If it is not, return T&. template<typename T, typename Enable = void> struct add_lvalue_reference_if_not_pointer { typedef T &type; }; -template<typename T> -struct add_lvalue_reference_if_not_pointer<T, - typename enable_if<is_pointer<T> >::type> { +template <typename T> +struct add_lvalue_reference_if_not_pointer< + T, typename std::enable_if<std::is_pointer<T>::value>::type> { typedef T type; }; -// If T is a pointer to X, return a pointer to const X. If it is not, return -// const T. +/// \brief If T is a pointer to X, return a pointer to const X. If it is not, +/// return const T. template<typename T, typename Enable = void> struct add_const_past_pointer { typedef const T type; }; -template<typename T> -struct add_const_past_pointer<T, typename enable_if<is_pointer<T> >::type> { - typedef const typename remove_pointer<T>::type *type; +template <typename T> +struct add_const_past_pointer< + T, typename std::enable_if<std::is_pointer<T>::value>::type> { + typedef const typename std::remove_pointer<T>::type *type; }; -template <bool, typename T, typename F> -struct conditional { typedef T type; }; - -template <typename T, typename F> -struct conditional<false, T, F> { typedef F type; }; - } #ifdef LLVM_DEFINED_HAS_FEATURE |