diff options
Diffstat (limited to 'include/llvm/Support')
76 files changed, 3213 insertions, 891 deletions
diff --git a/include/llvm/Support/AArch64TargetParser.def b/include/llvm/Support/AArch64TargetParser.def new file mode 100644 index 000000000000..67f981b8f2fa --- /dev/null +++ b/include/llvm/Support/AArch64TargetParser.def @@ -0,0 +1,72 @@ +//===- AARCH64TargetParser.def - AARCH64 target parsing defines ---------*- 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 defines to build up the AARCH64 target parser's logic. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef AARCH64_ARCH +#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) +#endif +AARCH64_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A, + FK_CRYPTO_NEON_FP_ARMV8, + (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | + AArch64::AEK_SIMD | AArch64::AEK_FP16 | AArch64::AEK_PROFILE)) +AARCH64_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a", + ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, + (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | + AArch64::AEK_SIMD | AArch64::AEK_FP16 | AArch64::AEK_PROFILE)) +AARCH64_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a", + ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, + (AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | + AArch64::AEK_SIMD | AArch64::AEK_FP16 | AArch64::AEK_PROFILE | + AArch64::AEK_RAS)) +#undef AARCH64_ARCH + +#ifndef AARCH64_ARCH_EXT_NAME +#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) +#endif +// FIXME: This would be nicer were it tablegen +AARCH64_ARCH_EXT_NAME("invalid", AArch64::AEK_INVALID, nullptr, nullptr) +AARCH64_ARCH_EXT_NAME("none", AArch64::AEK_NONE, nullptr, nullptr) +AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc") +AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto") +AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8") +AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon") +AARCH64_ARCH_EXT_NAME("fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16") +AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe") +AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras") +#undef AARCH64_ARCH_EXT_NAME + +#ifndef AARCH64_CPU_NAME +#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) +#endif +AARCH64_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, + ( AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("kryo", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +AARCH64_CPU_NAME("vulcan", AK_ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false, + (AArch64::AEK_SIMD | AArch64::AEK_CRC | AArch64::AEK_CRYPTO)) +// Invalid CPU +AARCH64_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, AArch64::AEK_INVALID) +#undef AARCH64_CPU_NAME diff --git a/include/llvm/Support/AIXDataTypesFix.h b/include/llvm/Support/AIXDataTypesFix.h deleted file mode 100644 index a9a9147de294..000000000000 --- a/include/llvm/Support/AIXDataTypesFix.h +++ /dev/null @@ -1,25 +0,0 @@ -//===-- llvm/Support/AIXDataTypesFix.h - Fix datatype defs ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file overrides default system-defined types and limits which cannot be -// done in DataTypes.h.in because it is processed by autoheader first, which -// comments out any #undef statement -// -//===----------------------------------------------------------------------===// - -// No include guards desired! - -#ifndef SUPPORT_DATATYPES_H -#error "AIXDataTypesFix.h must only be included via DataTypes.h!" -#endif - -// GCC is strict about defining large constants: they must have LL modifier. -// These will be defined properly at the end of DataTypes.h -#undef INT64_MAX -#undef INT64_MIN diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h index fc14cb2d0b0c..f447cd072b5f 100644 --- a/include/llvm/Support/ARMBuildAttributes.h +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -67,6 +67,7 @@ enum AttrType { ABI_FP_16bit_format = 38, MPextension_use = 42, // recoded from 70 (ABI r2.08) DIV_use = 44, + DSP_extension = 46, also_compatible_with = 65, conformance = 67, Virtualization_use = 68, @@ -106,7 +107,9 @@ enum CPUArch { 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,v8.1a AArch32 + v8_A = 14, // v8_A AArch32 + v8_M_Base= 16, // v8_M_Base AArch32 + v8_M_Main= 17, // v8_M_Main AArch32 }; enum CPUArchProfile { // (=7), uleb128 @@ -126,6 +129,7 @@ enum { // Tag_THUMB_ISA_use, (=9), uleb128 AllowThumb32 = 2, // 32-bit Thumb (implies 16-bit instructions) + AllowThumbDerived = 3, // Thumb allowed, derived from arch/profile // Tag_FP_arch (=10), uleb128 (formerly Tag_VFP_arch = 10) AllowFPv2 = 2, // v2 FP ISA permitted (implies use of the v1 FP ISA) diff --git a/include/llvm/Support/ARMTargetParser.def b/include/llvm/Support/ARMTargetParser.def index d94a51b8bcf9..195f7112d6a0 100644 --- a/include/llvm/Support/ARMTargetParser.def +++ b/include/llvm/Support/ARMTargetParser.def @@ -45,180 +45,198 @@ ARM_FPU("softvfp", FK_SOFTVFP, FV_NONE, NS_None, FR_None) #define ARM_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT) #endif ARM_ARCH("invalid", AK_INVALID, nullptr, nullptr, - ARMBuildAttrs::CPUArch::Pre_v4, FK_NONE, AEK_NONE) + ARMBuildAttrs::CPUArch::Pre_v4, FK_NONE, ARM::AEK_NONE) ARM_ARCH("armv2", AK_ARMV2, "2", "v2", ARMBuildAttrs::CPUArch::Pre_v4, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("armv2a", AK_ARMV2A, "2A", "v2a", ARMBuildAttrs::CPUArch::Pre_v4, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("armv3", AK_ARMV3, "3", "v3", ARMBuildAttrs::CPUArch::Pre_v4, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("armv3m", AK_ARMV3M, "3M", "v3m", ARMBuildAttrs::CPUArch::Pre_v4, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("armv4", AK_ARMV4, "4", "v4", ARMBuildAttrs::CPUArch::v4, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("armv4t", AK_ARMV4T, "4T", "v4t", ARMBuildAttrs::CPUArch::v4T, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("armv5t", AK_ARMV5T, "5T", "v5", ARMBuildAttrs::CPUArch::v5T, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("armv5te", AK_ARMV5TE, "5TE", "v5e", ARMBuildAttrs::CPUArch::v5TE, - FK_NONE, AEK_DSP) + FK_NONE, ARM::AEK_DSP) ARM_ARCH("armv5tej", AK_ARMV5TEJ, "5TEJ", "v5e", ARMBuildAttrs::CPUArch::v5TEJ, - FK_NONE, AEK_DSP) + FK_NONE, ARM::AEK_DSP) ARM_ARCH("armv6", AK_ARMV6, "6", "v6", ARMBuildAttrs::CPUArch::v6, - FK_VFPV2, AEK_DSP) + FK_VFPV2, ARM::AEK_DSP) ARM_ARCH("armv6k", AK_ARMV6K, "6K", "v6k", ARMBuildAttrs::CPUArch::v6K, - FK_VFPV2, AEK_DSP) + FK_VFPV2, ARM::AEK_DSP) ARM_ARCH("armv6t2", AK_ARMV6T2, "6T2", "v6t2", ARMBuildAttrs::CPUArch::v6T2, - FK_NONE, AEK_DSP) + FK_NONE, ARM::AEK_DSP) ARM_ARCH("armv6kz", AK_ARMV6KZ, "6KZ", "v6kz", ARMBuildAttrs::CPUArch::v6KZ, - FK_VFPV2, (AEK_SEC | AEK_DSP)) + FK_VFPV2, (ARM::AEK_SEC | ARM::AEK_DSP)) ARM_ARCH("armv6-m", AK_ARMV6M, "6-M", "v6m", ARMBuildAttrs::CPUArch::v6_M, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("armv7-a", AK_ARMV7A, "7-A", "v7", ARMBuildAttrs::CPUArch::v7, - FK_NEON, AEK_DSP) + FK_NEON, ARM::AEK_DSP) ARM_ARCH("armv7-r", AK_ARMV7R, "7-R", "v7r", ARMBuildAttrs::CPUArch::v7, - FK_NONE, (AEK_HWDIV | AEK_DSP)) + FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP)) ARM_ARCH("armv7-m", AK_ARMV7M, "7-M", "v7m", ARMBuildAttrs::CPUArch::v7, - FK_NONE, AEK_HWDIV) + FK_NONE, ARM::AEK_HWDIV) ARM_ARCH("armv7e-m", AK_ARMV7EM, "7E-M", "v7em", ARMBuildAttrs::CPUArch::v7E_M, - FK_NONE, (AEK_HWDIV | AEK_DSP)) -ARM_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8, - FK_CRYPTO_NEON_FP_ARMV8, (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | - AEK_HWDIV | AEK_DSP | AEK_CRC)) -ARM_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a", ARMBuildAttrs::CPUArch::v8, - FK_CRYPTO_NEON_FP_ARMV8, (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | - AEK_HWDIV | AEK_DSP | AEK_CRC)) -ARM_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a", ARMBuildAttrs::CPUArch::v8, - FK_CRYPTO_NEON_FP_ARMV8, (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | - AEK_HWDIV | AEK_DSP | AEK_CRC)) + FK_NONE, (ARM::AEK_HWDIV | ARM::AEK_DSP)) +ARM_ARCH("armv8-a", AK_ARMV8A, "8-A", "v8", ARMBuildAttrs::CPUArch::v8_A, + FK_CRYPTO_NEON_FP_ARMV8, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC)) +ARM_ARCH("armv8.1-a", AK_ARMV8_1A, "8.1-A", "v8.1a", + ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS)) +ARM_ARCH("armv8.2-a", AK_ARMV8_2A, "8.2-A", "v8.2a", + ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8, + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV | ARM::AEK_DSP | ARM::AEK_CRC)) +ARM_ARCH("armv8-m.base", AK_ARMV8MBaseline, "8-M.Baseline", "v8m.base", + ARMBuildAttrs::CPUArch::v8_M_Base, FK_NONE, ARM::AEK_HWDIV) +ARM_ARCH("armv8-m.main", AK_ARMV8MMainline, "8-M.Mainline", "v8m.main", + ARMBuildAttrs::CPUArch::v8_M_Main, FK_FPV5_D16, ARM::AEK_HWDIV) // Non-standard Arch names. ARM_ARCH("iwmmxt", AK_IWMMXT, "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("iwmmxt2", AK_IWMMXT2, "iwmmxt2", "", ARMBuildAttrs::CPUArch::v5TE, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("xscale", AK_XSCALE, "xscale", "v5e", ARMBuildAttrs::CPUArch::v5TE, - FK_NONE, AEK_NONE) + FK_NONE, ARM::AEK_NONE) ARM_ARCH("armv7s", AK_ARMV7S, "7-S", "v7s", ARMBuildAttrs::CPUArch::v7, - FK_NEON_VFPV4, AEK_DSP) + FK_NEON_VFPV4, ARM::AEK_DSP) ARM_ARCH("armv7k", AK_ARMV7K, "7-K", "v7k", ARMBuildAttrs::CPUArch::v7, - FK_NONE, AEK_DSP) + FK_NONE, ARM::AEK_DSP) #undef ARM_ARCH #ifndef ARM_ARCH_EXT_NAME #define ARM_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) #endif // FIXME: This would be nicer were it tablegen -ARM_ARCH_EXT_NAME("invalid", AEK_INVALID, nullptr, nullptr) -ARM_ARCH_EXT_NAME("none", AEK_NONE, nullptr, nullptr) -ARM_ARCH_EXT_NAME("crc", AEK_CRC, "+crc", "-crc") -ARM_ARCH_EXT_NAME("crypto", AEK_CRYPTO, "+crypto","-crypto") -ARM_ARCH_EXT_NAME("fp", AEK_FP, nullptr, nullptr) -ARM_ARCH_EXT_NAME("idiv", (AEK_HWDIVARM | AEK_HWDIV), nullptr, nullptr) -ARM_ARCH_EXT_NAME("mp", AEK_MP, nullptr, nullptr) -ARM_ARCH_EXT_NAME("simd", AEK_SIMD, nullptr, nullptr) -ARM_ARCH_EXT_NAME("sec", AEK_SEC, nullptr, nullptr) -ARM_ARCH_EXT_NAME("virt", AEK_VIRT, nullptr, nullptr) -ARM_ARCH_EXT_NAME("fp16", AEK_FP16, "+fullfp16", "-fullfp16") -ARM_ARCH_EXT_NAME("os", AEK_OS, nullptr, nullptr) -ARM_ARCH_EXT_NAME("iwmmxt", AEK_IWMMXT, nullptr, nullptr) -ARM_ARCH_EXT_NAME("iwmmxt2", AEK_IWMMXT2, nullptr, nullptr) -ARM_ARCH_EXT_NAME("maverick", AEK_MAVERICK, nullptr, nullptr) -ARM_ARCH_EXT_NAME("xscale", AEK_XSCALE, nullptr, nullptr) +ARM_ARCH_EXT_NAME("invalid", ARM::AEK_INVALID, nullptr, nullptr) +ARM_ARCH_EXT_NAME("none", ARM::AEK_NONE, nullptr, nullptr) +ARM_ARCH_EXT_NAME("crc", ARM::AEK_CRC, "+crc", "-crc") +ARM_ARCH_EXT_NAME("crypto", ARM::AEK_CRYPTO, "+crypto","-crypto") +ARM_ARCH_EXT_NAME("dsp", ARM::AEK_DSP, "+dsp", "-dsp") +ARM_ARCH_EXT_NAME("fp", ARM::AEK_FP, nullptr, nullptr) +ARM_ARCH_EXT_NAME("idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV), nullptr, nullptr) +ARM_ARCH_EXT_NAME("mp", ARM::AEK_MP, nullptr, nullptr) +ARM_ARCH_EXT_NAME("simd", ARM::AEK_SIMD, nullptr, nullptr) +ARM_ARCH_EXT_NAME("sec", ARM::AEK_SEC, nullptr, nullptr) +ARM_ARCH_EXT_NAME("virt", ARM::AEK_VIRT, nullptr, nullptr) +ARM_ARCH_EXT_NAME("fp16", ARM::AEK_FP16, "+fullfp16", "-fullfp16") +ARM_ARCH_EXT_NAME("ras", ARM::AEK_RAS, "+ras", "-ras") +ARM_ARCH_EXT_NAME("os", ARM::AEK_OS, nullptr, nullptr) +ARM_ARCH_EXT_NAME("iwmmxt", ARM::AEK_IWMMXT, nullptr, nullptr) +ARM_ARCH_EXT_NAME("iwmmxt2", ARM::AEK_IWMMXT2, nullptr, nullptr) +ARM_ARCH_EXT_NAME("maverick", ARM::AEK_MAVERICK, nullptr, nullptr) +ARM_ARCH_EXT_NAME("xscale", ARM::AEK_XSCALE, nullptr, nullptr) #undef ARM_ARCH_EXT_NAME #ifndef ARM_HW_DIV_NAME #define ARM_HW_DIV_NAME(NAME, ID) #endif -ARM_HW_DIV_NAME("invalid", AEK_INVALID) -ARM_HW_DIV_NAME("none", AEK_NONE) -ARM_HW_DIV_NAME("thumb", AEK_HWDIV) -ARM_HW_DIV_NAME("arm", AEK_HWDIVARM) -ARM_HW_DIV_NAME("arm,thumb", (AEK_HWDIVARM | AEK_HWDIV)) +ARM_HW_DIV_NAME("invalid", ARM::AEK_INVALID) +ARM_HW_DIV_NAME("none", ARM::AEK_NONE) +ARM_HW_DIV_NAME("thumb", ARM::AEK_HWDIV) +ARM_HW_DIV_NAME("arm", ARM::AEK_HWDIVARM) +ARM_HW_DIV_NAME("arm,thumb", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV)) #undef ARM_HW_DIV_NAME #ifndef ARM_CPU_NAME #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT) #endif -ARM_CPU_NAME("arm2", AK_ARMV2, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("arm3", AK_ARMV2A, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("arm6", AK_ARMV3, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("arm7m", AK_ARMV3M, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("arm8", AK_ARMV4, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm810", AK_ARMV4, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("strongarm", AK_ARMV4, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("strongarm110", AK_ARMV4, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("strongarm1100", AK_ARMV4, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("strongarm1110", AK_ARMV4, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm7tdmi", AK_ARMV4T, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("arm7tdmi-s", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm710t", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm720t", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm9", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm9tdmi", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm920", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm920t", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm922t", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm9312", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm940t", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("ep9312", AK_ARMV4T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm10tdmi", AK_ARMV5T, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("arm1020t", AK_ARMV5T, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm9e", AK_ARMV5TE, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm946e-s", AK_ARMV5TE, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm966e-s", AK_ARMV5TE, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm968e-s", AK_ARMV5TE, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm10e", AK_ARMV5TE, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm1020e", AK_ARMV5TE, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm1022e", AK_ARMV5TE, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("arm926ej-s", AK_ARMV5TEJ, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("arm1136j-s", AK_ARMV6, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm1136jf-s", AK_ARMV6, FK_VFPV2, true, AEK_NONE) -ARM_CPU_NAME("arm1136jz-s", AK_ARMV6, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm1176j-s", AK_ARMV6K, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("arm1176jz-s", AK_ARMV6KZ, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("mpcore", AK_ARMV6K, FK_VFPV2, false, AEK_NONE) -ARM_CPU_NAME("mpcorenovfp", AK_ARMV6K, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("arm1176jzf-s", AK_ARMV6KZ, FK_VFPV2, true, AEK_NONE) -ARM_CPU_NAME("arm1156t2-s", AK_ARMV6T2, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("arm1156t2f-s", AK_ARMV6T2, FK_VFPV2, false, AEK_NONE) -ARM_CPU_NAME("cortex-m0", AK_ARMV6M, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("cortex-m0plus", AK_ARMV6M, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("cortex-m1", AK_ARMV6M, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("sc000", AK_ARMV6M, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("cortex-a5", AK_ARMV7A, FK_NEON_VFPV4, false, (AEK_SEC | AEK_MP)) +ARM_CPU_NAME("arm2", AK_ARMV2, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm3", AK_ARMV2A, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm6", AK_ARMV3, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm7m", AK_ARMV3M, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm8", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm810", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("strongarm", AK_ARMV4, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("strongarm110", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("strongarm1100", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("strongarm1110", AK_ARMV4, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm7tdmi", AK_ARMV4T, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm7tdmi-s", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm710t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm720t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm9", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm9tdmi", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm920", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm920t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm922t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm9312", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm940t", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("ep9312", AK_ARMV4T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm10tdmi", AK_ARMV5T, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1020t", AK_ARMV5T, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm9e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm946e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm966e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm968e-s", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm10e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm1020e", AK_ARMV5TE, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm1022e", AK_ARMV5TE, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm926ej-s", AK_ARMV5TEJ, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1136j-s", AK_ARMV6, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm1136jf-s", AK_ARMV6, FK_VFPV2, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1136jz-s", AK_ARMV6, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm1176j-s", AK_ARMV6K, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1176jz-s", AK_ARMV6KZ, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("mpcore", AK_ARMV6K, FK_VFPV2, false, ARM::AEK_NONE) +ARM_CPU_NAME("mpcorenovfp", AK_ARMV6K, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("arm1176jzf-s", AK_ARMV6KZ, FK_VFPV2, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1156t2-s", AK_ARMV6T2, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("arm1156t2f-s", AK_ARMV6T2, FK_VFPV2, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m0", AK_ARMV6M, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m0plus", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m1", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("sc000", AK_ARMV6M, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-a5", AK_ARMV7A, FK_NEON_VFPV4, false, + (ARM::AEK_SEC | ARM::AEK_MP)) ARM_CPU_NAME("cortex-a7", AK_ARMV7A, FK_NEON_VFPV4, false, - (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV)) -ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, true, AEK_SEC) -ARM_CPU_NAME("cortex-a9", AK_ARMV7A, FK_NEON_FP16, false, (AEK_SEC | AEK_MP)) + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV)) +ARM_CPU_NAME("cortex-a8", AK_ARMV7A, FK_NEON, true, ARM::AEK_SEC) +ARM_CPU_NAME("cortex-a9", AK_ARMV7A, FK_NEON_FP16, false, (ARM::AEK_SEC | ARM::AEK_MP)) ARM_CPU_NAME("cortex-a12", AK_ARMV7A, FK_NEON_VFPV4, false, - (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV)) + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV)) ARM_CPU_NAME("cortex-a15", AK_ARMV7A, FK_NEON_VFPV4, false, - (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV)) + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV)) ARM_CPU_NAME("cortex-a17", AK_ARMV7A, FK_NEON_VFPV4, false, - (AEK_SEC | AEK_MP | AEK_VIRT | AEK_HWDIVARM | AEK_HWDIV)) + (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | + ARM::AEK_HWDIV)) ARM_CPU_NAME("krait", AK_ARMV7A, FK_NEON_VFPV4, false, - (AEK_HWDIVARM | AEK_HWDIV)) -ARM_CPU_NAME("cortex-r4", AK_ARMV7R, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("cortex-r4f", AK_ARMV7R, FK_VFPV3_D16, false, AEK_NONE) + (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV)) +ARM_CPU_NAME("cortex-r4", AK_ARMV7R, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-r4f", AK_ARMV7R, FK_VFPV3_D16, false, ARM::AEK_NONE) ARM_CPU_NAME("cortex-r5", AK_ARMV7R, FK_VFPV3_D16, false, - (AEK_MP | AEK_HWDIVARM)) + (ARM::AEK_MP | ARM::AEK_HWDIVARM)) ARM_CPU_NAME("cortex-r7", AK_ARMV7R, FK_VFPV3_D16_FP16, false, - (AEK_MP | AEK_HWDIVARM)) -ARM_CPU_NAME("sc300", AK_ARMV7M, FK_NONE, false, AEK_NONE) -ARM_CPU_NAME("cortex-m3", AK_ARMV7M, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("cortex-m4", AK_ARMV7EM, FK_FPV4_SP_D16, true, AEK_NONE) -ARM_CPU_NAME("cortex-m7", AK_ARMV7EM, FK_FPV5_D16, false, AEK_NONE) -ARM_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, AEK_CRC) -ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, AEK_CRC) -ARM_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, AEK_CRC) -ARM_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, AEK_CRC) -ARM_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, AEK_CRC) -ARM_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, AEK_CRC) + (ARM::AEK_MP | ARM::AEK_HWDIVARM)) +ARM_CPU_NAME("cortex-r8", AK_ARMV7R, FK_VFPV3_D16_FP16, false, + (ARM::AEK_MP | ARM::AEK_HWDIVARM)) +ARM_CPU_NAME("sc300", AK_ARMV7M, FK_NONE, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m3", AK_ARMV7M, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m4", AK_ARMV7EM, FK_FPV4_SP_D16, true, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-m7", AK_ARMV7EM, FK_FPV5_D16, false, ARM::AEK_NONE) +ARM_CPU_NAME("cortex-a32", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("cortex-a35", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("cortex-a53", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true, ARM::AEK_CRC) +ARM_CPU_NAME("cortex-a57", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("cortex-a72", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("cortex-a73", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("cyclone", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) +ARM_CPU_NAME("exynos-m1", AK_ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC) // Non-standard Arch names. -ARM_CPU_NAME("iwmmxt", AK_IWMMXT, FK_NONE, true, AEK_NONE) -ARM_CPU_NAME("xscale", AK_XSCALE, FK_NONE, true, AEK_NONE) +ARM_CPU_NAME("iwmmxt", AK_IWMMXT, FK_NONE, true, ARM::AEK_NONE) +ARM_CPU_NAME("xscale", AK_XSCALE, FK_NONE, true, ARM::AEK_NONE) ARM_CPU_NAME("swift", AK_ARMV7S, FK_NEON_VFPV4, true, - (AEK_HWDIVARM | AEK_HWDIV)) + (ARM::AEK_HWDIVARM | ARM::AEK_HWDIV)) // Invalid CPU -ARM_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, AEK_INVALID) +ARM_CPU_NAME("invalid", AK_INVALID, FK_INVALID, true, ARM::AEK_INVALID) #undef ARM_CPU_NAME diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 5268c8d16986..af7f20028b6d 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -38,7 +38,7 @@ struct AlignmentCalcImpl { #endif T t; private: - AlignmentCalcImpl() {} // Never instantiate. + AlignmentCalcImpl() = delete; }; // Abstract base class helper, this will have the minimal alignment and size @@ -55,7 +55,7 @@ struct AlignmentCalcImplBase { // of type T. template <typename T> struct AlignmentCalcImpl<T, true> : AlignmentCalcImplBase, T { - virtual ~AlignmentCalcImpl() = 0; + ~AlignmentCalcImpl() override = 0; }; } // End detail namespace. @@ -79,8 +79,8 @@ struct AlignOf { sizeof(detail::AlignmentCalcImpl<T>) - sizeof(T)); #else enum { - Alignment = static_cast<unsigned int>(sizeof(detail::AlignmentCalcImpl<T>) - - sizeof(T)) + Alignment = static_cast<unsigned int>( + sizeof(::llvm::detail::AlignmentCalcImpl<T>) - sizeof(T)) }; #endif enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; @@ -223,7 +223,7 @@ template <typename T1, class AlignerImpl { 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. + AlignerImpl() = delete; }; template <typename T1, @@ -249,10 +249,11 @@ template <typename T1, 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, T8, T9, T10> >::Alignment, - sizeof(detail::SizerImpl<T1, T2, T3, T4, T5, - T6, T7, T8, T9, T10>)> { + AlignOf<llvm::detail::AlignerImpl<T1, T2, T3, T4, T5, + T6, T7, T8, T9, T10> >::Alignment, + sizeof(::llvm::detail::SizerImpl<T1, T2, T3, T4, T5, + T6, T7, T8, T9, T10>)> { }; } // end namespace llvm -#endif + +#endif // LLVM_SUPPORT_ALIGNOF_H diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index 043d82314609..1c9508661d6f 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -278,6 +278,8 @@ public: return TotalMemory; } + size_t getBytesAllocated() const { return BytesAllocated; } + void PrintStats() const { detail::printBumpPtrAllocatorStats(Slabs.size(), BytesAllocated, getTotalMemory()); diff --git a/include/llvm/Support/Atomic.h b/include/llvm/Support/Atomic.h index 9ec23e827023..d03714b009c5 100644 --- a/include/llvm/Support/Atomic.h +++ b/include/llvm/Support/Atomic.h @@ -9,6 +9,10 @@ // // This file declares the llvm::sys atomic operations. // +// DO NOT USE IN NEW CODE! +// +// New code should always rely on the std::atomic facilities in C++11. +// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_ATOMIC_H @@ -28,11 +32,6 @@ namespace llvm { cas_flag CompareAndSwap(volatile cas_flag* ptr, cas_flag new_value, cas_flag old_value); - cas_flag AtomicIncrement(volatile cas_flag* ptr); - cas_flag AtomicDecrement(volatile cas_flag* ptr); - cas_flag AtomicAdd(volatile cas_flag* ptr, cas_flag val); - cas_flag AtomicMul(volatile cas_flag* ptr, cas_flag val); - cas_flag AtomicDiv(volatile cas_flag* ptr, cas_flag val); } } diff --git a/include/llvm/Support/AtomicOrdering.h b/include/llvm/Support/AtomicOrdering.h new file mode 100644 index 000000000000..8837fab19575 --- /dev/null +++ b/include/llvm/Support/AtomicOrdering.h @@ -0,0 +1,153 @@ +//===-- llvm/Support/AtomicOrdering.h ---Atomic Ordering---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Atomic ordering constants. +/// +/// These values are used by LLVM to represent atomic ordering for C++11's +/// memory model and more, as detailed in docs/Atomics.rst. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ATOMICORDERING_H +#define LLVM_SUPPORT_ATOMICORDERING_H + +#include <cstddef> + +namespace llvm { + +/// Atomic ordering for C11 / C++11's memody models. +/// +/// These values cannot change because they are shared with standard library +/// implementations as well as with other compilers. +enum class AtomicOrderingCABI { + relaxed = 0, + consume = 1, + acquire = 2, + release = 3, + acq_rel = 4, + seq_cst = 5, +}; + +bool operator<(AtomicOrderingCABI, AtomicOrderingCABI) = delete; +bool operator>(AtomicOrderingCABI, AtomicOrderingCABI) = delete; +bool operator<=(AtomicOrderingCABI, AtomicOrderingCABI) = delete; +bool operator>=(AtomicOrderingCABI, AtomicOrderingCABI) = delete; + +// Validate an integral value which isn't known to fit within the enum's range +// is a valid AtomicOrderingCABI. +template <typename Int> static inline bool isValidAtomicOrderingCABI(Int I) { + return (Int)AtomicOrderingCABI::relaxed <= I && + I <= (Int)AtomicOrderingCABI::seq_cst; +} + +/// Atomic ordering for LLVM's memory model. +/// +/// C++ defines ordering as a lattice. LLVM supplements this with NotAtomic and +/// Unordered, which are both below the C++ orders. +/// +/// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst +/// \-->consume-->acquire--/ +enum class AtomicOrdering { + NotAtomic = 0, + Unordered = 1, + Monotonic = 2, // Equivalent to C++'s relaxed. + // Consume = 3, // Not specified yet. + Acquire = 4, + Release = 5, + AcquireRelease = 6, + SequentiallyConsistent = 7 +}; + +bool operator<(AtomicOrdering, AtomicOrdering) = delete; +bool operator>(AtomicOrdering, AtomicOrdering) = delete; +bool operator<=(AtomicOrdering, AtomicOrdering) = delete; +bool operator>=(AtomicOrdering, AtomicOrdering) = delete; + +// Validate an integral value which isn't known to fit within the enum's range +// is a valid AtomicOrdering. +template <typename Int> static inline bool isValidAtomicOrdering(Int I) { + return (Int)AtomicOrdering::NotAtomic <= I && + I <= (Int)AtomicOrdering::SequentiallyConsistent; +} + +/// String used by LLVM IR to represent atomic ordering. +static inline const char *toIRString(AtomicOrdering ao) { + static const char *names[8] = {"not_atomic", "unordered", "monotonic", + "consume", "acquire", "release", + "acq_rel", "seq_cst"}; + return names[(size_t)ao]; +} + +/// Returns true if ao is stronger than other as defined by the AtomicOrdering +/// lattice, which is based on C++'s definition. +static inline bool isStrongerThan(AtomicOrdering ao, AtomicOrdering other) { + static const bool lookup[8][8] = { + // NA UN RX CO AC RE AR SC + /* NotAtomic */ {0, 0, 0, 0, 0, 0, 0, 0}, + /* Unordered */ {1, 0, 0, 0, 0, 0, 0, 0}, + /* relaxed */ {1, 1, 0, 0, 0, 0, 0, 0}, + /* consume */ {1, 1, 1, 0, 0, 0, 0, 0}, + /* acquire */ {1, 1, 1, 1, 0, 0, 0, 0}, + /* release */ {1, 1, 1, 0, 0, 0, 0, 0}, + /* acq_rel */ {1, 1, 1, 1, 1, 1, 0, 0}, + /* seq_cst */ {1, 1, 1, 1, 1, 1, 1, 0}, + }; + return lookup[(size_t)ao][(size_t)other]; +} + +static inline bool isAtLeastOrStrongerThan(AtomicOrdering ao, + AtomicOrdering other) { + static const bool lookup[8][8] = { + // NA UN RX CO AC RE AR SC + /* NotAtomic */ {1, 0, 0, 0, 0, 0, 0, 0}, + /* Unordered */ {1, 1, 0, 0, 0, 0, 0, 0}, + /* relaxed */ {1, 1, 1, 0, 0, 0, 0, 0}, + /* consume */ {1, 1, 1, 1, 0, 0, 0, 0}, + /* acquire */ {1, 1, 1, 1, 1, 0, 0, 0}, + /* release */ {1, 1, 1, 0, 0, 1, 0, 0}, + /* acq_rel */ {1, 1, 1, 1, 1, 1, 1, 0}, + /* seq_cst */ {1, 1, 1, 1, 1, 1, 1, 1}, + }; + return lookup[(size_t)ao][(size_t)other]; +} + +static inline bool isStrongerThanUnordered(AtomicOrdering ao) { + return isStrongerThan(ao, AtomicOrdering::Unordered); +} + +static inline bool isStrongerThanMonotonic(AtomicOrdering ao) { + return isStrongerThan(ao, AtomicOrdering::Monotonic); +} + +static inline bool isAcquireOrStronger(AtomicOrdering ao) { + return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire); +} + +static inline bool isReleaseOrStronger(AtomicOrdering ao) { + return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release); +} + +static inline AtomicOrderingCABI toCABI(AtomicOrdering ao) { + static const AtomicOrderingCABI lookup[8] = { + /* NotAtomic */ AtomicOrderingCABI::relaxed, + /* Unordered */ AtomicOrderingCABI::relaxed, + /* relaxed */ AtomicOrderingCABI::relaxed, + /* consume */ AtomicOrderingCABI::consume, + /* acquire */ AtomicOrderingCABI::acquire, + /* release */ AtomicOrderingCABI::release, + /* acq_rel */ AtomicOrderingCABI::acq_rel, + /* seq_cst */ AtomicOrderingCABI::seq_cst, + }; + return lookup[(size_t)ao]; +} + +} // end namespace llvm + +#endif // LLVM_SUPPORT_ATOMICORDERING_H diff --git a/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h index 26bc888d1cab..e8eb50d53eb6 100644 --- a/include/llvm/Support/BranchProbability.h +++ b/include/llvm/Support/BranchProbability.h @@ -203,7 +203,7 @@ void BranchProbability::normalizeProbabilities(ProbabilityIter Begin, if (Sum <= BranchProbability::getDenominator()) return; } - + if (Sum == 0) { BranchProbability BP(1, std::distance(Begin, End)); std::fill(Begin, End, BP); diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 0245632c96a0..7dad3e82bda6 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -377,7 +377,6 @@ namespace COFF { uint8_t unused[10]; }; - /// These are not documented in the spec, but are located in WinNT.h. enum WeakExternalCharacteristics { IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY = 1, IMAGE_WEAK_EXTERN_SEARCH_LIBRARY = 2, @@ -530,7 +529,7 @@ namespace COFF { EXCEPTION_TABLE, CERTIFICATE_TABLE, BASE_RELOCATION_TABLE, - DEBUG, + DEBUG_DIRECTORY, ARCHITECTURE, GLOBAL_PTR, TLS_TABLE, @@ -599,7 +598,13 @@ namespace COFF { IMAGE_DEBUG_TYPE_OMAP_TO_SRC = 7, IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8, IMAGE_DEBUG_TYPE_BORLAND = 9, - IMAGE_DEBUG_TYPE_CLSID = 11 + IMAGE_DEBUG_TYPE_RESERVED10 = 10, + IMAGE_DEBUG_TYPE_CLSID = 11, + IMAGE_DEBUG_TYPE_VC_FEATURE = 12, + IMAGE_DEBUG_TYPE_POGO = 13, + IMAGE_DEBUG_TYPE_ILTCG = 14, + IMAGE_DEBUG_TYPE_MPX = 15, + IMAGE_DEBUG_TYPE_REPRO = 16, }; enum BaseRelocationType { @@ -656,26 +661,8 @@ namespace COFF { } }; - enum CodeViewLine : unsigned { - CVL_LineNumberStartBits = 24, - CVL_LineNumberEndDeltaBits = 7, - CVL_LineNumberEndDeltaMask = (1U << CVL_LineNumberEndDeltaBits) - 1, - CVL_MaxLineNumber = (1U << CVL_LineNumberStartBits) - 1, - CVL_IsStatement = 1U << 31, - CVL_MaxColumnNumber = UINT16_MAX, - }; - enum CodeViewIdentifiers { - DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS = 0x1, DEBUG_SECTION_MAGIC = 0x4, - DEBUG_SYMBOL_SUBSECTION = 0xF1, - DEBUG_LINE_TABLE_SUBSECTION = 0xF2, - DEBUG_STRING_TABLE_SUBSECTION = 0xF3, - DEBUG_INDEX_SUBSECTION = 0xF4, - - // Symbol subsections are split into records of different types. - DEBUG_SYMBOL_TYPE_PROC_START = 0x1147, - DEBUG_SYMBOL_TYPE_PROC_END = 0x114F }; inline bool isReservedSectionNumber(int32_t SectionNumber) { diff --git a/include/llvm/Support/CachePruning.h b/include/llvm/Support/CachePruning.h new file mode 100644 index 000000000000..383414119139 --- /dev/null +++ b/include/llvm/Support/CachePruning.h @@ -0,0 +1,69 @@ +//=- CachePruning.h - Helper to manage the pruning of a cache dir -*- 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 pruning of a directory intended for cache storage, using +// various policies. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CACHE_PRUNING_H +#define LLVM_SUPPORT_CACHE_PRUNING_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +/// Handle pruning a directory provided a path and some options to control what +/// to prune. +class CachePruning { +public: + /// Prepare to prune \p Path. + CachePruning(StringRef Path) : Path(Path) {} + + /// Define the pruning interval. This is intended to be used to avoid scanning + /// the directory too often. It does not impact the decision of which file to + /// prune. A value of 0 forces the scan to occurs. + CachePruning &setPruningInterval(int PruningInterval) { + Interval = PruningInterval; + return *this; + } + + /// Define the expiration for a file. When a file hasn't been accessed for + /// \p ExpireAfter seconds, it is removed from the cache. A value of 0 disable + /// the expiration-based pruning. + CachePruning &setEntryExpiration(unsigned ExpireAfter) { + Expiration = ExpireAfter; + return *this; + } + + /// Define the maximum size for the cache directory, in terms of percentage of + /// the available space on the the disk. Set to 100 to indicate no limit, 50 + /// to indicate that the cache size will not be left over half the + /// available disk space. A value over 100 will be reduced to 100. A value of + /// 0 disable the size-based pruning. + CachePruning &setMaxSize(unsigned Percentage) { + PercentageOfAvailableSpace = std::min(100u, Percentage); + return *this; + } + + /// Peform pruning using the supplied options, returns true if pruning + /// occured, i.e. if PruningInterval was expired. + bool prune(); + +private: + // Options that matches the setters above. + std::string Path; + unsigned Expiration = 0; + unsigned Interval = 0; + unsigned PercentageOfAvailableSpace = 0; +}; + +} // namespace llvm + +#endif
\ No newline at end of file diff --git a/include/llvm/Support/CodeGen.h b/include/llvm/Support/CodeGen.h index 243f2dd7498c..e19abf8271eb 100644 --- a/include/llvm/Support/CodeGen.h +++ b/include/llvm/Support/CodeGen.h @@ -15,22 +15,25 @@ #ifndef LLVM_SUPPORT_CODEGEN_H #define LLVM_SUPPORT_CODEGEN_H -#include "llvm-c/TargetMachine.h" -#include "llvm/Support/ErrorHandling.h" - namespace llvm { // Relocation model types. namespace Reloc { - enum Model { Default, Static, PIC_, DynamicNoPIC }; + enum Model { Static, PIC_, DynamicNoPIC }; } // Code model types. namespace CodeModel { + // Sync changes with CodeGenCWrappers.h. enum Model { Default, JITDefault, Small, Kernel, Medium, Large }; } namespace PICLevel { + // This is used to map -fpic/-fPIC. + enum Level { NotPIC=0, SmallPIC=1, BigPIC=2 }; + } + + namespace PIELevel { enum Level { Default=0, Small=1, Large=2 }; } @@ -54,42 +57,6 @@ namespace llvm { }; } - // Create wrappers for C Binding types (see CBindingWrapping.h). - inline CodeModel::Model unwrap(LLVMCodeModel Model) { - switch (Model) { - case LLVMCodeModelDefault: - return CodeModel::Default; - case LLVMCodeModelJITDefault: - return CodeModel::JITDefault; - case LLVMCodeModelSmall: - return CodeModel::Small; - case LLVMCodeModelKernel: - return CodeModel::Kernel; - case LLVMCodeModelMedium: - return CodeModel::Medium; - case LLVMCodeModelLarge: - return CodeModel::Large; - } - return CodeModel::Default; - } - - inline LLVMCodeModel wrap(CodeModel::Model Model) { - switch (Model) { - case CodeModel::Default: - return LLVMCodeModelDefault; - case CodeModel::JITDefault: - return LLVMCodeModelJITDefault; - case CodeModel::Small: - return LLVMCodeModelSmall; - case CodeModel::Kernel: - return LLVMCodeModelKernel; - case CodeModel::Medium: - return LLVMCodeModelMedium; - case CodeModel::Large: - return LLVMCodeModelLarge; - } - llvm_unreachable("Bad CodeModel!"); - } } // end llvm namespace #endif diff --git a/include/llvm/Support/CodeGenCWrappers.h b/include/llvm/Support/CodeGenCWrappers.h new file mode 100644 index 000000000000..6db4433a4350 --- /dev/null +++ b/include/llvm/Support/CodeGenCWrappers.h @@ -0,0 +1,64 @@ +//===- llvm/Support/CodeGenCWrappers.h - CodeGen C Wrappers -----*- 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 C bindings wrappers for enums in llvm/Support/CodeGen.h +// that need them. The wrappers are separated to avoid adding an indirect +// dependency on llvm/Config/Targets.def to CodeGen.h. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CODEGENCWRAPPERS_H +#define LLVM_SUPPORT_CODEGENCWRAPPERS_H + +#include "llvm-c/TargetMachine.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/ErrorHandling.h" + +namespace llvm { + +inline CodeModel::Model unwrap(LLVMCodeModel Model) { + switch (Model) { + case LLVMCodeModelDefault: + return CodeModel::Default; + case LLVMCodeModelJITDefault: + return CodeModel::JITDefault; + case LLVMCodeModelSmall: + return CodeModel::Small; + case LLVMCodeModelKernel: + return CodeModel::Kernel; + case LLVMCodeModelMedium: + return CodeModel::Medium; + case LLVMCodeModelLarge: + return CodeModel::Large; + } + return CodeModel::Default; +} + +inline LLVMCodeModel wrap(CodeModel::Model Model) { + switch (Model) { + case CodeModel::Default: + return LLVMCodeModelDefault; + case CodeModel::JITDefault: + return LLVMCodeModelJITDefault; + case CodeModel::Small: + return LLVMCodeModelSmall; + case CodeModel::Kernel: + return LLVMCodeModelKernel; + case CodeModel::Medium: + return LLVMCodeModelMedium; + case CodeModel::Large: + return LLVMCodeModelLarge; + } + llvm_unreachable("Bad CodeModel!"); +} + +} // end llvm namespace + +#endif + diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 943d2df37708..70465a0e3fd3 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -21,10 +21,12 @@ #define LLVM_SUPPORT_COMMANDLINE_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/ManagedStatic.h" #include <cassert> #include <climits> #include <cstdarg> @@ -43,8 +45,9 @@ namespace cl { //===----------------------------------------------------------------------===// // ParseCommandLineOptions - Command line option processing entry point. // -void ParseCommandLineOptions(int argc, const char *const *argv, - const char *Overview = nullptr); +bool ParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview = nullptr, + bool IgnoreErrors = false); //===----------------------------------------------------------------------===// // ParseEnvironmentOptions - Environment variable option processing alternate @@ -171,6 +174,45 @@ public: extern OptionCategory GeneralCategory; //===----------------------------------------------------------------------===// +// SubCommand class +// +class SubCommand { +private: + const char *const Name = nullptr; + const char *const Description = nullptr; + +protected: + void registerSubCommand(); + void unregisterSubCommand(); + +public: + SubCommand(const char *const Name, const char *const Description = nullptr) + : Name(Name), Description(Description) { + registerSubCommand(); + } + SubCommand() {} + + void reset(); + + operator bool() const; + + const char *getName() const { return Name; } + const char *getDescription() const { return Description; } + + SmallVector<Option *, 4> PositionalOpts; + SmallVector<Option *, 4> SinkOpts; + StringMap<Option *> OptionsMap; + + Option *ConsumeAfterOpt = nullptr; // The ConsumeAfter option if it exists. +}; + +// A special subcommand representing no subcommand +extern ManagedStatic<SubCommand> TopLevelSubCommand; + +// A special subcommand that can be used to put an option into all subcommands. +extern ManagedStatic<SubCommand> AllSubCommands; + +//===----------------------------------------------------------------------===// // Option Base class // class alias; @@ -209,6 +251,7 @@ public: StringRef HelpStr; // The descriptive text message for -help StringRef ValueStr; // String describing what the value of this option is OptionCategory *Category; // The Category this option belongs to + SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to. bool FullyInitialized; // Has addArguemnt been called? inline enum NumOccurrencesFlag getNumOccurrencesFlag() const { @@ -229,6 +272,16 @@ public: // hasArgStr - Return true if the argstr != "" bool hasArgStr() const { return !ArgStr.empty(); } + bool isPositional() const { return getFormattingFlag() == cl::Positional; } + bool isSink() const { return getMiscFlags() & cl::Sink; } + bool isConsumeAfter() const { + return getNumOccurrencesFlag() == cl::ConsumeAfter; + } + bool isInAllSubCommands() const { + return std::any_of(Subs.begin(), Subs.end(), [](const SubCommand *SC) { + return SC == &*AllSubCommands; + }); + } //-------------------------------------------------------------------------=== // Accessor functions set by OptionModifiers @@ -243,6 +296,7 @@ public: void setMiscFlag(enum MiscFlags M) { Misc |= M; } void setPosition(unsigned pos) { Position = pos; } void setCategory(OptionCategory &C) { Category = &C; } + void addSubCommand(SubCommand &S) { Subs.insert(&S); } protected: explicit Option(enum NumOccurrencesFlag OccurrencesFlag, @@ -287,6 +341,7 @@ public: public: inline int getNumOccurrences() const { return NumOccurrences; } + inline void reset() { NumOccurrences = 0; } virtual ~Option() {} }; @@ -349,6 +404,14 @@ struct cat { template <class Opt> void apply(Opt &O) const { O.setCategory(Category); } }; +// sub - Specify the subcommand that this option belongs to. +struct sub { + SubCommand ⋐ + sub(SubCommand &S) : Sub(S) {} + + template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); } +}; + //===----------------------------------------------------------------------===// // OptionValue class @@ -946,7 +1009,7 @@ public: // getValueName - Overload in subclass to provide a better default value. const char *getValueName() const override { return "string"; } - void printOptionDiff(const Option &O, StringRef V, OptVal Default, + void printOptionDiff(const Option &O, StringRef V, const OptVal &Default, size_t GlobalWidth) const; // An out-of-line virtual method to provide a 'home' for this class. @@ -1589,6 +1652,7 @@ class alias : public Option { error("cl::alias must have argument name specified!"); if (!AliasFor) error("cl::alias must have an cl::aliasopt(option) specified!"); + Subs = AliasFor->Subs; addArgument(); } @@ -1669,7 +1733,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false); /// Hopefully this API can be depricated soon. Any situation where options need /// to be modified by tools or libraries should be handled by sane APIs rather /// than just handing around a global list. -StringMap<Option *> &getRegisteredOptions(); +StringMap<Option *> &getRegisteredOptions(SubCommand &Sub = *TopLevelSubCommand); //===----------------------------------------------------------------------===// // Standalone command line processing utilities. @@ -1737,7 +1801,8 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, /// Some tools (like clang-format) like to be able to hide all options that are /// not specific to the tool. This function allows a tool to specify a single /// option category to display in the -help output. -void HideUnrelatedOptions(cl::OptionCategory &Category); +void HideUnrelatedOptions(cl::OptionCategory &Category, + SubCommand &Sub = *TopLevelSubCommand); /// \brief Mark all options not part of the categories as cl::ReallyHidden. /// @@ -1746,7 +1811,19 @@ void HideUnrelatedOptions(cl::OptionCategory &Category); /// Some tools (like clang-format) like to be able to hide all options that are /// not specific to the tool. This function allows a tool to specify a single /// option category to display in the -help output. -void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories); +void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories, + SubCommand &Sub = *TopLevelSubCommand); + +/// \brief Reset all command line options to a state that looks as if they have +/// never appeared on the command line. This is useful for being able to parse +/// a command line multiple times (especially useful for writing tests). +void ResetAllOptionOccurrences(); + +/// \brief Reset the command line parser back to its initial state. This +/// removes +/// all options, categories, and subcommands and returns the parser to a state +/// where no options are supported. +void ResetCommandLineParser(); } // End namespace cl diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index b3416bbfffb6..fae0d8f4419e 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -17,6 +17,10 @@ #include "llvm/Config/llvm-config.h" +#if defined(_MSC_VER) +#include <sal.h> +#endif + #ifndef __has_feature # define __has_feature(x) 0 #endif @@ -92,7 +96,7 @@ #define LLVM_LVALUE_FUNCTION #endif -#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) +#if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1900) # define LLVM_CONSTEXPR constexpr #else # define LLVM_CONSTEXPR @@ -124,6 +128,8 @@ #if __has_attribute(warn_unused_result) || LLVM_GNUC_PREREQ(3, 4, 0) #define LLVM_ATTRIBUTE_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_UNUSED_RESULT _Check_return_ #else #define LLVM_ATTRIBUTE_UNUSED_RESULT #endif @@ -206,6 +212,8 @@ #if __has_attribute(returns_nonnull) || LLVM_GNUC_PREREQ(4, 9, 0) #define LLVM_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_RETURNS_NONNULL _Ret_notnull_ #else #define LLVM_ATTRIBUTE_RETURNS_NONNULL #endif @@ -266,6 +274,23 @@ # define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 #endif +/// LLVM_BUILTIN_DEBUGTRAP - On compilers which support it, expands to +/// an expression which causes the program to break while running +/// under a debugger. +#if __has_builtin(__builtin_debugtrap) +# define LLVM_BUILTIN_DEBUGTRAP __builtin_debugtrap() +#elif defined(_MSC_VER) +// The __debugbreak intrinsic is supported by MSVC and breaks while +// running under the debugger, and also supports invoking a debugger +// when the OS is configured appropriately. +# define LLVM_BUILTIN_DEBUGTRAP __debugbreak() +#else +// Just continue execution when built with compilers that have no +// support. This is a debugging aid and not intended to force the +// program to abort if encountered. +# define LLVM_BUILTIN_DEBUGTRAP +#endif + /// \macro LLVM_ASSUME_ALIGNED /// \brief Returns a pointer with an assumed alignment. #if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0) @@ -407,6 +432,14 @@ void AnnotateIgnoreWritesEnd(const char *file, int line); # define TsanIgnoreWritesEnd() #endif +/// \macro LLVM_NO_SANITIZE +/// \brief Disable a particular sanitizer for a function. +#if __has_attribute(no_sanitize) +#define LLVM_NO_SANITIZE(KIND) __attribute__((no_sanitize(KIND))) +#else +#define LLVM_NO_SANITIZE(KIND) +#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. diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h index 38952ec99e61..5de5774f9db5 100644 --- a/include/llvm/Support/ConvertUTF.h +++ b/include/llvm/Support/ConvertUTF.h @@ -180,10 +180,13 @@ unsigned getNumBytesForUTF8(UTF8 firstByte); /*************************************************************************/ /* Below are LLVM-specific wrappers of the functions above. */ -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" +#include <string> +#include <cstddef> namespace llvm { +template <typename T> class ArrayRef; +template <typename T> class SmallVectorImpl; +class StringRef; /** * Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on @@ -198,6 +201,25 @@ bool ConvertUTF8toWide(unsigned WideCharWidth, llvm::StringRef Source, char *&ResultPtr, const UTF8 *&ErrorPtr); /** +* Converts a UTF-8 StringRef to a std::wstring. +* \return true on success. +*/ +bool ConvertUTF8toWide(llvm::StringRef Source, std::wstring &Result); + +/** +* Converts a UTF-8 C-string to a std::wstring. +* \return true on success. +*/ +bool ConvertUTF8toWide(const char *Source, std::wstring &Result); + +/** +* Converts a std::wstring to a UTF-8 encoded std::string. +* \return true on success. +*/ +bool convertWideToUTF8(const std::wstring &Source, std::string &Result); + + +/** * Convert an Unicode code point to UTF8 sequence. * * \param Source a Unicode code point. @@ -252,6 +274,15 @@ bool hasUTF16ByteOrderMark(ArrayRef<char> SrcBytes); bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out); /** +* Converts a UTF16 string into a UTF8 std::string. +* +* \param [in] Src A buffer of UTF-16 encoded text. +* \param [out] Out Converted UTF-8 is stored here on success. +* \returns true on success +*/ +bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out); + +/** * Converts a UTF-8 string into a UTF-16 string with native endianness. * * \returns true on success diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index 1a1c74368761..6cbc331d2731 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -11,7 +11,6 @@ #define LLVM_SUPPORT_CRASHRECOVERYCONTEXT_H #include "llvm/ADT/STLExtras.h" -#include <string> namespace llvm { class CrashRecoveryContextCleanup; @@ -70,8 +69,7 @@ public: /// \return True if the function completed successfully, and false if the /// function crashed (or HandleCrash was called explicitly). Clients should /// 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. + /// RunSafely has returned false. bool RunSafely(function_ref<void()> Fn); bool RunSafely(void (*Fn)(void*), void *UserData) { return RunSafely([&]() { Fn(UserData); }); @@ -94,13 +92,6 @@ public: /// \brief Explicitly trigger a crash recovery in the current process, and /// return failure from RunSafely(). This function does not return. void HandleCrash(); - - /// \brief Return a string containing the backtrace where the crash was - /// detected; or empty if the backtrace wasn't recovered. - /// - /// This function is only valid when a crash has been detected (i.e., - /// RunSafely() has returned false. - const std::string &getBacktrace() const; }; class CrashRecoveryContextCleanup { diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake index c90bf51afaee..541dbc3d635d 100644 --- a/include/llvm/Support/DataTypes.h.cmake +++ b/include/llvm/Support/DataTypes.h.cmake @@ -21,8 +21,6 @@ /* Please leave this file C-compatible. */ -/* Please keep this file in sync with DataTypes.h.in */ - #ifndef SUPPORT_DATATYPES_H #define SUPPORT_DATATYPES_H @@ -37,36 +35,43 @@ #include <math.h> #endif +#ifdef __cplusplus +#include <cinttypes> +#else #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif +#endif +#ifdef __cplusplus +#include <cstdint> +#else #ifdef HAVE_STDINT_H #include <stdint.h> #else #error "Compiler must provide an implementation of stdint.h" #endif +#endif #ifndef _MSC_VER -/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS - being defined. We would define it here, but in order to prevent Bad Things - happening when system headers or C++ STL headers include stdint.h before we - define it here, we define it on the g++ command line (in Makefile.rules). */ -#if !defined(__STDC_LIMIT_MACROS) -# error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h" +#if !defined(UINT32_MAX) +# error "The standard header <cstdint> is not C++11 compliant. Must #define "\ + "__STDC_LIMIT_MACROS before #including Support/DataTypes.h" #endif -#if !defined(__STDC_CONSTANT_MACROS) -# error "Must #define __STDC_CONSTANT_MACROS before " \ - "#including Support/DataTypes.h" +#if !defined(UINT32_C) +# error "The standard header <cstdint> is not C++11 compliant. Must #define "\ + "__STDC_CONSTANT_MACROS before #including Support/DataTypes.h" #endif /* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ #include <sys/types.h> #ifdef _AIX -#include "llvm/Support/AIXDataTypesFix.h" +// GCC is strict about defining large constants: they must have LL modifier. +#undef INT64_MAX +#undef INT64_MIN #endif /* Handle incorrect definition of uint64_t as u_int64_t */ @@ -79,14 +84,14 @@ typedef u_int64_t uint64_t; #endif #else /* _MSC_VER */ -#include <stdlib.h> -#include <stddef.h> -#include <sys/types.h> #ifdef __cplusplus -#include <cmath> +#include <cstdlib> +#include <cstddef> #else -#include <math.h> +#include <stdlib.h> +#include <stddef.h> #endif +#include <sys/types.h> #if defined(_WIN64) typedef signed __int64 ssize_t; @@ -127,4 +132,4 @@ typedef signed int ssize_t; #define HUGE_VALF (float)HUGE_VAL #endif -#endif /* SUPPORT_DATATYPES_H */ +#endif /* SUPPORT_DATATYPES_H */ diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in deleted file mode 100644 index b8b2ba56ff30..000000000000 --- a/include/llvm/Support/DataTypes.h.in +++ /dev/null @@ -1,123 +0,0 @@ -/*===-- include/Support/DataTypes.h - Define fixed size types -----*- C -*-===*\ -|* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| -|* *| -|*===----------------------------------------------------------------------===*| -|* *| -|* This file contains definitions to figure out the size of _HOST_ data types.*| -|* This file is important because different host OS's define different macros,*| -|* which makes portability tough. This file exports the following *| -|* definitions: *| -|* *| -|* [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types*| -|* [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. *| -|* *| -|* No library is required when using these functions. *| -|* *| -|*===----------------------------------------------------------------------===*/ - -/* Please leave this file C-compatible. */ - -/* Please keep this file in sync with DataTypes.h.cmake */ - -#ifndef SUPPORT_DATATYPES_H -#define SUPPORT_DATATYPES_H - -#undef HAVE_INTTYPES_H -#undef HAVE_STDINT_H -#undef HAVE_UINT64_T -#undef HAVE_U_INT64_T - -#ifdef __cplusplus -#include <cmath> -#else -#include <math.h> -#endif - -#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 - being defined. We would define it here, but in order to prevent Bad Things - happening when system headers or C++ STL headers include stdint.h before we - define it here, we define it on the g++ command line (in Makefile.rules). */ -#if !defined(__STDC_LIMIT_MACROS) -# error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h" -#endif - -#if !defined(__STDC_CONSTANT_MACROS) -# error "Must #define __STDC_CONSTANT_MACROS before " \ - "#including Support/DataTypes.h" -#endif - -/* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ -#include <sys/types.h> - -#ifdef _AIX -#include "llvm/Support/AIXDataTypesFix.h" -#endif - -/* Handle incorrect definition of uint64_t as u_int64_t */ -#ifndef HAVE_UINT64_T -#ifdef HAVE_U_INT64_T -typedef u_int64_t uint64_t; -#else -# error "Don't have a definition for uint64_t on this platform" -#endif -#endif - -#else /* _MSC_VER */ -#include <stdlib.h> -#include <stddef.h> -#include <sys/types.h> -#ifdef __cplusplus -#include <cmath> -#else -#include <math.h> -#endif - -#if defined(_WIN64) -typedef signed __int64 ssize_t; -#else -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 */ - -/* Set defaults for constants which we cannot find. */ -#if !defined(INT64_MAX) -# define INT64_MAX 9223372036854775807LL -#endif -#if !defined(INT64_MIN) -# define INT64_MIN ((-INT64_MAX)-1) -#endif -#if !defined(UINT64_MAX) -# define UINT64_MAX 0xffffffffffffffffULL -#endif - -#ifndef HUGE_VALF -#define HUGE_VALF (float)HUGE_VAL -#endif - -#endif /* SUPPORT_DATATYPES_H */ diff --git a/include/llvm/Support/Dwarf.def b/include/llvm/Support/Dwarf.def index b15070b3e9b0..b73f2aed5311 100644 --- a/include/llvm/Support/Dwarf.def +++ b/include/llvm/Support/Dwarf.def @@ -14,7 +14,7 @@ // TODO: Add other DW-based macros. #if !(defined HANDLE_DW_TAG || defined HANDLE_DW_OP || \ defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \ - defined HANDLE_DW_VIRTUALITY) + defined HANDLE_DW_VIRTUALITY || defined HANDLE_DW_CC) #error "Missing macro definition of HANDLE_DW*" #endif @@ -38,6 +38,11 @@ #define HANDLE_DW_VIRTUALITY(ID, NAME) #endif +#ifndef HANDLE_DW_CC +#define HANDLE_DW_CC(ID, NAME) +#endif + + HANDLE_DW_TAG(0x0001, array_type) HANDLE_DW_TAG(0x0002, class_type) HANDLE_DW_TAG(0x0003, entry_point) @@ -320,6 +325,7 @@ HANDLE_DW_LANG(0x0021, C_plus_plus_14) HANDLE_DW_LANG(0x0022, Fortran03) HANDLE_DW_LANG(0x0023, Fortran08) HANDLE_DW_LANG(0x8001, Mips_Assembler) +HANDLE_DW_LANG(0x8e57, GOOGLE_RenderScript) HANDLE_DW_LANG(0xb000, BORLAND_Delphi) // DWARF attribute type encodings. @@ -345,8 +351,23 @@ HANDLE_DW_VIRTUALITY(0x00, none) HANDLE_DW_VIRTUALITY(0x01, virtual) HANDLE_DW_VIRTUALITY(0x02, pure_virtual) +// DWARF calling convention codes. +HANDLE_DW_CC(0x01, normal) +HANDLE_DW_CC(0x02, program) +HANDLE_DW_CC(0x03, nocall) +HANDLE_DW_CC(0x41, GNU_borland_fastcall_i386) +HANDLE_DW_CC(0xb0, BORLAND_safecall) +HANDLE_DW_CC(0xb1, BORLAND_stdcall) +HANDLE_DW_CC(0xb2, BORLAND_pascal) +HANDLE_DW_CC(0xb3, BORLAND_msfastcall) +HANDLE_DW_CC(0xb4, BORLAND_msreturn) +HANDLE_DW_CC(0xb5, BORLAND_thiscall) +HANDLE_DW_CC(0xb6, BORLAND_fastcall) +HANDLE_DW_CC(0xc0, LLVM_vectorcall) + #undef HANDLE_DW_TAG #undef HANDLE_DW_OP #undef HANDLE_DW_LANG #undef HANDLE_DW_ATE #undef HANDLE_DW_VIRTUALITY +#undef HANDLE_DW_CC diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index cea61bd75833..86b19676c345 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -20,11 +20,11 @@ #ifndef LLVM_SUPPORT_DWARF_H #define LLVM_SUPPORT_DWARF_H -#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" namespace llvm { +class StringRef; namespace dwarf { @@ -389,18 +389,9 @@ enum CaseSensitivity { enum CallingConvention { // Calling convention codes - DW_CC_normal = 0x01, - DW_CC_program = 0x02, - DW_CC_nocall = 0x03, +#define HANDLE_DW_CC(ID, NAME) DW_CC_##NAME = ID, +#include "llvm/Support/Dwarf.def" DW_CC_lo_user = 0x40, - DW_CC_GNU_borland_fastcall_i386 = 0x41, - DW_CC_BORLAND_safecall = 0xb0, - DW_CC_BORLAND_stdcall = 0xb1, - DW_CC_BORLAND_pascal = 0xb2, - DW_CC_BORLAND_msfastcall = 0xb3, - DW_CC_BORLAND_msreturn = 0xb4, - DW_CC_BORLAND_thiscall = 0xb5, - DW_CC_BORLAND_fastcall = 0xb6, DW_CC_hi_user = 0xff }; @@ -547,7 +538,7 @@ enum LocationListEntry : unsigned char { DW_LLE_offset_pair_entry }; -/// Contstants for the DW_APPLE_PROPERTY_attributes attribute. +/// Constants for the DW_APPLE_PROPERTY_attributes attribute. /// Keep this list in sync with clang's DeclSpec.h ObjCPropertyAttributeKind. enum ApplePropertyAttributes { // Apple Objective-C Property Attributes @@ -562,7 +553,10 @@ enum ApplePropertyAttributes { DW_APPLE_PROPERTY_atomic = 0x100, DW_APPLE_PROPERTY_weak = 0x200, DW_APPLE_PROPERTY_strong = 0x400, - DW_APPLE_PROPERTY_unsafe_unretained = 0x800 + DW_APPLE_PROPERTY_unsafe_unretained = 0x800, + DW_APPLE_PROPERTY_nullability = 0x1000, + DW_APPLE_PROPERTY_null_resettable = 0x2000, + DW_APPLE_PROPERTY_class = 0x4000 }; // Constants for the DWARF5 Accelerator Table Proposal @@ -652,6 +646,7 @@ unsigned getTag(StringRef TagString); unsigned getOperationEncoding(StringRef OperationEncodingString); unsigned getVirtuality(StringRef VirtualityString); unsigned getLanguage(StringRef LanguageString); +unsigned getCallingConvention(StringRef LanguageString); unsigned getAttributeEncoding(StringRef EncodingString); unsigned getMacinfo(StringRef MacinfoString); /// @} diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index e24420fc1fe4..70b9daab8360 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -310,6 +310,8 @@ enum { EM_NORC = 218, // Nanoradio Optimized RISC EM_CSR_KALIMBA = 219, // CSR Kalimba architecture family EM_AMDGPU = 224, // AMD GPU architecture + EM_LANAI = 244, // Lanai 32-bit processor + EM_BPF = 247, // Linux kernel bpf virtual machine // A request has been made to the maintainer of the official registry for // such numbers for an official value for WebAssembly. As soon as one is @@ -481,6 +483,7 @@ enum : unsigned { EF_MIPS_ABI = 0x0000f000, // Mask for selecting EF_MIPS_ABI_ variant. // MIPS machine variant + EF_MIPS_MACH_NONE = 0x00000000, // A standard MIPS implementation. EF_MIPS_MACH_3900 = 0x00810000, // Toshiba R3900 EF_MIPS_MACH_4010 = 0x00820000, // LSI R4010 EF_MIPS_MACH_4100 = 0x00830000, // NEC VR4100 @@ -589,6 +592,11 @@ enum { #include "ELFRelocs/Hexagon.def" }; +// ELF Relocation type for Lanai. +enum { +#include "ELFRelocs/Lanai.def" +}; + // ELF Relocation types for S390/zSeries enum { #include "ELFRelocs/SystemZ.def" @@ -604,6 +612,16 @@ enum { #include "ELFRelocs/WebAssembly.def" }; +// ELF Relocation types for AMDGPU +enum { +#include "ELFRelocs/AMDGPU.def" +}; + +// ELF Relocation types for BPF +enum { +#include "ELFRelocs/BPF.def" +}; + #undef ELF_RELOC // Section header. @@ -730,6 +748,9 @@ enum : unsigned { // This section holds Thread-Local Storage. SHF_TLS = 0x400U, + // Identifies a section containing compressed data. + SHF_COMPRESSED = 0x800U, + // This section is excluded from the final executable or shared library. SHF_EXCLUDE = 0x80000000U, @@ -1116,6 +1137,8 @@ enum { DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags. DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table. + DT_TLSDESC_PLT = 0x6FFFFEF6, // Location of PLT entry for TLS descriptor resolver calls. + DT_TLSDESC_GOT = 0x6FFFFEF7, // Location of GOT entry used by TLS descriptor resolver PLT entry. DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count. DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. @@ -1199,8 +1222,12 @@ enum { DT_MIPS_PLTGOT = 0x70000032, // Address of the base of the PLTGOT. DT_MIPS_RWPLT = 0x70000034, // Points to the base // of a writable PLT. - DT_MIPS_RLD_MAP_REL = 0x70000035 // Relative offset of run time loader + DT_MIPS_RLD_MAP_REL = 0x70000035, // Relative offset of run time loader // map, used for debugging. + + // Sun machine-independent extensions. + DT_AUXILIARY = 0x7FFFFFFD, // Shared object to load before self + DT_FILTER = 0x7FFFFFFF // Shared object to get values from }; // DT_FLAGS values. @@ -1294,6 +1321,35 @@ enum { VER_NEED_CURRENT = 1 }; +// SHT_NOTE section types +enum { + NT_GNU_BUILD_ID = 3 +}; + +// Compressed section header for ELF32. +struct Elf32_Chdr { + Elf32_Word ch_type; + Elf32_Word ch_size; + Elf32_Word ch_addralign; +}; + +// Compressed section header for ELF64. +struct Elf64_Chdr { + Elf64_Word ch_type; + Elf64_Word ch_reserved; + Elf64_Xword ch_size; + Elf64_Xword ch_addralign; +}; + +// Legal values for ch_type field of compressed section header. +enum { + ELFCOMPRESS_ZLIB = 1, // ZLIB/DEFLATE algorithm. + ELFCOMPRESS_LOOS = 0x60000000, // Start of OS-specific. + ELFCOMPRESS_HIOS = 0x6fffffff, // End of OS-specific. + ELFCOMPRESS_LOPROC = 0x70000000, // Start of processor-specific. + ELFCOMPRESS_HIPROC = 0x7fffffff // End of processor-specific. +}; + } // end namespace ELF } // end namespace llvm diff --git a/include/llvm/Support/ELFRelocs/AMDGPU.def b/include/llvm/Support/ELFRelocs/AMDGPU.def new file mode 100644 index 000000000000..c1e6797fdb0d --- /dev/null +++ b/include/llvm/Support/ELFRelocs/AMDGPU.def @@ -0,0 +1,12 @@ +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_AMDGPU_NONE, 0) +ELF_RELOC(R_AMDGPU_ABS32_LO, 1) +ELF_RELOC(R_AMDGPU_ABS32_HI, 2) +ELF_RELOC(R_AMDGPU_ABS64, 3) +ELF_RELOC(R_AMDGPU_REL32, 4) +ELF_RELOC(R_AMDGPU_REL64, 5) +ELF_RELOC(R_AMDGPU_ABS32, 6) +ELF_RELOC(R_AMDGPU_GOTPCREL, 7) diff --git a/include/llvm/Support/ELFRelocs/BPF.def b/include/llvm/Support/ELFRelocs/BPF.def new file mode 100644 index 000000000000..868974d683c7 --- /dev/null +++ b/include/llvm/Support/ELFRelocs/BPF.def @@ -0,0 +1,9 @@ +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// No relocation +ELF_RELOC(R_BPF_NONE, 0) +// Map index in "maps" section to file descriptor +// within ld_64 instruction. +ELF_RELOC(R_BPF_MAP_FD, 1) diff --git a/include/llvm/Support/ELFRelocs/Hexagon.def b/include/llvm/Support/ELFRelocs/Hexagon.def index a698ecb89e16..74e1d405cebd 100644 --- a/include/llvm/Support/ELFRelocs/Hexagon.def +++ b/include/llvm/Support/ELFRelocs/Hexagon.def @@ -98,3 +98,4 @@ ELF_RELOC(R_HEX_LD_GOT_16, 90) ELF_RELOC(R_HEX_LD_GOT_32_6_X, 91) ELF_RELOC(R_HEX_LD_GOT_16_X, 92) ELF_RELOC(R_HEX_LD_GOT_11_X, 93) +ELF_RELOC(R_HEX_23_REG, 94) diff --git a/include/llvm/Support/ELFRelocs/Lanai.def b/include/llvm/Support/ELFRelocs/Lanai.def new file mode 100644 index 000000000000..77ecb048403d --- /dev/null +++ b/include/llvm/Support/ELFRelocs/Lanai.def @@ -0,0 +1,19 @@ + +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// No relocation +ELF_RELOC(R_LANAI_NONE, 0) +// 21-bit symbol relocation +ELF_RELOC(R_LANAI_21, 1) +// 21-bit symbol relocation with last two bits masked to 0 +ELF_RELOC(R_LANAI_21_F, 2) +// 25-bit branch targets +ELF_RELOC(R_LANAI_25, 3) +// General 32-bit relocation +ELF_RELOC(R_LANAI_32, 4) +// Upper 16-bits of a symbolic relocation +ELF_RELOC(R_LANAI_HI16, 5) +// Lower 16-bits of a symbolic relocation +ELF_RELOC(R_LANAI_LO16, 6) diff --git a/include/llvm/Support/ELFRelocs/Mips.def b/include/llvm/Support/ELFRelocs/Mips.def index 77e7f8e8712b..bc0088dff3f4 100644 --- a/include/llvm/Support/ELFRelocs/Mips.def +++ b/include/llvm/Support/ELFRelocs/Mips.def @@ -108,8 +108,8 @@ ELF_RELOC(R_MICROMIPS_TLS_TPREL_HI16, 169) ELF_RELOC(R_MICROMIPS_TLS_TPREL_LO16, 170) ELF_RELOC(R_MICROMIPS_GPREL7_S2, 172) ELF_RELOC(R_MICROMIPS_PC23_S2, 173) -ELF_RELOC(R_MICROMIPS_PC21_S2, 174) -ELF_RELOC(R_MICROMIPS_PC26_S2, 175) +ELF_RELOC(R_MICROMIPS_PC21_S1, 174) +ELF_RELOC(R_MICROMIPS_PC26_S1, 175) ELF_RELOC(R_MICROMIPS_PC18_S3, 176) ELF_RELOC(R_MICROMIPS_PC19_S2, 177) ELF_RELOC(R_MIPS_NUM, 218) diff --git a/include/llvm/Support/ELFRelocs/i386.def b/include/llvm/Support/ELFRelocs/i386.def index 45eae7fe426b..1d28cf595cd5 100644 --- a/include/llvm/Support/ELFRelocs/i386.def +++ b/include/llvm/Support/ELFRelocs/i386.def @@ -44,4 +44,4 @@ ELF_RELOC(R_386_TLS_GOTDESC, 39) ELF_RELOC(R_386_TLS_DESC_CALL, 40) ELF_RELOC(R_386_TLS_DESC, 41) ELF_RELOC(R_386_IRELATIVE, 42) -ELF_RELOC(R_386_NUM, 43) +ELF_RELOC(R_386_GOT32X, 43) diff --git a/include/llvm/Support/ELFRelocs/x86_64.def b/include/llvm/Support/ELFRelocs/x86_64.def index 36ad0618eb2d..18fdcf9472dc 100644 --- a/include/llvm/Support/ELFRelocs/x86_64.def +++ b/include/llvm/Support/ELFRelocs/x86_64.def @@ -41,4 +41,5 @@ ELF_RELOC(R_X86_64_GOTPC32_TLSDESC, 34) ELF_RELOC(R_X86_64_TLSDESC_CALL, 35) ELF_RELOC(R_X86_64_TLSDESC, 36) ELF_RELOC(R_X86_64_IRELATIVE, 37) - +ELF_RELOC(R_X86_64_GOTPCRELX, 41) +ELF_RELOC(R_X86_64_REX_GOTPCRELX, 42) diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index bc93c9a66eef..cb5cd8e511b1 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -173,6 +173,10 @@ template<typename value_type, endianness endian, std::size_t alignment> struct packed_endian_specific_integral { + packed_endian_specific_integral() = default; + + explicit packed_endian_specific_integral(value_type val) { *this = val; } + operator value_type() const { return endian::read<value_type, endian, alignment>( (const void*)Value.buffer); diff --git a/include/llvm/Support/EndianStream.h b/include/llvm/Support/EndianStream.h index d44a9b3b7ce8..43ecd4a5c97e 100644 --- a/include/llvm/Support/EndianStream.h +++ b/include/llvm/Support/EndianStream.h @@ -15,6 +15,7 @@ #ifndef LLVM_SUPPORT_ENDIANSTREAM_H #define LLVM_SUPPORT_ENDIANSTREAM_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Endian.h" #include "llvm/Support/raw_ostream.h" @@ -26,6 +27,10 @@ namespace endian { template <endianness endian> struct Writer { raw_ostream &OS; Writer(raw_ostream &OS) : OS(OS) {} + template <typename value_type> void write(ArrayRef<value_type> Vals) { + for (value_type V : Vals) + write(V); + } template <typename value_type> void write(value_type Val) { Val = byte_swap<value_type, endian>(Val); OS.write((const char *)&Val, sizeof(value_type)); diff --git a/include/llvm/Support/Error.h b/include/llvm/Support/Error.h new file mode 100644 index 000000000000..5f515a88a021 --- /dev/null +++ b/include/llvm/Support/Error.h @@ -0,0 +1,950 @@ +//===----- llvm/Support/Error.h - Recoverable error handling ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an API used to report recoverable errors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ERROR_H +#define LLVM_SUPPORT_ERROR_H + +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/raw_ostream.h" +#include <vector> + +namespace llvm { + +class Error; +class ErrorList; + +/// Base class for error info classes. Do not extend this directly: Extend +/// the ErrorInfo template subclass instead. +class ErrorInfoBase { +public: + virtual ~ErrorInfoBase() {} + + /// Print an error message to an output stream. + virtual void log(raw_ostream &OS) const = 0; + + /// Return the error message as a string. + virtual std::string message() const { + std::string Msg; + raw_string_ostream OS(Msg); + log(OS); + return OS.str(); + } + + /// Convert this error to a std::error_code. + /// + /// This is a temporary crutch to enable interaction with code still + /// using std::error_code. It will be removed in the future. + virtual std::error_code convertToErrorCode() const = 0; + + // Check whether this instance is a subclass of the class identified by + // ClassID. + virtual bool isA(const void *const ClassID) const { + return ClassID == classID(); + } + + // Check whether this instance is a subclass of ErrorInfoT. + template <typename ErrorInfoT> bool isA() const { + return isA(ErrorInfoT::classID()); + } + + // Returns the class ID for this type. + static const void *classID() { return &ID; } + +private: + virtual void anchor(); + static char ID; +}; + +/// Lightweight error class with error context and mandatory checking. +/// +/// Instances of this class wrap a ErrorInfoBase pointer. Failure states +/// are represented by setting the pointer to a ErrorInfoBase subclass +/// instance containing information describing the failure. Success is +/// represented by a null pointer value. +/// +/// Instances of Error also contains a 'Checked' flag, which must be set +/// before the destructor is called, otherwise the destructor will trigger a +/// runtime error. This enforces at runtime the requirement that all Error +/// instances be checked or returned to the caller. +/// +/// There are two ways to set the checked flag, depending on what state the +/// Error instance is in. For Error instances indicating success, it +/// is sufficient to invoke the boolean conversion operator. E.g.: +/// +/// Error foo(<...>); +/// +/// if (auto E = foo(<...>)) +/// return E; // <- Return E if it is in the error state. +/// // We have verified that E was in the success state. It can now be safely +/// // destroyed. +/// +/// A success value *can not* be dropped. For example, just calling 'foo(<...>)' +/// without testing the return value will raise a runtime error, even if foo +/// returns success. +/// +/// For Error instances representing failure, you must use either the +/// handleErrors or handleAllErrors function with a typed handler. E.g.: +/// +/// class MyErrorInfo : public ErrorInfo<MyErrorInfo> { +/// // Custom error info. +/// }; +/// +/// Error foo(<...>) { return make_error<MyErrorInfo>(...); } +/// +/// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo. +/// auto NewE = +/// handleErrors(E, +/// [](const MyErrorInfo &M) { +/// // Deal with the error. +/// }, +/// [](std::unique_ptr<OtherError> M) -> Error { +/// if (canHandle(*M)) { +/// // handle error. +/// return Error::success(); +/// } +/// // Couldn't handle this error instance. Pass it up the stack. +/// return Error(std::move(M)); +/// ); +/// // Note - we must check or return NewE in case any of the handlers +/// // returned a new error. +/// +/// The handleAllErrors function is identical to handleErrors, except +/// that it has a void return type, and requires all errors to be handled and +/// no new errors be returned. It prevents errors (assuming they can all be +/// handled) from having to be bubbled all the way to the top-level. +/// +/// *All* Error instances must be checked before destruction, even if +/// they're moved-assigned or constructed from Success values that have already +/// been checked. This enforces checking through all levels of the call stack. +class Error { + + // ErrorList needs to be able to yank ErrorInfoBase pointers out of this + // class to add to the error list. + friend class ErrorList; + + // handleErrors needs to be able to set the Checked flag. + template <typename... HandlerTs> + friend Error handleErrors(Error E, HandlerTs &&... Handlers); + + // Expected<T> needs to be able to steal the payload when constructed from an + // error. + template <typename T> class Expected; + +public: + /// Create a success value. Prefer using 'Error::success()' for readability + /// where possible. + Error() { + setPtr(nullptr); + setChecked(false); + } + + /// Create a success value. This is equivalent to calling the default + /// constructor, but should be preferred for readability where possible. + static Error success() { return Error(); } + + // Errors are not copy-constructable. + Error(const Error &Other) = delete; + + /// Move-construct an error value. The newly constructed error is considered + /// unchecked, even if the source error had been checked. The original error + /// becomes a checked Success value, regardless of its original state. + Error(Error &&Other) { + setChecked(true); + *this = std::move(Other); + } + + /// Create an error value. Prefer using the 'make_error' function, but + /// this constructor can be useful when "re-throwing" errors from handlers. + Error(std::unique_ptr<ErrorInfoBase> Payload) { + setPtr(Payload.release()); + setChecked(false); + } + + // Errors are not copy-assignable. + Error &operator=(const Error &Other) = delete; + + /// Move-assign an error value. The current error must represent success, you + /// you cannot overwrite an unhandled error. The current error is then + /// considered unchecked. The source error becomes a checked success value, + /// regardless of its original state. + Error &operator=(Error &&Other) { + // Don't allow overwriting of unchecked values. + assertIsChecked(); + setPtr(Other.getPtr()); + + // This Error is unchecked, even if the source error was checked. + setChecked(false); + + // Null out Other's payload and set its checked bit. + Other.setPtr(nullptr); + Other.setChecked(true); + + return *this; + } + + /// Destroy a Error. Fails with a call to abort() if the error is + /// unchecked. + ~Error() { + assertIsChecked(); + delete getPtr(); + } + + /// Bool conversion. Returns true if this Error is in a failure state, + /// and false if it is in an accept state. If the error is in a Success state + /// it will be considered checked. + explicit operator bool() { + setChecked(getPtr() == nullptr); + return getPtr() != nullptr; + } + + /// Check whether one error is a subclass of another. + template <typename ErrT> bool isA() const { + return getPtr() && getPtr()->isA(ErrT::classID()); + } + +private: + void assertIsChecked() { +#ifndef NDEBUG + if (!getChecked() || getPtr()) { + dbgs() << "Program aborted due to an unhandled Error:\n"; + if (getPtr()) + getPtr()->log(dbgs()); + else + dbgs() + << "Error value was Success. (Note: Success values must still be " + "checked prior to being destroyed).\n"; + abort(); + } +#endif + } + + ErrorInfoBase *getPtr() const { +#ifndef NDEBUG + return PayloadAndCheckedBit.getPointer(); +#else + return Payload; +#endif + } + + void setPtr(ErrorInfoBase *EI) { +#ifndef NDEBUG + PayloadAndCheckedBit.setPointer(EI); +#else + Payload = EI; +#endif + } + + bool getChecked() const { +#ifndef NDEBUG + return PayloadAndCheckedBit.getInt(); +#else + return true; +#endif + } + + void setChecked(bool V) { +#ifndef NDEBUG + PayloadAndCheckedBit.setInt(V); +#endif + } + + std::unique_ptr<ErrorInfoBase> takePayload() { + std::unique_ptr<ErrorInfoBase> Tmp(getPtr()); + setPtr(nullptr); + setChecked(true); + return Tmp; + } + +#ifndef NDEBUG + PointerIntPair<ErrorInfoBase *, 1> PayloadAndCheckedBit; +#else + ErrorInfoBase *Payload; +#endif +}; + +/// Make a Error instance representing failure using the given error info +/// type. +template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) { + return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...)); +} + +/// Base class for user error types. Users should declare their error types +/// like: +/// +/// class MyError : public ErrorInfo<MyError> { +/// .... +/// }; +/// +/// This class provides an implementation of the ErrorInfoBase::kind +/// method, which is used by the Error RTTI system. +template <typename ThisErrT, typename ParentErrT = ErrorInfoBase> +class ErrorInfo : public ParentErrT { +public: + bool isA(const void *const ClassID) const override { + return ClassID == classID() || ParentErrT::isA(ClassID); + } + + static const void *classID() { return &ThisErrT::ID; } +}; + +/// Special ErrorInfo subclass representing a list of ErrorInfos. +/// Instances of this class are constructed by joinError. +class ErrorList final : public ErrorInfo<ErrorList> { + + // handleErrors needs to be able to iterate the payload list of an + // ErrorList. + template <typename... HandlerTs> + friend Error handleErrors(Error E, HandlerTs &&... Handlers); + + // joinErrors is implemented in terms of join. + friend Error joinErrors(Error, Error); + +public: + void log(raw_ostream &OS) const override { + OS << "Multiple errors:\n"; + for (auto &ErrPayload : Payloads) { + ErrPayload->log(OS); + OS << "\n"; + } + } + + std::error_code convertToErrorCode() const override; + + // Used by ErrorInfo::classID. + static char ID; + +private: + ErrorList(std::unique_ptr<ErrorInfoBase> Payload1, + std::unique_ptr<ErrorInfoBase> Payload2) { + assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && + "ErrorList constructor payloads should be singleton errors"); + Payloads.push_back(std::move(Payload1)); + Payloads.push_back(std::move(Payload2)); + } + + static Error join(Error E1, Error E2) { + if (!E1) + return E2; + if (!E2) + return E1; + if (E1.isA<ErrorList>()) { + auto &E1List = static_cast<ErrorList &>(*E1.getPtr()); + if (E2.isA<ErrorList>()) { + auto E2Payload = E2.takePayload(); + auto &E2List = static_cast<ErrorList &>(*E2Payload); + for (auto &Payload : E2List.Payloads) + E1List.Payloads.push_back(std::move(Payload)); + } else + E1List.Payloads.push_back(E2.takePayload()); + + return E1; + } + if (E2.isA<ErrorList>()) { + auto &E2List = static_cast<ErrorList &>(*E2.getPtr()); + E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload()); + return E2; + } + return Error(std::unique_ptr<ErrorList>( + new ErrorList(E1.takePayload(), E2.takePayload()))); + } + + std::vector<std::unique_ptr<ErrorInfoBase>> Payloads; +}; + +/// Concatenate errors. The resulting Error is unchecked, and contains the +/// ErrorInfo(s), if any, contained in E1, followed by the +/// ErrorInfo(s), if any, contained in E2. +inline Error joinErrors(Error E1, Error E2) { + return ErrorList::join(std::move(E1), std::move(E2)); +} + +/// Helper for testing applicability of, and applying, handlers for +/// ErrorInfo types. +template <typename HandlerT> +class ErrorHandlerTraits + : public ErrorHandlerTraits<decltype( + &std::remove_reference<HandlerT>::type::operator())> {}; + +// Specialization functions of the form 'Error (const ErrT&)'. +template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> { +public: + static bool appliesTo(const ErrorInfoBase &E) { + return E.template isA<ErrT>(); + } + + template <typename HandlerT> + static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { + assert(appliesTo(*E) && "Applying incorrect handler"); + return H(static_cast<ErrT &>(*E)); + } +}; + +// Specialization functions of the form 'void (const ErrT&)'. +template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> { +public: + static bool appliesTo(const ErrorInfoBase &E) { + return E.template isA<ErrT>(); + } + + template <typename HandlerT> + static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { + assert(appliesTo(*E) && "Applying incorrect handler"); + H(static_cast<ErrT &>(*E)); + return Error::success(); + } +}; + +/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. +template <typename ErrT> +class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> { +public: + static bool appliesTo(const ErrorInfoBase &E) { + return E.template isA<ErrT>(); + } + + template <typename HandlerT> + static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { + assert(appliesTo(*E) && "Applying incorrect handler"); + std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); + return H(std::move(SubE)); + } +}; + +/// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. +template <typename ErrT> +class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> { +public: + static bool appliesTo(const ErrorInfoBase &E) { + return E.template isA<ErrT>(); + } + + template <typename HandlerT> + static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { + assert(appliesTo(*E) && "Applying incorrect handler"); + std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); + H(std::move(SubE)); + return Error::success(); + } +}; + +// Specialization for member functions of the form 'RetT (const ErrT&)'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(ErrT &)> + : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; + +// Specialization for member functions of the form 'RetT (const ErrT&) const'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(ErrT &) const> + : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; + +// Specialization for member functions of the form 'RetT (const ErrT&)'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(const ErrT &)> + : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; + +// Specialization for member functions of the form 'RetT (const ErrT&) const'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const> + : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; + +/// Specialization for member functions of the form +/// 'RetT (std::unique_ptr<ErrT>) const'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)> + : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; + +/// Specialization for member functions of the form +/// 'RetT (std::unique_ptr<ErrT>) const'. +template <typename C, typename RetT, typename ErrT> +class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const> + : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; + +inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) { + return Error(std::move(Payload)); +} + +template <typename HandlerT, typename... HandlerTs> +Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload, + HandlerT &&Handler, HandlerTs &&... Handlers) { + if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload)) + return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler), + std::move(Payload)); + return handleErrorImpl(std::move(Payload), + std::forward<HandlerTs>(Handlers)...); +} + +/// Pass the ErrorInfo(s) contained in E to their respective handlers. Any +/// unhandled errors (or Errors returned by handlers) are re-concatenated and +/// returned. +/// Because this function returns an error, its result must also be checked +/// or returned. If you intend to handle all errors use handleAllErrors +/// (which returns void, and will abort() on unhandled errors) instead. +template <typename... HandlerTs> +Error handleErrors(Error E, HandlerTs &&... Hs) { + if (!E) + return Error::success(); + + std::unique_ptr<ErrorInfoBase> Payload = E.takePayload(); + + if (Payload->isA<ErrorList>()) { + ErrorList &List = static_cast<ErrorList &>(*Payload); + Error R; + for (auto &P : List.Payloads) + R = ErrorList::join( + std::move(R), + handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...)); + return R; + } + + return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...); +} + +/// Behaves the same as handleErrors, except that it requires that all +/// errors be handled by the given handlers. If any unhandled error remains +/// after the handlers have run, abort() will be called. +template <typename... HandlerTs> +void handleAllErrors(Error E, HandlerTs &&... Handlers) { + auto F = handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...); + // Cast 'F' to bool to set the 'Checked' flag if it's a success value: + (void)!F; +} + +/// Check that E is a non-error, then drop it. +inline void handleAllErrors(Error E) { + // Cast 'E' to a bool to set the 'Checked' flag if it's a success value: + (void)!E; +} + +/// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner +/// will be printed before the first one is logged. A newline will be printed +/// after each error. +/// +/// This is useful in the base level of your program to allow clean termination +/// (allowing clean deallocation of resources, etc.), while reporting error +/// information to the user. +void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner); + +/// Write all error messages (if any) in E to a string. The newline character +/// is used to separate error messages. +inline std::string toString(Error E) { + SmallVector<std::string, 2> Errors; + handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { + Errors.push_back(EI.message()); + }); + return join(Errors.begin(), Errors.end(), "\n"); +} + +/// Consume a Error without doing anything. This method should be used +/// only where an error can be considered a reasonable and expected return +/// value. +/// +/// Uses of this method are potentially indicative of design problems: If it's +/// legitimate to do nothing while processing an "error", the error-producer +/// might be more clearly refactored to return an Optional<T>. +inline void consumeError(Error Err) { + handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); +} + +/// Helper for Errors used as out-parameters. +/// +/// This helper is for use with the Error-as-out-parameter idiom, where an error +/// is passed to a function or method by reference, rather than being returned. +/// In such cases it is helpful to set the checked bit on entry to the function +/// so that the error can be written to (unchecked Errors abort on assignment) +/// and clear the checked bit on exit so that clients cannot accidentally forget +/// to check the result. This helper performs these actions automatically using +/// RAII: +/// +/// Result foo(Error &Err) { +/// ErrorAsOutParameter ErrAsOutParam(Err); // 'Checked' flag set +/// // <body of foo> +/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed. +/// } +class ErrorAsOutParameter { +public: + ErrorAsOutParameter(Error &Err) : Err(Err) { + // Raise the checked bit if Err is success. + (void)!!Err; + } + ~ErrorAsOutParameter() { + // Clear the checked bit. + if (!Err) + Err = Error::success(); + } + +private: + Error &Err; +}; + +/// Tagged union holding either a T or a Error. +/// +/// This class parallels ErrorOr, but replaces error_code with Error. Since +/// Error cannot be copied, this class replaces getError() with +/// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the +/// error class type. +template <class T> class Expected { + template <class OtherT> friend class Expected; + static const bool isRef = std::is_reference<T>::value; + typedef ReferenceStorage<typename std::remove_reference<T>::type> wrap; + + typedef std::unique_ptr<ErrorInfoBase> error_type; + +public: + typedef typename std::conditional<isRef, wrap, T>::type storage_type; + typedef T value_type; + +private: + 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; + typedef const typename std::remove_reference<T>::type *const_pointer; + +public: + /// Create an Expected<T> error value from the given Error. + Expected(Error Err) + : HasError(true) +#ifndef NDEBUG + , + Checked(false) +#endif + { + assert(Err && "Cannot create Expected<T> from Error success value."); + new (getErrorStorage()) Error(std::move(Err)); + } + + /// Create an Expected<T> success value from the given OtherT value, which + /// must be convertible to T. + template <typename OtherT> + Expected(OtherT &&Val, + typename std::enable_if<std::is_convertible<OtherT, T>::value>::type + * = nullptr) + : HasError(false) +#ifndef NDEBUG + , + Checked(false) +#endif + { + new (getStorage()) storage_type(std::forward<OtherT>(Val)); + } + + /// Move construct an Expected<T> value. + Expected(Expected &&Other) { moveConstruct(std::move(Other)); } + + /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT + /// must be convertible to T. + template <class OtherT> + Expected(Expected<OtherT> &&Other, + typename std::enable_if<std::is_convertible<OtherT, T>::value>::type + * = nullptr) { + moveConstruct(std::move(Other)); + } + + /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT + /// isn't convertible to T. + template <class OtherT> + explicit Expected( + Expected<OtherT> &&Other, + typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = + nullptr) { + moveConstruct(std::move(Other)); + } + + /// Move-assign from another Expected<T>. + Expected &operator=(Expected &&Other) { + moveAssign(std::move(Other)); + return *this; + } + + /// Destroy an Expected<T>. + ~Expected() { + assertIsChecked(); + if (!HasError) + getStorage()->~storage_type(); + else + getErrorStorage()->~error_type(); + } + + /// \brief Return false if there is an error. + explicit operator bool() { +#ifndef NDEBUG + Checked = !HasError; +#endif + return !HasError; + } + + /// \brief Returns a reference to the stored T value. + reference get() { + assertIsChecked(); + return *getStorage(); + } + + /// \brief Returns a const reference to the stored T value. + const_reference get() const { + assertIsChecked(); + return const_cast<Expected<T> *>(this)->get(); + } + + /// \brief Check that this Expected<T> is an error of type ErrT. + template <typename ErrT> bool errorIsA() const { + return HasError && getErrorStorage()->template isA<ErrT>(); + } + + /// \brief Take ownership of the stored error. + /// After calling this the Expected<T> is in an indeterminate state that can + /// only be safely destructed. No further calls (beside the destructor) should + /// be made on the Expected<T> vaule. + Error takeError() { +#ifndef NDEBUG + Checked = true; +#endif + return HasError ? Error(std::move(*getErrorStorage())) : Error::success(); + } + + /// \brief Returns a pointer to the stored T value. + pointer operator->() { + assertIsChecked(); + return toPointer(getStorage()); + } + + /// \brief Returns a const pointer to the stored T value. + const_pointer operator->() const { + assertIsChecked(); + return toPointer(getStorage()); + } + + /// \brief Returns a reference to the stored T value. + reference operator*() { + assertIsChecked(); + return *getStorage(); + } + + /// \brief Returns a const reference to the stored T value. + const_reference operator*() const { + assertIsChecked(); + return *getStorage(); + } + +private: + template <class T1> + static bool compareThisIfSameType(const T1 &a, const T1 &b) { + return &a == &b; + } + + template <class T1, class T2> + static bool compareThisIfSameType(const T1 &a, const T2 &b) { + return false; + } + + template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) { + HasError = Other.HasError; + +#ifndef NDEBUG + Checked = false; + Other.Checked = true; +#endif + + if (!HasError) + new (getStorage()) storage_type(std::move(*Other.getStorage())); + else + new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage())); + } + + template <class OtherT> void moveAssign(Expected<OtherT> &&Other) { + assertIsChecked(); + + if (compareThisIfSameType(*this, Other)) + return; + + this->~Expected(); + new (this) Expected(std::move(Other)); + } + + pointer toPointer(pointer Val) { return Val; } + + const_pointer toPointer(const_pointer Val) const { return Val; } + + pointer toPointer(wrap *Val) { return &Val->get(); } + + const_pointer toPointer(const wrap *Val) const { return &Val->get(); } + + storage_type *getStorage() { + assert(!HasError && "Cannot get value when an error exists!"); + return reinterpret_cast<storage_type *>(TStorage.buffer); + } + + const storage_type *getStorage() const { + assert(!HasError && "Cannot get value when an error exists!"); + return reinterpret_cast<const storage_type *>(TStorage.buffer); + } + + error_type *getErrorStorage() { + assert(HasError && "Cannot get error when a value exists!"); + return reinterpret_cast<error_type *>(ErrorStorage.buffer); + } + + void assertIsChecked() { +#ifndef NDEBUG + if (!Checked) { + dbgs() << "Expected<T> must be checked before access or destruction.\n"; + if (HasError) { + dbgs() << "Unchecked Expected<T> contained error:\n"; + (*getErrorStorage())->log(dbgs()); + } else + dbgs() << "Expected<T> value was in success state. (Note: Expected<T> " + "values in success mode must still be checked prior to being " + "destroyed).\n"; + abort(); + } +#endif + } + + union { + AlignedCharArrayUnion<storage_type> TStorage; + AlignedCharArrayUnion<error_type> ErrorStorage; + }; + bool HasError : 1; +#ifndef NDEBUG + bool Checked : 1; +#endif +}; + +/// This class wraps a std::error_code in a Error. +/// +/// This is useful if you're writing an interface that returns a Error +/// (or Expected) and you want to call code that still returns +/// std::error_codes. +class ECError : public ErrorInfo<ECError> { + friend Error errorCodeToError(std::error_code); +public: + void setErrorCode(std::error_code EC) { this->EC = EC; } + std::error_code convertToErrorCode() const override { return EC; } + void log(raw_ostream &OS) const override { OS << EC.message(); } + + // Used by ErrorInfo::classID. + static char ID; + +protected: + ECError() = default; + ECError(std::error_code EC) : EC(EC) {} + std::error_code EC; +}; + +/// The value returned by this function can be returned from convertToErrorCode +/// for Error values where no sensible translation to std::error_code exists. +/// It should only be used in this situation, and should never be used where a +/// sensible conversion to std::error_code is available, as attempts to convert +/// to/from this error will result in a fatal error. (i.e. it is a programmatic +///error to try to convert such a value). +std::error_code inconvertibleErrorCode(); + +/// Helper for converting an std::error_code to a Error. +Error errorCodeToError(std::error_code EC); + +/// Helper for converting an ECError to a std::error_code. +/// +/// This method requires that Err be Error() or an ECError, otherwise it +/// will trigger a call to abort(). +std::error_code errorToErrorCode(Error Err); + +/// Convert an ErrorOr<T> to an Expected<T>. +template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) { + if (auto EC = EO.getError()) + return errorCodeToError(EC); + return std::move(*EO); +} + +/// Convert an Expected<T> to an ErrorOr<T>. +template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) { + if (auto Err = E.takeError()) + return errorToErrorCode(std::move(Err)); + return std::move(*E); +} + +/// This class wraps a string in an Error. +/// +/// StringError is useful in cases where the client is not expected to be able +/// to consume the specific error message programmatically (for example, if the +/// error message is to be presented to the user). +class StringError : public ErrorInfo<StringError> { +public: + static char ID; + StringError(const Twine &S, std::error_code EC); + void log(raw_ostream &OS) const override; + std::error_code convertToErrorCode() const override; +private: + std::string Msg; + std::error_code EC; +}; + +/// Helper for check-and-exit error handling. +/// +/// For tool use only. NOT FOR USE IN LIBRARY CODE. +/// +class ExitOnError { +public: + /// Create an error on exit helper. + ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1) + : Banner(std::move(Banner)), + GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {} + + /// Set the banner string for any errors caught by operator(). + void setBanner(std::string Banner) { this->Banner = std::move(Banner); } + + /// Set the exit-code mapper function. + void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) { + this->GetExitCode = std::move(GetExitCode); + } + + /// Check Err. If it's in a failure state log the error(s) and exit. + void operator()(Error Err) const { checkError(std::move(Err)); } + + /// Check E. If it's in a success state then return the contained value. If + /// it's in a failure state log the error(s) and exit. + template <typename T> T operator()(Expected<T> &&E) const { + checkError(E.takeError()); + return std::move(*E); + } + + /// Check E. If it's in a success state then return the contained reference. If + /// it's in a failure state log the error(s) and exit. + template <typename T> T& operator()(Expected<T&> &&E) const { + checkError(E.takeError()); + return *E; + } + +private: + void checkError(Error Err) const { + if (Err) { + int ExitCode = GetExitCode(Err); + logAllUnhandledErrors(std::move(Err), errs(), Banner); + exit(ExitCode); + } + } + + std::string Banner; + std::function<int(const Error &)> GetExitCode; +}; + +/// Report a serious error, calling any installed error handler. See +/// ErrorHandling.h. +LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, + bool gen_crash_diag = true); + +} // namespace llvm + +#endif // LLVM_SUPPORT_ERROR_H diff --git a/include/llvm/Support/ErrorHandling.h b/include/llvm/Support/ErrorHandling.h index 32f05e0e9610..7c1edd801571 100644 --- a/include/llvm/Support/ErrorHandling.h +++ b/include/llvm/Support/ErrorHandling.h @@ -15,11 +15,11 @@ #ifndef LLVM_SUPPORT_ERRORHANDLING_H #define LLVM_SUPPORT_ERRORHANDLING_H -#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include <string> namespace llvm { +class StringRef; class Twine; /// An error handler callback. diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index ca6ede73e8df..877f4063cd23 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -23,20 +23,6 @@ #include <type_traits> namespace llvm { -template<class T, class V> -typename std::enable_if< std::is_constructible<T, V>::value - , typename std::remove_reference<V>::type>::type && - moveIfMoveConstructible(V &Val) { - return std::move(Val); -} - -template<class T, class V> -typename std::enable_if< !std::is_constructible<T, V>::value - , typename std::remove_reference<V>::type>::type & -moveIfMoveConstructible(V &Val) { - return Val; -} - /// \brief Stores a reference that can be changed. template <typename T> class ReferenceStorage { @@ -72,7 +58,7 @@ public: /// unary * and -> operators provide pointer like access to the value. Accessing /// the value when there is an error has undefined behavior. /// -/// When T is a reference type the behaivor is slightly different. The reference +/// When T is a reference type the behavior is slightly different. The reference /// is held in a std::reference_wrapper<std::remove_reference<T>::type>, and /// there is special handling to make operator -> work as if T was not a /// reference. @@ -98,7 +84,7 @@ public: ErrorOr(E ErrorCode, typename std::enable_if<std::is_error_code_enum<E>::value || std::is_error_condition_enum<E>::value, - void *>::type = 0) + void *>::type = nullptr) : HasError(true) { new (getErrorStorage()) std::error_code(make_error_code(ErrorCode)); } @@ -107,8 +93,12 @@ public: new (getErrorStorage()) std::error_code(EC); } - ErrorOr(T Val) : HasError(false) { - new (getStorage()) storage_type(moveIfMoveConstructible<storage_type>(Val)); + template <class OtherT> + ErrorOr(OtherT &&Val, + typename std::enable_if<std::is_convertible<OtherT, T>::value>::type + * = nullptr) + : HasError(false) { + new (getStorage()) storage_type(std::forward<OtherT>(Val)); } ErrorOr(const ErrorOr &Other) { @@ -278,7 +268,6 @@ private: return const_cast<ErrorOr<T> *>(this)->getErrorStorage(); } - union { AlignedCharArrayUnion<storage_type> TStorage; AlignedCharArrayUnion<std::error_code> ErrorStorage; @@ -295,4 +284,4 @@ operator==(const ErrorOr<T> &Err, E Code) { } } // end namespace llvm -#endif +#endif // LLVM_SUPPORT_ERROROR_H diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 4733ddb77575..42a6180e0eb3 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -29,12 +29,15 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/TimeValue.h" +#include <cassert> +#include <cstdint> #include <ctime> -#include <iterator> #include <stack> #include <string> #include <system_error> @@ -140,11 +143,14 @@ class file_status #if defined(LLVM_ON_UNIX) dev_t fs_st_dev; ino_t fs_st_ino; + time_t fs_st_atime; time_t fs_st_mtime; uid_t fs_st_uid; gid_t fs_st_gid; off_t fs_st_size; #elif defined (LLVM_ON_WIN32) + uint32_t LastAccessedTimeHigh; + uint32_t LastAccessedTimeLow; uint32_t LastWriteTimeHigh; uint32_t LastWriteTimeLow; uint32_t VolumeSerialNumber; @@ -159,43 +165,51 @@ class file_status public: #if defined(LLVM_ON_UNIX) - file_status() : fs_st_dev(0), fs_st_ino(0), fs_st_mtime(0), + file_status() + : fs_st_dev(0), fs_st_ino(0), fs_st_atime(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), + file_status(file_type Type) + : fs_st_dev(0), fs_st_ino(0), fs_st_atime(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) {} + file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t ATime, + time_t MTime, uid_t UID, gid_t GID, off_t Size) + : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_atime(ATime), 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() + : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), 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), + file_status(file_type Type) + : LastAccessedTimeHigh(0), LastAccessedTimeLow(0), 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, - uint32_t FileIndexHigh, uint32_t FileIndexLow) - : LastWriteTimeHigh(LastWriteTimeHigh), - LastWriteTimeLow(LastWriteTimeLow), - VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh), - FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh), - FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {} + file_status(file_type Type, uint32_t LastAccessTimeHigh, + uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh, + uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber, + uint32_t FileSizeHigh, uint32_t FileSizeLow, + uint32_t FileIndexHigh, uint32_t FileIndexLow) + : LastAccessedTimeHigh(LastAccessTimeHigh), LastAccessedTimeLow(LastAccessTimeLow), + LastWriteTimeHigh(LastWriteTimeHigh), + LastWriteTimeLow(LastWriteTimeLow), + VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh), + FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh), + FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {} #endif // getters file_type type() const { return Type; } perms permissions() const { return Perms; } + TimeValue getLastAccessedTime() const; TimeValue getLastModificationTime() const; UniqueID getUniqueID() const; @@ -251,7 +265,7 @@ struct file_magic { }; bool is_object() const { - return V == unknown ? false : true; + return V != unknown; } file_magic() : V(unknown) {} @@ -590,6 +604,12 @@ std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, std::error_code createUniqueDirectory(const Twine &Prefix, SmallVectorImpl<char> &ResultPath); +/// @brief Fetch a path to an open file, as specified by a file descriptor +/// +/// @param FD File descriptor to a currently open file +/// @param ResultPath The buffer into which to write the path +std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath); + enum OpenFlags : unsigned { F_None = 0, @@ -622,7 +642,8 @@ inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { std::error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags, unsigned Mode = 0666); -std::error_code openFileForRead(const Twine &Name, int &ResultFD); +std::error_code openFileForRead(const Twine &Name, int &ResultFD, + SmallVectorImpl<char> *RealPath = nullptr); /// @brief Identify the type of a binary file based on how magical it is. file_magic identify_magic(StringRef magic); @@ -637,6 +658,17 @@ std::error_code identify_magic(const Twine &path, file_magic &result); std::error_code getUniqueID(const Twine Path, UniqueID &Result); +/// @brief Get disk space usage information. +/// +/// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug. +/// Note: Windows reports results according to the quota allocated to the user. +/// +/// @param Path Input path. +/// @returns a space_info structure filled with the capacity, free, and +/// available space on the device \a Path is on. A platform specific error_code +/// is returned on error. +ErrorOr<space_info> disk_space(const Twine &Path); + /// This class represents a memory mapped file. It is based on /// boost::iostreams::mapped_file. class mapped_file_region { @@ -739,7 +771,7 @@ namespace detail { intptr_t IterationHandle; directory_entry CurrentEntry; }; -} +} // end namespace detail /// directory_iterator - Iterates through the entries in path. There is no /// operator++ because we need an error_code. If it's really needed we can make @@ -801,7 +833,7 @@ namespace detail { uint16_t Level; bool HasNoPushRequest; }; -} +} // end namespace detail /// recursive_directory_iterator - Same as directory_iterator except for it /// recurses down into child directories. @@ -900,4 +932,4 @@ public: } // end namespace sys } // end namespace llvm -#endif +#endif // LLVM_SUPPORT_FILESYSTEM_H diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index f0b437a0cbed..d5c301cd7e2b 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -170,13 +170,13 @@ inline FormattedNumber format_hex(uint64_t N, unsigned Width, /// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not /// prepend '0x' to the outputted string. If number will not fit in width, /// full number is still printed. Examples: -/// OS << format_hex_no_prefix(255, 4) => ff -/// OS << format_hex_no_prefix(255, 4, true) => FF -/// OS << format_hex_no_prefix(255, 6) => 00ff /// OS << format_hex_no_prefix(255, 2) => ff +/// OS << format_hex_no_prefix(255, 2, true) => FF +/// OS << format_hex_no_prefix(255, 4) => 00ff +/// OS << format_hex_no_prefix(255, 1) => ff inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper = false) { - assert(Width <= 18 && "hex width must be <= 18"); + assert(Width <= 16 && "hex width must be <= 16"); return FormattedNumber(N, 0, Width, true, Upper, false); } diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h index 8bae582d18c7..77b5ba7e3e97 100644 --- a/include/llvm/Support/GenericDomTree.h +++ b/include/llvm/Support/GenericDomTree.h @@ -109,13 +109,13 @@ public: return true; SmallPtrSet<const NodeT *, 4> OtherChildren; - for (const_iterator I = Other->begin(), E = Other->end(); I != E; ++I) { - const NodeT *Nd = (*I)->getBlock(); + for (const DomTreeNodeBase *I : *Other) { + const NodeT *Nd = I->getBlock(); OtherChildren.insert(Nd); } - for (const_iterator I = begin(), E = end(); I != E; ++I) { - const NodeT *N = (*I)->getBlock(); + for (const DomTreeNodeBase *I : *this) { + const NodeT *N = I->getBlock(); if (OtherChildren.count(N) == 0) return true; } @@ -138,8 +138,9 @@ public: } } - /// getDFSNumIn/getDFSNumOut - These are an internal implementation detail, do - /// not call them. + /// getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes + /// in the dominator tree. They are only guaranteed valid if + /// updateDFSNumbers() has been called. unsigned getDFSNumIn() const { return DFSNumIn; } unsigned getDFSNumOut() const { return DFSNumOut; } @@ -348,17 +349,14 @@ public: 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; + for (const auto &DomTreeNode : this->DomTreeNodes) { + NodeT *BB = DomTreeNode.first; typename DomTreeNodeMapType::const_iterator OI = OtherDomTreeNodes.find(BB); if (OI == OtherDomTreeNodes.end()) return true; - DomTreeNodeBase<NodeT> &MyNd = *I->second; + DomTreeNodeBase<NodeT> &MyNd = *DomTreeNode.second; DomTreeNodeBase<NodeT> &OtherNd = *OI->second; if (MyNd.compare(&OtherNd)) @@ -453,7 +451,7 @@ public: // Compare the result of the tree walk and the dfs numbers, if expensive // checks are enabled. -#ifdef XDEBUG +#ifdef EXPENSIVE_CHECKS assert((!DFSInfoValid || (dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) && "Tree walk disagrees with dfs numbers!"); diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h index 8f4bf3c1ba56..8114f9bf846b 100644 --- a/include/llvm/Support/Host.h +++ b/include/llvm/Support/Host.h @@ -16,7 +16,7 @@ #include "llvm/ADT/StringMap.h" -#if defined(__linux__) || defined(__GNU__) +#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) #include <endian.h> #else #if !defined(BYTE_ORDER) && !defined(LLVM_ON_WIN32) diff --git a/include/llvm/Support/JamCRC.h b/include/llvm/Support/JamCRC.h index 20c28a5f8e45..5268bbd9ba1e 100644 --- a/include/llvm/Support/JamCRC.h +++ b/include/llvm/Support/JamCRC.h @@ -27,10 +27,11 @@ #ifndef LLVM_SUPPORT_JAMCRC_H #define LLVM_SUPPORT_JAMCRC_H -#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/DataTypes.h" namespace llvm { +template <typename T> class ArrayRef; + class JamCRC { public: JamCRC(uint32_t Init = 0xFFFFFFFFU) : CRC(Init) {} diff --git a/include/llvm/Support/Locale.h b/include/llvm/Support/Locale.h index b384d58baea7..f7a2c036ed5e 100644 --- a/include/llvm/Support/Locale.h +++ b/include/llvm/Support/Locale.h @@ -1,9 +1,9 @@ #ifndef LLVM_SUPPORT_LOCALE_H #define LLVM_SUPPORT_LOCALE_H -#include "llvm/ADT/StringRef.h" - namespace llvm { +class StringRef; + namespace sys { namespace locale { diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index 8e88d4279bd8..13d252425b93 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -11,11 +11,12 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringRef.h" #include <system_error> #include <utility> // for std::pair namespace llvm { +class StringRef; + /// \brief Class that manages the creation of a lock file to aid /// implicit coordination between different processes. /// @@ -56,6 +57,7 @@ private: Optional<std::pair<std::string, int> > Owner; Optional<std::error_code> Error; + std::string ErrorDiagMsg; LockFileManager(const LockFileManager &) = delete; LockFileManager &operator=(const LockFileManager &) = delete; @@ -81,6 +83,15 @@ public: /// \brief Remove the lock file. This may delete a different lock file than /// the one previously read if there is a race. std::error_code unsafeRemoveLockFile(); + + /// \brief Get error message, or "" if there is no error. + std::string getErrorMessage() const; + + /// \brief Set error and error message + void setError(std::error_code &EC, StringRef ErrorMsg = "") { + Error = EC; + ErrorDiagMsg = ErrorMsg.str(); + } }; } // end namespace llvm diff --git a/include/llvm/Support/MD5.h b/include/llvm/Support/MD5.h index f6e1e92c9fa8..42d8ca8a1ebb 100644 --- a/include/llvm/Support/MD5.h +++ b/include/llvm/Support/MD5.h @@ -28,11 +28,12 @@ #ifndef LLVM_SUPPORT_MD5_H #define LLVM_SUPPORT_MD5_H -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Endian.h" namespace llvm { +template <typename T> class ArrayRef; class MD5 { // Any 32-bit or wider unsigned integer data type will do. @@ -65,6 +66,18 @@ private: const uint8_t *body(ArrayRef<uint8_t> Data); }; +/// Helper to compute and return lower 64 bits of the given string's MD5 hash. +inline uint64_t MD5Hash(StringRef Str) { + MD5 Hash; + Hash.update(Str); + llvm::MD5::MD5Result Result; + Hash.final(Result); + // Return the least significant 8 bytes. Our MD5 implementation returns the + // result in little endian, so we may need to swap bytes. + using namespace llvm::support; + return endian::read<uint64_t, little, unaligned>(Result); +} + } #endif diff --git a/include/llvm/Support/MachO.def b/include/llvm/Support/MachO.def new file mode 100644 index 000000000000..9ca6440dd82b --- /dev/null +++ b/include/llvm/Support/MachO.def @@ -0,0 +1,106 @@ +//,,,-- llvm/Support/MachO.def - The MachO file definitions -----*- C++ -*-,,,// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//,,,----------------------------------------------------------------------,,,// +// +// Definitions for MachO files +// +//,,,----------------------------------------------------------------------,,,// + +#ifdef HANDLE_LOAD_COMMAND + +HANDLE_LOAD_COMMAND(LC_SEGMENT, 0x00000001u, segment_command) +HANDLE_LOAD_COMMAND(LC_SYMTAB, 0x00000002u, symtab_command) +HANDLE_LOAD_COMMAND(LC_SYMSEG, 0x00000003u, symseg_command) +HANDLE_LOAD_COMMAND(LC_THREAD, 0x00000004u, thread_command) +HANDLE_LOAD_COMMAND(LC_UNIXTHREAD, 0x00000005u, thread_command) +HANDLE_LOAD_COMMAND(LC_LOADFVMLIB, 0x00000006u, fvmlib_command) +HANDLE_LOAD_COMMAND(LC_IDFVMLIB, 0x00000007u, fvmlib_command) +HANDLE_LOAD_COMMAND(LC_IDENT, 0x00000008u, ident_command) +HANDLE_LOAD_COMMAND(LC_FVMFILE, 0x00000009u, fvmfile_command) +HANDLE_LOAD_COMMAND(LC_PREPAGE, 0x0000000Au, load_command) +HANDLE_LOAD_COMMAND(LC_DYSYMTAB, 0x0000000Bu, dysymtab_command) +HANDLE_LOAD_COMMAND(LC_LOAD_DYLIB, 0x0000000Cu, dylib_command) +HANDLE_LOAD_COMMAND(LC_ID_DYLIB, 0x0000000Du, dylib_command) +HANDLE_LOAD_COMMAND(LC_LOAD_DYLINKER, 0x0000000Eu, dylinker_command) +HANDLE_LOAD_COMMAND(LC_ID_DYLINKER, 0x0000000Fu, dylinker_command) +HANDLE_LOAD_COMMAND(LC_PREBOUND_DYLIB, 0x00000010u, prebound_dylib_command) +HANDLE_LOAD_COMMAND(LC_ROUTINES, 0x00000011u, routines_command) +HANDLE_LOAD_COMMAND(LC_SUB_FRAMEWORK, 0x00000012u, sub_framework_command) +HANDLE_LOAD_COMMAND(LC_SUB_UMBRELLA, 0x00000013u, sub_umbrella_command) +HANDLE_LOAD_COMMAND(LC_SUB_CLIENT, 0x00000014u, sub_client_command) +HANDLE_LOAD_COMMAND(LC_SUB_LIBRARY, 0x00000015u, sub_library_command) +HANDLE_LOAD_COMMAND(LC_TWOLEVEL_HINTS, 0x00000016u, twolevel_hints_command) +HANDLE_LOAD_COMMAND(LC_PREBIND_CKSUM, 0x00000017u, prebind_cksum_command) +HANDLE_LOAD_COMMAND(LC_LOAD_WEAK_DYLIB, 0x80000018u, dylib_command) +HANDLE_LOAD_COMMAND(LC_SEGMENT_64, 0x00000019u, segment_command_64) +HANDLE_LOAD_COMMAND(LC_ROUTINES_64, 0x0000001Au, routines_command_64) +HANDLE_LOAD_COMMAND(LC_UUID, 0x0000001Bu, uuid_command) +HANDLE_LOAD_COMMAND(LC_RPATH, 0x8000001Cu, rpath_command) +HANDLE_LOAD_COMMAND(LC_CODE_SIGNATURE, 0x0000001Du, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_SEGMENT_SPLIT_INFO, 0x0000001Eu, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_REEXPORT_DYLIB, 0x8000001Fu, dylib_command) +HANDLE_LOAD_COMMAND(LC_LAZY_LOAD_DYLIB, 0x00000020u, dylib_command) +HANDLE_LOAD_COMMAND(LC_ENCRYPTION_INFO, 0x00000021u, encryption_info_command) +HANDLE_LOAD_COMMAND(LC_DYLD_INFO, 0x00000022u, dyld_info_command) +HANDLE_LOAD_COMMAND(LC_DYLD_INFO_ONLY, 0x80000022u, dyld_info_command) +HANDLE_LOAD_COMMAND(LC_LOAD_UPWARD_DYLIB, 0x80000023u, dylib_command) +HANDLE_LOAD_COMMAND(LC_VERSION_MIN_MACOSX, 0x00000024u, version_min_command) +HANDLE_LOAD_COMMAND(LC_VERSION_MIN_IPHONEOS, 0x00000025u, version_min_command) +HANDLE_LOAD_COMMAND(LC_FUNCTION_STARTS, 0x00000026u, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_DYLD_ENVIRONMENT, 0x00000027u, dylinker_command) +HANDLE_LOAD_COMMAND(LC_MAIN, 0x80000028u, entry_point_command) +HANDLE_LOAD_COMMAND(LC_DATA_IN_CODE, 0x00000029u, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_SOURCE_VERSION, 0x0000002Au, source_version_command) +HANDLE_LOAD_COMMAND(LC_DYLIB_CODE_SIGN_DRS, 0x0000002Bu, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_ENCRYPTION_INFO_64, 0x0000002Cu, + encryption_info_command_64) +HANDLE_LOAD_COMMAND(LC_LINKER_OPTION, 0x0000002Du, linker_option_command) +HANDLE_LOAD_COMMAND(LC_LINKER_OPTIMIZATION_HINT, 0x0000002Eu, linkedit_data_command) +HANDLE_LOAD_COMMAND(LC_VERSION_MIN_TVOS, 0x0000002Fu, version_min_command) +HANDLE_LOAD_COMMAND(LC_VERSION_MIN_WATCHOS, 0x00000030u, version_min_command) + +#endif + +#ifdef LOAD_COMMAND_STRUCT + +LOAD_COMMAND_STRUCT(dyld_info_command) +LOAD_COMMAND_STRUCT(dylib_command) +LOAD_COMMAND_STRUCT(dylinker_command) +LOAD_COMMAND_STRUCT(dysymtab_command) +LOAD_COMMAND_STRUCT(encryption_info_command) +LOAD_COMMAND_STRUCT(encryption_info_command_64) +LOAD_COMMAND_STRUCT(entry_point_command) +LOAD_COMMAND_STRUCT(fvmfile_command) +LOAD_COMMAND_STRUCT(fvmlib_command) +LOAD_COMMAND_STRUCT(ident_command) +LOAD_COMMAND_STRUCT(linkedit_data_command) +LOAD_COMMAND_STRUCT(linker_option_command) +LOAD_COMMAND_STRUCT(load_command) +LOAD_COMMAND_STRUCT(prebind_cksum_command) +LOAD_COMMAND_STRUCT(prebound_dylib_command) +LOAD_COMMAND_STRUCT(routines_command) +LOAD_COMMAND_STRUCT(routines_command_64) +LOAD_COMMAND_STRUCT(rpath_command) +LOAD_COMMAND_STRUCT(segment_command) +LOAD_COMMAND_STRUCT(segment_command_64) +LOAD_COMMAND_STRUCT(source_version_command) +LOAD_COMMAND_STRUCT(sub_client_command) +LOAD_COMMAND_STRUCT(sub_framework_command) +LOAD_COMMAND_STRUCT(sub_library_command) +LOAD_COMMAND_STRUCT(sub_umbrella_command) +LOAD_COMMAND_STRUCT(symseg_command) +LOAD_COMMAND_STRUCT(symtab_command) +LOAD_COMMAND_STRUCT(thread_command) +LOAD_COMMAND_STRUCT(twolevel_hints_command) +LOAD_COMMAND_STRUCT(uuid_command) +LOAD_COMMAND_STRUCT(version_min_command) + +#endif + +#undef HANDLE_LOAD_COMMAND +#undef LOAD_COMMAND_STRUCT diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index 54b8745de1c1..9a03722d250f 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -29,7 +29,9 @@ namespace llvm { MH_MAGIC_64 = 0xFEEDFACFu, MH_CIGAM_64 = 0xCFFAEDFEu, FAT_MAGIC = 0xCAFEBABEu, - FAT_CIGAM = 0xBEBAFECAu + FAT_CIGAM = 0xBEBAFECAu, + FAT_MAGIC_64 = 0xCAFEBABFu, + FAT_CIGAM_64 = 0xBFBAFECAu }; enum HeaderFileType { @@ -84,59 +86,15 @@ namespace llvm { LC_REQ_DYLD = 0x80000000u }; +#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \ + LCName = LCValue, + enum LoadCommandType : uint32_t { - // Constants for the "cmd" field in llvm::MachO::load_command - LC_SEGMENT = 0x00000001u, - LC_SYMTAB = 0x00000002u, - LC_SYMSEG = 0x00000003u, - LC_THREAD = 0x00000004u, - LC_UNIXTHREAD = 0x00000005u, - LC_LOADFVMLIB = 0x00000006u, - LC_IDFVMLIB = 0x00000007u, - LC_IDENT = 0x00000008u, - LC_FVMFILE = 0x00000009u, - LC_PREPAGE = 0x0000000Au, - LC_DYSYMTAB = 0x0000000Bu, - LC_LOAD_DYLIB = 0x0000000Cu, - LC_ID_DYLIB = 0x0000000Du, - LC_LOAD_DYLINKER = 0x0000000Eu, - LC_ID_DYLINKER = 0x0000000Fu, - LC_PREBOUND_DYLIB = 0x00000010u, - LC_ROUTINES = 0x00000011u, - LC_SUB_FRAMEWORK = 0x00000012u, - LC_SUB_UMBRELLA = 0x00000013u, - LC_SUB_CLIENT = 0x00000014u, - LC_SUB_LIBRARY = 0x00000015u, - LC_TWOLEVEL_HINTS = 0x00000016u, - LC_PREBIND_CKSUM = 0x00000017u, - LC_LOAD_WEAK_DYLIB = 0x80000018u, - LC_SEGMENT_64 = 0x00000019u, - LC_ROUTINES_64 = 0x0000001Au, - LC_UUID = 0x0000001Bu, - LC_RPATH = 0x8000001Cu, - LC_CODE_SIGNATURE = 0x0000001Du, - LC_SEGMENT_SPLIT_INFO = 0x0000001Eu, - LC_REEXPORT_DYLIB = 0x8000001Fu, - LC_LAZY_LOAD_DYLIB = 0x00000020u, - LC_ENCRYPTION_INFO = 0x00000021u, - LC_DYLD_INFO = 0x00000022u, - LC_DYLD_INFO_ONLY = 0x80000022u, - LC_LOAD_UPWARD_DYLIB = 0x80000023u, - LC_VERSION_MIN_MACOSX = 0x00000024u, - LC_VERSION_MIN_IPHONEOS = 0x00000025u, - LC_FUNCTION_STARTS = 0x00000026u, - LC_DYLD_ENVIRONMENT = 0x00000027u, - LC_MAIN = 0x80000028u, - LC_DATA_IN_CODE = 0x00000029u, - LC_SOURCE_VERSION = 0x0000002Au, - LC_DYLIB_CODE_SIGN_DRS = 0x0000002Bu, - LC_ENCRYPTION_INFO_64 = 0x0000002Cu, - LC_LINKER_OPTION = 0x0000002Du, - LC_LINKER_OPTIMIZATION_HINT = 0x0000002Eu, - LC_VERSION_MIN_TVOS = 0x0000002Fu, - LC_VERSION_MIN_WATCHOS = 0x00000030u, + #include "llvm/Support/MachO.def" }; +#undef HANDLE_LOAD_COMMAND + enum : uint32_t { // Constant bits for the "flags" field in llvm::MachO::segment_command SG_HIGHVM = 0x1u, @@ -935,6 +893,15 @@ namespace llvm { uint32_t align; }; + struct fat_arch_64 { + uint32_t cputype; + uint32_t cpusubtype; + uint64_t offset; + uint64_t size; + uint32_t align; + uint32_t reserved; + }; + // Structs from <mach-o/reloc.h> struct relocation_info { int32_t r_address; @@ -993,6 +960,28 @@ namespace llvm { // Byte order swapping functions for MachO structs + inline void swapStruct(fat_header &mh) { + sys::swapByteOrder(mh.magic); + sys::swapByteOrder(mh.nfat_arch); + } + + inline void swapStruct(fat_arch &mh) { + sys::swapByteOrder(mh.cputype); + sys::swapByteOrder(mh.cpusubtype); + sys::swapByteOrder(mh.offset); + sys::swapByteOrder(mh.size); + sys::swapByteOrder(mh.align); + } + + inline void swapStruct(fat_arch_64 &mh) { + sys::swapByteOrder(mh.cputype); + sys::swapByteOrder(mh.cpusubtype); + sys::swapByteOrder(mh.offset); + sys::swapByteOrder(mh.size); + sys::swapByteOrder(mh.align); + sys::swapByteOrder(mh.reserved); + } + inline void swapStruct(mach_header &mh) { sys::swapByteOrder(mh.magic); sys::swapByteOrder(mh.cputype); @@ -1279,6 +1268,58 @@ namespace llvm { sys::swapByteOrder(C); } + inline void swapStruct(prebind_cksum_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.cksum); + } + + inline void swapStruct(twolevel_hints_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.offset); + sys::swapByteOrder(C.nhints); + } + + inline void swapStruct(prebound_dylib_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.name); + sys::swapByteOrder(C.nmodules); + sys::swapByteOrder(C.linked_modules); + } + + inline void swapStruct(fvmfile_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.name); + sys::swapByteOrder(C.header_addr); + } + + inline void swapStruct(symseg_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.offset); + sys::swapByteOrder(C.size); + } + + inline void swapStruct(ident_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + } + + inline void swapStruct(fvmlib &C) { + sys::swapByteOrder(C.name); + sys::swapByteOrder(C.minor_version); + sys::swapByteOrder(C.header_addr); + } + + inline void swapStruct(fvmlib_command &C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + swapStruct(C.fvmlib); + } + // Get/Set functions from <mach-o/nlist.h> static inline uint16_t GET_LIBRARY_ORDINAL(uint16_t n_desc) { @@ -1669,6 +1710,13 @@ namespace llvm { const uint32_t x86_EXCEPTION_STATE_COUNT = sizeof(x86_exception_state_t) / sizeof(uint32_t); + // Define a union of all load command structs + #define LOAD_COMMAND_STRUCT(LCStruct) LCStruct LCStruct##_data; + + union macho_load_command { + #include "llvm/Support/MachO.def" + }; + } // end namespace MachO } // end namespace llvm diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h index 2e131e47177d..ec8154b828e5 100644 --- a/include/llvm/Support/ManagedStatic.h +++ b/include/llvm/Support/ManagedStatic.h @@ -14,25 +14,26 @@ #ifndef LLVM_SUPPORT_MANAGEDSTATIC_H #define LLVM_SUPPORT_MANAGEDSTATIC_H -#include "llvm/Support/Atomic.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/Threading.h" +#include <atomic> +#include <cstddef> namespace llvm { /// object_creator - Helper method for ManagedStatic. template<class C> -void* object_creator() { +LLVM_LIBRARY_VISIBILITY void* object_creator() { return new C(); } /// object_deleter - Helper method for ManagedStatic. /// -template<typename T> struct object_deleter { - static void call(void * Ptr) { delete (T*)Ptr; } +template <typename T> struct LLVM_LIBRARY_VISIBILITY object_deleter { + static void call(void *Ptr) { delete (T *)Ptr; } }; -template<typename T, size_t N> struct object_deleter<T[N]> { - static void call(void * Ptr) { delete[] (T*)Ptr; } +template <typename T, size_t N> +struct LLVM_LIBRARY_VISIBILITY object_deleter<T[N]> { + static void call(void *Ptr) { delete[](T *)Ptr; } }; /// ManagedStaticBase - Common base class for ManagedStatic instances. @@ -40,7 +41,7 @@ class ManagedStaticBase { protected: // This should only be used as a static variable, which guarantees that this // will be zero initialized. - mutable void *Ptr; + mutable std::atomic<void *> Ptr; mutable void (*DeleterFn)(void*); mutable const ManagedStaticBase *Next; @@ -60,40 +61,26 @@ public: template<class C> class ManagedStatic : public ManagedStaticBase { public: - // Accessors. C &operator*() { - void* tmp = Ptr; - if (llvm_is_multithreaded()) sys::MemoryFence(); - if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call); - TsanHappensAfter(this); + void *Tmp = Ptr.load(std::memory_order_acquire); + if (!Tmp) + RegisterManagedStatic(object_creator<C>, object_deleter<C>::call); - return *static_cast<C*>(Ptr); + return *static_cast<C *>(Ptr.load(std::memory_order_relaxed)); } - C *operator->() { - void* tmp = Ptr; - if (llvm_is_multithreaded()) sys::MemoryFence(); - if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call); - TsanHappensAfter(this); - return static_cast<C*>(Ptr); - } + C *operator->() { return &**this; } + const C &operator*() const { - void* tmp = Ptr; - if (llvm_is_multithreaded()) sys::MemoryFence(); - if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call); - TsanHappensAfter(this); + void *Tmp = Ptr.load(std::memory_order_acquire); + if (!Tmp) + RegisterManagedStatic(object_creator<C>, object_deleter<C>::call); - return *static_cast<C*>(Ptr); + return *static_cast<C *>(Ptr.load(std::memory_order_relaxed)); } - const C *operator->() const { - void* tmp = Ptr; - if (llvm_is_multithreaded()) sys::MemoryFence(); - if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>::call); - TsanHappensAfter(this); - return static_cast<C*>(Ptr); - } + const C *operator->() const { return &**this; } }; /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 408ae3c339a2..5c816ac9df92 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -16,9 +16,11 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/SwapByteOrder.h" +#include <algorithm> #include <cassert> #include <cstring> #include <type_traits> +#include <limits> #ifdef _MSC_VER #include <intrin.h> @@ -281,14 +283,19 @@ inline bool isInt<32>(int64_t x) { /// left by S. template<unsigned N, unsigned S> inline bool isShiftedInt(int64_t x) { - return isInt<N+S>(x) && (x % (1<<S) == 0); + static_assert( + N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number."); + static_assert(N + S <= 64, "isShiftedInt<N, S> with N + S > 64 is too wide."); + return isInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0); } /// isUInt - Checks if an unsigned integer fits into the given bit width. template<unsigned N> inline bool isUInt(uint64_t x) { + static_assert(N > 0, "isUInt<0> doesn't make sense."); return N >= 64 || x < (UINT64_C(1)<<(N)); } + // Template specializations to get better code for common cases. template<> inline bool isUInt<8>(uint64_t x) { @@ -303,23 +310,55 @@ inline bool isUInt<32>(uint64_t x) { return static_cast<uint32_t>(x) == x; } -/// isShiftedUInt<N,S> - Checks if a unsigned integer is an N bit number shifted -/// left by S. +/// Checks if a unsigned integer is an N bit number shifted left by S. template<unsigned N, unsigned S> inline bool isShiftedUInt(uint64_t x) { - return isUInt<N+S>(x) && (x % (1<<S) == 0); + static_assert( + N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)"); + static_assert(N + S <= 64, + "isShiftedUInt<N, S> with N + S > 64 is too wide."); + // Per the two static_asserts above, S must be strictly less than 64. So + // 1 << S is not undefined behavior. + return isUInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0); +} + +/// Gets the maximum value for a N-bit unsigned integer. +inline uint64_t maxUIntN(uint64_t N) { + assert(N > 0 && N <= 64 && "integer width out of range"); + + // uint64_t(1) << 64 is undefined behavior, so we can't do + // (uint64_t(1) << N) - 1 + // without checking first that N != 64. But this works and doesn't have a + // branch. + return UINT64_MAX >> (64 - N); +} + +/// Gets the minimum value for a N-bit signed integer. +inline int64_t minIntN(int64_t N) { + assert(N > 0 && N <= 64 && "integer width out of range"); + + return -(UINT64_C(1)<<(N-1)); +} + +/// Gets the maximum value for a N-bit signed integer. +inline int64_t maxIntN(int64_t N) { + assert(N > 0 && N <= 64 && "integer width out of range"); + + // This relies on two's complement wraparound when N == 64, so we convert to + // int64_t only at the very end to avoid UB. + return (UINT64_C(1) << (N - 1)) - 1; } /// isUIntN - Checks if an unsigned integer fits into the given (dynamic) /// bit width. inline bool isUIntN(unsigned N, uint64_t x) { - return N >= 64 || x < (UINT64_C(1)<<(N)); + return N >= 64 || x <= maxUIntN(N); } /// isIntN - Checks if an signed integer fits into the given (dynamic) /// bit width. inline bool isIntN(unsigned N, int64_t x) { - return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); + return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N)); } /// isMask_32 - This function returns true if the argument is a non-empty @@ -606,57 +645,78 @@ inline uint64_t PowerOf2Floor(uint64_t A) { /// /// Examples: /// \code -/// RoundUpToAlignment(5, 8) = 8 -/// RoundUpToAlignment(17, 8) = 24 -/// RoundUpToAlignment(~0LL, 8) = 0 -/// RoundUpToAlignment(321, 255) = 510 +/// alignTo(5, 8) = 8 +/// alignTo(17, 8) = 24 +/// alignTo(~0LL, 8) = 0 +/// alignTo(321, 255) = 510 /// -/// RoundUpToAlignment(5, 8, 7) = 7 -/// RoundUpToAlignment(17, 8, 1) = 17 -/// RoundUpToAlignment(~0LL, 8, 3) = 3 -/// RoundUpToAlignment(321, 255, 42) = 552 +/// alignTo(5, 8, 7) = 7 +/// alignTo(17, 8, 1) = 17 +/// alignTo(~0LL, 8, 3) = 3 +/// alignTo(321, 255, 42) = 552 /// \endcode -inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align, - uint64_t Skew = 0) { +inline uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew = 0) { Skew %= Align; return (Value + Align - 1 - Skew) / Align * Align + Skew; } +/// Returns the largest uint64_t less than or equal to \p Value and is +/// \p Skew mod \p Align. \p Align must be non-zero +inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) { + Skew %= Align; + return (Value - Skew) / Align * Align + Skew; +} + /// Returns the offset to 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. inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { - return RoundUpToAlignment(Value, Align) - Value; + return alignTo(Value, Align) - Value; } -/// SignExtend32 - Sign extend B-bit number x to 32-bit int. -/// Usage int32_t r = SignExtend32<5>(x); -template <unsigned B> inline int32_t SignExtend32(uint32_t x) { - return int32_t(x << (32 - B)) >> (32 - B); +/// Sign-extend the number in the bottom B bits of X to a 32-bit integer. +/// Requires 0 < B <= 32. +template <unsigned B> inline int32_t SignExtend32(uint32_t X) { + static_assert(B > 0, "Bit width can't be 0."); + static_assert(B <= 32, "Bit width out of range."); + return int32_t(X << (32 - B)) >> (32 - B); } -/// \brief Sign extend number in the bottom B bits of X to a 32-bit int. -/// Requires 0 < B <= 32. +/// Sign-extend the number in the bottom B bits of X to a 32-bit integer. +/// Requires 0 < B < 32. inline int32_t SignExtend32(uint32_t X, unsigned B) { + assert(B > 0 && "Bit width can't be 0."); + assert(B <= 32 && "Bit width out of range."); return int32_t(X << (32 - B)) >> (32 - B); } -/// SignExtend64 - Sign extend B-bit number x to 64-bit int. -/// Usage int64_t r = SignExtend64<5>(x); +/// Sign-extend the number in the bottom B bits of X to a 64-bit integer. +/// Requires 0 < B < 64. template <unsigned B> inline int64_t SignExtend64(uint64_t x) { + static_assert(B > 0, "Bit width can't be 0."); + static_assert(B <= 64, "Bit width out of range."); return int64_t(x << (64 - B)) >> (64 - B); } -/// \brief Sign extend number in the bottom B bits of X to a 64-bit int. -/// Requires 0 < B <= 64. +/// Sign-extend the number in the bottom B bits of X to a 64-bit integer. +/// Requires 0 < B < 64. inline int64_t SignExtend64(uint64_t X, unsigned B) { + assert(B > 0 && "Bit width can't be 0."); + assert(B <= 64 && "Bit width out of range."); return int64_t(X << (64 - B)) >> (64 - B); } -/// \brief Add two unsigned integers, X and Y, of type T. -/// Clamp the result to the maximum representable value of T on overflow. -/// ResultOverflowed indicates if the result is larger than the maximum -/// representable value of type T. +/// Subtract two unsigned integers, X and Y, of type T and return the absolute +/// value of the result. +template <typename T> +typename std::enable_if<std::is_unsigned<T>::value, T>::type +AbsoluteDifference(T X, T Y) { + return std::max(X, Y) - std::min(X, Y); +} + +/// Add two unsigned integers, X and Y, of type T. Clamp the result to the +/// maximum representable value of T on overflow. ResultOverflowed indicates if +/// the result is larger than the maximum representable value of type T. template <typename T> typename std::enable_if<std::is_unsigned<T>::value, T>::type SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) { @@ -671,10 +731,9 @@ SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) { return Z; } -/// \brief Multiply two unsigned integers, X and Y, of type T. -/// Clamp the result to the maximum representable value of T on overflow. -/// ResultOverflowed indicates if the result is larger than the maximum -/// representable value of type T. +/// Multiply two unsigned integers, X and Y, of type T. Clamp the result to the +/// maximum representable value of T on overflow. ResultOverflowed indicates if +/// the result is larger than the maximum representable value of type T. template <typename T> typename std::enable_if<std::is_unsigned<T>::value, T>::type SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) { @@ -717,12 +776,10 @@ SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) { return Z; } -/// \brief Multiply two unsigned integers, X and Y, and add the unsigned -/// integer, A to the product. Clamp the result to the maximum representable -/// value of T on overflow. ResultOverflowed indicates if the result is larger -/// than the maximum representable value of type T. -/// Note that this is purely a convenience function as there is no distinction -/// where overflow occurred in a 'fused' multiply-add for unsigned numbers. +/// Multiply two unsigned integers, X and Y, and add the unsigned integer, A to +/// the product. Clamp the result to the maximum representable value of T on +/// overflow. ResultOverflowed indicates if the result is larger than the +/// maximum representable value of type T. template <typename T> typename std::enable_if<std::is_unsigned<T>::value, T>::type SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) { @@ -736,6 +793,7 @@ SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) { return SaturatingAdd(A, Product, &Overflowed); } +/// Use this rather than HUGE_VALF; the latter causes warnings on MSVC. extern const float huge_valf; } // End llvm namespace diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h index ac978d4c242c..c28fcabe78fc 100644 --- a/include/llvm/Support/OnDiskHashTable.h +++ b/include/llvm/Support/OnDiskHashTable.h @@ -152,6 +152,22 @@ public: using namespace llvm::support; endian::Writer<little> LE(Out); + // Now we're done adding entries, resize the bucket list if it's + // significantly too large. (This only happens if the number of + // entries is small and we're within our initial allocation of + // 64 buckets.) We aim for an occupancy ratio in [3/8, 3/4). + // + // As a special case, if there are two or fewer entries, just + // form a single bucket. A linear scan is fine in that case, and + // this is very common in C++ class lookup tables. This also + // guarantees we produce at least one bucket for an empty table. + // + // FIXME: Try computing a perfect hash function at this point. + unsigned TargetNumBuckets = + NumEntries <= 2 ? 1 : NextPowerOf2(NumEntries * 4 / 3); + if (TargetNumBuckets != NumBuckets) + resize(TargetNumBuckets); + // Emit the payload of the table. for (offset_type I = 0; I < NumBuckets; ++I) { Bucket &B = Buckets[I]; @@ -309,7 +325,7 @@ public: Info *InfoObj; public: - iterator() : Data(nullptr), Len(0) {} + iterator() : Key(), Data(nullptr), Len(0), InfoObj(nullptr) {} iterator(const internal_key_type K, const unsigned char *D, offset_type L, Info *InfoObj) : Key(K), Data(D), Len(L), InfoObj(InfoObj) {} diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h index 955cc991d9b7..853f0997571c 100644 --- a/include/llvm/Support/Path.h +++ b/include/llvm/Support/Path.h @@ -16,7 +16,6 @@ #ifndef LLVM_SUPPORT_PATH_H #define LLVM_SUPPORT_PATH_H -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/DataTypes.h" #include <iterator> @@ -88,6 +87,9 @@ public: reverse_iterator &operator++(); // preincrement bool operator==(const reverse_iterator &RHS) const; bool operator!=(const reverse_iterator &RHS) const { return !(*this == RHS); } + + /// @brief Difference in bytes between this and RHS. + ptrdiff_t operator-(const reverse_iterator &RHS) const; }; /// @brief Get begin iterator over \a path. @@ -140,6 +142,23 @@ void remove_filename(SmallVectorImpl<char> &path); /// prepended. void replace_extension(SmallVectorImpl<char> &path, const Twine &extension); +/// @brief Replace matching path prefix with another path. +/// +/// @code +/// /foo, /old, /new => /foo +/// /old/foo, /old, /new => /new/foo +/// /foo, <empty>, /new => /new/foo +/// /old/foo, /old, <empty> => /foo +/// @endcode +/// +/// @param Path If \a Path starts with \a OldPrefix modify to instead +/// start with \a NewPrefix. +/// @param OldPrefix The path prefix to strip from \a Path. +/// @param NewPrefix The path prefix to replace \a NewPrefix with. +void replace_path_prefix(SmallVectorImpl<char> &Path, + const StringRef &OldPrefix, + const StringRef &NewPrefix); + /// @brief Append to path. /// /// @code diff --git a/include/llvm/Support/PointerLikeTypeTraits.h b/include/llvm/Support/PointerLikeTypeTraits.h index c12d237b2796..96cdaed142c2 100644 --- a/include/llvm/Support/PointerLikeTypeTraits.h +++ b/include/llvm/Support/PointerLikeTypeTraits.h @@ -37,7 +37,8 @@ template <> struct ConstantLog2<1> : std::integral_constant<size_t, 0> {}; } // Provide PointerLikeTypeTraits for non-cvr pointers. -template <typename T> struct PointerLikeTypeTraits<T *> { +template <typename T> class PointerLikeTypeTraits<T *> { +public: static inline void *getAsVoidPointer(T *P) { return P; } static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); } @@ -46,7 +47,8 @@ template <typename T> struct PointerLikeTypeTraits<T *> { }; }; -template <> struct PointerLikeTypeTraits<void *> { +template <> class PointerLikeTypeTraits<void *> { +public: static inline void *getAsVoidPointer(void *P) { return P; } static inline void *getFromVoidPointer(void *P) { return P; } diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h index 027f9433969d..62e3bbc0ddbc 100644 --- a/include/llvm/Support/PrettyStackTrace.h +++ b/include/llvm/Support/PrettyStackTrace.h @@ -29,9 +29,11 @@ namespace llvm { /// constructed and destructed, they will add their symbolic frames to a /// virtual stack trace. This gets dumped out if the program crashes. class PrettyStackTraceEntry { - const PrettyStackTraceEntry *NextEntry; + friend PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *); + + PrettyStackTraceEntry *NextEntry; PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete; - void operator=(const PrettyStackTraceEntry&) = delete; + void operator=(const PrettyStackTraceEntry &) = delete; public: PrettyStackTraceEntry(); virtual ~PrettyStackTraceEntry(); @@ -67,7 +69,7 @@ namespace llvm { }; /// Returns the topmost element of the "pretty" stack state. - const void* SavePrettyStackState(); + const void *SavePrettyStackState(); /// Restores the topmost element of the "pretty" stack state to State, which /// should come from a previous call to SavePrettyStackState(). This is @@ -76,7 +78,7 @@ namespace llvm { /// happens after a crash that's been recovered by CrashRecoveryContext /// doesn't have frames on it that were added in code unwound by the /// CrashRecoveryContext. - void RestorePrettyStackState(const void* State); + void RestorePrettyStackState(const void *State); } // end namespace llvm diff --git a/include/llvm/Support/Printable.h b/include/llvm/Support/Printable.h index 5c1b8d5070d4..83b8f0998ae6 100644 --- a/include/llvm/Support/Printable.h +++ b/include/llvm/Support/Printable.h @@ -38,8 +38,8 @@ class raw_ostream; class Printable { public: std::function<void(raw_ostream &OS)> Print; - Printable(const std::function<void(raw_ostream &OS)> Print) - : Print(Print) {} + Printable(std::function<void(raw_ostream &OS)> Print) + : Print(std::move(Print)) {} }; static inline raw_ostream &operator<<(raw_ostream &OS, const Printable &P) { diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index cfdd06c62f33..06fd0af10aa4 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -25,7 +25,6 @@ #ifndef LLVM_SUPPORT_PROCESS_H #define LLVM_SUPPORT_PROCESS_H -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/Allocator.h" @@ -34,6 +33,7 @@ #include <system_error> namespace llvm { +template <typename T> class ArrayRef; class StringRef; namespace sys { @@ -69,6 +69,9 @@ public: /// @brief Prevent core file generation. static void PreventCoreFiles(); + /// \brief true if PreventCoreFiles has been called, false otherwise. + static bool AreCoreFilesPrevented(); + // This function returns the environment variable \arg name's value as a UTF-8 // string. \arg Name is assumed to be in UTF-8 encoding too. static Optional<std::string> GetEnv(StringRef name); diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 727864df2721..055f016d8243 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -44,6 +44,8 @@ struct ProcessInfo { #error "ProcessInfo is not defined for this platform!" #endif + enum : ProcessId { InvalidPid = 0 }; + /// The process identifier. ProcessId Pid; @@ -88,7 +90,7 @@ struct ProcessInfo { /// -2 indicates a crash during execution or timeout int ExecuteAndWait( StringRef Program, ///< Path of the program to be executed. It is - /// presumed this is the result of the findProgramByName method. + ///< presumed this is the result of the findProgramByName method. const char **args, ///< A vector of strings that are passed to the ///< program. The first element should be the name of the program. ///< The list *must* be terminated by a null char* entry. diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h index 7446558f0c88..f146e350fe62 100644 --- a/include/llvm/Support/RandomNumberGenerator.h +++ b/include/llvm/Support/RandomNumberGenerator.h @@ -16,12 +16,12 @@ #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 { +class StringRef; /// A random number generator. /// diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h index bbea97b289a6..27f025fcd080 100644 --- a/include/llvm/Support/Registry.h +++ b/include/llvm/Support/Registry.h @@ -14,9 +14,10 @@ #ifndef LLVM_SUPPORT_REGISTRY_H #define LLVM_SUPPORT_REGISTRY_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/DynamicLibrary.h" #include <memory> namespace llvm { @@ -37,69 +38,45 @@ namespace llvm { std::unique_ptr<T> instantiate() const { return Ctor(); } }; - /// Traits for registry entries. If using other than SimpleRegistryEntry, it - /// is necessary to define an alternate traits class. - template <typename T> - class RegistryTraits { - RegistryTraits() = delete; - - public: - typedef SimpleRegistryEntry<T> entry; - - /// nameof/descof - Accessors for name and description of entries. These are - // used to generate help for command-line options. - static const char *nameof(const entry &Entry) { return Entry.getName(); } - static const char *descof(const entry &Entry) { return Entry.getDesc(); } - }; - /// A global registry used in conjunction with static constructors to make /// pluggable components (like targets or garbage collectors) "just work" when /// linked with an executable. - template <typename T, typename U = RegistryTraits<T> > + template <typename T> class Registry { public: - typedef U traits; - typedef typename U::entry entry; + typedef SimpleRegistryEntry<T> entry; class node; - class listener; class iterator; private: Registry() = delete; - static void Announce(const entry &E) { - for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) - Cur->registered(E); - } - friend class node; static node *Head, *Tail; - friend class listener; - static listener *ListenerHead, *ListenerTail; - public: /// Node in linked list of entries. /// class node { friend class iterator; + friend Registry<T>; node *Next; const entry& Val; public: - node(const entry& V) : Next(nullptr), Val(V) { - if (Tail) - Tail->Next = this; - else - Head = this; - Tail = this; - - Announce(V); - } + node(const entry &V) : Next(nullptr), Val(V) {} }; + static void add_node(node *N) { + if (Tail) + Tail->Next = N; + else + Head = N; + Tail = N; + } + /// Iterators for registry entries. /// class iterator { @@ -122,60 +99,6 @@ namespace llvm { return make_range(begin(), end()); } - /// Abstract base class for registry listeners, which are informed when new - /// entries are added to the registry. Simply subclass and instantiate: - /// - /// \code - /// class CollectorPrinter : public Registry<Collector>::listener { - /// protected: - /// void registered(const Registry<Collector>::entry &e) { - /// cerr << "collector now available: " << e->getName() << "\n"; - /// } - /// - /// public: - /// CollectorPrinter() { init(); } // Print those already registered. - /// }; - /// - /// CollectorPrinter Printer; - /// \endcode - class listener { - listener *Prev, *Next; - - friend void Registry::Announce(const entry &E); - - protected: - /// Called when an entry is added to the registry. - /// - virtual void registered(const entry &) = 0; - - /// Calls 'registered' for each pre-existing entry. - /// - void init() { - for (iterator I = begin(), E = end(); I != E; ++I) - registered(*I); - } - - public: - listener() : Prev(ListenerTail), Next(nullptr) { - if (Prev) - Prev->Next = this; - else - ListenerHead = this; - ListenerTail = this; - } - - virtual ~listener() { - if (Next) - Next->Prev = Prev; - else - ListenerTail = Prev; - if (Prev) - Prev->Next = Next; - else - ListenerHead = Next; - } - }; - /// A static registration template. Use like such: /// /// Registry<Collector>::Add<FancyGC> @@ -184,14 +107,6 @@ namespace llvm { /// Use of this template requires that: /// /// 1. The registered subclass has a default constructor. - // - /// 2. The registry entry type has a constructor compatible with this - /// signature: - /// - /// entry(const char *Name, const char *ShortDesc, T *(*Ctor)()); - /// - /// If you have more elaborate requirements, then copy and modify. - /// template <typename V> class Add { entry Entry; @@ -201,27 +116,65 @@ namespace llvm { public: Add(const char *Name, const char *Desc) - : Entry(Name, Desc, CtorFn), Node(Entry) {} + : Entry(Name, Desc, CtorFn), Node(Entry) { + add_node(&Node); + } }; - /// Registry::Parser now lives in llvm/Support/RegistryParser.h. + /// A dynamic import facility. This is used on Windows to + /// import the entries added in the plugin. + static void import(sys::DynamicLibrary &DL, const char *RegistryName) { + typedef void *(*GetRegistry)(); + std::string Name("LLVMGetRegistry_"); + Name.append(RegistryName); + GetRegistry Getter = + (GetRegistry)(intptr_t)DL.getAddressOfSymbol(Name.c_str()); + if (Getter) { + // Call the getter function in order to get the full copy of the + // registry defined in the plugin DLL, and copy them over to the + // current Registry. + typedef std::pair<const node *, const node *> Info; + Info *I = static_cast<Info *>(Getter()); + iterator begin(I->first); + iterator end(I->second); + for (++end; begin != end; ++begin) { + // This Node object needs to remain alive for the + // duration of the program. + add_node(new node(*begin)); + } + } + } + + /// Retrieve the data to be passed across DLL boundaries when + /// importing registries from another DLL on Windows. + static void *exportRegistry() { + static std::pair<const node *, const node *> Info(Head, Tail); + return &Info; + } }; + // Since these are defined in a header file, plugins must be sure to export // these symbols. + template <typename T> + typename Registry<T>::node *Registry<T>::Head; - template <typename T, typename U> - typename Registry<T,U>::node *Registry<T,U>::Head; - - template <typename T, typename U> - typename Registry<T,U>::node *Registry<T,U>::Tail; - - template <typename T, typename U> - typename Registry<T,U>::listener *Registry<T,U>::ListenerHead; - - template <typename T, typename U> - typename Registry<T,U>::listener *Registry<T,U>::ListenerTail; - + template <typename T> + typename Registry<T>::node *Registry<T>::Tail; } // end namespace llvm +#ifdef LLVM_ON_WIN32 +#define LLVM_EXPORT_REGISTRY(REGISTRY_CLASS) \ + extern "C" { \ + __declspec(dllexport) void *__cdecl LLVMGetRegistry_##REGISTRY_CLASS() { \ + return REGISTRY_CLASS::exportRegistry(); \ + } \ + } +#define LLVM_IMPORT_REGISTRY(REGISTRY_CLASS, DL) \ + REGISTRY_CLASS::import(DL, #REGISTRY_CLASS) +#else +#define LLVM_EXPORT_REGISTRY(REGISTRY_CLASS) +#define LLVM_IMPORT_REGISTRY(REGISTRY_CLASS, DL) +#endif + #endif // LLVM_SUPPORT_REGISTRY_H diff --git a/include/llvm/Support/RegistryParser.h b/include/llvm/Support/RegistryParser.h deleted file mode 100644 index a6997b6fe774..000000000000 --- a/include/llvm/Support/RegistryParser.h +++ /dev/null @@ -1,55 +0,0 @@ -//=== RegistryParser.h - Linker-supported plugin registries -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines a command-line parser for a registry. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_REGISTRYPARSER_H -#define LLVM_SUPPORT_REGISTRYPARSER_H - -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Registry.h" - -namespace llvm { - - /// A command-line parser for a registry. Use like such: - /// - /// static cl::opt<Registry<Collector>::entry, false, - /// RegistryParser<Collector> > - /// GCOpt("gc", cl::desc("Garbage collector to use."), - /// cl::value_desc()); - /// - /// To make use of the value: - /// - /// Collector *TheCollector = GCOpt->instantiate(); - /// - template <typename T, typename U = RegistryTraits<T> > - class RegistryParser : - public cl::parser<const typename U::entry*>, - public Registry<T, U>::listener { - typedef U traits; - typedef typename U::entry entry; - typedef typename Registry<T, U>::listener listener; - - protected: - void registered(const entry &E) { - addLiteralOption(traits::nameof(E), &E, traits::descof(E)); - } - - public: - void initialize(cl::Option &O) { - listener::init(); - cl::parser<const typename U::entry*>::initialize(O); - } - }; - -} - -#endif // LLVM_SUPPORT_REGISTRYPARSER_H diff --git a/include/llvm/Support/SHA1.h b/include/llvm/Support/SHA1.h new file mode 100644 index 000000000000..8347a713f272 --- /dev/null +++ b/include/llvm/Support/SHA1.h @@ -0,0 +1,82 @@ +//==- SHA1.h - SHA1 implementation for LLVM --*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This code is taken from public domain +// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c) +// and modified by wrapping it in a C++ interface for LLVM, +// and removing unnecessary code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SHA1_H +#define LLVM_SUPPORT_SHA1_H + +#include "llvm/ADT/ArrayRef.h" + +#include <cstdint> + +namespace llvm { +template <typename T> class ArrayRef; +class StringRef; + +/// A class that wrap the SHA1 algorithm. +class SHA1 { +public: + SHA1() { init(); } + + /// Reinitialize the internal state + void init(); + + /// Digest more data. + void update(ArrayRef<uint8_t> Data); + + /// Digest more data. + void update(StringRef Str) { + update(ArrayRef<uint8_t>((uint8_t *)const_cast<char *>(Str.data()), + Str.size())); + } + + /// Return a reference to the current raw 160-bits SHA1 for the digested data + /// since the last call to init(). This call will add data to the internal + /// state and as such is not suited for getting an intermediate result + /// (see result()). + StringRef final(); + + /// Return a reference to the current raw 160-bits SHA1 for the digested data + /// since the last call to init(). This is suitable for getting the SHA1 at + /// any time without invalidating the internal state so that more calls can be + /// made into update. + StringRef result(); + +private: + /// Define some constants. + /// "static constexpr" would be cleaner but MSVC does not support it yet. + enum { BLOCK_LENGTH = 64 }; + enum { HASH_LENGTH = 20 }; + + // Internal State + struct { + uint32_t Buffer[BLOCK_LENGTH / 4]; + uint32_t State[HASH_LENGTH / 4]; + uint32_t ByteCount; + uint8_t BufferOffset; + } InternalState; + + // Internal copy of the hash, populated and accessed on calls to result() + uint32_t HashResult[HASH_LENGTH / 4]; + + // Helper + void writebyte(uint8_t data); + void hashBlock(); + void addUncounted(uint8_t data); + void pad(); +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h index c6421efc8b49..910174732994 100644 --- a/include/llvm/Support/ScaledNumber.h +++ b/include/llvm/Support/ScaledNumber.h @@ -859,7 +859,6 @@ template <class DigitsT> void ScaledNumber<DigitsT>::shiftLeft(int32_t Shift) { } Digits <<= Shift; - return; } template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) { @@ -886,7 +885,6 @@ template <class DigitsT> void ScaledNumber<DigitsT>::shiftRight(int32_t Shift) { } Digits >>= Shift; - return; } template <typename T> struct isPodLike; @@ -896,4 +894,4 @@ template <typename T> struct isPodLike<ScaledNumber<T>> { } // end namespace llvm -#endif +#endif // LLVM_SUPPORT_SCALEDNUMBER_H diff --git a/include/llvm/Support/ScopedPrinter.h b/include/llvm/Support/ScopedPrinter.h new file mode 100644 index 000000000000..a2f2e0985431 --- /dev/null +++ b/include/llvm/Support/ScopedPrinter.h @@ -0,0 +1,378 @@ +//===-- ScopedPrinter.h ---------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SCOPEDPRINTER_H +#define LLVM_SUPPORT_SCOPEDPRINTER_H + +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> + +namespace llvm { + +template <typename T> struct EnumEntry { + StringRef Name; + // While Name suffices in most of the cases, in certain cases + // GNU style and LLVM style of ELFDumper do not + // display same string for same enum. The AltName if initialized appropriately + // will hold the string that GNU style emits. + // Example: + // "EM_X86_64" string on LLVM style for Elf_Ehdr->e_machine corresponds to + // "Advanced Micro Devices X86-64" on GNU style + StringRef AltName; + T Value; + EnumEntry(StringRef N, StringRef A, T V) : Name(N), AltName(A), Value(V) {} + EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {} +}; + +struct HexNumber { + // To avoid sign-extension we have to explicitly cast to the appropriate + // unsigned type. The overloads are here so that every type that is implicitly + // convertible to an integer (including enums and endian helpers) can be used + // without requiring type traits or call-site changes. + HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) {} + HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) {} + HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) {} + HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) {} + HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) {} + HexNumber(signed long long Value) + : Value(static_cast<unsigned long long>(Value)) {} + HexNumber(unsigned char Value) : Value(Value) {} + HexNumber(unsigned short Value) : Value(Value) {} + HexNumber(unsigned int Value) : Value(Value) {} + HexNumber(unsigned long Value) : Value(Value) {} + HexNumber(unsigned long long Value) : Value(Value) {} + uint64_t Value; +}; + +raw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value); +const std::string to_hexString(uint64_t Value, bool UpperCase = true); + +template <class T> const std::string to_string(const T &Value) { + std::string number; + llvm::raw_string_ostream stream(number); + stream << Value; + return stream.str(); +} + +class ScopedPrinter { +public: + ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {} + + void flush() { OS.flush(); } + + void indent(int Levels = 1) { IndentLevel += Levels; } + + void unindent(int Levels = 1) { + IndentLevel = std::max(0, IndentLevel - Levels); + } + + void resetIndent() { IndentLevel = 0; } + + void setPrefix(StringRef P) { Prefix = P; } + + void printIndent() { + OS << Prefix; + for (int i = 0; i < IndentLevel; ++i) + OS << " "; + } + + template <typename T> HexNumber hex(T Value) { return HexNumber(Value); } + + template <typename T, typename TEnum> + void printEnum(StringRef Label, T Value, + ArrayRef<EnumEntry<TEnum>> EnumValues) { + StringRef Name; + bool Found = false; + for (const auto &EnumItem : EnumValues) { + if (EnumItem.Value == Value) { + Name = EnumItem.Name; + Found = true; + break; + } + } + + if (Found) { + startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n"; + } else { + startLine() << Label << ": " << hex(Value) << "\n"; + } + } + + template <typename T, typename TFlag> + void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags, + TFlag EnumMask1 = {}, TFlag EnumMask2 = {}, + TFlag EnumMask3 = {}) { + typedef EnumEntry<TFlag> FlagEntry; + typedef SmallVector<FlagEntry, 10> FlagVector; + FlagVector SetFlags; + + for (const auto &Flag : Flags) { + if (Flag.Value == 0) + continue; + + TFlag EnumMask{}; + if (Flag.Value & EnumMask1) + EnumMask = EnumMask1; + else if (Flag.Value & EnumMask2) + EnumMask = EnumMask2; + else if (Flag.Value & EnumMask3) + EnumMask = EnumMask3; + bool IsEnum = (Flag.Value & EnumMask) != 0; + if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || + (IsEnum && (Value & EnumMask) == Flag.Value)) { + SetFlags.push_back(Flag); + } + } + + std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); + + startLine() << Label << " [ (" << hex(Value) << ")\n"; + for (const auto &Flag : SetFlags) { + startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n"; + } + startLine() << "]\n"; + } + + template <typename T> void printFlags(StringRef Label, T Value) { + startLine() << Label << " [ (" << hex(Value) << ")\n"; + uint64_t Flag = 1; + uint64_t Curr = Value; + while (Curr > 0) { + if (Curr & 1) + startLine() << " " << hex(Flag) << "\n"; + Curr >>= 1; + Flag <<= 1; + } + startLine() << "]\n"; + } + + void printNumber(StringRef Label, uint64_t Value) { + startLine() << Label << ": " << Value << "\n"; + } + + void printNumber(StringRef Label, uint32_t Value) { + startLine() << Label << ": " << Value << "\n"; + } + + void printNumber(StringRef Label, uint16_t Value) { + startLine() << Label << ": " << Value << "\n"; + } + + void printNumber(StringRef Label, uint8_t Value) { + startLine() << Label << ": " << unsigned(Value) << "\n"; + } + + void printNumber(StringRef Label, int64_t Value) { + startLine() << Label << ": " << Value << "\n"; + } + + void printNumber(StringRef Label, int32_t Value) { + startLine() << Label << ": " << Value << "\n"; + } + + void printNumber(StringRef Label, int16_t Value) { + startLine() << Label << ": " << Value << "\n"; + } + + void printNumber(StringRef Label, int8_t Value) { + startLine() << Label << ": " << int(Value) << "\n"; + } + + void printNumber(StringRef Label, const APSInt &Value) { + startLine() << Label << ": " << Value << "\n"; + } + + void printBoolean(StringRef Label, bool Value) { + startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n'; + } + + template <typename... T> void printVersion(StringRef Label, T... Version) { + startLine() << Label << ": "; + printVersionInternal(Version...); + getOStream() << "\n"; + } + + template <typename T> void printList(StringRef Label, const T &List) { + startLine() << Label << ": ["; + bool Comma = false; + for (const auto &Item : List) { + if (Comma) + OS << ", "; + OS << Item; + Comma = true; + } + OS << "]\n"; + } + + template <typename T, typename U> + void printList(StringRef Label, const T &List, const U &Printer) { + startLine() << Label << ": ["; + bool Comma = false; + for (const auto &Item : List) { + if (Comma) + OS << ", "; + Printer(OS, Item); + Comma = true; + } + OS << "]\n"; + } + + template <typename T> void printHexList(StringRef Label, const T &List) { + startLine() << Label << ": ["; + bool Comma = false; + for (const auto &Item : List) { + if (Comma) + OS << ", "; + OS << hex(Item); + Comma = true; + } + OS << "]\n"; + } + + template <typename T> void printHex(StringRef Label, T Value) { + startLine() << Label << ": " << hex(Value) << "\n"; + } + + template <typename T> void printHex(StringRef Label, StringRef Str, T Value) { + startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n"; + } + + template <typename T> + void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) { + startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n'; + } + + void printString(StringRef Value) { startLine() << Value << "\n"; } + + void printString(StringRef Label, StringRef Value) { + startLine() << Label << ": " << Value << "\n"; + } + + void printString(StringRef Label, const std::string &Value) { + startLine() << Label << ": " << Value << "\n"; + } + + template <typename T> + void printNumber(StringRef Label, StringRef Str, T Value) { + startLine() << Label << ": " << Str << " (" << Value << ")\n"; + } + + void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) { + printBinaryImpl(Label, Str, Value, false); + } + + void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) { + auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), + Value.size()); + printBinaryImpl(Label, Str, V, false); + } + + void printBinary(StringRef Label, ArrayRef<uint8_t> Value) { + printBinaryImpl(Label, StringRef(), Value, false); + } + + void printBinary(StringRef Label, ArrayRef<char> Value) { + auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), + Value.size()); + printBinaryImpl(Label, StringRef(), V, false); + } + + void printBinary(StringRef Label, StringRef Value) { + auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), + Value.size()); + printBinaryImpl(Label, StringRef(), V, false); + } + + void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) { + printBinaryImpl(Label, StringRef(), Value, true); + } + + void printBinaryBlock(StringRef Label, StringRef Value) { + auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()), + Value.size()); + printBinaryImpl(Label, StringRef(), V, true); + } + + template <typename T> void printObject(StringRef Label, const T &Value) { + startLine() << Label << ": " << Value << "\n"; + } + + raw_ostream &startLine() { + printIndent(); + return OS; + } + + raw_ostream &getOStream() { return OS; } + +private: + template <typename T> void printVersionInternal(T Value) { + getOStream() << Value; + } + + template <typename S, typename T, typename... TArgs> + void printVersionInternal(S Value, T Value2, TArgs... Args) { + getOStream() << Value << "."; + printVersionInternal(Value2, Args...); + } + + template <typename T> + static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) { + return lhs.Name < rhs.Name; + } + + void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value, + bool Block); + + raw_ostream &OS; + int IndentLevel; + StringRef Prefix; +}; + +template <> +inline void +ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label, + support::ulittle16_t Value) { + startLine() << Label << ": " << hex(Value) << "\n"; +} + +template<char Open, char Close> +struct DelimitedScope { + explicit DelimitedScope(ScopedPrinter &W) : W(W) { + W.startLine() << Open << '\n'; + W.indent(); + } + + DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) { + W.startLine() << N; + if (!N.empty()) + W.getOStream() << ' '; + W.getOStream() << Open << '\n'; + W.indent(); + } + + ~DelimitedScope() { + W.unindent(); + W.startLine() << Close << '\n'; + } + + ScopedPrinter &W; +}; + +using DictScope = DelimitedScope<'{', '}'>; +using ListScope = DelimitedScope<'[', ']'>; + +} // namespace llvm + +#endif diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h index 2a4d84bd891a..cbd6f686a778 100644 --- a/include/llvm/Support/Signals.h +++ b/include/llvm/Support/Signals.h @@ -38,8 +38,14 @@ namespace sys { /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the /// process, print a stack trace and then exit. - /// @brief Print a stack trace if a fatal signal occurs. - void PrintStackTraceOnErrorSignal(bool DisableCrashReporting = false); + /// \brief Print a stack trace if a fatal signal occurs. + /// \param Argv0 the current binary name, used to find the symbolizer + /// relative to the current binary before searching $PATH; can be + /// StringRef(), in which case we will only search $PATH. + /// \param DisableCrashReporting if \c true, disable the normal crash + /// reporting mechanisms on the underlying operating system. + void PrintStackTraceOnErrorSignal(StringRef Argv0, + bool DisableCrashReporting = false); /// Disable all system dialog boxes that appear when the process crashes. void DisableSystemDialogsOnCrash(); diff --git a/include/llvm/Support/StreamingMemoryObject.h b/include/llvm/Support/StreamingMemoryObject.h index a5980c235946..1ab85372cd20 100644 --- a/include/llvm/Support/StreamingMemoryObject.h +++ b/include/llvm/Support/StreamingMemoryObject.h @@ -28,15 +28,7 @@ public: uint64_t getExtent() const override; uint64_t readBytes(uint8_t *Buf, uint64_t Size, uint64_t Address) const override; - const uint8_t *getPointer(uint64_t address, uint64_t size) const override { - // FIXME: 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 (any - // that need Blobs) don't stream. - report_fatal_error("getPointer in streaming memory objects not allowed"); - return nullptr; - } + const uint8_t *getPointer(uint64_t Address, uint64_t Size) const override; bool isValidAddress(uint64_t address) const override; /// Drop s bytes from the front of the stream, pushing the positions of the diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index 7761fa1d7e01..91693aceb27d 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -18,7 +18,6 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include <cstddef> -#include <limits> namespace llvm { namespace sys { diff --git a/include/llvm/Support/TargetParser.h b/include/llvm/Support/TargetParser.h index c21019d0c5b8..0e2141f6d46f 100644 --- a/include/llvm/Support/TargetParser.h +++ b/include/llvm/Support/TargetParser.h @@ -83,6 +83,7 @@ enum ArchExtKind : unsigned { AEK_VIRT = 0x200, AEK_DSP = 0x400, AEK_FP16 = 0x800, + AEK_RAS = 0x1000, // Unsupported extensions. AEK_OS = 0x8000000, AEK_IWMMXT = 0x10000000, @@ -140,6 +141,61 @@ unsigned parseArchProfile(StringRef Arch); unsigned parseArchVersion(StringRef Arch); } // namespace ARM + +// FIXME:This should be made into class design,to avoid dupplication. +namespace AArch64 { + +// Arch extension modifiers for CPUs. +enum ArchExtKind : unsigned { + AEK_INVALID = 0x0, + AEK_NONE = 0x1, + AEK_CRC = 0x2, + AEK_CRYPTO = 0x4, + AEK_FP = 0x8, + AEK_SIMD = 0x10, + AEK_FP16 = 0x20, + AEK_PROFILE = 0x40, + AEK_RAS = 0x80 +}; + +StringRef getCanonicalArchName(StringRef Arch); + +// Information by ID +StringRef getFPUName(unsigned FPUKind); +unsigned getFPUVersion(unsigned FPUKind); +unsigned getFPUNeonSupportLevel(unsigned FPUKind); +unsigned getFPURestriction(unsigned FPUKind); + +// FIXME: These should be moved to TargetTuple once it exists +bool getFPUFeatures(unsigned FPUKind, std::vector<const char *> &Features); +bool getExtensionFeatures(unsigned Extensions, + std::vector<const char*> &Features); +bool getArchFeatures(unsigned ArchKind, std::vector<const char *> &Features); + +StringRef getArchName(unsigned ArchKind); +unsigned getArchAttr(unsigned ArchKind); +StringRef getCPUAttr(unsigned ArchKind); +StringRef getSubArch(unsigned ArchKind); +StringRef getArchExtName(unsigned ArchExtKind); +const char *getArchExtFeature(StringRef ArchExt); +unsigned checkArchVersion(StringRef Arch); + +// Information by Name +unsigned getDefaultFPU(StringRef CPU, unsigned ArchKind); +unsigned getDefaultExtensions(StringRef CPU, unsigned ArchKind); +StringRef getDefaultCPU(StringRef Arch); + +// Parser +unsigned parseFPU(StringRef FPU); +unsigned parseArch(StringRef Arch); +unsigned parseArchExt(StringRef ArchExt); +unsigned parseCPUArch(StringRef CPU); +unsigned parseArchISA(StringRef Arch); +unsigned parseArchEndian(StringRef Arch); +unsigned parseArchProfile(StringRef Arch); +unsigned parseArchVersion(StringRef Arch); + +} // namespace AArch64 } // namespace llvm #endif diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index aec181b1d266..076558e4df77 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -20,6 +20,7 @@ #define LLVM_SUPPORT_TARGETREGISTRY_H #include "llvm-c/Disassembler.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/FormattedStream.h" @@ -33,7 +34,6 @@ class MCAsmBackend; class MCAsmInfo; class MCAsmParser; class MCCodeEmitter; -class MCCodeGenInfo; class MCContext; class MCDisassembler; class MCInstrAnalysis; @@ -92,10 +92,9 @@ public: typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI, const Triple &TT); - typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(const Triple &TT, - Reloc::Model RM, - CodeModel::Model CM, - CodeGenOpt::Level OL); + typedef void (*MCAdjustCodeGenOptsFnTy)(const Triple &TT, Reloc::Model RM, + CodeModel::Model &CM); + typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo *Info); typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(const Triple &TT); @@ -104,8 +103,8 @@ public: StringRef Features); typedef TargetMachine *(*TargetMachineCtorTy)( const Target &T, const Triple &TT, StringRef CPU, StringRef Features, - const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL); + const TargetOptions &Options, Optional<Reloc::Model> RM, + CodeModel::Model CM, CodeGenOpt::Level OL); // If it weren't for layering issues (this header is in llvm/Support, but // depends on MC?) this should take the Streamer by value rather than rvalue // reference. @@ -177,9 +176,7 @@ private: /// registered. MCAsmInfoCtorFnTy MCAsmInfoCtorFn; - /// MCCodeGenInfoCtorFn - Constructor function for this target's - /// MCCodeGenInfo, if registered. - MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn; + MCAdjustCodeGenOptsFnTy MCAdjustCodeGenOptsFn; /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo, /// if registered. @@ -300,14 +297,10 @@ public: return MCAsmInfoCtorFn(MRI, Triple(TheTriple)); } - /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation. - /// - MCCodeGenInfo *createMCCodeGenInfo(StringRef TT, Reloc::Model RM, - CodeModel::Model CM, - CodeGenOpt::Level OL) const { - if (!MCCodeGenInfoCtorFn) - return nullptr; - return MCCodeGenInfoCtorFn(Triple(TT), RM, CM, OL); + void adjustCodeGenOpts(const Triple &TT, Reloc::Model RM, + CodeModel::Model &CM) const { + if (MCAdjustCodeGenOptsFn) + MCAdjustCodeGenOptsFn(TT, RM, CM); } /// createMCInstrInfo - Create a MCInstrInfo implementation. @@ -359,8 +352,7 @@ public: /// host if that does not exist. TargetMachine * createTargetMachine(StringRef TT, StringRef CPU, StringRef Features, - const TargetOptions &Options, - Reloc::Model RM = Reloc::Default, + const TargetOptions &Options, Optional<Reloc::Model> RM, CodeModel::Model CM = CodeModel::Default, CodeGenOpt::Level OL = CodeGenOpt::Default) const { if (!TargetMachineCtorFn) @@ -646,18 +638,9 @@ struct TargetRegistry { T.MCAsmInfoCtorFn = Fn; } - /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCCodeGenInfo for the target. - static void RegisterMCCodeGenInfo(Target &T, - Target::MCCodeGenInfoCtorFnTy Fn) { - T.MCCodeGenInfoCtorFn = Fn; + static void registerMCAdjustCodeGenOpts(Target &T, + Target::MCAdjustCodeGenOptsFnTy Fn) { + T.MCAdjustCodeGenOptsFn = Fn; } /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the @@ -914,39 +897,9 @@ struct RegisterMCAsmInfoFn { } }; -/// RegisterMCCodeGenInfo - Helper template for registering a target codegen -/// info -/// implementation. This invokes the static "Create" method on the class -/// to actually do the construction. Usage: -/// -/// extern "C" void LLVMInitializeFooTarget() { -/// extern Target TheFooTarget; -/// RegisterMCCodeGenInfo<FooMCCodeGenInfo> X(TheFooTarget); -/// } -template <class MCCodeGenInfoImpl> struct RegisterMCCodeGenInfo { - RegisterMCCodeGenInfo(Target &T) { - TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator); - } - -private: - static MCCodeGenInfo *Allocator(const Triple & /*TT*/, Reloc::Model /*RM*/, - CodeModel::Model /*CM*/, - CodeGenOpt::Level /*OL*/) { - return new MCCodeGenInfoImpl(); - } -}; - -/// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen -/// info implementation. This invokes the specified function to do the -/// construction. Usage: -/// -/// extern "C" void LLVMInitializeFooTarget() { -/// extern Target TheFooTarget; -/// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction); -/// } -struct RegisterMCCodeGenInfoFn { - RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCCodeGenInfo(T, Fn); +struct RegisterMCAdjustCodeGenOptsFn { + RegisterMCAdjustCodeGenOptsFn(Target &T, Target::MCAdjustCodeGenOptsFnTy Fn) { + TargetRegistry::registerMCAdjustCodeGenOpts(T, Fn); } }; @@ -1097,7 +1050,8 @@ template <class TargetMachineImpl> struct RegisterTargetMachine { private: static TargetMachine *Allocator(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, - const TargetOptions &Options, Reloc::Model RM, + const TargetOptions &Options, + Optional<Reloc::Model> RM, CodeModel::Model CM, CodeGenOpt::Level OL) { return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL); } diff --git a/include/llvm/Support/ThreadPool.h b/include/llvm/Support/ThreadPool.h index 745334db4450..665cec2465bf 100644 --- a/include/llvm/Support/ThreadPool.h +++ b/include/llvm/Support/ThreadPool.h @@ -33,6 +33,7 @@ #pragma warning(pop) #endif +#include <atomic> #include <condition_variable> #include <functional> #include <memory> diff --git a/include/llvm/Support/Threading.h b/include/llvm/Support/Threading.h index 9007c132a99a..09b96dfb4c1c 100644 --- a/include/llvm/Support/Threading.h +++ b/include/llvm/Support/Threading.h @@ -15,6 +15,27 @@ #ifndef LLVM_SUPPORT_THREADING_H #define LLVM_SUPPORT_THREADING_H +#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX +#include "llvm/Support/Compiler.h" +#include <ciso646> // So we can check the C++ standard lib macros. +#include <functional> + +// We use std::call_once on all Unix platforms except for NetBSD with +// libstdc++. That platform has a bug they are working to fix, and they'll +// remove the NetBSD checks once fixed. +#if defined(LLVM_ON_UNIX) && \ + !(defined(__NetBSD__) && !defined(_LIBCPP_VERSION)) && !defined(__ppc__) +#define LLVM_THREADING_USE_STD_CALL_ONCE 1 +#else +#define LLVM_THREADING_USE_STD_CALL_ONCE 0 +#endif + +#if LLVM_THREADING_USE_STD_CALL_ONCE +#include <mutex> +#else +#include "llvm/Support/Atomic.h" +#endif + namespace llvm { /// Returns true if LLVM is compiled with support for multi-threading, and /// false otherwise. @@ -34,6 +55,66 @@ namespace llvm { /// the thread stack. void llvm_execute_on_thread(void (*UserFn)(void*), void *UserData, unsigned RequestedStackSize = 0); + +#if LLVM_THREADING_USE_STD_CALL_ONCE + + typedef std::once_flag once_flag; + + /// This macro is the only way you should define your once flag for LLVM's + /// call_once. +#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag + +#else + + enum InitStatus { Uninitialized = 0, Wait = 1, Done = 2 }; + typedef volatile sys::cas_flag once_flag; + + /// This macro is the only way you should define your once flag for LLVM's + /// call_once. +#define LLVM_DEFINE_ONCE_FLAG(flag) static once_flag flag = Uninitialized + +#endif + + /// \brief Execute the function specified as a parameter once. + /// + /// Typical usage: + /// \code + /// void foo() {...}; + /// ... + /// LLVM_DEFINE_ONCE_FLAG(flag); + /// call_once(flag, foo); + /// \endcode + /// + /// \param flag Flag used for tracking whether or not this has run. + /// \param F Function to call once. + template <typename Function, typename... Args> + void call_once(once_flag &flag, Function &&F, Args &&... ArgList) { +#if LLVM_THREADING_USE_STD_CALL_ONCE + std::call_once(flag, std::forward<Function>(F), + std::forward<Args>(ArgList)...); +#else + // For other platforms we use a generic (if brittle) version based on our + // atomics. + sys::cas_flag old_val = sys::CompareAndSwap(&flag, Wait, Uninitialized); + if (old_val == Uninitialized) { + std::forward<Function>(F)(std::forward<Args>(ArgList)...); + sys::MemoryFence(); + TsanIgnoreWritesBegin(); + TsanHappensBefore(&flag); + flag = Done; + TsanIgnoreWritesEnd(); + } else { + // Wait until any thread doing the call has finished. + sys::cas_flag tmp = flag; + sys::MemoryFence(); + while (tmp != Done) { + tmp = flag; + sys::MemoryFence(); + } + } + TsanHappensAfter(&flag); +#endif + } } #endif diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index 499fe7b7e70c..f0cb07599b86 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -104,6 +104,9 @@ public: const std::string &getName() const { return Name; } bool isInitialized() const { return TG != nullptr; } + /// Check if the timer is currently running. + bool isRunning() const { return Running; } + /// Check if startTimer() has ever been called on this timer. bool hasTriggered() const { return Triggered; } diff --git a/include/llvm/Support/TrailingObjects.h b/include/llvm/Support/TrailingObjects.h index 8529746eeccc..5a21cddf9731 100644 --- a/include/llvm/Support/TrailingObjects.h +++ b/include/llvm/Support/TrailingObjects.h @@ -197,7 +197,7 @@ struct TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy, NextTy, typename ExtractSecondType<MoreTys, size_t>::type... MoreCounts) { return additionalSizeToAllocImpl( (requiresRealignment() - ? llvm::RoundUpToAlignment(SizeSoFar, llvm::alignOf<NextTy>()) + ? llvm::alignTo(SizeSoFar, llvm::alignOf<NextTy>()) : SizeSoFar) + sizeof(NextTy) * Count1, MoreCounts...); @@ -290,7 +290,7 @@ class TrailingObjects : private trailing_objects_internal::TrailingObjectsImpl< } public: - // make this (privately inherited) class public. + // Make this (privately inherited) member public. using ParentType::OverloadToken; /// Returns a pointer to the trailing object array of the given type @@ -342,6 +342,51 @@ public: TrailingTys, size_t>::type... Counts) { return sizeof(BaseTy) + ParentType::additionalSizeToAllocImpl(0, Counts...); } + + /// A type where its ::with_counts template member has a ::type member + /// suitable for use as uninitialized storage for an object with the given + /// trailing object counts. The template arguments are similar to those + /// of additionalSizeToAlloc. + /// + /// Use with FixedSizeStorageOwner, e.g.: + /// + /// \code{.cpp} + /// + /// MyObj::FixedSizeStorage<void *>::with_counts<1u>::type myStackObjStorage; + /// MyObj::FixedSizeStorageOwner + /// myStackObjOwner(new ((void *)&myStackObjStorage) MyObj); + /// MyObj *const myStackObjPtr = myStackObjOwner.get(); + /// + /// \endcode + template <typename... Tys> struct FixedSizeStorage { + template <size_t... Counts> struct with_counts { + enum { Size = totalSizeToAlloc<Tys...>(Counts...) }; + typedef llvm::AlignedCharArray< + llvm::AlignOf<BaseTy>::Alignment, Size + > type; + }; + }; + + /// A type that acts as the owner for an object placed into fixed storage. + class FixedSizeStorageOwner { + public: + FixedSizeStorageOwner(BaseTy *p) : p(p) {} + ~FixedSizeStorageOwner() { + assert(p && "FixedSizeStorageOwner owns null?"); + p->~BaseTy(); + } + + BaseTy *get() { return p; } + const BaseTy *get() const { return p; } + + private: + FixedSizeStorageOwner(const FixedSizeStorageOwner &) = delete; + FixedSizeStorageOwner(FixedSizeStorageOwner &&) = delete; + FixedSizeStorageOwner &operator=(const FixedSizeStorageOwner &) = delete; + FixedSizeStorageOwner &operator=(FixedSizeStorageOwner &&) = delete; + + BaseTy *const p; + }; }; } // end namespace llvm diff --git a/include/llvm/Support/TypeName.h b/include/llvm/Support/TypeName.h new file mode 100644 index 000000000000..0eb7ead98b21 --- /dev/null +++ b/include/llvm/Support/TypeName.h @@ -0,0 +1,65 @@ +//===- TypeName.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TYPENAME_H +#define LLVM_SUPPORT_TYPENAME_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +/// We provide a function which tries to compute the (demangled) name of a type +/// statically. +/// +/// This routine may fail on some platforms or for particularly unusual types. +/// Do not use it for anything other than logging and debugging aids. It isn't +/// portable or dependendable in any real sense. +/// +/// The returned StringRef will point into a static storage duration string. +/// However, it may not be null terminated and may be some strangely aligned +/// inner substring of a larger string. +template <typename DesiredTypeName> +inline StringRef getTypeName() { +#if defined(__clang__) || defined(__GNUC__) + StringRef Name = __PRETTY_FUNCTION__; + + StringRef Key = "DesiredTypeName = "; + Name = Name.substr(Name.find(Key)); + assert(!Name.empty() && "Unable to find the template parameter!"); + Name = Name.drop_front(Key.size()); + + assert(Name.endswith("]") && "Name doesn't end in the substitution key!"); + return Name.drop_back(1); +#elif defined(_MSC_VER) + StringRef Name = __FUNCSIG__; + + StringRef Key = "getTypeName<"; + Name = Name.substr(Name.find(Key)); + assert(!Name.empty() && "Unable to find the function name!"); + Name = Name.drop_front(Key.size()); + + for (StringRef Prefix : {"class ", "struct ", "union ", "enum "}) + if (Name.startswith(Prefix)) { + Name = Name.drop_front(Prefix.size()); + break; + } + + auto AnglePos = Name.rfind('>'); + assert(AnglePos != StringRef::npos && "Unable to find the closing '>'!"); + return Name.substr(0, AnglePos); +#else + // No known technique for statically extracting a type name on this compiler. + // We return a string that is unlikely to look like any type in LLVM. + return "UNKNOWN_TYPE"; +#endif +} + +} + +#endif diff --git a/include/llvm/Support/Unicode.h b/include/llvm/Support/Unicode.h index f668a5bc88df..adedb1ed83a6 100644 --- a/include/llvm/Support/Unicode.h +++ b/include/llvm/Support/Unicode.h @@ -15,9 +15,9 @@ #ifndef LLVM_SUPPORT_UNICODE_H #define LLVM_SUPPORT_UNICODE_H -#include "llvm/ADT/StringRef.h" - namespace llvm { +class StringRef; + namespace sys { namespace unicode { diff --git a/include/llvm/Support/Valgrind.h b/include/llvm/Support/Valgrind.h index 12b0dc961daa..084b901b326c 100644 --- a/include/llvm/Support/Valgrind.h +++ b/include/llvm/Support/Valgrind.h @@ -1,4 +1,4 @@ -//===- llvm/Support/Valgrind.h - Communication with Valgrind -----*- C++ -*-===// +//===- llvm/Support/Valgrind.h - Communication with Valgrind ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,9 +16,7 @@ #ifndef LLVM_SUPPORT_VALGRIND_H #define LLVM_SUPPORT_VALGRIND_H -#include "llvm/Config/llvm-config.h" -#include "llvm/Support/Compiler.h" -#include <stddef.h> +#include <cstddef> namespace llvm { namespace sys { @@ -28,7 +26,7 @@ namespace sys { // Discard valgrind's translation of code in the range [Addr .. Addr + Len). // Otherwise valgrind may continue to execute the old version of the code. void ValgrindDiscardTranslations(const void *Addr, size_t Len); -} -} +} // namespace sys +} // end namespace llvm -#endif +#endif // LLVM_SUPPORT_VALGRIND_H diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index a5addfa3c7ae..23014fc10a3f 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -41,7 +41,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/SMLoc.h" -#include <limits> #include <map> #include <utility> diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index fb2badfd93ba..bc3fa8ad11da 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -10,8 +10,6 @@ #ifndef LLVM_SUPPORT_YAMLTRAITS_H #define LLVM_SUPPORT_YAMLTRAITS_H -#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" @@ -19,6 +17,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/Regex.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/YAMLParser.h" @@ -512,11 +511,11 @@ public: template <typename FBT, typename T> void enumFallback(T &Val) { - if ( matchEnumFallback() ) { + if (matchEnumFallback()) { // FIXME: Force integral conversion to allow strong typedefs to convert. - FBT Res = (uint64_t)Val; + FBT Res = static_cast<typename FBT::BaseType>(Val); yamlize(*this, Res, true); - Val = (uint64_t)Res; + Val = static_cast<T>(static_cast<typename FBT::BaseType>(Res)); } } @@ -858,6 +857,32 @@ struct ScalarTraits<double> { static bool mustQuote(StringRef) { return false; } }; +// For endian types, we just use the existing ScalarTraits for the underlying +// type. This way endian aware types are supported whenever a ScalarTraits +// is defined for the underlying type. +template <typename value_type, support::endianness endian, size_t alignment> +struct ScalarTraits<support::detail::packed_endian_specific_integral< + value_type, endian, alignment>> { + typedef support::detail::packed_endian_specific_integral<value_type, endian, + alignment> + endian_type; + + static void output(const endian_type &E, void *Ctx, + llvm::raw_ostream &Stream) { + ScalarTraits<value_type>::output(static_cast<value_type>(E), Ctx, Stream); + } + static StringRef input(StringRef Str, void *Ctx, endian_type &E) { + value_type V; + auto R = ScalarTraits<value_type>::input(Str, Ctx, V); + E = static_cast<endian_type>(V); + return R; + } + + static bool mustQuote(StringRef Str) { + return ScalarTraits<value_type>::mustQuote(Str); + } +}; + // Utility for use within MappingTraits<>::mapping() method // to [de]normalize an object for use with YAML conversion. template <typename TNorm, typename TFinal> @@ -894,12 +919,16 @@ private: // to [de]normalize an object for use with YAML conversion. template <typename TNorm, typename TFinal> struct MappingNormalizationHeap { - MappingNormalizationHeap(IO &i_o, TFinal &Obj) + MappingNormalizationHeap(IO &i_o, TFinal &Obj, + llvm::BumpPtrAllocator *allocator) : io(i_o), BufPtr(nullptr), Result(Obj) { if ( io.outputting() ) { BufPtr = new (&Buffer) TNorm(io, Obj); } - else { + else if (allocator) { + BufPtr = allocator->Allocate<TNorm>(); + new (BufPtr) TNorm(io); + } else { BufPtr = new TNorm(io); } } @@ -1166,6 +1195,7 @@ private: bool operator==(const _base &rhs) const { return value == rhs; } \ bool operator<(const _type &rhs) const { return value < rhs.value; } \ _base value; \ + typedef _base BaseType; \ }; /// diff --git a/include/llvm/Support/raw_sha1_ostream.h b/include/llvm/Support/raw_sha1_ostream.h new file mode 100644 index 000000000000..329ef9fd069b --- /dev/null +++ b/include/llvm/Support/raw_sha1_ostream.h @@ -0,0 +1,47 @@ +//==- raw_sha1_ostream.h - raw_ostream that compute SHA1 --*- 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 raw_sha1_ostream class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_RAW_SHA1_OSTREAM_H +#define LLVM_SUPPORT_RAW_SHA1_OSTREAM_H + +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SHA1.h" +#include "llvm/ADT/ArrayRef.h" + +namespace llvm { + +/// A raw_ostream that hash the content using the sha1 algorithm. +class raw_sha1_ostream : public raw_ostream { + SHA1 State; + + /// See raw_ostream::write_impl. + void write_impl(const char *Ptr, size_t Size) override { + State.update(ArrayRef<uint8_t>((const uint8_t *)Ptr, Size)); + } + +public: + /// Return the current SHA1 hash for the content of the stream + StringRef sha1() { + flush(); + return State.result(); + } + + /// Reset the internal state to start over from scratch. + void resetHash() { State.init(); } + + uint64_t current_pos() const override { return 0; } +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/Support/thread.h b/include/llvm/Support/thread.h index 2d130418a57f..9c45418df55c 100644 --- a/include/llvm/Support/thread.h +++ b/include/llvm/Support/thread.h @@ -57,6 +57,7 @@ struct thread { thread(const thread &) = delete; void join() {} + static unsigned hardware_concurrency() { return 1; }; }; } diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index 88385c3fae1e..7706ff527197 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -17,6 +17,8 @@ #include <type_traits> #include <utility> +#include "llvm/Support/Compiler.h" + #ifndef __has_feature #define LLVM_DEFINED_HAS_FEATURE #define __has_feature(x) 0 @@ -54,11 +56,12 @@ struct isPodLike<std::pair<T, U> > { }; /// \brief Metafunction that determines whether the given type is either an -/// integral type or an enumeration type. +/// integral type or an enumeration type, including enum classes. /// /// Note that this accepts potentially more integral types than is_integral -/// because it is based on merely being convertible implicitly to an integral -/// type. +/// because it is based on being implicitly convertible to an integral type. +/// Also note that enum classes aren't implicitly convertible to integral types, +/// the value may therefore need to be explicitly converted before being used. template <typename T> class is_integral_or_enum { typedef typename std::remove_reference<T>::type UnderlyingT; @@ -67,7 +70,8 @@ public: !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; + (std::is_enum<UnderlyingT>::value || + std::is_convertible<UnderlyingT, unsigned long long>::value); }; /// \brief If T is a pointer, just return it. If it is not, return T&. |