aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Support
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Support')
-rw-r--r--include/llvm/Support/AArch64TargetParser.def72
-rw-r--r--include/llvm/Support/AArch64TargetParser.h3
-rw-r--r--include/llvm/Support/ARMTargetParser.def2
-rw-r--r--include/llvm/Support/ARMTargetParser.h20
-rw-r--r--include/llvm/Support/AlignOf.h134
-rw-r--r--include/llvm/Support/Alignment.h403
-rw-r--r--include/llvm/Support/Allocator.h22
-rw-r--r--include/llvm/Support/Automaton.h253
-rw-r--r--include/llvm/Support/BinaryStreamArray.h2
-rw-r--r--include/llvm/Support/BinaryStreamReader.h2
-rw-r--r--include/llvm/Support/CRC.h45
-rw-r--r--include/llvm/Support/CommandLine.h3
-rw-r--r--include/llvm/Support/Compiler.h81
-rw-r--r--include/llvm/Support/DataExtractor.h196
-rw-r--r--include/llvm/Support/Endian.h10
-rw-r--r--include/llvm/Support/Error.h42
-rw-r--r--include/llvm/Support/FileCheck.h604
-rw-r--r--include/llvm/Support/FileCollector.h79
-rw-r--r--include/llvm/Support/FileSystem.h30
-rw-r--r--include/llvm/Support/FileUtilities.h38
-rw-r--r--include/llvm/Support/Format.h5
-rw-r--r--include/llvm/Support/GenericDomTree.h6
-rw-r--r--include/llvm/Support/GenericDomTreeConstruction.h8
-rw-r--r--include/llvm/Support/GlobPattern.h2
-rw-r--r--include/llvm/Support/Host.h28
-rw-r--r--include/llvm/Support/JamCRC.h48
-rw-r--r--include/llvm/Support/MachineValueType.h419
-rw-r--r--include/llvm/Support/MathExtras.h187
-rw-r--r--include/llvm/Support/Mutex.h105
-rw-r--r--include/llvm/Support/MutexGuard.h40
-rw-r--r--include/llvm/Support/OnDiskHashTable.h3
-rw-r--r--include/llvm/Support/Parallel.h27
-rw-r--r--include/llvm/Support/RWMutex.h321
-rw-r--r--include/llvm/Support/Regex.h18
-rw-r--r--include/llvm/Support/Registry.h2
-rw-r--r--include/llvm/Support/SHA1.h2
-rw-r--r--include/llvm/Support/ScalableSize.h43
-rw-r--r--include/llvm/Support/Signals.h11
-rw-r--r--include/llvm/Support/SwapByteOrder.h38
-rw-r--r--include/llvm/Support/TargetOpcodes.def26
-rw-r--r--include/llvm/Support/TargetRegistry.h4
-rw-r--r--include/llvm/Support/TimeProfiler.h2
-rw-r--r--include/llvm/Support/TrailingObjects.h18
-rw-r--r--include/llvm/Support/TypeSize.h201
-rw-r--r--include/llvm/Support/UnicodeCharRanges.h3
-rw-r--r--include/llvm/Support/UniqueLock.h68
-rw-r--r--include/llvm/Support/VirtualFileSystem.h16
-rw-r--r--include/llvm/Support/Win64EH.h4
-rw-r--r--include/llvm/Support/X86TargetParser.def4
-rw-r--r--include/llvm/Support/YAMLTraits.h11
-rw-r--r--include/llvm/Support/circular_raw_ostream.h4
-rw-r--r--include/llvm/Support/raw_ostream.h27
-rw-r--r--include/llvm/Support/type_traits.h18
53 files changed, 2110 insertions, 1650 deletions
diff --git a/include/llvm/Support/AArch64TargetParser.def b/include/llvm/Support/AArch64TargetParser.def
index e152f383b3ec..15737265dfc3 100644
--- a/include/llvm/Support/AArch64TargetParser.def
+++ b/include/llvm/Support/AArch64TargetParser.def
@@ -50,35 +50,36 @@ AARCH64_ARCH("armv8.5-a", ARMV8_5A, "8.5-A", "v8.5a",
#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("lse", AArch64::AEK_LSE, "+lse", "-lse")
-AARCH64_ARCH_EXT_NAME("rdm", AArch64::AEK_RDM, "+rdm", "-rdm")
-AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto")
-AARCH64_ARCH_EXT_NAME("sm4", AArch64::AEK_SM4, "+sm4", "-sm4")
-AARCH64_ARCH_EXT_NAME("sha3", AArch64::AEK_SHA3, "+sha3", "-sha3")
-AARCH64_ARCH_EXT_NAME("sha2", AArch64::AEK_SHA2, "+sha2", "-sha2")
-AARCH64_ARCH_EXT_NAME("aes", AArch64::AEK_AES, "+aes", "-aes")
-AARCH64_ARCH_EXT_NAME("dotprod", AArch64::AEK_DOTPROD, "+dotprod","-dotprod")
-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("fp16fml", AArch64::AEK_FP16FML, "+fp16fml", "-fp16fml")
-AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe")
-AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras")
-AARCH64_ARCH_EXT_NAME("sve", AArch64::AEK_SVE, "+sve", "-sve")
-AARCH64_ARCH_EXT_NAME("sve2", AArch64::AEK_SVE2, "+sve2", "-sve2")
-AARCH64_ARCH_EXT_NAME("sve2-aes", AArch64::AEK_SVE2AES, "+sve2-aes", "-sve2-aes")
-AARCH64_ARCH_EXT_NAME("sve2-sm4", AArch64::AEK_SVE2SM4, "+sve2-sm4", "-sve2-sm4")
-AARCH64_ARCH_EXT_NAME("sve2-sha3", AArch64::AEK_SVE2SHA3, "+sve2-sha3", "-sve2-sha3")
-AARCH64_ARCH_EXT_NAME("bitperm", AArch64::AEK_BITPERM, "+bitperm", "-bitperm")
-AARCH64_ARCH_EXT_NAME("rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc")
-AARCH64_ARCH_EXT_NAME("rng", AArch64::AEK_RAND, "+rand", "-rand")
-AARCH64_ARCH_EXT_NAME("memtag", AArch64::AEK_MTE, "+mte", "-mte")
-AARCH64_ARCH_EXT_NAME("ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs")
-AARCH64_ARCH_EXT_NAME("sb", AArch64::AEK_SB, "+sb", "-sb")
-AARCH64_ARCH_EXT_NAME("predres", AArch64::AEK_PREDRES, "+predres", "-predres")
+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("lse", AArch64::AEK_LSE, "+lse", "-lse")
+AARCH64_ARCH_EXT_NAME("rdm", AArch64::AEK_RDM, "+rdm", "-rdm")
+AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto")
+AARCH64_ARCH_EXT_NAME("sm4", AArch64::AEK_SM4, "+sm4", "-sm4")
+AARCH64_ARCH_EXT_NAME("sha3", AArch64::AEK_SHA3, "+sha3", "-sha3")
+AARCH64_ARCH_EXT_NAME("sha2", AArch64::AEK_SHA2, "+sha2", "-sha2")
+AARCH64_ARCH_EXT_NAME("aes", AArch64::AEK_AES, "+aes", "-aes")
+AARCH64_ARCH_EXT_NAME("dotprod", AArch64::AEK_DOTPROD, "+dotprod","-dotprod")
+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("fp16fml", AArch64::AEK_FP16FML, "+fp16fml", "-fp16fml")
+AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe")
+AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras")
+AARCH64_ARCH_EXT_NAME("sve", AArch64::AEK_SVE, "+sve", "-sve")
+AARCH64_ARCH_EXT_NAME("sve2", AArch64::AEK_SVE2, "+sve2", "-sve2")
+AARCH64_ARCH_EXT_NAME("sve2-aes", AArch64::AEK_SVE2AES, "+sve2-aes", "-sve2-aes")
+AARCH64_ARCH_EXT_NAME("sve2-sm4", AArch64::AEK_SVE2SM4, "+sve2-sm4", "-sve2-sm4")
+AARCH64_ARCH_EXT_NAME("sve2-sha3", AArch64::AEK_SVE2SHA3, "+sve2-sha3", "-sve2-sha3")
+AARCH64_ARCH_EXT_NAME("sve2-bitperm", AArch64::AEK_SVE2BITPERM, "+sve2-bitperm", "-sve2-bitperm")
+AARCH64_ARCH_EXT_NAME("rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc")
+AARCH64_ARCH_EXT_NAME("rng", AArch64::AEK_RAND, "+rand", "-rand")
+AARCH64_ARCH_EXT_NAME("memtag", AArch64::AEK_MTE, "+mte", "-mte")
+AARCH64_ARCH_EXT_NAME("ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs")
+AARCH64_ARCH_EXT_NAME("sb", AArch64::AEK_SB, "+sb", "-sb")
+AARCH64_ARCH_EXT_NAME("predres", AArch64::AEK_PREDRES, "+predres", "-predres")
+AARCH64_ARCH_EXT_NAME("tme", AArch64::AEK_TME, "+tme", "-tme")
#undef AARCH64_ARCH_EXT_NAME
#ifndef AARCH64_CPU_NAME
@@ -92,6 +93,12 @@ AARCH64_CPU_NAME("cortex-a55", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC))
AARCH64_CPU_NAME("cortex-a57", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_CRC))
+AARCH64_CPU_NAME("cortex-a65", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_RAS |
+ AArch64::AEK_RCPC | AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("cortex-a65ae", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_RAS |
+ AArch64::AEK_RCPC | AArch64::AEK_SSBS))
AARCH64_CPU_NAME("cortex-a72", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_CRC))
AARCH64_CPU_NAME("cortex-a73", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
@@ -104,6 +111,13 @@ AARCH64_CPU_NAME("cortex-a76", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
AARCH64_CPU_NAME("cortex-a76ae", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("neoverse-e1", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 | AArch64::AEK_RAS |
+ AArch64::AEK_RCPC | AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("neoverse-n1", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16 |
+ AArch64::AEK_PROFILE | AArch64::AEK_RAS | AArch64::AEK_RCPC |
+ AArch64::AEK_SSBS))
AARCH64_CPU_NAME("cyclone", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_NONE))
AARCH64_CPU_NAME("exynos-m1", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
diff --git a/include/llvm/Support/AArch64TargetParser.h b/include/llvm/Support/AArch64TargetParser.h
index 965d38535e74..94f341c83260 100644
--- a/include/llvm/Support/AArch64TargetParser.h
+++ b/include/llvm/Support/AArch64TargetParser.h
@@ -53,7 +53,8 @@ enum ArchExtKind : unsigned {
AEK_SVE2AES = 1 << 24,
AEK_SVE2SM4 = 1 << 25,
AEK_SVE2SHA3 = 1 << 26,
- AEK_BITPERM = 1 << 27,
+ AEK_SVE2BITPERM = 1 << 27,
+ AEK_TME = 1 << 28,
};
enum class ArchKind {
diff --git a/include/llvm/Support/ARMTargetParser.def b/include/llvm/Support/ARMTargetParser.def
index f466b3252748..3e77e20762c1 100644
--- a/include/llvm/Support/ARMTargetParser.def
+++ b/include/llvm/Support/ARMTargetParser.def
@@ -274,6 +274,8 @@ ARM_CPU_NAME("cortex-a76", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(ARM::AEK_FP16 | ARM::AEK_DOTPROD))
ARM_CPU_NAME("cortex-a76ae", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(ARM::AEK_FP16 | ARM::AEK_DOTPROD))
+ARM_CPU_NAME("neoverse-n1", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
ARM_CPU_NAME("cyclone", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("exynos-m1", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("exynos-m2", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
diff --git a/include/llvm/Support/ARMTargetParser.h b/include/llvm/Support/ARMTargetParser.h
index 4b9070dea596..02d4c975129f 100644
--- a/include/llvm/Support/ARMTargetParser.h
+++ b/include/llvm/Support/ARMTargetParser.h
@@ -39,19 +39,13 @@ enum ArchExtKind : unsigned {
AEK_DSP = 1 << 10,
AEK_FP16 = 1 << 11,
AEK_RAS = 1 << 12,
- AEK_SVE = 1 << 13,
- AEK_DOTPROD = 1 << 14,
- AEK_SHA2 = 1 << 15,
- AEK_AES = 1 << 16,
- AEK_FP16FML = 1 << 17,
- AEK_SB = 1 << 18,
- AEK_SVE2 = 1 << 19,
- AEK_SVE2AES = 1 << 20,
- AEK_SVE2SM4 = 1 << 21,
- AEK_SVE2SHA3 = 1 << 22,
- AEK_BITPERM = 1 << 23,
- AEK_FP_DP = 1 << 24,
- AEK_LOB = 1 << 25,
+ AEK_DOTPROD = 1 << 13,
+ AEK_SHA2 = 1 << 14,
+ AEK_AES = 1 << 15,
+ AEK_FP16FML = 1 << 16,
+ AEK_SB = 1 << 17,
+ AEK_FP_DP = 1 << 18,
+ AEK_LOB = 1 << 19,
// Unsupported extensions.
AEK_OS = 0x8000000,
AEK_IWMMXT = 0x10000000,
diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h
index d12401f0eb49..eb42542b777f 100644
--- a/include/llvm/Support/AlignOf.h
+++ b/include/llvm/Support/AlignOf.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the AlignedCharArray and AlignedCharArrayUnion classes.
+// This file defines the AlignedCharArrayUnion class.
//
//===----------------------------------------------------------------------===//
@@ -18,128 +18,38 @@
namespace llvm {
-/// \struct AlignedCharArray
-/// Helper for building an aligned character array type.
-///
-/// This template is used to explicitly build up a collection of aligned
-/// character array types. We have to build these up using a macro and explicit
-/// specialization to cope with MSVC (at least till 2015) where only an
-/// integer literal can be used to specify an alignment constraint. Once built
-/// up here, we can then begin to indirect between these using normal C++
-/// template parameters.
-
-// MSVC requires special handling here.
-#ifndef _MSC_VER
-
-template<std::size_t Alignment, std::size_t Size>
-struct AlignedCharArray {
- alignas(Alignment) char buffer[Size];
-};
-
-#else // _MSC_VER
-
-/// Create a type with an aligned char buffer.
-template<std::size_t Alignment, std::size_t Size>
-struct AlignedCharArray;
-
-// We provide special variations of this template for the most common
-// alignments because __declspec(align(...)) doesn't actually work when it is
-// a member of a by-value function argument in MSVC, even if the alignment
-// request is something reasonably like 8-byte or 16-byte. Note that we can't
-// even include the declspec with the union that forces the alignment because
-// MSVC warns on the existence of the declspec despite the union member forcing
-// proper alignment.
-
-template<std::size_t Size>
-struct AlignedCharArray<1, Size> {
- union {
- char aligned;
- char buffer[Size];
- };
-};
-
-template<std::size_t Size>
-struct AlignedCharArray<2, Size> {
- union {
- short aligned;
- char buffer[Size];
- };
-};
-
-template<std::size_t Size>
-struct AlignedCharArray<4, Size> {
- union {
- int aligned;
- char buffer[Size];
- };
-};
+namespace detail {
-template<std::size_t Size>
-struct AlignedCharArray<8, Size> {
- union {
- double aligned;
- char buffer[Size];
- };
+template <typename T, typename... Ts> class AlignerImpl {
+ T t;
+ AlignerImpl<Ts...> rest;
+ AlignerImpl() = delete;
};
-
-// The rest of these are provided with a __declspec(align(...)) and we simply
-// can't pass them by-value as function arguments on MSVC.
-
-#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
- template<std::size_t Size> \
- struct AlignedCharArray<x, Size> { \
- __declspec(align(x)) char buffer[Size]; \
- };
-
-LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16)
-LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32)
-LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64)
-LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128)
-
-#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
-
-#endif // _MSC_VER
-
-namespace detail {
-template <typename T1,
- typename T2 = char, typename T3 = char, typename T4 = char,
- typename T5 = char, typename T6 = char, typename T7 = char,
- typename T8 = char, typename T9 = char, typename T10 = char>
-class AlignerImpl {
- T1 t1; T2 t2; T3 t3; T4 t4; T5 t5; T6 t6; T7 t7; T8 t8; T9 t9; T10 t10;
-
+template <typename T> class AlignerImpl<T> {
+ T t;
AlignerImpl() = delete;
};
-template <typename T1,
- typename T2 = char, typename T3 = char, typename T4 = char,
- typename T5 = char, typename T6 = char, typename T7 = char,
- typename T8 = char, typename T9 = char, typename T10 = char>
-union SizerImpl {
- char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)],
- arr5[sizeof(T5)], arr6[sizeof(T6)], arr7[sizeof(T7)], arr8[sizeof(T8)],
- arr9[sizeof(T9)], arr10[sizeof(T10)];
+template <typename T, typename... Ts> union SizerImpl {
+ char arr[sizeof(T)];
+ SizerImpl<Ts...> rest;
};
+
+template <typename T> union SizerImpl<T> { char arr[sizeof(T)]; };
} // end namespace detail
-/// This union template exposes a suitably aligned and sized character
-/// array member which can hold elements of any of up to ten types.
+/// A suitably aligned and sized character array member which can hold elements
+/// of any type.
///
-/// These types may be arrays, structs, or any other types. The goal is to
-/// expose a char array buffer member which can be used as suitable storage for
-/// a placement new of any of these types. Support for more than ten types can
-/// be added at the cost of more boilerplate.
-template <typename T1,
- typename T2 = char, typename T3 = char, typename T4 = char,
- typename T5 = char, typename T6 = char, typename T7 = char,
- typename T8 = char, typename T9 = char, typename T10 = char>
-struct AlignedCharArrayUnion : llvm::AlignedCharArray<
- alignof(llvm::detail::AlignerImpl<T1, T2, T3, T4, T5,
- T6, T7, T8, T9, T10>),
- sizeof(::llvm::detail::SizerImpl<T1, T2, T3, T4, T5,
- T6, T7, T8, T9, T10>)> {
+/// These types may be arrays, structs, or any other types. This exposes a
+/// `buffer` member which can be used as suitable storage for a placement new of
+/// any of these types.
+template <typename T, typename... Ts> struct AlignedCharArrayUnion {
+ alignas(::llvm::detail::AlignerImpl<T, Ts...>) char buffer[sizeof(
+ llvm::detail::SizerImpl<T, Ts...>)];
};
+
} // end namespace llvm
#endif // LLVM_SUPPORT_ALIGNOF_H
diff --git a/include/llvm/Support/Alignment.h b/include/llvm/Support/Alignment.h
new file mode 100644
index 000000000000..72fad87dd0d4
--- /dev/null
+++ b/include/llvm/Support/Alignment.h
@@ -0,0 +1,403 @@
+//===-- llvm/Support/Alignment.h - Useful alignment functions ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains types to represent alignments.
+// They are instrumented to guarantee some invariants are preserved and prevent
+// invalid manipulations.
+//
+// - Align represents an alignment in bytes, it is always set and always a valid
+// power of two, its minimum value is 1 which means no alignment requirements.
+//
+// - MaybeAlign is an optional type, it may be undefined or set. When it's set
+// you can get the underlying Align type by using the getValue() method.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ALIGNMENT_H_
+#define LLVM_SUPPORT_ALIGNMENT_H_
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include <cassert>
+#include <limits>
+
+namespace llvm {
+
+#define ALIGN_CHECK_ISPOSITIVE(decl) \
+ assert(decl > 0 && (#decl " should be defined"))
+#define ALIGN_CHECK_ISSET(decl) \
+ assert(decl.hasValue() && (#decl " should be defined"))
+
+/// This struct is a compact representation of a valid (non-zero power of two)
+/// alignment.
+/// It is suitable for use as static global constants.
+struct Align {
+private:
+ uint8_t ShiftValue = 0; /// The log2 of the required alignment.
+ /// ShiftValue is less than 64 by construction.
+
+ friend struct MaybeAlign;
+ friend unsigned Log2(Align);
+ friend bool operator==(Align Lhs, Align Rhs);
+ friend bool operator!=(Align Lhs, Align Rhs);
+ friend bool operator<=(Align Lhs, Align Rhs);
+ friend bool operator>=(Align Lhs, Align Rhs);
+ friend bool operator<(Align Lhs, Align Rhs);
+ friend bool operator>(Align Lhs, Align Rhs);
+ friend unsigned encode(struct MaybeAlign A);
+ friend struct MaybeAlign decodeMaybeAlign(unsigned Value);
+
+ /// A trivial type to allow construction of constexpr Align.
+ /// This is currently needed to workaround a bug in GCC 5.3 which prevents
+ /// definition of constexpr assign operators.
+ /// https://stackoverflow.com/questions/46756288/explicitly-defaulted-function-cannot-be-declared-as-constexpr-because-the-implic
+ /// FIXME: Remove this, make all assign operators constexpr and introduce user
+ /// defined literals when we don't have to support GCC 5.3 anymore.
+ /// https://llvm.org/docs/GettingStarted.html#getting-a-modern-host-c-toolchain
+ struct LogValue {
+ uint8_t Log;
+ };
+
+public:
+ /// Default is byte-aligned.
+ constexpr Align() = default;
+ /// Do not perform checks in case of copy/move construct/assign, because the
+ /// checks have been performed when building `Other`.
+ constexpr Align(const Align &Other) = default;
+ constexpr Align(Align &&Other) = default;
+ Align &operator=(const Align &Other) = default;
+ Align &operator=(Align &&Other) = default;
+
+ explicit Align(uint64_t Value) {
+ assert(Value > 0 && "Value must not be 0");
+ assert(llvm::isPowerOf2_64(Value) && "Alignment is not a power of 2");
+ ShiftValue = Log2_64(Value);
+ assert(ShiftValue < 64 && "Broken invariant");
+ }
+
+ /// This is a hole in the type system and should not be abused.
+ /// Needed to interact with C for instance.
+ uint64_t value() const { return uint64_t(1) << ShiftValue; }
+
+ /// Returns a default constructed Align which corresponds to no alignment.
+ /// This is useful to test for unalignment as it conveys clear semantic.
+ /// `if (A != Align::None())`
+ /// would be better than
+ /// `if (A > Align(1))`
+ constexpr static const Align None() { return Align(); }
+
+ /// Allow constructions of constexpr Align.
+ template <size_t kValue> constexpr static LogValue Constant() {
+ return LogValue{static_cast<uint8_t>(CTLog2<kValue>())};
+ }
+
+ /// Allow constructions of constexpr Align from types.
+ /// Compile time equivalent to Align(alignof(T)).
+ template <typename T> constexpr static LogValue Of() {
+ return Constant<std::alignment_of<T>::value>();
+ }
+
+ /// Constexpr constructor from LogValue type.
+ constexpr Align(LogValue CA) : ShiftValue(CA.Log) {}
+};
+
+/// Treats the value 0 as a 1, so Align is always at least 1.
+inline Align assumeAligned(uint64_t Value) {
+ return Value ? Align(Value) : Align();
+}
+
+/// This struct is a compact representation of a valid (power of two) or
+/// undefined (0) alignment.
+struct MaybeAlign : public llvm::Optional<Align> {
+private:
+ using UP = llvm::Optional<Align>;
+
+public:
+ /// Default is undefined.
+ MaybeAlign() = default;
+ /// Do not perform checks in case of copy/move construct/assign, because the
+ /// checks have been performed when building `Other`.
+ MaybeAlign(const MaybeAlign &Other) = default;
+ MaybeAlign &operator=(const MaybeAlign &Other) = default;
+ MaybeAlign(MaybeAlign &&Other) = default;
+ MaybeAlign &operator=(MaybeAlign &&Other) = default;
+
+ /// Use llvm::Optional<Align> constructor.
+ using UP::UP;
+
+ explicit MaybeAlign(uint64_t Value) {
+ assert((Value == 0 || llvm::isPowerOf2_64(Value)) &&
+ "Alignment is neither 0 nor a power of 2");
+ if (Value)
+ emplace(Value);
+ }
+
+ /// For convenience, returns a valid alignment or 1 if undefined.
+ Align valueOrOne() const { return hasValue() ? getValue() : Align(); }
+};
+
+/// Checks that SizeInBytes is a multiple of the alignment.
+inline bool isAligned(Align Lhs, uint64_t SizeInBytes) {
+ return SizeInBytes % Lhs.value() == 0;
+}
+
+/// Checks that SizeInBytes is a multiple of the alignment.
+/// Returns false if the alignment is undefined.
+inline bool isAligned(MaybeAlign Lhs, uint64_t SizeInBytes) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return SizeInBytes % (*Lhs).value() == 0;
+}
+
+/// Checks that Addr is a multiple of the alignment.
+inline bool isAddrAligned(Align Lhs, const void *Addr) {
+ return isAligned(Lhs, reinterpret_cast<uintptr_t>(Addr));
+}
+
+/// Returns a multiple of A needed to store `Size` bytes.
+inline uint64_t alignTo(uint64_t Size, Align A) {
+ const uint64_t value = A.value();
+ // The following line is equivalent to `(Size + value - 1) / value * value`.
+
+ // The division followed by a multiplication can be thought of as a right
+ // shift followed by a left shift which zeros out the extra bits produced in
+ // the bump; `~(value - 1)` is a mask where all those bits being zeroed out
+ // are just zero.
+
+ // Most compilers can generate this code but the pattern may be missed when
+ // multiple functions gets inlined.
+ return (Size + value - 1) & ~(value - 1);
+}
+
+/// Returns a multiple of A needed to store `Size` bytes.
+/// Returns `Size` if current alignment is undefined.
+inline uint64_t alignTo(uint64_t Size, MaybeAlign A) {
+ return A ? alignTo(Size, A.getValue()) : Size;
+}
+
+/// Aligns `Addr` to `Alignment` bytes, rounding up.
+inline uintptr_t alignAddr(const void *Addr, Align Alignment) {
+ uintptr_t ArithAddr = reinterpret_cast<uintptr_t>(Addr);
+ assert(static_cast<uintptr_t>(ArithAddr + Alignment.value() - 1) >=
+ ArithAddr && "Overflow");
+ return alignTo(ArithAddr, Alignment);
+}
+
+/// 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.
+inline uint64_t offsetToAlignment(uint64_t Value, Align Alignment) {
+ return alignTo(Value, Alignment) - Value;
+}
+
+/// Returns the necessary adjustment for aligning `Addr` to `Alignment`
+/// bytes, rounding up.
+inline uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment) {
+ return offsetToAlignment(reinterpret_cast<uintptr_t>(Addr), Alignment);
+}
+
+/// Returns the log2 of the alignment.
+inline unsigned Log2(Align A) { return A.ShiftValue; }
+
+/// Returns the log2 of the alignment.
+/// \pre A must be defined.
+inline unsigned Log2(MaybeAlign A) {
+ ALIGN_CHECK_ISSET(A);
+ return Log2(A.getValue());
+}
+
+/// Returns the alignment that satisfies both alignments.
+/// Same semantic as MinAlign.
+inline Align commonAlignment(Align A, Align B) { return std::min(A, B); }
+
+/// Returns the alignment that satisfies both alignments.
+/// Same semantic as MinAlign.
+inline Align commonAlignment(Align A, uint64_t Offset) {
+ return Align(MinAlign(A.value(), Offset));
+}
+
+/// Returns the alignment that satisfies both alignments.
+/// Same semantic as MinAlign.
+inline MaybeAlign commonAlignment(MaybeAlign A, MaybeAlign B) {
+ return A && B ? commonAlignment(*A, *B) : A ? A : B;
+}
+
+/// Returns the alignment that satisfies both alignments.
+/// Same semantic as MinAlign.
+inline MaybeAlign commonAlignment(MaybeAlign A, uint64_t Offset) {
+ return MaybeAlign(MinAlign((*A).value(), Offset));
+}
+
+/// Returns a representation of the alignment that encodes undefined as 0.
+inline unsigned encode(MaybeAlign A) { return A ? A->ShiftValue + 1 : 0; }
+
+/// Dual operation of the encode function above.
+inline MaybeAlign decodeMaybeAlign(unsigned Value) {
+ if (Value == 0)
+ return MaybeAlign();
+ Align Out;
+ Out.ShiftValue = Value - 1;
+ return Out;
+}
+
+/// Returns a representation of the alignment, the encoded value is positive by
+/// definition.
+inline unsigned encode(Align A) { return encode(MaybeAlign(A)); }
+
+/// Comparisons between Align and scalars. Rhs must be positive.
+inline bool operator==(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() == Rhs;
+}
+inline bool operator!=(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() != Rhs;
+}
+inline bool operator<=(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() <= Rhs;
+}
+inline bool operator>=(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() >= Rhs;
+}
+inline bool operator<(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() < Rhs;
+}
+inline bool operator>(Align Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return Lhs.value() > Rhs;
+}
+
+/// Comparisons between MaybeAlign and scalars.
+inline bool operator==(MaybeAlign Lhs, uint64_t Rhs) {
+ return Lhs ? (*Lhs).value() == Rhs : Rhs == 0;
+}
+inline bool operator!=(MaybeAlign Lhs, uint64_t Rhs) {
+ return Lhs ? (*Lhs).value() != Rhs : Rhs != 0;
+}
+inline bool operator<=(MaybeAlign Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return (*Lhs).value() <= Rhs;
+}
+inline bool operator>=(MaybeAlign Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return (*Lhs).value() >= Rhs;
+}
+inline bool operator<(MaybeAlign Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return (*Lhs).value() < Rhs;
+}
+inline bool operator>(MaybeAlign Lhs, uint64_t Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ ALIGN_CHECK_ISPOSITIVE(Rhs);
+ return (*Lhs).value() > Rhs;
+}
+
+/// Comparisons operators between Align.
+inline bool operator==(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue == Rhs.ShiftValue;
+}
+inline bool operator!=(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue != Rhs.ShiftValue;
+}
+inline bool operator<=(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue <= Rhs.ShiftValue;
+}
+inline bool operator>=(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue >= Rhs.ShiftValue;
+}
+inline bool operator<(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue < Rhs.ShiftValue;
+}
+inline bool operator>(Align Lhs, Align Rhs) {
+ return Lhs.ShiftValue > Rhs.ShiftValue;
+}
+
+/// Comparisons operators between Align and MaybeAlign.
+inline bool operator==(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() == (*Rhs).value();
+}
+inline bool operator!=(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() != (*Rhs).value();
+}
+inline bool operator<=(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() <= (*Rhs).value();
+}
+inline bool operator>=(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() >= (*Rhs).value();
+}
+inline bool operator<(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() < (*Rhs).value();
+}
+inline bool operator>(Align Lhs, MaybeAlign Rhs) {
+ ALIGN_CHECK_ISSET(Rhs);
+ return Lhs.value() > (*Rhs).value();
+}
+
+/// Comparisons operators between MaybeAlign and Align.
+inline bool operator==(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() == Rhs.value();
+}
+inline bool operator!=(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() != Rhs.value();
+}
+inline bool operator<=(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() <= Rhs.value();
+}
+inline bool operator>=(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() >= Rhs.value();
+}
+inline bool operator<(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() < Rhs.value();
+}
+inline bool operator>(MaybeAlign Lhs, Align Rhs) {
+ ALIGN_CHECK_ISSET(Lhs);
+ return Lhs && (*Lhs).value() > Rhs.value();
+}
+
+inline Align operator/(Align Lhs, uint64_t Divisor) {
+ assert(llvm::isPowerOf2_64(Divisor) &&
+ "Divisor must be positive and a power of 2");
+ assert(Lhs != 1 && "Can't halve byte alignment");
+ return Align(Lhs.value() / Divisor);
+}
+
+inline MaybeAlign operator/(MaybeAlign Lhs, uint64_t Divisor) {
+ assert(llvm::isPowerOf2_64(Divisor) &&
+ "Divisor must be positive and a power of 2");
+ return Lhs ? Lhs.getValue() / Divisor : MaybeAlign();
+}
+
+inline Align max(MaybeAlign Lhs, Align Rhs) {
+ return Lhs && *Lhs > Rhs ? *Lhs : Rhs;
+}
+
+inline Align max(Align Lhs, MaybeAlign Rhs) {
+ return Rhs && *Rhs > Lhs ? *Rhs : Lhs;
+}
+
+#undef ALIGN_CHECK_ISPOSITIVE
+#undef ALIGN_CHECK_ISSET
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_ALIGNMENT_H_
diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h
index 09e967b98abc..106b90c35bf5 100644
--- a/include/llvm/Support/Allocator.h
+++ b/include/llvm/Support/Allocator.h
@@ -22,6 +22,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -211,13 +212,11 @@ public:
/// Allocate space at the specified alignment.
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
- Allocate(size_t Size, size_t Alignment) {
- assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead.");
-
+ Allocate(size_t Size, Align Alignment) {
// Keep track of how many bytes we've allocated.
BytesAllocated += Size;
- size_t Adjustment = alignmentAdjustment(CurPtr, Alignment);
+ size_t Adjustment = offsetToAlignedAddr(CurPtr, Alignment);
assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow");
size_t SizeToAllocate = Size;
@@ -240,7 +239,7 @@ public:
}
// If Size is really big, allocate a separate slab for it.
- size_t PaddedSize = SizeToAllocate + Alignment - 1;
+ size_t PaddedSize = SizeToAllocate + Alignment.value() - 1;
if (PaddedSize > SizeThreshold) {
void *NewSlab = Allocator.Allocate(PaddedSize, 0);
// We own the new slab and don't want anyone reading anyting other than
@@ -268,6 +267,12 @@ public:
return AlignedPtr;
}
+ inline LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+ Allocate(size_t Size, size_t Alignment) {
+ assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead.");
+ return Allocate(Size, Align(Alignment));
+ }
+
// Pull in base class overloads.
using AllocatorBase<BumpPtrAllocatorImpl>::Allocate;
@@ -461,7 +466,7 @@ public:
/// all memory allocated so far.
void DestroyAll() {
auto DestroyElements = [](char *Begin, char *End) {
- assert(Begin == (char *)alignAddr(Begin, alignof(T)));
+ assert(Begin == (char *)alignAddr(Begin, Align::Of<T>()));
for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T))
reinterpret_cast<T *>(Ptr)->~T();
};
@@ -470,7 +475,7 @@ public:
++I) {
size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize(
std::distance(Allocator.Slabs.begin(), I));
- char *Begin = (char *)alignAddr(*I, alignof(T));
+ char *Begin = (char *)alignAddr(*I, Align::Of<T>());
char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr
: (char *)*I + AllocatedSlabSize;
@@ -480,7 +485,8 @@ public:
for (auto &PtrAndSize : Allocator.CustomSizedSlabs) {
void *Ptr = PtrAndSize.first;
size_t Size = PtrAndSize.second;
- DestroyElements((char *)alignAddr(Ptr, alignof(T)), (char *)Ptr + Size);
+ DestroyElements((char *)alignAddr(Ptr, Align::Of<T>()),
+ (char *)Ptr + Size);
}
Allocator.Reset();
diff --git a/include/llvm/Support/Automaton.h b/include/llvm/Support/Automaton.h
new file mode 100644
index 000000000000..7c13a698e492
--- /dev/null
+++ b/include/llvm/Support/Automaton.h
@@ -0,0 +1,253 @@
+//===-- Automaton.h - Support for driving TableGen-produced DFAs ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements class that drive and introspect deterministic finite-
+// state automata (DFAs) as generated by TableGen's -gen-automata backend.
+//
+// For a description of how to define an automaton, see
+// include/llvm/TableGen/Automaton.td.
+//
+// One important detail is that these deterministic automata are created from
+// (potentially) nondeterministic definitions. Therefore a unique sequence of
+// input symbols will produce one path through the DFA but multiple paths
+// through the original NFA. An automaton by default only returns "accepted" or
+// "not accepted", but frequently we want to analyze what NFA path was taken.
+// Finding a path through the NFA states that results in a DFA state can help
+// answer *what* the solution to a problem was, not just that there exists a
+// solution.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_AUTOMATON_H
+#define LLVM_SUPPORT_AUTOMATON_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Allocator.h"
+#include <deque>
+#include <map>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+namespace llvm {
+
+using NfaPath = SmallVector<uint64_t, 4>;
+
+/// Forward define the pair type used by the automata transition info tables.
+///
+/// Experimental results with large tables have shown a significant (multiple
+/// orders of magnitude) parsing speedup by using a custom struct here with a
+/// trivial constructor rather than std::pair<uint64_t, uint64_t>.
+struct NfaStatePair {
+ uint64_t FromDfaState, ToDfaState;
+
+ bool operator<(const NfaStatePair &Other) const {
+ return std::make_tuple(FromDfaState, ToDfaState) <
+ std::make_tuple(Other.FromDfaState, Other.ToDfaState);
+ }
+};
+
+namespace internal {
+/// The internal class that maintains all possible paths through an NFA based
+/// on a path through the DFA.
+class NfaTranscriber {
+private:
+ /// Cached transition table. This is a table of NfaStatePairs that contains
+ /// zero-terminated sequences pointed to by DFA transitions.
+ ArrayRef<NfaStatePair> TransitionInfo;
+
+ /// A simple linked-list of traversed states that can have a shared tail. The
+ /// traversed path is stored in reverse order with the latest state as the
+ /// head.
+ struct PathSegment {
+ uint64_t State;
+ PathSegment *Tail;
+ };
+
+ /// We allocate segment objects frequently. Allocate them upfront and dispose
+ /// at the end of a traversal rather than hammering the system allocator.
+ SpecificBumpPtrAllocator<PathSegment> Allocator;
+
+ /// Heads of each tracked path. These are not ordered.
+ std::deque<PathSegment *> Heads;
+
+ /// The returned paths. This is populated during getPaths.
+ SmallVector<NfaPath, 4> Paths;
+
+ /// Create a new segment and return it.
+ PathSegment *makePathSegment(uint64_t State, PathSegment *Tail) {
+ PathSegment *P = Allocator.Allocate();
+ *P = {State, Tail};
+ return P;
+ }
+
+ /// Pairs defines a sequence of possible NFA transitions for a single DFA
+ /// transition.
+ void transition(ArrayRef<NfaStatePair> Pairs) {
+ // Iterate over all existing heads. We will mutate the Heads deque during
+ // iteration.
+ unsigned NumHeads = Heads.size();
+ for (unsigned I = 0; I < NumHeads; ++I) {
+ PathSegment *Head = Heads[I];
+ // The sequence of pairs is sorted. Select the set of pairs that
+ // transition from the current head state.
+ auto PI = lower_bound(Pairs, NfaStatePair{Head->State, 0ULL});
+ auto PE = upper_bound(Pairs, NfaStatePair{Head->State, INT64_MAX});
+ // For every transition from the current head state, add a new path
+ // segment.
+ for (; PI != PE; ++PI)
+ if (PI->FromDfaState == Head->State)
+ Heads.push_back(makePathSegment(PI->ToDfaState, Head));
+ }
+ // Now we've iterated over all the initial heads and added new ones,
+ // dispose of the original heads.
+ Heads.erase(Heads.begin(), std::next(Heads.begin(), NumHeads));
+ }
+
+public:
+ NfaTranscriber(ArrayRef<NfaStatePair> TransitionInfo)
+ : TransitionInfo(TransitionInfo) {
+ reset();
+ }
+
+ void reset() {
+ Paths.clear();
+ Heads.clear();
+ Allocator.DestroyAll();
+ // The initial NFA state is 0.
+ Heads.push_back(makePathSegment(0ULL, nullptr));
+ }
+
+ void transition(unsigned TransitionInfoIdx) {
+ unsigned EndIdx = TransitionInfoIdx;
+ while (TransitionInfo[EndIdx].ToDfaState != 0)
+ ++EndIdx;
+ ArrayRef<NfaStatePair> Pairs(&TransitionInfo[TransitionInfoIdx],
+ EndIdx - TransitionInfoIdx);
+ transition(Pairs);
+ }
+
+ ArrayRef<NfaPath> getPaths() {
+ Paths.clear();
+ for (auto *Head : Heads) {
+ NfaPath P;
+ while (Head->State != 0) {
+ P.push_back(Head->State);
+ Head = Head->Tail;
+ }
+ std::reverse(P.begin(), P.end());
+ Paths.push_back(std::move(P));
+ }
+ return Paths;
+ }
+};
+} // namespace internal
+
+/// A deterministic finite-state automaton. The automaton is defined in
+/// TableGen; this object drives an automaton defined by tblgen-emitted tables.
+///
+/// An automaton accepts a sequence of input tokens ("actions"). This class is
+/// templated on the type of these actions.
+template <typename ActionT> class Automaton {
+ /// Map from {State, Action} to {NewState, TransitionInfoIdx}.
+ /// TransitionInfoIdx is used by the DfaTranscriber to analyze the transition.
+ /// FIXME: This uses a std::map because ActionT can be a pair type including
+ /// an enum. In particular DenseMapInfo<ActionT> must be defined to use
+ /// DenseMap here.
+ /// This is a shared_ptr to allow very quick copy-construction of Automata; this
+ /// state is immutable after construction so this is safe.
+ using MapTy = std::map<std::pair<uint64_t, ActionT>, std::pair<uint64_t, unsigned>>;
+ std::shared_ptr<MapTy> M;
+ /// An optional transcription object. This uses much more state than simply
+ /// traversing the DFA for acceptance, so is heap allocated.
+ std::shared_ptr<internal::NfaTranscriber> Transcriber;
+ /// The initial DFA state is 1.
+ uint64_t State = 1;
+ /// True if we should transcribe and false if not (even if Transcriber is defined).
+ bool Transcribe;
+
+public:
+ /// Create an automaton.
+ /// \param Transitions The Transitions table as created by TableGen. Note that
+ /// because the action type differs per automaton, the
+ /// table type is templated as ArrayRef<InfoT>.
+ /// \param TranscriptionTable The TransitionInfo table as created by TableGen.
+ ///
+ /// Providing the TranscriptionTable argument as non-empty will enable the
+ /// use of transcription, which analyzes the possible paths in the original
+ /// NFA taken by the DFA. NOTE: This is substantially more work than simply
+ /// driving the DFA, so unless you require the getPaths() method leave this
+ /// empty.
+ template <typename InfoT>
+ Automaton(ArrayRef<InfoT> Transitions,
+ ArrayRef<NfaStatePair> TranscriptionTable = {}) {
+ if (!TranscriptionTable.empty())
+ Transcriber =
+ std::make_shared<internal::NfaTranscriber>(TranscriptionTable);
+ Transcribe = Transcriber != nullptr;
+ M = std::make_shared<MapTy>();
+ for (const auto &I : Transitions)
+ // Greedily read and cache the transition table.
+ M->emplace(std::make_pair(I.FromDfaState, I.Action),
+ std::make_pair(I.ToDfaState, I.InfoIdx));
+ }
+ Automaton(const Automaton &) = default;
+
+ /// Reset the automaton to its initial state.
+ void reset() {
+ State = 1;
+ if (Transcriber)
+ Transcriber->reset();
+ }
+
+ /// Enable or disable transcription. Transcription is only available if
+ /// TranscriptionTable was provided to the constructor.
+ void enableTranscription(bool Enable = true) {
+ assert(Transcriber &&
+ "Transcription is only available if TranscriptionTable was provided "
+ "to the Automaton constructor");
+ Transcribe = Enable;
+ }
+
+ /// Transition the automaton based on input symbol A. Return true if the
+ /// automaton transitioned to a valid state, false if the automaton
+ /// transitioned to an invalid state.
+ ///
+ /// If this function returns false, all methods are undefined until reset() is
+ /// called.
+ bool add(const ActionT &A) {
+ auto I = M->find({State, A});
+ if (I == M->end())
+ return false;
+ if (Transcriber && Transcribe)
+ Transcriber->transition(I->second.second);
+ State = I->second.first;
+ return true;
+ }
+
+ /// Return true if the automaton can be transitioned based on input symbol A.
+ bool canAdd(const ActionT &A) {
+ auto I = M->find({State, A});
+ return I != M->end();
+ }
+
+ /// Obtain a set of possible paths through the input nondeterministic
+ /// automaton that could be obtained from the sequence of input actions
+ /// presented to this deterministic automaton.
+ ArrayRef<NfaPath> getNfaPaths() {
+ assert(Transcriber && Transcribe &&
+ "Can only obtain NFA paths if transcribing!");
+ return Transcriber->getPaths();
+ }
+};
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_AUTOMATON_H
diff --git a/include/llvm/Support/BinaryStreamArray.h b/include/llvm/Support/BinaryStreamArray.h
index 96d09db69ae5..67ba2e4189be 100644
--- a/include/llvm/Support/BinaryStreamArray.h
+++ b/include/llvm/Support/BinaryStreamArray.h
@@ -286,7 +286,7 @@ public:
// an exact multiple of the element size.
consumeError(std::move(EC));
}
- assert(llvm::alignmentAdjustment(Data.data(), alignof(T)) == 0);
+ assert(isAddrAligned(Align::Of<T>(), Data.data()));
return *reinterpret_cast<const T *>(Data.data());
}
diff --git a/include/llvm/Support/BinaryStreamReader.h b/include/llvm/Support/BinaryStreamReader.h
index d8fddde66bfa..9e16ce227ff8 100644
--- a/include/llvm/Support/BinaryStreamReader.h
+++ b/include/llvm/Support/BinaryStreamReader.h
@@ -198,7 +198,7 @@ public:
if (auto EC = readBytes(Bytes, NumElements * sizeof(T)))
return EC;
- assert(alignmentAdjustment(Bytes.data(), alignof(T)) == 0 &&
+ assert(isAddrAligned(Align::Of<T>(), Bytes.data()) &&
"Reading at invalid alignment!");
Array = ArrayRef<T>(reinterpret_cast<const T *>(Bytes.data()), NumElements);
diff --git a/include/llvm/Support/CRC.h b/include/llvm/Support/CRC.h
index 6ea8e3edcea4..210890ae06d4 100644
--- a/include/llvm/Support/CRC.h
+++ b/include/llvm/Support/CRC.h
@@ -6,20 +6,55 @@
//
//===----------------------------------------------------------------------===//
//
-// This file contains basic functions for calculating Cyclic Redundancy Check
-// or CRC.
+// This file contains implementations of CRC functions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_CRC_H
#define LLVM_SUPPORT_CRC_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
namespace llvm {
-/// zlib independent CRC32 calculation.
-uint32_t crc32(uint32_t CRC, StringRef S);
+template <typename T> class ArrayRef;
+
+// Compute the CRC-32 of Data.
+uint32_t crc32(ArrayRef<uint8_t> Data);
+
+// Compute the running CRC-32 of Data, with CRC being the previous value of the
+// checksum.
+uint32_t crc32(uint32_t CRC, ArrayRef<uint8_t> Data);
+
+// Class for computing the JamCRC.
+//
+// We will use the "Rocksoft^tm Model CRC Algorithm" to describe the properties
+// of this CRC:
+// Width : 32
+// Poly : 04C11DB7
+// Init : FFFFFFFF
+// RefIn : True
+// RefOut : True
+// XorOut : 00000000
+// Check : 340BC6D9 (result of CRC for "123456789")
+//
+// In other words, this is the same as CRC-32, except that XorOut is 0 instead
+// of FFFFFFFF.
+//
+// N.B. We permit flexibility of the "Init" value. Some consumers of this need
+// it to be zero.
+class JamCRC {
+public:
+ JamCRC(uint32_t Init = 0xFFFFFFFFU) : CRC(Init) {}
+
+ // Update the CRC calculation with Data.
+ void update(ArrayRef<uint8_t> Data);
+
+ uint32_t getCRC() const { return CRC; }
+
+private:
+ uint32_t CRC;
+};
+
} // end namespace llvm
#endif
diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h
index 3cc2c3c0121b..63784463e171 100644
--- a/include/llvm/Support/CommandLine.h
+++ b/include/llvm/Support/CommandLine.h
@@ -2000,6 +2000,9 @@ void ResetAllOptionOccurrences();
/// where no options are supported.
void ResetCommandLineParser();
+/// Parses `Arg` into the option handler `Handler`.
+bool ProvidePositionalOption(Option *Handler, StringRef Arg, int i);
+
} // end namespace cl
} // end namespace llvm
diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h
index 3f4f465f3960..cb7e57d4cd21 100644
--- a/include/llvm/Support/Compiler.h
+++ b/include/llvm/Support/Compiler.h
@@ -7,7 +7,8 @@
//===----------------------------------------------------------------------===//
//
// This file defines several macros, based on the current compiler. This allows
-// use of compiler-specific features in a way that remains portable.
+// use of compiler-specific features in a way that remains portable. This header
+// can be included from either C or C++.
//
//===----------------------------------------------------------------------===//
@@ -16,7 +17,9 @@
#include "llvm/Config/llvm-config.h"
+#ifdef __cplusplus
#include <new>
+#endif
#include <stddef.h>
#if defined(_MSC_VER)
@@ -35,14 +38,20 @@
# define __has_attribute(x) 0
#endif
-#ifndef __has_cpp_attribute
-# define __has_cpp_attribute(x) 0
-#endif
-
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif
+// Only use __has_cpp_attribute in C++ mode. GCC defines __has_cpp_attribute in
+// C mode, but the :: in __has_cpp_attribute(scoped::attribute) is invalid.
+#ifndef LLVM_HAS_CPP_ATTRIBUTE
+#if defined(__cplusplus) && defined(__has_cpp_attribute)
+# define LLVM_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+# define LLVM_HAS_CPP_ATTRIBUTE(x) 0
+#endif
+#endif
+
/// \macro LLVM_GNUC_PREREQ
/// Extend the default __GNUC_PREREQ even if glibc's features.h isn't
/// available.
@@ -62,13 +71,21 @@
/// \macro LLVM_MSC_PREREQ
/// Is the compiler MSVC of at least the specified version?
/// The common \param version values to check for are:
-/// * 1900: Microsoft Visual Studio 2015 / 14.0
+/// * 1910: VS2017, version 15.1 & 15.2
+/// * 1911: VS2017, version 15.3 & 15.4
+/// * 1912: VS2017, version 15.5
+/// * 1913: VS2017, version 15.6
+/// * 1914: VS2017, version 15.7
+/// * 1915: VS2017, version 15.8
+/// * 1916: VS2017, version 15.9
+/// * 1920: VS2019, version 16.0
+/// * 1921: VS2019, version 16.1
#ifdef _MSC_VER
#define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version))
-// We require at least MSVC 2015.
-#if !LLVM_MSC_PREREQ(1900)
-#error LLVM requires at least MSVC 2015.
+// We require at least MSVC 2017.
+#if !LLVM_MSC_PREREQ(1910)
+#error LLVM requires at least MSVC 2017.
#endif
#else
@@ -120,14 +137,18 @@
#endif
/// LLVM_NODISCARD - Warn if a type or return value is discarded.
-#if __cplusplus > 201402L && __has_cpp_attribute(nodiscard)
+
+// Use the 'nodiscard' attribute in C++17 or newer mode.
+#if __cplusplus > 201402L && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
#define LLVM_NODISCARD [[nodiscard]]
-#elif !__cplusplus
-// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious
-// error when __has_cpp_attribute is given a scoped attribute in C mode.
-#define LLVM_NODISCARD
-#elif __has_cpp_attribute(clang::warn_unused_result)
+#elif LLVM_HAS_CPP_ATTRIBUTE(clang::warn_unused_result)
#define LLVM_NODISCARD [[clang::warn_unused_result]]
+// Clang in C++14 mode claims that it has the 'nodiscard' attribute, but also
+// warns in the pedantic mode that 'nodiscard' is a C++17 extension (PR33518).
+// Use the 'nodiscard' attribute in C++14 mode only with GCC.
+// TODO: remove this workaround when PR33518 is resolved.
+#elif defined(__GNUC__) && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)
+#define LLVM_NODISCARD [[nodiscard]]
#else
#define LLVM_NODISCARD
#endif
@@ -139,7 +160,7 @@
// The clang-tidy check bugprone-use-after-move recognizes this attribute as a
// marker that a moved-from object has left the indeterminate state and can be
// reused.
-#if __has_cpp_attribute(clang::reinitializes)
+#if LLVM_HAS_CPP_ATTRIBUTE(clang::reinitializes)
#define LLVM_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
#else
#define LLVM_ATTRIBUTE_REINITIALIZES
@@ -240,15 +261,13 @@
#endif
/// LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
-#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
+#if __cplusplus > 201402L && LLVM_HAS_CPP_ATTRIBUTE(fallthrough)
#define LLVM_FALLTHROUGH [[fallthrough]]
-#elif __has_cpp_attribute(gnu::fallthrough)
+#elif LLVM_HAS_CPP_ATTRIBUTE(gnu::fallthrough)
#define LLVM_FALLTHROUGH [[gnu::fallthrough]]
-#elif !__cplusplus
-// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious
-// error when __has_cpp_attribute is given a scoped attribute in C mode.
-#define LLVM_FALLTHROUGH
-#elif __has_cpp_attribute(clang::fallthrough)
+#elif __has_attribute(fallthrough)
+#define LLVM_FALLTHROUGH __attribute__((fallthrough))
+#elif LLVM_HAS_CPP_ATTRIBUTE(clang::fallthrough)
#define LLVM_FALLTHROUGH [[clang::fallthrough]]
#else
#define LLVM_FALLTHROUGH
@@ -256,7 +275,7 @@
/// LLVM_REQUIRE_CONSTANT_INITIALIZATION - Apply this to globals to ensure that
/// they are constant initialized.
-#if __has_cpp_attribute(clang::require_constant_initialization)
+#if LLVM_HAS_CPP_ATTRIBUTE(clang::require_constant_initialization)
#define LLVM_REQUIRE_CONSTANT_INITIALIZATION \
[[clang::require_constant_initialization]]
#else
@@ -338,14 +357,6 @@
# define LLVM_ASSUME_ALIGNED(p, a) (p)
#endif
-/// \macro LLVM_ALIGNAS
-/// Used to specify a minimum alignment for a structure or variable.
-#if __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 1)
-# define LLVM_ALIGNAS(x) __attribute__((aligned(x)))
-#else
-# define LLVM_ALIGNAS(x) alignas(x)
-#endif
-
/// \macro LLVM_PACKED
/// Used to specify a packed structure.
/// LLVM_PACKED(
@@ -376,8 +387,8 @@
/// \macro LLVM_PTR_SIZE
/// A constant integer equivalent to the value of sizeof(void*).
-/// Generally used in combination with LLVM_ALIGNAS or when doing computation in
-/// the preprocessor.
+/// Generally used in combination with alignas or when doing computation in the
+/// preprocessor.
#ifdef __SIZEOF_POINTER__
# define LLVM_PTR_SIZE __SIZEOF_POINTER__
#elif defined(_WIN64)
@@ -527,6 +538,7 @@ void AnnotateIgnoreWritesEnd(const char *file, int line);
#define LLVM_ENABLE_EXCEPTIONS 1
#endif
+#ifdef __cplusplus
namespace llvm {
/// Allocate a buffer of memory with the given size and alignment.
@@ -569,4 +581,5 @@ inline void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) {
} // End namespace llvm
+#endif // __cplusplus
#endif
diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h
index 6b08a2a2a445..f590a1e104fb 100644
--- a/include/llvm/Support/DataExtractor.h
+++ b/include/llvm/Support/DataExtractor.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Error.h"
namespace llvm {
@@ -42,6 +43,38 @@ class DataExtractor {
uint8_t IsLittleEndian;
uint8_t AddressSize;
public:
+ /// A class representing a position in a DataExtractor, as well as any error
+ /// encountered during extraction. It enables one to extract a sequence of
+ /// values without error-checking and then checking for errors in bulk at the
+ /// end. The class holds an Error object, so failing to check the result of
+ /// the parse will result in a runtime error. The error flag is sticky and
+ /// will cause all subsequent extraction functions to fail without even
+ /// attempting to parse and without updating the Cursor offset. After clearing
+ /// the error flag, one can again use the Cursor object for parsing.
+ class Cursor {
+ uint64_t Offset;
+ Error Err;
+
+ friend class DataExtractor;
+
+ public:
+ /// Construct a cursor for extraction from the given offset.
+ explicit Cursor(uint64_t Offset) : Offset(Offset), Err(Error::success()) {}
+
+ /// Checks whether the cursor is valid (i.e. no errors were encountered). In
+ /// case of errors, this does not clear the error flag -- one must call
+ /// takeError() instead.
+ explicit operator bool() { return !Err; }
+
+ /// Return the current position of this Cursor. In the error state this is
+ /// the position of the Cursor before the first error was encountered.
+ uint64_t tell() const { return Offset; }
+
+ /// Return error contained inside this Cursor, if any. Clears the internal
+ /// Cursor state.
+ Error takeError() { return std::move(Err); }
+ };
+
/// Construct with a buffer that is owned by the caller.
///
/// This constructor allows us to use data that is owned by the
@@ -49,6 +82,11 @@ public:
/// valid.
DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)
: Data(Data), IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {}
+ DataExtractor(ArrayRef<uint8_t> Data, bool IsLittleEndian,
+ uint8_t AddressSize)
+ : Data(StringRef(reinterpret_cast<const char *>(Data.data()),
+ Data.size())),
+ IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {}
/// Get the data pointed to by this extractor.
StringRef getData() const { return Data; }
@@ -79,17 +117,17 @@ public:
/// pointed to by \a offset_ptr is out of bounds, or if the
/// offset plus the length of the C string is out of bounds,
/// NULL will be returned.
- const char *getCStr(uint32_t *offset_ptr) const;
+ const char *getCStr(uint64_t *offset_ptr) const;
- /// Extract a C string from \a *OffsetPtr.
+ /// Extract a C string from \a *offset_ptr.
///
/// Returns a StringRef for the C String from the data at the offset
- /// pointed to by \a OffsetPtr. A variable length NULL terminated C
- /// string will be extracted and the \a OffsetPtr will be
+ /// pointed to by \a offset_ptr. A variable length NULL terminated C
+ /// string will be extracted and the \a offset_ptr will be
/// updated with the offset of the byte that follows the NULL
/// terminator byte.
///
- /// \param[in,out] OffsetPtr
+ /// \param[in,out] offset_ptr
/// A pointer to an offset within the data that will be advanced
/// by the appropriate number of bytes if the value is extracted
/// correctly. If the offset is out of bounds or there are not
@@ -98,10 +136,10 @@ public:
///
/// \return
/// A StringRef for the C string value in the data. If the offset
- /// pointed to by \a OffsetPtr is out of bounds, or if the
+ /// pointed to by \a offset_ptr is out of bounds, or if the
/// offset plus the length of the C string is out of bounds,
/// a default-initialized StringRef will be returned.
- StringRef getCStrRef(uint32_t *OffsetPtr) const;
+ StringRef getCStrRef(uint64_t *offset_ptr) const;
/// Extract an unsigned integer of size \a byte_size from \a
/// *offset_ptr.
@@ -124,10 +162,24 @@ public:
/// @param[in] byte_size
/// The size in byte of the integer to extract.
///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
/// @return
/// The unsigned integer value that was extracted, or zero on
/// failure.
- uint64_t getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const;
+ uint64_t getUnsigned(uint64_t *offset_ptr, uint32_t byte_size,
+ Error *Err = nullptr) const;
+
+ /// Extract an unsigned integer of the given size from the location given by
+ /// the cursor. In case of an extraction error, or if the cursor is already in
+ /// an error state, zero is returned.
+ uint64_t getUnsigned(Cursor &C, uint32_t Size) const {
+ return getUnsigned(&C.Offset, Size, &C.Err);
+ }
/// Extract an signed integer of size \a byte_size from \a *offset_ptr.
///
@@ -152,7 +204,7 @@ public:
/// @return
/// The sign extended signed integer value that was extracted,
/// or zero on failure.
- int64_t getSigned(uint32_t *offset_ptr, uint32_t size) const;
+ int64_t getSigned(uint64_t *offset_ptr, uint32_t size) const;
//------------------------------------------------------------------
/// Extract an pointer from \a *offset_ptr.
@@ -171,10 +223,15 @@ public:
///
/// @return
/// The extracted pointer value as a 64 integer.
- uint64_t getAddress(uint32_t *offset_ptr) const {
+ uint64_t getAddress(uint64_t *offset_ptr) const {
return getUnsigned(offset_ptr, AddressSize);
}
+ /// Extract a pointer-sized unsigned integer from the location given by the
+ /// cursor. In case of an extraction error, or if the cursor is already in
+ /// an error state, zero is returned.
+ uint64_t getAddress(Cursor &C) const { return getUnsigned(C, AddressSize); }
+
/// Extract a uint8_t value from \a *offset_ptr.
///
/// Extract a single uint8_t from the binary data at the offset
@@ -187,9 +244,20 @@ public:
/// enough bytes to extract this value, the offset will be left
/// unmodified.
///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
/// @return
/// The extracted uint8_t value.
- uint8_t getU8(uint32_t *offset_ptr) const;
+ uint8_t getU8(uint64_t *offset_ptr, Error *Err = nullptr) const;
+
+ /// Extract a single uint8_t value from the location given by the cursor. In
+ /// case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ uint8_t getU8(Cursor &C) const { return getU8(&C.Offset, &C.Err); }
/// Extract \a count uint8_t values from \a *offset_ptr.
///
@@ -214,7 +282,27 @@ public:
/// @return
/// \a dst if all values were properly extracted and copied,
/// NULL otherise.
- uint8_t *getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const;
+ uint8_t *getU8(uint64_t *offset_ptr, uint8_t *dst, uint32_t count) const;
+
+ /// Extract \a Count uint8_t values from the location given by the cursor and
+ /// store them into the destination buffer. In case of an extraction error, or
+ /// if the cursor is already in an error state, a nullptr is returned and the
+ /// destination buffer is left unchanged.
+ uint8_t *getU8(Cursor &C, uint8_t *Dst, uint32_t Count) const;
+
+ /// Extract \a Count uint8_t values from the location given by the cursor and
+ /// store them into the destination vector. The vector is resized to fit the
+ /// extracted data. In case of an extraction error, or if the cursor is
+ /// already in an error state, the destination vector is left unchanged and
+ /// cursor is placed into an error state.
+ void getU8(Cursor &C, SmallVectorImpl<uint8_t> &Dst, uint32_t Count) const {
+ if (isValidOffsetForDataOfSize(C.Offset, Count))
+ Dst.resize(Count);
+
+ // This relies on the fact that getU8 will not attempt to write to the
+ // buffer if isValidOffsetForDataOfSize(C.Offset, Count) is false.
+ getU8(C, Dst.data(), Count);
+ }
//------------------------------------------------------------------
/// Extract a uint16_t value from \a *offset_ptr.
@@ -229,10 +317,21 @@ public:
/// enough bytes to extract this value, the offset will be left
/// unmodified.
///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
/// @return
/// The extracted uint16_t value.
//------------------------------------------------------------------
- uint16_t getU16(uint32_t *offset_ptr) const;
+ uint16_t getU16(uint64_t *offset_ptr, Error *Err = nullptr) const;
+
+ /// Extract a single uint16_t value from the location given by the cursor. In
+ /// case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ uint16_t getU16(Cursor &C) const { return getU16(&C.Offset, &C.Err); }
/// Extract \a count uint16_t values from \a *offset_ptr.
///
@@ -257,7 +356,7 @@ public:
/// @return
/// \a dst if all values were properly extracted and copied,
/// NULL otherise.
- uint16_t *getU16(uint32_t *offset_ptr, uint16_t *dst, uint32_t count) const;
+ uint16_t *getU16(uint64_t *offset_ptr, uint16_t *dst, uint32_t count) const;
/// Extract a 24-bit unsigned value from \a *offset_ptr and return it
/// in a uint32_t.
@@ -274,7 +373,7 @@ public:
///
/// @return
/// The extracted 24-bit value represented in a uint32_t.
- uint32_t getU24(uint32_t *offset_ptr) const;
+ uint32_t getU24(uint64_t *offset_ptr) const;
/// Extract a uint32_t value from \a *offset_ptr.
///
@@ -288,9 +387,20 @@ public:
/// enough bytes to extract this value, the offset will be left
/// unmodified.
///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
/// @return
/// The extracted uint32_t value.
- uint32_t getU32(uint32_t *offset_ptr) const;
+ uint32_t getU32(uint64_t *offset_ptr, Error *Err = nullptr) const;
+
+ /// Extract a single uint32_t value from the location given by the cursor. In
+ /// case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ uint32_t getU32(Cursor &C) const { return getU32(&C.Offset, &C.Err); }
/// Extract \a count uint32_t values from \a *offset_ptr.
///
@@ -315,7 +425,7 @@ public:
/// @return
/// \a dst if all values were properly extracted and copied,
/// NULL otherise.
- uint32_t *getU32(uint32_t *offset_ptr, uint32_t *dst, uint32_t count) const;
+ uint32_t *getU32(uint64_t *offset_ptr, uint32_t *dst, uint32_t count) const;
/// Extract a uint64_t value from \a *offset_ptr.
///
@@ -329,9 +439,20 @@ public:
/// enough bytes to extract this value, the offset will be left
/// unmodified.
///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
/// @return
/// The extracted uint64_t value.
- uint64_t getU64(uint32_t *offset_ptr) const;
+ uint64_t getU64(uint64_t *offset_ptr, Error *Err = nullptr) const;
+
+ /// Extract a single uint64_t value from the location given by the cursor. In
+ /// case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ uint64_t getU64(Cursor &C) const { return getU64(&C.Offset, &C.Err); }
/// Extract \a count uint64_t values from \a *offset_ptr.
///
@@ -356,7 +477,7 @@ public:
/// @return
/// \a dst if all values were properly extracted and copied,
/// NULL otherise.
- uint64_t *getU64(uint32_t *offset_ptr, uint64_t *dst, uint32_t count) const;
+ uint64_t *getU64(uint64_t *offset_ptr, uint64_t *dst, uint32_t count) const;
/// Extract a signed LEB128 value from \a *offset_ptr.
///
@@ -374,7 +495,7 @@ public:
///
/// @return
/// The extracted signed integer value.
- int64_t getSLEB128(uint32_t *offset_ptr) const;
+ int64_t getSLEB128(uint64_t *offset_ptr) const;
/// Extract a unsigned LEB128 value from \a *offset_ptr.
///
@@ -390,23 +511,44 @@ public:
/// enough bytes to extract this value, the offset will be left
/// unmodified.
///
+ /// @param[in,out] Err
+ /// A pointer to an Error object. Upon return the Error object is set to
+ /// indicate the result (success/failure) of the function. If the Error
+ /// object is already set when calling this function, no extraction is
+ /// performed.
+ ///
/// @return
/// The extracted unsigned integer value.
- uint64_t getULEB128(uint32_t *offset_ptr) const;
+ uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err = nullptr) const;
+
+ /// Extract an unsigned ULEB128 value from the location given by the cursor.
+ /// In case of an extraction error, or if the cursor is already in an error
+ /// state, zero is returned.
+ uint64_t getULEB128(Cursor &C) const { return getULEB128(&C.Offset, &C.Err); }
+
+ /// Advance the Cursor position by the given number of bytes. No-op if the
+ /// cursor is in an error state.
+ void skip(Cursor &C, uint64_t Length) const;
+
+ /// Return true iff the cursor is at the end of the buffer, regardless of the
+ /// error state of the cursor. The only way both eof and error states can be
+ /// true is if one attempts a read while the cursor is at the very end of the
+ /// data buffer.
+ bool eof(const Cursor &C) const { return Data.size() == C.Offset; }
/// Test the validity of \a offset.
///
/// @return
/// \b true if \a offset is a valid offset into the data in this
/// object, \b false otherwise.
- bool isValidOffset(uint32_t offset) const { return Data.size() > offset; }
+ bool isValidOffset(uint64_t offset) const { return Data.size() > offset; }
/// Test the availability of \a length bytes of data from \a offset.
///
/// @return
/// \b true if \a offset is a valid offset and there are \a
/// length bytes available at that offset, \b false otherwise.
- bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const {
+ bool isValidOffsetForDataOfSize(uint64_t offset, uint64_t length) const {
return offset + length >= offset && isValidOffset(offset + length - 1);
}
@@ -417,9 +559,15 @@ public:
/// \b true if \a offset is a valid offset and there are enough
/// bytes for a pointer available at that offset, \b false
/// otherwise.
- bool isValidOffsetForAddress(uint32_t offset) const {
+ bool isValidOffsetForAddress(uint64_t offset) const {
return isValidOffsetForDataOfSize(offset, AddressSize);
}
+
+protected:
+ // Make it possible for subclasses to access these fields without making them
+ // public.
+ static uint64_t &getOffset(Cursor &C) { return C.Offset; }
+ static Error &getError(Cursor &C) { return C.Err; }
};
} // namespace llvm
diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h
index d8be94427d7e..87aecedd3a4b 100644
--- a/include/llvm/Support/Endian.h
+++ b/include/llvm/Support/Endian.h
@@ -203,9 +203,8 @@ inline void writeAtBitAlignment(void *memory, value_type value,
namespace detail {
-template<typename ValueType,
- endianness Endian,
- std::size_t Alignment>
+template <typename ValueType, endianness Endian, std::size_t Alignment,
+ std::size_t ALIGN = PickAlignment<ValueType, Alignment>::value>
struct packed_endian_specific_integral {
using value_type = ValueType;
static constexpr endianness endian = Endian;
@@ -246,8 +245,9 @@ struct packed_endian_specific_integral {
}
private:
- AlignedCharArray<PickAlignment<value_type, alignment>::value,
- sizeof(value_type)> Value;
+ struct {
+ alignas(ALIGN) char buffer[sizeof(value_type)];
+ } Value;
public:
struct ref {
diff --git a/include/llvm/Support/Error.h b/include/llvm/Support/Error.h
index 299fce7a1368..350877a219bf 100644
--- a/include/llvm/Support/Error.h
+++ b/include/llvm/Support/Error.h
@@ -328,7 +328,7 @@ inline ErrorSuccess Error::success() { return ErrorSuccess(); }
/// 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)...));
+ return Error(std::make_unique<ErrT>(std::forward<ArgTs>(Args)...));
}
/// Base class for user error types. Users should declare their error types
@@ -548,7 +548,7 @@ public:
/// 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.
+ /// be made on the Expected<T> value.
Error takeError() {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
Unchecked = false;
@@ -704,6 +704,12 @@ inline void cantFail(Error Err, const char *Msg = nullptr) {
if (Err) {
if (!Msg)
Msg = "Failure value returned from cantFail wrapped call";
+#ifndef NDEBUG
+ std::string Str;
+ raw_string_ostream OS(Str);
+ OS << Msg << "\n" << Err;
+ Msg = OS.str().c_str();
+#endif
llvm_unreachable(Msg);
}
}
@@ -728,6 +734,13 @@ T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) {
else {
if (!Msg)
Msg = "Failure value returned from cantFail wrapped call";
+#ifndef NDEBUG
+ std::string Str;
+ raw_string_ostream OS(Str);
+ auto E = ValOrErr.takeError();
+ OS << Msg << "\n" << E;
+ Msg = OS.str().c_str();
+#endif
llvm_unreachable(Msg);
}
}
@@ -752,6 +765,13 @@ T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) {
else {
if (!Msg)
Msg = "Failure value returned from cantFail wrapped call";
+#ifndef NDEBUG
+ std::string Str;
+ raw_string_ostream OS(Str);
+ auto E = ValOrErr.takeError();
+ OS << Msg << "\n" << E;
+ Msg = OS.str().c_str();
+#endif
llvm_unreachable(Msg);
}
}
@@ -982,6 +1002,20 @@ inline void consumeError(Error Err) {
handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
}
+/// Convert an Expected to an Optional 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 problems: perhaps the
+/// error should be propagated further, or the error-producer should just
+/// return an Optional in the first place.
+template <typename T> Optional<T> expectedToOptional(Expected<T> &&E) {
+ if (E)
+ return std::move(*E);
+ consumeError(E.takeError());
+ return None;
+}
+
/// Helper for converting an Error to a bool.
///
/// This method returns true if Err is in an error state, or false if it is
@@ -1170,6 +1204,10 @@ inline Error createStringError(std::error_code EC, char const *Fmt,
Error createStringError(std::error_code EC, char const *Msg);
+inline Error createStringError(std::error_code EC, const Twine &S) {
+ return createStringError(EC, S.str().c_str());
+}
+
template <typename... Ts>
inline Error createStringError(std::errc EC, char const *Fmt,
const Ts &... Vals) {
diff --git a/include/llvm/Support/FileCheck.h b/include/llvm/Support/FileCheck.h
index 0cd25a71a3b3..2547449246a8 100644
--- a/include/llvm/Support/FileCheck.h
+++ b/include/llvm/Support/FileCheck.h
@@ -13,12 +13,12 @@
#ifndef LLVM_SUPPORT_FILECHECK_H
#define LLVM_SUPPORT_FILECHECK_H
-#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/SourceMgr.h"
+#include <string>
#include <vector>
-#include <map>
namespace llvm {
@@ -30,6 +30,7 @@ struct FileCheckRequest {
std::vector<std::string> GlobalDefines;
bool AllowEmptyInput = false;
bool MatchFullLines = false;
+ bool IgnoreCase = false;
bool EnableVarScope = false;
bool AllowDeprecatedDagOverlap = false;
bool Verbose = false;
@@ -37,217 +38,7 @@ struct FileCheckRequest {
};
//===----------------------------------------------------------------------===//
-// Numeric substitution handling code.
-//===----------------------------------------------------------------------===//
-
-/// Base class representing the AST of a given expression.
-class FileCheckExpressionAST {
-public:
- virtual ~FileCheckExpressionAST() = default;
-
- /// Evaluates and \returns the value of the expression represented by this
- /// AST or an error if evaluation fails.
- virtual Expected<uint64_t> eval() const = 0;
-};
-
-/// Class representing an unsigned literal in the AST of an expression.
-class FileCheckExpressionLiteral : public FileCheckExpressionAST {
-private:
- /// Actual value of the literal.
- uint64_t Value;
-
-public:
- /// Constructs a literal with the specified value.
- FileCheckExpressionLiteral(uint64_t Val) : Value(Val) {}
-
- /// \returns the literal's value.
- Expected<uint64_t> eval() const { return Value; }
-};
-
-/// Class to represent an undefined variable error, which quotes that
-/// variable's name when printed.
-class FileCheckUndefVarError : public ErrorInfo<FileCheckUndefVarError> {
-private:
- StringRef VarName;
-
-public:
- static char ID;
-
- FileCheckUndefVarError(StringRef VarName) : VarName(VarName) {}
-
- StringRef getVarName() const { return VarName; }
-
- std::error_code convertToErrorCode() const override {
- return inconvertibleErrorCode();
- }
-
- /// Print name of variable associated with this error.
- void log(raw_ostream &OS) const override {
- OS << "\"";
- OS.write_escaped(VarName) << "\"";
- }
-};
-
-/// Class representing a numeric variable and its associated current value.
-class FileCheckNumericVariable {
-private:
- /// Name of the numeric variable.
- StringRef Name;
-
- /// Value of numeric variable, if defined, or None otherwise.
- Optional<uint64_t> Value;
-
- /// Line number where this variable is defined, or None if defined before
- /// input is parsed. Used to determine whether a variable is defined on the
- /// same line as a given use.
- Optional<size_t> DefLineNumber;
-
-public:
- /// Constructor for a variable \p Name defined at line \p DefLineNumber or
- /// defined before input is parsed if DefLineNumber is None.
- FileCheckNumericVariable(StringRef Name,
- Optional<size_t> DefLineNumber = None)
- : Name(Name), DefLineNumber(DefLineNumber) {}
-
- /// \returns name of this numeric variable.
- StringRef getName() const { return Name; }
-
- /// \returns this variable's value.
- Optional<uint64_t> getValue() const { return Value; }
-
- /// Sets value of this numeric variable, if undefined. Triggers an assertion
- /// failure if the variable is actually defined.
- void setValue(uint64_t Value);
-
- /// Clears value of this numeric variable, regardless of whether it is
- /// currently defined or not.
- void clearValue();
-
- /// \returns the line number where this variable is defined, if any, or None
- /// if defined before input is parsed.
- Optional<size_t> getDefLineNumber() { return DefLineNumber; }
-};
-
-/// Class representing the use of a numeric variable in the AST of an
-/// expression.
-class FileCheckNumericVariableUse : public FileCheckExpressionAST {
-private:
- /// Name of the numeric variable.
- StringRef Name;
-
- /// Pointer to the class instance for the variable this use is about.
- FileCheckNumericVariable *NumericVariable;
-
-public:
- FileCheckNumericVariableUse(StringRef Name,
- FileCheckNumericVariable *NumericVariable)
- : Name(Name), NumericVariable(NumericVariable) {}
-
- /// \returns the value of the variable referenced by this instance.
- Expected<uint64_t> eval() const;
-};
-
-/// Type of functions evaluating a given binary operation.
-using binop_eval_t = uint64_t (*)(uint64_t, uint64_t);
-
-/// Class representing a single binary operation in the AST of an expression.
-class FileCheckASTBinop : public FileCheckExpressionAST {
-private:
- /// Left operand.
- std::unique_ptr<FileCheckExpressionAST> LeftOperand;
-
- /// Right operand.
- std::unique_ptr<FileCheckExpressionAST> RightOperand;
-
- /// Pointer to function that can evaluate this binary operation.
- binop_eval_t EvalBinop;
-
-public:
- FileCheckASTBinop(binop_eval_t EvalBinop,
- std::unique_ptr<FileCheckExpressionAST> LeftOp,
- std::unique_ptr<FileCheckExpressionAST> RightOp)
- : EvalBinop(EvalBinop) {
- LeftOperand = std::move(LeftOp);
- RightOperand = std::move(RightOp);
- }
-
- /// Evaluates the value of the binary operation represented by this AST,
- /// using EvalBinop on the result of recursively evaluating the operands.
- /// \returns the expression value or an error if an undefined numeric
- /// variable is used in one of the operands.
- Expected<uint64_t> eval() const;
-};
-
-class FileCheckPatternContext;
-
-/// Class representing a substitution to perform in the RegExStr string.
-class FileCheckSubstitution {
-protected:
- /// Pointer to a class instance holding, among other things, the table with
- /// the values of live string variables at the start of any given CHECK line.
- /// Used for substituting string variables with the text they were defined
- /// as. Expressions are linked to the numeric variables they use at
- /// parse time and directly access the value of the numeric variable to
- /// evaluate their value.
- FileCheckPatternContext *Context;
-
- /// The string that needs to be substituted for something else. For a
- /// string variable this is its name, otherwise this is the whole expression.
- StringRef FromStr;
-
- // Index in RegExStr of where to do the substitution.
- size_t InsertIdx;
-
-public:
- FileCheckSubstitution(FileCheckPatternContext *Context, StringRef VarName,
- size_t InsertIdx)
- : Context(Context), FromStr(VarName), InsertIdx(InsertIdx) {}
-
- virtual ~FileCheckSubstitution() = default;
-
- /// \returns the string to be substituted for something else.
- StringRef getFromString() const { return FromStr; }
-
- /// \returns the index where the substitution is to be performed in RegExStr.
- size_t getIndex() const { return InsertIdx; }
-
- /// \returns a string containing the result of the substitution represented
- /// by this class instance or an error if substitution failed.
- virtual Expected<std::string> getResult() const = 0;
-};
-
-class FileCheckStringSubstitution : public FileCheckSubstitution {
-public:
- FileCheckStringSubstitution(FileCheckPatternContext *Context,
- StringRef VarName, size_t InsertIdx)
- : FileCheckSubstitution(Context, VarName, InsertIdx) {}
-
- /// \returns the text that the string variable in this substitution matched
- /// when defined, or an error if the variable is undefined.
- Expected<std::string> getResult() const override;
-};
-
-class FileCheckNumericSubstitution : public FileCheckSubstitution {
-private:
- /// Pointer to the class representing the expression whose value is to be
- /// substituted.
- std::unique_ptr<FileCheckExpressionAST> ExpressionAST;
-
-public:
- FileCheckNumericSubstitution(FileCheckPatternContext *Context, StringRef Expr,
- std::unique_ptr<FileCheckExpressionAST> ExprAST,
- size_t InsertIdx)
- : FileCheckSubstitution(Context, Expr, InsertIdx) {
- ExpressionAST = std::move(ExprAST);
- }
-
- /// \returns a string containing the result of evaluating the expression in
- /// this substitution, or an error if evaluation failed.
- Expected<std::string> getResult() const override;
-};
-
-//===----------------------------------------------------------------------===//
-// Pattern handling code.
+// Summary of a FileCheck diagnostic.
//===----------------------------------------------------------------------===//
namespace Check {
@@ -291,325 +82,6 @@ public:
};
} // namespace Check
-struct FileCheckDiag;
-
-/// Class holding the FileCheckPattern global state, shared by all patterns:
-/// tables holding values of variables and whether they are defined or not at
-/// any given time in the matching process.
-class FileCheckPatternContext {
- friend class FileCheckPattern;
-
-private:
- /// When matching a given pattern, this holds the value of all the string
- /// variables defined in previous patterns. In a pattern, only the last
- /// definition for a given variable is recorded in this table.
- /// Back-references are used for uses after any the other definition.
- StringMap<StringRef> GlobalVariableTable;
-
- /// Map of all string variables defined so far. Used at parse time to detect
- /// a name conflict between a numeric variable and a string variable when
- /// the former is defined on a later line than the latter.
- StringMap<bool> DefinedVariableTable;
-
- /// When matching a given pattern, this holds the pointers to the classes
- /// representing the numeric variables defined in previous patterns. When
- /// matching a pattern all definitions for that pattern are recorded in the
- /// NumericVariableDefs table in the FileCheckPattern instance of that
- /// pattern.
- StringMap<FileCheckNumericVariable *> GlobalNumericVariableTable;
-
- /// Pointer to the class instance representing the @LINE pseudo variable for
- /// easily updating its value.
- FileCheckNumericVariable *LineVariable = nullptr;
-
- /// Vector holding pointers to all parsed numeric variables. Used to
- /// automatically free them once they are guaranteed to no longer be used.
- std::vector<std::unique_ptr<FileCheckNumericVariable>> NumericVariables;
-
- /// Vector holding pointers to all substitutions. Used to automatically free
- /// them once they are guaranteed to no longer be used.
- std::vector<std::unique_ptr<FileCheckSubstitution>> Substitutions;
-
-public:
- /// \returns the value of string variable \p VarName or an error if no such
- /// variable has been defined.
- Expected<StringRef> getPatternVarValue(StringRef VarName);
-
- /// Defines string and numeric variables from definitions given on the
- /// command line, passed as a vector of [#]VAR=VAL strings in
- /// \p CmdlineDefines. \returns an error list containing diagnostics against
- /// \p SM for all definition parsing failures, if any, or Success otherwise.
- Error defineCmdlineVariables(std::vector<std::string> &CmdlineDefines,
- SourceMgr &SM);
-
- /// Create @LINE pseudo variable. Value is set when pattern are being
- /// matched.
- void createLineVariable();
-
- /// Undefines local variables (variables whose name does not start with a '$'
- /// sign), i.e. removes them from GlobalVariableTable and from
- /// GlobalNumericVariableTable and also clears the value of numeric
- /// variables.
- void clearLocalVars();
-
-private:
- /// Makes a new numeric variable and registers it for destruction when the
- /// context is destroyed.
- template <class... Types>
- FileCheckNumericVariable *makeNumericVariable(Types... args);
-
- /// Makes a new string substitution and registers it for destruction when the
- /// context is destroyed.
- FileCheckSubstitution *makeStringSubstitution(StringRef VarName,
- size_t InsertIdx);
-
- /// Makes a new numeric substitution and registers it for destruction when
- /// the context is destroyed.
- FileCheckSubstitution *
- makeNumericSubstitution(StringRef ExpressionStr,
- std::unique_ptr<FileCheckExpressionAST> ExpressionAST,
- size_t InsertIdx);
-};
-
-/// Class to represent an error holding a diagnostic with location information
-/// used when printing it.
-class FileCheckErrorDiagnostic : public ErrorInfo<FileCheckErrorDiagnostic> {
-private:
- SMDiagnostic Diagnostic;
-
-public:
- static char ID;
-
- FileCheckErrorDiagnostic(SMDiagnostic &&Diag) : Diagnostic(Diag) {}
-
- std::error_code convertToErrorCode() const override {
- return inconvertibleErrorCode();
- }
-
- /// Print diagnostic associated with this error when printing the error.
- void log(raw_ostream &OS) const override { Diagnostic.print(nullptr, OS); }
-
- static Error get(const SourceMgr &SM, SMLoc Loc, const Twine &ErrMsg) {
- return make_error<FileCheckErrorDiagnostic>(
- SM.GetMessage(Loc, SourceMgr::DK_Error, ErrMsg));
- }
-
- static Error get(const SourceMgr &SM, StringRef Buffer, const Twine &ErrMsg) {
- return get(SM, SMLoc::getFromPointer(Buffer.data()), ErrMsg);
- }
-};
-
-class FileCheckNotFoundError : public ErrorInfo<FileCheckNotFoundError> {
-public:
- static char ID;
-
- std::error_code convertToErrorCode() const override {
- return inconvertibleErrorCode();
- }
-
- /// Print diagnostic associated with this error when printing the error.
- void log(raw_ostream &OS) const override {
- OS << "String not found in input";
- }
-};
-
-class FileCheckPattern {
- SMLoc PatternLoc;
-
- /// A fixed string to match as the pattern or empty if this pattern requires
- /// a regex match.
- StringRef FixedStr;
-
- /// A regex string to match as the pattern or empty if this pattern requires
- /// a fixed string to match.
- std::string RegExStr;
-
- /// Entries in this vector represent a substitution of a string variable or
- /// an expression in the RegExStr regex at match time. For example, in the
- /// case of a CHECK directive with the pattern "foo[[bar]]baz[[#N+1]]",
- /// RegExStr will contain "foobaz" and we'll get two entries in this vector
- /// that tells us to insert the value of string variable "bar" at offset 3
- /// and the value of expression "N+1" at offset 6.
- std::vector<FileCheckSubstitution *> Substitutions;
-
- /// Maps names of string variables defined in a pattern to the number of
- /// their parenthesis group in RegExStr capturing their last definition.
- ///
- /// E.g. for the pattern "foo[[bar:.*]]baz([[bar]][[QUUX]][[bar:.*]])",
- /// RegExStr will be "foo(.*)baz(\1<quux value>(.*))" where <quux value> is
- /// the value captured for QUUX on the earlier line where it was defined, and
- /// VariableDefs will map "bar" to the third parenthesis group which captures
- /// the second definition of "bar".
- ///
- /// Note: uses std::map rather than StringMap to be able to get the key when
- /// iterating over values.
- std::map<StringRef, unsigned> VariableDefs;
-
- /// Structure representing the definition of a numeric variable in a pattern.
- /// It holds the pointer to the class representing the numeric variable whose
- /// value is being defined and the number of the parenthesis group in
- /// RegExStr to capture that value.
- struct FileCheckNumericVariableMatch {
- /// Pointer to class representing the numeric variable whose value is being
- /// defined.
- FileCheckNumericVariable *DefinedNumericVariable;
-
- /// Number of the parenthesis group in RegExStr that captures the value of
- /// this numeric variable definition.
- unsigned CaptureParenGroup;
- };
-
- /// Holds the number of the parenthesis group in RegExStr and pointer to the
- /// corresponding FileCheckNumericVariable class instance of all numeric
- /// variable definitions. Used to set the matched value of all those
- /// variables.
- StringMap<FileCheckNumericVariableMatch> NumericVariableDefs;
-
- /// Pointer to a class instance holding the global state shared by all
- /// patterns:
- /// - separate tables with the values of live string and numeric variables
- /// respectively at the start of any given CHECK line;
- /// - table holding whether a string variable has been defined at any given
- /// point during the parsing phase.
- FileCheckPatternContext *Context;
-
- Check::FileCheckType CheckTy;
-
- /// Line number for this CHECK pattern or None if it is an implicit pattern.
- /// Used to determine whether a variable definition is made on an earlier
- /// line to the one with this CHECK.
- Optional<size_t> LineNumber;
-
-public:
- FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
- Optional<size_t> Line = None)
- : Context(Context), CheckTy(Ty), LineNumber(Line) {}
-
- /// \returns the location in source code.
- SMLoc getLoc() const { return PatternLoc; }
-
- /// \returns the pointer to the global state for all patterns in this
- /// FileCheck instance.
- FileCheckPatternContext *getContext() const { return Context; }
-
- /// \returns whether \p C is a valid first character for a variable name.
- static bool isValidVarNameStart(char C);
-
- /// Parsing information about a variable.
- struct VariableProperties {
- StringRef Name;
- bool IsPseudo;
- };
-
- /// Parses the string at the start of \p Str for a variable name. \returns
- /// a VariableProperties structure holding the variable name and whether it
- /// is the name of a pseudo variable, or an error holding a diagnostic
- /// against \p SM if parsing fail. If parsing was successful, also strips
- /// \p Str from the variable name.
- static Expected<VariableProperties> parseVariable(StringRef &Str,
- const SourceMgr &SM);
- /// Parses \p Expr for the name of a numeric variable to be defined at line
- /// \p LineNumber or before input is parsed if \p LineNumber is None.
- /// \returns a pointer to the class instance representing that variable,
- /// creating it if needed, or an error holding a diagnostic against \p SM
- /// should defining such a variable be invalid.
- static Expected<FileCheckNumericVariable *> parseNumericVariableDefinition(
- StringRef &Expr, FileCheckPatternContext *Context,
- Optional<size_t> LineNumber, const SourceMgr &SM);
- /// Parses \p Expr for a numeric substitution block. Parameter
- /// \p IsLegacyLineExpr indicates whether \p Expr should be a legacy @LINE
- /// expression. \returns a pointer to the class instance representing the AST
- /// of the expression whose value must be substituted, or an error holding a
- /// diagnostic against \p SM if parsing fails. If substitution was
- /// successful, sets \p DefinedNumericVariable to point to the class
- /// representing the numeric variable being defined in this numeric
- /// substitution block, or None if this block does not define any variable.
- Expected<std::unique_ptr<FileCheckExpressionAST>>
- parseNumericSubstitutionBlock(
- StringRef Expr,
- Optional<FileCheckNumericVariable *> &DefinedNumericVariable,
- bool IsLegacyLineExpr, const SourceMgr &SM) const;
- /// Parses the pattern in \p PatternStr and initializes this FileCheckPattern
- /// instance accordingly.
- ///
- /// \p Prefix provides which prefix is being matched, \p Req describes the
- /// global options that influence the parsing such as whitespace
- /// canonicalization, \p SM provides the SourceMgr used for error reports.
- /// \returns true in case of an error, false otherwise.
- bool parsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
- const FileCheckRequest &Req);
- /// Matches the pattern string against the input buffer \p Buffer
- ///
- /// \returns the position that is matched or an error indicating why matching
- /// failed. If there is a match, updates \p MatchLen with the size of the
- /// matched string.
- ///
- /// The GlobalVariableTable StringMap in the FileCheckPatternContext class
- /// instance provides the current values of FileCheck string variables and
- /// is updated if this match defines new values. Likewise, the
- /// GlobalNumericVariableTable StringMap in the same class provides the
- /// current values of FileCheck numeric variables and is updated if this
- /// match defines new numeric values.
- Expected<size_t> match(StringRef Buffer, size_t &MatchLen,
- const SourceMgr &SM) const;
- /// Prints the value of successful substitutions or the name of the undefined
- /// string or numeric variables preventing a successful substitution.
- void printSubstitutions(const SourceMgr &SM, StringRef Buffer,
- SMRange MatchRange = None) const;
- void printFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
- std::vector<FileCheckDiag> *Diags) const;
-
- bool hasVariable() const {
- return !(Substitutions.empty() && VariableDefs.empty());
- }
-
- Check::FileCheckType getCheckTy() const { return CheckTy; }
-
- int getCount() const { return CheckTy.getCount(); }
-
-private:
- bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
- void AddBackrefToRegEx(unsigned BackrefNum);
- /// Computes an arbitrary estimate for the quality of matching this pattern
- /// at the start of \p Buffer; a distance of zero should correspond to a
- /// perfect match.
- unsigned computeMatchDistance(StringRef Buffer) const;
- /// Finds the closing sequence of a regex variable usage or definition.
- ///
- /// \p Str has to point in the beginning of the definition (right after the
- /// opening sequence). \p SM holds the SourceMgr used for error repporting.
- /// \returns the offset of the closing sequence within Str, or npos if it
- /// was not found.
- size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
-
- /// Parses \p Name as a (pseudo if \p IsPseudo is true) numeric variable use.
- /// \returns the pointer to the class instance representing that variable if
- /// successful, or an error holding a diagnostic against \p SM otherwise.
- Expected<std::unique_ptr<FileCheckNumericVariableUse>>
- parseNumericVariableUse(StringRef Name, bool IsPseudo,
- const SourceMgr &SM) const;
- enum class AllowedOperand { LineVar, Literal, Any };
- /// Parses \p Expr for use of a numeric operand. Accepts both literal values
- /// and numeric variables, depending on the value of \p AO. \returns the
- /// class representing that operand in the AST of the expression or an error
- /// holding a diagnostic against \p SM otherwise.
- Expected<std::unique_ptr<FileCheckExpressionAST>>
- parseNumericOperand(StringRef &Expr, AllowedOperand AO,
- const SourceMgr &SM) const;
- /// Parses \p Expr for a binary operation. The left operand of this binary
- /// operation is given in \p LeftOp and \p IsLegacyLineExpr indicates whether
- /// we are parsing a legacy @LINE expression. \returns the class representing
- /// the binary operation in the AST of the expression, or an error holding a
- /// diagnostic against \p SM otherwise.
- Expected<std::unique_ptr<FileCheckExpressionAST>>
- parseBinop(StringRef &Expr, std::unique_ptr<FileCheckExpressionAST> LeftOp,
- bool IsLegacyLineExpr, const SourceMgr &SM) const;
-};
-
-//===----------------------------------------------------------------------===//
-/// Summary of a FileCheck diagnostic.
-//===----------------------------------------------------------------------===//
-
struct FileCheckDiag {
/// What is the FileCheck directive for this diagnostic?
Check::FileCheckType CheckTy;
@@ -659,61 +131,20 @@ struct FileCheckDiag {
SMLoc CheckLoc, MatchType MatchTy, SMRange InputRange);
};
-//===----------------------------------------------------------------------===//
-// Check Strings.
-//===----------------------------------------------------------------------===//
-
-/// A check that we found in the input file.
-struct FileCheckString {
- /// The pattern to match.
- FileCheckPattern Pat;
-
- /// Which prefix name this check matched.
- StringRef Prefix;
-
- /// The location in the match file that the check string was specified.
- SMLoc Loc;
-
- /// All of the strings that are disallowed from occurring between this match
- /// string and the previous one (or start of file).
- std::vector<FileCheckPattern> DagNotStrings;
-
- FileCheckString(const FileCheckPattern &P, StringRef S, SMLoc L)
- : Pat(P), Prefix(S), Loc(L) {}
-
- /// Matches check string and its "not strings" and/or "dag strings".
- size_t Check(const SourceMgr &SM, StringRef Buffer, bool IsLabelScanMode,
- size_t &MatchLen, FileCheckRequest &Req,
- std::vector<FileCheckDiag> *Diags) const;
-
- /// Verifies that there is a single line in the given \p Buffer. Errors are
- /// reported against \p SM.
- bool CheckNext(const SourceMgr &SM, StringRef Buffer) const;
- /// Verifies that there is no newline in the given \p Buffer. Errors are
- /// reported against \p SM.
- bool CheckSame(const SourceMgr &SM, StringRef Buffer) const;
- /// Verifies that none of the strings in \p NotStrings are found in the given
- /// \p Buffer. Errors are reported against \p SM and diagnostics recorded in
- /// \p Diags according to the verbosity level set in \p Req.
- bool CheckNot(const SourceMgr &SM, StringRef Buffer,
- const std::vector<const FileCheckPattern *> &NotStrings,
- const FileCheckRequest &Req,
- std::vector<FileCheckDiag> *Diags) const;
- /// Matches "dag strings" and their mixed "not strings".
- size_t CheckDag(const SourceMgr &SM, StringRef Buffer,
- std::vector<const FileCheckPattern *> &NotStrings,
- const FileCheckRequest &Req,
- std::vector<FileCheckDiag> *Diags) const;
-};
+class FileCheckPatternContext;
+struct FileCheckString;
/// FileCheck class takes the request and exposes various methods that
/// use information from the request.
class FileCheck {
FileCheckRequest Req;
- FileCheckPatternContext PatternContext;
+ std::unique_ptr<FileCheckPatternContext> PatternContext;
+ // C++17 TODO: make this a plain std::vector.
+ std::unique_ptr<std::vector<FileCheckString>> CheckStrings;
public:
- FileCheck(FileCheckRequest Req) : Req(Req) {}
+ explicit FileCheck(FileCheckRequest Req);
+ ~FileCheck();
// Combines the check prefixes into a single regex so that we can efficiently
// scan for any of the set.
@@ -723,13 +154,11 @@ public:
Regex buildCheckPrefixRegex();
/// Reads the check file from \p Buffer and records the expected strings it
- /// contains in the \p CheckStrings vector. Errors are reported against
- /// \p SM.
+ /// contains. Errors are reported against \p SM.
///
/// Only expected strings whose prefix is one of those listed in \p PrefixRE
/// are recorded. \returns true in case of an error, false otherwise.
- bool ReadCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE,
- std::vector<FileCheckString> &CheckStrings);
+ bool readCheckFile(SourceMgr &SM, StringRef Buffer, Regex &PrefixRE);
bool ValidateCheckPrefixes();
@@ -739,13 +168,14 @@ public:
SmallVectorImpl<char> &OutputBuffer);
/// Checks the input to FileCheck provided in the \p Buffer against the
- /// \p CheckStrings read from the check file and record diagnostics emitted
+ /// expected strings read from the check file and record diagnostics emitted
/// in \p Diags. Errors are recorded against \p SM.
///
/// \returns false if the input fails to satisfy the checks.
- bool CheckInput(SourceMgr &SM, StringRef Buffer,
- ArrayRef<FileCheckString> CheckStrings,
+ bool checkInput(SourceMgr &SM, StringRef Buffer,
std::vector<FileCheckDiag> *Diags = nullptr);
};
+
} // namespace llvm
+
#endif
diff --git a/include/llvm/Support/FileCollector.h b/include/llvm/Support/FileCollector.h
new file mode 100644
index 000000000000..19429bd3e9b4
--- /dev/null
+++ b/include/llvm/Support/FileCollector.h
@@ -0,0 +1,79 @@
+//===-- FileCollector.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FILE_COLLECTOR_H
+#define LLVM_SUPPORT_FILE_COLLECTOR_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+#include <mutex>
+
+namespace llvm {
+
+/// Collects files into a directory and generates a mapping that can be used by
+/// the VFS.
+class FileCollector {
+public:
+ FileCollector(std::string Root, std::string OverlayRoot);
+
+ void addFile(const Twine &file);
+
+ /// Write the yaml mapping (for the VFS) to the given file.
+ std::error_code writeMapping(StringRef mapping_file);
+
+ /// Copy the files into the root directory.
+ ///
+ /// When StopOnError is true (the default) we abort as soon as one file
+ /// cannot be copied. This is relatively common, for example when a file was
+ /// removed after it was added to the mapping.
+ std::error_code copyFiles(bool StopOnError = true);
+
+ /// Create a VFS that collects all the paths that might be looked at by the
+ /// file system accesses.
+ static IntrusiveRefCntPtr<vfs::FileSystem>
+ createCollectorVFS(IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
+ std::shared_ptr<FileCollector> Collector);
+
+private:
+ void addFileImpl(StringRef SrcPath);
+
+ bool markAsSeen(StringRef Path) { return Seen.insert(Path).second; }
+
+ bool getRealPath(StringRef SrcPath, SmallVectorImpl<char> &Result);
+
+ void addFileToMapping(StringRef VirtualPath, StringRef RealPath) {
+ VFSWriter.addFileMapping(VirtualPath, RealPath);
+ }
+
+protected:
+ /// Synchronizes adding files.
+ std::mutex Mutex;
+
+ /// The root directory where files are copied.
+ std::string Root;
+
+ /// The root directory where the VFS overlay lives.
+ std::string OverlayRoot;
+
+ /// Tracks already seen files so they can be skipped.
+ StringSet<> Seen;
+
+ /// The yaml mapping writer.
+ vfs::YAMLVFSWriter VFSWriter;
+
+ /// Caches RealPath calls when resolving symlinks.
+ StringMap<std::string> SymlinkMap;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_FILE_COLLECTOR_H
diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h
index 1bec27bddad9..a29a9d787947 100644
--- a/include/llvm/Support/FileSystem.h
+++ b/include/llvm/Support/FileSystem.h
@@ -991,29 +991,27 @@ file_t getStdoutHandle();
/// Returns kInvalidFile when the stream is closed.
file_t getStderrHandle();
-/// Reads \p Buf.size() bytes from \p FileHandle into \p Buf. The number of
-/// bytes actually read is returned in \p BytesRead. On Unix, this is equivalent
-/// to `*BytesRead = ::read(FD, Buf.data(), Buf.size())`, with error reporting.
-/// BytesRead will contain zero when reaching EOF.
+/// Reads \p Buf.size() bytes from \p FileHandle into \p Buf. Returns the number
+/// of bytes actually read. On Unix, this is equivalent to `return ::read(FD,
+/// Buf.data(), Buf.size())`, with error reporting. Returns 0 when reaching EOF.
///
/// @param FileHandle File to read from.
/// @param Buf Buffer to read into.
-/// @param BytesRead Output parameter of the number of bytes read.
-/// @returns The error, if any, or errc::success.
-std::error_code readNativeFile(file_t FileHandle, MutableArrayRef<char> Buf,
- size_t *BytesRead);
+/// @returns The number of bytes read, or error.
+Expected<size_t> readNativeFile(file_t FileHandle, MutableArrayRef<char> Buf);
/// Reads \p Buf.size() bytes from \p FileHandle at offset \p Offset into \p
/// Buf. If 'pread' is available, this will use that, otherwise it will use
-/// 'lseek'. Bytes requested beyond the end of the file will be zero
-/// initialized.
+/// 'lseek'. Returns the number of bytes actually read. Returns 0 when reaching
+/// EOF.
///
/// @param FileHandle File to read from.
/// @param Buf Buffer to read into.
/// @param Offset Offset into the file at which the read should occur.
-/// @returns The error, if any, or errc::success.
-std::error_code readNativeFileSlice(file_t FileHandle,
- MutableArrayRef<char> Buf, size_t Offset);
+/// @returns The number of bytes read, or error.
+Expected<size_t> readNativeFileSlice(file_t FileHandle,
+ MutableArrayRef<char> Buf,
+ uint64_t Offset);
/// @brief Opens the file with the given name in a write-only or read-write
/// mode, returning its open file descriptor. If the file does not exist, it
@@ -1217,9 +1215,9 @@ class directory_entry {
// that whole structure, callers end up paying for a stat().
// std::filesystem::directory_entry may be a better model.
std::string Path;
- file_type Type; // Most platforms can provide this.
- bool FollowSymlinks; // Affects the behavior of status().
- basic_file_status Status; // If available.
+ file_type Type = file_type::type_unknown; // Most platforms can provide this.
+ bool FollowSymlinks = true; // Affects the behavior of status().
+ basic_file_status Status; // If available.
public:
explicit directory_entry(const Twine &Path, bool FollowSymlinks = true,
diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h
index 16b2206924c3..04efdced32a4 100644
--- a/include/llvm/Support/FileUtilities.h
+++ b/include/llvm/Support/FileUtilities.h
@@ -14,6 +14,9 @@
#ifndef LLVM_SUPPORT_FILEUTILITIES_H
#define LLVM_SUPPORT_FILEUTILITIES_H
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -72,6 +75,41 @@ namespace llvm {
/// will not be removed when the object is destroyed.
void releaseFile() { DeleteIt = false; }
};
+
+ enum class atomic_write_error {
+ failed_to_create_uniq_file = 0,
+ output_stream_error,
+ failed_to_rename_temp_file
+ };
+
+ class AtomicFileWriteError : public llvm::ErrorInfo<AtomicFileWriteError> {
+ public:
+ AtomicFileWriteError(atomic_write_error Error) : Error(Error) {}
+
+ void log(raw_ostream &OS) const override;
+
+ const atomic_write_error Error;
+ static char ID;
+
+ private:
+ // Users are not expected to use error_code.
+ std::error_code convertToErrorCode() const override {
+ return llvm::inconvertibleErrorCode();
+ }
+ };
+
+ // atomic_write_error + whatever the Writer can return
+
+ /// Creates a unique file with name according to the given \p TempPathModel,
+ /// writes content of \p Buffer to the file and renames it to \p FinalPath.
+ ///
+ /// \returns \c AtomicFileWriteError in case of error.
+ llvm::Error writeFileAtomically(StringRef TempPathModel, StringRef FinalPath,
+ StringRef Buffer);
+
+ llvm::Error
+ writeFileAtomically(StringRef TempPathModel, StringRef FinalPath,
+ std::function<llvm::Error(llvm::raw_ostream &)> Writer);
} // End llvm namespace
#endif
diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h
index 77dcbaebf1a3..9dd7b401b46a 100644
--- a/include/llvm/Support/Format.h
+++ b/include/llvm/Support/Format.h
@@ -29,6 +29,7 @@
#include <cassert>
#include <cstdio>
#include <tuple>
+#include <utility>
namespace llvm {
@@ -91,7 +92,7 @@ class format_object final : public format_object_base {
template <std::size_t... Is>
int snprint_tuple(char *Buffer, unsigned BufferSize,
- index_sequence<Is...>) const {
+ std::index_sequence<Is...>) const {
#ifdef _MSC_VER
return _snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
#else
@@ -106,7 +107,7 @@ public:
}
int snprint(char *Buffer, unsigned BufferSize) const override {
- return snprint_tuple(Buffer, BufferSize, index_sequence_for<Ts...>());
+ return snprint_tuple(Buffer, BufferSize, std::index_sequence_for<Ts...>());
}
};
diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h
index 99620802505b..9169379f746d 100644
--- a/include/llvm/Support/GenericDomTree.h
+++ b/include/llvm/Support/GenericDomTree.h
@@ -242,7 +242,7 @@ protected:
using DomTreeNodeMapType =
DenseMap<NodeT *, std::unique_ptr<DomTreeNodeBase<NodeT>>>;
DomTreeNodeMapType DomTreeNodes;
- DomTreeNodeBase<NodeT> *RootNode;
+ DomTreeNodeBase<NodeT> *RootNode = nullptr;
ParentPtr Parent = nullptr;
mutable bool DFSInfoValid = false;
@@ -571,7 +571,7 @@ protected:
assert(IDomNode && "Not immediate dominator specified for block!");
DFSInfoValid = false;
return (DomTreeNodes[BB] = IDomNode->addChild(
- llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get();
+ std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get();
}
/// Add a new node to the forward dominator tree and make it a new root.
@@ -585,7 +585,7 @@ protected:
"Cannot change root of post-dominator tree");
DFSInfoValid = false;
DomTreeNodeBase<NodeT> *NewNode = (DomTreeNodes[BB] =
- llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, nullptr)).get();
+ std::make_unique<DomTreeNodeBase<NodeT>>(BB, nullptr)).get();
if (Roots.empty()) {
addRoot(BB);
} else {
diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h
index ccceba881718..7c0278e8770e 100644
--- a/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/include/llvm/Support/GenericDomTreeConstruction.h
@@ -186,7 +186,7 @@ struct SemiNCAInfo {
// Add a new tree node for this NodeT, and link it as a child of
// IDomNode
return (DT.DomTreeNodes[BB] = IDomNode->addChild(
- llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode)))
+ std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode)))
.get();
}
@@ -586,7 +586,7 @@ struct SemiNCAInfo {
NodePtr Root = IsPostDom ? nullptr : DT.Roots[0];
DT.RootNode = (DT.DomTreeNodes[Root] =
- llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr))
+ std::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr))
.get();
SNCA.attachNewSubtree(DT, DT.RootNode);
}
@@ -611,7 +611,7 @@ struct SemiNCAInfo {
// Add a new tree node for this BasicBlock, and link it as a child of
// IDomNode.
DT.DomTreeNodes[W] = IDomNode->addChild(
- llvm::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode));
+ std::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode));
}
}
@@ -663,7 +663,7 @@ struct SemiNCAInfo {
TreeNodePtr VirtualRoot = DT.getNode(nullptr);
FromTN =
(DT.DomTreeNodes[From] = VirtualRoot->addChild(
- llvm::make_unique<DomTreeNodeBase<NodeT>>(From, VirtualRoot)))
+ std::make_unique<DomTreeNodeBase<NodeT>>(From, VirtualRoot)))
.get();
DT.Roots.push_back(From);
}
diff --git a/include/llvm/Support/GlobPattern.h b/include/llvm/Support/GlobPattern.h
index 66a4cd94c12a..0098ac65fd30 100644
--- a/include/llvm/Support/GlobPattern.h
+++ b/include/llvm/Support/GlobPattern.h
@@ -21,7 +21,7 @@
#include <vector>
// This class represents a glob pattern. Supported metacharacters
-// are "*", "?", "[<chars>]" and "[^<chars>]".
+// are "*", "?", "\", "[<chars>]", "[^<chars>]", and "[!<chars>]".
namespace llvm {
class BitVector;
template <typename T> class ArrayRef;
diff --git a/include/llvm/Support/Host.h b/include/llvm/Support/Host.h
index b37cc514c92e..44f543c363db 100644
--- a/include/llvm/Support/Host.h
+++ b/include/llvm/Support/Host.h
@@ -15,39 +15,11 @@
#include "llvm/ADT/StringMap.h"
-#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__)
-#include <endian.h>
-#elif defined(_AIX)
-#include <sys/machine.h>
-#elif defined(__sun)
-/* Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h */
-#include <sys/types.h>
-#define BIG_ENDIAN 4321
-#define LITTLE_ENDIAN 1234
-#if defined(_BIG_ENDIAN)
-#define BYTE_ORDER BIG_ENDIAN
-#else
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-#else
-#if !defined(BYTE_ORDER) && !defined(_WIN32)
-#include <machine/endian.h>
-#endif
-#endif
-
#include <string>
namespace llvm {
namespace sys {
-#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
-constexpr bool IsBigEndianHost = true;
-#else
-constexpr bool IsBigEndianHost = false;
-#endif
-
- static const bool IsLittleEndianHost = !IsBigEndianHost;
-
/// getDefaultTargetTriple() - Return the default target triple the compiler
/// has been configured to produce code for.
///
diff --git a/include/llvm/Support/JamCRC.h b/include/llvm/Support/JamCRC.h
deleted file mode 100644
index b6fc4e7b9b03..000000000000
--- a/include/llvm/Support/JamCRC.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//===-- llvm/Support/JamCRC.h - Cyclic Redundancy Check ---------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains an implementation of JamCRC.
-//
-// We will use the "Rocksoft^tm Model CRC Algorithm" to describe the properties
-// of this CRC:
-// Width : 32
-// Poly : 04C11DB7
-// Init : FFFFFFFF
-// RefIn : True
-// RefOut : True
-// XorOut : 00000000
-// Check : 340BC6D9 (result of CRC for "123456789")
-//
-// N.B. We permit flexibility of the "Init" value. Some consumers of this need
-// it to be zero.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_JAMCRC_H
-#define LLVM_SUPPORT_JAMCRC_H
-
-#include "llvm/Support/DataTypes.h"
-
-namespace llvm {
-template <typename T> class ArrayRef;
-
-class JamCRC {
-public:
- JamCRC(uint32_t Init = 0xFFFFFFFFU) : CRC(Init) {}
-
- // Update the CRC calculation with Data.
- void update(ArrayRef<char> Data);
-
- uint32_t getCRC() const { return CRC; }
-
-private:
- uint32_t CRC;
-};
-} // End of namespace llvm
-
-#endif
diff --git a/include/llvm/Support/MachineValueType.h b/include/llvm/Support/MachineValueType.h
index b94d2c4836cc..7f9f0b85c55e 100644
--- a/include/llvm/Support/MachineValueType.h
+++ b/include/llvm/Support/MachineValueType.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/TypeSize.h"
#include <cassert>
namespace llvm {
@@ -64,152 +65,162 @@ namespace llvm {
v32i1 = 19, // 32 x i1
v64i1 = 20, // 64 x i1
v128i1 = 21, // 128 x i1
- v512i1 = 22, // 512 x i1
- v1024i1 = 23, // 1024 x i1
-
- v1i8 = 24, // 1 x i8
- v2i8 = 25, // 2 x i8
- v4i8 = 26, // 4 x i8
- v8i8 = 27, // 8 x i8
- v16i8 = 28, // 16 x i8
- v32i8 = 29, // 32 x i8
- v64i8 = 30, // 64 x i8
- v128i8 = 31, //128 x i8
- v256i8 = 32, //256 x i8
-
- v1i16 = 33, // 1 x i16
- v2i16 = 34, // 2 x i16
- v4i16 = 35, // 4 x i16
- v8i16 = 36, // 8 x i16
- v16i16 = 37, // 16 x i16
- v32i16 = 38, // 32 x i16
- v64i16 = 39, // 64 x i16
- v128i16 = 40, //128 x i16
-
- v1i32 = 41, // 1 x i32
- v2i32 = 42, // 2 x i32
- v3i32 = 43, // 3 x i32
- v4i32 = 44, // 4 x i32
- v5i32 = 45, // 5 x i32
- v8i32 = 46, // 8 x i32
- v16i32 = 47, // 16 x i32
- v32i32 = 48, // 32 x i32
- v64i32 = 49, // 64 x i32
- v128i32 = 50, // 128 x i32
- v256i32 = 51, // 256 x i32
- v512i32 = 52, // 512 x i32
- v1024i32 = 53, // 1024 x i32
- v2048i32 = 54, // 2048 x i32
-
- v1i64 = 55, // 1 x i64
- v2i64 = 56, // 2 x i64
- v4i64 = 57, // 4 x i64
- v8i64 = 58, // 8 x i64
- v16i64 = 59, // 16 x i64
- v32i64 = 60, // 32 x i64
-
- v1i128 = 61, // 1 x i128
-
- // Scalable integer types
- nxv1i1 = 62, // n x 1 x i1
- nxv2i1 = 63, // n x 2 x i1
- nxv4i1 = 64, // n x 4 x i1
- nxv8i1 = 65, // n x 8 x i1
- nxv16i1 = 66, // n x 16 x i1
- nxv32i1 = 67, // n x 32 x i1
-
- nxv1i8 = 68, // n x 1 x i8
- nxv2i8 = 69, // n x 2 x i8
- nxv4i8 = 70, // n x 4 x i8
- nxv8i8 = 71, // n x 8 x i8
- nxv16i8 = 72, // n x 16 x i8
- nxv32i8 = 73, // n x 32 x i8
-
- nxv1i16 = 74, // n x 1 x i16
- nxv2i16 = 75, // n x 2 x i16
- nxv4i16 = 76, // n x 4 x i16
- nxv8i16 = 77, // n x 8 x i16
- nxv16i16 = 78, // n x 16 x i16
- nxv32i16 = 79, // n x 32 x i16
-
- nxv1i32 = 80, // n x 1 x i32
- nxv2i32 = 81, // n x 2 x i32
- nxv4i32 = 82, // n x 4 x i32
- nxv8i32 = 83, // n x 8 x i32
- nxv16i32 = 84, // n x 16 x i32
- nxv32i32 = 85, // n x 32 x i32
-
- nxv1i64 = 86, // n x 1 x i64
- nxv2i64 = 87, // n x 2 x i64
- nxv4i64 = 88, // n x 4 x i64
- nxv8i64 = 89, // n x 8 x i64
- nxv16i64 = 90, // n x 16 x i64
- nxv32i64 = 91, // n x 32 x i64
-
- FIRST_INTEGER_VECTOR_VALUETYPE = v1i1,
- LAST_INTEGER_VECTOR_VALUETYPE = nxv32i64,
-
- FIRST_INTEGER_SCALABLE_VALUETYPE = nxv1i1,
- LAST_INTEGER_SCALABLE_VALUETYPE = nxv32i64,
-
- v2f16 = 92, // 2 x f16
- v4f16 = 93, // 4 x f16
- v8f16 = 94, // 8 x f16
- v1f32 = 95, // 1 x f32
- v2f32 = 96, // 2 x f32
- v3f32 = 97, // 3 x f32
- v4f32 = 98, // 4 x f32
- v5f32 = 99, // 5 x f32
- v8f32 = 100, // 8 x f32
- v16f32 = 101, // 16 x f32
- v32f32 = 102, // 32 x f32
- v64f32 = 103, // 64 x f32
- v128f32 = 104, // 128 x f32
- v256f32 = 105, // 256 x f32
- v512f32 = 106, // 512 x f32
- v1024f32 = 107, // 1024 x f32
- v2048f32 = 108, // 2048 x f32
- v1f64 = 109, // 1 x f64
- v2f64 = 110, // 2 x f64
- v4f64 = 111, // 4 x f64
- v8f64 = 112, // 8 x f64
-
- nxv2f16 = 113, // n x 2 x f16
- nxv4f16 = 114, // n x 4 x f16
- nxv8f16 = 115, // n x 8 x f16
- nxv1f32 = 116, // n x 1 x f32
- nxv2f32 = 117, // n x 2 x f32
- nxv4f32 = 118, // n x 4 x f32
- nxv8f32 = 119, // n x 8 x f32
- nxv16f32 = 120, // n x 16 x f32
- nxv1f64 = 121, // n x 1 x f64
- nxv2f64 = 122, // n x 2 x f64
- nxv4f64 = 123, // n x 4 x f64
- nxv8f64 = 124, // n x 8 x f64
-
- FIRST_FP_VECTOR_VALUETYPE = v2f16,
- LAST_FP_VECTOR_VALUETYPE = nxv8f64,
-
- FIRST_FP_SCALABLE_VALUETYPE = nxv2f16,
- LAST_FP_SCALABLE_VALUETYPE = nxv8f64,
+ v256i1 = 22, // 256 x i1
+ v512i1 = 23, // 512 x i1
+ v1024i1 = 24, // 1024 x i1
+
+ v1i8 = 25, // 1 x i8
+ v2i8 = 26, // 2 x i8
+ v4i8 = 27, // 4 x i8
+ v8i8 = 28, // 8 x i8
+ v16i8 = 29, // 16 x i8
+ v32i8 = 30, // 32 x i8
+ v64i8 = 31, // 64 x i8
+ v128i8 = 32, //128 x i8
+ v256i8 = 33, //256 x i8
+
+ v1i16 = 34, // 1 x i16
+ v2i16 = 35, // 2 x i16
+ v3i16 = 36, // 3 x i16
+ v4i16 = 37, // 4 x i16
+ v8i16 = 38, // 8 x i16
+ v16i16 = 39, // 16 x i16
+ v32i16 = 40, // 32 x i16
+ v64i16 = 41, // 64 x i16
+ v128i16 = 42, //128 x i16
+
+ v1i32 = 43, // 1 x i32
+ v2i32 = 44, // 2 x i32
+ v3i32 = 45, // 3 x i32
+ v4i32 = 46, // 4 x i32
+ v5i32 = 47, // 5 x i32
+ v8i32 = 48, // 8 x i32
+ v16i32 = 49, // 16 x i32
+ v32i32 = 50, // 32 x i32
+ v64i32 = 51, // 64 x i32
+ v128i32 = 52, // 128 x i32
+ v256i32 = 53, // 256 x i32
+ v512i32 = 54, // 512 x i32
+ v1024i32 = 55, // 1024 x i32
+ v2048i32 = 56, // 2048 x i32
+
+ v1i64 = 57, // 1 x i64
+ v2i64 = 58, // 2 x i64
+ v4i64 = 59, // 4 x i64
+ v8i64 = 60, // 8 x i64
+ v16i64 = 61, // 16 x i64
+ v32i64 = 62, // 32 x i64
+
+ v1i128 = 63, // 1 x i128
+
+ FIRST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE = v1i1,
+ LAST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE = v1i128,
+
+ v2f16 = 64, // 2 x f16
+ v3f16 = 65, // 3 x f16
+ v4f16 = 66, // 4 x f16
+ v8f16 = 67, // 8 x f16
+ v16f16 = 68, // 16 x f16
+ v32f16 = 69, // 32 x f16
+ v1f32 = 70, // 1 x f32
+ v2f32 = 71, // 2 x f32
+ v3f32 = 72, // 3 x f32
+ v4f32 = 73, // 4 x f32
+ v5f32 = 74, // 5 x f32
+ v8f32 = 75, // 8 x f32
+ v16f32 = 76, // 16 x f32
+ v32f32 = 77, // 32 x f32
+ v64f32 = 78, // 64 x f32
+ v128f32 = 79, // 128 x f32
+ v256f32 = 80, // 256 x f32
+ v512f32 = 81, // 512 x f32
+ v1024f32 = 82, // 1024 x f32
+ v2048f32 = 83, // 2048 x f32
+ v1f64 = 84, // 1 x f64
+ v2f64 = 85, // 2 x f64
+ v4f64 = 86, // 4 x f64
+ v8f64 = 87, // 8 x f64
+
+ FIRST_FP_FIXEDLEN_VECTOR_VALUETYPE = v2f16,
+ LAST_FP_FIXEDLEN_VECTOR_VALUETYPE = v8f64,
+
+ FIRST_FIXEDLEN_VECTOR_VALUETYPE = v1i1,
+ LAST_FIXEDLEN_VECTOR_VALUETYPE = v8f64,
+
+ nxv1i1 = 88, // n x 1 x i1
+ nxv2i1 = 89, // n x 2 x i1
+ nxv4i1 = 90, // n x 4 x i1
+ nxv8i1 = 91, // n x 8 x i1
+ nxv16i1 = 92, // n x 16 x i1
+ nxv32i1 = 93, // n x 32 x i1
+
+ nxv1i8 = 94, // n x 1 x i8
+ nxv2i8 = 95, // n x 2 x i8
+ nxv4i8 = 96, // n x 4 x i8
+ nxv8i8 = 97, // n x 8 x i8
+ nxv16i8 = 98, // n x 16 x i8
+ nxv32i8 = 99, // n x 32 x i8
+
+ nxv1i16 = 100, // n x 1 x i16
+ nxv2i16 = 101, // n x 2 x i16
+ nxv4i16 = 102, // n x 4 x i16
+ nxv8i16 = 103, // n x 8 x i16
+ nxv16i16 = 104, // n x 16 x i16
+ nxv32i16 = 105, // n x 32 x i16
+
+ nxv1i32 = 106, // n x 1 x i32
+ nxv2i32 = 107, // n x 2 x i32
+ nxv4i32 = 108, // n x 4 x i32
+ nxv8i32 = 109, // n x 8 x i32
+ nxv16i32 = 110, // n x 16 x i32
+ nxv32i32 = 111, // n x 32 x i32
+
+ nxv1i64 = 112, // n x 1 x i64
+ nxv2i64 = 113, // n x 2 x i64
+ nxv4i64 = 114, // n x 4 x i64
+ nxv8i64 = 115, // n x 8 x i64
+ nxv16i64 = 116, // n x 16 x i64
+ nxv32i64 = 117, // n x 32 x i64
+
+ FIRST_INTEGER_SCALABLE_VECTOR_VALUETYPE = nxv1i1,
+ LAST_INTEGER_SCALABLE_VECTOR_VALUETYPE = nxv32i64,
+
+ nxv2f16 = 118, // n x 2 x f16
+ nxv4f16 = 119, // n x 4 x f16
+ nxv8f16 = 120, // n x 8 x f16
+ nxv1f32 = 121, // n x 1 x f32
+ nxv2f32 = 122, // n x 2 x f32
+ nxv4f32 = 123, // n x 4 x f32
+ nxv8f32 = 124, // n x 8 x f32
+ nxv16f32 = 125, // n x 16 x f32
+ nxv1f64 = 126, // n x 1 x f64
+ nxv2f64 = 127, // n x 2 x f64
+ nxv4f64 = 128, // n x 4 x f64
+ nxv8f64 = 129, // n x 8 x f64
+
+ FIRST_FP_SCALABLE_VECTOR_VALUETYPE = nxv2f16,
+ LAST_FP_SCALABLE_VECTOR_VALUETYPE = nxv8f64,
+
+ FIRST_SCALABLE_VECTOR_VALUETYPE = nxv1i1,
+ LAST_SCALABLE_VECTOR_VALUETYPE = nxv8f64,
FIRST_VECTOR_VALUETYPE = v1i1,
LAST_VECTOR_VALUETYPE = nxv8f64,
- x86mmx = 125, // This is an X86 MMX value
+ x86mmx = 130, // This is an X86 MMX value
- Glue = 126, // This glues nodes together during pre-RA sched
+ Glue = 131, // This glues nodes together during pre-RA sched
- isVoid = 127, // This has no value
+ isVoid = 132, // This has no value
- Untyped = 128, // This value takes a register, but has
+ Untyped = 133, // This value takes a register, but has
// unspecified type. The register class
// will be determined by the opcode.
- exnref = 129, // WebAssembly's exnref type
+ exnref = 134, // WebAssembly's exnref type
FIRST_VALUETYPE = 1, // This is always the beginning of the list.
- LAST_VALUETYPE = 130, // This always remains at the end of the list.
+ LAST_VALUETYPE = 135, // This always remains at the end of the list.
// This is the current maximum for LAST_VALUETYPE.
// MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors
@@ -253,41 +264,6 @@ namespace llvm {
SimpleValueType SimpleTy = INVALID_SIMPLE_VALUE_TYPE;
- // A class to represent the number of elements in a vector
- //
- // For fixed-length vectors, the total number of elements is equal to 'Min'
- // For scalable vectors, the total number of elements is a multiple of 'Min'
- class ElementCount {
- public:
- unsigned Min;
- bool Scalable;
-
- ElementCount(unsigned Min, bool Scalable)
- : Min(Min), Scalable(Scalable) {}
-
- ElementCount operator*(unsigned RHS) {
- return { Min * RHS, Scalable };
- }
-
- ElementCount& operator*=(unsigned RHS) {
- Min *= RHS;
- return *this;
- }
-
- ElementCount operator/(unsigned RHS) {
- return { Min / RHS, Scalable };
- }
-
- ElementCount& operator/=(unsigned RHS) {
- Min /= RHS;
- return *this;
- }
-
- bool operator==(const ElementCount& RHS) {
- return Min == RHS.Min && Scalable == RHS.Scalable;
- }
- };
-
constexpr MVT() = default;
constexpr MVT(SimpleValueType SVT) : SimpleTy(SVT) {}
@@ -308,16 +284,20 @@ namespace llvm {
bool isFloatingPoint() const {
return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE &&
SimpleTy <= MVT::LAST_FP_VALUETYPE) ||
- (SimpleTy >= MVT::FIRST_FP_VECTOR_VALUETYPE &&
- SimpleTy <= MVT::LAST_FP_VECTOR_VALUETYPE));
+ (SimpleTy >= MVT::FIRST_FP_FIXEDLEN_VECTOR_VALUETYPE &&
+ SimpleTy <= MVT::LAST_FP_FIXEDLEN_VECTOR_VALUETYPE) ||
+ (SimpleTy >= MVT::FIRST_FP_SCALABLE_VECTOR_VALUETYPE &&
+ SimpleTy <= MVT::LAST_FP_SCALABLE_VECTOR_VALUETYPE));
}
/// Return true if this is an integer or a vector integer type.
bool isInteger() const {
return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE &&
SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) ||
- (SimpleTy >= MVT::FIRST_INTEGER_VECTOR_VALUETYPE &&
- SimpleTy <= MVT::LAST_INTEGER_VECTOR_VALUETYPE));
+ (SimpleTy >= MVT::FIRST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE &&
+ SimpleTy <= MVT::LAST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE) ||
+ (SimpleTy >= MVT::FIRST_INTEGER_SCALABLE_VECTOR_VALUETYPE &&
+ SimpleTy <= MVT::LAST_INTEGER_SCALABLE_VECTOR_VALUETYPE));
}
/// Return true if this is an integer, not including vectors.
@@ -335,10 +315,13 @@ namespace llvm {
/// Return true if this is a vector value type where the
/// runtime length is machine dependent
bool isScalableVector() const {
- return ((SimpleTy >= MVT::FIRST_INTEGER_SCALABLE_VALUETYPE &&
- SimpleTy <= MVT::LAST_INTEGER_SCALABLE_VALUETYPE) ||
- (SimpleTy >= MVT::FIRST_FP_SCALABLE_VALUETYPE &&
- SimpleTy <= MVT::LAST_FP_SCALABLE_VALUETYPE));
+ return (SimpleTy >= MVT::FIRST_SCALABLE_VECTOR_VALUETYPE &&
+ SimpleTy <= MVT::LAST_SCALABLE_VECTOR_VALUETYPE);
+ }
+
+ bool isFixedLengthVector() const {
+ return (SimpleTy >= MVT::FIRST_FIXEDLEN_VECTOR_VALUETYPE &&
+ SimpleTy <= MVT::LAST_FIXEDLEN_VECTOR_VALUETYPE);
}
/// Return true if this is a 16-bit vector type.
@@ -373,17 +356,18 @@ namespace llvm {
/// Return true if this is a 256-bit vector type.
bool is256BitVector() const {
- return (SimpleTy == MVT::v8f32 || SimpleTy == MVT::v4f64 ||
- SimpleTy == MVT::v32i8 || SimpleTy == MVT::v16i16 ||
- SimpleTy == MVT::v8i32 || SimpleTy == MVT::v4i64);
+ return (SimpleTy == MVT::v16f16 || SimpleTy == MVT::v8f32 ||
+ SimpleTy == MVT::v4f64 || SimpleTy == MVT::v32i8 ||
+ SimpleTy == MVT::v16i16 || SimpleTy == MVT::v8i32 ||
+ SimpleTy == MVT::v4i64 || SimpleTy == MVT::v256i1);
}
/// Return true if this is a 512-bit vector type.
bool is512BitVector() const {
- return (SimpleTy == MVT::v16f32 || SimpleTy == MVT::v8f64 ||
- SimpleTy == MVT::v512i1 || SimpleTy == MVT::v64i8 ||
- SimpleTy == MVT::v32i16 || SimpleTy == MVT::v16i32 ||
- SimpleTy == MVT::v8i64);
+ return (SimpleTy == MVT::v32f16 || SimpleTy == MVT::v16f32 ||
+ SimpleTy == MVT::v8f64 || SimpleTy == MVT::v512i1 ||
+ SimpleTy == MVT::v64i8 || SimpleTy == MVT::v32i16 ||
+ SimpleTy == MVT::v16i32 || SimpleTy == MVT::v8i64);
}
/// Return true if this is a 1024-bit vector type.
@@ -406,6 +390,15 @@ namespace llvm {
SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny);
}
+ /// Return a VT for a vector type with the same element type but
+ /// half the number of elements.
+ MVT getHalfNumVectorElementsVT() const {
+ MVT EltVT = getVectorElementType();
+ auto EltCnt = getVectorElementCount();
+ assert(!(EltCnt.Min & 1) && "Splitting vector, but not in half!");
+ return getVectorVT(EltVT, EltCnt / 2);
+ }
+
/// Returns true if the given vector is a power of 2.
bool isPow2VectorType() const {
unsigned NElts = getVectorNumElements();
@@ -440,6 +433,7 @@ namespace llvm {
case v32i1:
case v64i1:
case v128i1:
+ case v256i1:
case v512i1:
case v1024i1:
case nxv1i1:
@@ -465,6 +459,7 @@ namespace llvm {
case nxv32i8: return i8;
case v1i16:
case v2i16:
+ case v3i16:
case v4i16:
case v8i16:
case v16i16:
@@ -511,8 +506,11 @@ namespace llvm {
case nxv32i64: return i64;
case v1i128: return i128;
case v2f16:
+ case v3f16:
case v4f16:
case v8f16:
+ case v16f16:
+ case v32f16:
case nxv2f16:
case nxv4f16:
case nxv8f16: return f16;
@@ -558,6 +556,7 @@ namespace llvm {
case v512i1:
case v512i32:
case v512f32: return 512;
+ case v256i1:
case v256i8:
case v256i32:
case v256f32: return 256;
@@ -576,6 +575,7 @@ namespace llvm {
case v32i16:
case v32i32:
case v32i64:
+ case v32f16:
case v32f32:
case nxv32i1:
case nxv32i8:
@@ -587,6 +587,7 @@ namespace llvm {
case v16i16:
case v16i32:
case v16i64:
+ case v16f16:
case v16f32:
case nxv16i1:
case nxv16i8:
@@ -628,7 +629,9 @@ namespace llvm {
case nxv4f16:
case nxv4f32:
case nxv4f64: return 4;
+ case v3i16:
case v3i32:
+ case v3f16:
case v3f32: return 3;
case v2i1:
case v2i8:
@@ -664,7 +667,7 @@ namespace llvm {
}
}
- MVT::ElementCount getVectorElementCount() const {
+ ElementCount getVectorElementCount() const {
return { getVectorNumElements(), isScalableVector() };
}
@@ -721,6 +724,8 @@ namespace llvm {
case nxv1i32:
case nxv2f16:
case nxv1f32: return 32;
+ case v3i16:
+ case v3f16: return 48;
case x86mmx:
case f64 :
case i64 :
@@ -763,10 +768,12 @@ namespace llvm {
case nxv2f64: return 128;
case v5i32:
case v5f32: return 160;
+ case v256i1:
case v32i8:
case v16i16:
case v8i32:
case v4i64:
+ case v16f16:
case v8f32:
case v4f64:
case nxv32i8:
@@ -780,6 +787,7 @@ namespace llvm {
case v32i16:
case v16i32:
case v8i64:
+ case v32f16:
case v16f32:
case v8f64:
case nxv32i16:
@@ -900,6 +908,7 @@ namespace llvm {
if (NumElements == 32) return MVT::v32i1;
if (NumElements == 64) return MVT::v64i1;
if (NumElements == 128) return MVT::v128i1;
+ if (NumElements == 256) return MVT::v256i1;
if (NumElements == 512) return MVT::v512i1;
if (NumElements == 1024) return MVT::v1024i1;
break;
@@ -917,6 +926,7 @@ namespace llvm {
case MVT::i16:
if (NumElements == 1) return MVT::v1i16;
if (NumElements == 2) return MVT::v2i16;
+ if (NumElements == 3) return MVT::v3i16;
if (NumElements == 4) return MVT::v4i16;
if (NumElements == 8) return MVT::v8i16;
if (NumElements == 16) return MVT::v16i16;
@@ -953,8 +963,11 @@ namespace llvm {
break;
case MVT::f16:
if (NumElements == 2) return MVT::v2f16;
+ if (NumElements == 3) return MVT::v3f16;
if (NumElements == 4) return MVT::v4f16;
if (NumElements == 8) return MVT::v8f16;
+ if (NumElements == 16) return MVT::v16f16;
+ if (NumElements == 32) return MVT::v32f16;
break;
case MVT::f32:
if (NumElements == 1) return MVT::v1f32;
@@ -1054,7 +1067,7 @@ namespace llvm {
return getVectorVT(VT, NumElements);
}
- static MVT getVectorVT(MVT VT, MVT::ElementCount EC) {
+ static MVT getVectorVT(MVT VT, ElementCount EC) {
if (EC.Scalable)
return getScalableVectorVT(VT, EC.Min);
return getVectorVT(VT, EC.Min);
@@ -1108,26 +1121,40 @@ namespace llvm {
(MVT::SimpleValueType)(MVT::LAST_VECTOR_VALUETYPE + 1));
}
- static mvt_range integer_vector_valuetypes() {
+ static mvt_range fixedlen_vector_valuetypes() {
return mvt_range(
- MVT::FIRST_INTEGER_VECTOR_VALUETYPE,
- (MVT::SimpleValueType)(MVT::LAST_INTEGER_VECTOR_VALUETYPE + 1));
+ MVT::FIRST_FIXEDLEN_VECTOR_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_FIXEDLEN_VECTOR_VALUETYPE + 1));
}
- static mvt_range fp_vector_valuetypes() {
+ static mvt_range scalable_vector_valuetypes() {
return mvt_range(
- MVT::FIRST_FP_VECTOR_VALUETYPE,
- (MVT::SimpleValueType)(MVT::LAST_FP_VECTOR_VALUETYPE + 1));
+ MVT::FIRST_SCALABLE_VECTOR_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_SCALABLE_VECTOR_VALUETYPE + 1));
+ }
+
+ static mvt_range integer_fixedlen_vector_valuetypes() {
+ return mvt_range(
+ MVT::FIRST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE + 1));
+ }
+
+ static mvt_range fp_fixedlen_vector_valuetypes() {
+ return mvt_range(
+ MVT::FIRST_FP_FIXEDLEN_VECTOR_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_FP_FIXEDLEN_VECTOR_VALUETYPE + 1));
}
static mvt_range integer_scalable_vector_valuetypes() {
- return mvt_range(MVT::FIRST_INTEGER_SCALABLE_VALUETYPE,
- (MVT::SimpleValueType)(MVT::LAST_INTEGER_SCALABLE_VALUETYPE + 1));
+ return mvt_range(
+ MVT::FIRST_INTEGER_SCALABLE_VECTOR_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_INTEGER_SCALABLE_VECTOR_VALUETYPE + 1));
}
static mvt_range fp_scalable_vector_valuetypes() {
- return mvt_range(MVT::FIRST_FP_SCALABLE_VALUETYPE,
- (MVT::SimpleValueType)(MVT::LAST_FP_SCALABLE_VALUETYPE + 1));
+ return mvt_range(
+ MVT::FIRST_FP_SCALABLE_VECTOR_VALUETYPE,
+ (MVT::SimpleValueType)(MVT::LAST_FP_SCALABLE_VECTOR_VALUETYPE + 1));
}
/// @}
};
diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h
index 249139e824b5..004a6f5f6eb8 100644
--- a/include/llvm/Support/MathExtras.h
+++ b/include/llvm/Support/MathExtras.h
@@ -39,6 +39,7 @@ unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
#endif
namespace llvm {
+
/// The behavior an operation has on an input of 0.
enum ZeroBehavior {
/// The returned value is undefined.
@@ -49,6 +50,42 @@ enum ZeroBehavior {
ZB_Width
};
+/// Mathematical constants.
+namespace numbers {
+// TODO: Track C++20 std::numbers.
+// TODO: Favor using the hexadecimal FP constants (requires C++17).
+constexpr double e = 2.7182818284590452354, // (0x1.5bf0a8b145749P+1) https://oeis.org/A001113
+ egamma = .57721566490153286061, // (0x1.2788cfc6fb619P-1) https://oeis.org/A001620
+ ln2 = .69314718055994530942, // (0x1.62e42fefa39efP-1) https://oeis.org/A002162
+ ln10 = 2.3025850929940456840, // (0x1.24bb1bbb55516P+1) https://oeis.org/A002392
+ log2e = 1.4426950408889634074, // (0x1.71547652b82feP+0)
+ log10e = .43429448190325182765, // (0x1.bcb7b1526e50eP-2)
+ pi = 3.1415926535897932385, // (0x1.921fb54442d18P+1) https://oeis.org/A000796
+ inv_pi = .31830988618379067154, // (0x1.45f306bc9c883P-2) https://oeis.org/A049541
+ sqrtpi = 1.7724538509055160273, // (0x1.c5bf891b4ef6bP+0) https://oeis.org/A002161
+ inv_sqrtpi = .56418958354775628695, // (0x1.20dd750429b6dP-1) https://oeis.org/A087197
+ sqrt2 = 1.4142135623730950488, // (0x1.6a09e667f3bcdP+0) https://oeis.org/A00219
+ inv_sqrt2 = .70710678118654752440, // (0x1.6a09e667f3bcdP-1)
+ sqrt3 = 1.7320508075688772935, // (0x1.bb67ae8584caaP+0) https://oeis.org/A002194
+ inv_sqrt3 = .57735026918962576451, // (0x1.279a74590331cP-1)
+ phi = 1.6180339887498948482; // (0x1.9e3779b97f4a8P+0) https://oeis.org/A001622
+constexpr float ef = 2.71828183F, // (0x1.5bf0a8P+1) https://oeis.org/A001113
+ egammaf = .577215665F, // (0x1.2788d0P-1) https://oeis.org/A001620
+ ln2f = .693147181F, // (0x1.62e430P-1) https://oeis.org/A002162
+ ln10f = 2.30258509F, // (0x1.26bb1cP+1) https://oeis.org/A002392
+ log2ef = 1.44269504F, // (0x1.715476P+0)
+ log10ef = .434294482F, // (0x1.bcb7b2P-2)
+ pif = 3.14159265F, // (0x1.921fb6P+1) https://oeis.org/A000796
+ inv_pif = .318309886F, // (0x1.45f306P-2) https://oeis.org/A049541
+ sqrtpif = 1.77245385F, // (0x1.c5bf8aP+0) https://oeis.org/A002161
+ inv_sqrtpif = .564189584F, // (0x1.20dd76P-1) https://oeis.org/A087197
+ sqrt2f = 1.41421356F, // (0x1.6a09e6P+0) https://oeis.org/A002193
+ inv_sqrt2f = .707106781F, // (0x1.6a09e6P-1)
+ sqrt3f = 1.73205081F, // (0x1.bb67aeP+0) https://oeis.org/A002194
+ inv_sqrt3f = .577350269F, // (0x1.279a74P-1)
+ phif = 1.61803399F; // (0x1.9e377aP+0) https://oeis.org/A001622
+} // namespace numbers
+
namespace detail {
template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
static unsigned count(T Val, ZeroBehavior) {
@@ -73,13 +110,13 @@ template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
}
};
-#if __GNUC__ >= 4 || defined(_MSC_VER)
+#if defined(__GNUC__) || defined(_MSC_VER)
template <typename T> struct TrailingZerosCounter<T, 4> {
static unsigned count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 32;
-#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0)
+#if __has_builtin(__builtin_ctz) || defined(__GNUC__)
return __builtin_ctz(Val);
#elif defined(_MSC_VER)
unsigned long Index;
@@ -95,7 +132,7 @@ template <typename T> struct TrailingZerosCounter<T, 8> {
if (ZB != ZB_Undefined && Val == 0)
return 64;
-#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0)
+#if __has_builtin(__builtin_ctzll) || defined(__GNUC__)
return __builtin_ctzll(Val);
#elif defined(_MSC_VER)
unsigned long Index;
@@ -142,13 +179,13 @@ template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
}
};
-#if __GNUC__ >= 4 || defined(_MSC_VER)
+#if defined(__GNUC__) || defined(_MSC_VER)
template <typename T> struct LeadingZerosCounter<T, 4> {
static unsigned count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 32;
-#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0)
+#if __has_builtin(__builtin_clz) || defined(__GNUC__)
return __builtin_clz(Val);
#elif defined(_MSC_VER)
unsigned long Index;
@@ -164,7 +201,7 @@ template <typename T> struct LeadingZerosCounter<T, 8> {
if (ZB != ZB_Undefined && Val == 0)
return 64;
-#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0)
+#if __has_builtin(__builtin_clzll) || defined(__GNUC__)
return __builtin_clzll(Val);
#elif defined(_MSC_VER)
unsigned long Index;
@@ -486,7 +523,7 @@ template <typename T, std::size_t SizeOfT> struct PopulationCounter {
static unsigned count(T Value) {
// Generic version, forward to 32 bits.
static_assert(SizeOfT <= 4, "Not implemented!");
-#if __GNUC__ >= 4
+#if defined(__GNUC__)
return __builtin_popcount(Value);
#else
uint32_t v = Value;
@@ -499,7 +536,7 @@ template <typename T, std::size_t SizeOfT> struct PopulationCounter {
template <typename T> struct PopulationCounter<T, 8> {
static unsigned count(T Value) {
-#if __GNUC__ >= 4
+#if defined(__GNUC__)
return __builtin_popcountll(Value);
#else
uint64_t v = Value;
@@ -523,6 +560,16 @@ inline unsigned countPopulation(T Value) {
return detail::PopulationCounter<T, sizeof(T)>::count(Value);
}
+/// Compile time Log2.
+/// Valid only for positive powers of two.
+template <size_t kValue> constexpr inline size_t CTLog2() {
+ static_assert(kValue > 0 && llvm::isPowerOf2_64(kValue),
+ "Value is not a valid power of 2");
+ return 1 + CTLog2<kValue / 2>();
+}
+
+template <> constexpr inline size_t CTLog2<1>() { return 0; }
+
/// Return the log base 2 of the specified value.
inline double Log2(double Value) {
#if defined(__ANDROID_API__) && __ANDROID_API__ < 18
@@ -620,25 +667,6 @@ constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) {
return (A | B) & (1 + ~(A | B));
}
-/// Aligns \c Addr to \c Alignment bytes, rounding up.
-///
-/// Alignment should be a power of two. This method rounds up, so
-/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8.
-inline uintptr_t alignAddr(const void *Addr, size_t Alignment) {
- assert(Alignment && isPowerOf2_64((uint64_t)Alignment) &&
- "Alignment is not a power of two!");
-
- assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr);
-
- return (((uintptr_t)Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1));
-}
-
-/// Returns the necessary adjustment for aligning \c Ptr to \c Alignment
-/// bytes, rounding up.
-inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) {
- return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr;
-}
-
/// Returns the next power of two (in 64-bits) that is strictly greater than A.
/// Returns zero on overflow.
inline uint64_t NextPowerOf2(uint64_t A) {
@@ -704,19 +732,6 @@ inline uint64_t divideCeil(uint64_t Numerator, uint64_t Denominator) {
return alignTo(Numerator, Denominator) / Denominator;
}
-/// \c alignTo for contexts where a constant expression is required.
-/// \sa alignTo
-///
-/// \todo FIXME: remove when \c constexpr becomes really \c constexpr
-template <uint64_t Align>
-struct AlignTo {
- static_assert(Align != 0u, "Align must be non-zero");
- template <uint64_t Value>
- struct from_value {
- static const uint64_t value = (Value + Align - 1) / Align * Align;
- };
-};
-
/// 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) {
@@ -725,13 +740,6 @@ inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
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 alignTo(Value, Align) - Value;
-}
-
/// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
/// Requires 0 < B <= 32.
template <unsigned B> constexpr inline int32_t SignExtend32(uint32_t X) {
@@ -853,6 +861,91 @@ SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
/// Use this rather than HUGE_VALF; the latter causes warnings on MSVC.
extern const float huge_valf;
+
+
+/// Add two signed integers, computing the two's complement truncated result,
+/// returning true if overflow occured.
+template <typename T>
+typename std::enable_if<std::is_signed<T>::value, T>::type
+AddOverflow(T X, T Y, T &Result) {
+#if __has_builtin(__builtin_add_overflow)
+ return __builtin_add_overflow(X, Y, &Result);
+#else
+ // Perform the unsigned addition.
+ using U = typename std::make_unsigned<T>::type;
+ const U UX = static_cast<U>(X);
+ const U UY = static_cast<U>(Y);
+ const U UResult = UX + UY;
+
+ // Convert to signed.
+ Result = static_cast<T>(UResult);
+
+ // Adding two positive numbers should result in a positive number.
+ if (X > 0 && Y > 0)
+ return Result <= 0;
+ // Adding two negatives should result in a negative number.
+ if (X < 0 && Y < 0)
+ return Result >= 0;
+ return false;
+#endif
+}
+
+/// Subtract two signed integers, computing the two's complement truncated
+/// result, returning true if an overflow ocurred.
+template <typename T>
+typename std::enable_if<std::is_signed<T>::value, T>::type
+SubOverflow(T X, T Y, T &Result) {
+#if __has_builtin(__builtin_sub_overflow)
+ return __builtin_sub_overflow(X, Y, &Result);
+#else
+ // Perform the unsigned addition.
+ using U = typename std::make_unsigned<T>::type;
+ const U UX = static_cast<U>(X);
+ const U UY = static_cast<U>(Y);
+ const U UResult = UX - UY;
+
+ // Convert to signed.
+ Result = static_cast<T>(UResult);
+
+ // Subtracting a positive number from a negative results in a negative number.
+ if (X <= 0 && Y > 0)
+ return Result >= 0;
+ // Subtracting a negative number from a positive results in a positive number.
+ if (X >= 0 && Y < 0)
+ return Result <= 0;
+ return false;
+#endif
+}
+
+
+/// Multiply two signed integers, computing the two's complement truncated
+/// result, returning true if an overflow ocurred.
+template <typename T>
+typename std::enable_if<std::is_signed<T>::value, T>::type
+MulOverflow(T X, T Y, T &Result) {
+ // Perform the unsigned multiplication on absolute values.
+ using U = typename std::make_unsigned<T>::type;
+ const U UX = X < 0 ? (0 - static_cast<U>(X)) : static_cast<U>(X);
+ const U UY = Y < 0 ? (0 - static_cast<U>(Y)) : static_cast<U>(Y);
+ const U UResult = UX * UY;
+
+ // Convert to signed.
+ const bool IsNegative = (X < 0) ^ (Y < 0);
+ Result = IsNegative ? (0 - UResult) : UResult;
+
+ // If any of the args was 0, result is 0 and no overflow occurs.
+ if (UX == 0 || UY == 0)
+ return false;
+
+ // UX and UY are in [1, 2^n], where n is the number of digits.
+ // Check how the max allowed absolute value (2^n for negative, 2^(n-1) for
+ // positive) divided by an argument compares to the other.
+ if (IsNegative)
+ return UX > (static_cast<U>(std::numeric_limits<T>::max()) + U(1)) / UY;
+ else
+ return UX > (static_cast<U>(std::numeric_limits<T>::max())) / UY;
+}
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h
index c3abfc7a7806..1d8a0d3c87cb 100644
--- a/include/llvm/Support/Mutex.h
+++ b/include/llvm/Support/Mutex.h
@@ -13,97 +13,31 @@
#ifndef LLVM_SUPPORT_MUTEX_H
#define LLVM_SUPPORT_MUTEX_H
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/Threading.h"
#include <cassert>
+#include <mutex>
namespace llvm
{
namespace sys
{
- /// Platform agnostic Mutex class.
- class MutexImpl
- {
- /// @name Constructors
- /// @{
- public:
-
- /// Initializes the lock but doesn't acquire it. if \p recursive is set
- /// to false, the lock will not be recursive which makes it cheaper but
- /// also more likely to deadlock (same thread can't acquire more than
- /// once).
- /// Default Constructor.
- explicit MutexImpl(bool recursive = true);
-
- /// Releases and removes the lock
- /// Destructor
- ~MutexImpl();
-
- /// @}
- /// @name Methods
- /// @{
- public:
-
- /// Attempts to unconditionally acquire the lock. If the lock is held by
- /// another thread, this method will wait until it can acquire the lock.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally acquire the lock.
- bool acquire();
-
- /// Attempts to release the lock. If the lock is held by the current
- /// thread, the lock is released allowing other threads to acquire the
- /// lock.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally release the lock.
- bool release();
-
- /// Attempts to acquire the lock without blocking. If the lock is not
- /// available, this function returns false quickly (without blocking). If
- /// the lock is available, it is acquired.
- /// @returns false if any kind of error occurs or the lock is not
- /// available, true otherwise.
- /// Try to acquire the lock.
- bool tryacquire();
-
- //@}
- /// @name Platform Dependent Data
- /// @{
- private:
-#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
- void* data_; ///< We don't know what the data will be
-#endif
-
- /// @}
- /// @name Do Not Implement
- /// @{
- private:
- MutexImpl(const MutexImpl &) = delete;
- void operator=(const MutexImpl &) = delete;
- /// @}
- };
-
-
/// SmartMutex - A mutex with a compile time constant parameter that
/// indicates whether this mutex should become a no-op when we're not
/// running in multithreaded mode.
template<bool mt_only>
class SmartMutex {
- MutexImpl impl;
- unsigned acquired;
- bool recursive;
- public:
- explicit SmartMutex(bool rec = true) :
- impl(rec), acquired(0), recursive(rec) { }
+ std::recursive_mutex impl;
+ unsigned acquired = 0;
+ public:
bool lock() {
if (!mt_only || llvm_is_multithreaded()) {
- return impl.acquire();
+ impl.lock();
+ return true;
} else {
// Single-threaded debugging code. This would be racy in
// multithreaded mode, but provides not sanity checks in single
// threaded mode.
- assert((recursive || acquired == 0) && "Lock already acquired!!");
++acquired;
return true;
}
@@ -111,13 +45,13 @@ namespace llvm
bool unlock() {
if (!mt_only || llvm_is_multithreaded()) {
- return impl.release();
+ impl.unlock();
+ return true;
} else {
// Single-threaded debugging code. This would be racy in
// multithreaded mode, but provides not sanity checks in single
// threaded mode.
- assert(((recursive && acquired) || (acquired == 1)) &&
- "Lock not acquired before release!");
+ assert(acquired && "Lock not acquired before release!");
--acquired;
return true;
}
@@ -125,31 +59,16 @@ namespace llvm
bool try_lock() {
if (!mt_only || llvm_is_multithreaded())
- return impl.tryacquire();
+ return impl.try_lock();
else return true;
}
-
- private:
- SmartMutex(const SmartMutex<mt_only> & original);
- void operator=(const SmartMutex<mt_only> &);
};
/// Mutex - A standard, always enforced mutex.
typedef SmartMutex<false> Mutex;
- template<bool mt_only>
- class SmartScopedLock {
- SmartMutex<mt_only>& mtx;
-
- public:
- SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) {
- mtx.lock();
- }
-
- ~SmartScopedLock() {
- mtx.unlock();
- }
- };
+ template <bool mt_only>
+ using SmartScopedLock = std::lock_guard<SmartMutex<mt_only>>;
typedef SmartScopedLock<false> ScopedLock;
}
diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h
deleted file mode 100644
index d86ced145816..000000000000
--- a/include/llvm/Support/MutexGuard.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===-- Support/MutexGuard.h - Acquire/Release Mutex In Scope ---*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a guard for a block of code that ensures a Mutex is locked
-// upon construction and released upon destruction.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_MUTEXGUARD_H
-#define LLVM_SUPPORT_MUTEXGUARD_H
-
-#include "llvm/Support/Mutex.h"
-
-namespace llvm {
- /// Instances of this class acquire a given Mutex Lock when constructed and
- /// hold that lock until destruction. The intention is to instantiate one of
- /// these on the stack at the top of some scope to be assured that C++
- /// destruction of the object will always release the Mutex and thus avoid
- /// a host of nasty multi-threading problems in the face of exceptions, etc.
- /// Guard a section of code with a Mutex.
- class MutexGuard {
- sys::Mutex &M;
- MutexGuard(const MutexGuard &) = delete;
- void operator=(const MutexGuard &) = delete;
- public:
- MutexGuard(sys::Mutex &m) : M(m) { M.lock(); }
- ~MutexGuard() { M.unlock(); }
- /// holds - Returns true if this locker instance holds the specified lock.
- /// This is mostly used in assertions to validate that the correct mutex
- /// is held.
- bool holds(const sys::Mutex& lock) const { return &M == &lock; }
- };
-}
-
-#endif // LLVM_SUPPORT_MUTEXGUARD_H
diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h
index d84da92aab9b..11dc0de0f354 100644
--- a/include/llvm/Support/OnDiskHashTable.h
+++ b/include/llvm/Support/OnDiskHashTable.h
@@ -13,6 +13,7 @@
#ifndef LLVM_SUPPORT_ONDISKHASHTABLE_H
#define LLVM_SUPPORT_ONDISKHASHTABLE_H
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/EndianStream.h"
@@ -207,7 +208,7 @@ public:
// Pad with zeros so that we can start the hashtable at an aligned address.
offset_type TableOff = Out.tell();
- uint64_t N = llvm::OffsetToAlignment(TableOff, alignof(offset_type));
+ uint64_t N = offsetToAlignment(TableOff, Align(alignof(offset_type)));
TableOff += N;
while (N--)
LE.write<uint8_t>(0);
diff --git a/include/llvm/Support/Parallel.h b/include/llvm/Support/Parallel.h
index eab9b492c4a5..3c0ed2c11127 100644
--- a/include/llvm/Support/Parallel.h
+++ b/include/llvm/Support/Parallel.h
@@ -18,14 +18,6 @@
#include <functional>
#include <mutex>
-#if defined(_MSC_VER) && LLVM_ENABLE_THREADS
-#pragma warning(push)
-#pragma warning(disable : 4530)
-#include <concrt.h>
-#include <ppl.h>
-#pragma warning(pop)
-#endif
-
namespace llvm {
namespace parallel {
@@ -84,23 +76,6 @@ public:
void sync() const { L.sync(); }
};
-#if defined(_MSC_VER)
-template <class RandomAccessIterator, class Comparator>
-void parallel_sort(RandomAccessIterator Start, RandomAccessIterator End,
- const Comparator &Comp) {
- concurrency::parallel_sort(Start, End, Comp);
-}
-template <class IterTy, class FuncTy>
-void parallel_for_each(IterTy Begin, IterTy End, FuncTy Fn) {
- concurrency::parallel_for_each(Begin, End, Fn);
-}
-
-template <class IndexTy, class FuncTy>
-void parallel_for_each_n(IndexTy Begin, IndexTy End, FuncTy Fn) {
- concurrency::parallel_for(Begin, End, Fn);
-}
-
-#else
const ptrdiff_t MinParallelSize = 1024;
/// Inclusive median.
@@ -188,8 +163,6 @@ void parallel_for_each_n(IndexTy Begin, IndexTy End, FuncTy Fn) {
#endif
-#endif
-
template <typename Iter>
using DefComparator =
std::less<typename std::iterator_traits<Iter>::value_type>;
diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h
index 9cd57cbd65a1..150bc7dbbce1 100644
--- a/include/llvm/Support/RWMutex.h
+++ b/include/llvm/Support/RWMutex.h
@@ -16,161 +16,184 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Threading.h"
#include <cassert>
+#include <mutex>
+#include <shared_mutex>
+
+// std::shared_timed_mutex is only availble on macOS 10.12 and later.
+#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200
+#define LLVM_USE_RW_MUTEX_IMPL
+#endif
+#endif
namespace llvm {
namespace sys {
- /// Platform agnostic RWMutex class.
- class RWMutexImpl
- {
- /// @name Constructors
- /// @{
- public:
-
- /// Initializes the lock but doesn't acquire it.
- /// Default Constructor.
- explicit RWMutexImpl();
-
- /// @}
- /// @name Do Not Implement
- /// @{
- RWMutexImpl(const RWMutexImpl & original) = delete;
- RWMutexImpl &operator=(const RWMutexImpl &) = delete;
- /// @}
-
- /// Releases and removes the lock
- /// Destructor
- ~RWMutexImpl();
-
- /// @}
- /// @name Methods
- /// @{
- public:
-
- /// Attempts to unconditionally acquire the lock in reader mode. If the
- /// lock is held by a writer, this method will wait until it can acquire
- /// the lock.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally acquire the lock in reader mode.
- bool reader_acquire();
-
- /// Attempts to release the lock in reader mode.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally release the lock in reader mode.
- bool reader_release();
-
- /// Attempts to unconditionally acquire the lock in reader mode. If the
- /// lock is held by any readers, this method will wait until it can
- /// acquire the lock.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally acquire the lock in writer mode.
- bool writer_acquire();
-
- /// Attempts to release the lock in writer mode.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally release the lock in write mode.
- bool writer_release();
-
- //@}
- /// @name Platform Dependent Data
- /// @{
- private:
+#if defined(LLVM_USE_RW_MUTEX_IMPL)
+/// Platform agnostic RWMutex class.
+class RWMutexImpl {
+ /// @name Constructors
+ /// @{
+public:
+ /// Initializes the lock but doesn't acquire it.
+ /// Default Constructor.
+ explicit RWMutexImpl();
+
+ /// @}
+ /// @name Do Not Implement
+ /// @{
+ RWMutexImpl(const RWMutexImpl &original) = delete;
+ RWMutexImpl &operator=(const RWMutexImpl &) = delete;
+ /// @}
+
+ /// Releases and removes the lock
+ /// Destructor
+ ~RWMutexImpl();
+
+ /// @}
+ /// @name Methods
+ /// @{
+public:
+ /// Attempts to unconditionally acquire the lock in reader mode. If the
+ /// lock is held by a writer, this method will wait until it can acquire
+ /// the lock.
+ /// @returns false if any kind of error occurs, true otherwise.
+ /// Unconditionally acquire the lock in reader mode.
+ bool lock_shared();
+
+ /// Attempts to release the lock in reader mode.
+ /// @returns false if any kind of error occurs, true otherwise.
+ /// Unconditionally release the lock in reader mode.
+ bool unlock_shared();
+
+ /// Attempts to unconditionally acquire the lock in reader mode. If the
+ /// lock is held by any readers, this method will wait until it can
+ /// acquire the lock.
+ /// @returns false if any kind of error occurs, true otherwise.
+ /// Unconditionally acquire the lock in writer mode.
+ bool lock();
+
+ /// Attempts to release the lock in writer mode.
+ /// @returns false if any kind of error occurs, true otherwise.
+ /// Unconditionally release the lock in write mode.
+ bool unlock();
+
+ //@}
+ /// @name Platform Dependent Data
+ /// @{
+private:
#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
- void* data_ = nullptr; ///< We don't know what the data will be
+ void *data_ = nullptr; ///< We don't know what the data will be
+#endif
+};
+#endif
+
+/// SmartMutex - An R/W mutex with a compile time constant parameter that
+/// indicates whether this mutex should become a no-op when we're not
+/// running in multithreaded mode.
+template <bool mt_only> class SmartRWMutex {
+ // shared_mutex (C++17) is more efficient than shared_timed_mutex (C++14)
+ // on Windows and always available on MSVC.
+#if defined(_MSC_VER) || __cplusplus > 201402L
+ std::shared_mutex impl;
+#else
+#if !defined(LLVM_USE_RW_MUTEX_IMPL)
+ std::shared_timed_mutex impl;
+#else
+ RWMutexImpl impl;
+#endif
+#endif
+ unsigned readers = 0;
+ unsigned writers = 0;
+
+public:
+ bool lock_shared() {
+ if (!mt_only || llvm_is_multithreaded()) {
+ impl.lock_shared();
+ return true;
+ }
+
+ // Single-threaded debugging code. This would be racy in multithreaded
+ // mode, but provides not sanity checks in single threaded mode.
+ ++readers;
+ return true;
+ }
+
+ bool unlock_shared() {
+ if (!mt_only || llvm_is_multithreaded()) {
+ impl.unlock_shared();
+ return true;
+ }
+
+ // Single-threaded debugging code. This would be racy in multithreaded
+ // mode, but provides not sanity checks in single threaded mode.
+ assert(readers > 0 && "Reader lock not acquired before release!");
+ --readers;
+ return true;
+ }
+
+ bool lock() {
+ if (!mt_only || llvm_is_multithreaded()) {
+ impl.lock();
+ return true;
+ }
+
+ // Single-threaded debugging code. This would be racy in multithreaded
+ // mode, but provides not sanity checks in single threaded mode.
+ assert(writers == 0 && "Writer lock already acquired!");
+ ++writers;
+ return true;
+ }
+
+ bool unlock() {
+ if (!mt_only || llvm_is_multithreaded()) {
+ impl.unlock();
+ return true;
+ }
+
+ // Single-threaded debugging code. This would be racy in multithreaded
+ // mode, but provides not sanity checks in single threaded mode.
+ assert(writers == 1 && "Writer lock not acquired before release!");
+ --writers;
+ return true;
+ }
+};
+
+typedef SmartRWMutex<false> RWMutex;
+
+/// ScopedReader - RAII acquisition of a reader lock
+#if !defined(LLVM_USE_RW_MUTEX_IMPL)
+template <bool mt_only>
+using SmartScopedReader = const std::shared_lock<SmartRWMutex<mt_only>>;
+#else
+template <bool mt_only> struct SmartScopedReader {
+ SmartRWMutex<mt_only> &mutex;
+
+ explicit SmartScopedReader(SmartRWMutex<mt_only> &m) : mutex(m) {
+ mutex.lock_shared();
+ }
+
+ ~SmartScopedReader() { mutex.unlock_shared(); }
+};
+#endif
+typedef SmartScopedReader<false> ScopedReader;
+
+/// ScopedWriter - RAII acquisition of a writer lock
+#if !defined(LLVM_USE_RW_MUTEX_IMPL)
+template <bool mt_only>
+using SmartScopedWriter = std::lock_guard<SmartRWMutex<mt_only>>;
+#else
+template <bool mt_only> struct SmartScopedWriter {
+ SmartRWMutex<mt_only> &mutex;
+
+ explicit SmartScopedWriter(SmartRWMutex<mt_only> &m) : mutex(m) {
+ mutex.lock();
+ }
+
+ ~SmartScopedWriter() { mutex.unlock(); }
+};
#endif
- };
-
- /// SmartMutex - An R/W mutex with a compile time constant parameter that
- /// indicates whether this mutex should become a no-op when we're not
- /// running in multithreaded mode.
- template<bool mt_only>
- class SmartRWMutex {
- RWMutexImpl impl;
- unsigned readers = 0;
- unsigned writers = 0;
-
- public:
- explicit SmartRWMutex() = default;
- SmartRWMutex(const SmartRWMutex<mt_only> & original) = delete;
- SmartRWMutex<mt_only> &operator=(const SmartRWMutex<mt_only> &) = delete;
-
- bool lock_shared() {
- if (!mt_only || llvm_is_multithreaded())
- return impl.reader_acquire();
-
- // Single-threaded debugging code. This would be racy in multithreaded
- // mode, but provides not sanity checks in single threaded mode.
- ++readers;
- return true;
- }
-
- bool unlock_shared() {
- if (!mt_only || llvm_is_multithreaded())
- return impl.reader_release();
-
- // Single-threaded debugging code. This would be racy in multithreaded
- // mode, but provides not sanity checks in single threaded mode.
- assert(readers > 0 && "Reader lock not acquired before release!");
- --readers;
- return true;
- }
-
- bool lock() {
- if (!mt_only || llvm_is_multithreaded())
- return impl.writer_acquire();
-
- // Single-threaded debugging code. This would be racy in multithreaded
- // mode, but provides not sanity checks in single threaded mode.
- assert(writers == 0 && "Writer lock already acquired!");
- ++writers;
- return true;
- }
-
- bool unlock() {
- if (!mt_only || llvm_is_multithreaded())
- return impl.writer_release();
-
- // Single-threaded debugging code. This would be racy in multithreaded
- // mode, but provides not sanity checks in single threaded mode.
- assert(writers == 1 && "Writer lock not acquired before release!");
- --writers;
- return true;
- }
- };
-
- typedef SmartRWMutex<false> RWMutex;
-
- /// ScopedReader - RAII acquisition of a reader lock
- template<bool mt_only>
- struct SmartScopedReader {
- SmartRWMutex<mt_only>& mutex;
-
- explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
- mutex.lock_shared();
- }
-
- ~SmartScopedReader() {
- mutex.unlock_shared();
- }
- };
-
- typedef SmartScopedReader<false> ScopedReader;
-
- /// ScopedWriter - RAII acquisition of a writer lock
- template<bool mt_only>
- struct SmartScopedWriter {
- SmartRWMutex<mt_only>& mutex;
-
- explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) {
- mutex.lock();
- }
-
- ~SmartScopedWriter() {
- mutex.unlock();
- }
- };
-
- typedef SmartScopedWriter<false> ScopedWriter;
+typedef SmartScopedWriter<false> ScopedWriter;
} // end namespace sys
} // end namespace llvm
diff --git a/include/llvm/Support/Regex.h b/include/llvm/Support/Regex.h
index 2d19b10fd890..b2620ab4cfc9 100644
--- a/include/llvm/Support/Regex.h
+++ b/include/llvm/Support/Regex.h
@@ -44,6 +44,9 @@ namespace llvm {
Regex();
/// Compiles the given regular expression \p Regex.
+ ///
+ /// \param Regex - referenced string is no longer needed after this
+ /// constructor does finish. Only its compiled form is kept stored.
Regex(StringRef Regex, unsigned Flags = NoFlags);
Regex(const Regex &) = delete;
Regex &operator=(Regex regex) {
@@ -54,9 +57,10 @@ namespace llvm {
Regex(Regex &&regex);
~Regex();
- /// isValid - returns the error encountered during regex compilation, or
- /// matching, if any.
+ /// isValid - returns the error encountered during regex compilation, if
+ /// any.
bool isValid(std::string &Error) const;
+ bool isValid() const { return !error; }
/// getNumMatches - In a valid regex, return the number of parenthesized
/// matches it contains. The number filled in by match will include this
@@ -69,8 +73,12 @@ namespace llvm {
/// with references to the matched group expressions (inside \p String),
/// the first group is always the entire pattern.
///
+ /// \param Error - If non-null, any errors in the matching will be recorded
+ /// as a non-empty string. If there is no error, it will be an empty string.
+ ///
/// This returns true on a successful match.
- bool match(StringRef String, SmallVectorImpl<StringRef> *Matches = nullptr);
+ bool match(StringRef String, SmallVectorImpl<StringRef> *Matches = nullptr,
+ std::string *Error = nullptr) const;
/// sub - Return the result of replacing the first match of the regex in
/// \p String with the \p Repl string. Backreferences like "\0" in the
@@ -81,9 +89,9 @@ namespace llvm {
///
/// \param Error If non-null, any errors in the substitution (invalid
/// backreferences, trailing backslashes) will be recorded as a non-empty
- /// string.
+ /// string. If there is no error, it will be an empty string.
std::string sub(StringRef Repl, StringRef String,
- std::string *Error = nullptr);
+ std::string *Error = nullptr) const;
/// If this function returns true, ^Str$ is an extended regular
/// expression that matches Str and only Str.
diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h
index 4d8aa5f1470d..5bb6a254a47f 100644
--- a/include/llvm/Support/Registry.h
+++ b/include/llvm/Support/Registry.h
@@ -115,7 +115,7 @@ namespace llvm {
entry Entry;
node Node;
- static std::unique_ptr<T> CtorFn() { return make_unique<V>(); }
+ static std::unique_ptr<T> CtorFn() { return std::make_unique<V>(); }
public:
Add(StringRef Name, StringRef Desc)
diff --git a/include/llvm/Support/SHA1.h b/include/llvm/Support/SHA1.h
index 87fe94bbd5cd..2cfbd2179364 100644
--- a/include/llvm/Support/SHA1.h
+++ b/include/llvm/Support/SHA1.h
@@ -16,13 +16,13 @@
#define LLVM_SUPPORT_SHA1_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
#include <array>
#include <cstdint>
namespace llvm {
template <typename T> class ArrayRef;
-class StringRef;
/// A class that wrap the SHA1 algorithm.
class SHA1 {
diff --git a/include/llvm/Support/ScalableSize.h b/include/llvm/Support/ScalableSize.h
deleted file mode 100644
index 96bf043773a0..000000000000
--- a/include/llvm/Support/ScalableSize.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- ScalableSize.h - Scalable vector size info ---------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides a struct that can be used to query the size of IR types
-// which may be scalable vectors. It provides convenience operators so that
-// it can be used in much the same way as a single scalar value.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_SCALABLESIZE_H
-#define LLVM_SUPPORT_SCALABLESIZE_H
-
-namespace llvm {
-
-class ElementCount {
-public:
- unsigned Min; // Minimum number of vector elements.
- bool Scalable; // If true, NumElements is a multiple of 'Min' determined
- // at runtime rather than compile time.
-
- ElementCount(unsigned Min, bool Scalable)
- : Min(Min), Scalable(Scalable) {}
-
- ElementCount operator*(unsigned RHS) {
- return { Min * RHS, Scalable };
- }
- ElementCount operator/(unsigned RHS) {
- return { Min / RHS, Scalable };
- }
-
- bool operator==(const ElementCount& RHS) const {
- return Min == RHS.Min && Scalable == RHS.Scalable;
- }
-};
-
-} // end namespace llvm
-
-#endif // LLVM_SUPPORT_SCALABLESIZE_H
diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h
index a6b215a24311..a4f1fad22dd5 100644
--- a/include/llvm/Support/Signals.h
+++ b/include/llvm/Support/Signals.h
@@ -84,6 +84,17 @@ namespace sys {
/// function. Note also that the handler may be executed on a different
/// thread on some platforms.
void SetInfoSignalFunction(void (*Handler)());
+
+ /// Registers a function to be called when a "pipe" signal is delivered to
+ /// the process.
+ ///
+ /// The "pipe" signal typically indicates a failed write to a pipe (SIGPIPE).
+ /// The default installed handler calls `exit(EX_IOERR)`, causing the process
+ /// to immediately exit with an IO error exit code.
+ ///
+ /// This function is only applicable on POSIX systems.
+ void SetPipeSignalFunction(void (*Handler)());
+
} // End sys namespace
} // End llvm namespace
diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h
index 06a447a27c2a..6cec87006c02 100644
--- a/include/llvm/Support/SwapByteOrder.h
+++ b/include/llvm/Support/SwapByteOrder.h
@@ -22,9 +22,37 @@
#include <stdlib.h>
#endif
+#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__)
+#include <endian.h>
+#elif defined(_AIX)
+#include <sys/machine.h>
+#elif defined(__sun)
+/* Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h */
+#include <sys/types.h>
+#define BIG_ENDIAN 4321
+#define LITTLE_ENDIAN 1234
+#if defined(_BIG_ENDIAN)
+#define BYTE_ORDER BIG_ENDIAN
+#else
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+#else
+#if !defined(BYTE_ORDER) && !defined(_WIN32)
+#include <machine/endian.h>
+#endif
+#endif
+
namespace llvm {
namespace sys {
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
+constexpr bool IsBigEndianHost = true;
+#else
+constexpr bool IsBigEndianHost = false;
+#endif
+
+static const bool IsLittleEndianHost = !IsBigEndianHost;
+
/// SwapByteOrder_16 - This function returns a byte-swapped representation of
/// the 16-bit argument.
inline uint16_t SwapByteOrder_16(uint16_t value) {
@@ -39,10 +67,9 @@ inline uint16_t SwapByteOrder_16(uint16_t value) {
#endif
}
-/// SwapByteOrder_32 - This function returns a byte-swapped representation of
-/// the 32-bit argument.
+/// This function returns a byte-swapped representation of the 32-bit argument.
inline uint32_t SwapByteOrder_32(uint32_t value) {
-#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC))
+#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
return __builtin_bswap32(value);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_ulong(value);
@@ -55,10 +82,9 @@ inline uint32_t SwapByteOrder_32(uint32_t value) {
#endif
}
-/// SwapByteOrder_64 - This function returns a byte-swapped representation of
-/// the 64-bit argument.
+/// This function returns a byte-swapped representation of the 64-bit argument.
inline uint64_t SwapByteOrder_64(uint64_t value) {
-#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC))
+#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
return __builtin_bswap64(value);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_uint64(value);
diff --git a/include/llvm/Support/TargetOpcodes.def b/include/llvm/Support/TargetOpcodes.def
index 598c1064efd0..11731ac35415 100644
--- a/include/llvm/Support/TargetOpcodes.def
+++ b/include/llvm/Support/TargetOpcodes.def
@@ -294,9 +294,21 @@ HANDLE_TARGET_OPCODE(G_SEXTLOAD)
/// Generic zeroext load
HANDLE_TARGET_OPCODE(G_ZEXTLOAD)
+/// Generic indexed load (including anyext load)
+HANDLE_TARGET_OPCODE(G_INDEXED_LOAD)
+
+/// Generic indexed signext load
+HANDLE_TARGET_OPCODE(G_INDEXED_SEXTLOAD)
+
+/// Generic indexed zeroext load
+HANDLE_TARGET_OPCODE(G_INDEXED_ZEXTLOAD)
+
/// Generic store.
HANDLE_TARGET_OPCODE(G_STORE)
+/// Generic indexed store.
+HANDLE_TARGET_OPCODE(G_INDEXED_STORE)
+
/// Generic atomic cmpxchg with internal success check.
HANDLE_TARGET_OPCODE(G_ATOMIC_CMPXCHG_WITH_SUCCESS)
@@ -315,6 +327,8 @@ HANDLE_TARGET_OPCODE(G_ATOMICRMW_MAX)
HANDLE_TARGET_OPCODE(G_ATOMICRMW_MIN)
HANDLE_TARGET_OPCODE(G_ATOMICRMW_UMAX)
HANDLE_TARGET_OPCODE(G_ATOMICRMW_UMIN)
+HANDLE_TARGET_OPCODE(G_ATOMICRMW_FADD)
+HANDLE_TARGET_OPCODE(G_ATOMICRMW_FSUB)
// Generic atomic fence
HANDLE_TARGET_OPCODE(G_FENCE)
@@ -354,6 +368,7 @@ HANDLE_TARGET_OPCODE(G_VAARG)
// Generic sign extend
HANDLE_TARGET_OPCODE(G_SEXT)
+HANDLE_TARGET_OPCODE(G_SEXT_INREG)
// Generic zero extend
HANDLE_TARGET_OPCODE(G_ZEXT)
@@ -436,6 +451,9 @@ HANDLE_TARGET_OPCODE(G_FMUL)
/// Generic FMA multiplication. Behaves like llvm fma intrinsic
HANDLE_TARGET_OPCODE(G_FMA)
+/// Generic FP multiply and add. Behaves as separate fmul and fadd.
+HANDLE_TARGET_OPCODE(G_FMAD)
+
/// Generic FP division.
HANDLE_TARGET_OPCODE(G_FDIV)
@@ -557,6 +575,9 @@ HANDLE_TARGET_OPCODE(G_CTPOP)
/// Generic byte swap.
HANDLE_TARGET_OPCODE(G_BSWAP)
+/// Generic bit reverse.
+HANDLE_TARGET_OPCODE(G_BITREVERSE)
+
/// Floating point ceil.
HANDLE_TARGET_OPCODE(G_FCEIL)
@@ -587,12 +608,15 @@ HANDLE_TARGET_OPCODE(G_BLOCK_ADDR)
/// Generic jump table address
HANDLE_TARGET_OPCODE(G_JUMP_TABLE)
+/// Generic dynamic stack allocation.
+HANDLE_TARGET_OPCODE(G_DYN_STACKALLOC)
+
// TODO: Add more generic opcodes as we move along.
/// Marker for the end of the generic opcode.
/// This is used to check if an opcode is in the range of the
/// generic opcodes.
-HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_JUMP_TABLE)
+HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_DYN_STACKALLOC)
/// BUILTIN_OP_END - This must be the last enum value in this list.
/// The target-specific post-isel opcode values start here.
diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h
index bf75650760d0..f4bc26b858c8 100644
--- a/include/llvm/Support/TargetRegistry.h
+++ b/include/llvm/Support/TargetRegistry.h
@@ -510,8 +510,8 @@ public:
std::move(Emitter), RelaxAll);
break;
case Triple::XCOFF:
- S = createXCOFFStreamer(Ctx, std::move(TAB), std::move(OW),
- std::move(Emitter), RelaxAll);
+ S = createXCOFFStreamer(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll);
break;
}
if (ObjectTargetStreamerCtorFn)
diff --git a/include/llvm/Support/TimeProfiler.h b/include/llvm/Support/TimeProfiler.h
index 72b6f7180bde..8cc430d0bc72 100644
--- a/include/llvm/Support/TimeProfiler.h
+++ b/include/llvm/Support/TimeProfiler.h
@@ -19,7 +19,7 @@ extern TimeTraceProfiler *TimeTraceProfilerInstance;
/// Initialize the time trace profiler.
/// This sets up the global \p TimeTraceProfilerInstance
/// variable to be the profiler instance.
-void timeTraceProfilerInitialize();
+void timeTraceProfilerInitialize(unsigned TimeTraceGranularity);
/// Cleanup the time trace profiler, if it was initialized.
void timeTraceProfilerCleanup();
diff --git a/include/llvm/Support/TrailingObjects.h b/include/llvm/Support/TrailingObjects.h
index 8cf4f7aed7f8..49be89613c43 100644
--- a/include/llvm/Support/TrailingObjects.h
+++ b/include/llvm/Support/TrailingObjects.h
@@ -47,6 +47,7 @@
#define LLVM_SUPPORT_TRAILINGOBJECTS_H
#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/type_traits.h"
@@ -87,11 +88,6 @@ protected:
template <typename T> struct OverloadToken {};
};
-/// This helper template works-around MSVC 2013's lack of useful
-/// alignas() support. The argument to alignas(), in MSVC, is
-/// required to be a literal integer. But, you *can* use template
-/// specialization to select between a bunch of different alignas()
-/// expressions...
template <int Align>
class TrailingObjectsAligner : public TrailingObjectsBase {};
template <>
@@ -172,7 +168,7 @@ protected:
if (requiresRealignment())
return reinterpret_cast<const NextTy *>(
- llvm::alignAddr(Ptr, alignof(NextTy)));
+ alignAddr(Ptr, Align::Of<NextTy>()));
else
return reinterpret_cast<const NextTy *>(Ptr);
}
@@ -186,7 +182,7 @@ protected:
Obj, TrailingObjectsBase::OverloadToken<PrevTy>());
if (requiresRealignment())
- return reinterpret_cast<NextTy *>(llvm::alignAddr(Ptr, alignof(NextTy)));
+ return reinterpret_cast<NextTy *>(alignAddr(Ptr, Align::Of<NextTy>()));
else
return reinterpret_cast<NextTy *>(Ptr);
}
@@ -254,9 +250,7 @@ class TrailingObjects : private trailing_objects_internal::TrailingObjectsImpl<
// because BaseTy isn't complete at class instantiation time, but
// will be by the time this function is instantiated.
static void verifyTrailingObjectsAssertions() {
-#ifdef LLVM_IS_FINAL
- static_assert(LLVM_IS_FINAL(BaseTy), "BaseTy must be final.");
-#endif
+ static_assert(std::is_final<BaseTy>(), "BaseTy must be final.");
}
// These two methods are the base of the recursion for this method.
@@ -369,7 +363,9 @@ public:
template <typename... Tys> struct FixedSizeStorage {
template <size_t... Counts> struct with_counts {
enum { Size = totalSizeToAlloc<Tys...>(Counts...) };
- typedef llvm::AlignedCharArray<alignof(BaseTy), Size> type;
+ struct type {
+ alignas(BaseTy) char buffer[Size];
+ };
};
};
diff --git a/include/llvm/Support/TypeSize.h b/include/llvm/Support/TypeSize.h
new file mode 100644
index 000000000000..711679cdcacb
--- /dev/null
+++ b/include/llvm/Support/TypeSize.h
@@ -0,0 +1,201 @@
+//===- TypeSize.h - Wrapper around type sizes -------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a struct that can be used to query the size of IR types
+// which may be scalable vectors. It provides convenience operators so that
+// it can be used in much the same way as a single scalar value.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_TYPESIZE_H
+#define LLVM_SUPPORT_TYPESIZE_H
+
+#include <cassert>
+#include <tuple>
+
+namespace llvm {
+
+class ElementCount {
+public:
+ unsigned Min; // Minimum number of vector elements.
+ bool Scalable; // If true, NumElements is a multiple of 'Min' determined
+ // at runtime rather than compile time.
+
+ ElementCount(unsigned Min, bool Scalable)
+ : Min(Min), Scalable(Scalable) {}
+
+ ElementCount operator*(unsigned RHS) {
+ return { Min * RHS, Scalable };
+ }
+ ElementCount operator/(unsigned RHS) {
+ return { Min / RHS, Scalable };
+ }
+
+ bool operator==(const ElementCount& RHS) const {
+ return Min == RHS.Min && Scalable == RHS.Scalable;
+ }
+ bool operator!=(const ElementCount& RHS) const {
+ return !(*this == RHS);
+ }
+};
+
+// This class is used to represent the size of types. If the type is of fixed
+// size, it will represent the exact size. If the type is a scalable vector,
+// it will represent the known minimum size.
+class TypeSize {
+ uint64_t MinSize; // The known minimum size.
+ bool IsScalable; // If true, then the runtime size is an integer multiple
+ // of MinSize.
+
+public:
+ constexpr TypeSize(uint64_t MinSize, bool Scalable)
+ : MinSize(MinSize), IsScalable(Scalable) {}
+
+ static constexpr TypeSize Fixed(uint64_t Size) {
+ return TypeSize(Size, /*IsScalable=*/false);
+ }
+
+ static constexpr TypeSize Scalable(uint64_t MinSize) {
+ return TypeSize(MinSize, /*IsScalable=*/true);
+ }
+
+ // Scalable vector types with the same minimum size as a fixed size type are
+ // not guaranteed to be the same size at runtime, so they are never
+ // considered to be equal.
+ friend bool operator==(const TypeSize &LHS, const TypeSize &RHS) {
+ return std::tie(LHS.MinSize, LHS.IsScalable) ==
+ std::tie(RHS.MinSize, RHS.IsScalable);
+ }
+
+ friend bool operator!=(const TypeSize &LHS, const TypeSize &RHS) {
+ return !(LHS == RHS);
+ }
+
+ // For many cases, size ordering between scalable and fixed size types cannot
+ // be determined at compile time, so such comparisons aren't allowed.
+ //
+ // e.g. <vscale x 2 x i16> could be bigger than <4 x i32> with a runtime
+ // vscale >= 5, equal sized with a vscale of 4, and smaller with
+ // a vscale <= 3.
+ //
+ // If the scalable flags match, just perform the requested comparison
+ // between the minimum sizes.
+ friend bool operator<(const TypeSize &LHS, const TypeSize &RHS) {
+ assert(LHS.IsScalable == RHS.IsScalable &&
+ "Ordering comparison of scalable and fixed types");
+
+ return LHS.MinSize < RHS.MinSize;
+ }
+
+ friend bool operator>(const TypeSize &LHS, const TypeSize &RHS) {
+ return RHS < LHS;
+ }
+
+ friend bool operator<=(const TypeSize &LHS, const TypeSize &RHS) {
+ return !(RHS < LHS);
+ }
+
+ friend bool operator>=(const TypeSize &LHS, const TypeSize& RHS) {
+ return !(LHS < RHS);
+ }
+
+ // Convenience operators to obtain relative sizes independently of
+ // the scalable flag.
+ TypeSize operator*(unsigned RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ friend TypeSize operator*(const unsigned LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ TypeSize operator/(unsigned RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+
+ // Return the minimum size with the assumption that the size is exact.
+ // Use in places where a scalable size doesn't make sense (e.g. non-vector
+ // types, or vectors in backends which don't support scalable vectors).
+ uint64_t getFixedSize() const {
+ assert(!IsScalable && "Request for a fixed size on a scalable object");
+ return MinSize;
+ }
+
+ // Return the known minimum size. Use in places where the scalable property
+ // doesn't matter (e.g. determining alignment) or in conjunction with the
+ // isScalable method below.
+ uint64_t getKnownMinSize() const {
+ return MinSize;
+ }
+
+ // Return whether or not the size is scalable.
+ bool isScalable() const {
+ return IsScalable;
+ }
+
+ // Casts to a uint64_t if this is a fixed-width size.
+ //
+ // NOTE: This interface is obsolete and will be removed in a future version
+ // of LLVM in favour of calling getFixedSize() directly.
+ operator uint64_t() const {
+ return getFixedSize();
+ }
+
+ // Additional convenience operators needed to avoid ambiguous parses.
+ // TODO: Make uint64_t the default operator?
+ TypeSize operator*(uint64_t RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ TypeSize operator*(int RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ TypeSize operator*(int64_t RHS) const {
+ return { MinSize * RHS, IsScalable };
+ }
+
+ friend TypeSize operator*(const uint64_t LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ friend TypeSize operator*(const int LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ friend TypeSize operator*(const int64_t LHS, const TypeSize &RHS) {
+ return { LHS * RHS.MinSize, RHS.IsScalable };
+ }
+
+ TypeSize operator/(uint64_t RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+
+ TypeSize operator/(int RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+
+ TypeSize operator/(int64_t RHS) const {
+ return { MinSize / RHS, IsScalable };
+ }
+};
+
+/// Returns a TypeSize with a known minimum size that is 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.
+///
+/// Similar to the alignTo functions in MathExtras.h
+inline TypeSize alignTo(TypeSize Size, uint64_t Align) {
+ assert(Align != 0u && "Align must be non-zero");
+ return {(Size.getKnownMinSize() + Align - 1) / Align * Align,
+ Size.isScalable()};
+}
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_TypeSize_H
diff --git a/include/llvm/Support/UnicodeCharRanges.h b/include/llvm/Support/UnicodeCharRanges.h
index 4b59f8a92b76..73d3603b74df 100644
--- a/include/llvm/Support/UnicodeCharRanges.h
+++ b/include/llvm/Support/UnicodeCharRanges.h
@@ -9,11 +9,8 @@
#define LLVM_SUPPORT_UNICODECHARRANGES_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
diff --git a/include/llvm/Support/UniqueLock.h b/include/llvm/Support/UniqueLock.h
deleted file mode 100644
index 0a887ad5965d..000000000000
--- a/include/llvm/Support/UniqueLock.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//===- Support/UniqueLock.h - Acquire/Release Mutex In Scope ----*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a guard for a block of code that ensures a Mutex is locked
-// upon construction and released upon destruction.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_UNIQUE_LOCK_H
-#define LLVM_SUPPORT_UNIQUE_LOCK_H
-
-#include <cassert>
-
-namespace llvm {
-
- /// A pared-down imitation of std::unique_lock from C++11. Contrary to the
- /// name, it's really more of a wrapper for a lock. It may or may not have
- /// an associated mutex, which is guaranteed to be locked upon creation
- /// and unlocked after destruction. unique_lock can also unlock the mutex
- /// and re-lock it freely during its lifetime.
- /// Guard a section of code with a mutex.
- template<typename MutexT>
- class unique_lock {
- MutexT *M = nullptr;
- bool locked = false;
-
- public:
- unique_lock() = default;
- explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); }
- unique_lock(const unique_lock &) = delete;
- unique_lock &operator=(const unique_lock &) = delete;
-
- void operator=(unique_lock &&o) {
- if (owns_lock())
- M->unlock();
- M = o.M;
- locked = o.locked;
- o.M = nullptr;
- o.locked = false;
- }
-
- ~unique_lock() { if (owns_lock()) M->unlock(); }
-
- void lock() {
- assert(!locked && "mutex already locked!");
- assert(M && "no associated mutex!");
- M->lock();
- locked = true;
- }
-
- void unlock() {
- assert(locked && "unlocking a mutex that isn't locked!");
- assert(M && "no associated mutex!");
- M->unlock();
- locked = false;
- }
-
- bool owns_lock() { return locked; }
- };
-
-} // end namespace llvm
-
-#endif // LLVM_SUPPORT_UNIQUE_LOCK_H
diff --git a/include/llvm/Support/VirtualFileSystem.h b/include/llvm/Support/VirtualFileSystem.h
index 31c9e851daed..c844d9d194f0 100644
--- a/include/llvm/Support/VirtualFileSystem.h
+++ b/include/llvm/Support/VirtualFileSystem.h
@@ -647,9 +647,19 @@ private:
friend class VFSFromYamlDirIterImpl;
friend class RedirectingFileSystemParser;
+ bool shouldUseExternalFS() const {
+ return ExternalFSValidWD && IsFallthrough;
+ }
+
/// The root(s) of the virtual file system.
std::vector<std::unique_ptr<Entry>> Roots;
+ /// The current working directory of the file system.
+ std::string WorkingDirectory;
+
+ /// Whether the current working directory is valid for the external FS.
+ bool ExternalFSValidWD = false;
+
/// The file system to use for external references.
IntrusiveRefCntPtr<FileSystem> ExternalFS;
@@ -689,8 +699,7 @@ private:
true;
#endif
- RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS)
- : ExternalFS(std::move(ExternalFS)) {}
+ RedirectingFileSystem(IntrusiveRefCntPtr<FileSystem> ExternalFS);
/// Looks up the path <tt>[Start, End)</tt> in \p From, possibly
/// recursing into the contents of \p From if it is a directory.
@@ -730,9 +739,10 @@ public:
StringRef getExternalContentsPrefixDir() const;
+ void dump(raw_ostream &OS) const;
+ void dumpEntry(raw_ostream &OS, Entry *E, int NumSpaces = 0) const;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void dump() const;
- LLVM_DUMP_METHOD void dumpEntry(Entry *E, int NumSpaces = 0) const;
#endif
};
diff --git a/include/llvm/Support/Win64EH.h b/include/llvm/Support/Win64EH.h
index bdd23b41594e..8220131e5be9 100644
--- a/include/llvm/Support/Win64EH.h
+++ b/include/llvm/Support/Win64EH.h
@@ -30,7 +30,9 @@ enum UnwindOpcodes {
UOP_SetFPReg,
UOP_SaveNonVol,
UOP_SaveNonVolBig,
- UOP_SaveXMM128 = 8,
+ UOP_Epilog,
+ UOP_SpareCode,
+ UOP_SaveXMM128,
UOP_SaveXMM128Big,
UOP_PushMachFrame,
// The following set of unwind opcodes is for ARM64. They are documented at
diff --git a/include/llvm/Support/X86TargetParser.def b/include/llvm/Support/X86TargetParser.def
index 1749be3b3ae2..4ebf2d79cb8d 100644
--- a/include/llvm/Support/X86TargetParser.def
+++ b/include/llvm/Support/X86TargetParser.def
@@ -112,6 +112,7 @@ X86_CPU_SUBTYPE ("k6-2", AMDPENTIUM_K62)
X86_CPU_SUBTYPE ("k6-3", AMDPENTIUM_K63)
X86_CPU_SUBTYPE ("geode", AMDPENTIUM_GEODE)
X86_CPU_SUBTYPE ("cooperlake", INTEL_COREI7_COOPERLAKE)
+X86_CPU_SUBTYPE ("tigerlake", INTEL_COREI7_TIGERLAKE)
#undef X86_CPU_SUBTYPE_COMPAT
#undef X86_CPU_SUBTYPE
@@ -160,12 +161,13 @@ X86_FEATURE_COMPAT(32, FEATURE_GFNI, "gfni")
X86_FEATURE_COMPAT(33, FEATURE_VPCLMULQDQ, "vpclmulqdq")
X86_FEATURE_COMPAT(34, FEATURE_AVX512VNNI, "avx512vnni")
X86_FEATURE_COMPAT(35, FEATURE_AVX512BITALG, "avx512bitalg")
+X86_FEATURE_COMPAT(36, FEATURE_AVX512BF16, "avx512bf16")
// Features below here are not in libgcc/compiler-rt.
X86_FEATURE (64, FEATURE_MOVBE)
X86_FEATURE (65, FEATURE_ADX)
X86_FEATURE (66, FEATURE_EM64T)
X86_FEATURE (67, FEATURE_CLFLUSHOPT)
X86_FEATURE (68, FEATURE_SHA)
-X86_FEATURE (69, FEATURE_AVX512BF16)
+X86_FEATURE (69, FEATURE_AVX512VP2INTERSECT)
#undef X86_FEATURE_COMPAT
#undef X86_FEATURE
diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h
index 5181dc56d81d..a3bfa7dc4678 100644
--- a/include/llvm/Support/YAMLTraits.h
+++ b/include/llvm/Support/YAMLTraits.h
@@ -649,7 +649,8 @@ inline bool isBool(StringRef S) {
inline QuotingType needsQuotes(StringRef S) {
if (S.empty())
return QuotingType::Single;
- if (isspace(S.front()) || isspace(S.back()))
+ if (isspace(static_cast<unsigned char>(S.front())) ||
+ isspace(static_cast<unsigned char>(S.back())))
return QuotingType::Single;
if (isNull(S))
return QuotingType::Single;
@@ -748,7 +749,7 @@ public:
IO(void *Ctxt = nullptr);
virtual ~IO();
- virtual bool outputting() = 0;
+ virtual bool outputting() const = 0;
virtual unsigned beginSequence() = 0;
virtual bool preflightElement(unsigned, void *&) = 0;
@@ -842,7 +843,7 @@ public:
Val = Val | ConstVal;
}
- void *getContext();
+ void *getContext() const;
void setContext(void *);
template <typename T> void mapRequired(const char *Key, T &Val) {
@@ -1402,7 +1403,7 @@ public:
std::error_code error();
private:
- bool outputting() override;
+ bool outputting() const override;
bool mapTag(StringRef, bool) override;
void beginMapping() override;
void endMapping() override;
@@ -1549,7 +1550,7 @@ public:
/// anyway.
void setWriteDefaultValues(bool Write) { WriteDefaultValues = Write; }
- bool outputting() override;
+ bool outputting() const override;
bool mapTag(StringRef, bool) override;
void beginMapping() override;
void endMapping() override;
diff --git a/include/llvm/Support/circular_raw_ostream.h b/include/llvm/Support/circular_raw_ostream.h
index 4ecdb17376f1..a72acd4fe002 100644
--- a/include/llvm/Support/circular_raw_ostream.h
+++ b/include/llvm/Support/circular_raw_ostream.h
@@ -122,6 +122,10 @@ namespace llvm {
delete[] BufferArray;
}
+ bool is_displayed() const override {
+ return TheStream->is_displayed();
+ }
+
/// setStream - Tell the circular_raw_ostream to output a
/// different stream. "Owns" tells circular_raw_ostream whether
/// it should take responsibility for managing the underlying
diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h
index 48bb623b0638..0debc5da7a68 100644
--- a/include/llvm/Support/raw_ostream.h
+++ b/include/llvm/Support/raw_ostream.h
@@ -72,7 +72,7 @@ private:
public:
// color order matches ANSI escape sequence, don't change
- enum Colors {
+ enum class Colors {
BLACK = 0,
RED,
GREEN,
@@ -81,9 +81,21 @@ public:
MAGENTA,
CYAN,
WHITE,
- SAVEDCOLOR
+ SAVEDCOLOR,
+ RESET,
};
+ static const Colors BLACK = Colors::BLACK;
+ static const Colors RED = Colors::RED;
+ static const Colors GREEN = Colors::GREEN;
+ static const Colors YELLOW = Colors::YELLOW;
+ static const Colors BLUE = Colors::BLUE;
+ static const Colors MAGENTA = Colors::MAGENTA;
+ static const Colors CYAN = Colors::CYAN;
+ static const Colors WHITE = Colors::WHITE;
+ static const Colors SAVEDCOLOR = Colors::SAVEDCOLOR;
+ static const Colors RESET = Colors::RESET;
+
explicit raw_ostream(bool unbuffered = false)
: BufferMode(unbuffered ? Unbuffered : InternalBuffer) {
// Start out ready to flush.
@@ -214,6 +226,9 @@ public:
/// Output \p N in hexadecimal, without any prefix or padding.
raw_ostream &write_hex(unsigned long long N);
+ // Change the foreground color of text.
+ raw_ostream &operator<<(Colors C);
+
/// Output a formatted UUID with dash separators.
using uuid_t = uint8_t[16];
raw_ostream &write_uuid(const uuid_t UUID);
@@ -277,6 +292,10 @@ public:
/// This function determines if this stream is displayed and supports colors.
virtual bool has_colors() const { return is_displayed(); }
+ // Enable or disable colors. Once disable_colors() is called,
+ // changeColor() has no effect until enable_colors() is called.
+ virtual void enable_colors(bool /*enable*/) {}
+
//===--------------------------------------------------------------------===//
// Subclass Interface
//===--------------------------------------------------------------------===//
@@ -365,8 +384,8 @@ public:
class raw_fd_ostream : public raw_pwrite_stream {
int FD;
bool ShouldClose;
-
bool SupportsSeeking;
+ bool ColorEnabled = true;
#ifdef _WIN32
/// True if this fd refers to a Windows console device. Mintty and other
@@ -442,6 +461,8 @@ public:
bool has_colors() const override;
+ void enable_colors(bool enable) override { ColorEnabled = enable; }
+
std::error_code error() const { return EC; }
/// Return the value of the flag in this raw_fd_ostream indicating whether an
diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h
index c8c6a76a90f1..b7d48e8e1ade 100644
--- a/include/llvm/Support/type_traits.h
+++ b/include/llvm/Support/type_traits.h
@@ -17,11 +17,6 @@
#include <type_traits>
#include <utility>
-#ifndef __has_feature
-#define LLVM_DEFINED_HAS_FEATURE
-#define __has_feature(x) 0
-#endif
-
namespace llvm {
@@ -194,17 +189,4 @@ class is_trivially_copyable<T*> : public std::true_type {
} // end namespace llvm
-// If the compiler supports detecting whether a class is final, define
-// an LLVM_IS_FINAL macro. If it cannot be defined properly, this
-// macro will be left undefined.
-#if __cplusplus >= 201402L || defined(_MSC_VER)
-#define LLVM_IS_FINAL(Ty) std::is_final<Ty>()
-#elif __has_feature(is_final) || LLVM_GNUC_PREREQ(4, 7, 0)
-#define LLVM_IS_FINAL(Ty) __is_final(Ty)
-#endif
-
-#ifdef LLVM_DEFINED_HAS_FEATURE
-#undef __has_feature
-#endif
-
#endif // LLVM_SUPPORT_TYPE_TRAITS_H