Update prebuilt Clang to r416183b from Android.
https://android.googlesource.com/platform/prebuilts/clang/host/
linux-x86/+/06a71ddac05c22edb2d10b590e1769b3f8619bef
clang 12.0.5 (based on r416183b) from build 7284624.
Change-Id: I277a316abcf47307562d8b748b84870f31a72866
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/linux-x64/clang/include/llvm/Support/AArch64TargetParser.def b/linux-x64/clang/include/llvm/Support/AArch64TargetParser.def
index e152f38..5f36b0e 100644
--- a/linux-x64/clang/include/llvm/Support/AArch64TargetParser.def
+++ b/linux-x64/clang/include/llvm/Support/AArch64TargetParser.def
@@ -44,46 +44,79 @@
(AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |
AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD))
+AARCH64_ARCH("armv8.6-a", ARMV8_6A, "8.6-A", "v8.6a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
+ AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 |
+ AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM))
+AARCH64_ARCH("armv8.7-a", ARMV8_7A, "8.7-A", "v8.7a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_FP |
+ AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE |
+ AArch64::AEK_RDM | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
+ AArch64::AEK_SM4 | AArch64::AEK_SHA3 | AArch64::AEK_BF16 |
+ AArch64::AEK_SHA2 | AArch64::AEK_AES | AArch64::AEK_I8MM))
+// For v8-R, we do not enable crypto and align with GCC that enables a more
+// minimal set of optional architecture extensions.
+AARCH64_ARCH("armv8-r", ARMV8R, "8-R", "v8r",
+ ARMBuildAttrs::CPUArch::v8_R, FK_CRYPTO_NEON_FP_ARMV8,
+ (AArch64::AEK_CRC | AArch64::AEK_RDM | AArch64::AEK_SSBS |
+ AArch64::AEK_DOTPROD | AArch64::AEK_FP | AArch64::AEK_SIMD |
+ AArch64::AEK_FP16 | AArch64::AEK_FP16FML | AArch64::AEK_RAS |
+ AArch64::AEK_RCPC | AArch64::AEK_SB))
#undef AARCH64_ARCH
#ifndef AARCH64_ARCH_EXT_NAME
#define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE)
#endif
// FIXME: This would be nicer were it tablegen
-AARCH64_ARCH_EXT_NAME("invalid", AArch64::AEK_INVALID, nullptr, nullptr)
-AARCH64_ARCH_EXT_NAME("none", AArch64::AEK_NONE, nullptr, nullptr)
-AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc")
-AARCH64_ARCH_EXT_NAME("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("bf16", AArch64::AEK_BF16, "+bf16", "-bf16")
+AARCH64_ARCH_EXT_NAME("i8mm", AArch64::AEK_I8MM, "+i8mm", "-i8mm")
+AARCH64_ARCH_EXT_NAME("f32mm", AArch64::AEK_F32MM, "+f32mm", "-f32mm")
+AARCH64_ARCH_EXT_NAME("f64mm", AArch64::AEK_F64MM, "+f64mm", "-f64mm")
+AARCH64_ARCH_EXT_NAME("tme", AArch64::AEK_TME, "+tme", "-tme")
+AARCH64_ARCH_EXT_NAME("ls64", AArch64::AEK_LS64, "+ls64", "-ls64")
+AARCH64_ARCH_EXT_NAME("brbe", AArch64::AEK_BRBE, "+brbe", "-brbe")
+AARCH64_ARCH_EXT_NAME("pauth", AArch64::AEK_PAUTH, "+pauth", "-pauth")
+AARCH64_ARCH_EXT_NAME("flagm", AArch64::AEK_FLAGM, "+flagm", "-flagm")
#undef AARCH64_ARCH_EXT_NAME
#ifndef AARCH64_CPU_NAME
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)
#endif
+AARCH64_CPU_NAME("cortex-a34", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("cortex-a35", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_CRC))
AARCH64_CPU_NAME("cortex-a53", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true,
@@ -92,6 +125,12 @@
(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,12 +143,56 @@
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("cortex-a77", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16 | AArch64::AEK_RCPC | AArch64::AEK_DOTPROD |
+ AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("cortex-a78", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+ AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("cortex-a78c", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+ AArch64::AEK_SSBS))
+AARCH64_CPU_NAME("cortex-r82", ARMV8R, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_LSE))
+AARCH64_CPU_NAME("cortex-x1", 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("neoverse-n2", ARMV8_5A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_BF16 | AArch64::AEK_DOTPROD | AArch64::AEK_FP16 |
+ AArch64::AEK_I8MM | AArch64::AEK_MTE | AArch64::AEK_RAS |
+ AArch64::AEK_RCPC | AArch64::AEK_SB | AArch64::AEK_SSBS |
+ AArch64::AEK_SVE | AArch64::AEK_SVE2 | AArch64::AEK_SVE2BITPERM))
+AARCH64_CPU_NAME("neoverse-v1", ARMV8_4A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_RAS | AArch64::AEK_SVE | AArch64::AEK_SSBS |
+ AArch64::AEK_RCPC | AArch64::AEK_FP16 | AArch64::AEK_BF16 |
+ AArch64::AEK_DOTPROD ))
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,
- (AArch64::AEK_CRC))
-AARCH64_CPU_NAME("exynos-m2", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC))
+AARCH64_CPU_NAME("apple-a7", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_NONE))
+AARCH64_CPU_NAME("apple-a8", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_NONE))
+AARCH64_CPU_NAME("apple-a9", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_NONE))
+AARCH64_CPU_NAME("apple-a10", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC | AArch64::AEK_RDM))
+AARCH64_CPU_NAME("apple-a11", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_NONE))
+AARCH64_CPU_NAME("apple-a12", ARMV8_3A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16))
+AARCH64_CPU_NAME("apple-a13", ARMV8_4A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16 | AArch64::AEK_FP16FML))
+AARCH64_CPU_NAME("apple-s4", ARMV8_3A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16))
+AARCH64_CPU_NAME("apple-s5", ARMV8_3A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16))
AARCH64_CPU_NAME("exynos-m3", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_CRC))
AARCH64_CPU_NAME("exynos-m4", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
@@ -124,6 +207,10 @@
(AArch64::AEK_CRC))
AARCH64_CPU_NAME("thunderx2t99", ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_NONE))
+AARCH64_CPU_NAME("thunderx3t110", ARMV8_3A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_CRC | AEK_CRYPTO | AEK_FP | AEK_SIMD |
+ AEK_LSE | AEK_RAND | AArch64::AEK_PROFILE |
+ AArch64::AEK_RAS))
AARCH64_CPU_NAME("thunderx", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_CRC | AArch64::AEK_PROFILE))
AARCH64_CPU_NAME("thunderxt88", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
@@ -136,6 +223,10 @@
(AArch64::AEK_DOTPROD |
AArch64::AEK_FP16 | AArch64::AEK_FP16FML |
AArch64::AEK_PROFILE))
+AARCH64_CPU_NAME("a64fx", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16 | AArch64::AEK_SVE))
+AARCH64_CPU_NAME("carmel", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ AArch64::AEK_FP16)
// Invalid CPU
AARCH64_CPU_NAME("invalid", INVALID, FK_INVALID, true, AArch64::AEK_INVALID)
#undef AARCH64_CPU_NAME
diff --git a/linux-x64/clang/include/llvm/Support/AArch64TargetParser.h b/linux-x64/clang/include/llvm/Support/AArch64TargetParser.h
index 965d385..7c9e245 100644
--- a/linux-x64/clang/include/llvm/Support/AArch64TargetParser.h
+++ b/linux-x64/clang/include/llvm/Support/AArch64TargetParser.h
@@ -14,17 +14,20 @@
#ifndef LLVM_SUPPORT_AARCH64TARGETPARSERCOMMON_H
#define LLVM_SUPPORT_AARCH64TARGETPARSERCOMMON_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Support/ARMTargetParser.h"
#include <vector>
// FIXME:This should be made into class design,to avoid dupplication.
namespace llvm {
+
+class Triple;
+
namespace AArch64 {
// Arch extension modifiers for CPUs.
-enum ArchExtKind : unsigned {
+enum ArchExtKind : uint64_t {
AEK_INVALID = 0,
AEK_NONE = 1,
AEK_CRC = 1 << 1,
@@ -53,7 +56,16 @@
AEK_SVE2AES = 1 << 24,
AEK_SVE2SM4 = 1 << 25,
AEK_SVE2SHA3 = 1 << 26,
- AEK_BITPERM = 1 << 27,
+ AEK_SVE2BITPERM = 1 << 27,
+ AEK_TME = 1 << 28,
+ AEK_BF16 = 1 << 29,
+ AEK_I8MM = 1 << 30,
+ AEK_F32MM = 1ULL << 31,
+ AEK_F64MM = 1ULL << 32,
+ AEK_LS64 = 1ULL << 33,
+ AEK_BRBE = 1ULL << 34,
+ AEK_PAUTH = 1ULL << 35,
+ AEK_FLAGM = 1ULL << 36,
};
enum class ArchKind {
@@ -96,7 +108,7 @@
};
// FIXME: These should be moved to TargetTuple once it exists
-bool getExtensionFeatures(unsigned Extensions,
+bool getExtensionFeatures(uint64_t Extensions,
std::vector<StringRef> &Features);
bool getArchFeatures(ArchKind AK, std::vector<StringRef> &Features);
@@ -109,7 +121,7 @@
// Information by Name
unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
-unsigned getDefaultExtensions(StringRef CPU, ArchKind AK);
+uint64_t getDefaultExtensions(StringRef CPU, ArchKind AK);
StringRef getDefaultCPU(StringRef Arch);
ArchKind getCPUArchKind(StringRef CPU);
@@ -122,6 +134,15 @@
bool isX18ReservedByDefault(const Triple &TT);
+struct ParsedBranchProtection {
+ StringRef Scope;
+ StringRef Key;
+ bool BranchTargetEnforcement;
+};
+
+bool parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP,
+ StringRef &Err);
+
} // namespace AArch64
} // namespace llvm
diff --git a/linux-x64/clang/include/llvm/Support/AMDGPUMetadata.h b/linux-x64/clang/include/llvm/Support/AMDGPUMetadata.h
index f7f1ec4..920c97f 100644
--- a/linux-x64/clang/include/llvm/Support/AMDGPUMetadata.h
+++ b/linux-x64/clang/include/llvm/Support/AMDGPUMetadata.h
@@ -75,10 +75,12 @@
HiddenDefaultQueue = 12,
HiddenCompletionAction = 13,
HiddenMultiGridSyncArg = 14,
+ HiddenHostcallBuffer = 15,
Unknown = 0xff
};
-/// Value types.
+/// Value types. This is deprecated and only remains for compatibility parsing
+/// of old metadata.
enum class ValueType : uint8_t {
Struct = 0,
I8 = 1,
@@ -163,7 +165,7 @@
constexpr char Align[] = "Align";
/// Key for Kernel::Arg::Metadata::mValueKind.
constexpr char ValueKind[] = "ValueKind";
-/// Key for Kernel::Arg::Metadata::mValueType.
+/// Key for Kernel::Arg::Metadata::mValueType. (deprecated)
constexpr char ValueType[] = "ValueType";
/// Key for Kernel::Arg::Metadata::mPointeeAlign.
constexpr char PointeeAlign[] = "PointeeAlign";
@@ -197,8 +199,6 @@
uint32_t mAlign = 0;
/// Value kind. Required.
ValueKind mValueKind = ValueKind::Unknown;
- /// Value type. Required.
- ValueType mValueType = ValueType::Unknown;
/// Pointee alignment in bytes. Optional.
uint32_t mPointeeAlign = 0;
/// Address space qualifier. Optional.
diff --git a/linux-x64/clang/include/llvm/Support/AMDHSAKernelDescriptor.h b/linux-x64/clang/include/llvm/Support/AMDHSAKernelDescriptor.h
index d1c2147..bd84da4 100644
--- a/linux-x64/clang/include/llvm/Support/AMDHSAKernelDescriptor.h
+++ b/linux-x64/clang/include/llvm/Support/AMDHSAKernelDescriptor.h
@@ -100,7 +100,7 @@
#define COMPUTE_PGM_RSRC2(NAME, SHIFT, WIDTH) \
AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC2_ ## NAME, SHIFT, WIDTH)
enum : int32_t {
- COMPUTE_PGM_RSRC2(ENABLE_SGPR_PRIVATE_SEGMENT_WAVEFRONT_OFFSET, 0, 1),
+ COMPUTE_PGM_RSRC2(ENABLE_PRIVATE_SEGMENT, 0, 1),
COMPUTE_PGM_RSRC2(USER_SGPR_COUNT, 1, 5),
COMPUTE_PGM_RSRC2(ENABLE_TRAP_HANDLER, 6, 1),
COMPUTE_PGM_RSRC2(ENABLE_SGPR_WORKGROUP_ID_X, 7, 1),
@@ -162,39 +162,49 @@
uint8_t reserved2[6];
};
+enum : uint32_t {
+ GROUP_SEGMENT_FIXED_SIZE_OFFSET = 0,
+ PRIVATE_SEGMENT_FIXED_SIZE_OFFSET = 4,
+ RESERVED0_OFFSET = 8,
+ KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET = 16,
+ RESERVED1_OFFSET = 24,
+ COMPUTE_PGM_RSRC3_OFFSET = 44,
+ COMPUTE_PGM_RSRC1_OFFSET = 48,
+ COMPUTE_PGM_RSRC2_OFFSET = 52,
+ KERNEL_CODE_PROPERTIES_OFFSET = 56,
+ RESERVED2_OFFSET = 58,
+};
+
static_assert(
sizeof(kernel_descriptor_t) == 64,
"invalid size for kernel_descriptor_t");
-static_assert(
- offsetof(kernel_descriptor_t, group_segment_fixed_size) == 0,
- "invalid offset for group_segment_fixed_size");
-static_assert(
- offsetof(kernel_descriptor_t, private_segment_fixed_size) == 4,
- "invalid offset for private_segment_fixed_size");
-static_assert(
- offsetof(kernel_descriptor_t, reserved0) == 8,
- "invalid offset for reserved0");
-static_assert(
- offsetof(kernel_descriptor_t, kernel_code_entry_byte_offset) == 16,
- "invalid offset for kernel_code_entry_byte_offset");
-static_assert(
- offsetof(kernel_descriptor_t, reserved1) == 24,
- "invalid offset for reserved1");
-static_assert(
- offsetof(kernel_descriptor_t, compute_pgm_rsrc3) == 44,
- "invalid offset for compute_pgm_rsrc3");
-static_assert(
- offsetof(kernel_descriptor_t, compute_pgm_rsrc1) == 48,
- "invalid offset for compute_pgm_rsrc1");
-static_assert(
- offsetof(kernel_descriptor_t, compute_pgm_rsrc2) == 52,
- "invalid offset for compute_pgm_rsrc2");
-static_assert(
- offsetof(kernel_descriptor_t, kernel_code_properties) == 56,
- "invalid offset for kernel_code_properties");
-static_assert(
- offsetof(kernel_descriptor_t, reserved2) == 58,
- "invalid offset for reserved2");
+static_assert(offsetof(kernel_descriptor_t, group_segment_fixed_size) ==
+ GROUP_SEGMENT_FIXED_SIZE_OFFSET,
+ "invalid offset for group_segment_fixed_size");
+static_assert(offsetof(kernel_descriptor_t, private_segment_fixed_size) ==
+ PRIVATE_SEGMENT_FIXED_SIZE_OFFSET,
+ "invalid offset for private_segment_fixed_size");
+static_assert(offsetof(kernel_descriptor_t, reserved0) == RESERVED0_OFFSET,
+ "invalid offset for reserved0");
+static_assert(offsetof(kernel_descriptor_t, kernel_code_entry_byte_offset) ==
+ KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET,
+ "invalid offset for kernel_code_entry_byte_offset");
+static_assert(offsetof(kernel_descriptor_t, reserved1) == RESERVED1_OFFSET,
+ "invalid offset for reserved1");
+static_assert(offsetof(kernel_descriptor_t, compute_pgm_rsrc3) ==
+ COMPUTE_PGM_RSRC3_OFFSET,
+ "invalid offset for compute_pgm_rsrc3");
+static_assert(offsetof(kernel_descriptor_t, compute_pgm_rsrc1) ==
+ COMPUTE_PGM_RSRC1_OFFSET,
+ "invalid offset for compute_pgm_rsrc1");
+static_assert(offsetof(kernel_descriptor_t, compute_pgm_rsrc2) ==
+ COMPUTE_PGM_RSRC2_OFFSET,
+ "invalid offset for compute_pgm_rsrc2");
+static_assert(offsetof(kernel_descriptor_t, kernel_code_properties) ==
+ KERNEL_CODE_PROPERTIES_OFFSET,
+ "invalid offset for kernel_code_properties");
+static_assert(offsetof(kernel_descriptor_t, reserved2) == RESERVED2_OFFSET,
+ "invalid offset for reserved2");
} // end namespace amdhsa
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/Support/ARMAttributeParser.h b/linux-x64/clang/include/llvm/Support/ARMAttributeParser.h
index f6c39ab..bf85ea1 100644
--- a/linux-x64/clang/include/llvm/Support/ARMAttributeParser.h
+++ b/linux-x64/clang/include/llvm/Support/ARMAttributeParser.h
@@ -1,4 +1,4 @@
-//===--- ARMAttributeParser.h - ARM Attribute Information Printer ---------===//
+//===- ARMAttributeParser.h - ARM Attribute Information Printer -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -10,132 +10,71 @@
#define LLVM_SUPPORT_ARMATTRIBUTEPARSER_H
#include "ARMBuildAttributes.h"
+#include "ELFAttributeParser.h"
#include "ScopedPrinter.h"
-
-#include <map>
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
namespace llvm {
class StringRef;
-class ARMAttributeParser {
- ScopedPrinter *SW;
-
- std::map<unsigned, unsigned> Attributes;
-
+class ARMAttributeParser : public ELFAttributeParser {
struct DisplayHandler {
- ARMBuildAttrs::AttrType Attribute;
- void (ARMAttributeParser::*Routine)(ARMBuildAttrs::AttrType,
- const uint8_t *, uint32_t &);
+ ARMBuildAttrs::AttrType attribute;
+ Error (ARMAttributeParser::*routine)(ARMBuildAttrs::AttrType);
};
- static const DisplayHandler DisplayRoutines[];
+ static const DisplayHandler displayRoutines[];
- uint64_t ParseInteger(const uint8_t *Data, uint32_t &Offset);
- StringRef ParseString(const uint8_t *Data, uint32_t &Offset);
+ Error handler(uint64_t tag, bool &handled) override;
- void IntegerAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void StringAttribute(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
+ Error stringAttribute(ARMBuildAttrs::AttrType tag);
- void PrintAttribute(unsigned Tag, unsigned Value, StringRef ValueDesc);
+ Error CPU_arch(ARMBuildAttrs::AttrType tag);
+ Error CPU_arch_profile(ARMBuildAttrs::AttrType tag);
+ Error ARM_ISA_use(ARMBuildAttrs::AttrType tag);
+ Error THUMB_ISA_use(ARMBuildAttrs::AttrType tag);
+ Error FP_arch(ARMBuildAttrs::AttrType tag);
+ Error WMMX_arch(ARMBuildAttrs::AttrType tag);
+ Error Advanced_SIMD_arch(ARMBuildAttrs::AttrType tag);
+ Error MVE_arch(ARMBuildAttrs::AttrType tag);
+ Error PCS_config(ARMBuildAttrs::AttrType tag);
+ Error ABI_PCS_R9_use(ARMBuildAttrs::AttrType tag);
+ Error ABI_PCS_RW_data(ARMBuildAttrs::AttrType tag);
+ Error ABI_PCS_RO_data(ARMBuildAttrs::AttrType tag);
+ Error ABI_PCS_GOT_use(ARMBuildAttrs::AttrType tag);
+ Error ABI_PCS_wchar_t(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_rounding(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_denormal(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_exceptions(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_user_exceptions(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_number_model(ARMBuildAttrs::AttrType tag);
+ Error ABI_align_needed(ARMBuildAttrs::AttrType tag);
+ Error ABI_align_preserved(ARMBuildAttrs::AttrType tag);
+ Error ABI_enum_size(ARMBuildAttrs::AttrType tag);
+ Error ABI_HardFP_use(ARMBuildAttrs::AttrType tag);
+ Error ABI_VFP_args(ARMBuildAttrs::AttrType tag);
+ Error ABI_WMMX_args(ARMBuildAttrs::AttrType tag);
+ Error ABI_optimization_goals(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_optimization_goals(ARMBuildAttrs::AttrType tag);
+ Error compatibility(ARMBuildAttrs::AttrType tag);
+ Error CPU_unaligned_access(ARMBuildAttrs::AttrType tag);
+ Error FP_HP_extension(ARMBuildAttrs::AttrType tag);
+ Error ABI_FP_16bit_format(ARMBuildAttrs::AttrType tag);
+ Error MPextension_use(ARMBuildAttrs::AttrType tag);
+ Error DIV_use(ARMBuildAttrs::AttrType tag);
+ Error DSP_extension(ARMBuildAttrs::AttrType tag);
+ Error T2EE_use(ARMBuildAttrs::AttrType tag);
+ Error Virtualization_use(ARMBuildAttrs::AttrType tag);
+ Error nodefaults(ARMBuildAttrs::AttrType tag);
- void CPU_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void CPU_arch_profile(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ARM_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void THUMB_ISA_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void FP_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void WMMX_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void Advanced_SIMD_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void MVE_arch(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void PCS_config(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_PCS_R9_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_PCS_RW_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_PCS_RO_data(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_PCS_GOT_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_PCS_wchar_t(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_FP_rounding(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_FP_denormal(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_FP_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_FP_user_exceptions(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_FP_number_model(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_align_needed(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_align_preserved(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_enum_size(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_HardFP_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_VFP_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_WMMX_args(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_optimization_goals(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_FP_optimization_goals(ARMBuildAttrs::AttrType Tag,
- const uint8_t *Data, uint32_t &Offset);
- void compatibility(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void CPU_unaligned_access(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void FP_HP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void ABI_FP_16bit_format(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void MPextension_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void DIV_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void DSP_extension(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void T2EE_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void Virtualization_use(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
- void nodefaults(ARMBuildAttrs::AttrType Tag, const uint8_t *Data,
- uint32_t &Offset);
-
- void ParseAttributeList(const uint8_t *Data, uint32_t &Offset,
- uint32_t Length);
- void ParseIndexList(const uint8_t *Data, uint32_t &Offset,
- SmallVectorImpl<uint8_t> &IndexList);
- void ParseSubsection(const uint8_t *Data, uint32_t Length);
public:
- ARMAttributeParser(ScopedPrinter *SW) : SW(SW) {}
-
- ARMAttributeParser() : SW(nullptr) { }
-
- void Parse(ArrayRef<uint8_t> Section, bool isLittle);
-
- bool hasAttribute(unsigned Tag) const {
- return Attributes.count(Tag);
- }
-
- unsigned getAttributeValue(unsigned Tag) const {
- return Attributes.find(Tag)->second;
- }
+ ARMAttributeParser(ScopedPrinter *sw)
+ : ELFAttributeParser(sw, ARMBuildAttrs::ARMAttributeTags, "aeabi") {}
+ ARMAttributeParser()
+ : ELFAttributeParser(ARMBuildAttrs::ARMAttributeTags, "aeabi") {}
};
-
}
#endif
-
diff --git a/linux-x64/clang/include/llvm/Support/ARMBuildAttributes.h b/linux-x64/clang/include/llvm/Support/ARMBuildAttributes.h
index 90481ea..5a06fd6 100644
--- a/linux-x64/clang/include/llvm/Support/ARMBuildAttributes.h
+++ b/linux-x64/clang/include/llvm/Support/ARMBuildAttributes.h
@@ -18,77 +18,70 @@
#ifndef LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
#define LLVM_SUPPORT_ARMBUILDATTRIBUTES_H
-namespace llvm {
-class StringRef;
+#include "llvm/Support/ELFAttributes.h"
+namespace llvm {
namespace ARMBuildAttrs {
+extern const TagNameMap ARMAttributeTags;
+
enum SpecialAttr {
// This is for the .cpu asm attr. It translates into one or more
// AttrType (below) entries in the .ARM.attributes section in the ELF.
SEL_CPU
};
-enum AttrType {
+enum AttrType : unsigned {
// Rest correspond to ELF/.ARM.attributes
- File = 1,
- CPU_raw_name = 4,
- CPU_name = 5,
- CPU_arch = 6,
- CPU_arch_profile = 7,
- ARM_ISA_use = 8,
- THUMB_ISA_use = 9,
- FP_arch = 10,
- WMMX_arch = 11,
- Advanced_SIMD_arch = 12,
- PCS_config = 13,
- ABI_PCS_R9_use = 14,
- ABI_PCS_RW_data = 15,
- ABI_PCS_RO_data = 16,
- ABI_PCS_GOT_use = 17,
- ABI_PCS_wchar_t = 18,
- ABI_FP_rounding = 19,
- ABI_FP_denormal = 20,
- ABI_FP_exceptions = 21,
- ABI_FP_user_exceptions = 22,
- ABI_FP_number_model = 23,
- ABI_align_needed = 24,
- ABI_align_preserved = 25,
- ABI_enum_size = 26,
- ABI_HardFP_use = 27,
- ABI_VFP_args = 28,
- ABI_WMMX_args = 29,
- ABI_optimization_goals = 30,
+ File = 1,
+ CPU_raw_name = 4,
+ CPU_name = 5,
+ CPU_arch = 6,
+ CPU_arch_profile = 7,
+ ARM_ISA_use = 8,
+ THUMB_ISA_use = 9,
+ FP_arch = 10,
+ WMMX_arch = 11,
+ Advanced_SIMD_arch = 12,
+ PCS_config = 13,
+ ABI_PCS_R9_use = 14,
+ ABI_PCS_RW_data = 15,
+ ABI_PCS_RO_data = 16,
+ ABI_PCS_GOT_use = 17,
+ ABI_PCS_wchar_t = 18,
+ ABI_FP_rounding = 19,
+ ABI_FP_denormal = 20,
+ ABI_FP_exceptions = 21,
+ ABI_FP_user_exceptions = 22,
+ ABI_FP_number_model = 23,
+ ABI_align_needed = 24,
+ ABI_align_preserved = 25,
+ ABI_enum_size = 26,
+ ABI_HardFP_use = 27,
+ ABI_VFP_args = 28,
+ ABI_WMMX_args = 29,
+ ABI_optimization_goals = 30,
ABI_FP_optimization_goals = 31,
- compatibility = 32,
- CPU_unaligned_access = 34,
- FP_HP_extension = 36,
- ABI_FP_16bit_format = 38,
- MPextension_use = 42, // recoded from 70 (ABI r2.08)
- DIV_use = 44,
- DSP_extension = 46,
- MVE_arch = 48,
- also_compatible_with = 65,
- conformance = 67,
- Virtualization_use = 68,
+ compatibility = 32,
+ CPU_unaligned_access = 34,
+ FP_HP_extension = 36,
+ ABI_FP_16bit_format = 38,
+ MPextension_use = 42, // recoded from 70 (ABI r2.08)
+ DIV_use = 44,
+ DSP_extension = 46,
+ MVE_arch = 48,
+ also_compatible_with = 65,
+ conformance = 67,
+ Virtualization_use = 68,
/// Legacy Tags
- Section = 2, // deprecated (ABI r2.09)
- Symbol = 3, // deprecated (ABI r2.09)
- ABI_align8_needed = 24, // renamed to ABI_align_needed (ABI r2.09)
- ABI_align8_preserved = 25, // renamed to ABI_align_preserved (ABI r2.09)
- nodefaults = 64, // deprecated (ABI r2.09)
- T2EE_use = 66, // deprecated (ABI r2.09)
- MPextension_use_old = 70 // recoded to MPextension_use (ABI r2.08)
-};
-
-StringRef AttrTypeAsString(unsigned Attr, bool HasTagPrefix = true);
-StringRef AttrTypeAsString(AttrType Attr, bool HasTagPrefix = true);
-int AttrTypeFromString(StringRef Tag);
-
-// Magic numbers for .ARM.attributes
-enum AttrMagic {
- Format_Version = 0x41
+ Section = 2, // deprecated (ABI r2.09)
+ Symbol = 3, // deprecated (ABI r2.09)
+ ABI_align8_needed = 24, // renamed to ABI_align_needed (ABI r2.09)
+ ABI_align8_preserved = 25, // renamed to ABI_align_preserved (ABI r2.09)
+ nodefaults = 64, // deprecated (ABI r2.09)
+ T2EE_use = 66, // deprecated (ABI r2.09)
+ MPextension_use_old = 70 // recoded to MPextension_use (ABI r2.08)
};
// Legal Values for CPU_arch, (=6), uleb128
diff --git a/linux-x64/clang/include/llvm/Support/ARMTargetParser.def b/linux-x64/clang/include/llvm/Support/ARMTargetParser.def
index 593480f..37cf0a9 100644
--- a/linux-x64/clang/include/llvm/Support/ARMTargetParser.def
+++ b/linux-x64/clang/include/llvm/Support/ARMTargetParser.def
@@ -112,6 +112,18 @@
(ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS |
ARM::AEK_DOTPROD))
+ARM_ARCH("armv8.6-a", ARMV8_6A, "8.6-A", "v8.6a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS |
+ ARM::AEK_DOTPROD | ARM::AEK_BF16 | ARM::AEK_SHA2 | ARM::AEK_AES |
+ ARM::AEK_I8MM))
+ARM_ARCH("armv8.7-a", ARMV8_7A, "8.7-A", "v8.7a",
+ ARMBuildAttrs::CPUArch::v8_A, FK_CRYPTO_NEON_FP_ARMV8,
+ (ARM::AEK_SEC | ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM |
+ ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_CRC | ARM::AEK_RAS |
+ ARM::AEK_DOTPROD | ARM::AEK_BF16 | ARM::AEK_SHA2 | ARM::AEK_AES |
+ ARM::AEK_I8MM))
ARM_ARCH("armv8-r", ARMV8R, "8-R", "v8r", ARMBuildAttrs::CPUArch::v8_R,
FK_NEON_FP_ARMV8,
(ARM::AEK_MP | ARM::AEK_VIRT | ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB |
@@ -148,8 +160,9 @@
ARM_ARCH_EXT_NAME("dotprod", ARM::AEK_DOTPROD, "+dotprod","-dotprod")
ARM_ARCH_EXT_NAME("dsp", ARM::AEK_DSP, "+dsp", "-dsp")
ARM_ARCH_EXT_NAME("fp", ARM::AEK_FP, nullptr, nullptr)
-ARM_ARCH_EXT_NAME("mve", ARM::AEK_SIMD, "+mve", "-mve")
-ARM_ARCH_EXT_NAME("mve.fp", (ARM::AEK_SIMD | ARM::AEK_FP), "+mve.fp", "-mve.fp")
+ARM_ARCH_EXT_NAME("fp.dp", ARM::AEK_FP_DP, nullptr, nullptr)
+ARM_ARCH_EXT_NAME("mve", (ARM::AEK_DSP | ARM::AEK_SIMD), "+mve", "-mve")
+ARM_ARCH_EXT_NAME("mve.fp", (ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP), "+mve.fp", "-mve.fp")
ARM_ARCH_EXT_NAME("idiv", (ARM::AEK_HWDIVARM | ARM::AEK_HWDIVTHUMB), nullptr, nullptr)
ARM_ARCH_EXT_NAME("mp", ARM::AEK_MP, nullptr, nullptr)
ARM_ARCH_EXT_NAME("simd", ARM::AEK_SIMD, nullptr, nullptr)
@@ -163,8 +176,18 @@
ARM_ARCH_EXT_NAME("maverick", ARM::AEK_MAVERICK, nullptr, nullptr)
ARM_ARCH_EXT_NAME("xscale", ARM::AEK_XSCALE, nullptr, nullptr)
ARM_ARCH_EXT_NAME("fp16fml", ARM::AEK_FP16FML, "+fp16fml", "-fp16fml")
+ARM_ARCH_EXT_NAME("bf16", ARM::AEK_BF16, "+bf16", "-bf16")
ARM_ARCH_EXT_NAME("sb", ARM::AEK_SB, "+sb", "-sb")
+ARM_ARCH_EXT_NAME("i8mm", ARM::AEK_I8MM, "+i8mm", "-i8mm")
ARM_ARCH_EXT_NAME("lob", ARM::AEK_LOB, "+lob", "-lob")
+ARM_ARCH_EXT_NAME("cdecp0", ARM::AEK_CDECP0, "+cdecp0", "-cdecp0")
+ARM_ARCH_EXT_NAME("cdecp1", ARM::AEK_CDECP1, "+cdecp1", "-cdecp1")
+ARM_ARCH_EXT_NAME("cdecp2", ARM::AEK_CDECP2, "+cdecp2", "-cdecp2")
+ARM_ARCH_EXT_NAME("cdecp3", ARM::AEK_CDECP3, "+cdecp3", "-cdecp3")
+ARM_ARCH_EXT_NAME("cdecp4", ARM::AEK_CDECP4, "+cdecp4", "-cdecp4")
+ARM_ARCH_EXT_NAME("cdecp5", ARM::AEK_CDECP5, "+cdecp5", "-cdecp5")
+ARM_ARCH_EXT_NAME("cdecp6", ARM::AEK_CDECP6, "+cdecp6", "-cdecp6")
+ARM_ARCH_EXT_NAME("cdecp7", ARM::AEK_CDECP7, "+cdecp7", "-cdecp7")
#undef ARM_ARCH_EXT_NAME
#ifndef ARM_HW_DIV_NAME
@@ -259,6 +282,8 @@
ARM_CPU_NAME("cortex-m23", ARMV8MBaseline, FK_NONE, false, ARM::AEK_NONE)
ARM_CPU_NAME("cortex-m33", ARMV8MMainline, FK_FPV5_SP_D16, false, ARM::AEK_DSP)
ARM_CPU_NAME("cortex-m35p", ARMV8MMainline, FK_FPV5_SP_D16, false, ARM::AEK_DSP)
+ARM_CPU_NAME("cortex-m55", ARMV8_1MMainline, FK_FP_ARMV8_FULLFP16_D16, false,
+ (ARM::AEK_DSP | ARM::AEK_SIMD | ARM::AEK_FP | ARM::AEK_FP16))
ARM_CPU_NAME("cortex-a32", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a35", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a53", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
@@ -273,9 +298,22 @@
(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("cortex-a77", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
+ARM_CPU_NAME("cortex-a78", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
+ARM_CPU_NAME("cortex-a78c", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ ARM::AEK_FP16 | ARM::AEK_DOTPROD)
+ARM_CPU_NAME("cortex-x1", 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("neoverse-n2", ARMV8_5A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_BF16 | ARM::AEK_DOTPROD | ARM::AEK_I8MM | ARM::AEK_RAS |
+ ARM::AEK_SB))
+ARM_CPU_NAME("neoverse-v1", ARMV8_4A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_RAS | ARM::AEK_FP16 | ARM::AEK_BF16 | 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)
ARM_CPU_NAME("exynos-m3", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("exynos-m4", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(ARM::AEK_FP16 | ARM::AEK_DOTPROD))
diff --git a/linux-x64/clang/include/llvm/Support/ARMTargetParser.h b/linux-x64/clang/include/llvm/Support/ARMTargetParser.h
index 4b9070d..7dd2abd 100644
--- a/linux-x64/clang/include/llvm/Support/ARMTargetParser.h
+++ b/linux-x64/clang/include/llvm/Support/ARMTargetParser.h
@@ -14,17 +14,20 @@
#ifndef LLVM_SUPPORT_ARMTARGETPARSER_H
#define LLVM_SUPPORT_ARMTARGETPARSER_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include <vector>
namespace llvm {
+
+class Triple;
+
namespace ARM {
// Arch extension modifiers for CPUs.
// Note that this is not the same as the AArch64 list
-enum ArchExtKind : unsigned {
+enum ArchExtKind : uint64_t {
AEK_INVALID = 0,
AEK_NONE = 1,
AEK_CRC = 1 << 1,
@@ -39,25 +42,30 @@
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,
+ AEK_BF16 = 1 << 20,
+ AEK_I8MM = 1 << 21,
+ AEK_CDECP0 = 1 << 22,
+ AEK_CDECP1 = 1 << 23,
+ AEK_CDECP2 = 1 << 24,
+ AEK_CDECP3 = 1 << 25,
+ AEK_CDECP4 = 1 << 26,
+ AEK_CDECP5 = 1 << 27,
+ AEK_CDECP6 = 1 << 28,
+ AEK_CDECP7 = 1 << 29,
+
// Unsupported extensions.
- AEK_OS = 0x8000000,
- AEK_IWMMXT = 0x10000000,
- AEK_IWMMXT2 = 0x20000000,
- AEK_MAVERICK = 0x40000000,
- AEK_XSCALE = 0x80000000,
+ AEK_OS = 1ULL << 59,
+ AEK_IWMMXT = 1ULL << 60,
+ AEK_IWMMXT2 = 1ULL << 61,
+ AEK_MAVERICK = 1ULL << 62,
+ AEK_XSCALE = 1ULL << 63,
};
// List of Arch Extension names.
@@ -65,7 +73,7 @@
struct ExtName {
const char *NameCStr;
size_t NameLength;
- unsigned ID;
+ uint64_t ID;
const char *Feature;
const char *NegFeature;
@@ -84,7 +92,7 @@
const struct {
const char *NameCStr;
size_t NameLength;
- unsigned ID;
+ uint64_t ID;
StringRef getName() const { return StringRef(NameCStr, NameLength); }
} HWDivNames[] = {
@@ -108,7 +116,7 @@
size_t NameLength;
T ArchID;
bool Default; // is $Name the default CPU for $ArchID ?
- unsigned DefaultExtensions;
+ uint64_t DefaultExtensions;
StringRef getName() const { return StringRef(NameCStr, NameLength); }
};
@@ -199,7 +207,7 @@
const char *SubArchCStr;
size_t SubArchLength;
unsigned DefaultFPU;
- unsigned ArchBaseExtensions;
+ uint64_t ArchBaseExtensions;
T ID;
ARMBuildAttrs::CPUArch ArchAttr; // Arch ID in build attributes.
@@ -231,33 +239,34 @@
// FIXME: These should be moved to TargetTuple once it exists
bool getFPUFeatures(unsigned FPUKind, std::vector<StringRef> &Features);
-bool getHWDivFeatures(unsigned HWDivKind, std::vector<StringRef> &Features);
-bool getExtensionFeatures(unsigned Extensions,
+bool getHWDivFeatures(uint64_t HWDivKind, std::vector<StringRef> &Features);
+bool getExtensionFeatures(uint64_t Extensions,
std::vector<StringRef> &Features);
StringRef getArchName(ArchKind AK);
unsigned getArchAttr(ArchKind AK);
StringRef getCPUAttr(ArchKind AK);
StringRef getSubArch(ArchKind AK);
-StringRef getArchExtName(unsigned ArchExtKind);
+StringRef getArchExtName(uint64_t ArchExtKind);
StringRef getArchExtFeature(StringRef ArchExt);
bool appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, StringRef ArchExt,
- std::vector<StringRef> &Features);
-StringRef getHWDivName(unsigned HWDivKind);
+ std::vector<StringRef> &Features,
+ unsigned &ArgFPUKind);
+StringRef getHWDivName(uint64_t HWDivKind);
// Information by Name
unsigned getDefaultFPU(StringRef CPU, ArchKind AK);
-unsigned getDefaultExtensions(StringRef CPU, ArchKind AK);
+uint64_t getDefaultExtensions(StringRef CPU, ArchKind AK);
StringRef getDefaultCPU(StringRef Arch);
StringRef getCanonicalArchName(StringRef Arch);
StringRef getFPUSynonym(StringRef FPU);
StringRef getArchSynonym(StringRef Arch);
// Parser
-unsigned parseHWDiv(StringRef HWDiv);
+uint64_t parseHWDiv(StringRef HWDiv);
unsigned parseFPU(StringRef FPU);
ArchKind parseArch(StringRef Arch);
-unsigned parseArchExt(StringRef ArchExt);
+uint64_t parseArchExt(StringRef ArchExt);
ArchKind parseCPUArch(StringRef CPU);
ISAKind parseArchISA(StringRef Arch);
EndianKind parseArchEndian(StringRef Arch);
diff --git a/linux-x64/clang/include/llvm/Support/ARMWinEH.h b/linux-x64/clang/include/llvm/Support/ARMWinEH.h
index 857a0d3..327aa98 100644
--- a/linux-x64/clang/include/llvm/Support/ARMWinEH.h
+++ b/linux-x64/clang/include/llvm/Support/ARMWinEH.h
@@ -31,6 +31,9 @@
/// RuntimeFunction - An entry in the table of procedure data (.pdata)
///
+/// This is ARM specific, but the Function Start RVA, Flag and
+/// ExceptionInformationRVA fields work identically for ARM64.
+///
/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
/// +---------------------------------------------------------------+
@@ -204,6 +207,85 @@
/// purpose (r0-r15) and VFP (d0-d31) registers.
std::pair<uint16_t, uint32_t> SavedRegisterMask(const RuntimeFunction &RF);
+/// RuntimeFunctionARM64 - An entry in the table of procedure data (.pdata)
+///
+/// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+/// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+/// +---------------------------------------------------------------+
+/// | Function Start RVA |
+/// +-----------------+---+-+-------+-----+---------------------+---+
+/// | Frame Size |CR |H| RegI |RegF | Function Length |Flg|
+/// +-----------------+---+-+-------+-----+---------------------+---+
+///
+/// See https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
+/// for the full reference for this struct.
+
+class RuntimeFunctionARM64 {
+public:
+ const support::ulittle32_t BeginAddress;
+ const support::ulittle32_t UnwindData;
+
+ RuntimeFunctionARM64(const support::ulittle32_t *Data)
+ : BeginAddress(Data[0]), UnwindData(Data[1]) {}
+
+ RuntimeFunctionARM64(const support::ulittle32_t BeginAddress,
+ const support::ulittle32_t UnwindData)
+ : BeginAddress(BeginAddress), UnwindData(UnwindData) {}
+
+ RuntimeFunctionFlag Flag() const {
+ return RuntimeFunctionFlag(UnwindData & 0x3);
+ }
+
+ uint32_t ExceptionInformationRVA() const {
+ assert(Flag() == RuntimeFunctionFlag::RFF_Unpacked &&
+ "unpacked form required for this operation");
+ return (UnwindData & ~0x3);
+ }
+
+ uint32_t PackedUnwindData() const {
+ assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
+ Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
+ "packed form required for this operation");
+ return (UnwindData & ~0x3);
+ }
+ uint32_t FunctionLength() const {
+ assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
+ Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
+ "packed form required for this operation");
+ return (((UnwindData & 0x00001ffc) >> 2) << 2);
+ }
+ uint8_t RegF() const {
+ assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
+ Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
+ "packed form required for this operation");
+ return ((UnwindData & 0x0000e000) >> 13);
+ }
+ uint8_t RegI() const {
+ assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
+ Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
+ "packed form required for this operation");
+ return ((UnwindData & 0x000f0000) >> 16);
+ }
+ bool H() const {
+ assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
+ Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
+ "packed form required for this operation");
+ return ((UnwindData & 0x00100000) >> 20);
+ }
+ uint8_t CR() const {
+ assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
+ Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
+ "packed form required for this operation");
+ return ((UnwindData & 0x600000) >> 21);
+ }
+ uint16_t FrameSize() const {
+ assert((Flag() == RuntimeFunctionFlag::RFF_Packed ||
+ Flag() == RuntimeFunctionFlag::RFF_PackedFragment) &&
+ "packed form required for this operation");
+ return ((UnwindData & 0xff800000) >> 23);
+ }
+};
+
/// ExceptionDataRecord - An entry in the table of exception data (.xdata)
///
/// The format on ARM is:
@@ -416,12 +498,13 @@
uint32_t ExceptionHandlerRVA() const {
assert(X() && "Exception Handler RVA is only valid if the X bit is set");
- return Data[HeaderWords(*this) + EpilogueCount() + CodeWords()];
+ return Data[HeaderWords(*this) + (E() ? 0 : EpilogueCount()) + CodeWords()];
}
uint32_t ExceptionHandlerParameter() const {
assert(X() && "Exception Handler RVA is only valid if the X bit is set");
- return Data[HeaderWords(*this) + EpilogueCount() + CodeWords() + 1];
+ return Data[HeaderWords(*this) + (E() ? 0 : EpilogueCount()) + CodeWords() +
+ 1];
}
};
diff --git a/linux-x64/clang/include/llvm/Support/AlignOf.h b/linux-x64/clang/include/llvm/Support/AlignOf.h
index d12401f..f586d7f 100644
--- a/linux-x64/clang/include/llvm/Support/AlignOf.h
+++ b/linux-x64/clang/include/llvm/Support/AlignOf.h
@@ -6,140 +6,29 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the AlignedCharArray and AlignedCharArrayUnion classes.
+// This file defines the AlignedCharArrayUnion class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_ALIGNOF_H
#define LLVM_SUPPORT_ALIGNOF_H
-#include "llvm/Support/Compiler.h"
-#include <cstddef>
+#include <type_traits>
namespace llvm {
-/// \struct AlignedCharArray
-/// Helper for building an aligned character array type.
+/// A suitably aligned and sized character array member which can hold elements
+/// of any 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];
+/// This template is equivalent to std::aligned_union_t<1, ...>, but we cannot
+/// use it due to a bug in the MSVC x86 compiler:
+/// https://github.com/microsoft/STL/issues/1533
+/// Using `alignas` here works around the bug.
+template <typename T, typename... Ts> struct AlignedCharArrayUnion {
+ using AlignedUnion = std::aligned_union_t<1, T, Ts...>;
+ alignas(alignof(AlignedUnion)) char buffer[sizeof(AlignedUnion)];
};
-#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];
- };
-};
-
-template<std::size_t Size>
-struct AlignedCharArray<8, Size> {
- union {
- double aligned;
- char buffer[Size];
- };
-};
-
-
-// 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;
-
- 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)];
-};
-} // 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.
-///
-/// 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>)> {
-};
} // end namespace llvm
#endif // LLVM_SUPPORT_ALIGNOF_H
diff --git a/linux-x64/clang/include/llvm/Support/Alignment.h b/linux-x64/clang/include/llvm/Support/Alignment.h
new file mode 100644
index 0000000..667434e
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/Alignment.h
@@ -0,0 +1,375 @@
+//===-- 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/MathExtras.h"
+#include <cassert>
+#ifndef NDEBUG
+#include <string>
+#endif // NDEBUG
+
+namespace llvm {
+
+#define ALIGN_CHECK_ISPOSITIVE(decl) \
+ assert(decl > 0 && (#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.
+ /// It was decided to deprecate Align::None because it's too close to
+ /// llvm::None which can be used to initialize `MaybeAlign`.
+ /// MaybeAlign = llvm::None means unspecified alignment,
+ /// Align = Align::None() means alignment of one byte.
+ LLVM_ATTRIBUTE_DEPRECATED(constexpr static const Align None(),
+ "Use Align() or Align(1) instead") {
+ 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 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 - 1U);
+}
+
+/// If non-zero \p Skew is specified, the return value will be a minimal integer
+/// that is greater than or equal to \p Size and equal to \p A * N + \p Skew for
+/// some integer N. If \p Skew is larger than \p A, its value is adjusted to '\p
+/// Skew mod \p A'.
+///
+/// Examples:
+/// \code
+/// alignTo(5, Align(8), 7) = 7
+/// alignTo(17, Align(8), 1) = 17
+/// alignTo(~0LL, Align(8), 3) = 3
+/// \endcode
+inline uint64_t alignTo(uint64_t Size, Align A, uint64_t Skew) {
+ const uint64_t Value = A.value();
+ Skew %= Value;
+ return ((Size + Value - 1 - Skew) & ~(Value - 1U)) + Skew;
+}
+
+/// 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 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;
+}
+
+/// 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;
+}
+
+// Don't allow relational comparisons with MaybeAlign.
+bool operator<=(Align Lhs, MaybeAlign Rhs) = delete;
+bool operator>=(Align Lhs, MaybeAlign Rhs) = delete;
+bool operator<(Align Lhs, MaybeAlign Rhs) = delete;
+bool operator>(Align Lhs, MaybeAlign Rhs) = delete;
+
+bool operator<=(MaybeAlign Lhs, Align Rhs) = delete;
+bool operator>=(MaybeAlign Lhs, Align Rhs) = delete;
+bool operator<(MaybeAlign Lhs, Align Rhs) = delete;
+bool operator>(MaybeAlign Lhs, Align Rhs) = delete;
+
+bool operator<=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
+bool operator>=(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
+bool operator<(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
+bool operator>(MaybeAlign Lhs, MaybeAlign Rhs) = delete;
+
+inline Align operator*(Align Lhs, uint64_t Rhs) {
+ assert(Rhs > 0 && "Rhs must be positive");
+ return Align(Lhs.value() * Rhs);
+}
+
+inline MaybeAlign operator*(MaybeAlign Lhs, uint64_t Rhs) {
+ assert(Rhs > 0 && "Rhs must be positive");
+ return Lhs ? Lhs.getValue() * Rhs : MaybeAlign();
+}
+
+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;
+}
+
+#ifndef NDEBUG
+// For usage in LLVM_DEBUG macros.
+inline std::string DebugStr(const Align &A) {
+ return std::to_string(A.value());
+}
+// For usage in LLVM_DEBUG macros.
+inline std::string DebugStr(const MaybeAlign &MA) {
+ if (MA)
+ return std::to_string(MA->value());
+ return "None";
+}
+#endif // NDEBUG
+
+#undef ALIGN_CHECK_ISPOSITIVE
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_ALIGNMENT_H_
diff --git a/linux-x64/clang/include/llvm/Support/Allocator.h b/linux-x64/clang/include/llvm/Support/Allocator.h
index 09e967b..245432d 100644
--- a/linux-x64/clang/include/llvm/Support/Allocator.h
+++ b/linux-x64/clang/include/llvm/Support/Allocator.h
@@ -7,13 +7,10 @@
//===----------------------------------------------------------------------===//
/// \file
///
-/// This file defines the MallocAllocator and BumpPtrAllocator interfaces. Both
-/// of these conform to an LLVM "Allocator" concept which consists of an
-/// Allocate method accepting a size and alignment, and a Deallocate accepting
-/// a pointer and size. Further, the LLVM "Allocator" concept has overloads of
-/// Allocate and Deallocate for setting size and alignment based on the final
-/// type. These overloads are typically provided by a base class template \c
-/// AllocatorBase.
+/// This file defines the BumpPtrAllocator interface. BumpPtrAllocator conforms
+/// to the LLVM "Allocator" concept and is similar to MallocAllocator, but
+/// objects cannot be deallocated. Their lifetime is tied to the lifetime of the
+/// allocator.
///
//===----------------------------------------------------------------------===//
@@ -22,6 +19,8 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Alignment.h"
+#include "llvm/Support/AllocatorBase.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -37,81 +36,6 @@
namespace llvm {
-/// CRTP base class providing obvious overloads for the core \c
-/// Allocate() methods of LLVM-style allocators.
-///
-/// This base class both documents the full public interface exposed by all
-/// LLVM-style allocators, and redirects all of the overloads to a single core
-/// set of methods which the derived class must define.
-template <typename DerivedT> class AllocatorBase {
-public:
- /// Allocate \a Size bytes of \a Alignment aligned memory. This method
- /// must be implemented by \c DerivedT.
- void *Allocate(size_t Size, size_t Alignment) {
-#ifdef __clang__
- static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>(
- &AllocatorBase::Allocate) !=
- static_cast<void *(DerivedT::*)(size_t, size_t)>(
- &DerivedT::Allocate),
- "Class derives from AllocatorBase without implementing the "
- "core Allocate(size_t, size_t) overload!");
-#endif
- return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
- }
-
- /// Deallocate \a Ptr to \a Size bytes of memory allocated by this
- /// allocator.
- void Deallocate(const void *Ptr, size_t Size) {
-#ifdef __clang__
- static_assert(static_cast<void (AllocatorBase::*)(const void *, size_t)>(
- &AllocatorBase::Deallocate) !=
- static_cast<void (DerivedT::*)(const void *, size_t)>(
- &DerivedT::Deallocate),
- "Class derives from AllocatorBase without implementing the "
- "core Deallocate(void *) overload!");
-#endif
- return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size);
- }
-
- // The rest of these methods are helpers that redirect to one of the above
- // core methods.
-
- /// Allocate space for a sequence of objects without constructing them.
- template <typename T> T *Allocate(size_t Num = 1) {
- return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
- }
-
- /// Deallocate space for a sequence of objects without constructing them.
- template <typename T>
- typename std::enable_if<
- !std::is_same<typename std::remove_cv<T>::type, void>::value, void>::type
- Deallocate(T *Ptr, size_t Num = 1) {
- Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T));
- }
-};
-
-class MallocAllocator : public AllocatorBase<MallocAllocator> {
-public:
- void Reset() {}
-
- LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size,
- size_t /*Alignment*/) {
- return safe_malloc(Size);
- }
-
- // Pull in base class overloads.
- using AllocatorBase<MallocAllocator>::Allocate;
-
- void Deallocate(const void *Ptr, size_t /*Size*/) {
- free(const_cast<void *>(Ptr));
- }
-
- // Pull in base class overloads.
- using AllocatorBase<MallocAllocator>::Deallocate;
-
- void PrintStats() const {}
-};
-
namespace detail {
// We call out to an external function to actually print the message as the
@@ -135,30 +59,37 @@
/// The BumpPtrAllocatorImpl template defaults to using a MallocAllocator
/// object, which wraps malloc, to allocate memory, but it can be changed to
/// use a custom allocator.
+///
+/// The GrowthDelay specifies after how many allocated slabs the allocator
+/// increases the size of the slabs.
template <typename AllocatorT = MallocAllocator, size_t SlabSize = 4096,
- size_t SizeThreshold = SlabSize>
+ size_t SizeThreshold = SlabSize, size_t GrowthDelay = 128>
class BumpPtrAllocatorImpl
- : public AllocatorBase<
- BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold>> {
+ : public AllocatorBase<BumpPtrAllocatorImpl<AllocatorT, SlabSize,
+ SizeThreshold, GrowthDelay>>,
+ private AllocatorT {
public:
static_assert(SizeThreshold <= SlabSize,
"The SizeThreshold must be at most the SlabSize to ensure "
"that objects larger than a slab go into their own memory "
"allocation.");
+ static_assert(GrowthDelay > 0,
+ "GrowthDelay must be at least 1 which already increases the"
+ "slab size after each allocated slab.");
BumpPtrAllocatorImpl() = default;
template <typename T>
BumpPtrAllocatorImpl(T &&Allocator)
- : Allocator(std::forward<T &&>(Allocator)) {}
+ : AllocatorT(std::forward<T &&>(Allocator)) {}
// Manually implement a move constructor as we must clear the old allocator's
// slabs as a matter of correctness.
BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old)
- : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)),
+ : AllocatorT(static_cast<AllocatorT &&>(Old)), CurPtr(Old.CurPtr),
+ End(Old.End), Slabs(std::move(Old.Slabs)),
CustomSizedSlabs(std::move(Old.CustomSizedSlabs)),
- BytesAllocated(Old.BytesAllocated), RedZoneSize(Old.RedZoneSize),
- Allocator(std::move(Old.Allocator)) {
+ BytesAllocated(Old.BytesAllocated), RedZoneSize(Old.RedZoneSize) {
Old.CurPtr = Old.End = nullptr;
Old.BytesAllocated = 0;
Old.Slabs.clear();
@@ -180,7 +111,7 @@
RedZoneSize = RHS.RedZoneSize;
Slabs = std::move(RHS.Slabs);
CustomSizedSlabs = std::move(RHS.CustomSizedSlabs);
- Allocator = std::move(RHS.Allocator);
+ AllocatorT::operator=(static_cast<AllocatorT &&>(RHS));
RHS.CurPtr = RHS.End = nullptr;
RHS.BytesAllocated = 0;
@@ -211,13 +142,11 @@
/// 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,9 +169,10 @@
}
// 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);
+ void *NewSlab =
+ AllocatorT::Allocate(PaddedSize, alignof(std::max_align_t));
// We own the new slab and don't want anyone reading anyting other than
// pieces returned from this method. So poison the whole slab.
__asan_poison_memory_region(NewSlab, PaddedSize);
@@ -268,13 +198,19 @@
return AlignedPtr;
}
+ inline LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+ Allocate(size_t Size, size_t Alignment) {
+ assert(Alignment > 0 && "0-byte alignment is not allowed. Use 1 instead.");
+ return Allocate(Size, Align(Alignment));
+ }
+
// Pull in base class overloads.
using AllocatorBase<BumpPtrAllocatorImpl>::Allocate;
// Bump pointer allocators are expected to never free their storage; and
// clients expect pointers to remain valid for non-dereferencing uses even
// after deallocation.
- void Deallocate(const void *Ptr, size_t Size) {
+ void Deallocate(const void *Ptr, size_t Size, size_t /*Alignment*/) {
__asan_poison_memory_region(Ptr, Size);
}
@@ -381,15 +317,13 @@
/// a sanitizer.
size_t RedZoneSize = 1;
- /// The allocator instance we use to get slabs of memory.
- AllocatorT Allocator;
-
static size_t computeSlabSize(unsigned SlabIdx) {
// Scale the actual allocated slab size based on the number of slabs
- // allocated. Every 128 slabs allocated, we double the allocated size to
- // reduce allocation frequency, but saturate at multiplying the slab size by
- // 2^30.
- return SlabSize * ((size_t)1 << std::min<size_t>(30, SlabIdx / 128));
+ // allocated. Every GrowthDelay slabs allocated, we double
+ // the allocated size to reduce allocation frequency, but saturate at
+ // multiplying the slab size by 2^30.
+ return SlabSize *
+ ((size_t)1 << std::min<size_t>(30, SlabIdx / GrowthDelay));
}
/// Allocate a new slab and move the bump pointers over into the new
@@ -397,7 +331,8 @@
void StartNewSlab() {
size_t AllocatedSlabSize = computeSlabSize(Slabs.size());
- void *NewSlab = Allocator.Allocate(AllocatedSlabSize, 0);
+ void *NewSlab =
+ AllocatorT::Allocate(AllocatedSlabSize, alignof(std::max_align_t));
// We own the new slab and don't want anyone reading anything other than
// pieces returned from this method. So poison the whole slab.
__asan_poison_memory_region(NewSlab, AllocatedSlabSize);
@@ -413,7 +348,7 @@
for (; I != E; ++I) {
size_t AllocatedSlabSize =
computeSlabSize(std::distance(Slabs.begin(), I));
- Allocator.Deallocate(*I, AllocatedSlabSize);
+ AllocatorT::Deallocate(*I, AllocatedSlabSize, alignof(std::max_align_t));
}
}
@@ -422,7 +357,7 @@
for (auto &PtrAndSize : CustomSizedSlabs) {
void *Ptr = PtrAndSize.first;
size_t Size = PtrAndSize.second;
- Allocator.Deallocate(Ptr, Size);
+ AllocatorT::Deallocate(Ptr, Size, alignof(std::max_align_t));
}
}
@@ -461,7 +396,7 @@
/// 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 +405,7 @@
++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 +415,8 @@
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();
@@ -492,26 +428,21 @@
} // end namespace llvm
-template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
-void *operator new(size_t Size,
- llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize,
- SizeThreshold> &Allocator) {
- struct S {
- char c;
- union {
- double D;
- long double LD;
- long long L;
- void *P;
- } x;
- };
- return Allocator.Allocate(
- Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x)));
+template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold,
+ size_t GrowthDelay>
+void *
+operator new(size_t Size,
+ llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold,
+ GrowthDelay> &Allocator) {
+ return Allocator.Allocate(Size, std::min((size_t)llvm::NextPowerOf2(Size),
+ alignof(std::max_align_t)));
}
-template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold>
-void operator delete(
- void *, llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize, SizeThreshold> &) {
+template <typename AllocatorT, size_t SlabSize, size_t SizeThreshold,
+ size_t GrowthDelay>
+void operator delete(void *,
+ llvm::BumpPtrAllocatorImpl<AllocatorT, SlabSize,
+ SizeThreshold, GrowthDelay> &) {
}
#endif // LLVM_SUPPORT_ALLOCATOR_H
diff --git a/linux-x64/clang/include/llvm/Support/AllocatorBase.h b/linux-x64/clang/include/llvm/Support/AllocatorBase.h
new file mode 100644
index 0000000..e5549d1
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/AllocatorBase.h
@@ -0,0 +1,103 @@
+//===- AllocatorBase.h - Simple memory allocation abstraction ---*- 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
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file defines MallocAllocator. MallocAllocator conforms to the LLVM
+/// "Allocator" concept which consists of an Allocate method accepting a size
+/// and alignment, and a Deallocate accepting a pointer and size. Further, the
+/// LLVM "Allocator" concept has overloads of Allocate and Deallocate for
+/// setting size and alignment based on the final type. These overloads are
+/// typically provided by a base class template \c AllocatorBase.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_ALLOCATORBASE_H
+#define LLVM_SUPPORT_ALLOCATORBASE_H
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemAlloc.h"
+
+namespace llvm {
+
+/// CRTP base class providing obvious overloads for the core \c
+/// Allocate() methods of LLVM-style allocators.
+///
+/// This base class both documents the full public interface exposed by all
+/// LLVM-style allocators, and redirects all of the overloads to a single core
+/// set of methods which the derived class must define.
+template <typename DerivedT> class AllocatorBase {
+public:
+ /// Allocate \a Size bytes of \a Alignment aligned memory. This method
+ /// must be implemented by \c DerivedT.
+ void *Allocate(size_t Size, size_t Alignment) {
+#ifdef __clang__
+ static_assert(static_cast<void *(AllocatorBase::*)(size_t, size_t)>(
+ &AllocatorBase::Allocate) !=
+ static_cast<void *(DerivedT::*)(size_t, size_t)>(
+ &DerivedT::Allocate),
+ "Class derives from AllocatorBase without implementing the "
+ "core Allocate(size_t, size_t) overload!");
+#endif
+ return static_cast<DerivedT *>(this)->Allocate(Size, Alignment);
+ }
+
+ /// Deallocate \a Ptr to \a Size bytes of memory allocated by this
+ /// allocator.
+ void Deallocate(const void *Ptr, size_t Size, size_t Alignment) {
+#ifdef __clang__
+ static_assert(
+ static_cast<void (AllocatorBase::*)(const void *, size_t, size_t)>(
+ &AllocatorBase::Deallocate) !=
+ static_cast<void (DerivedT::*)(const void *, size_t, size_t)>(
+ &DerivedT::Deallocate),
+ "Class derives from AllocatorBase without implementing the "
+ "core Deallocate(void *) overload!");
+#endif
+ return static_cast<DerivedT *>(this)->Deallocate(Ptr, Size, Alignment);
+ }
+
+ // The rest of these methods are helpers that redirect to one of the above
+ // core methods.
+
+ /// Allocate space for a sequence of objects without constructing them.
+ template <typename T> T *Allocate(size_t Num = 1) {
+ return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
+ }
+
+ /// Deallocate space for a sequence of objects without constructing them.
+ template <typename T>
+ std::enable_if_t<!std::is_same<std::remove_cv_t<T>, void>::value, void>
+ Deallocate(T *Ptr, size_t Num = 1) {
+ Deallocate(static_cast<const void *>(Ptr), Num * sizeof(T), alignof(T));
+ }
+};
+
+class MallocAllocator : public AllocatorBase<MallocAllocator> {
+public:
+ void Reset() {}
+
+ LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) {
+ return allocate_buffer(Size, Alignment);
+ }
+
+ // Pull in base class overloads.
+ using AllocatorBase<MallocAllocator>::Allocate;
+
+ void Deallocate(const void *Ptr, size_t Size, size_t Alignment) {
+ deallocate_buffer(const_cast<void *>(Ptr), Size, Alignment);
+ }
+
+ // Pull in base class overloads.
+ using AllocatorBase<MallocAllocator>::Deallocate;
+
+ void PrintStats() const {}
+};
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_ALLOCATORBASE_H
diff --git a/linux-x64/clang/include/llvm/Support/AtomicOrdering.h b/linux-x64/clang/include/llvm/Support/AtomicOrdering.h
index 763bc3e..27ca825 100644
--- a/linux-x64/clang/include/llvm/Support/AtomicOrdering.h
+++ b/linux-x64/clang/include/llvm/Support/AtomicOrdering.h
@@ -21,7 +21,7 @@
namespace llvm {
-/// Atomic ordering for C11 / C++11's memody models.
+/// Atomic ordering for C11 / C++11's memory models.
///
/// These values cannot change because they are shared with standard library
/// implementations as well as with other compilers.
@@ -53,7 +53,7 @@
///
/// not_atomic-->unordered-->relaxed-->release--------------->acq_rel-->seq_cst
/// \-->consume-->acquire--/
-enum class AtomicOrdering {
+enum class AtomicOrdering : unsigned {
NotAtomic = 0,
Unordered = 1,
Monotonic = 2, // Equivalent to C++'s relaxed.
@@ -61,7 +61,8 @@
Acquire = 4,
Release = 5,
AcquireRelease = 6,
- SequentiallyConsistent = 7
+ SequentiallyConsistent = 7,
+ LAST = SequentiallyConsistent
};
bool operator<(AtomicOrdering, AtomicOrdering) = delete;
@@ -86,7 +87,7 @@
/// Returns true if ao is stronger than other as defined by the AtomicOrdering
/// lattice, which is based on C++'s definition.
-inline bool isStrongerThan(AtomicOrdering ao, AtomicOrdering other) {
+inline bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other) {
static const bool lookup[8][8] = {
// NA UN RX CO AC RE AR SC
/* NotAtomic */ {false, false, false, false, false, false, false, false},
@@ -98,10 +99,10 @@
/* acq_rel */ { true, true, true, true, true, true, false, false},
/* seq_cst */ { true, true, true, true, true, true, true, false},
};
- return lookup[static_cast<size_t>(ao)][static_cast<size_t>(other)];
+ return lookup[static_cast<size_t>(AO)][static_cast<size_t>(Other)];
}
-inline bool isAtLeastOrStrongerThan(AtomicOrdering ao, AtomicOrdering other) {
+inline bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other) {
static const bool lookup[8][8] = {
// NA UN RX CO AC RE AR SC
/* NotAtomic */ { true, false, false, false, false, false, false, false},
@@ -113,26 +114,26 @@
/* acq_rel */ { true, true, true, true, true, true, true, false},
/* seq_cst */ { true, true, true, true, true, true, true, true},
};
- return lookup[static_cast<size_t>(ao)][static_cast<size_t>(other)];
+ return lookup[static_cast<size_t>(AO)][static_cast<size_t>(Other)];
}
-inline bool isStrongerThanUnordered(AtomicOrdering ao) {
- return isStrongerThan(ao, AtomicOrdering::Unordered);
+inline bool isStrongerThanUnordered(AtomicOrdering AO) {
+ return isStrongerThan(AO, AtomicOrdering::Unordered);
}
-inline bool isStrongerThanMonotonic(AtomicOrdering ao) {
- return isStrongerThan(ao, AtomicOrdering::Monotonic);
+inline bool isStrongerThanMonotonic(AtomicOrdering AO) {
+ return isStrongerThan(AO, AtomicOrdering::Monotonic);
}
-inline bool isAcquireOrStronger(AtomicOrdering ao) {
- return isAtLeastOrStrongerThan(ao, AtomicOrdering::Acquire);
+inline bool isAcquireOrStronger(AtomicOrdering AO) {
+ return isAtLeastOrStrongerThan(AO, AtomicOrdering::Acquire);
}
-inline bool isReleaseOrStronger(AtomicOrdering ao) {
- return isAtLeastOrStrongerThan(ao, AtomicOrdering::Release);
+inline bool isReleaseOrStronger(AtomicOrdering AO) {
+ return isAtLeastOrStrongerThan(AO, AtomicOrdering::Release);
}
-inline AtomicOrderingCABI toCABI(AtomicOrdering ao) {
+inline AtomicOrderingCABI toCABI(AtomicOrdering AO) {
static const AtomicOrderingCABI lookup[8] = {
/* NotAtomic */ AtomicOrderingCABI::relaxed,
/* Unordered */ AtomicOrderingCABI::relaxed,
@@ -143,7 +144,7 @@
/* acq_rel */ AtomicOrderingCABI::acq_rel,
/* seq_cst */ AtomicOrderingCABI::seq_cst,
};
- return lookup[static_cast<size_t>(ao)];
+ return lookup[static_cast<size_t>(AO)];
}
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/Support/Automaton.h b/linux-x64/clang/include/llvm/Support/Automaton.h
new file mode 100644
index 0000000..c2b9213
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/Automaton.h
@@ -0,0 +1,263 @@
+//===-- 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();
+ }
+
+ ArrayRef<NfaStatePair> getTransitionInfo() const {
+ return TransitionInfo;
+ }
+
+ 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 &Other)
+ : M(Other.M), State(Other.State), Transcribe(Other.Transcribe) {
+ // Transcriber is not thread-safe, so create a new instance on copy.
+ if (Other.Transcriber)
+ Transcriber = std::make_shared<internal::NfaTranscriber>(
+ Other.Transcriber->getTransitionInfo());
+ }
+
+ /// 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/linux-x64/clang/include/llvm/Support/Base64.h b/linux-x64/clang/include/llvm/Support/Base64.h
new file mode 100644
index 0000000..62064a3
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/Base64.h
@@ -0,0 +1,56 @@
+//===--- Base64.h - Base64 Encoder/Decoder ----------------------*- 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 generic base64 encoder/decoder.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_BASE64_H
+#define LLVM_SUPPORT_BASE64_H
+
+#include <string>
+
+namespace llvm {
+
+template <class InputBytes> std::string encodeBase64(InputBytes const &Bytes) {
+ static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+ std::string Buffer;
+ Buffer.resize(((Bytes.size() + 2) / 3) * 4);
+
+ size_t i = 0, j = 0;
+ for (size_t n = Bytes.size() / 3 * 3; i < n; i += 3, j += 4) {
+ uint32_t x = ((unsigned char)Bytes[i] << 16) |
+ ((unsigned char)Bytes[i + 1] << 8) |
+ (unsigned char)Bytes[i + 2];
+ Buffer[j + 0] = Table[(x >> 18) & 63];
+ Buffer[j + 1] = Table[(x >> 12) & 63];
+ Buffer[j + 2] = Table[(x >> 6) & 63];
+ Buffer[j + 3] = Table[x & 63];
+ }
+ if (i + 1 == Bytes.size()) {
+ uint32_t x = ((unsigned char)Bytes[i] << 16);
+ Buffer[j + 0] = Table[(x >> 18) & 63];
+ Buffer[j + 1] = Table[(x >> 12) & 63];
+ Buffer[j + 2] = '=';
+ Buffer[j + 3] = '=';
+ } else if (i + 2 == Bytes.size()) {
+ uint32_t x =
+ ((unsigned char)Bytes[i] << 16) | ((unsigned char)Bytes[i + 1] << 8);
+ Buffer[j + 0] = Table[(x >> 18) & 63];
+ Buffer[j + 1] = Table[(x >> 12) & 63];
+ Buffer[j + 2] = Table[(x >> 6) & 63];
+ Buffer[j + 3] = '=';
+ }
+ return Buffer;
+}
+
+} // end namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/BinaryItemStream.h b/linux-x64/clang/include/llvm/Support/BinaryItemStream.h
index 4cd66ad..4d27013 100644
--- a/linux-x64/clang/include/llvm/Support/BinaryItemStream.h
+++ b/linux-x64/clang/include/llvm/Support/BinaryItemStream.h
@@ -88,8 +88,7 @@
if (Offset >= getLength())
return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
++Offset;
- auto Iter =
- std::lower_bound(ItemEndOffsets.begin(), ItemEndOffsets.end(), Offset);
+ auto Iter = llvm::lower_bound(ItemEndOffsets, Offset);
size_t Idx = std::distance(ItemEndOffsets.begin(), Iter);
assert(Idx < Items.size() && "binary search for offset failed");
return Idx;
diff --git a/linux-x64/clang/include/llvm/Support/BinaryStreamArray.h b/linux-x64/clang/include/llvm/Support/BinaryStreamArray.h
index 96d09db..3ba65c0 100644
--- a/linux-x64/clang/include/llvm/Support/BinaryStreamArray.h
+++ b/linux-x64/clang/include/llvm/Support/BinaryStreamArray.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Error.h"
#include <cassert>
@@ -133,9 +134,9 @@
Extractor &getExtractor() { return E; }
BinaryStreamRef getUnderlyingStream() const { return Stream; }
- void setUnderlyingStream(BinaryStreamRef S, uint32_t Skew = 0) {
- Stream = S;
- this->Skew = Skew;
+ void setUnderlyingStream(BinaryStreamRef NewStream, uint32_t NewSkew = 0) {
+ Stream = NewStream;
+ Skew = NewSkew;
}
void drop_front() { Skew += begin()->length(); }
@@ -143,7 +144,7 @@
private:
BinaryStreamRef Stream;
Extractor E;
- uint32_t Skew;
+ uint32_t Skew = 0;
};
template <typename ValueType, typename Extractor>
@@ -274,6 +275,7 @@
return !(*this == Other);
}
+ FixedStreamArray(const FixedStreamArray &) = default;
FixedStreamArray &operator=(const FixedStreamArray &) = default;
const T &operator[](uint32_t Index) const {
@@ -286,7 +288,7 @@
// 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());
}
@@ -323,6 +325,8 @@
FixedStreamArrayIterator(const FixedStreamArray<T> &Array, uint32_t Index)
: Array(Array), Index(Index) {}
+ FixedStreamArrayIterator<T>(const FixedStreamArrayIterator<T> &Other)
+ : Array(Other.Array), Index(Other.Index) {}
FixedStreamArrayIterator<T> &
operator=(const FixedStreamArrayIterator<T> &Other) {
Array = Other.Array;
diff --git a/linux-x64/clang/include/llvm/Support/BinaryStreamReader.h b/linux-x64/clang/include/llvm/Support/BinaryStreamReader.h
index d8fddde..b611707 100644
--- a/linux-x64/clang/include/llvm/Support/BinaryStreamReader.h
+++ b/linux-x64/clang/include/llvm/Support/BinaryStreamReader.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/ConvertUTF.h"
@@ -89,7 +90,7 @@
template <typename T> Error readEnum(T &Dest) {
static_assert(std::is_enum<T>::value,
"Cannot call readEnum with non-enum value!");
- typename std::underlying_type<T>::type N;
+ std::underlying_type_t<T> N;
if (auto EC = readInteger(N))
return EC;
Dest = static_cast<T>(N);
@@ -148,14 +149,14 @@
/// returns an appropriate error code.
Error readStreamRef(BinaryStreamRef &Ref, uint32_t Length);
- /// Read \p Length bytes from the underlying stream into \p Stream. This is
+ /// Read \p Length bytes from the underlying stream into \p Ref. This is
/// equivalent to calling getUnderlyingStream().slice(Offset, Length).
/// Updates the stream's offset to point after the newly read object. Never
/// causes a copy.
///
/// \returns a success error code if the data was successfully read, otherwise
/// returns an appropriate error code.
- Error readSubstream(BinarySubstreamRef &Stream, uint32_t Size);
+ Error readSubstream(BinarySubstreamRef &Ref, uint32_t Length);
/// Get a pointer to an object of type T from the underlying stream, as if by
/// memcpy, and store the result into \p Dest. It is up to the caller to
@@ -198,7 +199,7 @@
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/linux-x64/clang/include/llvm/Support/BinaryStreamRef.h b/linux-x64/clang/include/llvm/Support/BinaryStreamRef.h
index 7427b8d..ba4c387 100644
--- a/linux-x64/clang/include/llvm/Support/BinaryStreamRef.h
+++ b/linux-x64/clang/include/llvm/Support/BinaryStreamRef.h
@@ -121,12 +121,12 @@
bool valid() const { return BorrowedImpl != nullptr; }
- bool operator==(const RefType &Other) const {
- if (BorrowedImpl != Other.BorrowedImpl)
+ friend bool operator==(const RefType &LHS, const RefType &RHS) {
+ if (LHS.BorrowedImpl != RHS.BorrowedImpl)
return false;
- if (ViewOffset != Other.ViewOffset)
+ if (LHS.ViewOffset != RHS.ViewOffset)
return false;
- if (Length != Other.Length)
+ if (LHS.Length != RHS.Length)
return false;
return true;
}
@@ -198,7 +198,7 @@
};
struct BinarySubstreamRef {
- uint32_t Offset; // Offset in the parent stream
+ uint32_t Offset = 0; // Offset in the parent stream
BinaryStreamRef StreamData; // Stream Data
BinarySubstreamRef slice(uint32_t Off, uint32_t Size) const {
@@ -211,8 +211,8 @@
BinarySubstreamRef keep_front(uint32_t N) const { return slice(0, N); }
std::pair<BinarySubstreamRef, BinarySubstreamRef>
- split(uint32_t Offset) const {
- return std::make_pair(keep_front(Offset), drop_front(Offset));
+ split(uint32_t Off) const {
+ return std::make_pair(keep_front(Off), drop_front(Off));
}
uint32_t size() const { return StreamData.getLength(); }
diff --git a/linux-x64/clang/include/llvm/Support/BinaryStreamWriter.h b/linux-x64/clang/include/llvm/Support/BinaryStreamWriter.h
index 86d2389..ceba792 100644
--- a/linux-x64/clang/include/llvm/Support/BinaryStreamWriter.h
+++ b/linux-x64/clang/include/llvm/Support/BinaryStreamWriter.h
@@ -75,7 +75,7 @@
static_assert(std::is_enum<T>::value,
"Cannot call writeEnum with non-Enum type");
- using U = typename std::underlying_type<T>::type;
+ using U = std::underlying_type_t<T>;
return writeInteger<U>(static_cast<U>(Num));
}
diff --git a/linux-x64/clang/include/llvm/Support/BranchProbability.h b/linux-x64/clang/include/llvm/Support/BranchProbability.h
index cd9d369..6c7ad1f 100644
--- a/linux-x64/clang/include/llvm/Support/BranchProbability.h
+++ b/linux-x64/clang/include/llvm/Support/BranchProbability.h
@@ -32,8 +32,8 @@
uint32_t N;
// Denominator, which is a constant value.
- static const uint32_t D = 1u << 31;
- static const uint32_t UnknownN = UINT32_MAX;
+ static constexpr uint32_t D = 1u << 31;
+ static constexpr uint32_t UnknownN = UINT32_MAX;
// Construct a BranchProbability with only numerator assuming the denominator
// is 1<<31. For internal use only.
diff --git a/linux-x64/clang/include/llvm/Support/CFGDiff.h b/linux-x64/clang/include/llvm/Support/CFGDiff.h
new file mode 100644
index 0000000..c90b9ac
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/CFGDiff.h
@@ -0,0 +1,177 @@
+//===- CFGDiff.h - Define a CFG snapshot. -----------------------*- 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 specializations of GraphTraits that allows generic
+// algorithms to see a different snapshot of a CFG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_CFGDIFF_H
+#define LLVM_SUPPORT_CFGDIFF_H
+
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/CFGUpdate.h"
+#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+
+// Two booleans are used to define orders in graphs:
+// InverseGraph defines when we need to reverse the whole graph and is as such
+// also equivalent to applying updates in reverse.
+// InverseEdge defines whether we want to change the edges direction. E.g., for
+// a non-inversed graph, the children are naturally the successors when
+// InverseEdge is false and the predecessors when InverseEdge is true.
+
+namespace llvm {
+
+namespace detail {
+template <typename Range>
+auto reverse_if_helper(Range &&R, std::integral_constant<bool, false>) {
+ return std::forward<Range>(R);
+}
+
+template <typename Range>
+auto reverse_if_helper(Range &&R, std::integral_constant<bool, true>) {
+ return llvm::reverse(std::forward<Range>(R));
+}
+
+template <bool B, typename Range> auto reverse_if(Range &&R) {
+ return reverse_if_helper(std::forward<Range>(R),
+ std::integral_constant<bool, B>{});
+}
+} // namespace detail
+
+// GraphDiff defines a CFG snapshot: given a set of Update<NodePtr>, provides
+// a getChildren method to get a Node's children based on the additional updates
+// in the snapshot. The current diff treats the CFG as a graph rather than a
+// multigraph. Added edges are pruned to be unique, and deleted edges will
+// remove all existing edges between two blocks.
+template <typename NodePtr, bool InverseGraph = false> class GraphDiff {
+ struct DeletesInserts {
+ SmallVector<NodePtr, 2> DI[2];
+ };
+ using UpdateMapType = SmallDenseMap<NodePtr, DeletesInserts>;
+ UpdateMapType Succ;
+ UpdateMapType Pred;
+
+ // By default, it is assumed that, given a CFG and a set of updates, we wish
+ // to apply these updates as given. If UpdatedAreReverseApplied is set, the
+ // updates will be applied in reverse: deleted edges are considered re-added
+ // and inserted edges are considered deleted when returning children.
+ bool UpdatedAreReverseApplied;
+
+ // Keep the list of legalized updates for a deterministic order of updates
+ // when using a GraphDiff for incremental updates in the DominatorTree.
+ // The list is kept in reverse to allow popping from end.
+ SmallVector<cfg::Update<NodePtr>, 4> LegalizedUpdates;
+
+ void printMap(raw_ostream &OS, const UpdateMapType &M) const {
+ StringRef DIText[2] = {"Delete", "Insert"};
+ for (auto Pair : M) {
+ for (unsigned IsInsert = 0; IsInsert <= 1; ++IsInsert) {
+ OS << DIText[IsInsert] << " edges: \n";
+ for (auto Child : Pair.second.DI[IsInsert]) {
+ OS << "(";
+ Pair.first->printAsOperand(OS, false);
+ OS << ", ";
+ Child->printAsOperand(OS, false);
+ OS << ") ";
+ }
+ }
+ }
+ OS << "\n";
+ }
+
+public:
+ GraphDiff() : UpdatedAreReverseApplied(false) {}
+ GraphDiff(ArrayRef<cfg::Update<NodePtr>> Updates,
+ bool ReverseApplyUpdates = false) {
+ cfg::LegalizeUpdates<NodePtr>(Updates, LegalizedUpdates, InverseGraph);
+ for (auto U : LegalizedUpdates) {
+ unsigned IsInsert =
+ (U.getKind() == cfg::UpdateKind::Insert) == !ReverseApplyUpdates;
+ Succ[U.getFrom()].DI[IsInsert].push_back(U.getTo());
+ Pred[U.getTo()].DI[IsInsert].push_back(U.getFrom());
+ }
+ UpdatedAreReverseApplied = ReverseApplyUpdates;
+ }
+
+ auto getLegalizedUpdates() const {
+ return make_range(LegalizedUpdates.begin(), LegalizedUpdates.end());
+ }
+
+ unsigned getNumLegalizedUpdates() const { return LegalizedUpdates.size(); }
+
+ cfg::Update<NodePtr> popUpdateForIncrementalUpdates() {
+ assert(!LegalizedUpdates.empty() && "No updates to apply!");
+ auto U = LegalizedUpdates.pop_back_val();
+ unsigned IsInsert =
+ (U.getKind() == cfg::UpdateKind::Insert) == !UpdatedAreReverseApplied;
+ auto &SuccDIList = Succ[U.getFrom()];
+ auto &SuccList = SuccDIList.DI[IsInsert];
+ assert(SuccList.back() == U.getTo());
+ SuccList.pop_back();
+ if (SuccList.empty() && SuccDIList.DI[!IsInsert].empty())
+ Succ.erase(U.getFrom());
+
+ auto &PredDIList = Pred[U.getTo()];
+ auto &PredList = PredDIList.DI[IsInsert];
+ assert(PredList.back() == U.getFrom());
+ PredList.pop_back();
+ if (PredList.empty() && PredDIList.DI[!IsInsert].empty())
+ Pred.erase(U.getTo());
+ return U;
+ }
+
+ using VectRet = SmallVector<NodePtr, 8>;
+ template <bool InverseEdge> VectRet getChildren(NodePtr N) const {
+ using DirectedNodeT =
+ std::conditional_t<InverseEdge, Inverse<NodePtr>, NodePtr>;
+ auto R = children<DirectedNodeT>(N);
+ VectRet Res = VectRet(detail::reverse_if<!InverseEdge>(R));
+
+ // Remove nullptr children for clang.
+ llvm::erase_value(Res, nullptr);
+
+ auto &Children = (InverseEdge != InverseGraph) ? Pred : Succ;
+ auto It = Children.find(N);
+ if (It == Children.end())
+ return Res;
+
+ // Remove children present in the CFG but not in the snapshot.
+ for (auto *Child : It->second.DI[0])
+ llvm::erase_value(Res, Child);
+
+ // Add children present in the snapshot for not in the real CFG.
+ auto &AddedChildren = It->second.DI[1];
+ llvm::append_range(Res, AddedChildren);
+
+ return Res;
+ }
+
+ void print(raw_ostream &OS) const {
+ OS << "===== GraphDiff: CFG edge changes to create a CFG snapshot. \n"
+ "===== (Note: notion of children/inverse_children depends on "
+ "the direction of edges and the graph.)\n";
+ OS << "Children to delete/insert:\n\t";
+ printMap(OS, Succ);
+ OS << "Inverse_children to delete/insert:\n\t";
+ printMap(OS, Pred);
+ OS << "\n";
+ }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
+#endif
+};
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_CFGDIFF_H
diff --git a/linux-x64/clang/include/llvm/Support/CFGUpdate.h b/linux-x64/clang/include/llvm/Support/CFGUpdate.h
index eeaf5d0..3a12b9d 100644
--- a/linux-x64/clang/include/llvm/Support/CFGUpdate.h
+++ b/linux-x64/clang/include/llvm/Support/CFGUpdate.h
@@ -14,7 +14,6 @@
#ifndef LLVM_SUPPORT_CFGUPDATE_H
#define LLVM_SUPPORT_CFGUPDATE_H
-#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Compiler.h"
@@ -62,7 +61,7 @@
template <typename NodePtr>
void LegalizeUpdates(ArrayRef<Update<NodePtr>> AllUpdates,
SmallVectorImpl<Update<NodePtr>> &Result,
- bool InverseGraph) {
+ bool InverseGraph, bool ReverseResultOrder = false) {
// Count the total number of inserions of each edge.
// Each insertion adds 1 and deletion subtracts 1. The end number should be
// one of {-1 (deletion), 0 (NOP), +1 (insertion)}. Otherwise, the sequence
@@ -104,11 +103,11 @@
Operations[{U.getTo(), U.getFrom()}] = int(i);
}
- llvm::sort(Result,
- [&Operations](const Update<NodePtr> &A, const Update<NodePtr> &B) {
- return Operations[{A.getFrom(), A.getTo()}] >
- Operations[{B.getFrom(), B.getTo()}];
- });
+ llvm::sort(Result, [&](const Update<NodePtr> &A, const Update<NodePtr> &B) {
+ const auto &OpA = Operations[{A.getFrom(), A.getTo()}];
+ const auto &OpB = Operations[{B.getFrom(), B.getTo()}];
+ return ReverseResultOrder ? OpA < OpB : OpA > OpB;
+ });
}
} // end namespace cfg
diff --git a/linux-x64/clang/include/llvm/Support/CRC.h b/linux-x64/clang/include/llvm/Support/CRC.h
index 6ea8e3e..210890a 100644
--- a/linux-x64/clang/include/llvm/Support/CRC.h
+++ b/linux-x64/clang/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/linux-x64/clang/include/llvm/Support/CachePruning.h b/linux-x64/clang/include/llvm/Support/CachePruning.h
index a72a864..10d6372 100644
--- a/linux-x64/clang/include/llvm/Support/CachePruning.h
+++ b/linux-x64/clang/include/llvm/Support/CachePruning.h
@@ -14,12 +14,13 @@
#ifndef LLVM_SUPPORT_CACHE_PRUNING_H
#define LLVM_SUPPORT_CACHE_PRUNING_H
-#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Optional.h"
#include <chrono>
namespace llvm {
template <typename T> class Expected;
+class StringRef;
/// Policy for the pruneCache() function. A default constructed
/// CachePruningPolicy provides a reasonable default policy.
diff --git a/linux-x64/clang/include/llvm/Support/Casting.h b/linux-x64/clang/include/llvm/Support/Casting.h
index 46bdedb..d6f7793 100644
--- a/linux-x64/clang/include/llvm/Support/Casting.h
+++ b/linux-x64/clang/include/llvm/Support/Casting.h
@@ -61,8 +61,7 @@
/// Always allow upcasts, and perform no dynamic check for them.
template <typename To, typename From>
-struct isa_impl<
- To, From, typename std::enable_if<std::is_base_of<To, From>::value>::type> {
+struct isa_impl<To, From, std::enable_if_t<std::is_base_of<To, From>::value>> {
static inline bool doit(const From &) { return true; }
};
@@ -133,24 +132,30 @@
}
};
-// isa<X> - Return true if the parameter to the template is an instance of the
-// template type argument. Used like this:
+// isa<X> - Return true if the parameter to the template is an instance of one
+// of the template type arguments. Used like this:
//
// if (isa<Type>(myVal)) { ... }
+// if (isa<Type0, Type1, Type2>(myVal)) { ... }
//
template <class X, class Y> LLVM_NODISCARD inline bool isa(const Y &Val) {
return isa_impl_wrap<X, const Y,
typename simplify_type<const Y>::SimpleType>::doit(Val);
}
+template <typename First, typename Second, typename... Rest, typename Y>
+LLVM_NODISCARD inline bool isa(const Y &Val) {
+ return isa<First>(Val) || isa<Second, Rest...>(Val);
+}
+
// isa_and_nonnull<X> - Functionally identical to isa, except that a null value
// is accepted.
//
-template <class X, class Y>
+template <typename... X, class Y>
LLVM_NODISCARD inline bool isa_and_nonnull(const Y &Val) {
if (!Val)
return false;
- return isa<X>(Val);
+ return isa<X...>(Val);
}
//===----------------------------------------------------------------------===//
@@ -184,7 +189,7 @@
struct cast_retty_impl<To, std::unique_ptr<From>> {
private:
using PointerType = typename cast_retty_impl<To, From *>::ret_type;
- using ResultType = typename std::remove_pointer<PointerType>::type;
+ using ResultType = std::remove_pointer_t<PointerType>;
public:
using ret_type = std::unique_ptr<ResultType>;
@@ -244,8 +249,8 @@
// cast<Instruction>(myVal)->getParent()
//
template <class X, class Y>
-inline typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, const Y>::ret_type>::type
+inline std::enable_if_t<!is_simple_type<Y>::value,
+ typename cast_retty<X, const Y>::ret_type>
cast(const Y &Val) {
assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
return cast_convert_val<
@@ -280,10 +285,9 @@
// accepted.
//
template <class X, class Y>
-LLVM_NODISCARD inline
- typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, const Y>::ret_type>::type
- cast_or_null(const Y &Val) {
+LLVM_NODISCARD inline std::enable_if_t<
+ !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>
+cast_or_null(const Y &Val) {
if (!Val)
return nullptr;
assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
@@ -291,10 +295,9 @@
}
template <class X, class Y>
-LLVM_NODISCARD inline
- typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, Y>::ret_type>::type
- cast_or_null(Y &Val) {
+LLVM_NODISCARD inline std::enable_if_t<!is_simple_type<Y>::value,
+ typename cast_retty<X, Y>::ret_type>
+cast_or_null(Y &Val) {
if (!Val)
return nullptr;
assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
@@ -326,10 +329,9 @@
//
template <class X, class Y>
-LLVM_NODISCARD inline
- typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, const Y>::ret_type>::type
- dyn_cast(const Y &Val) {
+LLVM_NODISCARD inline std::enable_if_t<
+ !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>
+dyn_cast(const Y &Val) {
return isa<X>(Val) ? cast<X>(Val) : nullptr;
}
@@ -347,18 +349,16 @@
// value is accepted.
//
template <class X, class Y>
-LLVM_NODISCARD inline
- typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, const Y>::ret_type>::type
- dyn_cast_or_null(const Y &Val) {
+LLVM_NODISCARD inline std::enable_if_t<
+ !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>
+dyn_cast_or_null(const Y &Val) {
return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
}
template <class X, class Y>
-LLVM_NODISCARD inline
- typename std::enable_if<!is_simple_type<Y>::value,
- typename cast_retty<X, Y>::ret_type>::type
- dyn_cast_or_null(Y &Val) {
+LLVM_NODISCARD inline std::enable_if_t<!is_simple_type<Y>::value,
+ typename cast_retty<X, Y>::ret_type>
+dyn_cast_or_null(Y &Val) {
return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
}
@@ -382,8 +382,7 @@
}
template <class X, class Y>
-LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val)
- -> decltype(cast<X>(Val)) {
+LLVM_NODISCARD inline auto unique_dyn_cast(std::unique_ptr<Y> &&Val) {
return unique_dyn_cast<X, Y>(Val);
}
@@ -398,8 +397,7 @@
}
template <class X, class Y>
-LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val)
- -> decltype(cast<X>(Val)) {
+LLVM_NODISCARD inline auto unique_dyn_cast_or_null(std::unique_ptr<Y> &&Val) {
return unique_dyn_cast_or_null<X, Y>(Val);
}
diff --git a/linux-x64/clang/include/llvm/Support/CheckedArithmetic.h b/linux-x64/clang/include/llvm/Support/CheckedArithmetic.h
index 8a50e3d..09e6d7e 100644
--- a/linux-x64/clang/include/llvm/Support/CheckedArithmetic.h
+++ b/linux-x64/clang/include/llvm/Support/CheckedArithmetic.h
@@ -25,11 +25,11 @@
/// \p RHS.
/// \return Empty optional if the operation overflows, or result otherwise.
template <typename T, typename F>
-typename std::enable_if<std::is_integral<T>::value && sizeof(T) * 8 <= 64,
- llvm::Optional<T>>::type
+std::enable_if_t<std::is_integral<T>::value && sizeof(T) * 8 <= 64,
+ llvm::Optional<T>>
checkedOp(T LHS, T RHS, F Op, bool Signed = true) {
- llvm::APInt ALHS(/*BitSize=*/sizeof(T) * 8, LHS, Signed);
- llvm::APInt ARHS(/*BitSize=*/sizeof(T) * 8, RHS, Signed);
+ llvm::APInt ALHS(sizeof(T) * 8, LHS, Signed);
+ llvm::APInt ARHS(sizeof(T) * 8, RHS, Signed);
bool Overflow;
llvm::APInt Out = (ALHS.*Op)(ARHS, Overflow);
if (Overflow)
@@ -44,7 +44,7 @@
/// \return Optional of sum if no signed overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
checkedAdd(T LHS, T RHS) {
return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov);
}
@@ -53,7 +53,7 @@
/// \return Optional of sum if no signed overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
checkedSub(T LHS, T RHS) {
return checkedOp(LHS, RHS, &llvm::APInt::ssub_ov);
}
@@ -62,7 +62,7 @@
/// \return Optional of product if no signed overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
checkedMul(T LHS, T RHS) {
return checkedOp(LHS, RHS, &llvm::APInt::smul_ov);
}
@@ -71,7 +71,7 @@
/// \return Optional of result if no signed overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_signed<T>::value, llvm::Optional<T>>
checkedMulAdd(T A, T B, T C) {
if (auto Product = checkedMul(A, B))
return checkedAdd(*Product, C);
@@ -82,7 +82,7 @@
/// \return Optional of sum if no unsigned overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_unsigned<T>::value, llvm::Optional<T>>
checkedAddUnsigned(T LHS, T RHS) {
return checkedOp(LHS, RHS, &llvm::APInt::uadd_ov, /*Signed=*/false);
}
@@ -91,7 +91,7 @@
/// \return Optional of product if no unsigned overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_unsigned<T>::value, llvm::Optional<T>>
checkedMulUnsigned(T LHS, T RHS) {
return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, /*Signed=*/false);
}
@@ -100,7 +100,7 @@
/// \return Optional of result if no unsigned overflow occurred,
/// \c None otherwise.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, llvm::Optional<T>>::type
+std::enable_if_t<std::is_unsigned<T>::value, llvm::Optional<T>>
checkedMulAddUnsigned(T A, T B, T C) {
if (auto Product = checkedMulUnsigned(A, B))
return checkedAddUnsigned(*Product, C);
diff --git a/linux-x64/clang/include/llvm/Support/Chrono.h b/linux-x64/clang/include/llvm/Support/Chrono.h
index 334ab60..098512d 100644
--- a/linux-x64/clang/include/llvm/Support/Chrono.h
+++ b/linux-x64/clang/include/llvm/Support/Chrono.h
@@ -112,8 +112,8 @@
struct format_provider<std::chrono::duration<Rep, Period>> {
private:
typedef std::chrono::duration<Rep, Period> Dur;
- typedef typename std::conditional<
- std::chrono::treat_as_floating_point<Rep>::value, double, intmax_t>::type
+ typedef std::conditional_t<std::chrono::treat_as_floating_point<Rep>::value,
+ double, intmax_t>
InternalRep;
template <typename AsPeriod> static InternalRep getAs(const Dur &D) {
diff --git a/linux-x64/clang/include/llvm/Support/CodeGen.h b/linux-x64/clang/include/llvm/Support/CodeGen.h
index a3f423e..e2aa2b6 100644
--- a/linux-x64/clang/include/llvm/Support/CodeGen.h
+++ b/linux-x64/clang/include/llvm/Support/CodeGen.h
@@ -57,6 +57,15 @@
};
}
+ /// These enums are meant to be passed into addPassesToEmitFile to indicate
+ /// what type of file to emit, and returned by it to indicate what type of
+ /// file could actually be made.
+ enum CodeGenFileType {
+ CGFT_AssemblyFile,
+ CGFT_ObjectFile,
+ CGFT_Null // Do not emit any output.
+ };
+
// Specify effect of frame pointer elimination optimization.
namespace FramePointer {
enum FP {All, NonLeaf, None};
diff --git a/linux-x64/clang/include/llvm/Support/CommandLine.h b/linux-x64/clang/include/llvm/Support/CommandLine.h
index 3cc2c3c..38f3e18 100644
--- a/linux-x64/clang/include/llvm/Support/CommandLine.h
+++ b/linux-x64/clang/include/llvm/Support/CommandLine.h
@@ -20,6 +20,8 @@
#define LLVM_SUPPORT_COMMANDLINE_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
@@ -29,6 +31,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <climits>
@@ -42,7 +45,6 @@
namespace llvm {
class StringSaver;
-class raw_ostream;
/// cl Namespace - This namespace contains all of the command line option
/// processing machinery. It is intentionally a short name to make qualified
@@ -69,13 +71,6 @@
const char *EnvVar = nullptr,
bool LongOptionsUseDoubleDash = false);
-//===----------------------------------------------------------------------===//
-// ParseEnvironmentOptions - Environment variable option processing alternate
-// entry point.
-//
-void ParseEnvironmentOptions(const char *progName, const char *envvar,
- const char *Overview = "");
-
// Function pointer type for printing version information.
using VersionPrinterTy = std::function<void(raw_ostream &)>;
@@ -468,6 +463,42 @@
template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); }
};
+// Specify a callback function to be called when an option is seen.
+// Can be used to set other options automatically.
+template <typename R, typename Ty> struct cb {
+ std::function<R(Ty)> CB;
+
+ cb(std::function<R(Ty)> CB) : CB(CB) {}
+
+ template <typename Opt> void apply(Opt &O) const { O.setCallback(CB); }
+};
+
+namespace detail {
+template <typename F>
+struct callback_traits : public callback_traits<decltype(&F::operator())> {};
+
+template <typename R, typename C, typename... Args>
+struct callback_traits<R (C::*)(Args...) const> {
+ using result_type = R;
+ using arg_type = std::tuple_element_t<0, std::tuple<Args...>>;
+ static_assert(sizeof...(Args) == 1, "callback function must have one and only one parameter");
+ static_assert(std::is_same<result_type, void>::value,
+ "callback return type must be void");
+ static_assert(std::is_lvalue_reference<arg_type>::value &&
+ std::is_const<std::remove_reference_t<arg_type>>::value,
+ "callback arg_type must be a const lvalue reference");
+};
+} // namespace detail
+
+template <typename F>
+cb<typename detail::callback_traits<F>::result_type,
+ typename detail::callback_traits<F>::arg_type>
+callback(F CB) {
+ using result_type = typename detail::callback_traits<F>::result_type;
+ using arg_type = typename detail::callback_traits<F>::arg_type;
+ return cb<result_type, arg_type>(CB);
+}
+
//===----------------------------------------------------------------------===//
// OptionValue class
@@ -641,7 +672,7 @@
: Values(Options) {}
template <class Opt> void apply(Opt &O) const {
- for (auto Value : Values)
+ for (const auto &Value : Values)
O.getParser().addLiteralOption(Value.Name, Value.Value,
Value.Description);
}
@@ -952,6 +983,50 @@
extern template class basic_parser<int>;
//--------------------------------------------------
+// parser<long>
+//
+template <> class parser<long> final : public basic_parser<long> {
+public:
+ parser(Option &O) : basic_parser(O) {}
+
+ // parse - Return true on error.
+ bool parse(Option &O, StringRef ArgName, StringRef Arg, long &Val);
+
+ // getValueName - Overload in subclass to provide a better default value.
+ StringRef getValueName() const override { return "long"; }
+
+ void printOptionDiff(const Option &O, long V, OptVal Default,
+ size_t GlobalWidth) const;
+
+ // An out-of-line virtual method to provide a 'home' for this class.
+ void anchor() override;
+};
+
+extern template class basic_parser<long>;
+
+//--------------------------------------------------
+// parser<long long>
+//
+template <> class parser<long long> : public basic_parser<long long> {
+public:
+ parser(Option &O) : basic_parser(O) {}
+
+ // parse - Return true on error.
+ bool parse(Option &O, StringRef ArgName, StringRef Arg, long long &Val);
+
+ // getValueName - Overload in subclass to provide a better default value.
+ StringRef getValueName() const override { return "long"; }
+
+ void printOptionDiff(const Option &O, long long V, OptVal Default,
+ size_t GlobalWidth) const;
+
+ // An out-of-line virtual method to provide a 'home' for this class.
+ void anchor() override;
+};
+
+extern template class basic_parser<long long>;
+
+//--------------------------------------------------
// parser<unsigned>
//
template <> class parser<unsigned> : public basic_parser<unsigned> {
@@ -1341,6 +1416,7 @@
return true; // Parse error!
this->setValue(Val);
this->setPosition(pos);
+ Callback(Val);
return false;
}
@@ -1368,16 +1444,16 @@
}
}
- template <class T, class = typename std::enable_if<
- std::is_assignable<T&, T>::value>::type>
+ template <class T,
+ class = std::enable_if_t<std::is_assignable<T &, T>::value>>
void setDefaultImpl() {
const OptionValue<DataType> &V = this->getDefault();
if (V.hasValue())
this->setValue(V.getValue());
}
- template <class T, class = typename std::enable_if<
- !std::is_assignable<T&, T>::value>::type>
+ template <class T,
+ class = std::enable_if_t<!std::is_assignable<T &, T>::value>>
void setDefaultImpl(...) {}
void setDefault() override { setDefaultImpl<DataType>(); }
@@ -1399,15 +1475,24 @@
template <class T> DataType &operator=(const T &Val) {
this->setValue(Val);
+ Callback(Val);
return this->getValue();
}
template <class... Mods>
explicit opt(const Mods &... Ms)
- : Option(Optional, NotHidden), Parser(*this) {
+ : Option(llvm::cl::Optional, NotHidden), Parser(*this) {
apply(this, Ms...);
done();
}
+
+ void setCallback(
+ std::function<void(const typename ParserClass::parser_data_type &)> CB) {
+ Callback = CB;
+ }
+
+ std::function<void(const typename ParserClass::parser_data_type &)> Callback =
+ [](const typename ParserClass::parser_data_type &) {};
};
extern template class opt<unsigned>;
@@ -1513,8 +1598,8 @@
reference front() { return Storage.front(); }
const_reference front() const { return Storage.front(); }
- operator std::vector<DataType>&() { return Storage; }
- operator ArrayRef<DataType>() { return Storage; }
+ operator std::vector<DataType> &() { return Storage; }
+ operator ArrayRef<DataType>() const { return Storage; }
std::vector<DataType> *operator&() { return &Storage; }
const std::vector<DataType> *operator&() const { return &Storage; }
@@ -1547,6 +1632,7 @@
list_storage<DataType, StorageClass>::addValue(Val);
setPosition(pos);
Positions.push_back(pos);
+ Callback(Val);
return false;
}
@@ -1593,6 +1679,14 @@
apply(this, Ms...);
done();
}
+
+ void setCallback(
+ std::function<void(const typename ParserClass::parser_data_type &)> CB) {
+ Callback = CB;
+ }
+
+ std::function<void(const typename ParserClass::parser_data_type &)> Callback =
+ [](const typename ParserClass::parser_data_type &) {};
};
// multi_val - Modifier to set the number of additional values.
@@ -1693,6 +1787,7 @@
this->addValue(Val);
setPosition(pos);
Positions.push_back(pos);
+ Callback(Val);
return false;
}
@@ -1734,6 +1829,14 @@
apply(this, Ms...);
done();
}
+
+ void setCallback(
+ std::function<void(const typename ParserClass::parser_data_type &)> CB) {
+ Callback = CB;
+ }
+
+ std::function<void(const typename ParserClass::parser_data_type &)> Callback =
+ [](const typename ParserClass::parser_data_type &) {};
};
//===----------------------------------------------------------------------===//
@@ -1831,7 +1934,7 @@
//
/// Use this to get a StringMap to all registered named options
-/// (e.g. -help). Note \p Map Should be an empty StringMap.
+/// (e.g. -help).
///
/// \return A reference to the StringMap used by the cl APIs to parse options.
///
@@ -1916,6 +2019,13 @@
SmallVectorImpl<const char *> &NewArgv,
bool MarkEOLs = false);
+/// Tokenizes a Windows command line while attempting to avoid copies. If no
+/// quoting or escaping was used, this produces substrings of the original
+/// string. If a token requires unquoting, it will be allocated with the
+/// StringSaver.
+void TokenizeWindowsCommandLineNoCopy(StringRef Source, StringSaver &Saver,
+ SmallVectorImpl<StringRef> &NewArgv);
+
/// String tokenization function type. Should be compatible with either
/// Windows or Unix command line tokenizers.
using TokenizerCallback = void (*)(StringRef Source, StringSaver &Saver,
@@ -1964,10 +2074,24 @@
/// with nullptrs in the Argv vector.
/// \param [in] RelativeNames true if names of nested response files must be
/// resolved relative to including file.
+/// \param [in] FS File system used for all file access when running the tool.
+/// \param [in] CurrentDir Path used to resolve relative rsp files. If set to
+/// None, process' cwd is used instead.
/// \return true if all @files were expanded successfully or there were none.
-bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
- SmallVectorImpl<const char *> &Argv,
- bool MarkEOLs = false, bool RelativeNames = false);
+bool ExpandResponseFiles(
+ StringSaver &Saver, TokenizerCallback Tokenizer,
+ SmallVectorImpl<const char *> &Argv, bool MarkEOLs = false,
+ bool RelativeNames = false,
+ llvm::vfs::FileSystem &FS = *llvm::vfs::getRealFileSystem(),
+ llvm::Optional<llvm::StringRef> CurrentDir = llvm::None);
+
+/// A convenience helper which concatenates the options specified by the
+/// environment variable EnvVar and command line options, then expands response
+/// files recursively. The tokenizer is a predefined GNU or Windows one.
+/// \return true if all @files were expanded successfully or there were none.
+bool expandResponseFiles(int Argc, const char *const *Argv, const char *EnvVar,
+ StringSaver &Saver,
+ SmallVectorImpl<const char *> &NewArgv);
/// Mark all options not part of this category as cl::ReallyHidden.
///
@@ -2000,6 +2124,9 @@
/// 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/linux-x64/clang/include/llvm/Support/Compiler.h b/linux-x64/clang/include/llvm/Support/Compiler.h
index 3f4f465..9348ada 100644
--- a/linux-x64/clang/include/llvm/Support/Compiler.h
+++ b/linux-x64/clang/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
@@ -78,7 +95,8 @@
/// Does the compiler support ref-qualifiers for *this?
///
/// Sadly, this is separate from just rvalue reference support because GCC
-/// and MSVC implemented this later than everything else.
+/// and MSVC implemented this later than everything else. This appears to be
+/// corrected in MSVC 2019 but not MSVC 2017.
#if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1)
#define LLVM_HAS_RVALUE_REFERENCE_THIS 1
#else
@@ -100,11 +118,17 @@
/// not accessible from outside it. Can also be used to mark variables and
/// functions, making them private to any shared library they are linked into.
/// On PE/COFF targets, library visibility is the default, so this isn't needed.
+///
+/// LLVM_EXTERNAL_VISIBILITY - classes, functions, and variables marked with
+/// this attribute will be made public and visible outside of any shared library
+/// they are linked in to.
#if (__has_attribute(visibility) || LLVM_GNUC_PREREQ(4, 0, 0)) && \
!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32)
#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden")))
+#define LLVM_EXTERNAL_VISIBILITY __attribute__ ((visibility("default")))
#else
#define LLVM_LIBRARY_VISIBILITY
+#define LLVM_EXTERNAL_VISIBILITY
#endif
#if defined(__GNUC__)
@@ -120,14 +144,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 defined(__cplusplus) && __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 +167,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
@@ -206,11 +234,11 @@
/// 3.4 supported this but is buggy in various cases and produces unimplemented
/// errors, just use it in GCC 4.0 and later.
#if __has_attribute(always_inline) || LLVM_GNUC_PREREQ(4, 0, 0)
-#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline))
#elif defined(_MSC_VER)
#define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline
#else
-#define LLVM_ATTRIBUTE_ALWAYS_INLINE
+#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline
#endif
#ifdef __GNUC__
@@ -240,15 +268,13 @@
#endif
/// LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
-#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
+#if defined(__cplusplus) && __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,13 +282,29 @@
/// 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
#define LLVM_REQUIRE_CONSTANT_INITIALIZATION
#endif
+/// LLVM_GSL_OWNER - Apply this to owning classes like SmallVector to enable
+/// lifetime warnings.
+#if LLVM_HAS_CPP_ATTRIBUTE(gsl::Owner)
+#define LLVM_GSL_OWNER [[gsl::Owner]]
+#else
+#define LLVM_GSL_OWNER
+#endif
+
+/// LLVM_GSL_POINTER - Apply this to non-owning classes like
+/// StringRef to enable lifetime warnings.
+#if LLVM_HAS_CPP_ATTRIBUTE(gsl::Pointer)
+#define LLVM_GSL_POINTER [[gsl::Pointer]]
+#else
+#define LLVM_GSL_POINTER
+#endif
+
/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
/// pedantic diagnostics.
#ifdef __GNUC__
@@ -272,19 +314,9 @@
#endif
// LLVM_ATTRIBUTE_DEPRECATED(decl, "message")
-#if __has_feature(attribute_deprecated_with_message)
-# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
- decl __attribute__((deprecated(message)))
-#elif defined(__GNUC__)
-# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
- decl __attribute__((deprecated))
-#elif defined(_MSC_VER)
-# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
- __declspec(deprecated(message)) decl
-#else
-# define LLVM_ATTRIBUTE_DEPRECATED(decl, message) \
- decl
-#endif
+// This macro will be removed.
+// Use C++14's attribute instead: [[deprecated("message")]]
+#define LLVM_ATTRIBUTE_DEPRECATED(decl, message) [[deprecated(message)]] decl
/// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands
/// to an expression which states that it is undefined behavior for the
@@ -331,21 +363,12 @@
#if __has_builtin(__builtin_assume_aligned) || LLVM_GNUC_PREREQ(4, 7, 0)
# define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a)
#elif defined(LLVM_BUILTIN_UNREACHABLE)
-// As of today, clang does not support __builtin_assume_aligned.
# define LLVM_ASSUME_ALIGNED(p, a) \
(((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p)))
#else
# 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 +399,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)
@@ -395,10 +418,12 @@
#if __has_feature(memory_sanitizer)
# define LLVM_MEMORY_SANITIZER_BUILD 1
# include <sanitizer/msan_interface.h>
+# define LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE __attribute__((no_sanitize_memory))
#else
# define LLVM_MEMORY_SANITIZER_BUILD 0
# define __msan_allocated_memory(p, size)
# define __msan_unpoison(p, size)
+# define LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE
#endif
/// \macro LLVM_ADDRESS_SANITIZER_BUILD
@@ -493,19 +518,15 @@
/// extern globals, and static globals.
///
/// This is essentially an extremely restricted analog to C++11's thread_local
-/// support, and uses that when available. However, it falls back on
-/// platform-specific or vendor-provided extensions when necessary. These
-/// extensions don't support many of the C++11 thread_local's features. You
-/// should only use this for PODs that you can statically initialize to
-/// some constant value. In almost all circumstances this is most appropriate
-/// for use with a pointer, integer, or small aggregation of pointers and
-/// integers.
+/// support. It uses thread_local if available, falling back on gcc __thread
+/// if not. __thread doesn't support many of the C++11 thread_local's
+/// features. You should only use this for PODs that you can statically
+/// initialize to some constant value. In almost all circumstances this is most
+/// appropriate for use with a pointer, integer, or small aggregation of
+/// pointers and integers.
#if LLVM_ENABLE_THREADS
-#if __has_feature(cxx_thread_local)
+#if __has_feature(cxx_thread_local) || defined(_MSC_VER)
#define LLVM_THREAD_LOCAL thread_local
-#elif defined(_MSC_VER)
-// MSVC supports this with a __declspec.
-#define LLVM_THREAD_LOCAL __declspec(thread)
#else
// Clang, GCC, and other compatible compilers used __thread prior to C++11 and
// we only need the restricted functionality that provides.
@@ -527,46 +548,4 @@
#define LLVM_ENABLE_EXCEPTIONS 1
#endif
-namespace llvm {
-
-/// Allocate a buffer of memory with the given size and alignment.
-///
-/// When the compiler supports aligned operator new, this will use it to to
-/// handle even over-aligned allocations.
-///
-/// However, this doesn't make any attempt to leverage the fancier techniques
-/// like posix_memalign due to portability. It is mostly intended to allow
-/// compatibility with platforms that, after aligned allocation was added, use
-/// reduced default alignment.
-inline void *allocate_buffer(size_t Size, size_t Alignment) {
- return ::operator new(Size
-#ifdef __cpp_aligned_new
- ,
- std::align_val_t(Alignment)
-#endif
- );
-}
-
-/// Deallocate a buffer of memory with the given size and alignment.
-///
-/// If supported, this will used the sized delete operator. Also if supported,
-/// this will pass the alignment to the delete operator.
-///
-/// The pointer must have been allocated with the corresponding new operator,
-/// most likely using the above helper.
-inline void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) {
- ::operator delete(Ptr
-#ifdef __cpp_sized_deallocation
- ,
- Size
-#endif
-#ifdef __cpp_aligned_new
- ,
- std::align_val_t(Alignment)
-#endif
- );
-}
-
-} // End namespace llvm
-
#endif
diff --git a/linux-x64/clang/include/llvm/Support/CrashRecoveryContext.h b/linux-x64/clang/include/llvm/Support/CrashRecoveryContext.h
index feb449e..f756635 100644
--- a/linux-x64/clang/include/llvm/Support/CrashRecoveryContext.h
+++ b/linux-x64/clang/include/llvm/Support/CrashRecoveryContext.h
@@ -44,11 +44,11 @@
/// executed in any case, whether crash occurs or not. These actions may be used
/// to reclaim resources in the case of crash.
class CrashRecoveryContext {
- void *Impl;
- CrashRecoveryContextCleanup *head;
+ void *Impl = nullptr;
+ CrashRecoveryContextCleanup *head = nullptr;
public:
- CrashRecoveryContext() : Impl(nullptr), head(nullptr) {}
+ CrashRecoveryContext();
~CrashRecoveryContext();
/// Register cleanup handler, which is used when the recovery context is
@@ -99,7 +99,20 @@
/// Explicitly trigger a crash recovery in the current process, and
/// return failure from RunSafely(). This function does not return.
- void HandleCrash();
+ LLVM_ATTRIBUTE_NORETURN
+ void HandleExit(int RetCode);
+
+ /// Throw again a signal or an exception, after it was catched once by a
+ /// CrashRecoveryContext.
+ static bool throwIfCrash(int RetCode);
+
+ /// In case of a crash, this is the crash identifier.
+ int RetCode = 0;
+
+ /// Selects whether handling of failures should be done in the same way as
+ /// for regular crashes. When this is active, a crash would print the
+ /// callstack, clean-up any temporary files and create a coredump/minidump.
+ bool DumpStackAndCleanupOnFailure = false;
};
/// Abstract base class of cleanup handlers.
@@ -111,12 +124,12 @@
/// a crash recovery context.
class CrashRecoveryContextCleanup {
protected:
- CrashRecoveryContext *context;
+ CrashRecoveryContext *context = nullptr;
CrashRecoveryContextCleanup(CrashRecoveryContext *context)
- : context(context), cleanupFired(false) {}
+ : context(context) {}
public:
- bool cleanupFired;
+ bool cleanupFired = false;
virtual ~CrashRecoveryContextCleanup();
virtual void recoverResources() = 0;
@@ -127,7 +140,7 @@
private:
friend class CrashRecoveryContext;
- CrashRecoveryContextCleanup *prev, *next;
+ CrashRecoveryContextCleanup *prev = nullptr, *next = nullptr;
};
/// Base class of cleanup handler that controls recovery of resources of the
@@ -172,7 +185,7 @@
: CrashRecoveryContextCleanupBase<
CrashRecoveryContextDestructorCleanup<T>, T>(context, resource) {}
- virtual void recoverResources() {
+ void recoverResources() override {
this->resource->~T();
}
};
diff --git a/linux-x64/clang/include/llvm/Support/DOTGraphTraits.h b/linux-x64/clang/include/llvm/Support/DOTGraphTraits.h
index ec01b7d..a73538f 100644
--- a/linux-x64/clang/include/llvm/Support/DOTGraphTraits.h
+++ b/linux-x64/clang/include/llvm/Support/DOTGraphTraits.h
@@ -60,7 +60,8 @@
/// isNodeHidden - If the function returns true, the given node is not
/// displayed in the graph.
- static bool isNodeHidden(const void *) {
+ template <typename GraphType>
+ static bool isNodeHidden(const void *, const GraphType &) {
return false;
}
diff --git a/linux-x64/clang/include/llvm/Support/DataExtractor.h b/linux-x64/clang/include/llvm/Support/DataExtractor.h
index 6b08a2a..f9335c1 100644
--- a/linux-x64/clang/include/llvm/Support/DataExtractor.h
+++ b/linux-x64/clang/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 @@
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 @@
/// 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; }
@@ -67,25 +105,38 @@
/// updated with the offset of the byte that follows the NULL
/// terminator byte.
///
- /// @param[in,out] offset_ptr
+ /// @param[in,out] OffsetPtr
/// 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
/// 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
/// A pointer to the C string value in the data. If the offset
/// 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 *OffsetPtr, Error *Err = nullptr) const {
+ return getCStrRef(OffsetPtr, Err).data();
+ }
- /// Extract a C string from \a *OffsetPtr.
+ /// Extract a C string from the location given by the cursor. In case of an
+ /// extraction error, or if the cursor is already in an error state, a
+ /// nullptr is returned.
+ const char *getCStr(Cursor &C) const { return getCStrRef(C).data(); }
+
+ /// 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.
///
@@ -96,12 +147,95 @@
/// 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
+ /// A StringRef for the C string value in the data. If the offset
+ /// 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(uint64_t *OffsetPtr, Error *Err = nullptr) const;
+
+ /// Extract a C string (as a StringRef) from the location given by the cursor.
+ /// In case of an extraction error, or if the cursor is already in an error
+ /// state, a default-initialized StringRef is returned.
+ StringRef getCStrRef(Cursor &C) const {
+ return getCStrRef(&C.Offset, &C.Err);
+ }
+
+ /// Extract a fixed length string from \a *OffsetPtr and consume \a Length
+ /// bytes.
+ ///
+ /// Returns a StringRef for the string from the data at the offset
+ /// pointed to by \a OffsetPtr. A fixed length C string will be extracted
+ /// and the \a OffsetPtr will be advanced by \a Length bytes.
+ ///
+ /// \param[in,out] OffsetPtr
+ /// 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
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// \param[in] Length
+ /// The length of the fixed length string to extract. If there are not
+ /// enough bytes in the data to extract the full string, the offset will
+ /// be left unmodified.
+ ///
+ /// \param[in] TrimChars
+ /// A set of characters to trim from the end of the string. Fixed length
+ /// strings are commonly either NULL terminated by one or more zero
+ /// bytes. Some clients have one or more spaces at the end of the string,
+ /// but a good default is to trim the NULL characters.
+ ///
/// \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
/// 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 getFixedLengthString(uint64_t *OffsetPtr,
+ uint64_t Length, StringRef TrimChars = {"\0", 1}) const;
+
+ /// Extract a fixed number of bytes from the specified offset.
+ ///
+ /// Returns a StringRef for the bytes from the data at the offset
+ /// pointed to by \a OffsetPtr. A fixed length C string will be extracted
+ /// and the \a OffsetPtr will be advanced by \a Length bytes.
+ ///
+ /// \param[in,out] OffsetPtr
+ /// 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
+ /// enough bytes to extract this value, the offset will be left
+ /// unmodified.
+ ///
+ /// \param[in] Length
+ /// The number of bytes to extract. If there are not enough bytes in the
+ /// data to extract all of the bytes, 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
+ /// A StringRef for the extracted bytes. If the offset pointed to by
+ /// \a OffsetPtr is out of bounds, or if the offset plus the length
+ /// is out of bounds, a default-initialized StringRef will be returned.
+ StringRef getBytes(uint64_t *OffsetPtr, uint64_t Length,
+ Error *Err = nullptr) const;
+
+ /// Extract a fixed number of bytes from the location given by the cursor. In
+ /// case of an extraction error, or if the cursor is already in an error
+ /// state, a default-initialized StringRef is returned.
+ StringRef getBytes(Cursor &C, uint64_t Length) {
+ return getBytes(&C.Offset, Length, &C.Err);
+ }
/// Extract an unsigned integer of size \a byte_size from \a
/// *offset_ptr.
@@ -124,10 +258,24 @@
/// @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 +300,7 @@
/// @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 +319,15 @@
///
/// @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 +340,20 @@
/// 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 +378,27 @@
/// @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 +413,21 @@
/// 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 +452,7 @@
/// @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.
@@ -266,15 +461,26 @@
/// \a offset_ptr, construct a uint32_t from them and update the offset
/// on success.
///
- /// @param[in,out] offset_ptr
+ /// @param[in,out] OffsetPtr
/// A pointer to an offset within the data that will be advanced
/// by the 3 bytes if the value is extracted correctly. If the offset
/// is out of bounds or there are not 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 24-bit value represented in a uint32_t.
- uint32_t getU24(uint32_t *offset_ptr) const;
+ uint32_t getU24(uint64_t *OffsetPtr, Error *Err = nullptr) const;
+
+ /// Extract a single 24-bit unsigned 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 getU24(Cursor &C) const { return getU24(&C.Offset, &C.Err); }
/// Extract a uint32_t value from \a *offset_ptr.
///
@@ -288,9 +494,20 @@
/// 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 +532,7 @@
/// @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 +546,20 @@
/// 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 +584,7 @@
/// @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.
///
@@ -365,16 +593,27 @@
/// pointed to by \a offset_ptr will be updated with the offset of
/// the byte following the last extracted byte.
///
- /// @param[in,out] offset_ptr
+ /// @param[in,out] OffsetPtr
/// 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
/// 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 signed integer value.
- int64_t getSLEB128(uint32_t *offset_ptr) const;
+ int64_t getSLEB128(uint64_t *OffsetPtr, Error *Err = nullptr) const;
+
+ /// Extract an signed LEB128 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.
+ int64_t getSLEB128(Cursor &C) const { return getSLEB128(&C.Offset, &C.Err); }
/// Extract a unsigned LEB128 value from \a *offset_ptr.
///
@@ -390,23 +629,44 @@
/// 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 LEB128 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 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 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 +677,28 @@
/// \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);
}
+
+ /// Return the number of bytes in the underlying buffer.
+ size_t size() const { return Data.size(); }
+
+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; }
+
+private:
+ /// If it is possible to read \a Size bytes at offset \a Offset, returns \b
+ /// true. Otherwise, returns \b false. If \a E is not nullptr, also sets the
+ /// error object to indicate an error.
+ bool prepareRead(uint64_t Offset, uint64_t Size, Error *E) const;
+
+ template <typename T> T getU(uint64_t *OffsetPtr, Error *Err) const;
+ template <typename T>
+ T *getUs(uint64_t *OffsetPtr, T *Dst, uint32_t Count, Error *Err) const;
};
} // namespace llvm
diff --git a/linux-x64/clang/include/llvm/Support/DebugCounter.h b/linux-x64/clang/include/llvm/Support/DebugCounter.h
index e7d1fa6..cd9474a 100644
--- a/linux-x64/clang/include/llvm/Support/DebugCounter.h
+++ b/linux-x64/clang/include/llvm/Support/DebugCounter.h
@@ -44,14 +44,15 @@
#define LLVM_SUPPORT_DEBUGCOUNTER_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/UniqueVector.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
#include <string>
namespace llvm {
+class raw_ostream;
+
class DebugCounter {
public:
~DebugCounter();
@@ -68,7 +69,7 @@
// line option parsing. The main reason to register counters is to produce a
// nice list of them on the command line, but i'm not sure this is worth it.
static unsigned registerCounter(StringRef Name, StringRef Desc) {
- return instance().addCounter(Name, Desc);
+ return instance().addCounter(std::string(Name), std::string(Desc));
}
inline static bool shouldExecute(unsigned CounterName) {
if (!isCountingEnabled())
diff --git a/linux-x64/clang/include/llvm/Support/ELFAttributeParser.h b/linux-x64/clang/include/llvm/Support/ELFAttributeParser.h
new file mode 100644
index 0000000..8bf87b2
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/ELFAttributeParser.h
@@ -0,0 +1,72 @@
+//===- ELF AttributeParser.h - ELF Attribute Parser -------------*- 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_ELFATTRIBUTEPARSER_H
+#define LLVM_SUPPORT_ELFATTRIBUTEPARSER_H
+
+#include "ELFAttributes.h"
+#include "ScopedPrinter.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Error.h"
+
+#include <unordered_map>
+
+namespace llvm {
+class StringRef;
+
+class ELFAttributeParser {
+ StringRef vendor;
+ std::unordered_map<unsigned, unsigned> attributes;
+ std::unordered_map<unsigned, StringRef> attributesStr;
+
+ virtual Error handler(uint64_t tag, bool &handled) = 0;
+
+protected:
+ ScopedPrinter *sw;
+ TagNameMap tagToStringMap;
+ DataExtractor de{ArrayRef<uint8_t>{}, true, 0};
+ DataExtractor::Cursor cursor{0};
+
+ void printAttribute(unsigned tag, unsigned value, StringRef valueDesc);
+
+ Error parseStringAttribute(const char *name, unsigned tag,
+ ArrayRef<const char *> strings);
+ Error parseAttributeList(uint32_t length);
+ void parseIndexList(SmallVectorImpl<uint8_t> &indexList);
+ Error parseSubsection(uint32_t length);
+
+public:
+ virtual ~ELFAttributeParser() { static_cast<void>(!cursor.takeError()); }
+ Error integerAttribute(unsigned tag);
+ Error stringAttribute(unsigned tag);
+
+ ELFAttributeParser(ScopedPrinter *sw, TagNameMap tagNameMap, StringRef vendor)
+ : vendor(vendor), sw(sw), tagToStringMap(tagNameMap) {}
+
+ ELFAttributeParser(TagNameMap tagNameMap, StringRef vendor)
+ : vendor(vendor), sw(nullptr), tagToStringMap(tagNameMap) {}
+
+ Error parse(ArrayRef<uint8_t> section, support::endianness endian);
+
+ Optional<unsigned> getAttributeValue(unsigned tag) const {
+ auto I = attributes.find(tag);
+ if (I == attributes.end())
+ return None;
+ return I->second;
+ }
+ Optional<StringRef> getAttributeString(unsigned tag) const {
+ auto I = attributesStr.find(tag);
+ if (I == attributesStr.end())
+ return None;
+ return I->second;
+ }
+};
+
+} // namespace llvm
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/ELFAttributes.h b/linux-x64/clang/include/llvm/Support/ELFAttributes.h
new file mode 100644
index 0000000..c8a7ae1
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/ELFAttributes.h
@@ -0,0 +1,37 @@
+//===-- ELFAttributes.h - ELF Attributes ------------------------*- 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_ELFATTRIBUTES_H
+#define LLVM_SUPPORT_ELFATTRIBUTES_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+struct TagNameItem {
+ unsigned attr;
+ StringRef tagName;
+};
+
+using TagNameMap = ArrayRef<TagNameItem>;
+
+namespace ELFAttrs {
+
+enum AttrType : unsigned { File = 1, Section = 2, Symbol = 3 };
+
+StringRef attrTypeAsString(unsigned attr, TagNameMap tagNameMap,
+ bool hasTagPrefix = true);
+Optional<unsigned> attrTypeFromString(StringRef tag, TagNameMap tagNameMap);
+
+// Magic numbers for ELF attributes.
+enum AttrMagic { Format_Version = 0x41 };
+
+} // namespace ELFAttrs
+} // namespace llvm
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/Endian.h b/linux-x64/clang/include/llvm/Support/Endian.h
index d8be944..5e7c1e9 100644
--- a/linux-x64/clang/include/llvm/Support/Endian.h
+++ b/linux-x64/clang/include/llvm/Support/Endian.h
@@ -13,9 +13,7 @@
#ifndef LLVM_SUPPORT_ENDIAN_H
#define LLVM_SUPPORT_ENDIAN_H
-#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/SwapByteOrder.h"
#include <cassert>
#include <cstddef>
@@ -111,7 +109,7 @@
}
template <typename value_type>
-using make_unsigned_t = typename std::make_unsigned<value_type>::type;
+using make_unsigned_t = std::make_unsigned_t<value_type>;
/// Read a value of a particular endianness from memory, for a location
/// that starts at the given bit offset within the first byte.
@@ -203,9 +201,8 @@
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 +243,9 @@
}
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/linux-x64/clang/include/llvm/Support/Errno.h b/linux-x64/clang/include/llvm/Support/Errno.h
index aedb5fb..dc3b332 100644
--- a/linux-x64/clang/include/llvm/Support/Errno.h
+++ b/linux-x64/clang/include/llvm/Support/Errno.h
@@ -30,8 +30,8 @@
std::string StrError(int errnum);
template <typename FailT, typename Fun, typename... Args>
-inline auto RetryAfterSignal(const FailT &Fail, const Fun &F,
- const Args &... As) -> decltype(F(As...)) {
+inline decltype(auto) RetryAfterSignal(const FailT &Fail, const Fun &F,
+ const Args &... As) {
decltype(F(As...)) Res;
do {
errno = 0;
diff --git a/linux-x64/clang/include/llvm/Support/Error.h b/linux-x64/clang/include/llvm/Support/Error.h
index 299fce7..c0f7c10 100644
--- a/linux-x64/clang/include/llvm/Support/Error.h
+++ b/linux-x64/clang/include/llvm/Support/Error.h
@@ -155,10 +155,10 @@
/// they're moved-assigned or constructed from Success values that have already
/// been checked. This enforces checking through all levels of the call stack.
class LLVM_NODISCARD Error {
- // Both ErrorList and FileError need to be able to yank ErrorInfoBase
- // pointers out of this class to add to the error list.
+ // ErrorList needs to be able to yank ErrorInfoBase pointers out of Errors
+ // to add to the error list. It can't rely on handleErrors for this, since
+ // handleErrors does not support ErrorList handlers.
friend class ErrorList;
- friend class FileError;
// handleErrors needs to be able to set the Checked flag.
template <typename... HandlerTs>
@@ -269,9 +269,13 @@
}
ErrorInfoBase *getPtr() const {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
return reinterpret_cast<ErrorInfoBase*>(
reinterpret_cast<uintptr_t>(Payload) &
~static_cast<uintptr_t>(0x1));
+#else
+ return Payload;
+#endif
}
void setPtr(ErrorInfoBase *EI) {
@@ -294,10 +298,12 @@
}
void setChecked(bool V) {
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
Payload = reinterpret_cast<ErrorInfoBase*>(
(reinterpret_cast<uintptr_t>(Payload) &
~static_cast<uintptr_t>(0x1)) |
(V ? 0 : 1));
+#endif
}
std::unique_ptr<ErrorInfoBase> takePayload() {
@@ -328,7 +334,7 @@
/// 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
@@ -434,21 +440,21 @@
template <class T1> friend class ExpectedAsOutParameter;
template <class OtherT> friend class Expected;
- static const bool isRef = std::is_reference<T>::value;
+ static constexpr bool isRef = std::is_reference<T>::value;
- using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
+ using wrap = std::reference_wrapper<std::remove_reference_t<T>>;
using error_type = std::unique_ptr<ErrorInfoBase>;
public:
- using storage_type = typename std::conditional<isRef, wrap, T>::type;
+ using storage_type = std::conditional_t<isRef, wrap, T>;
using value_type = T;
private:
- using reference = typename std::remove_reference<T>::type &;
- using const_reference = const typename std::remove_reference<T>::type &;
- using pointer = typename std::remove_reference<T>::type *;
- using const_pointer = const typename std::remove_reference<T>::type *;
+ using reference = std::remove_reference_t<T> &;
+ using const_reference = const std::remove_reference_t<T> &;
+ using pointer = std::remove_reference_t<T> *;
+ using const_pointer = const std::remove_reference_t<T> *;
public:
/// Create an Expected<T> error value from the given Error.
@@ -472,12 +478,12 @@
/// must be convertible to T.
template <typename OtherT>
Expected(OtherT &&Val,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
- * = nullptr)
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr)
: HasError(false)
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
// Expected is unchecked upon construction in Debug builds.
- , Unchecked(true)
+ ,
+ Unchecked(true)
#endif
{
new (getStorage()) storage_type(std::forward<OtherT>(Val));
@@ -489,9 +495,9 @@
/// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT
/// must be convertible to T.
template <class OtherT>
- Expected(Expected<OtherT> &&Other,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
- * = nullptr) {
+ Expected(
+ Expected<OtherT> &&Other,
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr) {
moveConstruct(std::move(Other));
}
@@ -500,8 +506,7 @@
template <class OtherT>
explicit Expected(
Expected<OtherT> &&Other,
- typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
- nullptr) {
+ std::enable_if_t<!std::is_convertible<OtherT, T>::value> * = nullptr) {
moveConstruct(std::move(Other));
}
@@ -548,7 +553,7 @@
/// 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;
@@ -624,22 +629,22 @@
storage_type *getStorage() {
assert(!HasError && "Cannot get value when an error exists!");
- return reinterpret_cast<storage_type *>(TStorage.buffer);
+ return reinterpret_cast<storage_type *>(&TStorage);
}
const storage_type *getStorage() const {
assert(!HasError && "Cannot get value when an error exists!");
- return reinterpret_cast<const storage_type *>(TStorage.buffer);
+ return reinterpret_cast<const storage_type *>(&TStorage);
}
error_type *getErrorStorage() {
assert(HasError && "Cannot get error when a value exists!");
- return reinterpret_cast<error_type *>(ErrorStorage.buffer);
+ return reinterpret_cast<error_type *>(&ErrorStorage);
}
const error_type *getErrorStorage() const {
assert(HasError && "Cannot get error when a value exists!");
- return reinterpret_cast<const error_type *>(ErrorStorage.buffer);
+ return reinterpret_cast<const error_type *>(&ErrorStorage);
}
// Used by ExpectedAsOutParameter to reset the checked flag.
@@ -704,6 +709,12 @@
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 +739,13 @@
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 +770,13 @@
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 +1007,20 @@
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 +1209,10 @@
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) {
@@ -1194,6 +1237,8 @@
Err->log(OS);
}
+ StringRef getFileName() { return FileName; }
+
Error takeError() { return Error(std::move(Err)); }
std::error_code convertToErrorCode() const override;
@@ -1213,8 +1258,14 @@
}
static Error build(const Twine &F, Optional<size_t> Line, Error E) {
+ std::unique_ptr<ErrorInfoBase> Payload;
+ handleAllErrors(std::move(E),
+ [&](std::unique_ptr<ErrorInfoBase> EIB) -> Error {
+ Payload = std::move(EIB);
+ return Error::success();
+ });
return Error(
- std::unique_ptr<FileError>(new FileError(F, Line, E.takePayload())));
+ std::unique_ptr<FileError>(new FileError(F, Line, std::move(Payload))));
}
std::string FileName;
diff --git a/linux-x64/clang/include/llvm/Support/ErrorHandling.h b/linux-x64/clang/include/llvm/Support/ErrorHandling.h
index f75c298..0ec0242 100644
--- a/linux-x64/clang/include/llvm/Support/ErrorHandling.h
+++ b/linux-x64/clang/include/llvm/Support/ErrorHandling.h
@@ -66,7 +66,7 @@
///
/// If no error handler is installed the default is to print the message to
/// standard error, followed by a newline.
-/// After the error handler is called this function will call exit(1), it
+/// After the error handler is called this function will call abort(), it
/// does not return.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason,
bool gen_crash_diag = true);
@@ -103,17 +103,18 @@
/// Reports a bad alloc error, calling any user defined bad alloc
/// error handler. In contrast to the generic 'report_fatal_error'
-/// functions, this function is expected to return, e.g. the user
-/// defined error handler throws an exception.
+/// functions, this function might not terminate, e.g. the user
+/// defined error handler throws an exception, but it won't return.
///
/// Note: When throwing an exception in the bad alloc handler, make sure that
/// the following unwind succeeds, e.g. do not trigger additional allocations
/// in the unwind chain.
///
-/// If no error handler is installed (default), then a bad_alloc exception
-/// is thrown, if LLVM is compiled with exception support, otherwise an
-/// assertion is called.
-void report_bad_alloc_error(const char *Reason, bool GenCrashDiag = true);
+/// If no error handler is installed (default), throws a bad_alloc exception
+/// if LLVM is compiled with exception support. Otherwise prints the error
+/// to standard error and calls abort().
+LLVM_ATTRIBUTE_NORETURN void report_bad_alloc_error(const char *Reason,
+ bool GenCrashDiag = true);
/// This function calls abort(), and prints the optional message to stderr.
/// Use the llvm_unreachable macro (that adds location info), instead of
@@ -127,7 +128,7 @@
/// In !NDEBUG builds, prints the message and location info to stderr.
/// In NDEBUG builds, becomes an optimizer hint that the current location
/// is not supposed to be reachable. On compilers that don't support
-/// such hints, prints a reduced message instead.
+/// such hints, prints a reduced message instead and aborts the program.
///
/// Use this instead of assert(0). It conveys intent more clearly and
/// allows compilers to omit some unnecessary code.
diff --git a/linux-x64/clang/include/llvm/Support/ErrorOr.h b/linux-x64/clang/include/llvm/Support/ErrorOr.h
index 8211f4d..b654c9c 100644
--- a/linux-x64/clang/include/llvm/Support/ErrorOr.h
+++ b/linux-x64/clang/include/llvm/Support/ErrorOr.h
@@ -56,25 +56,25 @@
class ErrorOr {
template <class OtherT> friend class ErrorOr;
- static const bool isRef = std::is_reference<T>::value;
+ static constexpr bool isRef = std::is_reference<T>::value;
- using wrap = std::reference_wrapper<typename std::remove_reference<T>::type>;
+ using wrap = std::reference_wrapper<std::remove_reference_t<T>>;
public:
- using storage_type = typename std::conditional<isRef, wrap, T>::type;
+ using storage_type = std::conditional_t<isRef, wrap, T>;
private:
- using reference = typename std::remove_reference<T>::type &;
- using const_reference = const typename std::remove_reference<T>::type &;
- using pointer = typename std::remove_reference<T>::type *;
- using const_pointer = const typename std::remove_reference<T>::type *;
+ using reference = std::remove_reference_t<T> &;
+ using const_reference = const std::remove_reference_t<T> &;
+ using pointer = std::remove_reference_t<T> *;
+ using const_pointer = const std::remove_reference_t<T> *;
public:
template <class E>
ErrorOr(E ErrorCode,
- typename std::enable_if<std::is_error_code_enum<E>::value ||
- std::is_error_condition_enum<E>::value,
- void *>::type = nullptr)
+ std::enable_if_t<std::is_error_code_enum<E>::value ||
+ std::is_error_condition_enum<E>::value,
+ void *> = nullptr)
: HasError(true) {
new (getErrorStorage()) std::error_code(make_error_code(ErrorCode));
}
@@ -85,8 +85,7 @@
template <class OtherT>
ErrorOr(OtherT &&Val,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type
- * = nullptr)
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr)
: HasError(false) {
new (getStorage()) storage_type(std::forward<OtherT>(Val));
}
@@ -96,18 +95,16 @@
}
template <class OtherT>
- ErrorOr(
- const ErrorOr<OtherT> &Other,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
- nullptr) {
+ ErrorOr(const ErrorOr<OtherT> &Other,
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr) {
copyConstruct(Other);
}
template <class OtherT>
explicit ErrorOr(
const ErrorOr<OtherT> &Other,
- typename std::enable_if<
- !std::is_convertible<OtherT, const T &>::value>::type * = nullptr) {
+ std::enable_if_t<!std::is_convertible<OtherT, const T &>::value> * =
+ nullptr) {
copyConstruct(Other);
}
@@ -116,10 +113,8 @@
}
template <class OtherT>
- ErrorOr(
- ErrorOr<OtherT> &&Other,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
- nullptr) {
+ ErrorOr(ErrorOr<OtherT> &&Other,
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr) {
moveConstruct(std::move(Other));
}
@@ -128,8 +123,7 @@
template <class OtherT>
explicit ErrorOr(
ErrorOr<OtherT> &&Other,
- typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
- nullptr) {
+ std::enable_if_t<!std::is_convertible<OtherT, T>::value> * = nullptr) {
moveConstruct(std::move(Other));
}
@@ -241,17 +235,17 @@
storage_type *getStorage() {
assert(!HasError && "Cannot get value when an error exists!");
- return reinterpret_cast<storage_type*>(TStorage.buffer);
+ return reinterpret_cast<storage_type *>(&TStorage);
}
const storage_type *getStorage() const {
assert(!HasError && "Cannot get value when an error exists!");
- return reinterpret_cast<const storage_type*>(TStorage.buffer);
+ return reinterpret_cast<const storage_type *>(&TStorage);
}
std::error_code *getErrorStorage() {
assert(HasError && "Cannot get error when a value exists!");
- return reinterpret_cast<std::error_code *>(ErrorStorage.buffer);
+ return reinterpret_cast<std::error_code *>(&ErrorStorage);
}
const std::error_code *getErrorStorage() const {
@@ -266,9 +260,9 @@
};
template <class T, class E>
-typename std::enable_if<std::is_error_code_enum<E>::value ||
- std::is_error_condition_enum<E>::value,
- bool>::type
+std::enable_if_t<std::is_error_code_enum<E>::value ||
+ std::is_error_condition_enum<E>::value,
+ bool>
operator==(const ErrorOr<T> &Err, E Code) {
return Err.getError() == Code;
}
diff --git a/linux-x64/clang/include/llvm/Support/ExitCodes.h b/linux-x64/clang/include/llvm/Support/ExitCodes.h
new file mode 100644
index 0000000..b9041f5
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/ExitCodes.h
@@ -0,0 +1,33 @@
+//===-- llvm/Support/ExitCodes.h - Exit codes for exit() -------*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains definitions of exit codes for exit() function. They are
+/// either defined by sysexits.h if it is supported, or defined here if
+/// sysexits.h is not supported.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_EXITCODES_H
+#define LLVM_SUPPORT_EXITCODES_H
+
+#include "llvm/Config/llvm-config.h"
+
+#if HAVE_SYSEXITS_H
+#include <sysexits.h>
+#elif __MVS__
+// <sysexits.h> does not exist on z/OS. The only value used in LLVM is
+// EX_IOERR, which is used to signal a special error condition (broken pipe).
+// Define the macro with its usual value from BSD systems, which is chosen to
+// not clash with more standard exit codes like 1.
+#define EX_IOERR 74
+#elif LLVM_ON_UNIX
+#error Exit code EX_IOERR not available
+#endif
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/ExtensibleRTTI.h b/linux-x64/clang/include/llvm/Support/ExtensibleRTTI.h
new file mode 100644
index 0000000..6b8510c
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/ExtensibleRTTI.h
@@ -0,0 +1,135 @@
+//===-- llvm/Support/ExtensibleRTTI.h - ExtensibleRTTI support --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// \file
+//
+// Defines an extensible RTTI mechanism designed to work with Casting.h.
+//
+// Extensible RTTI differs from LLVM's primary RTTI mechanism (see
+// llvm.org/docs/HowToSetUpLLVMStyleRTTI.html) by supporting open type
+// hierarchies, where new types can be added from outside libraries without
+// needing to change existing code. LLVM's primary RTTI mechanism should be
+// preferred where possible, but where open hierarchies are needed this system
+// can be used.
+//
+// The RTTIRoot class defines methods for comparing type ids. Implementations
+// of these methods can be injected into new classes using the RTTIExtends
+// class template.
+//
+// E.g.
+//
+// @code{.cpp}
+// class MyBaseClass : public RTTIExtends<MyBaseClass, RTTIRoot> {
+// public:
+// static char ID;
+// virtual void foo() = 0;
+// };
+//
+// class MyDerivedClass1 : public RTTIExtends<MyDerivedClass1, MyBaseClass> {
+// public:
+// static char ID;
+// void foo() override {}
+// };
+//
+// class MyDerivedClass2 : public RTTIExtends<MyDerivedClass2, MyBaseClass> {
+// public:
+// static char ID;
+// void foo() override {}
+// };
+//
+// char MyBaseClass::ID = 0;
+// char MyDerivedClass1::ID = 0;
+// char MyDerivedClass2:: ID = 0;
+//
+// void fn() {
+// std::unique_ptr<MyBaseClass> B = llvm::make_unique<MyDerivedClass1>();
+// llvm::outs() << isa<MyBaseClass>(B) << "\n"; // Outputs "1".
+// llvm::outs() << isa<MyDerivedClass1>(B) << "\n"; // Outputs "1".
+// llvm::outs() << isa<MyDerivedClass2>(B) << "\n"; // Outputs "0'.
+// }
+//
+// @endcode
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_EXTENSIBLERTTI_H
+#define LLVM_SUPPORT_EXTENSIBLERTTI_H
+
+namespace llvm {
+
+template <typename ThisT, typename ParentT> class RTTIExtends;
+
+/// Base class for the extensible RTTI hierarchy.
+///
+/// This class defines virtual methods, dynamicClassID and isA, that enable
+/// type comparisons.
+class RTTIRoot {
+public:
+ virtual ~RTTIRoot() = default;
+
+ /// Returns the class ID for this type.
+ static const void *classID() { return &ID; }
+
+ /// Returns the class ID for the dynamic type of this RTTIRoot instance.
+ virtual const void *dynamicClassID() const = 0;
+
+ /// Returns true if this class's ID matches the given class ID.
+ virtual bool isA(const void *const ClassID) const {
+ return ClassID == classID();
+ }
+
+ /// Check whether this instance is a subclass of QueryT.
+ template <typename QueryT>
+ bool isA() const { return isA(QueryT::classID()); }
+
+private:
+ virtual void anchor();
+
+ static char ID;
+};
+
+/// Inheritance utility for extensible RTTI.
+///
+/// Supports single inheritance only: A class can only have one
+/// ExtensibleRTTI-parent (i.e. a parent for which the isa<> test will work),
+/// though it can have many non-ExtensibleRTTI parents.
+///
+/// RTTIExtents uses CRTP so the first template argument to RTTIExtends is the
+/// newly introduced type, and the *second* argument is the parent class.
+///
+/// class MyType : public RTTIExtends<MyType, RTTIRoot> {
+/// public:
+/// static char ID;
+/// };
+///
+/// class MyDerivedType : public RTTIExtends<MyDerivedType, MyType> {
+/// public:
+/// static char ID;
+/// };
+///
+template <typename ThisT, typename ParentT>
+class RTTIExtends : public ParentT {
+public:
+ // Inherit constructors from ParentT.
+ using ParentT::ParentT;
+
+ static const void *classID() { return &ThisT::ID; }
+
+ const void *dynamicClassID() const override { return &ThisT::ID; }
+
+ bool isA(const void *const ClassID) const override {
+ return ClassID == classID() || ParentT::isA(ClassID);
+ }
+
+ static bool classof(const RTTIRoot *R) { return R->isA<ThisT>(); }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_EXTENSIBLERTTI_H
diff --git a/linux-x64/clang/include/llvm/Support/Extension.def b/linux-x64/clang/include/llvm/Support/Extension.def
new file mode 100644
index 0000000..cb872c0
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/Extension.def
@@ -0,0 +1,3 @@
+//extension handlers
+HANDLE_EXTENSION(Polly)
+#undef HANDLE_EXTENSION
diff --git a/linux-x64/clang/include/llvm/Support/FileCheck.h b/linux-x64/clang/include/llvm/Support/FileCheck.h
deleted file mode 100644
index b3a8433..0000000
--- a/linux-x64/clang/include/llvm/Support/FileCheck.h
+++ /dev/null
@@ -1,693 +0,0 @@
-//==-- llvm/Support/FileCheck.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
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file This file has some utilities to use FileCheck as an API
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_FILECHECK_H
-#define LLVM_SUPPORT_FILECHECK_H
-
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Regex.h"
-#include "llvm/Support/SourceMgr.h"
-#include <vector>
-#include <map>
-
-namespace llvm {
-
-/// Contains info about various FileCheck options.
-struct FileCheckRequest {
- std::vector<std::string> CheckPrefixes;
- bool NoCanonicalizeWhiteSpace = false;
- std::vector<std::string> ImplicitCheckNot;
- std::vector<std::string> GlobalDefines;
- bool AllowEmptyInput = false;
- bool MatchFullLines = false;
- bool EnableVarScope = false;
- bool AllowDeprecatedDagOverlap = false;
- bool Verbose = false;
- bool VerboseVerbose = false;
-};
-
-//===----------------------------------------------------------------------===//
-// Numeric substitution handling code.
-//===----------------------------------------------------------------------===//
-
-/// 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. Used to determine whether a
- /// variable is defined on the same line as a given use.
- size_t DefLineNumber;
-
-public:
- /// Constructor for a variable \p Name defined at line \p DefLineNumber.
- FileCheckNumericVariable(size_t DefLineNumber, StringRef Name)
- : Name(Name), DefLineNumber(DefLineNumber) {}
-
- /// Constructor for numeric variable \p Name with a known \p Value at parse
- /// time (e.g. the @LINE numeric variable).
- FileCheckNumericVariable(StringRef Name, uint64_t Value)
- : Name(Name), Value(Value), DefLineNumber(0) {}
-
- /// \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.
- size_t getDefLineNumber() { return DefLineNumber; }
-};
-
-/// Type of functions evaluating a given binary operation.
-using binop_eval_t = uint64_t (*)(uint64_t, uint64_t);
-
-/// Class to represent an undefined variable error which prints that variable's
-/// name between quotes 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 an expression consisting of either a single numeric
-/// variable or a binary operation between a numeric variable and an
-/// immediate.
-class FileCheckExpression {
-private:
- /// Left operand.
- FileCheckNumericVariable *LeftOp;
-
- /// Right operand.
- uint64_t RightOp;
-
- /// Pointer to function that can evaluate this binary operation.
- binop_eval_t EvalBinop;
-
-public:
- FileCheckExpression(binop_eval_t EvalBinop,
- FileCheckNumericVariable *OperandLeft,
- uint64_t OperandRight)
- : LeftOp(OperandLeft), RightOp(OperandRight), EvalBinop(EvalBinop) {}
-
- /// Evaluates the value of this expression, using EvalBinop to perform the
- /// binary operation it consists of. \returns an error if the numeric
- /// variable used is undefined, or the expression value otherwise.
- 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.
- FileCheckExpression *Expression;
-
-public:
- FileCheckNumericSubstitution(FileCheckPatternContext *Context,
- StringRef ExpressionStr,
- FileCheckExpression *Expression,
- size_t InsertIdx)
- : FileCheckSubstitution(Context, ExpressionStr, InsertIdx),
- Expression(Expression) {}
-
- /// \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.
-//===----------------------------------------------------------------------===//
-
-namespace Check {
-
-enum FileCheckKind {
- CheckNone = 0,
- CheckPlain,
- CheckNext,
- CheckSame,
- CheckNot,
- CheckDAG,
- CheckLabel,
- CheckEmpty,
-
- /// Indicates the pattern only matches the end of file. This is used for
- /// trailing CHECK-NOTs.
- CheckEOF,
-
- /// Marks when parsing found a -NOT check combined with another CHECK suffix.
- CheckBadNot,
-
- /// Marks when parsing found a -COUNT directive with invalid count value.
- CheckBadCount
-};
-
-class FileCheckType {
- FileCheckKind Kind;
- int Count; ///< optional Count for some checks
-
-public:
- FileCheckType(FileCheckKind Kind = CheckNone) : Kind(Kind), Count(1) {}
- FileCheckType(const FileCheckType &) = default;
-
- operator FileCheckKind() const { return Kind; }
-
- int getCount() const { return Count; }
- FileCheckType &setCount(int C);
-
- // \returns a description of \p Prefix.
- std::string getDescription(StringRef Prefix) const;
-};
-} // 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 expressions. Used to automatically
- /// free the expressions once they are guaranteed to no longer be used.
- std::vector<std::unique_ptr<FileCheckExpression>> Expressions;
-
- /// 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 expression instance and registers it for destruction when
- /// the context is destroyed.
- FileCheckExpression *makeExpression(binop_eval_t EvalBinop,
- FileCheckNumericVariable *OperandLeft,
- uint64_t OperandRight);
-
- /// 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,
- FileCheckExpression *Expression, 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. Used to determine whether a variable
- /// definition is made on an earlier line to the one with this CHECK.
- size_t LineNumber;
-
-public:
- FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
- size_t Line)
- : 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);
- /// Parses the string at the start of \p Str for a variable name. \returns
- /// an error holding a diagnostic against \p SM if parsing fail, or the
- /// name of the variable otherwise. In the latter case, sets \p IsPseudo to
- /// indicate if it is a pseudo variable and strips \p Str from the variable
- /// name.
- static Expected<StringRef> parseVariable(StringRef &Str, bool &IsPseudo,
- const SourceMgr &SM);
- /// Parses \p Expr for the name of a numeric variable to be defined at line
- /// \p LineNumber. \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,
- size_t LineNumber, const SourceMgr &SM);
- /// Parses \p Expr for a numeric substitution block. \returns the class
- /// 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 defined in this numeric
- /// substitution block, or None if this block does not define any variable.
- Expected<FileCheckExpression *> parseNumericSubstitutionBlock(
- StringRef Expr,
- Optional<FileCheckNumericVariable *> &DefinedNumericVariable,
- 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 variable 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 Expr for the use of a numeric variable. \returns the pointer to
- /// the class instance representing that variable if successful, or an error
- /// holding a diagnostic against \p SM otherwise.
- Expected<FileCheckNumericVariable *>
- parseNumericVariableUse(StringRef &Expr, const SourceMgr &SM) const;
- /// Parses \p Expr for a binary operation.
- /// \returns the class representing the binary operation of the expression,
- /// or an error holding a diagnostic against \p SM otherwise.
- Expected<FileCheckExpression *> parseBinop(StringRef &Expr,
- const SourceMgr &SM) const;
-};
-
-//===----------------------------------------------------------------------===//
-/// Summary of a FileCheck diagnostic.
-//===----------------------------------------------------------------------===//
-
-struct FileCheckDiag {
- /// What is the FileCheck directive for this diagnostic?
- Check::FileCheckType CheckTy;
- /// Where is the FileCheck directive for this diagnostic?
- unsigned CheckLine, CheckCol;
- /// What type of match result does this diagnostic describe?
- ///
- /// A directive's supplied pattern is said to be either expected or excluded
- /// depending on whether the pattern must have or must not have a match in
- /// order for the directive to succeed. For example, a CHECK directive's
- /// pattern is expected, and a CHECK-NOT directive's pattern is excluded.
- /// All match result types whose names end with "Excluded" are for excluded
- /// patterns, and all others are for expected patterns.
- ///
- /// There might be more than one match result for a single pattern. For
- /// example, there might be several discarded matches
- /// (MatchFoundButDiscarded) before either a good match
- /// (MatchFoundAndExpected) or a failure to match (MatchNoneButExpected),
- /// and there might be a fuzzy match (MatchFuzzy) after the latter.
- enum MatchType {
- /// Indicates a good match for an expected pattern.
- MatchFoundAndExpected,
- /// Indicates a match for an excluded pattern.
- MatchFoundButExcluded,
- /// Indicates a match for an expected pattern, but the match is on the
- /// wrong line.
- MatchFoundButWrongLine,
- /// Indicates a discarded match for an expected pattern.
- MatchFoundButDiscarded,
- /// Indicates no match for an excluded pattern.
- MatchNoneAndExcluded,
- /// Indicates no match for an expected pattern, but this might follow good
- /// matches when multiple matches are expected for the pattern, or it might
- /// follow discarded matches for the pattern.
- MatchNoneButExpected,
- /// Indicates a fuzzy match that serves as a suggestion for the next
- /// intended match for an expected pattern with too few or no good matches.
- MatchFuzzy,
- } MatchTy;
- /// The search range if MatchTy is MatchNoneAndExcluded or
- /// MatchNoneButExpected, or the match range otherwise.
- unsigned InputStartLine;
- unsigned InputStartCol;
- unsigned InputEndLine;
- unsigned InputEndCol;
- FileCheckDiag(const SourceMgr &SM, const Check::FileCheckType &CheckTy,
- 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;
-};
-
-/// FileCheck class takes the request and exposes various methods that
-/// use information from the request.
-class FileCheck {
- FileCheckRequest Req;
- FileCheckPatternContext PatternContext;
-
-public:
- FileCheck(FileCheckRequest Req) : Req(Req) {}
-
- // Combines the check prefixes into a single regex so that we can efficiently
- // scan for any of the set.
- //
- // The semantics are that the longest-match wins which matches our regex
- // library.
- 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.
- ///
- /// 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 ValidateCheckPrefixes();
-
- /// Canonicalizes whitespaces in the file. Line endings are replaced with
- /// UNIX-style '\n'.
- StringRef CanonicalizeFile(MemoryBuffer &MB,
- 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
- /// 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,
- std::vector<FileCheckDiag> *Diags = nullptr);
-};
-} // namespace llvm
-#endif
diff --git a/linux-x64/clang/include/llvm/Support/FileCollector.h b/linux-x64/clang/include/llvm/Support/FileCollector.h
new file mode 100644
index 0000000..cbb870e
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/FileCollector.h
@@ -0,0 +1,128 @@
+//===-- 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/Support/VirtualFileSystem.h"
+#include <mutex>
+#include <string>
+
+namespace llvm {
+class FileCollectorFileSystem;
+class Twine;
+
+class FileCollectorBase {
+public:
+ FileCollectorBase();
+ virtual ~FileCollectorBase();
+
+ void addFile(const Twine &file);
+ void addDirectory(const Twine &Dir);
+
+protected:
+ bool markAsSeen(StringRef Path) {
+ if (Path.empty())
+ return false;
+ return Seen.insert(Path).second;
+ }
+
+ virtual void addFileImpl(StringRef SrcPath) = 0;
+
+ virtual llvm::vfs::directory_iterator
+ addDirectoryImpl(const llvm::Twine &Dir,
+ IntrusiveRefCntPtr<vfs::FileSystem> FS,
+ std::error_code &EC) = 0;
+
+ /// Synchronizes access to internal data structures.
+ std::mutex Mutex;
+
+ /// Tracks already seen files so they can be skipped.
+ StringSet<> Seen;
+};
+
+/// Captures file system interaction and generates data to be later replayed
+/// with the RedirectingFileSystem.
+///
+/// For any file that gets accessed we eventually create:
+/// - a copy of the file inside Root
+/// - a record in RedirectingFileSystem mapping that maps:
+/// current real path -> path to the copy in Root
+///
+/// That intent is that later when the mapping is used by RedirectingFileSystem
+/// it simulates the state of FS that we collected.
+///
+/// We generate file copies and mapping lazily - see writeMapping and copyFiles.
+/// We don't try to capture the state of the file at the exact time when it's
+/// accessed. Files might get changed, deleted ... we record only the "final"
+/// state.
+///
+/// In order to preserve the relative topology of files we use their real paths
+/// as relative paths inside of the Root.
+class FileCollector : public FileCollectorBase {
+public:
+ /// \p Root is the directory where collected files are will be stored.
+ /// \p OverlayRoot is VFS mapping root.
+ /// \p Root directory gets created in copyFiles unless it already exists.
+ FileCollector(std::string Root, std::string OverlayRoot);
+
+ /// Write the yaml mapping (for the VFS) to the given file.
+ std::error_code writeMapping(StringRef MappingFile);
+
+ /// 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 uses \p Collector to collect files accessed via \p
+ /// BaseFS.
+ static IntrusiveRefCntPtr<vfs::FileSystem>
+ createCollectorVFS(IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
+ std::shared_ptr<FileCollector> Collector);
+
+private:
+ friend FileCollectorFileSystem;
+
+ bool getRealPath(StringRef SrcPath, SmallVectorImpl<char> &Result);
+
+ void addFileToMapping(StringRef VirtualPath, StringRef RealPath) {
+ if (sys::fs::is_directory(VirtualPath))
+ VFSWriter.addDirectoryMapping(VirtualPath, RealPath);
+ else
+ VFSWriter.addFileMapping(VirtualPath, RealPath);
+ }
+
+protected:
+ void addFileImpl(StringRef SrcPath) override;
+
+ llvm::vfs::directory_iterator
+ addDirectoryImpl(const llvm::Twine &Dir,
+ IntrusiveRefCntPtr<vfs::FileSystem> FS,
+ std::error_code &EC) override;
+
+ /// The directory where collected files are copied to in copyFiles().
+ const std::string Root;
+
+ /// The root directory where the VFS overlay lives.
+ const std::string OverlayRoot;
+
+ /// 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/linux-x64/clang/include/llvm/Support/FileOutputBuffer.h b/linux-x64/clang/include/llvm/Support/FileOutputBuffer.h
index 999f551..8eb36d0 100644
--- a/linux-x64/clang/include/llvm/Support/FileOutputBuffer.h
+++ b/linux-x64/clang/include/llvm/Support/FileOutputBuffer.h
@@ -13,11 +13,9 @@
#ifndef LLVM_SUPPORT_FILEOUTPUTBUFFER_H
#define LLVM_SUPPORT_FILEOUTPUTBUFFER_H
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
namespace llvm {
/// FileOutputBuffer - This interface provides simple way to create an in-memory
@@ -32,6 +30,10 @@
enum {
/// set the 'x' bit on the resulting file
F_executable = 1,
+
+ /// Don't use mmap and instead write an in-memory buffer to a file when this
+ /// buffer is closed.
+ F_no_mmap = 2,
};
/// Factory method to create an OutputBuffer object which manages a read/write
diff --git a/linux-x64/clang/include/llvm/Support/FileSystem.h b/linux-x64/clang/include/llvm/Support/FileSystem.h
index 3f2c939..2483aae 100644
--- a/linux-x64/clang/include/llvm/Support/FileSystem.h
+++ b/linux-x64/clang/include/llvm/Support/FileSystem.h
@@ -34,6 +34,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem/UniqueID.h"
#include "llvm/Support/MD5.h"
#include <cassert>
#include <cstdint>
@@ -42,7 +43,6 @@
#include <stack>
#include <string>
#include <system_error>
-#include <tuple>
#include <vector>
#ifdef HAVE_SYS_STAT_H
@@ -131,26 +131,6 @@
static_cast<unsigned short>(~static_cast<unsigned short>(x)));
}
-class UniqueID {
- uint64_t Device;
- uint64_t File;
-
-public:
- UniqueID() = default;
- UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
-
- bool operator==(const UniqueID &Other) const {
- return Device == Other.Device && File == Other.File;
- }
- bool operator!=(const UniqueID &Other) const { return !(*this == Other); }
- bool operator<(const UniqueID &Other) const {
- return std::tie(Device, File) < std::tie(Other.Device, Other.File);
- }
-
- uint64_t getDevice() const { return Device; }
- uint64_t getFile() const { return File; }
-};
-
/// Represents the result of a call to directory_iterator::status(). This is a
/// subset of the information returned by a regular sys::fs::status() call, and
/// represents the information provided by Windows FileFirstFile/FindNextFile.
@@ -665,15 +645,17 @@
///
/// @param Path File to set permissions on.
/// @param Permissions New file permissions.
-/// @param RespectUmask If true then Permissions will be changed to respect the
-/// umask of the current process.
/// @returns errc::success if the permissions were successfully set, otherwise
/// a platform-specific error_code.
/// @note On Windows, all permissions except *_write are ignored. Using any of
/// owner_write, group_write, or all_write will make the file writable.
/// Otherwise, the file will be marked as read-only.
-std::error_code setPermissions(const Twine &Path, perms Permissions,
- bool RespectUmask = false);
+std::error_code setPermissions(const Twine &Path, perms Permissions);
+
+/// Vesion of setPermissions accepting a file descriptor.
+/// TODO Delete the path based overload once we implement the FD based overload
+/// on Windows.
+std::error_code setPermissions(int FD, perms Permissions);
/// Get file permissions.
///
@@ -989,29 +971,27 @@
/// 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
@@ -1131,6 +1111,43 @@
openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None,
SmallVectorImpl<char> *RealPath = nullptr);
+/// Try to locks the file during the specified time.
+///
+/// This function implements advisory locking on entire file. If it returns
+/// <em>errc::success</em>, the file is locked by the calling process. Until the
+/// process unlocks the file by calling \a unlockFile, all attempts to lock the
+/// same file will fail/block. The process that locked the file may assume that
+/// none of other processes read or write this file, provided that all processes
+/// lock the file prior to accessing its content.
+///
+/// @param FD The descriptor representing the file to lock.
+/// @param Timeout Time in milliseconds that the process should wait before
+/// reporting lock failure. Zero value means try to get lock only
+/// once.
+/// @returns errc::success if lock is successfully obtained,
+/// errc::no_lock_available if the file cannot be locked, or platform-specific
+/// error_code otherwise.
+///
+/// @note Care should be taken when using this function in a multithreaded
+/// context, as it may not prevent other threads in the same process from
+/// obtaining a lock on the same file, even if they are using a different file
+/// descriptor.
+std::error_code
+tryLockFile(int FD,
+ std::chrono::milliseconds Timeout = std::chrono::milliseconds(0));
+
+/// Lock the file.
+///
+/// This function acts as @ref tryLockFile but it waits infinitely.
+std::error_code lockFile(int FD);
+
+/// Unlock the file.
+///
+/// @param FD The descriptor representing the file to unlock.
+/// @returns errc::success if lock is successfully released or platform-specific
+/// error_code otherwise.
+std::error_code unlockFile(int FD);
+
/// @brief Close the file object. This should be used instead of ::close for
/// portability. On error, the caller should assume the file is closed, as is
/// the case for Process::SafelyCloseFileDescriptor
@@ -1142,6 +1159,35 @@
/// means that the filesystem may have failed to perform some buffered writes.
std::error_code closeFile(file_t &F);
+/// RAII class that facilitates file locking.
+class FileLocker {
+ int FD; ///< Locked file handle.
+ FileLocker(int FD) : FD(FD) {}
+ friend class llvm::raw_fd_ostream;
+
+public:
+ FileLocker(const FileLocker &L) = delete;
+ FileLocker(FileLocker &&L) : FD(L.FD) { L.FD = -1; }
+ ~FileLocker() {
+ if (FD != -1)
+ unlockFile(FD);
+ }
+ FileLocker &operator=(FileLocker &&L) {
+ FD = L.FD;
+ L.FD = -1;
+ return *this;
+ }
+ FileLocker &operator=(const FileLocker &L) = delete;
+ std::error_code unlock() {
+ if (FD != -1) {
+ std::error_code Result = unlockFile(FD);
+ FD = -1;
+ return Result;
+ }
+ return std::error_code();
+ }
+};
+
std::error_code getUniqueID(const Twine Path, UniqueID &Result);
/// Get disk space usage information.
@@ -1215,9 +1261,9 @@
// 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/linux-x64/clang/include/llvm/Support/FileSystem/UniqueID.h b/linux-x64/clang/include/llvm/Support/FileSystem/UniqueID.h
new file mode 100644
index 0000000..229410c
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/FileSystem/UniqueID.h
@@ -0,0 +1,52 @@
+//===- llvm/Support/FileSystem/UniqueID.h - UniqueID for files --*- 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 is cut out of llvm/Support/FileSystem.h to allow UniqueID to be
+// reused without bloating the includes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FILESYSTEM_UNIQUEID_H
+#define LLVM_SUPPORT_FILESYSTEM_UNIQUEID_H
+
+#include <cstdint>
+
+namespace llvm {
+namespace sys {
+namespace fs {
+
+class UniqueID {
+ uint64_t Device;
+ uint64_t File;
+
+public:
+ UniqueID() = default;
+ UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
+
+ bool operator==(const UniqueID &Other) const {
+ return Device == Other.Device && File == Other.File;
+ }
+ bool operator!=(const UniqueID &Other) const { return !(*this == Other); }
+ bool operator<(const UniqueID &Other) const {
+ /// Don't use std::tie since it bloats the compile time of this header.
+ if (Device < Other.Device)
+ return true;
+ if (Other.Device < Device)
+ return false;
+ return File < Other.File;
+ }
+
+ uint64_t getDevice() const { return Device; }
+ uint64_t getFile() const { return File; }
+};
+
+} // end namespace fs
+} // end namespace sys
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_FILESYSTEM_UNIQUEID_H
diff --git a/linux-x64/clang/include/llvm/Support/FileUtilities.h b/linux-x64/clang/include/llvm/Support/FileUtilities.h
index 16b2206..04efdce 100644
--- a/linux-x64/clang/include/llvm/Support/FileUtilities.h
+++ b/linux-x64/clang/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 @@
/// 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/linux-x64/clang/include/llvm/Support/Format.h b/linux-x64/clang/include/llvm/Support/Format.h
index 77dcbae..9dd7b40 100644
--- a/linux-x64/clang/include/llvm/Support/Format.h
+++ b/linux-x64/clang/include/llvm/Support/Format.h
@@ -29,6 +29,7 @@
#include <cassert>
#include <cstdio>
#include <tuple>
+#include <utility>
namespace llvm {
@@ -91,7 +92,7 @@
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 @@
}
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/linux-x64/clang/include/llvm/Support/FormatAdapters.h b/linux-x64/clang/include/llvm/Support/FormatAdapters.h
index a0e8cc4..495205d 100644
--- a/linux-x64/clang/include/llvm/Support/FormatAdapters.h
+++ b/linux-x64/clang/include/llvm/Support/FormatAdapters.h
@@ -9,7 +9,6 @@
#ifndef LLVM_SUPPORT_FORMATADAPTERS_H
#define LLVM_SUPPORT_FORMATADAPTERS_H
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatCommon.h"
@@ -35,7 +34,7 @@
: FormatAdapter<T>(std::forward<T>(Item)), Where(Where), Amount(Amount),
Fill(Fill) {}
- void format(llvm::raw_ostream &Stream, StringRef Style) {
+ void format(llvm::raw_ostream &Stream, StringRef Style) override {
auto Adapter = detail::build_format_adapter(std::forward<T>(this->Item));
FmtAlign(Adapter, Where, Amount, Fill).format(Stream, Style);
}
@@ -49,7 +48,7 @@
PadAdapter(T &&Item, size_t Left, size_t Right)
: FormatAdapter<T>(std::forward<T>(Item)), Left(Left), Right(Right) {}
- void format(llvm::raw_ostream &Stream, StringRef Style) {
+ void format(llvm::raw_ostream &Stream, StringRef Style) override {
auto Adapter = detail::build_format_adapter(std::forward<T>(this->Item));
Stream.indent(Left);
Adapter.format(Stream, Style);
@@ -64,7 +63,7 @@
RepeatAdapter(T &&Item, size_t Count)
: FormatAdapter<T>(std::forward<T>(Item)), Count(Count) {}
- void format(llvm::raw_ostream &Stream, StringRef Style) {
+ void format(llvm::raw_ostream &Stream, StringRef Style) override {
auto Adapter = detail::build_format_adapter(std::forward<T>(this->Item));
for (size_t I = 0; I < Count; ++I) {
Adapter.format(Stream, Style);
@@ -77,7 +76,9 @@
ErrorAdapter(Error &&Item) : FormatAdapter(std::move(Item)) {}
ErrorAdapter(ErrorAdapter &&) = default;
~ErrorAdapter() { consumeError(std::move(Item)); }
- void format(llvm::raw_ostream &Stream, StringRef Style) { Stream << Item; }
+ void format(llvm::raw_ostream &Stream, StringRef Style) override {
+ Stream << Item;
+ }
};
}
diff --git a/linux-x64/clang/include/llvm/Support/FormatProviders.h b/linux-x64/clang/include/llvm/Support/FormatProviders.h
index 629a484..c31481a 100644
--- a/linux-x64/clang/include/llvm/Support/FormatProviders.h
+++ b/linux-x64/clang/include/llvm/Support/FormatProviders.h
@@ -124,7 +124,7 @@
template <typename T>
struct format_provider<
- T, typename std::enable_if<detail::use_integral_formatter<T>::value>::type>
+ T, std::enable_if_t<detail::use_integral_formatter<T>::value>>
: public detail::HelperFunctions {
private:
public:
@@ -173,7 +173,7 @@
/// cases indicates the minimum number of nibbles to print.
template <typename T>
struct format_provider<
- T, typename std::enable_if<detail::use_pointer_formatter<T>::value>::type>
+ T, std::enable_if_t<detail::use_pointer_formatter<T>::value>>
: public detail::HelperFunctions {
private:
public:
@@ -198,7 +198,7 @@
template <typename T>
struct format_provider<
- T, typename std::enable_if<detail::use_string_formatter<T>::value>::type> {
+ T, std::enable_if_t<detail::use_string_formatter<T>::value>> {
static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
size_t N = StringRef::npos;
if (!Style.empty() && Style.getAsInteger(10, N)) {
@@ -230,8 +230,8 @@
/// character. Otherwise, it is treated as an integer options string.
///
template <typename T>
-struct format_provider<
- T, typename std::enable_if<detail::use_char_formatter<T>::value>::type> {
+struct format_provider<T,
+ std::enable_if_t<detail::use_char_formatter<T>::value>> {
static void format(const char &V, llvm::raw_ostream &Stream,
StringRef Style) {
if (Style.empty())
@@ -296,8 +296,8 @@
/// else.
template <typename T>
-struct format_provider<
- T, typename std::enable_if<detail::use_double_formatter<T>::value>::type>
+struct format_provider<T,
+ std::enable_if_t<detail::use_double_formatter<T>::value>>
: public detail::HelperFunctions {
static void format(const T &V, llvm::raw_ostream &Stream, StringRef Style) {
FloatStyle S;
diff --git a/linux-x64/clang/include/llvm/Support/FormatVariadic.h b/linux-x64/clang/include/llvm/Support/FormatVariadic.h
index 5bbda9d..094b054 100644
--- a/linux-x64/clang/include/llvm/Support/FormatVariadic.h
+++ b/linux-x64/clang/include/llvm/Support/FormatVariadic.h
@@ -25,6 +25,7 @@
#ifndef LLVM_SUPPORT_FORMATVARIADIC_H
#define LLVM_SUPPORT_FORMATVARIADIC_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
@@ -57,29 +58,14 @@
size_t Index = 0;
size_t Align = 0;
AlignStyle Where = AlignStyle::Right;
- char Pad;
+ char Pad = 0;
StringRef Options;
};
class formatv_object_base {
protected:
- // The parameters are stored in a std::tuple, which does not provide runtime
- // indexing capabilities. In order to enable runtime indexing, we use this
- // structure to put the parameters into a std::vector. Since the parameters
- // are not all the same type, we use some type-erasure by wrapping the
- // parameters in a template class that derives from a non-template superclass.
- // Essentially, we are converting a std::tuple<Derived<Ts...>> to a
- // std::vector<Base*>.
- struct create_adapters {
- template <typename... Ts>
- std::vector<detail::format_adapter *> operator()(Ts &... Items) {
- return std::vector<detail::format_adapter *>{&Items...};
- }
- };
-
StringRef Fmt;
- std::vector<detail::format_adapter *> Adapters;
- std::vector<ReplacementItem> Replacements;
+ ArrayRef<detail::format_adapter *> Adapters;
static bool consumeFieldLayout(StringRef &Spec, AlignStyle &Where,
size_t &Align, char &Pad);
@@ -87,23 +73,16 @@
static std::pair<ReplacementItem, StringRef>
splitLiteralAndReplacement(StringRef Fmt);
-public:
- formatv_object_base(StringRef Fmt, std::size_t ParamCount)
- : Fmt(Fmt), Replacements(parseFormatString(Fmt)) {
- Adapters.reserve(ParamCount);
- }
+ formatv_object_base(StringRef Fmt,
+ ArrayRef<detail::format_adapter *> Adapters)
+ : Fmt(Fmt), Adapters(Adapters) {}
formatv_object_base(formatv_object_base const &rhs) = delete;
+ formatv_object_base(formatv_object_base &&rhs) = default;
- formatv_object_base(formatv_object_base &&rhs)
- : Fmt(std::move(rhs.Fmt)),
- Adapters(), // Adapters are initialized by formatv_object
- Replacements(std::move(rhs.Replacements)) {
- Adapters.reserve(rhs.Adapters.size());
- };
-
+public:
void format(raw_ostream &S) const {
- for (auto &R : Replacements) {
+ for (auto &R : parseFormatString(Fmt)) {
if (R.Type == ReplacementType::Empty)
continue;
if (R.Type == ReplacementType::Literal) {
@@ -121,7 +100,7 @@
Align.format(S, R.Options);
}
}
- static std::vector<ReplacementItem> parseFormatString(StringRef Fmt);
+ static SmallVector<ReplacementItem, 2> parseFormatString(StringRef Fmt);
static Optional<ReplacementItem> parseReplacementItem(StringRef Spec);
@@ -150,12 +129,29 @@
// of the parameters, we have to own the storage for the parameters here, and
// have the base class store type-erased pointers into this tuple.
Tuple Parameters;
+ std::array<detail::format_adapter *, std::tuple_size<Tuple>::value>
+ ParameterPointers;
+
+ // The parameters are stored in a std::tuple, which does not provide runtime
+ // indexing capabilities. In order to enable runtime indexing, we use this
+ // structure to put the parameters into a std::array. Since the parameters
+ // are not all the same type, we use some type-erasure by wrapping the
+ // parameters in a template class that derives from a non-template superclass.
+ // Essentially, we are converting a std::tuple<Derived<Ts...>> to a
+ // std::array<Base*>.
+ struct create_adapters {
+ template <typename... Ts>
+ std::array<detail::format_adapter *, std::tuple_size<Tuple>::value>
+ operator()(Ts &... Items) {
+ return {{&Items...}};
+ }
+ };
public:
formatv_object(StringRef Fmt, Tuple &&Params)
- : formatv_object_base(Fmt, std::tuple_size<Tuple>::value),
+ : formatv_object_base(Fmt, ParameterPointers),
Parameters(std::move(Params)) {
- Adapters = apply_tuple(create_adapters(), Parameters);
+ ParameterPointers = apply_tuple(create_adapters(), Parameters);
}
formatv_object(formatv_object const &rhs) = delete;
@@ -163,7 +159,8 @@
formatv_object(formatv_object &&rhs)
: formatv_object_base(std::move(rhs)),
Parameters(std::move(rhs.Parameters)) {
- Adapters = apply_tuple(create_adapters(), Parameters);
+ ParameterPointers = apply_tuple(create_adapters(), Parameters);
+ Adapters = ParameterPointers;
}
};
@@ -208,10 +205,10 @@
//
// The characters '{' and '}' are reserved and cannot appear anywhere within a
// replacement sequence. Outside of a replacement sequence, in order to print
-// a literal '{' or '}' it must be doubled -- "{{" to print a literal '{' and
-// "}}" to print a literal '}'.
+// a literal '{' it must be doubled as "{{".
//
// ===Parameter Indexing===
+//
// `index` specifies the index of the parameter in the parameter pack to format
// into the output. Note that it is possible to refer to the same parameter
// index multiple times in a given format string. This makes it possible to
diff --git a/linux-x64/clang/include/llvm/Support/FormatVariadicDetails.h b/linux-x64/clang/include/llvm/Support/FormatVariadicDetails.h
index e3c1851..d5e67b7 100644
--- a/linux-x64/clang/include/llvm/Support/FormatVariadicDetails.h
+++ b/linux-x64/clang/include/llvm/Support/FormatVariadicDetails.h
@@ -36,7 +36,7 @@
explicit provider_format_adapter(T &&Item) : Item(std::forward<T>(Item)) {}
void format(llvm::raw_ostream &S, StringRef Options) override {
- format_provider<typename std::decay<T>::type>::format(Item, S, Options);
+ format_provider<std::decay_t<T>>::format(Item, S, Options);
}
};
@@ -59,7 +59,7 @@
//
template <class T> class has_FormatProvider {
public:
- using Decayed = typename std::decay<T>::type;
+ using Decayed = std::decay_t<T>;
typedef void (*Signature_format)(const Decayed &, llvm::raw_ostream &,
StringRef);
@@ -75,14 +75,14 @@
// Test if raw_ostream& << T -> raw_ostream& is findable via ADL.
template <class T> class has_StreamOperator {
public:
- using ConstRefT = const typename std::decay<T>::type &;
+ using ConstRefT = const std::decay_t<T> &;
template <typename U>
- static char test(typename std::enable_if<
- std::is_same<decltype(std::declval<llvm::raw_ostream &>()
- << std::declval<U>()),
- llvm::raw_ostream &>::value,
- int *>::type);
+ static char test(
+ std::enable_if_t<std::is_same<decltype(std::declval<llvm::raw_ostream &>()
+ << std::declval<U>()),
+ llvm::raw_ostream &>::value,
+ int *>);
template <typename U> static double test(...);
@@ -95,8 +95,8 @@
struct uses_format_member
: public std::integral_constant<
bool,
- std::is_base_of<format_adapter,
- typename std::remove_reference<T>::type>::value> {};
+ std::is_base_of<format_adapter, std::remove_reference_t<T>>::value> {
+};
// Simple template that decides whether a type T should use the format_provider
// based format() invocation. The member function takes priority, so this test
@@ -127,34 +127,32 @@
};
template <typename T>
-typename std::enable_if<uses_format_member<T>::value, T>::type
+std::enable_if_t<uses_format_member<T>::value, T>
build_format_adapter(T &&Item) {
return std::forward<T>(Item);
}
template <typename T>
-typename std::enable_if<uses_format_provider<T>::value,
- provider_format_adapter<T>>::type
+std::enable_if_t<uses_format_provider<T>::value, provider_format_adapter<T>>
build_format_adapter(T &&Item) {
return provider_format_adapter<T>(std::forward<T>(Item));
}
template <typename T>
-typename std::enable_if<uses_stream_operator<T>::value,
- stream_operator_format_adapter<T>>::type
+std::enable_if_t<uses_stream_operator<T>::value,
+ stream_operator_format_adapter<T>>
build_format_adapter(T &&Item) {
// If the caller passed an Error by value, then stream_operator_format_adapter
// would be responsible for consuming it.
// Make the caller opt into this by calling fmt_consume().
static_assert(
- !std::is_same<llvm::Error, typename std::remove_cv<T>::type>::value,
+ !std::is_same<llvm::Error, std::remove_cv_t<T>>::value,
"llvm::Error-by-value must be wrapped in fmt_consume() for formatv");
return stream_operator_format_adapter<T>(std::forward<T>(Item));
}
template <typename T>
-typename std::enable_if<uses_missing_provider<T>::value,
- missing_format_adapter<T>>::type
+std::enable_if_t<uses_missing_provider<T>::value, missing_format_adapter<T>>
build_format_adapter(T &&Item) {
return missing_format_adapter<T>();
}
diff --git a/linux-x64/clang/include/llvm/Support/FormattedStream.h b/linux-x64/clang/include/llvm/Support/FormattedStream.h
index b49c8d8..5f937cf 100644
--- a/linux-x64/clang/include/llvm/Support/FormattedStream.h
+++ b/linux-x64/clang/include/llvm/Support/FormattedStream.h
@@ -14,6 +14,7 @@
#ifndef LLVM_SUPPORT_FORMATTEDSTREAM_H
#define LLVM_SUPPORT_FORMATTEDSTREAM_H
+#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>
@@ -21,8 +22,11 @@
/// formatted_raw_ostream - A raw_ostream that wraps another one and keeps track
/// of line and column position, allowing padding out to specific column
-/// boundaries and querying the number of lines written to the stream.
-///
+/// boundaries and querying the number of lines written to the stream. This
+/// assumes that the contents of the stream is valid UTF-8 encoded text. This
+/// doesn't attempt to handle everything Unicode can do (combining characters,
+/// right-to-left markers, etc), but should cover the cases likely to appear in
+/// source code or diagnostic messages.
class formatted_raw_ostream : public raw_ostream {
/// TheStream - The real stream we output to. We set it to be
/// unbuffered, since we're already doing our own buffering.
@@ -40,6 +44,14 @@
///
const char *Scanned;
+ /// PartialUTF8Char - Either empty or a prefix of a UTF-8 code unit sequence
+ /// for a Unicode scalar value which should be prepended to the buffer for the
+ /// next call to ComputePosition. This is needed when the buffer is flushed
+ /// when it ends part-way through the UTF-8 encoding of a Unicode scalar
+ /// value, so that we can compute the display width of the character once we
+ /// have the rest of it.
+ SmallString<4> PartialUTF8Char;
+
void write_impl(const char *Ptr, size_t Size) override;
/// current_pos - Return the current position within the stream,
@@ -52,10 +64,16 @@
}
/// ComputePosition - Examine the given output buffer and figure out the new
- /// position after output.
- ///
+ /// position after output. This is safe to call multiple times on the same
+ /// buffer, as it records the most recently scanned character and resumes from
+ /// there when the buffer has not been flushed.
void ComputePosition(const char *Ptr, size_t size);
+ /// UpdatePosition - scan the characters in [Ptr, Ptr+Size), and update the
+ /// line and column numbers. Unlike ComputePosition, this must be called
+ /// exactly once on each region of the buffer.
+ void UpdatePosition(const char *Ptr, size_t Size);
+
void setStream(raw_ostream &Stream) {
releaseStream();
@@ -105,11 +123,17 @@
/// \param NewCol - The column to move to.
formatted_raw_ostream &PadToColumn(unsigned NewCol);
- /// getColumn - Return the column number
- unsigned getColumn() { return Position.first; }
+ unsigned getColumn() {
+ // Calculate current position, taking buffer contents into account.
+ ComputePosition(getBufferStart(), GetNumBytesInBuffer());
+ return Position.first;
+ }
- /// getLine - Return the line number
- unsigned getLine() { return Position.second; }
+ unsigned getLine() {
+ // Calculate current position, taking buffer contents into account.
+ ComputePosition(getBufferStart(), GetNumBytesInBuffer());
+ return Position.second;
+ }
raw_ostream &resetColor() override {
TheStream->resetColor();
diff --git a/linux-x64/clang/include/llvm/Support/GenericDomTree.h b/linux-x64/clang/include/llvm/Support/GenericDomTree.h
index 9962080..28b2537 100644
--- a/linux-x64/clang/include/llvm/Support/GenericDomTree.h
+++ b/linux-x64/clang/include/llvm/Support/GenericDomTree.h
@@ -25,10 +25,10 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
-#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/CFGDiff.h"
#include "llvm/Support/CFGUpdate.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -38,7 +38,6 @@
#include <memory>
#include <type_traits>
#include <utility>
-#include <vector>
namespace llvm {
@@ -61,7 +60,7 @@
NodeT *TheBB;
DomTreeNodeBase *IDom;
unsigned Level;
- std::vector<DomTreeNodeBase *> Children;
+ SmallVector<DomTreeNodeBase *, 4> Children;
mutable unsigned DFSNumIn = ~0;
mutable unsigned DFSNumOut = ~0;
@@ -69,27 +68,34 @@
DomTreeNodeBase(NodeT *BB, DomTreeNodeBase *iDom)
: TheBB(BB), IDom(iDom), Level(IDom ? IDom->Level + 1 : 0) {}
- using iterator = typename std::vector<DomTreeNodeBase *>::iterator;
+ using iterator = typename SmallVector<DomTreeNodeBase *, 4>::iterator;
using const_iterator =
- typename std::vector<DomTreeNodeBase *>::const_iterator;
+ typename SmallVector<DomTreeNodeBase *, 4>::const_iterator;
iterator begin() { return Children.begin(); }
iterator end() { return Children.end(); }
const_iterator begin() const { return Children.begin(); }
const_iterator end() const { return Children.end(); }
+ DomTreeNodeBase *const &back() const { return Children.back(); }
+ DomTreeNodeBase *&back() { return Children.back(); }
+
+ iterator_range<iterator> children() { return make_range(begin(), end()); }
+ iterator_range<const_iterator> children() const {
+ return make_range(begin(), end());
+ }
+
NodeT *getBlock() const { return TheBB; }
DomTreeNodeBase *getIDom() const { return IDom; }
unsigned getLevel() const { return Level; }
- const std::vector<DomTreeNodeBase *> &getChildren() const { return Children; }
-
std::unique_ptr<DomTreeNodeBase> addChild(
std::unique_ptr<DomTreeNodeBase> C) {
Children.push_back(C.get());
return C;
}
+ bool isLeaf() const { return Children.empty(); }
size_t getNumChildren() const { return Children.size(); }
void clearAllChildren() { Children.clear(); }
@@ -205,7 +211,10 @@
template <typename DomTreeT>
void ApplyUpdates(DomTreeT &DT,
- ArrayRef<typename DomTreeT::UpdateType> Updates);
+ GraphDiff<typename DomTreeT::NodePtr,
+ DomTreeT::IsPostDominator> &PreViewCFG,
+ GraphDiff<typename DomTreeT::NodePtr,
+ DomTreeT::IsPostDominator> *PostViewCFG);
template <typename DomTreeT>
bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL);
@@ -225,7 +234,7 @@
using ParentPtr = decltype(std::declval<NodeT *>()->getParent());
static_assert(std::is_pointer<ParentPtr>::value,
"Currently NodeT's parent must be a pointer type");
- using ParentType = typename std::remove_pointer<ParentPtr>::type;
+ using ParentType = std::remove_pointer_t<ParentPtr>;
static constexpr bool IsPostDominator = IsPostDom;
using UpdateType = cfg::Update<NodePtr>;
@@ -242,7 +251,7 @@
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;
@@ -277,11 +286,27 @@
DominatorTreeBase(const DominatorTreeBase &) = delete;
DominatorTreeBase &operator=(const DominatorTreeBase &) = delete;
- /// getRoots - Return the root blocks of the current CFG. This may include
- /// multiple blocks if we are computing post dominators. For forward
- /// dominators, this will always be a single block (the entry node).
+ /// Iteration over roots.
///
- const SmallVectorImpl<NodeT *> &getRoots() const { return Roots; }
+ /// This may include multiple blocks if we are computing post dominators.
+ /// For forward dominators, this will always be a single block (the entry
+ /// block).
+ using root_iterator = typename SmallVectorImpl<NodeT *>::iterator;
+ using const_root_iterator = typename SmallVectorImpl<NodeT *>::const_iterator;
+
+ root_iterator root_begin() { return Roots.begin(); }
+ const_root_iterator root_begin() const { return Roots.begin(); }
+ root_iterator root_end() { return Roots.end(); }
+ const_root_iterator root_end() const { return Roots.end(); }
+
+ size_t root_size() const { return Roots.size(); }
+
+ iterator_range<root_iterator> roots() {
+ return make_range(root_begin(), root_end());
+ }
+ iterator_range<const_root_iterator> roots() const {
+ return make_range(root_begin(), root_end());
+ }
/// isPostDominator - Returns true if analysis based of postdoms
///
@@ -319,8 +344,6 @@
return false;
}
- void releaseMemory() { reset(); }
-
/// getNode - return the (Post)DominatorTree node for the specified basic
/// block. This is the same as using operator[] on this class. The result
/// may (but is not required to) be null for a forward (backwards)
@@ -440,8 +463,8 @@
return this->Roots[0];
}
- /// findNearestCommonDominator - Find nearest common dominator basic block
- /// for basic block A and B. If there is no such block then return nullptr.
+ /// Find nearest common dominator basic block for basic block A and B. A and B
+ /// must have tree nodes.
NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) const {
assert(A && B && "Pointers are not valid");
assert(A->getParent() == B->getParent() &&
@@ -457,18 +480,18 @@
DomTreeNodeBase<NodeT> *NodeA = getNode(A);
DomTreeNodeBase<NodeT> *NodeB = getNode(B);
-
- if (!NodeA || !NodeB) return nullptr;
+ assert(NodeA && "A must be in the tree");
+ assert(NodeB && "B must be in the tree");
// Use level information to go up the tree until the levels match. Then
// continue going up til we arrive at the same node.
- while (NodeA && NodeA != NodeB) {
+ while (NodeA != NodeB) {
if (NodeA->getLevel() < NodeB->getLevel()) std::swap(NodeA, NodeB);
NodeA = NodeA->IDom;
}
- return NodeA ? NodeA->getBlock() : nullptr;
+ return NodeA->getBlock();
}
const NodeT *findNearestCommonDominator(const NodeT *A,
@@ -515,10 +538,39 @@
/// The type of updates is the same for DomTreeBase<T> and PostDomTreeBase<T>
/// with the same template parameter T.
///
- /// \param Updates An unordered sequence of updates to perform.
+ /// \param Updates An unordered sequence of updates to perform. The current
+ /// CFG and the reverse of these updates provides the pre-view of the CFG.
///
void applyUpdates(ArrayRef<UpdateType> Updates) {
- DomTreeBuilder::ApplyUpdates(*this, Updates);
+ GraphDiff<NodePtr, IsPostDominator> PreViewCFG(
+ Updates, /*ReverseApplyUpdates=*/true);
+ DomTreeBuilder::ApplyUpdates(*this, PreViewCFG, nullptr);
+ }
+
+ /// \param Updates An unordered sequence of updates to perform. The current
+ /// CFG and the reverse of these updates provides the pre-view of the CFG.
+ /// \param PostViewUpdates An unordered sequence of update to perform in order
+ /// to obtain a post-view of the CFG. The DT will be updated assuming the
+ /// obtained PostViewCFG is the desired end state.
+ void applyUpdates(ArrayRef<UpdateType> Updates,
+ ArrayRef<UpdateType> PostViewUpdates) {
+ if (Updates.empty()) {
+ GraphDiff<NodePtr, IsPostDom> PostViewCFG(PostViewUpdates);
+ DomTreeBuilder::ApplyUpdates(*this, PostViewCFG, &PostViewCFG);
+ } else {
+ // PreViewCFG needs to merge Updates and PostViewCFG. The updates in
+ // Updates need to be reversed, and match the direction in PostViewCFG.
+ // The PostViewCFG is created with updates reversed (equivalent to changes
+ // made to the CFG), so the PreViewCFG needs all the updates reverse
+ // applied.
+ SmallVector<UpdateType> AllUpdates(Updates.begin(), Updates.end());
+ for (auto &Update : PostViewUpdates)
+ AllUpdates.push_back(Update);
+ GraphDiff<NodePtr, IsPostDom> PreViewCFG(AllUpdates,
+ /*ReverseApplyUpdates=*/true);
+ GraphDiff<NodePtr, IsPostDom> PostViewCFG(PostViewUpdates);
+ DomTreeBuilder::ApplyUpdates(*this, PreViewCFG, &PostViewCFG);
+ }
}
/// Inform the dominator tree about a CFG edge insertion and update the tree.
@@ -570,8 +622,7 @@
DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB);
assert(IDomNode && "Not immediate dominator specified for block!");
DFSInfoValid = false;
- return (DomTreeNodes[BB] = IDomNode->addChild(
- llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get();
+ return createChild(BB, IDomNode);
}
/// Add a new node to the forward dominator tree and make it a new root.
@@ -584,8 +635,7 @@
assert(!this->isPostDominator() &&
"Cannot change root of post-dominator tree");
DFSInfoValid = false;
- DomTreeNodeBase<NodeT> *NewNode = (DomTreeNodes[BB] =
- llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, nullptr)).get();
+ DomTreeNodeBase<NodeT> *NewNode = createNode(BB);
if (Roots.empty()) {
addRoot(BB);
} else {
@@ -620,7 +670,7 @@
void eraseNode(NodeT *BB) {
DomTreeNodeBase<NodeT> *Node = getNode(BB);
assert(Node && "Removing node that isn't in dominator tree.");
- assert(Node->getChildren().empty() && "Node is not a leaf node.");
+ assert(Node->isLeaf() && "Node is not a leaf node.");
DFSInfoValid = false;
@@ -754,9 +804,6 @@
return DomTreeBuilder::Verify(*this, VL);
}
-protected:
- void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
-
void reset() {
DomTreeNodes.clear();
Roots.clear();
@@ -766,6 +813,21 @@
SlowQueries = 0;
}
+protected:
+ void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
+
+ DomTreeNodeBase<NodeT> *createChild(NodeT *BB, DomTreeNodeBase<NodeT> *IDom) {
+ return (DomTreeNodes[BB] = IDom->addChild(
+ std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDom)))
+ .get();
+ }
+
+ DomTreeNodeBase<NodeT> *createNode(NodeT *BB) {
+ return (DomTreeNodes[BB] =
+ std::make_unique<DomTreeNodeBase<NodeT>>(BB, nullptr))
+ .get();
+ }
+
// NewBB is split and now it has one successor. Update dominator tree to
// reflect this change.
template <class N>
@@ -777,14 +839,14 @@
"NewBB should have a single successor!");
NodeRef NewBBSucc = *GraphT::child_begin(NewBB);
- std::vector<NodeRef> PredBlocks;
- for (const auto &Pred : children<Inverse<N>>(NewBB))
+ SmallVector<NodeRef, 4> PredBlocks;
+ for (auto Pred : children<Inverse<N>>(NewBB))
PredBlocks.push_back(Pred);
assert(!PredBlocks.empty() && "No predblocks?");
bool NewBBDominatesNewBBSucc = true;
- for (const auto &Pred : children<Inverse<N>>(NewBBSucc)) {
+ for (auto Pred : children<Inverse<N>>(NewBBSucc)) {
if (Pred != NewBB && !dominates(NewBBSucc, Pred) &&
isReachableFromEntry(Pred)) {
NewBBDominatesNewBBSucc = false;
diff --git a/linux-x64/clang/include/llvm/Support/GenericDomTreeConstruction.h b/linux-x64/clang/include/llvm/Support/GenericDomTreeConstruction.h
index ccceba8..4b59ad1 100644
--- a/linux-x64/clang/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/linux-x64/clang/include/llvm/Support/GenericDomTreeConstruction.h
@@ -7,11 +7,11 @@
//===----------------------------------------------------------------------===//
/// \file
///
-/// Generic dominator tree construction - This file provides routines to
+/// Generic dominator tree construction - this file provides routines to
/// construct immediate dominator information for a flow-graph based on the
/// Semi-NCA algorithm described in this dissertation:
///
-/// Linear-Time Algorithms for Dominators and Related Problems
+/// [1] Linear-Time Algorithms for Dominators and Related Problems
/// Loukas Georgiadis, Princeton University, November 2005, pp. 21-23:
/// ftp://ftp.cs.princeton.edu/reports/2005/737.pdf
///
@@ -20,13 +20,15 @@
///
/// O(n^2) worst cases happen when the computation of nearest common ancestors
/// requires O(n) average time, which is very unlikely in real world. If this
-/// ever turns out to be an issue, consider implementing a hybrid algorithm.
+/// ever turns out to be an issue, consider implementing a hybrid algorithm
+/// that uses SLT to perform full constructions and SemiNCA for incremental
+/// updates.
///
/// The file uses the Depth Based Search algorithm to perform incremental
/// updates (insertion and deletions). The implemented algorithm is based on
/// this publication:
///
-/// An Experimental Study of Dynamic Dominators
+/// [2] An Experimental Study of Dynamic Dominators
/// Loukas Georgiadis, et al., April 12 2016, pp. 5-7, 9-10:
/// https://arxiv.org/pdf/1604.02711.pdf
///
@@ -35,7 +37,6 @@
#ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
#define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
-#include <queue>
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DepthFirstIterator.h"
@@ -43,6 +44,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GenericDomTree.h"
+#include <queue>
#define DEBUG_TYPE "dom-tree-builder"
@@ -56,6 +58,7 @@
using TreeNodePtr = DomTreeNodeBase<NodeT> *;
using RootsT = decltype(DomTreeT::Roots);
static constexpr bool IsPostDom = DomTreeT::IsPostDominator;
+ using GraphDiffT = GraphDiff<NodePtr, IsPostDom>;
// Information record used by Semi-NCA during tree construction.
struct InfoRec {
@@ -75,21 +78,17 @@
using UpdateT = typename DomTreeT::UpdateType;
using UpdateKind = typename DomTreeT::UpdateKind;
struct BatchUpdateInfo {
- SmallVector<UpdateT, 4> Updates;
- using NodePtrAndKind = PointerIntPair<NodePtr, 1, UpdateKind>;
+ // Note: Updates inside PreViewCFG are aleady legalized.
+ BatchUpdateInfo(GraphDiffT &PreViewCFG, GraphDiffT *PostViewCFG = nullptr)
+ : PreViewCFG(PreViewCFG), PostViewCFG(PostViewCFG),
+ NumLegalized(PreViewCFG.getNumLegalizedUpdates()) {}
- // In order to be able to walk a CFG that is out of sync with the CFG
- // DominatorTree last knew about, use the list of updates to reconstruct
- // previous CFG versions of the current CFG. For each node, we store a set
- // of its virtually added/deleted future successors and predecessors.
- // Note that these children are from the future relative to what the
- // DominatorTree knows about -- using them to gets us some snapshot of the
- // CFG from the past (relative to the state of the CFG).
- DenseMap<NodePtr, SmallVector<NodePtrAndKind, 4>> FutureSuccessors;
- DenseMap<NodePtr, SmallVector<NodePtrAndKind, 4>> FuturePredecessors;
// Remembers if the whole tree was recalculated at some point during the
// current batch update.
bool IsRecalculated = false;
+ GraphDiffT &PreViewCFG;
+ GraphDiffT *PostViewCFG;
+ const size_t NumLegalized;
};
BatchUpdateInfo *BatchUpdates;
@@ -105,66 +104,24 @@
// in progress, we need this information to continue it.
}
- template <bool Inverse>
- struct ChildrenGetter {
- using ResultTy = SmallVector<NodePtr, 8>;
+ template <bool Inversed>
+ static SmallVector<NodePtr, 8> getChildren(NodePtr N, BatchUpdatePtr BUI) {
+ if (BUI)
+ return BUI->PreViewCFG.template getChildren<Inversed>(N);
+ return getChildren<Inversed>(N);
+ }
- static ResultTy Get(NodePtr N, std::integral_constant<bool, false>) {
- auto RChildren = reverse(children<NodePtr>(N));
- return ResultTy(RChildren.begin(), RChildren.end());
- }
+ template <bool Inversed>
+ static SmallVector<NodePtr, 8> getChildren(NodePtr N) {
+ using DirectedNodeT =
+ std::conditional_t<Inversed, Inverse<NodePtr>, NodePtr>;
+ auto R = children<DirectedNodeT>(N);
+ SmallVector<NodePtr, 8> Res(detail::reverse_if<!Inversed>(R));
- static ResultTy Get(NodePtr N, std::integral_constant<bool, true>) {
- auto IChildren = inverse_children<NodePtr>(N);
- return ResultTy(IChildren.begin(), IChildren.end());
- }
-
- using Tag = std::integral_constant<bool, Inverse>;
-
- // The function below is the core part of the batch updater. It allows the
- // Depth Based Search algorithm to perform incremental updates in lockstep
- // with updates to the CFG. We emulated lockstep CFG updates by getting its
- // next snapshots by reverse-applying future updates.
- static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) {
- ResultTy Res = Get(N, Tag());
- // If there's no batch update in progress, simply return node's children.
- if (!BUI) return Res;
-
- // CFG children are actually its *most current* children, and we have to
- // reverse-apply the future updates to get the node's children at the
- // point in time the update was performed.
- auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors
- : BUI->FutureSuccessors;
- auto FCIt = FutureChildren.find(N);
- if (FCIt == FutureChildren.end()) return Res;
-
- for (auto ChildAndKind : FCIt->second) {
- const NodePtr Child = ChildAndKind.getPointer();
- const UpdateKind UK = ChildAndKind.getInt();
-
- // Reverse-apply the future update.
- if (UK == UpdateKind::Insert) {
- // If there's an insertion in the future, it means that the edge must
- // exist in the current CFG, but was not present in it before.
- assert(llvm::find(Res, Child) != Res.end()
- && "Expected child not found in the CFG");
- Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end());
- LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> "
- << BlockNamePrinter(Child) << "\n");
- } else {
- // If there's an deletion in the future, it means that the edge cannot
- // exist in the current CFG, but existed in it before.
- assert(llvm::find(Res, Child) == Res.end() &&
- "Unexpected child found in the CFG");
- LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N)
- << " -> " << BlockNamePrinter(Child) << "\n");
- Res.push_back(Child);
- }
- }
-
- return Res;
- }
- };
+ // Remove nullptr children for clang.
+ llvm::erase_value(Res, nullptr);
+ return Res;
+ }
NodePtr getIDom(NodePtr BB) const {
auto InfoIt = NodeToInfo.find(BB);
@@ -185,9 +142,7 @@
// 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)))
- .get();
+ return DT.createChild(BB, IDomNode);
}
static bool AlwaysDescend(NodePtr, NodePtr) { return true; }
@@ -208,6 +163,8 @@
}
};
+ using NodeOrderMap = DenseMap<NodePtr, unsigned>;
+
// Custom DFS implementation which can skip nodes based on a provided
// predicate. It also collects ReverseChildren so that we don't have to spend
// time getting predecessors in SemiNCA.
@@ -215,9 +172,13 @@
// If IsReverse is set to true, the DFS walk will be performed backwards
// relative to IsPostDom -- using reverse edges for dominators and forward
// edges for postdominators.
+ //
+ // If SuccOrder is specified then in this order the DFS traverses the children
+ // otherwise the order is implied by the results of getChildren().
template <bool IsReverse = false, typename DescendCondition>
unsigned runDFS(NodePtr V, unsigned LastNum, DescendCondition Condition,
- unsigned AttachToNum) {
+ unsigned AttachToNum,
+ const NodeOrderMap *SuccOrder = nullptr) {
assert(V);
SmallVector<NodePtr, 64> WorkList = {V};
if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum;
@@ -233,8 +194,14 @@
NumToNode.push_back(BB);
constexpr bool Direction = IsReverse != IsPostDom; // XOR.
- for (const NodePtr Succ :
- ChildrenGetter<Direction>::Get(BB, BatchUpdates)) {
+ auto Successors = getChildren<Direction>(BB, BatchUpdates);
+ if (SuccOrder && Successors.size() > 1)
+ llvm::sort(
+ Successors.begin(), Successors.end(), [=](NodePtr A, NodePtr B) {
+ return SuccOrder->find(A)->second < SuccOrder->find(B)->second;
+ });
+
+ for (const NodePtr Succ : Successors) {
const auto SIT = NodeToInfo.find(Succ);
// Don't visit nodes more than once but remember to collect
// ReverseChildren.
@@ -369,7 +336,7 @@
// to CFG nodes within infinite loops.
static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI) {
assert(N && "N must be a valid node");
- return !ChildrenGetter<false>::Get(N, BUI).empty();
+ return !getChildren<false>(N, BUI).empty();
}
static NodePtr GetEntryNode(const DomTreeT &DT) {
@@ -430,6 +397,32 @@
// nodes.
if (Total + 1 != Num) {
HasNonTrivialRoots = true;
+
+ // SuccOrder is the order of blocks in the function. It is needed to make
+ // the calculation of the FurthestAway node and the whole PostDomTree
+ // immune to swap successors transformation (e.g. canonicalizing branch
+ // predicates). SuccOrder is initialized lazily only for successors of
+ // reverse unreachable nodes.
+ Optional<NodeOrderMap> SuccOrder;
+ auto InitSuccOrderOnce = [&]() {
+ SuccOrder = NodeOrderMap();
+ for (const auto Node : nodes(DT.Parent))
+ if (SNCA.NodeToInfo.count(Node) == 0)
+ for (const auto Succ : getChildren<false>(Node, SNCA.BatchUpdates))
+ SuccOrder->try_emplace(Succ, 0);
+
+ // Add mapping for all entries of SuccOrder.
+ unsigned NodeNum = 0;
+ for (const auto Node : nodes(DT.Parent)) {
+ ++NodeNum;
+ auto Order = SuccOrder->find(Node);
+ if (Order != SuccOrder->end()) {
+ assert(Order->second == 0);
+ Order->second = NodeNum;
+ }
+ }
+ };
+
// Make another DFS pass over all other nodes to find the
// reverse-unreachable blocks, and find the furthest paths we'll be able
// to make.
@@ -454,7 +447,12 @@
// expensive and does not always lead to a minimal set of roots.
LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n");
- const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num);
+ if (!SuccOrder)
+ InitSuccOrderOnce();
+ assert(SuccOrder);
+
+ const unsigned NewNum =
+ SNCA.runDFS<true>(I, Num, AlwaysDescend, Num, &*SuccOrder);
const NodePtr FurthestAway = SNCA.NumToNode[NewNum];
LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node "
<< "(non-trivial root): "
@@ -530,7 +528,7 @@
// If we wound another root in a (forward) DFS walk, remove the current
// root from the set of roots, as it is reverse-reachable from the other
// one.
- if (llvm::find(Roots, N) != Roots.end()) {
+ if (llvm::is_contained(Roots, N)) {
LLVM_DEBUG(dbgs() << "\tForward DFS walk found another root "
<< BlockNamePrinter(N) << "\n\tRemoving root "
<< BlockNamePrinter(Root) << "\n");
@@ -563,12 +561,21 @@
auto *Parent = DT.Parent;
DT.reset();
DT.Parent = Parent;
- SemiNCAInfo SNCA(nullptr); // Since we are rebuilding the whole tree,
- // there's no point doing it incrementally.
+ // If the update is using the actual CFG, BUI is null. If it's using a view,
+ // BUI is non-null and the PreCFGView is used. When calculating from
+ // scratch, make the PreViewCFG equal to the PostCFGView, so Post is used.
+ BatchUpdatePtr PostViewBUI = nullptr;
+ if (BUI && BUI->PostViewCFG) {
+ BUI->PreViewCFG = *BUI->PostViewCFG;
+ PostViewBUI = BUI;
+ }
+ // This is rebuilding the whole tree, not incrementally, but PostViewBUI is
+ // used in case the caller needs a DT update with a CFGView.
+ SemiNCAInfo SNCA(PostViewBUI);
// Step #0: Number blocks in depth-first order and initialize variables used
// in later stages of the algorithm.
- DT.Roots = FindRoots(DT, nullptr);
+ DT.Roots = FindRoots(DT, PostViewBUI);
SNCA.doFullDFSWalk(DT, AlwaysDescend);
SNCA.runSemiNCA(DT);
@@ -585,9 +592,7 @@
// all real exits (including multiple exit blocks, infinite loops).
NodePtr Root = IsPostDom ? nullptr : DT.Roots[0];
- DT.RootNode = (DT.DomTreeNodes[Root] =
- llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr))
- .get();
+ DT.RootNode = DT.createNode(Root);
SNCA.attachNewSubtree(DT, DT.RootNode);
}
@@ -597,8 +602,6 @@
// Loop over all of the discovered blocks in the function...
for (size_t i = 1, e = NumToNode.size(); i != e; ++i) {
NodePtr W = NumToNode[i];
- LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node "
- << BlockNamePrinter(W) << "\n");
// Don't replace this with 'count', the insertion side effect is important
if (DT.DomTreeNodes[W]) continue; // Haven't calculated this node yet?
@@ -610,8 +613,7 @@
// 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));
+ DT.createChild(W, IDomNode);
}
}
@@ -661,10 +663,7 @@
// The unreachable node becomes a new root -- a tree node for it.
TreeNodePtr VirtualRoot = DT.getNode(nullptr);
- FromTN =
- (DT.DomTreeNodes[From] = VirtualRoot->addChild(
- llvm::make_unique<DomTreeNodeBase<NodeT>>(From, VirtualRoot)))
- .get();
+ FromTN = DT.createChild(From, VirtualRoot);
DT.Roots.push_back(From);
}
@@ -687,8 +686,7 @@
// root.
if (!DT.isVirtualRoot(To->getIDom())) return false;
- auto RIt = llvm::find(DT.Roots, To->getBlock());
- if (RIt == DT.Roots.end())
+ if (!llvm::is_contained(DT.Roots, To->getBlock()))
return false; // To is not a root, nothing to update.
LLVM_DEBUG(dbgs() << "\t\tAfter the insertion, " << BlockNamePrinter(To)
@@ -732,7 +730,7 @@
LLVM_DEBUG(dbgs() << "Roots are different in updated trees\n"
<< "The entire tree needs to be rebuilt\n");
// It may be possible to update the tree without recalculating it, but
- // we do not know yet how to do it, and it happens rarely in practise.
+ // we do not know yet how to do it, and it happens rarely in practice.
CalculateFromScratch(DT, BUI);
}
}
@@ -757,13 +755,13 @@
LLVM_DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n");
const unsigned NCDLevel = NCD->getLevel();
- // Based on Lemma 2.5 from the second paper, after insertion of (From,To), v
- // is affected iff depth(NCD)+1 < depth(v) && a path P from To to v exists
- // where every w on P s.t. depth(v) <= depth(w)
+ // Based on Lemma 2.5 from [2], after insertion of (From,To), v is affected
+ // iff depth(NCD)+1 < depth(v) && a path P from To to v exists where every
+ // w on P s.t. depth(v) <= depth(w)
//
// This reduces to a widest path problem (maximizing the depth of the
// minimum vertex in the path) which can be solved by a modified version of
- // Dijkstra with a bucket queue (named depth-based search in the paper).
+ // Dijkstra with a bucket queue (named depth-based search in [2]).
// To is in the path, so depth(NCD)+1 < depth(v) <= depth(To). Nothing
// affected if this does not hold.
@@ -795,8 +793,7 @@
//
// Invariant: there is an optimal path from `To` to TN with the minimum
// depth being CurrentLevel.
- for (const NodePtr Succ :
- ChildrenGetter<IsPostDom>::Get(TN->getBlock(), BUI)) {
+ for (const NodePtr Succ : getChildren<IsPostDom>(TN->getBlock(), BUI)) {
const TreeNodePtr SuccTN = DT.getNode(Succ);
assert(SuccTN &&
"Unreachable successor found at reachable insertion");
@@ -926,8 +923,8 @@
// the DomTree about it.
// The check is O(N), so run it only in debug configuration.
auto IsSuccessor = [BUI](const NodePtr SuccCandidate, const NodePtr Of) {
- auto Successors = ChildrenGetter<IsPostDom>::Get(Of, BUI);
- return llvm::find(Successors, SuccCandidate) != Successors.end();
+ auto Successors = getChildren<IsPostDom>(Of, BUI);
+ return llvm::is_contained(Successors, SuccCandidate);
};
(void)IsSuccessor;
assert(!IsSuccessor(To, From) && "Deleted edge still exists in the CFG!");
@@ -957,7 +954,7 @@
<< BlockNamePrinter(ToIDom) << "\n");
// To remains reachable after deletion.
- // (Based on the caption under Figure 4. from the second paper.)
+ // (Based on the caption under Figure 4. from [2].)
if (FromTN != ToIDom || HasProperSupport(DT, BUI, ToTN))
DeleteReachable(DT, BUI, FromTN, ToTN);
else
@@ -976,7 +973,7 @@
LLVM_DEBUG(dbgs() << "\tRebuilding subtree\n");
// Find the top of the subtree that needs to be rebuilt.
- // (Based on the lemma 2.6 from the second paper.)
+ // (Based on the lemma 2.6 from [2].)
const NodePtr ToIDom =
DT.findNearestCommonDominator(FromTN->getBlock(), ToTN->getBlock());
assert(ToIDom || DT.isPostDominator());
@@ -1008,20 +1005,19 @@
}
// Checks if a node has proper support, as defined on the page 3 and later
- // explained on the page 7 of the second paper.
+ // explained on the page 7 of [2].
static bool HasProperSupport(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr TN) {
LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN)
<< "\n");
- for (const NodePtr Pred :
- ChildrenGetter<!IsPostDom>::Get(TN->getBlock(), BUI)) {
+ auto TNB = TN->getBlock();
+ for (const NodePtr Pred : getChildren<!IsPostDom>(TNB, BUI)) {
LLVM_DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n");
if (!DT.getNode(Pred)) continue;
- const NodePtr Support =
- DT.findNearestCommonDominator(TN->getBlock(), Pred);
+ const NodePtr Support = DT.findNearestCommonDominator(TNB, Pred);
LLVM_DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n");
- if (Support != TN->getBlock()) {
+ if (Support != TNB) {
LLVM_DEBUG(dbgs() << "\t" << BlockNamePrinter(TN)
<< " is reachable from support "
<< BlockNamePrinter(Support) << "\n");
@@ -1033,7 +1029,7 @@
}
// Handle deletions that make destination node unreachable.
- // (Based on the lemma 2.7 from the second paper.)
+ // (Based on the lemma 2.7 from the [2].)
static void DeleteUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr ToTN) {
LLVM_DEBUG(dbgs() << "Deleting unreachable subtree "
@@ -1062,7 +1058,7 @@
const TreeNodePtr TN = DT.getNode(To);
assert(TN);
if (TN->getLevel() > Level) return true;
- if (llvm::find(AffectedQueue, To) == AffectedQueue.end())
+ if (!llvm::is_contained(AffectedQueue, To))
AffectedQueue.push_back(To);
return false;
@@ -1152,53 +1148,34 @@
//===--------------------- DomTree Batch Updater --------------------------===
//~~
- static void ApplyUpdates(DomTreeT &DT, ArrayRef<UpdateT> Updates) {
- const size_t NumUpdates = Updates.size();
+ static void ApplyUpdates(DomTreeT &DT, GraphDiffT &PreViewCFG,
+ GraphDiffT *PostViewCFG) {
+ // Note: the PostViewCFG is only used when computing from scratch. It's data
+ // should already included in the PreViewCFG for incremental updates.
+ const size_t NumUpdates = PreViewCFG.getNumLegalizedUpdates();
if (NumUpdates == 0)
return;
// Take the fast path for a single update and avoid running the batch update
// machinery.
if (NumUpdates == 1) {
- const auto &Update = Updates.front();
- if (Update.getKind() == UpdateKind::Insert)
- DT.insertEdge(Update.getFrom(), Update.getTo());
- else
- DT.deleteEdge(Update.getFrom(), Update.getTo());
-
+ UpdateT Update = PreViewCFG.popUpdateForIncrementalUpdates();
+ if (!PostViewCFG) {
+ if (Update.getKind() == UpdateKind::Insert)
+ InsertEdge(DT, /*BUI=*/nullptr, Update.getFrom(), Update.getTo());
+ else
+ DeleteEdge(DT, /*BUI=*/nullptr, Update.getFrom(), Update.getTo());
+ } else {
+ BatchUpdateInfo BUI(*PostViewCFG, PostViewCFG);
+ if (Update.getKind() == UpdateKind::Insert)
+ InsertEdge(DT, &BUI, Update.getFrom(), Update.getTo());
+ else
+ DeleteEdge(DT, &BUI, Update.getFrom(), Update.getTo());
+ }
return;
}
- BatchUpdateInfo BUI;
- LLVM_DEBUG(dbgs() << "Legalizing " << BUI.Updates.size() << " updates\n");
- cfg::LegalizeUpdates<NodePtr>(Updates, BUI.Updates, IsPostDom);
-
- const size_t NumLegalized = BUI.Updates.size();
- BUI.FutureSuccessors.reserve(NumLegalized);
- BUI.FuturePredecessors.reserve(NumLegalized);
-
- // Use the legalized future updates to initialize future successors and
- // predecessors. Note that these sets will only decrease size over time, as
- // the next CFG snapshots slowly approach the actual (current) CFG.
- for (UpdateT &U : BUI.Updates) {
- BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()});
- BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()});
- }
-
-#if 0
- // FIXME: The LLVM_DEBUG macro only plays well with a modular
- // build of LLVM when the header is marked as textual, but doing
- // so causes redefinition errors.
- LLVM_DEBUG(dbgs() << "About to apply " << NumLegalized << " updates\n");
- LLVM_DEBUG(if (NumLegalized < 32) for (const auto &U
- : reverse(BUI.Updates)) {
- dbgs() << "\t";
- U.dump();
- dbgs() << "\n";
- });
- LLVM_DEBUG(dbgs() << "\n");
-#endif
-
+ BatchUpdateInfo BUI(PreViewCFG, PostViewCFG);
// Recalculate the DominatorTree when the number of updates
// exceeds a threshold, which usually makes direct updating slower than
// recalculation. We select this threshold proportional to the
@@ -1208,21 +1185,21 @@
// Make unittests of the incremental algorithm work
if (DT.DomTreeNodes.size() <= 100) {
- if (NumLegalized > DT.DomTreeNodes.size())
+ if (BUI.NumLegalized > DT.DomTreeNodes.size())
CalculateFromScratch(DT, &BUI);
- } else if (NumLegalized > DT.DomTreeNodes.size() / 40)
+ } else if (BUI.NumLegalized > DT.DomTreeNodes.size() / 40)
CalculateFromScratch(DT, &BUI);
// If the DominatorTree was recalculated at some point, stop the batch
// updates. Full recalculations ignore batch updates and look at the actual
// CFG.
- for (size_t i = 0; i < NumLegalized && !BUI.IsRecalculated; ++i)
+ for (size_t i = 0; i < BUI.NumLegalized && !BUI.IsRecalculated; ++i)
ApplyNextUpdate(DT, BUI);
}
static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI) {
- assert(!BUI.Updates.empty() && "No updates to apply!");
- UpdateT CurrentUpdate = BUI.Updates.pop_back_val();
+ // Popping the next update, will move the PreViewCFG to the next snapshot.
+ UpdateT CurrentUpdate = BUI.PreViewCFG.popUpdateForIncrementalUpdates();
#if 0
// FIXME: The LLVM_DEBUG macro only plays well with a modular
// build of LLVM when the header is marked as textual, but doing
@@ -1231,21 +1208,6 @@
LLVM_DEBUG(CurrentUpdate.dump(); dbgs() << "\n");
#endif
- // Move to the next snapshot of the CFG by removing the reverse-applied
- // current update. Since updates are performed in the same order they are
- // legalized it's sufficient to pop the last item here.
- auto &FS = BUI.FutureSuccessors[CurrentUpdate.getFrom()];
- assert(FS.back().getPointer() == CurrentUpdate.getTo() &&
- FS.back().getInt() == CurrentUpdate.getKind());
- FS.pop_back();
- if (FS.empty()) BUI.FutureSuccessors.erase(CurrentUpdate.getFrom());
-
- auto &FP = BUI.FuturePredecessors[CurrentUpdate.getTo()];
- assert(FP.back().getPointer() == CurrentUpdate.getFrom() &&
- FP.back().getInt() == CurrentUpdate.getKind());
- FP.pop_back();
- if (FP.empty()) BUI.FuturePredecessors.erase(CurrentUpdate.getTo());
-
if (CurrentUpdate.getKind() == UpdateKind::Insert)
InsertEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());
else
@@ -1372,7 +1334,7 @@
if (!DT.DFSInfoValid || !DT.Parent)
return true;
- const NodePtr RootBB = IsPostDom ? nullptr : DT.getRoots()[0];
+ const NodePtr RootBB = IsPostDom ? nullptr : *DT.root_begin();
const TreeNodePtr Root = DT.getNode(RootBB);
auto PrintNodeAndDFSNums = [](const TreeNodePtr TN) {
@@ -1396,7 +1358,7 @@
const TreeNodePtr Node = NodeToTN.second.get();
// Handle tree leaves.
- if (Node->getChildren().empty()) {
+ if (Node->isLeaf()) {
if (Node->getDFSNumIn() + 1 != Node->getDFSNumOut()) {
errs() << "Tree leaf should have DFSOut = DFSIn + 1:\n\t";
PrintNodeAndDFSNums(Node);
@@ -1493,9 +1455,9 @@
// LEFT, and thus, LEFT is really an ancestor (in the dominator tree) of
// RIGHT, not a sibling.
- // It is possible to verify the parent and sibling properties in
- // linear time, but the algorithms are complex. Instead, we do it in a
- // straightforward N^2 and N^3 way below, using direct path reachability.
+ // It is possible to verify the parent and sibling properties in linear time,
+ // but the algorithms are complex. Instead, we do it in a straightforward
+ // N^2 and N^3 way below, using direct path reachability.
// Checks if the tree has the parent property: if for all edges from V to W in
// the input graph, such that V is reachable, the parent of W in the tree is
@@ -1508,7 +1470,8 @@
for (auto &NodeToTN : DT.DomTreeNodes) {
const TreeNodePtr TN = NodeToTN.second.get();
const NodePtr BB = TN->getBlock();
- if (!BB || TN->getChildren().empty()) continue;
+ if (!BB || TN->isLeaf())
+ continue;
LLVM_DEBUG(dbgs() << "Verifying parent property of node "
<< BlockNamePrinter(TN) << "\n");
@@ -1517,7 +1480,7 @@
return From != BB && To != BB;
});
- for (TreeNodePtr Child : TN->getChildren())
+ for (TreeNodePtr Child : TN->children())
if (NodeToInfo.count(Child->getBlock()) != 0) {
errs() << "Child " << BlockNamePrinter(Child)
<< " reachable after its parent " << BlockNamePrinter(BB)
@@ -1541,17 +1504,17 @@
for (auto &NodeToTN : DT.DomTreeNodes) {
const TreeNodePtr TN = NodeToTN.second.get();
const NodePtr BB = TN->getBlock();
- if (!BB || TN->getChildren().empty()) continue;
+ if (!BB || TN->isLeaf())
+ continue;
- const auto &Siblings = TN->getChildren();
- for (const TreeNodePtr N : Siblings) {
+ for (const TreeNodePtr N : TN->children()) {
clear();
NodePtr BBN = N->getBlock();
doFullDFSWalk(DT, [BBN](NodePtr From, NodePtr To) {
return From != BBN && To != BBN;
});
- for (const TreeNodePtr S : Siblings) {
+ for (const TreeNodePtr S : TN->children()) {
if (S == N) continue;
if (NodeToInfo.count(S->getBlock()) == 0) {
@@ -1571,7 +1534,7 @@
// Check if the given tree is the same as a freshly computed one for the same
// Parent.
- // Running time: O(N^2), but faster in practise (same as tree construction).
+ // Running time: O(N^2), but faster in practice (same as tree construction).
//
// Note that this does not check if that the tree construction algorithm is
// correct and should be only used for fast (but possibly unsound)
@@ -1603,19 +1566,11 @@
template <typename DomTreeT>
void CalculateWithUpdates(DomTreeT &DT,
ArrayRef<typename DomTreeT::UpdateType> Updates) {
- // TODO: Move BUI creation in common method, reuse in ApplyUpdates.
- typename SemiNCAInfo<DomTreeT>::BatchUpdateInfo BUI;
- LLVM_DEBUG(dbgs() << "Legalizing " << BUI.Updates.size() << " updates\n");
- cfg::LegalizeUpdates<typename DomTreeT::NodePtr>(Updates, BUI.Updates,
- DomTreeT::IsPostDominator);
- const size_t NumLegalized = BUI.Updates.size();
- BUI.FutureSuccessors.reserve(NumLegalized);
- BUI.FuturePredecessors.reserve(NumLegalized);
- for (auto &U : BUI.Updates) {
- BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()});
- BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()});
- }
-
+ // FIXME: Updated to use the PreViewCFG and behave the same as until now.
+ // This behavior is however incorrect; this actually needs the PostViewCFG.
+ GraphDiff<typename DomTreeT::NodePtr, DomTreeT::IsPostDominator> PreViewCFG(
+ Updates, /*ReverseApplyUpdates=*/true);
+ typename SemiNCAInfo<DomTreeT>::BatchUpdateInfo BUI(PreViewCFG);
SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, &BUI);
}
@@ -1635,8 +1590,11 @@
template <class DomTreeT>
void ApplyUpdates(DomTreeT &DT,
- ArrayRef<typename DomTreeT::UpdateType> Updates) {
- SemiNCAInfo<DomTreeT>::ApplyUpdates(DT, Updates);
+ GraphDiff<typename DomTreeT::NodePtr,
+ DomTreeT::IsPostDominator> &PreViewCFG,
+ GraphDiff<typename DomTreeT::NodePtr,
+ DomTreeT::IsPostDominator> *PostViewCFG) {
+ SemiNCAInfo<DomTreeT>::ApplyUpdates(DT, PreViewCFG, PostViewCFG);
}
template <class DomTreeT>
@@ -1648,12 +1606,12 @@
if (!SNCA.IsSameAsFreshTree(DT))
return false;
- // Common checks to verify the properties of the tree. O(N log N) at worst
+ // Common checks to verify the properties of the tree. O(N log N) at worst.
if (!SNCA.verifyRoots(DT) || !SNCA.verifyReachability(DT) ||
!SNCA.VerifyLevels(DT) || !SNCA.VerifyDFSNumbers(DT))
return false;
- // Extra checks depending on VerificationLevel. Up to O(N^3)
+ // Extra checks depending on VerificationLevel. Up to O(N^3).
if (VL == DomTreeT::VerificationLevel::Basic ||
VL == DomTreeT::VerificationLevel::Full)
if (!SNCA.verifyParentProperty(DT))
diff --git a/linux-x64/clang/include/llvm/Support/GenericIteratedDominanceFrontier.h b/linux-x64/clang/include/llvm/Support/GenericIteratedDominanceFrontier.h
index fcd2133..a8fca70 100644
--- a/linux-x64/clang/include/llvm/Support/GenericIteratedDominanceFrontier.h
+++ b/linux-x64/clang/include/llvm/Support/GenericIteratedDominanceFrontier.h
@@ -57,7 +57,7 @@
template <class NodeTy, bool IsPostDom> class IDFCalculatorBase {
public:
using OrderedNodeTy =
- typename std::conditional<IsPostDom, Inverse<NodeTy *>, NodeTy *>::type;
+ std::conditional_t<IsPostDom, Inverse<NodeTy *>, NodeTy *>;
using ChildrenGetterTy =
IDFCalculatorDetail::ChildrenGetterTy<NodeTy, IsPostDom>;
@@ -117,8 +117,7 @@
template <class NodeTy, bool IsPostDom>
typename ChildrenGetterTy<NodeTy, IsPostDom>::ChildrenTy
-ChildrenGetterTy<NodeTy, IsPostDom>::get(
- const ChildrenGetterTy<NodeTy, IsPostDom>::NodeRef &N) {
+ChildrenGetterTy<NodeTy, IsPostDom>::get(const NodeRef &N) {
using OrderedNodeTy =
typename IDFCalculatorBase<NodeTy, IsPostDom>::OrderedNodeTy;
@@ -130,7 +129,7 @@
template <class NodeTy, bool IsPostDom>
void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
- SmallVectorImpl<NodeTy *> &PHIBlocks) {
+ SmallVectorImpl<NodeTy *> &IDFBlocks) {
// Use a priority queue keyed on dominator tree level so that inserted nodes
// are handled from the bottom of the dominator tree upwards. We also augment
// the level with a DFS number to ensure that the blocks are ordered in a
@@ -145,15 +144,16 @@
DT.updateDFSNumbers();
- for (NodeTy *BB : *DefBlocks) {
- if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB))
- PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
- }
-
SmallVector<DomTreeNodeBase<NodeTy> *, 32> Worklist;
SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedPQ;
SmallPtrSet<DomTreeNodeBase<NodeTy> *, 32> VisitedWorklist;
+ for (NodeTy *BB : *DefBlocks)
+ if (DomTreeNodeBase<NodeTy> *Node = DT.getNode(BB)) {
+ PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
+ VisitedWorklist.insert(Node);
+ }
+
while (!PQ.empty()) {
DomTreeNodePair RootPair = PQ.top();
PQ.pop();
@@ -165,9 +165,8 @@
// most Root's level are added to the iterated dominance frontier of the
// definition set.
- Worklist.clear();
+ assert(Worklist.empty());
Worklist.push_back(Root);
- VisitedWorklist.insert(Root);
while (!Worklist.empty()) {
DomTreeNodeBase<NodeTy> *Node = Worklist.pop_back_val();
@@ -188,7 +187,7 @@
if (useLiveIn && !LiveInBlocks->count(SuccBB))
return;
- PHIBlocks.emplace_back(SuccBB);
+ IDFBlocks.emplace_back(SuccBB);
if (!DefBlocks->count(SuccBB))
PQ.push(std::make_pair(
SuccNode, std::make_pair(SuccLevel, SuccNode->getDFSNumIn())));
diff --git a/linux-x64/clang/include/llvm/Support/GlobPattern.h b/linux-x64/clang/include/llvm/Support/GlobPattern.h
index 66a4cd9..b79de6f 100644
--- a/linux-x64/clang/include/llvm/Support/GlobPattern.h
+++ b/linux-x64/clang/include/llvm/Support/GlobPattern.h
@@ -16,21 +16,31 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#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;
+class StringRef;
class GlobPattern {
public:
static Expected<GlobPattern> create(StringRef Pat);
bool match(StringRef S) const;
+ // Returns true for glob pattern "*". Can be used to avoid expensive
+ // preparation/acquisition of the input for match().
+ bool isTrivialMatchAll() const {
+ if (Prefix && Prefix->empty()) {
+ assert(!Suffix);
+ return true;
+ }
+ return false;
+ }
+
private:
bool matchOne(ArrayRef<BitVector> Pat, StringRef S) const;
diff --git a/linux-x64/clang/include/llvm/Support/GraphWriter.h b/linux-x64/clang/include/llvm/Support/GraphWriter.h
index 466a044..1f60fbc 100644
--- a/linux-x64/clang/include/llvm/Support/GraphWriter.h
+++ b/linux-x64/clang/include/llvm/Support/GraphWriter.h
@@ -126,7 +126,7 @@
}
void writeHeader(const std::string &Title) {
- std::string GraphName = DTraits.getGraphName(G);
+ std::string GraphName(DTraits.getGraphName(G));
if (!Title.empty())
O << "digraph \"" << DOT::EscapeString(Title) << "\" {\n";
@@ -158,9 +158,7 @@
writeNode(Node);
}
- bool isNodeHidden(NodeRef Node) {
- return DTraits.isNodeHidden(Node);
- }
+ bool isNodeHidden(NodeRef Node) { return DTraits.isNodeHidden(Node, G); }
void writeNode(NodeRef Node) {
std::string NodeAttributes = DTraits.getNodeAttributes(Node, G);
@@ -228,10 +226,10 @@
child_iterator EI = GTraits::child_begin(Node);
child_iterator EE = GTraits::child_end(Node);
for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i)
- if (!DTraits.isNodeHidden(*EI))
+ if (!DTraits.isNodeHidden(*EI, G))
writeEdge(Node, i, EI);
for (; EI != EE; ++EI)
- if (!DTraits.isNodeHidden(*EI))
+ if (!DTraits.isNodeHidden(*EI, G))
writeEdge(Node, 64, EI);
}
@@ -330,11 +328,8 @@
const Twine &Title = "",
std::string Filename = "") {
int FD;
- // Windows can't always handle long paths, so limit the length of the name.
- std::string N = Name.str();
- N = N.substr(0, std::min<std::size_t>(N.size(), 140));
if (Filename.empty()) {
- Filename = createGraphFilename(N, FD);
+ Filename = createGraphFilename(Name.str(), FD);
} else {
std::error_code EC = sys::fs::openFileForWrite(Filename, FD);
@@ -344,6 +339,8 @@
} else if (EC) {
errs() << "error writing into file" << "\n";
return "";
+ } else {
+ errs() << "writing to the newly created file " << Filename << "\n";
}
}
raw_fd_ostream O(FD, /*shouldClose=*/ true);
@@ -359,6 +356,17 @@
return Filename;
}
+/// DumpDotGraph - Just dump a dot graph to the user-provided file name.
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+template <typename GraphType>
+LLVM_DUMP_METHOD void
+dumpDotGraphToFile(const GraphType &G, const Twine &FileName,
+ const Twine &Title, bool ShortNames = false,
+ const Twine &Name = "") {
+ llvm::WriteGraph(G, Name, ShortNames, Title, FileName.str());
+}
+#endif
+
/// ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file,
/// then cleanup. For use from the debugger.
///
diff --git a/linux-x64/clang/include/llvm/Support/Host.h b/linux-x64/clang/include/llvm/Support/Host.h
index b37cc51..d4ef389 100644
--- a/linux-x64/clang/include/llvm/Support/Host.h
+++ b/linux-x64/clang/include/llvm/Support/Host.h
@@ -13,41 +13,15 @@
#ifndef LLVM_SUPPORT_HOST_H
#define LLVM_SUPPORT_HOST_H
-#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 {
+class MallocAllocator;
+class StringRef;
+template <typename ValueTy, typename AllocatorTy> class StringMap;
+
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.
///
@@ -78,7 +52,7 @@
/// all valid LLVM feature names.
///
/// \return - True on success.
- bool getHostCPUFeatures(StringMap<bool> &Features);
+ bool getHostCPUFeatures(StringMap<bool, MallocAllocator> &Features);
/// Get the number of physical cores (as opposed to logical cores returned
/// from thread::hardware_concurrency(), which includes hyperthreads).
diff --git a/linux-x64/clang/include/llvm/Support/InitLLVM.h b/linux-x64/clang/include/llvm/Support/InitLLVM.h
index 57a0ebc..879dc15 100644
--- a/linux-x64/clang/include/llvm/Support/InitLLVM.h
+++ b/linux-x64/clang/include/llvm/Support/InitLLVM.h
@@ -9,6 +9,7 @@
#ifndef LLVM_SUPPORT_LLVM_H
#define LLVM_SUPPORT_LLVM_H
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -17,9 +18,13 @@
// the following one-time initializations:
//
// 1. Setting up a signal handler so that pretty stack trace is printed out
-// if a process crashes.
+// if a process crashes. A signal handler that exits when a failed write to
+// a pipe occurs may optionally be installed: this is on-by-default.
//
-// 2. If running on Windows, obtain command line arguments using a
+// 2. Set up the global new-handler which is called when a memory allocation
+// attempt fails.
+//
+// 3. If running on Windows, obtain command line arguments using a
// multibyte character-aware API and convert arguments into UTF-8
// encoding, so that you can assume that command line arguments are
// always encoded in UTF-8 on any platform.
@@ -29,16 +34,18 @@
namespace llvm {
class InitLLVM {
public:
- InitLLVM(int &Argc, const char **&Argv);
- InitLLVM(int &Argc, char **&Argv)
- : InitLLVM(Argc, const_cast<const char **&>(Argv)) {}
+ InitLLVM(int &Argc, const char **&Argv,
+ bool InstallPipeSignalExitHandler = true);
+ InitLLVM(int &Argc, char **&Argv, bool InstallPipeSignalExitHandler = true)
+ : InitLLVM(Argc, const_cast<const char **&>(Argv),
+ InstallPipeSignalExitHandler) {}
~InitLLVM();
private:
BumpPtrAllocator Alloc;
SmallVector<const char *, 0> Args;
- PrettyStackTraceProgram StackPrinter;
+ Optional<PrettyStackTraceProgram> StackPrinter;
};
} // namespace llvm
diff --git a/linux-x64/clang/include/llvm/Support/InstructionCost.h b/linux-x64/clang/include/llvm/Support/InstructionCost.h
new file mode 100644
index 0000000..725f849
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/InstructionCost.h
@@ -0,0 +1,237 @@
+//===- InstructionCost.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
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file defines an InstructionCost class that is used when calculating
+/// the cost of an instruction, or a group of instructions. In addition to a
+/// numeric value representing the cost the class also contains a state that
+/// can be used to encode particular properties, i.e. a cost being invalid or
+/// unknown.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_INSTRUCTIONCOST_H
+#define LLVM_SUPPORT_INSTRUCTIONCOST_H
+
+#include "llvm/ADT/Optional.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class InstructionCost {
+public:
+ using CostType = int;
+
+ /// These states can currently be used to indicate whether a cost is valid or
+ /// invalid. Examples of an invalid cost might be where the cost is
+ /// prohibitively expensive and the user wants to prevent certain
+ /// optimizations being performed. Or perhaps the cost is simply unknown
+ /// because the operation makes no sense in certain circumstances. These
+ /// states can be expanded in future to support other cases if necessary.
+ enum CostState { Valid, Invalid };
+
+private:
+ CostType Value;
+ CostState State;
+
+ void propagateState(const InstructionCost &RHS) {
+ if (RHS.State == Invalid)
+ State = Invalid;
+ }
+
+public:
+ InstructionCost() = default;
+
+ InstructionCost(CostType Val) : Value(Val), State(Valid) {}
+
+ static InstructionCost getInvalid(CostType Val = 0) {
+ InstructionCost Tmp(Val);
+ Tmp.setInvalid();
+ return Tmp;
+ }
+
+ bool isValid() const { return State == Valid; }
+ void setValid() { State = Valid; }
+ void setInvalid() { State = Invalid; }
+ CostState getState() const { return State; }
+
+ /// This function is intended to be used as sparingly as possible, since the
+ /// class provides the full range of operator support required for arithmetic
+ /// and comparisons.
+ Optional<CostType> getValue() const {
+ if (isValid())
+ return Value;
+ return None;
+ }
+
+ /// For all of the arithmetic operators provided here any invalid state is
+ /// perpetuated and cannot be removed. Once a cost becomes invalid it stays
+ /// invalid, and it also inherits any invalid state from the RHS. Regardless
+ /// of the state, arithmetic and comparisons work on the actual values in the
+ /// same way as they would on a basic type, such as integer.
+
+ InstructionCost &operator+=(const InstructionCost &RHS) {
+ propagateState(RHS);
+ Value += RHS.Value;
+ return *this;
+ }
+
+ InstructionCost &operator+=(const CostType RHS) {
+ InstructionCost RHS2(RHS);
+ *this += RHS2;
+ return *this;
+ }
+
+ InstructionCost &operator-=(const InstructionCost &RHS) {
+ propagateState(RHS);
+ Value -= RHS.Value;
+ return *this;
+ }
+
+ InstructionCost &operator-=(const CostType RHS) {
+ InstructionCost RHS2(RHS);
+ *this -= RHS2;
+ return *this;
+ }
+
+ InstructionCost &operator*=(const InstructionCost &RHS) {
+ propagateState(RHS);
+ Value *= RHS.Value;
+ return *this;
+ }
+
+ InstructionCost &operator*=(const CostType RHS) {
+ InstructionCost RHS2(RHS);
+ *this *= RHS2;
+ return *this;
+ }
+
+ InstructionCost &operator/=(const InstructionCost &RHS) {
+ propagateState(RHS);
+ Value /= RHS.Value;
+ return *this;
+ }
+
+ InstructionCost &operator/=(const CostType RHS) {
+ InstructionCost RHS2(RHS);
+ *this /= RHS2;
+ return *this;
+ }
+
+ InstructionCost &operator++() {
+ *this += 1;
+ return *this;
+ }
+
+ InstructionCost operator++(int) {
+ InstructionCost Copy = *this;
+ ++*this;
+ return Copy;
+ }
+
+ InstructionCost &operator--() {
+ *this -= 1;
+ return *this;
+ }
+
+ InstructionCost operator--(int) {
+ InstructionCost Copy = *this;
+ --*this;
+ return Copy;
+ }
+
+ bool operator==(const InstructionCost &RHS) const {
+ return State == RHS.State && Value == RHS.Value;
+ }
+
+ bool operator!=(const InstructionCost &RHS) const { return !(*this == RHS); }
+
+ bool operator==(const CostType RHS) const {
+ return State == Valid && Value == RHS;
+ }
+
+ bool operator!=(const CostType RHS) const { return !(*this == RHS); }
+
+ /// For the comparison operators we have chosen to use total ordering with
+ /// the following rules:
+ /// 1. If either of the states != Valid then a lexicographical order is
+ /// applied based upon the state.
+ /// 2. If both states are valid then order based upon value.
+ /// This avoids having to add asserts the comparison operators that the states
+ /// are valid and users can test for validity of the cost explicitly.
+ bool operator<(const InstructionCost &RHS) const {
+ if (State != Valid || RHS.State != Valid)
+ return State < RHS.State;
+ return Value < RHS.Value;
+ }
+
+ bool operator>(const InstructionCost &RHS) const { return RHS < *this; }
+
+ bool operator<=(const InstructionCost &RHS) const { return !(RHS < *this); }
+
+ bool operator>=(const InstructionCost &RHS) const { return !(*this < RHS); }
+
+ bool operator<(const CostType RHS) const {
+ InstructionCost RHS2(RHS);
+ return *this < RHS2;
+ }
+
+ bool operator>(const CostType RHS) const {
+ InstructionCost RHS2(RHS);
+ return *this > RHS2;
+ }
+
+ bool operator<=(const CostType RHS) const {
+ InstructionCost RHS2(RHS);
+ return *this <= RHS2;
+ }
+
+ bool operator>=(const CostType RHS) const {
+ InstructionCost RHS2(RHS);
+ return *this >= RHS2;
+ }
+
+ void print(raw_ostream &OS) const;
+};
+
+inline InstructionCost operator+(const InstructionCost &LHS,
+ const InstructionCost &RHS) {
+ InstructionCost LHS2(LHS);
+ LHS2 += RHS;
+ return LHS2;
+}
+
+inline InstructionCost operator-(const InstructionCost &LHS,
+ const InstructionCost &RHS) {
+ InstructionCost LHS2(LHS);
+ LHS2 -= RHS;
+ return LHS2;
+}
+
+inline InstructionCost operator*(const InstructionCost &LHS,
+ const InstructionCost &RHS) {
+ InstructionCost LHS2(LHS);
+ LHS2 *= RHS;
+ return LHS2;
+}
+
+inline InstructionCost operator/(const InstructionCost &LHS,
+ const InstructionCost &RHS) {
+ InstructionCost LHS2(LHS);
+ LHS2 /= RHS;
+ return LHS2;
+}
+
+inline raw_ostream &operator<<(raw_ostream &OS, const InstructionCost &V) {
+ V.print(OS);
+ return OS;
+}
+
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/ItaniumManglingCanonicalizer.h b/linux-x64/clang/include/llvm/Support/ItaniumManglingCanonicalizer.h
index 6920000..8e1b3d6 100644
--- a/linux-x64/clang/include/llvm/Support/ItaniumManglingCanonicalizer.h
+++ b/linux-x64/clang/include/llvm/Support/ItaniumManglingCanonicalizer.h
@@ -14,11 +14,13 @@
#ifndef LLVM_SUPPORT_ITANIUMMANGLINGCANONICALIZER_H
#define LLVM_SUPPORT_ITANIUMMANGLINGCANONICALIZER_H
-#include "llvm/ADT/StringRef.h"
-
#include <cstddef>
+#include <cstdint>
namespace llvm {
+
+class StringRef;
+
/// Canonicalizer for mangled names.
///
/// This class allows specifying a list of "equivalent" manglings. For example,
diff --git a/linux-x64/clang/include/llvm/Support/JSON.h b/linux-x64/clang/include/llvm/Support/JSON.h
index 0ca4109..c753cee 100644
--- a/linux-x64/clang/include/llvm/Support/JSON.h
+++ b/linux-x64/clang/include/llvm/Support/JSON.h
@@ -122,6 +122,8 @@
std::pair<iterator, bool> try_emplace(ObjectKey &&K, Ts &&... Args) {
return M.try_emplace(std::move(K), std::forward<Ts>(Args)...);
}
+ bool erase(StringRef K);
+ void erase(iterator I) { M.erase(I); }
iterator find(StringRef K) { return M.find_as(K); }
const_iterator find(StringRef K) const { return M.find_as(K); }
@@ -251,7 +253,14 @@
/// === Converting JSON values to C++ types ===
///
/// The convention is to have a deserializer function findable via ADL:
-/// fromJSON(const json::Value&, T&)->bool
+/// fromJSON(const json::Value&, T&, Path) -> bool
+///
+/// The return value indicates overall success, and Path is used for precise
+/// error reporting. (The Path::Root passed in at the top level fromJSON call
+/// captures any nested error and can render it in context).
+/// If conversion fails, fromJSON calls Path::report() and immediately returns.
+/// This ensures that the first fatal error survives.
+///
/// Deserializers are provided for:
/// - bool
/// - int and int64_t
@@ -327,32 +336,28 @@
Value(std::nullptr_t) : Type(T_Null) {}
// Boolean (disallow implicit conversions).
// (The last template parameter is a dummy to keep templates distinct.)
- template <
- typename T,
- typename = typename std::enable_if<std::is_same<T, bool>::value>::type,
- bool = false>
+ template <typename T,
+ typename = std::enable_if_t<std::is_same<T, bool>::value>,
+ bool = false>
Value(T B) : Type(T_Boolean) {
create<bool>(B);
}
// Integers (except boolean). Must be non-narrowing convertible to int64_t.
- template <
- typename T,
- typename = typename std::enable_if<std::is_integral<T>::value>::type,
- typename = typename std::enable_if<!std::is_same<T, bool>::value>::type>
+ template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>,
+ typename = std::enable_if_t<!std::is_same<T, bool>::value>>
Value(T I) : Type(T_Integer) {
create<int64_t>(int64_t{I});
}
// Floating point. Must be non-narrowing convertible to double.
template <typename T,
- typename =
- typename std::enable_if<std::is_floating_point<T>::value>::type,
+ typename = std::enable_if_t<std::is_floating_point<T>::value>,
double * = nullptr>
Value(T D) : Type(T_Double) {
create<double>(double{D});
}
// Serializable types: with a toJSON(const T&)->Value function, found by ADL.
template <typename T,
- typename = typename std::enable_if<std::is_same<
+ typename = std::enable_if_t<std::is_same<
Value, decltype(toJSON(*(const T *)nullptr))>::value>,
Value * = nullptr>
Value(const T &V) : Value(toJSON(V)) {}
@@ -451,12 +456,12 @@
friend class Object;
template <typename T, typename... U> void create(U &&... V) {
- new (reinterpret_cast<T *>(Union.buffer)) T(std::forward<U>(V)...);
+ new (reinterpret_cast<T *>(&Union)) T(std::forward<U>(V)...);
}
template <typename T> T &as() const {
// Using this two-step static_cast via void * instead of reinterpret_cast
// silences a -Wstrict-aliasing false positive from GCC6 and earlier.
- void *Storage = static_cast<void *>(Union.buffer);
+ void *Storage = static_cast<void *>(&Union);
return *static_cast<T *>(Storage);
}
@@ -555,75 +560,173 @@
inline std::pair<Object::iterator, bool> Object::insert(KV E) {
return try_emplace(std::move(E.K), std::move(E.V));
}
+inline bool Object::erase(StringRef K) {
+ return M.erase(ObjectKey(K));
+}
+
+/// A "cursor" marking a position within a Value.
+/// The Value is a tree, and this is the path from the root to the current node.
+/// This is used to associate errors with particular subobjects.
+class Path {
+public:
+ class Root;
+
+ /// Records that the value at the current path is invalid.
+ /// Message is e.g. "expected number" and becomes part of the final error.
+ /// This overwrites any previously written error message in the root.
+ void report(llvm::StringLiteral Message);
+
+ /// The root may be treated as a Path.
+ Path(Root &R) : Parent(nullptr), Seg(&R) {}
+ /// Derives a path for an array element: this[Index]
+ Path index(unsigned Index) const { return Path(this, Segment(Index)); }
+ /// Derives a path for an object field: this.Field
+ Path field(StringRef Field) const { return Path(this, Segment(Field)); }
+
+private:
+ /// One element in a JSON path: an object field (.foo) or array index [27].
+ /// Exception: the root Path encodes a pointer to the Path::Root.
+ class Segment {
+ uintptr_t Pointer;
+ unsigned Offset;
+
+ public:
+ Segment() = default;
+ Segment(Root *R) : Pointer(reinterpret_cast<uintptr_t>(R)) {}
+ Segment(llvm::StringRef Field)
+ : Pointer(reinterpret_cast<uintptr_t>(Field.data())),
+ Offset(static_cast<unsigned>(Field.size())) {}
+ Segment(unsigned Index) : Pointer(0), Offset(Index) {}
+
+ bool isField() const { return Pointer != 0; }
+ StringRef field() const {
+ return StringRef(reinterpret_cast<const char *>(Pointer), Offset);
+ }
+ unsigned index() const { return Offset; }
+ Root *root() const { return reinterpret_cast<Root *>(Pointer); }
+ };
+
+ const Path *Parent;
+ Segment Seg;
+
+ Path(const Path *Parent, Segment S) : Parent(Parent), Seg(S) {}
+};
+
+/// The root is the trivial Path to the root value.
+/// It also stores the latest reported error and the path where it occurred.
+class Path::Root {
+ llvm::StringRef Name;
+ llvm::StringLiteral ErrorMessage;
+ std::vector<Path::Segment> ErrorPath; // Only valid in error state. Reversed.
+
+ friend void Path::report(llvm::StringLiteral Message);
+
+public:
+ Root(llvm::StringRef Name = "") : Name(Name), ErrorMessage("") {}
+ // No copy/move allowed as there are incoming pointers.
+ Root(Root &&) = delete;
+ Root &operator=(Root &&) = delete;
+ Root(const Root &) = delete;
+ Root &operator=(const Root &) = delete;
+
+ /// Returns the last error reported, or else a generic error.
+ Error getError() const;
+ /// Print the root value with the error shown inline as a comment.
+ /// Unrelated parts of the value are elided for brevity, e.g.
+ /// {
+ /// "id": 42,
+ /// "name": /* expected string */ null,
+ /// "properties": { ... }
+ /// }
+ void printErrorContext(const Value &, llvm::raw_ostream &) const;
+};
// Standard deserializers are provided for primitive types.
// See comments on Value.
-inline bool fromJSON(const Value &E, std::string &Out) {
+inline bool fromJSON(const Value &E, std::string &Out, Path P) {
if (auto S = E.getAsString()) {
- Out = *S;
+ Out = std::string(*S);
return true;
}
+ P.report("expected string");
return false;
}
-inline bool fromJSON(const Value &E, int &Out) {
+inline bool fromJSON(const Value &E, int &Out, Path P) {
if (auto S = E.getAsInteger()) {
Out = *S;
return true;
}
+ P.report("expected integer");
return false;
}
-inline bool fromJSON(const Value &E, int64_t &Out) {
+inline bool fromJSON(const Value &E, int64_t &Out, Path P) {
if (auto S = E.getAsInteger()) {
Out = *S;
return true;
}
+ P.report("expected integer");
return false;
}
-inline bool fromJSON(const Value &E, double &Out) {
+inline bool fromJSON(const Value &E, double &Out, Path P) {
if (auto S = E.getAsNumber()) {
Out = *S;
return true;
}
+ P.report("expected number");
return false;
}
-inline bool fromJSON(const Value &E, bool &Out) {
+inline bool fromJSON(const Value &E, bool &Out, Path P) {
if (auto S = E.getAsBoolean()) {
Out = *S;
return true;
}
+ P.report("expected boolean");
return false;
}
-template <typename T> bool fromJSON(const Value &E, llvm::Optional<T> &Out) {
+inline bool fromJSON(const Value &E, std::nullptr_t &Out, Path P) {
+ if (auto S = E.getAsNull()) {
+ Out = *S;
+ return true;
+ }
+ P.report("expected null");
+ return false;
+}
+template <typename T>
+bool fromJSON(const Value &E, llvm::Optional<T> &Out, Path P) {
if (E.getAsNull()) {
Out = llvm::None;
return true;
}
T Result;
- if (!fromJSON(E, Result))
+ if (!fromJSON(E, Result, P))
return false;
Out = std::move(Result);
return true;
}
-template <typename T> bool fromJSON(const Value &E, std::vector<T> &Out) {
+template <typename T>
+bool fromJSON(const Value &E, std::vector<T> &Out, Path P) {
if (auto *A = E.getAsArray()) {
Out.clear();
Out.resize(A->size());
for (size_t I = 0; I < A->size(); ++I)
- if (!fromJSON((*A)[I], Out[I]))
+ if (!fromJSON((*A)[I], Out[I], P.index(I)))
return false;
return true;
}
+ P.report("expected array");
return false;
}
template <typename T>
-bool fromJSON(const Value &E, std::map<std::string, T> &Out) {
+bool fromJSON(const Value &E, std::map<std::string, T> &Out, Path P) {
if (auto *O = E.getAsObject()) {
Out.clear();
for (const auto &KV : *O)
- if (!fromJSON(KV.second, Out[llvm::StringRef(KV.first)]))
+ if (!fromJSON(KV.second, Out[std::string(llvm::StringRef(KV.first))],
+ P.field(KV.first)))
return false;
return true;
}
+ P.report("expected object");
return false;
}
@@ -636,42 +739,59 @@
///
/// Example:
/// \code
-/// bool fromJSON(const Value &E, MyStruct &R) {
-/// ObjectMapper O(E);
-/// if (!O || !O.map("mandatory_field", R.MandatoryField))
-/// return false;
-/// O.map("optional_field", R.OptionalField);
-/// return true;
+/// bool fromJSON(const Value &E, MyStruct &R, Path P) {
+/// ObjectMapper O(E, P);
+/// // When returning false, error details were already reported.
+/// return O && O.map("mandatory_field", R.MandatoryField) &&
+/// O.mapOptional("optional_field", R.OptionalField);
/// }
/// \endcode
class ObjectMapper {
public:
- ObjectMapper(const Value &E) : O(E.getAsObject()) {}
+ /// If O is not an object, this mapper is invalid and an error is reported.
+ ObjectMapper(const Value &E, Path P) : O(E.getAsObject()), P(P) {
+ if (!O)
+ P.report("expected object");
+ }
/// True if the expression is an object.
/// Must be checked before calling map().
- operator bool() { return O; }
+ operator bool() const { return O; }
- /// Maps a property to a field, if it exists.
- template <typename T> bool map(StringRef Prop, T &Out) {
+ /// Maps a property to a field.
+ /// If the property is missing or invalid, reports an error.
+ template <typename T> bool map(StringLiteral Prop, T &Out) {
assert(*this && "Must check this is an object before calling map()");
if (const Value *E = O->get(Prop))
- return fromJSON(*E, Out);
+ return fromJSON(*E, Out, P.field(Prop));
+ P.field(Prop).report("missing value");
return false;
}
/// Maps a property to a field, if it exists.
+ /// If the property exists and is invalid, reports an error.
/// (Optional requires special handling, because missing keys are OK).
- template <typename T> bool map(StringRef Prop, llvm::Optional<T> &Out) {
+ template <typename T> bool map(StringLiteral Prop, llvm::Optional<T> &Out) {
assert(*this && "Must check this is an object before calling map()");
if (const Value *E = O->get(Prop))
- return fromJSON(*E, Out);
+ return fromJSON(*E, Out, P.field(Prop));
Out = llvm::None;
return true;
}
+ /// Maps a property to a field, if it exists.
+ /// If the property exists and is invalid, reports an error.
+ /// If the property does not exist, Out is unchanged.
+ template <typename T> bool mapOptional(StringLiteral Prop, T &Out) {
+ assert(*this && "Must check this is an object before calling map()");
+ if (const Value *E = O->get(Prop))
+ return fromJSON(*E, Out, P.field(Prop));
+ return true;
+ }
+
private:
const Object *O;
+ Path P;
};
/// Parses the provided JSON source, or returns a ParseError.
@@ -695,9 +815,24 @@
}
};
+/// Version of parse() that converts the parsed value to the type T.
+/// RootName describes the root object and is used in error messages.
+template <typename T>
+Expected<T> parse(const llvm::StringRef &JSON, const char *RootName = "") {
+ auto V = parse(JSON);
+ if (!V)
+ return V.takeError();
+ Path::Root R(RootName);
+ T Result;
+ if (fromJSON(*V, Result, R))
+ return std::move(Result);
+ return R.getError();
+}
+
/// json::OStream allows writing well-formed JSON without materializing
/// all structures as json::Value ahead of time.
/// It's faster, lower-level, and less safe than OS << json::Value.
+/// It also allows emitting more constructs, such as comments.
///
/// Only one "top-level" object can be written to a stream.
/// Simplest usage involves passing lambdas (Blocks) to fill in containers:
@@ -709,7 +844,7 @@
/// J.attribute("timestamp", int64_t(E.Time));
/// J.attributeArray("participants", [&] {
/// for (const Participant &P : E.Participants)
-/// J.string(P.toString());
+/// J.value(P.toString());
/// });
/// });
/// });
@@ -783,6 +918,21 @@
Contents();
objectEnd();
}
+ /// Emit an externally-serialized value.
+ /// The caller must write exactly one valid JSON value to the provided stream.
+ /// No validation or formatting of this value occurs.
+ void rawValue(llvm::function_ref<void(raw_ostream &)> Contents) {
+ rawValueBegin();
+ Contents(OS);
+ rawValueEnd();
+ }
+ void rawValue(llvm::StringRef Contents) {
+ rawValue([&](raw_ostream &OS) { OS << Contents; });
+ }
+ /// Emit a JavaScript comment associated with the next printed value.
+ /// The string must be valid until the next attribute or value is emitted.
+ /// Comments are not part of standard JSON, and many parsers reject them!
+ void comment(llvm::StringRef);
// High level functions to output object attributes.
// Valid only within an object (any number of times).
@@ -809,8 +959,10 @@
void objectEnd();
void attributeBegin(llvm::StringRef Key);
void attributeEnd();
+ raw_ostream &rawValueBegin();
+ void rawValueEnd();
- private:
+private:
void attributeImpl(llvm::StringRef Key, Block Contents) {
attributeBegin(Key);
Contents();
@@ -818,18 +970,21 @@
}
void valueBegin();
+ void flushComment();
void newline();
enum Context {
Singleton, // Top level, or object attribute.
Array,
Object,
+ RawValue, // External code writing a value to OS directly.
};
struct State {
Context Ctx = Singleton;
bool HasValue = false;
};
llvm::SmallVector<State, 16> Stack; // Never empty.
+ llvm::StringRef PendingComment;
llvm::raw_ostream &OS;
unsigned IndentSize;
unsigned Indent = 0;
diff --git a/linux-x64/clang/include/llvm/Support/JamCRC.h b/linux-x64/clang/include/llvm/Support/JamCRC.h
deleted file mode 100644
index b6fc4e7..0000000
--- a/linux-x64/clang/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/linux-x64/clang/include/llvm/Support/KnownBits.h b/linux-x64/clang/include/llvm/Support/KnownBits.h
index 07fd94e..d854aad 100644
--- a/linux-x64/clang/include/llvm/Support/KnownBits.h
+++ b/linux-x64/clang/include/llvm/Support/KnownBits.h
@@ -15,6 +15,7 @@
#define LLVM_SUPPORT_KNOWNBITS_H
#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/Optional.h"
namespace llvm {
@@ -97,6 +98,12 @@
/// Returns true if this value is known to be non-negative.
bool isNonNegative() const { return Zero.isSignBitSet(); }
+ /// Returns true if this value is known to be non-zero.
+ bool isNonZero() const { return !One.isNullValue(); }
+
+ /// Returns true if this value is known to be positive.
+ bool isStrictlyPositive() const { return Zero.isSignBitSet() && !One.isNullValue(); }
+
/// Make this value negative.
void makeNegative() {
One.setSignBit();
@@ -107,41 +114,107 @@
Zero.setSignBit();
}
- /// Truncate the underlying known Zero and One bits. This is equivalent
- /// to truncating the value we're tracking.
+ /// Return the minimal unsigned value possible given these KnownBits.
+ APInt getMinValue() const {
+ // Assume that all bits that aren't known-ones are zeros.
+ return One;
+ }
+
+ /// Return the minimal signed value possible given these KnownBits.
+ APInt getSignedMinValue() const {
+ // Assume that all bits that aren't known-ones are zeros.
+ APInt Min = One;
+ // Sign bit is unknown.
+ if (Zero.isSignBitClear())
+ Min.setSignBit();
+ return Min;
+ }
+
+ /// Return the maximal unsigned value possible given these KnownBits.
+ APInt getMaxValue() const {
+ // Assume that all bits that aren't known-zeros are ones.
+ return ~Zero;
+ }
+
+ /// Return the maximal signed value possible given these KnownBits.
+ APInt getSignedMaxValue() const {
+ // Assume that all bits that aren't known-zeros are ones.
+ APInt Max = ~Zero;
+ // Sign bit is unknown.
+ if (One.isSignBitClear())
+ Max.clearSignBit();
+ return Max;
+ }
+
+ /// Return known bits for a truncation of the value we're tracking.
KnownBits trunc(unsigned BitWidth) const {
return KnownBits(Zero.trunc(BitWidth), One.trunc(BitWidth));
}
- /// Extends the underlying known Zero and One bits.
- /// By setting ExtendedBitsAreKnownZero=true this will be equivalent to
- /// zero extending the value we're tracking.
- /// With ExtendedBitsAreKnownZero=false the extended bits are set to unknown.
- KnownBits zext(unsigned BitWidth, bool ExtendedBitsAreKnownZero) const {
+ /// Return known bits for an "any" extension of the value we're tracking,
+ /// where we don't know anything about the extended bits.
+ KnownBits anyext(unsigned BitWidth) const {
+ return KnownBits(Zero.zext(BitWidth), One.zext(BitWidth));
+ }
+
+ /// Return known bits for a zero extension of the value we're tracking.
+ KnownBits zext(unsigned BitWidth) const {
unsigned OldBitWidth = getBitWidth();
APInt NewZero = Zero.zext(BitWidth);
- if (ExtendedBitsAreKnownZero)
- NewZero.setBitsFrom(OldBitWidth);
+ NewZero.setBitsFrom(OldBitWidth);
return KnownBits(NewZero, One.zext(BitWidth));
}
- /// Sign extends the underlying known Zero and One bits. This is equivalent
- /// to sign extending the value we're tracking.
+ /// Return known bits for a sign extension of the value we're tracking.
KnownBits sext(unsigned BitWidth) const {
return KnownBits(Zero.sext(BitWidth), One.sext(BitWidth));
}
- /// Extends or truncates the underlying known Zero and One bits. When
- /// extending the extended bits can either be set as known zero (if
- /// ExtendedBitsAreKnownZero=true) or as unknown (if
- /// ExtendedBitsAreKnownZero=false).
- KnownBits zextOrTrunc(unsigned BitWidth,
- bool ExtendedBitsAreKnownZero) const {
+ /// Return known bits for an "any" extension or truncation of the value we're
+ /// tracking.
+ KnownBits anyextOrTrunc(unsigned BitWidth) const {
if (BitWidth > getBitWidth())
- return zext(BitWidth, ExtendedBitsAreKnownZero);
- return KnownBits(Zero.zextOrTrunc(BitWidth), One.zextOrTrunc(BitWidth));
+ return anyext(BitWidth);
+ if (BitWidth < getBitWidth())
+ return trunc(BitWidth);
+ return *this;
}
+ /// Return known bits for a zero extension or truncation of the value we're
+ /// tracking.
+ KnownBits zextOrTrunc(unsigned BitWidth) const {
+ if (BitWidth > getBitWidth())
+ return zext(BitWidth);
+ if (BitWidth < getBitWidth())
+ return trunc(BitWidth);
+ return *this;
+ }
+
+ /// Return known bits for a sign extension or truncation of the value we're
+ /// tracking.
+ KnownBits sextOrTrunc(unsigned BitWidth) const {
+ if (BitWidth > getBitWidth())
+ return sext(BitWidth);
+ if (BitWidth < getBitWidth())
+ return trunc(BitWidth);
+ return *this;
+ }
+
+ /// Return known bits for a in-register sign extension of the value we're
+ /// tracking.
+ KnownBits sextInReg(unsigned SrcBitWidth) const;
+
+ /// Return a KnownBits with the extracted bits
+ /// [bitPosition,bitPosition+numBits).
+ KnownBits extractBits(unsigned NumBits, unsigned BitPosition) const {
+ return KnownBits(Zero.extractBits(NumBits, BitPosition),
+ One.extractBits(NumBits, BitPosition));
+ }
+
+ /// Return KnownBits based on this, but updated given that the underlying
+ /// value is known to be greater than or equal to Val.
+ KnownBits makeGE(const APInt &Val) const;
+
/// Returns the minimum number of trailing zero bits.
unsigned countMinTrailingZeros() const {
return Zero.countTrailingOnes();
@@ -202,6 +275,16 @@
return getBitWidth() - Zero.countPopulation();
}
+ /// Create known bits from a known constant.
+ static KnownBits makeConstant(const APInt &C) {
+ return KnownBits(~C, C);
+ }
+
+ /// Compute known bits common to LHS and RHS.
+ static KnownBits commonBits(const KnownBits &LHS, const KnownBits &RHS) {
+ return KnownBits(LHS.Zero & RHS.Zero, LHS.One & RHS.One);
+ }
+
/// Compute known bits resulting from adding LHS, RHS and a 1-bit Carry.
static KnownBits computeForAddCarry(
const KnownBits &LHS, const KnownBits &RHS, const KnownBits &Carry);
@@ -209,8 +292,136 @@
/// Compute known bits resulting from adding LHS and RHS.
static KnownBits computeForAddSub(bool Add, bool NSW, const KnownBits &LHS,
KnownBits RHS);
+
+ /// Compute known bits resulting from multiplying LHS and RHS.
+ static KnownBits computeForMul(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Compute known bits for udiv(LHS, RHS).
+ static KnownBits udiv(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Compute known bits for urem(LHS, RHS).
+ static KnownBits urem(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Compute known bits for srem(LHS, RHS).
+ static KnownBits srem(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Compute known bits for umax(LHS, RHS).
+ static KnownBits umax(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Compute known bits for umin(LHS, RHS).
+ static KnownBits umin(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Compute known bits for smax(LHS, RHS).
+ static KnownBits smax(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Compute known bits for smin(LHS, RHS).
+ static KnownBits smin(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Compute known bits for shl(LHS, RHS).
+ /// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS.
+ static KnownBits shl(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Compute known bits for lshr(LHS, RHS).
+ /// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS.
+ static KnownBits lshr(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Compute known bits for ashr(LHS, RHS).
+ /// NOTE: RHS (shift amount) bitwidth doesn't need to be the same as LHS.
+ static KnownBits ashr(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Determine if these known bits always give the same ICMP_EQ result.
+ static Optional<bool> eq(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Determine if these known bits always give the same ICMP_NE result.
+ static Optional<bool> ne(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Determine if these known bits always give the same ICMP_UGT result.
+ static Optional<bool> ugt(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Determine if these known bits always give the same ICMP_UGE result.
+ static Optional<bool> uge(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Determine if these known bits always give the same ICMP_ULT result.
+ static Optional<bool> ult(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Determine if these known bits always give the same ICMP_ULE result.
+ static Optional<bool> ule(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Determine if these known bits always give the same ICMP_SGT result.
+ static Optional<bool> sgt(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Determine if these known bits always give the same ICMP_SGE result.
+ static Optional<bool> sge(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Determine if these known bits always give the same ICMP_SLT result.
+ static Optional<bool> slt(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Determine if these known bits always give the same ICMP_SLE result.
+ static Optional<bool> sle(const KnownBits &LHS, const KnownBits &RHS);
+
+ /// Insert the bits from a smaller known bits starting at bitPosition.
+ void insertBits(const KnownBits &SubBits, unsigned BitPosition) {
+ Zero.insertBits(SubBits.Zero, BitPosition);
+ One.insertBits(SubBits.One, BitPosition);
+ }
+
+ /// Return a subset of the known bits from [bitPosition,bitPosition+numBits).
+ KnownBits extractBits(unsigned NumBits, unsigned BitPosition) {
+ return KnownBits(Zero.extractBits(NumBits, BitPosition),
+ One.extractBits(NumBits, BitPosition));
+ }
+
+ /// Update known bits based on ANDing with RHS.
+ KnownBits &operator&=(const KnownBits &RHS);
+
+ /// Update known bits based on ORing with RHS.
+ KnownBits &operator|=(const KnownBits &RHS);
+
+ /// Update known bits based on XORing with RHS.
+ KnownBits &operator^=(const KnownBits &RHS);
+
+ /// Compute known bits for the absolute value.
+ KnownBits abs(bool IntMinIsPoison = false) const;
+
+ KnownBits byteSwap() {
+ return KnownBits(Zero.byteSwap(), One.byteSwap());
+ }
+
+ KnownBits reverseBits() {
+ return KnownBits(Zero.reverseBits(), One.reverseBits());
+ }
};
+inline KnownBits operator&(KnownBits LHS, const KnownBits &RHS) {
+ LHS &= RHS;
+ return LHS;
+}
+
+inline KnownBits operator&(const KnownBits &LHS, KnownBits &&RHS) {
+ RHS &= LHS;
+ return std::move(RHS);
+}
+
+inline KnownBits operator|(KnownBits LHS, const KnownBits &RHS) {
+ LHS |= RHS;
+ return LHS;
+}
+
+inline KnownBits operator|(const KnownBits &LHS, KnownBits &&RHS) {
+ RHS |= LHS;
+ return std::move(RHS);
+}
+
+inline KnownBits operator^(KnownBits LHS, const KnownBits &RHS) {
+ LHS ^= RHS;
+ return LHS;
+}
+
+inline KnownBits operator^(const KnownBits &LHS, KnownBits &&RHS) {
+ RHS ^= LHS;
+ return std::move(RHS);
+}
+
} // end namespace llvm
#endif
diff --git a/linux-x64/clang/include/llvm/Support/LEB128.h b/linux-x64/clang/include/llvm/Support/LEB128.h
index a02b83c..8ab3543 100644
--- a/linux-x64/clang/include/llvm/Support/LEB128.h
+++ b/linux-x64/clang/include/llvm/Support/LEB128.h
@@ -134,7 +134,7 @@
if (error)
*error = nullptr;
do {
- if (end && p == end) {
+ if (p == end) {
if (error)
*error = "malformed uleb128, extends past end";
if (n)
@@ -168,7 +168,7 @@
if (error)
*error = nullptr;
do {
- if (end && p == end) {
+ if (p == end) {
if (error)
*error = "malformed sleb128, extends past end";
if (n)
diff --git a/linux-x64/clang/include/llvm/Support/LineIterator.h b/linux-x64/clang/include/llvm/Support/LineIterator.h
index c9f10ca..b391412 100644
--- a/linux-x64/clang/include/llvm/Support/LineIterator.h
+++ b/linux-x64/clang/include/llvm/Support/LineIterator.h
@@ -9,8 +9,10 @@
#ifndef LLVM_SUPPORT_LINEITERATOR_H
#define LLVM_SUPPORT_LINEITERATOR_H
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MemoryBufferRef.h"
#include <iterator>
namespace llvm {
@@ -30,16 +32,20 @@
/// Note that this iterator requires the buffer to be nul terminated.
class line_iterator
: public std::iterator<std::forward_iterator_tag, StringRef> {
- const MemoryBuffer *Buffer;
- char CommentMarker;
- bool SkipBlanks;
+ Optional<MemoryBufferRef> Buffer;
+ char CommentMarker = '\0';
+ bool SkipBlanks = true;
- unsigned LineNumber;
+ unsigned LineNumber = 1;
StringRef CurrentLine;
public:
/// Default construct an "end" iterator.
- line_iterator() : Buffer(nullptr) {}
+ line_iterator() = default;
+
+ /// Construct a new iterator around an unowned memory buffer.
+ explicit line_iterator(const MemoryBufferRef &Buffer, bool SkipBlanks = true,
+ char CommentMarker = '\0');
/// Construct a new iterator around some memory buffer.
explicit line_iterator(const MemoryBuffer &Buffer, bool SkipBlanks = true,
diff --git a/linux-x64/clang/include/llvm/Support/LockFileManager.h b/linux-x64/clang/include/llvm/Support/LockFileManager.h
index 57e4fbd..ab66621 100644
--- a/linux-x64/clang/include/llvm/Support/LockFileManager.h
+++ b/linux-x64/clang/include/llvm/Support/LockFileManager.h
@@ -77,7 +77,9 @@
operator LockFileState() const { return getState(); }
/// For a shared lock, wait until the owner releases the lock.
- WaitForUnlockResult waitForUnlock();
+ /// Total timeout for the file to appear is ~1.5 minutes.
+ /// \param MaxSeconds the maximum total wait time in seconds.
+ WaitForUnlockResult waitForUnlock(const unsigned MaxSeconds = 90);
/// Remove the lock file. This may delete a different lock file than
/// the one previously read if there is a race.
diff --git a/linux-x64/clang/include/llvm/Support/LowLevelTypeImpl.h b/linux-x64/clang/include/llvm/Support/LowLevelTypeImpl.h
index 0e02b6e..c1d516f 100644
--- a/linux-x64/clang/include/llvm/Support/LowLevelTypeImpl.h
+++ b/linux-x64/clang/include/llvm/Support/LowLevelTypeImpl.h
@@ -27,6 +27,7 @@
#define LLVM_SUPPORT_LOWLEVELTYPEIMPL_H
#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/MachineValueType.h"
#include <cassert>
@@ -137,6 +138,28 @@
: LLT::scalar(NewEltSize);
}
+ /// Return a vector or scalar with the same element type and the new number of
+ /// elements.
+ LLT changeNumElements(unsigned NewNumElts) const {
+ return LLT::scalarOrVector(NewNumElts, getScalarType());
+ }
+
+ /// Return a type that is \p Factor times smaller. Reduces the number of
+ /// elements if this is a vector, or the bitwidth for scalar/pointers. Does
+ /// not attempt to handle cases that aren't evenly divisible.
+ LLT divide(int Factor) const {
+ assert(Factor != 1);
+ if (isVector()) {
+ assert(getNumElements() % Factor == 0);
+ return scalarOrVector(getNumElements() / Factor, getElementType());
+ }
+
+ assert(getSizeInBits() % Factor == 0);
+ return scalar(getSizeInBits() / Factor);
+ }
+
+ bool isByteSized() const { return (getSizeInBits() & 7) == 0; }
+
unsigned getScalarSizeInBits() const {
assert(RawData != 0 && "Invalid Type");
if (!IsVector) {
@@ -172,6 +195,13 @@
void print(raw_ostream &OS) const;
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const {
+ print(dbgs());
+ dbgs() << '\n';
+ }
+#endif
+
bool operator==(const LLT &RHS) const {
return IsPointer == RHS.IsPointer && IsVector == RHS.IsVector &&
RHS.RawData == RawData;
diff --git a/linux-x64/clang/include/llvm/Support/MD5.h b/linux-x64/clang/include/llvm/Support/MD5.h
index bb2bdbf..3b2d5b9 100644
--- a/linux-x64/clang/include/llvm/Support/MD5.h
+++ b/linux-x64/clang/include/llvm/Support/MD5.h
@@ -28,7 +28,6 @@
#ifndef LLVM_SUPPORT_MD5_H
#define LLVM_SUPPORT_MD5_H
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Endian.h"
#include <array>
@@ -36,6 +35,7 @@
namespace llvm {
+template <unsigned N> class SmallString;
template <typename T> class ArrayRef;
class MD5 {
diff --git a/linux-x64/clang/include/llvm/Support/MSVCErrorWorkarounds.h b/linux-x64/clang/include/llvm/Support/MSVCErrorWorkarounds.h
index 30e8feb..bf983dc 100644
--- a/linux-x64/clang/include/llvm/Support/MSVCErrorWorkarounds.h
+++ b/linux-x64/clang/include/llvm/Support/MSVCErrorWorkarounds.h
@@ -59,22 +59,19 @@
template <typename OtherT>
MSVCPExpected(
OtherT &&Val,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
- nullptr)
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr)
: Expected<T>(std::move(Val)) {}
template <class OtherT>
MSVCPExpected(
Expected<OtherT> &&Other,
- typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * =
- nullptr)
+ std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr)
: Expected<T>(std::move(Other)) {}
template <class OtherT>
explicit MSVCPExpected(
Expected<OtherT> &&Other,
- typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * =
- nullptr)
+ std::enable_if_t<!std::is_convertible<OtherT, T>::value> * = nullptr)
: Expected<T>(std::move(Other)) {}
};
diff --git a/linux-x64/clang/include/llvm/Support/MachineValueType.h b/linux-x64/clang/include/llvm/Support/MachineValueType.h
index a9b130f..1c600d0 100644
--- a/linux-x64/clang/include/llvm/Support/MachineValueType.h
+++ b/linux-x64/clang/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 {
@@ -46,175 +47,214 @@
FIRST_INTEGER_VALUETYPE = i1,
LAST_INTEGER_VALUETYPE = i128,
- f16 = 8, // This is a 16 bit floating point value
- f32 = 9, // This is a 32 bit floating point value
- f64 = 10, // This is a 64 bit floating point value
- f80 = 11, // This is a 80 bit floating point value
- f128 = 12, // This is a 128 bit floating point value
- ppcf128 = 13, // This is a PPC 128-bit floating point value
+ bf16 = 8, // This is a 16 bit brain floating point value
+ f16 = 9, // This is a 16 bit floating point value
+ f32 = 10, // This is a 32 bit floating point value
+ f64 = 11, // This is a 64 bit floating point value
+ f80 = 12, // This is a 80 bit floating point value
+ f128 = 13, // This is a 128 bit floating point value
+ ppcf128 = 14, // This is a PPC 128-bit floating point value
- FIRST_FP_VALUETYPE = f16,
+ FIRST_FP_VALUETYPE = bf16,
LAST_FP_VALUETYPE = ppcf128,
- v1i1 = 14, // 1 x i1
- v2i1 = 15, // 2 x i1
- v4i1 = 16, // 4 x i1
- v8i1 = 17, // 8 x i1
- v16i1 = 18, // 16 x i1
- 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
+ v1i1 = 15, // 1 x i1
+ v2i1 = 16, // 2 x i1
+ v4i1 = 17, // 4 x i1
+ v8i1 = 18, // 8 x i1
+ v16i1 = 19, // 16 x i1
+ v32i1 = 20, // 32 x i1
+ v64i1 = 21, // 64 x i1
+ v128i1 = 22, // 128 x i1
+ v256i1 = 23, // 256 x i1
+ v512i1 = 24, // 512 x i1
+ v1024i1 = 25, // 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
+ v1i8 = 26, // 1 x i8
+ v2i8 = 27, // 2 x i8
+ v4i8 = 28, // 4 x i8
+ v8i8 = 29, // 8 x i8
+ v16i8 = 30, // 16 x i8
+ v32i8 = 31, // 32 x i8
+ v64i8 = 32, // 64 x i8
+ v128i8 = 33, //128 x i8
+ v256i8 = 34, //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
+ v1i16 = 35, // 1 x i16
+ v2i16 = 36, // 2 x i16
+ v3i16 = 37, // 3 x i16
+ v4i16 = 38, // 4 x i16
+ v8i16 = 39, // 8 x i16
+ v16i16 = 40, // 16 x i16
+ v32i16 = 41, // 32 x i16
+ v64i16 = 42, // 64 x i16
+ v128i16 = 43, //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
+ v1i32 = 44, // 1 x i32
+ v2i32 = 45, // 2 x i32
+ v3i32 = 46, // 3 x i32
+ v4i32 = 47, // 4 x i32
+ v5i32 = 48, // 5 x i32
+ v8i32 = 49, // 8 x i32
+ v16i32 = 50, // 16 x i32
+ v32i32 = 51, // 32 x i32
+ v64i32 = 52, // 64 x i32
+ v128i32 = 53, // 128 x i32
+ v256i32 = 54, // 256 x i32
+ v512i32 = 55, // 512 x i32
+ v1024i32 = 56, // 1024 x i32
+ v2048i32 = 57, // 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
+ v1i64 = 58, // 1 x i64
+ v2i64 = 59, // 2 x i64
+ v4i64 = 60, // 4 x i64
+ v8i64 = 61, // 8 x i64
+ v16i64 = 62, // 16 x i64
+ v32i64 = 63, // 32 x i64
+ v64i64 = 64, // 64 x i64
+ v128i64 = 65, // 128 x i64
+ v256i64 = 66, // 256 x i64
- v1i128 = 61, // 1 x i128
+ v1i128 = 67, // 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
+ FIRST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE = v1i1,
+ LAST_INTEGER_FIXEDLEN_VECTOR_VALUETYPE = v1i128,
- 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
+ v2f16 = 68, // 2 x f16
+ v3f16 = 69, // 3 x f16
+ v4f16 = 70, // 4 x f16
+ v8f16 = 71, // 8 x f16
+ v16f16 = 72, // 16 x f16
+ v32f16 = 73, // 32 x f16
+ v64f16 = 74, // 64 x f16
+ v128f16 = 75, // 128 x f16
+ v2bf16 = 76, // 2 x bf16
+ v3bf16 = 77, // 3 x bf16
+ v4bf16 = 78, // 4 x bf16
+ v8bf16 = 79, // 8 x bf16
+ v16bf16 = 80, // 16 x bf16
+ v32bf16 = 81, // 32 x bf16
+ v64bf16 = 82, // 64 x bf16
+ v128bf16 = 83, // 128 x bf16
+ v1f32 = 84, // 1 x f32
+ v2f32 = 85, // 2 x f32
+ v3f32 = 86, // 3 x f32
+ v4f32 = 87, // 4 x f32
+ v5f32 = 88, // 5 x f32
+ v8f32 = 89, // 8 x f32
+ v16f32 = 90, // 16 x f32
+ v32f32 = 91, // 32 x f32
+ v64f32 = 92, // 64 x f32
+ v128f32 = 93, // 128 x f32
+ v256f32 = 94, // 256 x f32
+ v512f32 = 95, // 512 x f32
+ v1024f32 = 96, // 1024 x f32
+ v2048f32 = 97, // 2048 x f32
+ v1f64 = 98, // 1 x f64
+ v2f64 = 99, // 2 x f64
+ v4f64 = 100, // 4 x f64
+ v8f64 = 101, // 8 x f64
+ v16f64 = 102, // 16 x f64
+ v32f64 = 103, // 32 x f64
+ v64f64 = 104, // 64 x f64
+ v128f64 = 105, // 128 x f64
+ v256f64 = 106, // 256 x f64
- 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
+ FIRST_FP_FIXEDLEN_VECTOR_VALUETYPE = v2f16,
+ LAST_FP_FIXEDLEN_VECTOR_VALUETYPE = v256f64,
- 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
+ FIRST_FIXEDLEN_VECTOR_VALUETYPE = v1i1,
+ LAST_FIXEDLEN_VECTOR_VALUETYPE = v256f64,
- 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
+ nxv1i1 = 107, // n x 1 x i1
+ nxv2i1 = 108, // n x 2 x i1
+ nxv4i1 = 109, // n x 4 x i1
+ nxv8i1 = 110, // n x 8 x i1
+ nxv16i1 = 111, // n x 16 x i1
+ nxv32i1 = 112, // n x 32 x i1
+ nxv64i1 = 113, // n x 64 x i1
- FIRST_INTEGER_VECTOR_VALUETYPE = v1i1,
- LAST_INTEGER_VECTOR_VALUETYPE = nxv32i64,
+ nxv1i8 = 114, // n x 1 x i8
+ nxv2i8 = 115, // n x 2 x i8
+ nxv4i8 = 116, // n x 4 x i8
+ nxv8i8 = 117, // n x 8 x i8
+ nxv16i8 = 118, // n x 16 x i8
+ nxv32i8 = 119, // n x 32 x i8
+ nxv64i8 = 120, // n x 64 x i8
- FIRST_INTEGER_SCALABLE_VALUETYPE = nxv1i1,
- LAST_INTEGER_SCALABLE_VALUETYPE = nxv32i64,
+ nxv1i16 = 121, // n x 1 x i16
+ nxv2i16 = 122, // n x 2 x i16
+ nxv4i16 = 123, // n x 4 x i16
+ nxv8i16 = 124, // n x 8 x i16
+ nxv16i16 = 125, // n x 16 x i16
+ nxv32i16 = 126, // n x 32 x i16
- 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
+ nxv1i32 = 127, // n x 1 x i32
+ nxv2i32 = 128, // n x 2 x i32
+ nxv4i32 = 129, // n x 4 x i32
+ nxv8i32 = 130, // n x 8 x i32
+ nxv16i32 = 131, // n x 16 x i32
+ nxv32i32 = 132, // n x 32 x i32
- 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
+ nxv1i64 = 133, // n x 1 x i64
+ nxv2i64 = 134, // n x 2 x i64
+ nxv4i64 = 135, // n x 4 x i64
+ nxv8i64 = 136, // n x 8 x i64
+ nxv16i64 = 137, // n x 16 x i64
+ nxv32i64 = 138, // n x 32 x i64
- FIRST_FP_VECTOR_VALUETYPE = v2f16,
- LAST_FP_VECTOR_VALUETYPE = nxv8f64,
+ FIRST_INTEGER_SCALABLE_VECTOR_VALUETYPE = nxv1i1,
+ LAST_INTEGER_SCALABLE_VECTOR_VALUETYPE = nxv32i64,
- FIRST_FP_SCALABLE_VALUETYPE = nxv2f16,
- LAST_FP_SCALABLE_VALUETYPE = nxv8f64,
+ nxv1f16 = 139, // n x 1 x f16
+ nxv2f16 = 140, // n x 2 x f16
+ nxv4f16 = 141, // n x 4 x f16
+ nxv8f16 = 142, // n x 8 x f16
+ nxv16f16 = 143, // n x 16 x f16
+ nxv32f16 = 144, // n x 32 x f16
+ nxv2bf16 = 145, // n x 2 x bf16
+ nxv4bf16 = 146, // n x 4 x bf16
+ nxv8bf16 = 147, // n x 8 x bf16
+ nxv1f32 = 148, // n x 1 x f32
+ nxv2f32 = 149, // n x 2 x f32
+ nxv4f32 = 150, // n x 4 x f32
+ nxv8f32 = 151, // n x 8 x f32
+ nxv16f32 = 152, // n x 16 x f32
+ nxv1f64 = 153, // n x 1 x f64
+ nxv2f64 = 154, // n x 2 x f64
+ nxv4f64 = 155, // n x 4 x f64
+ nxv8f64 = 156, // n x 8 x f64
+
+ FIRST_FP_SCALABLE_VECTOR_VALUETYPE = nxv1f16,
+ 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 = 157, // This is an X86 MMX value
- Glue = 126, // This glues nodes together during pre-RA sched
+ Glue = 158, // This glues nodes together during pre-RA sched
- isVoid = 127, // This has no value
+ isVoid = 159, // This has no value
- Untyped = 128, // This value takes a register, but has
- // unspecified type. The register class
- // will be determined by the opcode.
+ Untyped = 160, // This value takes a register, but has
+ // unspecified type. The register class
+ // will be determined by the opcode.
- ExceptRef = 129, // WebAssembly's except_ref type
+ funcref = 161, // WebAssembly's funcref type
+ externref = 162, // WebAssembly's externref type
+ x86amx = 163, // This is an X86 AMX value
- FIRST_VALUETYPE = 1, // This is always the beginning of the list.
- LAST_VALUETYPE = 130, // This always remains at the end of the list.
+ FIRST_VALUETYPE = 1, // This is always the beginning of the list.
+ LAST_VALUETYPE = 164, // 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
// This value must be a multiple of 32.
- MAX_ALLOWED_VALUETYPE = 160,
+ MAX_ALLOWED_VALUETYPE = 192,
// A value of type llvm::TokenTy
token = 248,
@@ -253,41 +293,6 @@
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 +313,20 @@
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 +344,13 @@
/// 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.
@@ -349,17 +361,19 @@
/// Return true if this is a 32-bit vector type.
bool is32BitVector() const {
- return (SimpleTy == MVT::v32i1 || SimpleTy == MVT::v4i8 ||
- SimpleTy == MVT::v2i16 || SimpleTy == MVT::v1i32 ||
- SimpleTy == MVT::v2f16 || SimpleTy == MVT::v1f32);
+ return (SimpleTy == MVT::v32i1 || SimpleTy == MVT::v4i8 ||
+ SimpleTy == MVT::v2i16 || SimpleTy == MVT::v1i32 ||
+ SimpleTy == MVT::v2f16 || SimpleTy == MVT::v2bf16 ||
+ SimpleTy == MVT::v1f32);
}
/// Return true if this is a 64-bit vector type.
bool is64BitVector() const {
- return (SimpleTy == MVT::v64i1 || SimpleTy == MVT::v8i8 ||
- SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 ||
- SimpleTy == MVT::v1i64 || SimpleTy == MVT::v4f16 ||
- SimpleTy == MVT::v2f32 || SimpleTy == MVT::v1f64);
+ return (SimpleTy == MVT::v64i1 || SimpleTy == MVT::v8i8 ||
+ SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 ||
+ SimpleTy == MVT::v1i64 || SimpleTy == MVT::v4f16 ||
+ SimpleTy == MVT::v4bf16 ||SimpleTy == MVT::v2f32 ||
+ SimpleTy == MVT::v1f64);
}
/// Return true if this is a 128-bit vector type.
@@ -367,22 +381,25 @@
return (SimpleTy == MVT::v128i1 || SimpleTy == MVT::v16i8 ||
SimpleTy == MVT::v8i16 || SimpleTy == MVT::v4i32 ||
SimpleTy == MVT::v2i64 || SimpleTy == MVT::v1i128 ||
- SimpleTy == MVT::v8f16 || SimpleTy == MVT::v4f32 ||
- SimpleTy == MVT::v2f64);
+ SimpleTy == MVT::v8f16 || SimpleTy == MVT::v8bf16 ||
+ SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64);
}
/// 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::v16bf16 ||
+ 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 ||
+ return (SimpleTy == MVT::v32f16 || SimpleTy == MVT::v32bf16 ||
+ SimpleTy == MVT::v16f32 || SimpleTy == MVT::v8f64 ||
+ SimpleTy == MVT::v512i1 || SimpleTy == MVT::v64i8 ||
+ SimpleTy == MVT::v32i16 || SimpleTy == MVT::v16i32 ||
SimpleTy == MVT::v8i64);
}
@@ -390,20 +407,63 @@
bool is1024BitVector() const {
return (SimpleTy == MVT::v1024i1 || SimpleTy == MVT::v128i8 ||
SimpleTy == MVT::v64i16 || SimpleTy == MVT::v32i32 ||
- SimpleTy == MVT::v16i64);
+ SimpleTy == MVT::v16i64 || SimpleTy == MVT::v64f16 ||
+ SimpleTy == MVT::v32f32 || SimpleTy == MVT::v16f64 ||
+ SimpleTy == MVT::v64bf16);
}
/// Return true if this is a 2048-bit vector type.
bool is2048BitVector() const {
- return (SimpleTy == MVT::v256i8 || SimpleTy == MVT::v128i16 ||
- SimpleTy == MVT::v64i32 || SimpleTy == MVT::v32i64);
+ return (SimpleTy == MVT::v256i8 || SimpleTy == MVT::v128i16 ||
+ SimpleTy == MVT::v64i32 || SimpleTy == MVT::v32i64 ||
+ SimpleTy == MVT::v128f16 || SimpleTy == MVT::v64f32 ||
+ SimpleTy == MVT::v32f64 || SimpleTy == MVT::v128bf16);
}
/// Return true if this is an overloaded type for TableGen.
bool isOverloaded() const {
- return (SimpleTy==MVT::Any ||
- SimpleTy==MVT::iAny || SimpleTy==MVT::fAny ||
- SimpleTy==MVT::vAny || SimpleTy==MVT::iPTRAny);
+ return (SimpleTy == MVT::Any || SimpleTy == MVT::iAny ||
+ SimpleTy == MVT::fAny || SimpleTy == MVT::vAny ||
+ SimpleTy == MVT::iPTRAny);
+ }
+
+ /// Return a vector with the same number of elements as this vector, but
+ /// with the element type converted to an integer type with the same
+ /// bitwidth.
+ MVT changeVectorElementTypeToInteger() const {
+ MVT EltTy = getVectorElementType();
+ MVT IntTy = MVT::getIntegerVT(EltTy.getSizeInBits());
+ MVT VecTy = MVT::getVectorVT(IntTy, getVectorElementCount());
+ assert(VecTy.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE &&
+ "Simple vector VT not representable by simple integer vector VT!");
+ return VecTy;
+ }
+
+ /// Return a VT for a vector type whose attributes match ourselves
+ /// with the exception of the element type that is chosen by the caller.
+ MVT changeVectorElementType(MVT EltVT) const {
+ MVT VecTy = MVT::getVectorVT(EltVT, getVectorElementCount());
+ assert(VecTy.SimpleTy != MVT::INVALID_SIMPLE_VALUE_TYPE &&
+ "Simple vector VT not representable by simple integer vector VT!");
+ return VecTy;
+ }
+
+ /// Return the type converted to an equivalently sized integer or vector
+ /// with integer element type. Similar to changeVectorElementTypeToInteger,
+ /// but also handles scalars.
+ MVT changeTypeToInteger() {
+ if (isVector())
+ return changeVectorElementTypeToInteger();
+ return MVT::getIntegerVT(getSizeInBits());
+ }
+
+ /// 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.isKnownEven() && "Splitting vector, but not in half!");
+ return getVectorVT(EltVT, EltCnt.divideCoefficientBy(2));
}
/// Returns true if the given vector is a power of 2.
@@ -440,6 +500,7 @@
case v32i1:
case v64i1:
case v128i1:
+ case v256i1:
case v512i1:
case v1024i1:
case nxv1i1:
@@ -447,7 +508,8 @@
case nxv4i1:
case nxv8i1:
case nxv16i1:
- case nxv32i1: return i1;
+ case nxv32i1:
+ case nxv64i1: return i1;
case v1i8:
case v2i8:
case v4i8:
@@ -462,9 +524,11 @@
case nxv4i8:
case nxv8i8:
case nxv16i8:
- case nxv32i8: return i8;
+ case nxv32i8:
+ case nxv64i8: return i8;
case v1i16:
case v2i16:
+ case v3i16:
case v4i16:
case v8i16:
case v16i16:
@@ -503,6 +567,9 @@
case v8i64:
case v16i64:
case v32i64:
+ case v64i64:
+ case v128i64:
+ case v256i64:
case nxv1i64:
case nxv2i64:
case nxv4i64:
@@ -511,11 +578,30 @@
case nxv32i64: return i64;
case v1i128: return i128;
case v2f16:
+ case v3f16:
case v4f16:
case v8f16:
+ case v16f16:
+ case v32f16:
+ case v64f16:
+ case v128f16:
+ case nxv1f16:
case nxv2f16:
case nxv4f16:
- case nxv8f16: return f16;
+ case nxv8f16:
+ case nxv16f16:
+ case nxv32f16: return f16;
+ case v2bf16:
+ case v3bf16:
+ case v4bf16:
+ case v8bf16:
+ case v16bf16:
+ case v32bf16:
+ case v64bf16:
+ case v128bf16:
+ case nxv2bf16:
+ case nxv4bf16:
+ case nxv8bf16: return bf16;
case v1f32:
case v2f32:
case v3f32:
@@ -539,6 +625,11 @@
case v2f64:
case v4f64:
case v8f64:
+ case v16f64:
+ case v32f64:
+ case v64f64:
+ case v128f64:
+ case v256f64:
case nxv1f64:
case nxv2f64:
case nxv4f64:
@@ -558,41 +649,62 @@
case v512i1:
case v512i32:
case v512f32: return 512;
+ case v256i1:
case v256i8:
case v256i32:
- case v256f32: return 256;
+ case v256i64:
+ case v256f32:
+ case v256f64: return 256;
case v128i1:
case v128i8:
case v128i16:
case v128i32:
- case v128f32: return 128;
+ case v128i64:
+ case v128f16:
+ case v128bf16:
+ case v128f32:
+ case v128f64: return 128;
case v64i1:
case v64i8:
case v64i16:
case v64i32:
- case v64f32: return 64;
+ case v64i64:
+ case v64f16:
+ case v64bf16:
+ case v64f32:
+ case v64f64:
+ case nxv64i1:
+ case nxv64i8: return 64;
case v32i1:
case v32i8:
case v32i16:
case v32i32:
case v32i64:
+ case v32f16:
+ case v32bf16:
case v32f32:
+ case v32f64:
case nxv32i1:
case nxv32i8:
case nxv32i16:
case nxv32i32:
- case nxv32i64: return 32;
+ case nxv32i64:
+ case nxv32f16: return 32;
case v16i1:
case v16i8:
case v16i16:
case v16i32:
case v16i64:
+ case v16f16:
+ case v16bf16:
case v16f32:
+ case v16f64:
case nxv16i1:
case nxv16i8:
case nxv16i16:
case nxv16i32:
case nxv16i64:
+ case nxv16f16:
case nxv16f32: return 16;
case v8i1:
case v8i8:
@@ -600,6 +712,7 @@
case v8i32:
case v8i64:
case v8f16:
+ case v8bf16:
case v8f32:
case v8f64:
case nxv8i1:
@@ -608,6 +721,7 @@
case nxv8i32:
case nxv8i64:
case nxv8f16:
+ case nxv8bf16:
case nxv8f32:
case nxv8f64: return 8;
case v5i32:
@@ -618,6 +732,7 @@
case v4i32:
case v4i64:
case v4f16:
+ case v4bf16:
case v4f32:
case v4f64:
case nxv4i1:
@@ -626,9 +741,13 @@
case nxv4i32:
case nxv4i64:
case nxv4f16:
+ case nxv4bf16:
case nxv4f32:
case nxv4f64: return 4;
+ case v3i16:
case v3i32:
+ case v3f16:
+ case v3bf16:
case v3f32: return 3;
case v2i1:
case v2i8:
@@ -636,6 +755,7 @@
case v2i32:
case v2i64:
case v2f16:
+ case v2bf16:
case v2f32:
case v2f64:
case nxv2i1:
@@ -644,6 +764,7 @@
case nxv2i32:
case nxv2i64:
case nxv2f16:
+ case nxv2bf16:
case nxv2f32:
case nxv2f64: return 2;
case v1i1:
@@ -659,16 +780,27 @@
case nxv1i16:
case nxv1i32:
case nxv1i64:
+ case nxv1f16:
case nxv1f32:
case nxv1f64: return 1;
}
}
- MVT::ElementCount getVectorElementCount() const {
- return { getVectorNumElements(), isScalableVector() };
+ ElementCount getVectorElementCount() const {
+ return ElementCount::get(getVectorNumElements(), isScalableVector());
}
- unsigned getSizeInBits() const {
+ /// Given a vector type, return the minimum number of elements it contains.
+ unsigned getVectorMinNumElements() const {
+ return getVectorElementCount().getKnownMinValue();
+ }
+
+ /// Returns the size of the specified MVT in bits.
+ ///
+ /// If the value type is a scalable vector type, the scalable property will
+ /// be set and the runtime size will be a positive integer multiple of the
+ /// base size.
+ TypeSize getSizeInBits() const {
switch (SimpleTy) {
default:
llvm_unreachable("getSizeInBits called on extended MVT.");
@@ -688,39 +820,46 @@
case Metadata:
llvm_unreachable("Value type is metadata.");
case i1:
- case v1i1:
- case nxv1i1: return 1;
- case v2i1:
- case nxv2i1: return 2;
- case v4i1:
- case nxv4i1: return 4;
+ case v1i1: return TypeSize::Fixed(1);
+ case nxv1i1: return TypeSize::Scalable(1);
+ case v2i1: return TypeSize::Fixed(2);
+ case nxv2i1: return TypeSize::Scalable(2);
+ case v4i1: return TypeSize::Fixed(4);
+ case nxv4i1: return TypeSize::Scalable(4);
case i8 :
case v1i8:
- case v8i1:
+ case v8i1: return TypeSize::Fixed(8);
case nxv1i8:
- case nxv8i1: return 8;
+ case nxv8i1: return TypeSize::Scalable(8);
case i16 :
case f16:
+ case bf16:
case v16i1:
case v2i8:
- case v1i16:
+ case v1i16: return TypeSize::Fixed(16);
case nxv16i1:
case nxv2i8:
- case nxv1i16: return 16;
+ case nxv1i16:
+ case nxv1f16: return TypeSize::Scalable(16);
case f32 :
case i32 :
case v32i1:
case v4i8:
case v2i16:
case v2f16:
+ case v2bf16:
case v1f32:
- case v1i32:
+ case v1i32: return TypeSize::Fixed(32);
case nxv32i1:
case nxv4i8:
case nxv2i16:
case nxv1i32:
case nxv2f16:
- case nxv1f32: return 32;
+ case nxv2bf16:
+ case nxv1f32: return TypeSize::Scalable(32);
+ case v3i16:
+ case v3f16:
+ case v3bf16: return TypeSize::Fixed(48);
case x86mmx:
case f64 :
case i64 :
@@ -730,18 +869,21 @@
case v2i32:
case v1i64:
case v4f16:
+ case v4bf16:
case v2f32:
- case v1f64:
+ case v1f64: return TypeSize::Fixed(64);
+ case nxv64i1:
case nxv8i8:
case nxv4i16:
case nxv2i32:
case nxv1i64:
case nxv4f16:
+ case nxv4bf16:
case nxv2f32:
- case nxv1f64: return 64;
- case f80 : return 80;
+ case nxv1f64: return TypeSize::Scalable(64);
+ case f80 : return TypeSize::Fixed(80);
case v3i32:
- case v3f32: return 96;
+ case v3f32: return TypeSize::Fixed(96);
case f128:
case ppcf128:
case i128:
@@ -752,103 +894,176 @@
case v2i64:
case v1i128:
case v8f16:
+ case v8bf16:
case v4f32:
- case v2f64:
+ case v2f64: return TypeSize::Fixed(128);
case nxv16i8:
case nxv8i16:
case nxv4i32:
case nxv2i64:
case nxv8f16:
+ case nxv8bf16:
case nxv4f32:
- case nxv2f64: return 128;
+ case nxv2f64: return TypeSize::Scalable(128);
case v5i32:
- case v5f32: return 160;
+ case v5f32: return TypeSize::Fixed(160);
+ case v256i1:
case v32i8:
case v16i16:
case v8i32:
case v4i64:
+ case v16f16:
+ case v16bf16:
case v8f32:
- case v4f64:
+ case v4f64: return TypeSize::Fixed(256);
case nxv32i8:
case nxv16i16:
case nxv8i32:
case nxv4i64:
+ case nxv16f16:
case nxv8f32:
- case nxv4f64: return 256;
+ case nxv4f64: return TypeSize::Scalable(256);
case v512i1:
case v64i8:
case v32i16:
case v16i32:
case v8i64:
+ case v32f16:
+ case v32bf16:
case v16f32:
- case v8f64:
+ case v8f64: return TypeSize::Fixed(512);
+ case nxv64i8:
case nxv32i16:
case nxv16i32:
case nxv8i64:
+ case nxv32f16:
case nxv16f32:
- case nxv8f64: return 512;
+ case nxv8f64: return TypeSize::Scalable(512);
case v1024i1:
case v128i8:
case v64i16:
case v32i32:
case v16i64:
+ case v64f16:
+ case v64bf16:
case v32f32:
+ case v16f64: return TypeSize::Fixed(1024);
case nxv32i32:
- case nxv16i64: return 1024;
+ case nxv16i64: return TypeSize::Scalable(1024);
case v256i8:
case v128i16:
case v64i32:
case v32i64:
+ case v128f16:
+ case v128bf16:
case v64f32:
- case nxv32i64: return 2048;
+ case v32f64: return TypeSize::Fixed(2048);
+ case nxv32i64: return TypeSize::Scalable(2048);
case v128i32:
- case v128f32: return 4096;
+ case v64i64:
+ case v128f32:
+ case v64f64: return TypeSize::Fixed(4096);
case v256i32:
- case v256f32: return 8192;
+ case v128i64:
+ case v256f32:
+ case x86amx:
+ case v128f64: return TypeSize::Fixed(8192);
case v512i32:
- case v512f32: return 16384;
+ case v256i64:
+ case v512f32:
+ case v256f64: return TypeSize::Fixed(16384);
case v1024i32:
- case v1024f32: return 32768;
+ case v1024f32: return TypeSize::Fixed(32768);
case v2048i32:
- case v2048f32: return 65536;
- case ExceptRef: return 0; // opaque type
+ case v2048f32: return TypeSize::Fixed(65536);
+ case funcref:
+ case externref: return TypeSize::Fixed(0); // opaque type
}
}
- unsigned getScalarSizeInBits() const {
- return getScalarType().getSizeInBits();
+ /// Return the size of the specified fixed width value type in bits. The
+ /// function will assert if the type is scalable.
+ uint64_t getFixedSizeInBits() const {
+ return getSizeInBits().getFixedSize();
+ }
+
+ uint64_t getScalarSizeInBits() const {
+ return getScalarType().getSizeInBits().getFixedSize();
}
/// Return the number of bytes overwritten by a store of the specified value
/// type.
- unsigned getStoreSize() const {
- return (getSizeInBits() + 7) / 8;
+ ///
+ /// If the value type is a scalable vector type, the scalable property will
+ /// be set and the runtime size will be a positive integer multiple of the
+ /// base size.
+ TypeSize getStoreSize() const {
+ TypeSize BaseSize = getSizeInBits();
+ return {(BaseSize.getKnownMinSize() + 7) / 8, BaseSize.isScalable()};
}
/// Return the number of bits overwritten by a store of the specified value
/// type.
- unsigned getStoreSizeInBits() const {
+ ///
+ /// If the value type is a scalable vector type, the scalable property will
+ /// be set and the runtime size will be a positive integer multiple of the
+ /// base size.
+ TypeSize getStoreSizeInBits() const {
return getStoreSize() * 8;
}
+ /// Returns true if the number of bits for the type is a multiple of an
+ /// 8-bit byte.
+ bool isByteSized() const { return getSizeInBits().isKnownMultipleOf(8); }
+
+ /// Return true if we know at compile time this has more bits than VT.
+ bool knownBitsGT(MVT VT) const {
+ return TypeSize::isKnownGT(getSizeInBits(), VT.getSizeInBits());
+ }
+
+ /// Return true if we know at compile time this has more than or the same
+ /// bits as VT.
+ bool knownBitsGE(MVT VT) const {
+ return TypeSize::isKnownGE(getSizeInBits(), VT.getSizeInBits());
+ }
+
+ /// Return true if we know at compile time this has fewer bits than VT.
+ bool knownBitsLT(MVT VT) const {
+ return TypeSize::isKnownLT(getSizeInBits(), VT.getSizeInBits());
+ }
+
+ /// Return true if we know at compile time this has fewer than or the same
+ /// bits as VT.
+ bool knownBitsLE(MVT VT) const {
+ return TypeSize::isKnownLE(getSizeInBits(), VT.getSizeInBits());
+ }
+
/// Return true if this has more bits than VT.
bool bitsGT(MVT VT) const {
- return getSizeInBits() > VT.getSizeInBits();
+ assert(isScalableVector() == VT.isScalableVector() &&
+ "Comparison between scalable and fixed types");
+ return knownBitsGT(VT);
}
/// Return true if this has no less bits than VT.
bool bitsGE(MVT VT) const {
- return getSizeInBits() >= VT.getSizeInBits();
+ assert(isScalableVector() == VT.isScalableVector() &&
+ "Comparison between scalable and fixed types");
+ return knownBitsGE(VT);
}
/// Return true if this has less bits than VT.
bool bitsLT(MVT VT) const {
- return getSizeInBits() < VT.getSizeInBits();
+ assert(isScalableVector() == VT.isScalableVector() &&
+ "Comparison between scalable and fixed types");
+ return knownBitsLT(VT);
}
/// Return true if this has no more bits than VT.
bool bitsLE(MVT VT) const {
- return getSizeInBits() <= VT.getSizeInBits();
+ assert(isScalableVector() == VT.isScalableVector() &&
+ "Comparison between scalable and fixed types");
+ return knownBitsLE(VT);
}
static MVT getFloatingPointVT(unsigned BitWidth) {
@@ -900,6 +1115,7 @@
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 +1133,7 @@
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;
@@ -947,14 +1164,32 @@
if (NumElements == 8) return MVT::v8i64;
if (NumElements == 16) return MVT::v16i64;
if (NumElements == 32) return MVT::v32i64;
+ if (NumElements == 64) return MVT::v64i64;
+ if (NumElements == 128) return MVT::v128i64;
+ if (NumElements == 256) return MVT::v256i64;
break;
case MVT::i128:
if (NumElements == 1) return MVT::v1i128;
break;
case MVT::f16:
- if (NumElements == 2) return MVT::v2f16;
- if (NumElements == 4) return MVT::v4f16;
- if (NumElements == 8) return MVT::v8f16;
+ 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;
+ if (NumElements == 64) return MVT::v64f16;
+ if (NumElements == 128) return MVT::v128f16;
+ break;
+ case MVT::bf16:
+ if (NumElements == 2) return MVT::v2bf16;
+ if (NumElements == 3) return MVT::v3bf16;
+ if (NumElements == 4) return MVT::v4bf16;
+ if (NumElements == 8) return MVT::v8bf16;
+ if (NumElements == 16) return MVT::v16bf16;
+ if (NumElements == 32) return MVT::v32bf16;
+ if (NumElements == 64) return MVT::v64bf16;
+ if (NumElements == 128) return MVT::v128bf16;
break;
case MVT::f32:
if (NumElements == 1) return MVT::v1f32;
@@ -977,6 +1212,11 @@
if (NumElements == 2) return MVT::v2f64;
if (NumElements == 4) return MVT::v4f64;
if (NumElements == 8) return MVT::v8f64;
+ if (NumElements == 16) return MVT::v16f64;
+ if (NumElements == 32) return MVT::v32f64;
+ if (NumElements == 64) return MVT::v64f64;
+ if (NumElements == 128) return MVT::v128f64;
+ if (NumElements == 256) return MVT::v256f64;
break;
}
return (MVT::SimpleValueType)(MVT::INVALID_SIMPLE_VALUE_TYPE);
@@ -993,6 +1233,7 @@
if (NumElements == 8) return MVT::nxv8i1;
if (NumElements == 16) return MVT::nxv16i1;
if (NumElements == 32) return MVT::nxv32i1;
+ if (NumElements == 64) return MVT::nxv64i1;
break;
case MVT::i8:
if (NumElements == 1) return MVT::nxv1i8;
@@ -1001,6 +1242,7 @@
if (NumElements == 8) return MVT::nxv8i8;
if (NumElements == 16) return MVT::nxv16i8;
if (NumElements == 32) return MVT::nxv32i8;
+ if (NumElements == 64) return MVT::nxv64i8;
break;
case MVT::i16:
if (NumElements == 1) return MVT::nxv1i16;
@@ -1027,9 +1269,17 @@
if (NumElements == 32) return MVT::nxv32i64;
break;
case MVT::f16:
+ if (NumElements == 1) return MVT::nxv1f16;
if (NumElements == 2) return MVT::nxv2f16;
if (NumElements == 4) return MVT::nxv4f16;
if (NumElements == 8) return MVT::nxv8f16;
+ if (NumElements == 16) return MVT::nxv16f16;
+ if (NumElements == 32) return MVT::nxv32f16;
+ break;
+ case MVT::bf16:
+ if (NumElements == 2) return MVT::nxv2bf16;
+ if (NumElements == 4) return MVT::nxv4bf16;
+ if (NumElements == 8) return MVT::nxv8bf16;
break;
case MVT::f32:
if (NumElements == 1) return MVT::nxv1f32;
@@ -1054,10 +1304,10 @@
return getVectorVT(VT, NumElements);
}
- static MVT getVectorVT(MVT VT, MVT::ElementCount EC) {
- if (EC.Scalable)
- return getScalableVectorVT(VT, EC.Min);
- return getVectorVT(VT, EC.Min);
+ static MVT getVectorVT(MVT VT, ElementCount EC) {
+ if (EC.isScalable())
+ return getScalableVectorVT(VT, EC.getKnownMinValue());
+ return getVectorVT(VT, EC.getKnownMinValue());
}
/// Return the value type corresponding to the specified type. This returns
@@ -1108,26 +1358,40 @@
(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/linux-x64/clang/include/llvm/Support/ManagedStatic.h b/linux-x64/clang/include/llvm/Support/ManagedStatic.h
index e65bb05..f2b4142 100644
--- a/linux-x64/clang/include/llvm/Support/ManagedStatic.h
+++ b/linux-x64/clang/include/llvm/Support/ManagedStatic.h
@@ -40,8 +40,8 @@
// constexpr, a dynamic initializer may be emitted depending on optimization
// settings. For the affected versions of MSVC, use the old linker
// initialization pattern of not providing a constructor and leaving the fields
-// uninitialized.
-#if !defined(_MSC_VER) || defined(__clang__)
+// uninitialized. See http://llvm.org/PR41367 for details.
+#if !defined(_MSC_VER) || (_MSC_VER >= 1925) || defined(__clang__)
#define LLVM_USE_CONSTEXPR_CTOR
#endif
@@ -102,6 +102,12 @@
}
const C *operator->() const { return &**this; }
+
+ // Extract the instance, leaving the ManagedStatic uninitialized. The
+ // user is then responsible for the lifetime of the returned instance.
+ C *claim() {
+ return static_cast<C *>(Ptr.exchange(nullptr));
+ }
};
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
diff --git a/linux-x64/clang/include/llvm/Support/MathExtras.h b/linux-x64/clang/include/llvm/Support/MathExtras.h
index 85d5a5a..33b9065 100644
--- a/linux-x64/clang/include/llvm/Support/MathExtras.h
+++ b/linux-x64/clang/include/llvm/Support/MathExtras.h
@@ -14,10 +14,11 @@
#define LLVM_SUPPORT_MATHEXTRAS_H
#include "llvm/Support/Compiler.h"
-#include "llvm/Support/SwapByteOrder.h"
#include <algorithm>
#include <cassert>
#include <climits>
+#include <cmath>
+#include <cstdint>
#include <cstring>
#include <limits>
#include <type_traits>
@@ -39,6 +40,7 @@
#endif
namespace llvm {
+
/// The behavior an operation has on an input of 0.
enum ZeroBehavior {
/// The returned value is undefined.
@@ -49,6 +51,42 @@
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 +111,13 @@
}
};
-#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 +133,7 @@
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 +180,13 @@
}
};
-#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 +202,7 @@
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;
@@ -275,6 +313,34 @@
return Val;
}
+#if __has_builtin(__builtin_bitreverse8)
+template<>
+inline uint8_t reverseBits<uint8_t>(uint8_t Val) {
+ return __builtin_bitreverse8(Val);
+}
+#endif
+
+#if __has_builtin(__builtin_bitreverse16)
+template<>
+inline uint16_t reverseBits<uint16_t>(uint16_t Val) {
+ return __builtin_bitreverse16(Val);
+}
+#endif
+
+#if __has_builtin(__builtin_bitreverse32)
+template<>
+inline uint32_t reverseBits<uint32_t>(uint32_t Val) {
+ return __builtin_bitreverse32(Val);
+}
+#endif
+
+#if __has_builtin(__builtin_bitreverse64)
+template<>
+inline uint64_t reverseBits<uint64_t>(uint64_t Val) {
+ return __builtin_bitreverse64(Val);
+}
+#endif
+
// NOTE: The following support functions use the _32/_64 extensions instead of
// type overloading so that signed and unsigned integers can be used without
// ambiguity.
@@ -327,14 +393,12 @@
/// to keep MSVC from (incorrectly) warning on isUInt<64> that we're shifting
/// left too many places.
template <unsigned N>
-constexpr inline typename std::enable_if<(N < 64), bool>::type
-isUInt(uint64_t X) {
+constexpr inline std::enable_if_t<(N < 64), bool> isUInt(uint64_t X) {
static_assert(N > 0, "isUInt<0> doesn't make sense");
return X < (UINT64_C(1) << (N));
}
template <unsigned N>
-constexpr inline typename std::enable_if<N >= 64, bool>::type
-isUInt(uint64_t X) {
+constexpr inline std::enable_if_t<N >= 64, bool> isUInt(uint64_t X) {
return true;
}
@@ -376,7 +440,7 @@
inline int64_t minIntN(int64_t N) {
assert(N > 0 && N <= 64 && "integer width out of range");
- return -(UINT64_C(1)<<(N-1));
+ return UINT64_C(1) + ~(UINT64_C(1) << (N - 1));
}
/// Gets the maximum value for a N-bit signed integer.
@@ -434,21 +498,6 @@
return Value && !(Value & (Value - 1));
}
-/// Return a byte-swapped representation of the 16-bit argument.
-inline uint16_t ByteSwap_16(uint16_t Value) {
- return sys::SwapByteOrder_16(Value);
-}
-
-/// Return a byte-swapped representation of the 32-bit argument.
-inline uint32_t ByteSwap_32(uint32_t Value) {
- return sys::SwapByteOrder_32(Value);
-}
-
-/// Return a byte-swapped representation of the 64-bit argument.
-inline uint64_t ByteSwap_64(uint64_t Value) {
- return sys::SwapByteOrder_64(Value);
-}
-
/// Count the number of ones from the most significant bit to the first
/// zero bit.
///
@@ -486,7 +535,7 @@
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 +548,7 @@
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 +572,16 @@
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
@@ -559,15 +618,20 @@
}
/// Return the greatest common divisor of the values using Euclid's algorithm.
-inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) {
+template <typename T>
+inline T greatestCommonDivisor(T A, T B) {
while (B) {
- uint64_t T = B;
+ T Tmp = B;
B = A % B;
- A = T;
+ A = Tmp;
}
return A;
}
+inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) {
+ return greatestCommonDivisor<uint64_t>(A, B);
+}
+
/// This function takes a 64-bit integer and returns the bit equivalent double.
inline double BitsToDouble(uint64_t Bits) {
double D;
@@ -615,25 +679,6 @@
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) {
@@ -699,18 +744,10 @@
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 integer nearest(Numerator / Denominator).
+inline uint64_t divideNearest(uint64_t Numerator, uint64_t Denominator) {
+ return (Numerator + (Denominator / 2)) / Denominator;
+}
/// 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
@@ -720,13 +757,6 @@
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) {
@@ -762,8 +792,7 @@
/// Subtract two unsigned integers, X and Y, of type T and return the absolute
/// value of the result.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
-AbsoluteDifference(T X, T Y) {
+std::enable_if_t<std::is_unsigned<T>::value, T> AbsoluteDifference(T X, T Y) {
return std::max(X, Y) - std::min(X, Y);
}
@@ -771,7 +800,7 @@
/// maximum representable value of T on overflow. ResultOverflowed indicates if
/// the result is larger than the maximum representable value of type T.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
+std::enable_if_t<std::is_unsigned<T>::value, T>
SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
bool Dummy;
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
@@ -788,7 +817,7 @@
/// maximum representable value of T on overflow. ResultOverflowed indicates if
/// the result is larger than the maximum representable value of type T.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
+std::enable_if_t<std::is_unsigned<T>::value, T>
SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
bool Dummy;
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
@@ -834,7 +863,7 @@
/// overflow. ResultOverflowed indicates if the result is larger than the
/// maximum representable value of type T.
template <typename T>
-typename std::enable_if<std::is_unsigned<T>::value, T>::type
+std::enable_if_t<std::is_unsigned<T>::value, T>
SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
bool Dummy;
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
@@ -848,6 +877,87 @@
/// 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>
+std::enable_if_t<std::is_signed<T>::value, T> 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 = std::make_unsigned_t<T>;
+ 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>
+std::enable_if_t<std::is_signed<T>::value, T> 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 = std::make_unsigned_t<T>;
+ 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>
+std::enable_if_t<std::is_signed<T>::value, T> MulOverflow(T X, T Y, T &Result) {
+ // Perform the unsigned multiplication on absolute values.
+ using U = std::make_unsigned_t<T>;
+ 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/linux-x64/clang/include/llvm/Support/MemAlloc.h b/linux-x64/clang/include/llvm/Support/MemAlloc.h
index 0e58691..d6012bd 100644
--- a/linux-x64/clang/include/llvm/Support/MemAlloc.h
+++ b/linux-x64/clang/include/llvm/Support/MemAlloc.h
@@ -62,5 +62,26 @@
return Result;
}
-}
+/// Allocate a buffer of memory with the given size and alignment.
+///
+/// When the compiler supports aligned operator new, this will use it to to
+/// handle even over-aligned allocations.
+///
+/// However, this doesn't make any attempt to leverage the fancier techniques
+/// like posix_memalign due to portability. It is mostly intended to allow
+/// compatibility with platforms that, after aligned allocation was added, use
+/// reduced default alignment.
+LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void *
+allocate_buffer(size_t Size, size_t Alignment);
+
+/// Deallocate a buffer of memory with the given size and alignment.
+///
+/// If supported, this will used the sized delete operator. Also if supported,
+/// this will pass the alignment to the delete operator.
+///
+/// The pointer must have been allocated with the corresponding new operator,
+/// most likely using the above helper.
+void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment);
+
+} // namespace llvm
#endif
diff --git a/linux-x64/clang/include/llvm/Support/Memory.h b/linux-x64/clang/include/llvm/Support/Memory.h
index 6f22dd7..c045422 100644
--- a/linux-x64/clang/include/llvm/Support/Memory.h
+++ b/linux-x64/clang/include/llvm/Support/Memory.h
@@ -57,6 +57,17 @@
MF_WRITE = 0x2000000,
MF_EXEC = 0x4000000,
MF_RWE_MASK = 0x7000000,
+
+ /// The \p MF_HUGE_HINT flag is used to indicate that the request for
+ /// a memory block should be satisfied with large pages if possible.
+ /// This is only a hint and small pages will be used as fallback.
+ ///
+ /// The presence or absence of this flag in the returned memory block
+ /// is (at least currently) *not* a reliable indicator that the memory
+ /// block will use or will not use large pages. On some systems a request
+ /// without this flag can be backed by large pages without this flag being
+ /// set, and on some other systems a request with this flag can fallback
+ /// to small pages without this flag being cleared.
MF_HUGE_HINT = 0x0000001
};
diff --git a/linux-x64/clang/include/llvm/Support/MemoryBuffer.h b/linux-x64/clang/include/llvm/Support/MemoryBuffer.h
index b5196cd..9e6ee25 100644
--- a/linux-x64/clang/include/llvm/Support/MemoryBuffer.h
+++ b/linux-x64/clang/include/llvm/Support/MemoryBuffer.h
@@ -19,14 +19,23 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBufferRef.h"
#include <cstddef>
#include <cstdint>
#include <memory>
namespace llvm {
-
-class MemoryBufferRef;
+namespace sys {
+namespace fs {
+// Duplicated from FileSystem.h to avoid a dependency.
+#if defined(_WIN32)
+// A Win32 HANDLE is a typedef of void*
+using file_t = void *;
+#else
+using file_t = int;
+#endif
+} // namespace fs
+} // namespace sys
/// This interface provides simple read-only access to a block of memory, and
/// provides simple methods for reading files and standard input into a memory
@@ -48,9 +57,6 @@
void init(const char *BufStart, const char *BufEnd,
bool RequiresNullTerminator);
- static constexpr sys::fs::mapped_file_region::mapmode Mapmode =
- sys::fs::mapped_file_region::readonly;
-
public:
MemoryBuffer(const MemoryBuffer &) = delete;
MemoryBuffer &operator=(const MemoryBuffer &) = delete;
@@ -156,9 +162,6 @@
protected:
WritableMemoryBuffer() = default;
- static constexpr sys::fs::mapped_file_region::mapmode Mapmode =
- sys::fs::mapped_file_region::priv;
-
public:
using MemoryBuffer::getBuffer;
using MemoryBuffer::getBufferEnd;
@@ -218,9 +221,6 @@
protected:
WriteThroughMemoryBuffer() = default;
- static constexpr sys::fs::mapped_file_region::mapmode Mapmode =
- sys::fs::mapped_file_region::readwrite;
-
public:
using MemoryBuffer::getBuffer;
using MemoryBuffer::getBufferEnd;
@@ -258,26 +258,6 @@
using MemoryBuffer::getSTDIN;
};
-class MemoryBufferRef {
- StringRef Buffer;
- StringRef Identifier;
-
-public:
- MemoryBufferRef() = default;
- MemoryBufferRef(const MemoryBuffer& Buffer)
- : Buffer(Buffer.getBuffer()), Identifier(Buffer.getBufferIdentifier()) {}
- MemoryBufferRef(StringRef Buffer, StringRef Identifier)
- : Buffer(Buffer), Identifier(Identifier) {}
-
- StringRef getBuffer() const { return Buffer; }
-
- StringRef getBufferIdentifier() const { return Identifier; }
-
- const char *getBufferStart() const { return Buffer.begin(); }
- const char *getBufferEnd() const { return Buffer.end(); }
- size_t getBufferSize() const { return Buffer.size(); }
-};
-
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(MemoryBuffer, LLVMMemoryBufferRef)
diff --git a/linux-x64/clang/include/llvm/Support/MemoryBufferRef.h b/linux-x64/clang/include/llvm/Support/MemoryBufferRef.h
new file mode 100644
index 0000000..b38a1f3
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/MemoryBufferRef.h
@@ -0,0 +1,56 @@
+//===- MemoryBufferRef.h - Memory Buffer Reference --------------*- 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 the MemoryBuffer interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_MEMORYBUFFERREF_H
+#define LLVM_SUPPORT_MEMORYBUFFERREF_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+class MemoryBuffer;
+
+class MemoryBufferRef {
+ StringRef Buffer;
+ StringRef Identifier;
+
+public:
+ MemoryBufferRef() = default;
+ MemoryBufferRef(const MemoryBuffer &Buffer);
+ MemoryBufferRef(StringRef Buffer, StringRef Identifier)
+ : Buffer(Buffer), Identifier(Identifier) {}
+
+ StringRef getBuffer() const { return Buffer; }
+ StringRef getBufferIdentifier() const { return Identifier; }
+
+ const char *getBufferStart() const { return Buffer.begin(); }
+ const char *getBufferEnd() const { return Buffer.end(); }
+ size_t getBufferSize() const { return Buffer.size(); }
+
+ /// Check pointer identity (not value) of identifier and data.
+ friend bool operator==(const MemoryBufferRef &LHS,
+ const MemoryBufferRef &RHS) {
+ return LHS.Buffer.begin() == RHS.Buffer.begin() &&
+ LHS.Buffer.end() == RHS.Buffer.end() &&
+ LHS.Identifier.begin() == RHS.Identifier.begin() &&
+ LHS.Identifier.end() == RHS.Identifier.end();
+ }
+
+ friend bool operator!=(const MemoryBufferRef &LHS,
+ const MemoryBufferRef &RHS) {
+ return !(LHS == RHS);
+ }
+};
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_MEMORYBUFFERREF_H
diff --git a/linux-x64/clang/include/llvm/Support/Mutex.h b/linux-x64/clang/include/llvm/Support/Mutex.h
index c3abfc7..1d8a0d3 100644
--- a/linux-x64/clang/include/llvm/Support/Mutex.h
+++ b/linux-x64/clang/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 @@
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 @@
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/linux-x64/clang/include/llvm/Support/MutexGuard.h b/linux-x64/clang/include/llvm/Support/MutexGuard.h
deleted file mode 100644
index d86ced1..0000000
--- a/linux-x64/clang/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/linux-x64/clang/include/llvm/Support/NativeFormatting.h b/linux-x64/clang/include/llvm/Support/NativeFormatting.h
index 825a44c..e664d05 100644
--- a/linux-x64/clang/include/llvm/Support/NativeFormatting.h
+++ b/linux-x64/clang/include/llvm/Support/NativeFormatting.h
@@ -10,11 +10,10 @@
#define LLVM_SUPPORT_NATIVE_FORMATTING_H
#include "llvm/ADT/Optional.h"
-#include "llvm/Support/raw_ostream.h"
-
#include <cstdint>
namespace llvm {
+class raw_ostream;
enum class FloatStyle { Exponent, ExponentUpper, Fixed, Percent };
enum class IntegerStyle {
Integer,
diff --git a/linux-x64/clang/include/llvm/Support/OnDiskHashTable.h b/linux-x64/clang/include/llvm/Support/OnDiskHashTable.h
index d84da92..11dc0de 100644
--- a/linux-x64/clang/include/llvm/Support/OnDiskHashTable.h
+++ b/linux-x64/clang/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 @@
// 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/linux-x64/clang/include/llvm/Support/OptimizedStructLayout.h b/linux-x64/clang/include/llvm/Support/OptimizedStructLayout.h
new file mode 100644
index 0000000..773ddfe
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/OptimizedStructLayout.h
@@ -0,0 +1,142 @@
+//===-- OptimizedStructLayout.h - Struct layout algorithm ---------*- 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 an interface for laying out a sequence of fields
+/// as a struct in a way that attempts to minimizes the total space
+/// requirements of the struct while still satisfying the layout
+/// requirements of the individual fields. The resulting layout may be
+/// substantially more compact than simply laying out the fields in their
+/// original order.
+///
+/// Fields may be pre-assigned fixed offsets. They may also be given sizes
+/// that are not multiples of their alignments. There is no currently no
+/// way to describe that a field has interior padding that other fields may
+/// be allocated into.
+///
+/// This algorithm does not claim to be "optimal" for several reasons:
+///
+/// - First, it does not guarantee that the result is minimal in size.
+/// There is no known efficient algoorithm to achieve minimality for
+/// unrestricted inputs. Nonetheless, this algorithm
+///
+/// - Second, there are other ways that a struct layout could be optimized
+/// besides space usage, such as locality. This layout may have a mixed
+/// impact on locality: less overall memory may be used, but adjacent
+/// fields in the original array may be moved further from one another.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_OPTIMIZEDSTRUCTLAYOUT_H
+#define LLVM_SUPPORT_OPTIMIZEDSTRUCTLAYOUT_H
+
+#include "llvm/Support/Alignment.h"
+#include "llvm/ADT/ArrayRef.h"
+#include <utility>
+
+namespace llvm {
+
+/// A field in a structure.
+struct OptimizedStructLayoutField {
+ /// A special value for Offset indicating that the field can be moved
+ /// anywhere.
+ static constexpr uint64_t FlexibleOffset = ~(uint64_t)0;
+
+ OptimizedStructLayoutField(const void *Id, uint64_t Size, Align Alignment,
+ uint64_t FixedOffset = FlexibleOffset)
+ : Offset(FixedOffset), Size(Size), Id(Id), Alignment(Alignment) {
+ assert(Size > 0 && "adding an empty field to the layout");
+ }
+
+ /// The offset of this field in the final layout. If this is
+ /// initialized to FlexibleOffset, layout will overwrite it with
+ /// the assigned offset of the field.
+ uint64_t Offset;
+
+ /// The required size of this field in bytes. Does not have to be
+ /// a multiple of Alignment. Must be non-zero.
+ uint64_t Size;
+
+ /// A opaque value which uniquely identifies this field.
+ const void *Id;
+
+ /// Private scratch space for the algorithm. The implementation
+ /// must treat this as uninitialized memory on entry.
+ void *Scratch;
+
+ /// The required alignment of this field.
+ Align Alignment;
+
+ /// Return true if this field has been assigned a fixed offset.
+ /// After layout, this will be true of all the fields.
+ bool hasFixedOffset() const {
+ return (Offset != FlexibleOffset);
+ }
+
+ /// Given that this field has a fixed offset, return the offset
+ /// of the first byte following it.
+ uint64_t getEndOffset() const {
+ assert(hasFixedOffset());
+ return Offset + Size;
+ }
+};
+
+/// Compute a layout for a struct containing the given fields, making a
+/// best-effort attempt to minimize the amount of space required.
+///
+/// Two features are supported which require a more careful solution
+/// than the well-known "sort by decreasing alignment" solution:
+///
+/// - Fields may be assigned a fixed offset in the layout. If there are
+/// gaps among the fixed-offset fields, the algorithm may attempt
+/// to allocate flexible-offset fields into those gaps. If that's
+/// undesirable, the caller should "block out" those gaps by e.g.
+/// just creating a single fixed-offset field that represents the
+/// entire "header".
+///
+/// - The size of a field is not required to be a multiple of, or even
+/// greater than, the field's required alignment. The only constraint
+/// on fields is that they must not be zero-sized.
+///
+/// To simplify the implementation, any fixed-offset fields in the
+/// layout must appear at the start of the field array, and they must
+/// be ordered by increasing offset.
+///
+/// The algorithm will produce a guaranteed-minimal layout with no
+/// interior padding in the following "C-style" case:
+///
+/// - every field's size is a multiple of its required alignment and
+/// - either no fields have initially fixed offsets, or the fixed-offset
+/// fields have no interior padding and end at an offset that is at
+/// least as aligned as all the flexible-offset fields.
+///
+/// Otherwise, while the algorithm will make a best-effort attempt to
+/// avoid padding, it cannot guarantee a minimal layout, as there is
+/// no known efficient algorithm for doing so.
+///
+/// The layout produced by this algorithm may not be stable across LLVM
+/// releases. Do not use this anywhere where ABI stability is required.
+///
+/// Flexible-offset fields with the same size and alignment will be ordered
+/// the same way they were in the initial array. Otherwise the current
+/// algorithm makes no effort to preserve the initial order of
+/// flexible-offset fields.
+///
+/// On return, all fields will have been assigned a fixed offset, and the
+/// array will be sorted in order of ascending offsets. Note that this
+/// means that the fixed-offset fields may no longer form a strict prefix
+/// if there's any padding before they end.
+///
+/// The return value is the total size of the struct and its required
+/// alignment. Note that the total size is not rounded up to a multiple
+/// of the required alignment; clients which require this can do so easily.
+std::pair<uint64_t, Align> performOptimizedStructLayout(
+ MutableArrayRef<OptimizedStructLayoutField> Fields);
+
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/Options.h b/linux-x64/clang/include/llvm/Support/Options.h
deleted file mode 100644
index d02ef85..0000000
--- a/linux-x64/clang/include/llvm/Support/Options.h
+++ /dev/null
@@ -1,119 +0,0 @@
-//===- llvm/Support/Options.h - Debug options support -----------*- 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
-//
-//===----------------------------------------------------------------------===//
-/// \file
-/// This file declares helper objects for defining debug options that can be
-/// configured via the command line. The new API currently builds on the cl::opt
-/// API, but does not require the use of static globals.
-///
-/// With this API options are registered during initialization. For passes, this
-/// happens during pass initialization. Passes with options will call a static
-/// registerOptions method during initialization that registers options with the
-/// OptionRegistry. An example implementation of registerOptions is:
-///
-/// static void registerOptions() {
-/// OptionRegistry::registerOption<bool, Scalarizer,
-/// &Scalarizer::ScalarizeLoadStore>(
-/// "scalarize-load-store",
-/// "Allow the scalarizer pass to scalarize loads and store", false);
-/// }
-///
-/// When reading data for options the interface is via the LLVMContext. Option
-/// data for passes should be read from the context during doInitialization. An
-/// example of reading the above option would be:
-///
-/// ScalarizeLoadStore =
-/// M.getContext().getOption<bool,
-/// Scalarizer,
-/// &Scalarizer::ScalarizeLoadStore>();
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_OPTIONS_H
-#define LLVM_SUPPORT_OPTIONS_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Support/CommandLine.h"
-
-namespace llvm {
-
-namespace detail {
-
-// Options are keyed of the unique address of a static character synthesized
-// based on template arguments.
-template <typename ValT, typename Base, ValT(Base::*Mem)> class OptionKey {
-public:
- static char ID;
-};
-
-template <typename ValT, typename Base, ValT(Base::*Mem)>
-char OptionKey<ValT, Base, Mem>::ID = 0;
-
-} // namespace detail
-
-/// Singleton class used to register debug options.
-///
-/// The OptionRegistry is responsible for managing lifetimes of the options and
-/// provides interfaces for option registration and reading values from options.
-/// This object is a singleton, only one instance should ever exist so that all
-/// options are registered in the same place.
-class OptionRegistry {
-private:
- DenseMap<void *, cl::Option *> Options;
-
- /// Adds a cl::Option to the registry.
- ///
- /// \param Key unique key for option
- /// \param O option to map to \p Key
- ///
- /// Allocated cl::Options are owned by the OptionRegistry and are deallocated
- /// on destruction or removal
- void addOption(void *Key, cl::Option *O);
-
-public:
- ~OptionRegistry();
- OptionRegistry() {}
-
- /// Returns a reference to the singleton instance.
- static OptionRegistry &instance();
-
- /// Registers an option with the OptionRegistry singleton.
- ///
- /// \tparam ValT type of the option's data
- /// \tparam Base class used to key the option
- /// \tparam Mem member of \p Base used for keying the option
- ///
- /// Options are keyed off the template parameters to generate unique static
- /// characters. The template parameters are (1) the type of the data the
- /// option stores (\p ValT), the class that will read the option (\p Base),
- /// and the member that the class will store the data into (\p Mem).
- template <typename ValT, typename Base, ValT(Base::*Mem)>
- static void registerOption(StringRef ArgStr, StringRef Desc,
- const ValT &InitValue) {
- cl::opt<ValT> *Option = new cl::opt<ValT>(ArgStr, cl::desc(Desc),
- cl::Hidden, cl::init(InitValue));
- instance().addOption(&detail::OptionKey<ValT, Base, Mem>::ID, Option);
- }
-
- /// Returns the value of the option.
- ///
- /// \tparam ValT type of the option's data
- /// \tparam Base class used to key the option
- /// \tparam Mem member of \p Base used for keying the option
- ///
- /// Reads option values based on the key generated by the template parameters.
- /// Keying for get() is the same as keying for registerOption.
- template <typename ValT, typename Base, ValT(Base::*Mem)> ValT get() const {
- auto It = Options.find(&detail::OptionKey<ValT, Base, Mem>::ID);
- assert(It != Options.end() && "Option not in OptionRegistry");
- return *(cl::opt<ValT> *)It->second;
- }
-};
-
-} // namespace llvm
-
-#endif
diff --git a/linux-x64/clang/include/llvm/Support/Parallel.h b/linux-x64/clang/include/llvm/Support/Parallel.h
index eab9b49..d2f0067 100644
--- a/linux-x64/clang/include/llvm/Support/Parallel.h
+++ b/linux-x64/clang/include/llvm/Support/Parallel.h
@@ -11,35 +11,23 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Threading.h"
#include <algorithm>
#include <condition_variable>
#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 {
-struct sequential_execution_policy {};
-struct parallel_execution_policy {};
-template <typename T>
-struct is_execution_policy
- : public std::integral_constant<
- bool, llvm::is_one_of<T, sequential_execution_policy,
- parallel_execution_policy>::value> {};
-
-constexpr sequential_execution_policy seq{};
-constexpr parallel_execution_policy par{};
+// Strategy for the default executor used by the parallel routines provided by
+// this file. It defaults to using all hardware threads and should be
+// initialized before the first use of parallel routines.
+extern ThreadPoolStrategy strategy;
namespace detail {
@@ -84,23 +72,6 @@
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.
@@ -150,13 +121,17 @@
llvm::Log2_64(std::distance(Start, End)) + 1);
}
+// TaskGroup has a relatively high overhead, so we want to reduce
+// the number of spawn() calls. We'll create up to 1024 tasks here.
+// (Note that 1024 is an arbitrary number. This code probably needs
+// improving to take the number of available cores into account.)
+enum { MaxTasksPerGroup = 1024 };
+
template <class IterTy, class FuncTy>
void parallel_for_each(IterTy Begin, IterTy End, FuncTy Fn) {
- // TaskGroup has a relatively high overhead, so we want to reduce
- // the number of spawn() calls. We'll create up to 1024 tasks here.
- // (Note that 1024 is an arbitrary number. This code probably needs
- // improving to take the number of available cores into account.)
- ptrdiff_t TaskSize = std::distance(Begin, End) / 1024;
+ // Limit the number of tasks to MaxTasksPerGroup to limit job scheduling
+ // overhead on large inputs.
+ ptrdiff_t TaskSize = std::distance(Begin, End) / MaxTasksPerGroup;
if (TaskSize == 0)
TaskSize = 1;
@@ -170,7 +145,9 @@
template <class IndexTy, class FuncTy>
void parallel_for_each_n(IndexTy Begin, IndexTy End, FuncTy Fn) {
- ptrdiff_t TaskSize = (End - Begin) / 1024;
+ // Limit the number of tasks to MaxTasksPerGroup to limit job scheduling
+ // overhead on large inputs.
+ ptrdiff_t TaskSize = (End - Begin) / MaxTasksPerGroup;
if (TaskSize == 0)
TaskSize = 1;
@@ -186,65 +163,145 @@
Fn(J);
}
-#endif
+template <class IterTy, class ResultTy, class ReduceFuncTy,
+ class TransformFuncTy>
+ResultTy parallel_transform_reduce(IterTy Begin, IterTy End, ResultTy Init,
+ ReduceFuncTy Reduce,
+ TransformFuncTy Transform) {
+ // Limit the number of tasks to MaxTasksPerGroup to limit job scheduling
+ // overhead on large inputs.
+ size_t NumInputs = std::distance(Begin, End);
+ if (NumInputs == 0)
+ return std::move(Init);
+ size_t NumTasks = std::min(static_cast<size_t>(MaxTasksPerGroup), NumInputs);
+ std::vector<ResultTy> Results(NumTasks, Init);
+ {
+ // Each task processes either TaskSize or TaskSize+1 inputs. Any inputs
+ // remaining after dividing them equally amongst tasks are distributed as
+ // one extra input over the first tasks.
+ TaskGroup TG;
+ size_t TaskSize = NumInputs / NumTasks;
+ size_t RemainingInputs = NumInputs % NumTasks;
+ IterTy TBegin = Begin;
+ for (size_t TaskId = 0; TaskId < NumTasks; ++TaskId) {
+ IterTy TEnd = TBegin + TaskSize + (TaskId < RemainingInputs ? 1 : 0);
+ TG.spawn([=, &Transform, &Reduce, &Results] {
+ // Reduce the result of transformation eagerly within each task.
+ ResultTy R = Init;
+ for (IterTy It = TBegin; It != TEnd; ++It)
+ R = Reduce(R, Transform(*It));
+ Results[TaskId] = R;
+ });
+ TBegin = TEnd;
+ }
+ assert(TBegin == End);
+ }
+
+ // Do a final reduction. There are at most 1024 tasks, so this only adds
+ // constant single-threaded overhead for large inputs. Hopefully most
+ // reductions are cheaper than the transformation.
+ ResultTy FinalResult = std::move(Results.front());
+ for (ResultTy &PartialResult :
+ makeMutableArrayRef(Results.data() + 1, Results.size() - 1))
+ FinalResult = Reduce(FinalResult, std::move(PartialResult));
+ return std::move(FinalResult);
+}
#endif
-template <typename Iter>
-using DefComparator =
- std::less<typename std::iterator_traits<Iter>::value_type>;
-
} // namespace detail
+} // namespace parallel
-// sequential algorithm implementations.
-template <class Policy, class RandomAccessIterator,
- class Comparator = detail::DefComparator<RandomAccessIterator>>
-void sort(Policy policy, RandomAccessIterator Start, RandomAccessIterator End,
- const Comparator &Comp = Comparator()) {
- static_assert(is_execution_policy<Policy>::value,
- "Invalid execution policy!");
+template <class RandomAccessIterator,
+ class Comparator = std::less<
+ typename std::iterator_traits<RandomAccessIterator>::value_type>>
+void parallelSort(RandomAccessIterator Start, RandomAccessIterator End,
+ const Comparator &Comp = Comparator()) {
+#if LLVM_ENABLE_THREADS
+ if (parallel::strategy.ThreadsRequested != 1) {
+ parallel::detail::parallel_sort(Start, End, Comp);
+ return;
+ }
+#endif
llvm::sort(Start, End, Comp);
}
-template <class Policy, class IterTy, class FuncTy>
-void for_each(Policy policy, IterTy Begin, IterTy End, FuncTy Fn) {
- static_assert(is_execution_policy<Policy>::value,
- "Invalid execution policy!");
+template <class IterTy, class FuncTy>
+void parallelForEach(IterTy Begin, IterTy End, FuncTy Fn) {
+#if LLVM_ENABLE_THREADS
+ if (parallel::strategy.ThreadsRequested != 1) {
+ parallel::detail::parallel_for_each(Begin, End, Fn);
+ return;
+ }
+#endif
std::for_each(Begin, End, Fn);
}
-template <class Policy, class IndexTy, class FuncTy>
-void for_each_n(Policy policy, IndexTy Begin, IndexTy End, FuncTy Fn) {
- static_assert(is_execution_policy<Policy>::value,
- "Invalid execution policy!");
- for (IndexTy I = Begin; I != End; ++I)
+template <class FuncTy>
+void parallelForEachN(size_t Begin, size_t End, FuncTy Fn) {
+#if LLVM_ENABLE_THREADS
+ if (parallel::strategy.ThreadsRequested != 1) {
+ parallel::detail::parallel_for_each_n(Begin, End, Fn);
+ return;
+ }
+#endif
+ for (size_t I = Begin; I != End; ++I)
Fn(I);
}
-// Parallel algorithm implementations, only available when LLVM_ENABLE_THREADS
-// is true.
+template <class IterTy, class ResultTy, class ReduceFuncTy,
+ class TransformFuncTy>
+ResultTy parallelTransformReduce(IterTy Begin, IterTy End, ResultTy Init,
+ ReduceFuncTy Reduce,
+ TransformFuncTy Transform) {
#if LLVM_ENABLE_THREADS
-template <class RandomAccessIterator,
- class Comparator = detail::DefComparator<RandomAccessIterator>>
-void sort(parallel_execution_policy policy, RandomAccessIterator Start,
- RandomAccessIterator End, const Comparator &Comp = Comparator()) {
- detail::parallel_sort(Start, End, Comp);
-}
-
-template <class IterTy, class FuncTy>
-void for_each(parallel_execution_policy policy, IterTy Begin, IterTy End,
- FuncTy Fn) {
- detail::parallel_for_each(Begin, End, Fn);
-}
-
-template <class IndexTy, class FuncTy>
-void for_each_n(parallel_execution_policy policy, IndexTy Begin, IndexTy End,
- FuncTy Fn) {
- detail::parallel_for_each_n(Begin, End, Fn);
-}
+ if (parallel::strategy.ThreadsRequested != 1) {
+ return parallel::detail::parallel_transform_reduce(Begin, End, Init, Reduce,
+ Transform);
+ }
#endif
+ for (IterTy I = Begin; I != End; ++I)
+ Init = Reduce(std::move(Init), Transform(*I));
+ return std::move(Init);
+}
-} // namespace parallel
+// Range wrappers.
+template <class RangeTy,
+ class Comparator = std::less<decltype(*std::begin(RangeTy()))>>
+void parallelSort(RangeTy &&R, const Comparator &Comp = Comparator()) {
+ parallelSort(std::begin(R), std::end(R), Comp);
+}
+
+template <class RangeTy, class FuncTy>
+void parallelForEach(RangeTy &&R, FuncTy Fn) {
+ parallelForEach(std::begin(R), std::end(R), Fn);
+}
+
+template <class RangeTy, class ResultTy, class ReduceFuncTy,
+ class TransformFuncTy>
+ResultTy parallelTransformReduce(RangeTy &&R, ResultTy Init,
+ ReduceFuncTy Reduce,
+ TransformFuncTy Transform) {
+ return parallelTransformReduce(std::begin(R), std::end(R), Init, Reduce,
+ Transform);
+}
+
+// Parallel for-each, but with error handling.
+template <class RangeTy, class FuncTy>
+Error parallelForEachError(RangeTy &&R, FuncTy Fn) {
+ // The transform_reduce algorithm requires that the initial value be copyable.
+ // Error objects are uncopyable. We only need to copy initial success values,
+ // so work around this mismatch via the C API. The C API represents success
+ // values with a null pointer. The joinErrors discards null values and joins
+ // multiple errors into an ErrorList.
+ return unwrap(parallelTransformReduce(
+ std::begin(R), std::end(R), wrap(Error::success()),
+ [](LLVMErrorRef Lhs, LLVMErrorRef Rhs) {
+ return wrap(joinErrors(unwrap(Lhs), unwrap(Rhs)));
+ },
+ [&Fn](auto &&V) { return wrap(Fn(V)); }));
+}
+
} // namespace llvm
#endif // LLVM_SUPPORT_PARALLEL_H
diff --git a/linux-x64/clang/include/llvm/Support/Path.h b/linux-x64/clang/include/llvm/Support/Path.h
index 5c0bee5..af70e08 100644
--- a/linux-x64/clang/include/llvm/Support/Path.h
+++ b/linux-x64/clang/include/llvm/Support/Path.h
@@ -47,15 +47,15 @@
/// foo/ => foo,.
/// /foo/bar => /,foo,bar
/// ../ => ..,.
-/// C:\foo\bar => C:,/,foo,bar
+/// C:\foo\bar => C:,\,foo,bar
/// @endcode
class const_iterator
: public iterator_facade_base<const_iterator, std::input_iterator_tag,
const StringRef> {
- StringRef Path; ///< The entire path.
- StringRef Component; ///< The current component. Not necessarily in Path.
- size_t Position; ///< The iterators current position within Path.
- Style S; ///< The path style to use.
+ StringRef Path; ///< The entire path.
+ StringRef Component; ///< The current component. Not necessarily in Path.
+ size_t Position = 0; ///< The iterators current position within Path.
+ Style S = Style::native; ///< The path style to use.
// An end iterator has Position = Path.size() + 1.
friend const_iterator begin(StringRef path, Style style);
@@ -78,10 +78,10 @@
class reverse_iterator
: public iterator_facade_base<reverse_iterator, std::input_iterator_tag,
const StringRef> {
- StringRef Path; ///< The entire path.
- StringRef Component; ///< The current component. Not necessarily in Path.
- size_t Position; ///< The iterators current position within Path.
- Style S; ///< The path style to use.
+ StringRef Path; ///< The entire path.
+ StringRef Component; ///< The current component. Not necessarily in Path.
+ size_t Position = 0; ///< The iterators current position within Path.
+ Style S = Style::native; ///< The path style to use.
friend reverse_iterator rbegin(StringRef path, Style style);
friend reverse_iterator rend(StringRef path);
@@ -121,6 +121,8 @@
/// Remove the last component from \a path unless it is the root dir.
///
+/// Similar to the POSIX "dirname" utility.
+///
/// @code
/// directory/filename.cpp => directory/
/// directory/ => directory
@@ -150,8 +152,14 @@
///
/// @code
/// /foo, /old, /new => /foo
+/// /old, /old, /new => /new
+/// /old, /old/, /new => /old
/// /old/foo, /old, /new => /new/foo
+/// /old/foo, /old/, /new => /new/foo
+/// /old/foo, /old/, /new/ => /new/foo
+/// /oldfoo, /old, /new => /oldfoo
/// /foo, <empty>, /new => /new/foo
+/// /foo, <empty>, new => new/foo
/// /old/foo, /old, <empty> => /foo
/// @endcode
///
@@ -159,8 +167,11 @@
/// start with \a NewPrefix.
/// @param OldPrefix The path prefix to strip from \a Path.
/// @param NewPrefix The path prefix to replace \a NewPrefix with.
-void replace_path_prefix(SmallVectorImpl<char> &Path,
- const StringRef &OldPrefix, const StringRef &NewPrefix,
+/// @param style The style used to match the prefix. Exact match using
+/// Posix style, case/separator insensitive match for Windows style.
+/// @result true if \a Path begins with OldPrefix
+bool replace_path_prefix(SmallVectorImpl<char> &Path, StringRef OldPrefix,
+ StringRef NewPrefix,
Style style = Style::native);
/// Append to path.
@@ -295,7 +306,7 @@
///
/// @param path Input path.
/// @result The filename part of \a path. This is defined as the last component
-/// of \a path.
+/// of \a path. Similar to the POSIX "basename" utility.
StringRef filename(StringRef path, Style style = Style::native);
/// Get stem.
@@ -360,6 +371,20 @@
/// @result True if a home directory is set, false otherwise.
bool home_directory(SmallVectorImpl<char> &result);
+/// Get the directory where packages should read user-specific configurations.
+/// e.g. $XDG_CONFIG_HOME.
+///
+/// @param result Holds the resulting path name.
+/// @result True if the appropriate path was determined, it need not exist.
+bool user_config_directory(SmallVectorImpl<char> &result);
+
+/// Get the directory where installed packages should put their
+/// machine-local cache, e.g. $XDG_CACHE_HOME.
+///
+/// @param result Holds the resulting path name.
+/// @result True if the appropriate path was determined, it need not exist.
+bool cache_directory(SmallVectorImpl<char> &result);
+
/// Has root name?
///
/// root_name != ""
@@ -426,10 +451,48 @@
/// Is path absolute?
///
+/// According to cppreference.com, C++17 states: "An absolute path is a path
+/// that unambiguously identifies the location of a file without reference to
+/// an additional starting location."
+///
+/// In other words, the rules are:
+/// 1) POSIX style paths with nonempty root directory are absolute.
+/// 2) Windows style paths with nonempty root name and root directory are
+/// absolute.
+/// 3) No other paths are absolute.
+///
+/// \see has_root_name
+/// \see has_root_directory
+///
/// @param path Input path.
/// @result True if the path is absolute, false if it is not.
bool is_absolute(const Twine &path, Style style = Style::native);
+/// Is path absolute using GNU rules?
+///
+/// GNU rules are:
+/// 1) Paths starting with a path separator are absolute.
+/// 2) Windows style paths are also absolute if they start with a character
+/// followed by ':'.
+/// 3) No other paths are absolute.
+///
+/// On Windows style the path "C:\Users\Default" has "C:" as root name and "\"
+/// as root directory.
+///
+/// Hence "C:" on Windows is absolute under GNU rules and not absolute under
+/// C++17 because it has no root directory. Likewise "/" and "\" on Windows are
+/// absolute under GNU and are not absolute under C++17 due to empty root name.
+///
+/// \see has_root_name
+/// \see has_root_directory
+///
+/// @param path Input path.
+/// @param style The style of \p path (e.g. Windows or POSIX). "native" style
+/// means to derive the style from the host.
+/// @result True if the path is absolute following GNU rules, false if it is
+/// not.
+bool is_absolute_gnu(const Twine &path, Style style = Style::native);
+
/// Is path relative?
///
/// @param path Input path.
@@ -451,10 +514,6 @@
bool remove_dots(SmallVectorImpl<char> &path, bool remove_dot_dot = false,
Style style = Style::native);
-#if defined(_WIN32)
-std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16);
-#endif
-
} // end namespace path
} // end namespace sys
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/Support/PluginLoader.h b/linux-x64/clang/include/llvm/Support/PluginLoader.h
index c0c516b..95c087f 100644
--- a/linux-x64/clang/include/llvm/Support/PluginLoader.h
+++ b/linux-x64/clang/include/llvm/Support/PluginLoader.h
@@ -16,7 +16,11 @@
#ifndef LLVM_SUPPORT_PLUGINLOADER_H
#define LLVM_SUPPORT_PLUGINLOADER_H
+#ifndef DONT_GET_PLUGIN_LOADER_OPTION
#include "llvm/Support/CommandLine.h"
+#endif
+
+#include <string>
namespace llvm {
struct PluginLoader {
diff --git a/linux-x64/clang/include/llvm/Support/PointerLikeTypeTraits.h b/linux-x64/clang/include/llvm/Support/PointerLikeTypeTraits.h
index 1e7e5b5..1b15f93 100644
--- a/linux-x64/clang/include/llvm/Support/PointerLikeTypeTraits.h
+++ b/linux-x64/clang/include/llvm/Support/PointerLikeTypeTraits.h
@@ -15,7 +15,7 @@
#define LLVM_SUPPORT_POINTERLIKETYPETRAITS_H
#include "llvm/Support/DataTypes.h"
-#include <assert.h>
+#include <cassert>
#include <type_traits>
namespace llvm {
@@ -37,8 +37,9 @@
};
// sizeof(T) is valid only for a complete T.
-template <typename T> struct HasPointerLikeTypeTraits<
- T, decltype((sizeof(PointerLikeTypeTraits<T>) + sizeof(T)), void())> {
+template <typename T>
+struct HasPointerLikeTypeTraits<
+ T, decltype((sizeof(PointerLikeTypeTraits<T>) + sizeof(T)), void())> {
static const bool value = true;
};
@@ -56,7 +57,8 @@
static inline void *getAsVoidPointer(T *P) { return P; }
static inline T *getFromVoidPointer(void *P) { return static_cast<T *>(P); }
- enum { NumLowBitsAvailable = detail::ConstantLog2<alignof(T)>::value };
+ static constexpr int NumLowBitsAvailable =
+ detail::ConstantLog2<alignof(T)>::value;
};
template <> struct PointerLikeTypeTraits<void *> {
@@ -70,7 +72,7 @@
///
/// All clients should use assertions to do a run-time check to ensure that
/// this is actually true.
- enum { NumLowBitsAvailable = 2 };
+ static constexpr int NumLowBitsAvailable = 2;
};
// Provide PointerLikeTypeTraits for const things.
@@ -83,7 +85,7 @@
static inline const T getFromVoidPointer(const void *P) {
return NonConst::getFromVoidPointer(const_cast<void *>(P));
}
- enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable };
+ static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable;
};
// Provide PointerLikeTypeTraits for const pointers.
@@ -96,7 +98,7 @@
static inline const T *getFromVoidPointer(const void *P) {
return NonConst::getFromVoidPointer(const_cast<void *>(P));
}
- enum { NumLowBitsAvailable = NonConst::NumLowBitsAvailable };
+ static constexpr int NumLowBitsAvailable = NonConst::NumLowBitsAvailable;
};
// Provide PointerLikeTypeTraits for uintptr_t.
@@ -108,7 +110,7 @@
return reinterpret_cast<uintptr_t>(P);
}
// No bits are available!
- enum { NumLowBitsAvailable = 0 };
+ static constexpr int NumLowBitsAvailable = 0;
};
/// Provide suitable custom traits struct for function pointers.
@@ -121,7 +123,8 @@
/// potentially use alignment attributes on functions to satisfy that.
template <int Alignment, typename FunctionPointerT>
struct FunctionPointerLikeTypeTraits {
- enum { NumLowBitsAvailable = detail::ConstantLog2<Alignment>::value };
+ static constexpr int NumLowBitsAvailable =
+ detail::ConstantLog2<Alignment>::value;
static inline void *getAsVoidPointer(FunctionPointerT P) {
assert((reinterpret_cast<uintptr_t>(P) &
~((uintptr_t)-1 << NumLowBitsAvailable)) == 0 &&
diff --git a/linux-x64/clang/include/llvm/Support/PrettyStackTrace.h b/linux-x64/clang/include/llvm/Support/PrettyStackTrace.h
index f6ed7c9..ac25cff 100644
--- a/linux-x64/clang/include/llvm/Support/PrettyStackTrace.h
+++ b/linux-x64/clang/include/llvm/Support/PrettyStackTrace.h
@@ -21,8 +21,29 @@
namespace llvm {
class raw_ostream;
+ /// Enables dumping a "pretty" stack trace when the program crashes.
+ ///
+ /// \see PrettyStackTraceEntry
void EnablePrettyStackTrace();
+ /// Enables (or disables) dumping a "pretty" stack trace when the user sends
+ /// SIGINFO or SIGUSR1 to the current process.
+ ///
+ /// This is a per-thread decision so that a program can choose to print stack
+ /// traces only on a primary thread, or on all threads that use
+ /// PrettyStackTraceEntry.
+ ///
+ /// \see EnablePrettyStackTrace
+ /// \see PrettyStackTraceEntry
+ void EnablePrettyStackTraceOnSigInfoForThisThread(bool ShouldEnable = true);
+
+ /// Replaces the generic bug report message that is output upon
+ /// a crash.
+ void setBugReportMsg(const char *Msg);
+
+ /// Get the bug report message that will be output upon a crash.
+ const char *getBugReportMsg();
+
/// PrettyStackTraceEntry - This class is used to represent a frame of the
/// "pretty" stack trace that is dumped when a program crashes. You can define
/// subclasses of this and declare them on the program stack: when they are
diff --git a/linux-x64/clang/include/llvm/Support/Process.h b/linux-x64/clang/include/llvm/Support/Process.h
index 67e3791..729917b 100644
--- a/linux-x64/clang/include/llvm/Support/Process.h
+++ b/linux-x64/clang/include/llvm/Support/Process.h
@@ -25,10 +25,11 @@
#define LLVM_SUPPORT_PROCESS_H
#include "llvm/ADT/Optional.h"
-#include "llvm/Support/Allocator.h"
+#include "llvm/Support/AllocatorBase.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/Program.h"
#include <system_error>
namespace llvm {
@@ -42,6 +43,11 @@
/// current executing process.
class Process {
public:
+ using Pid = int32_t;
+
+ /// Get the process's identifier.
+ static Pid getProcessId();
+
/// Get the process's page size.
/// This may fail if the underlying syscall returns an error. In most cases,
/// page size information is used for optimization, and this error can be
@@ -102,10 +108,12 @@
/// considered.
static Optional<std::string> FindInEnvPath(StringRef EnvName,
StringRef FileName,
- ArrayRef<std::string> IgnoreList);
+ ArrayRef<std::string> IgnoreList,
+ char Separator = EnvPathSeparator);
static Optional<std::string> FindInEnvPath(StringRef EnvName,
- StringRef FileName);
+ StringRef FileName,
+ char Separator = EnvPathSeparator);
// This functions ensures that the standard file descriptors (input, output,
// and error) are properly mapped to a file descriptor before we use any of
@@ -201,6 +209,13 @@
/// Get the result of a process wide random number generator. The
/// generator will be automatically seeded in non-deterministic fashion.
static unsigned GetRandomNumber();
+
+ /// Equivalent to ::exit(), except when running inside a CrashRecoveryContext.
+ /// In that case, the control flow will resume after RunSafely(), like for a
+ /// crash, rather than exiting the current process.
+ /// Use \arg NoCleanup for calling _exit() instead of exit().
+ LLVM_ATTRIBUTE_NORETURN
+ static void Exit(int RetCode, bool NoCleanup = false);
};
}
diff --git a/linux-x64/clang/include/llvm/Support/Program.h b/linux-x64/clang/include/llvm/Support/Program.h
index 6b2315c..bfd2719 100644
--- a/linux-x64/clang/include/llvm/Support/Program.h
+++ b/linux-x64/clang/include/llvm/Support/Program.h
@@ -14,10 +14,12 @@
#define LLVM_SUPPORT_PROGRAM_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/ErrorOr.h"
+#include <chrono>
#include <system_error>
namespace llvm {
@@ -35,7 +37,7 @@
typedef unsigned long procid_t; // Must match the type of DWORD on Windows.
typedef void *process_t; // Must match the type of HANDLE on Windows.
#else
- typedef pid_t procid_t;
+ typedef ::pid_t procid_t;
typedef procid_t process_t;
#endif
@@ -52,6 +54,13 @@
ProcessInfo();
};
+ /// This struct encapsulates information about a process execution.
+ struct ProcessStatistics {
+ std::chrono::microseconds TotalTime;
+ std::chrono::microseconds UserTime;
+ uint64_t PeakMemory = 0; ///< Maximum resident set size in KiB.
+ };
+
/// Find the first executable file \p Name in \p Paths.
///
/// This does not perform hashing as a shell would but instead stats each PATH
@@ -116,10 +125,16 @@
///< string instance in which error messages will be returned. If the
///< string is non-empty upon return an error occurred while invoking the
///< program.
- bool *ExecutionFailed = nullptr);
+ bool *ExecutionFailed = nullptr,
+ Optional<ProcessStatistics> *ProcStat = nullptr, ///< If non-zero,
+ /// provides a pointer to a structure in which process execution
+ /// statistics will be stored.
+ BitVector *AffinityMask = nullptr ///< CPUs or processors the new
+ /// program shall run on.
+ );
/// Similar to ExecuteAndWait, but returns immediately.
- /// @returns The \see ProcessInfo of the newly launced process.
+ /// @returns The \see ProcessInfo of the newly launched process.
/// \note On Microsoft Windows systems, users will need to either call
/// \see Wait until the process finished execution or win32 CloseHandle() API
/// on ProcessInfo.ProcessHandle to avoid memory leaks.
@@ -128,7 +143,8 @@
ArrayRef<Optional<StringRef>> Redirects = {},
unsigned MemoryLimit = 0,
std::string *ErrMsg = nullptr,
- bool *ExecutionFailed = nullptr);
+ bool *ExecutionFailed = nullptr,
+ BitVector *AffinityMask = nullptr);
/// Return true if the given arguments fit within system-specific
/// argument length limits.
@@ -182,25 +198,31 @@
/// \note Users of this function should always check the ReturnCode member of
/// the \see ProcessInfo returned from this function.
ProcessInfo Wait(
- const ProcessInfo &PI, ///< The child process that should be waited on.
+ const ProcessInfo &PI, ///< The child process that should be waited on.
unsigned SecondsToWait, ///< If non-zero, this specifies the amount of
///< time to wait for the child process to exit. If the time expires, the
///< child is killed and this function returns. If zero, this function
///< will perform a non-blocking wait on the child process.
bool WaitUntilTerminates, ///< If true, ignores \p SecondsToWait and waits
///< until child has terminated.
- std::string *ErrMsg = nullptr ///< If non-zero, provides a pointer to a
+ std::string *ErrMsg = nullptr, ///< If non-zero, provides a pointer to a
///< string instance in which error messages will be returned. If the
///< string is non-empty upon return an error occurred while invoking the
///< program.
- );
+ Optional<ProcessStatistics> *ProcStat = nullptr ///< If non-zero, provides
+ /// a pointer to a structure in which process execution statistics will be
+ /// stored.
+ );
+
+ /// Print a command argument, and optionally quote it.
+ void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote);
#if defined(_WIN32)
/// Given a list of command line arguments, quote and escape them as necessary
/// to build a single flat command line appropriate for calling CreateProcess
/// on
/// Windows.
- std::string flattenWindowsCommandLine(ArrayRef<StringRef> Args);
+ ErrorOr<std::wstring> flattenWindowsCommandLine(ArrayRef<StringRef> Args);
#endif
}
}
diff --git a/linux-x64/clang/include/llvm/Support/RISCVAttributeParser.h b/linux-x64/clang/include/llvm/Support/RISCVAttributeParser.h
new file mode 100644
index 0000000..3e62941
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/RISCVAttributeParser.h
@@ -0,0 +1,37 @@
+//===-- RISCVAttributeParser.h - RISCV Attribute Parser ---------*- 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_RISCVATTRIBUTEPARSER_H
+#define LLVM_SUPPORT_RISCVATTRIBUTEPARSER_H
+
+#include "llvm/Support/ELFAttributeParser.h"
+#include "llvm/Support/RISCVAttributes.h"
+
+namespace llvm {
+class RISCVAttributeParser : public ELFAttributeParser {
+ struct DisplayHandler {
+ RISCVAttrs::AttrType attribute;
+ Error (RISCVAttributeParser::*routine)(unsigned);
+ };
+ static const DisplayHandler displayRoutines[];
+
+ Error handler(uint64_t tag, bool &handled) override;
+
+ Error unalignedAccess(unsigned tag);
+ Error stackAlign(unsigned tag);
+
+public:
+ RISCVAttributeParser(ScopedPrinter *sw)
+ : ELFAttributeParser(sw, RISCVAttrs::RISCVAttributeTags, "riscv") {}
+ RISCVAttributeParser()
+ : ELFAttributeParser(RISCVAttrs::RISCVAttributeTags, "riscv") {}
+};
+
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/RISCVAttributes.h b/linux-x64/clang/include/llvm/Support/RISCVAttributes.h
new file mode 100644
index 0000000..caded95
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/RISCVAttributes.h
@@ -0,0 +1,44 @@
+//===-- RISCVAttributes.h - RISCV Attributes --------------------*- 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 enumerations for RISCV attributes as defined in RISC-V
+// ELF psABI specification.
+//
+// RISC-V ELF psABI specification
+//
+// https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_SUPPORT_RISCVATTRIBUTES_H
+#define LLVM_SUPPORT_RISCVATTRIBUTES_H
+
+#include "llvm/Support/ELFAttributes.h"
+
+namespace llvm {
+namespace RISCVAttrs {
+
+extern const TagNameMap RISCVAttributeTags;
+
+enum AttrType : unsigned {
+ // Attribute types in ELF/.riscv.attributes.
+ STACK_ALIGN = 4,
+ ARCH = 5,
+ UNALIGNED_ACCESS = 6,
+ PRIV_SPEC = 8,
+ PRIV_SPEC_MINOR = 10,
+ PRIV_SPEC_REVISION = 12,
+};
+
+enum StackAlign { ALIGN_4 = 4, ALIGN_16 = 16 };
+
+enum { NOT_ALLOWED = 0, ALLOWED = 1 };
+
+} // namespace RISCVAttrs
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/RISCVTargetParser.def b/linux-x64/clang/include/llvm/Support/RISCVTargetParser.def
new file mode 100644
index 0000000..6a06f92
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/RISCVTargetParser.def
@@ -0,0 +1,27 @@
+#ifndef PROC_ALIAS
+#define PROC_ALIAS(NAME, RV32, RV64)
+#endif
+
+PROC_ALIAS("generic", "generic-rv32", "generic-rv64")
+PROC_ALIAS("rocket", "rocket-rv32", "rocket-rv64")
+PROC_ALIAS("sifive-7-series", "sifive-7-rv32", "sifive-7-rv64")
+
+#undef PROC_ALIAS
+
+#ifndef PROC
+#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH)
+#endif
+
+PROC(INVALID, {"invalid"}, FK_INVALID, {""})
+PROC(GENERIC_RV32, {"generic-rv32"}, FK_NONE, {""})
+PROC(GENERIC_RV64, {"generic-rv64"}, FK_64BIT, {""})
+PROC(ROCKET_RV32, {"rocket-rv32"}, FK_NONE, {""})
+PROC(ROCKET_RV64, {"rocket-rv64"}, FK_64BIT, {""})
+PROC(SIFIVE_732, {"sifive-7-rv32"}, FK_NONE, {""})
+PROC(SIFIVE_764, {"sifive-7-rv64"}, FK_64BIT, {""})
+PROC(SIFIVE_E31, {"sifive-e31"}, FK_NONE, {"rv32imac"})
+PROC(SIFIVE_U54, {"sifive-u54"}, FK_64BIT, {"rv64gc"})
+PROC(SIFIVE_E76, {"sifive-e76"}, FK_NONE, {"rv32imafc"})
+PROC(SIFIVE_U74, {"sifive-u74"}, FK_64BIT, {"rv64gc"})
+
+#undef PROC
diff --git a/linux-x64/clang/include/llvm/Support/RWMutex.h b/linux-x64/clang/include/llvm/Support/RWMutex.h
index 9cd57cb..150bc7d 100644
--- a/linux-x64/clang/include/llvm/Support/RWMutex.h
+++ b/linux-x64/clang/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:
+#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();
- /// 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;
+ /// @}
- /// @}
- /// @name Do Not Implement
- /// @{
- RWMutexImpl(const RWMutexImpl & original) = delete;
- RWMutexImpl &operator=(const RWMutexImpl &) = delete;
- /// @}
+ /// Releases and removes the lock
+ /// Destructor
+ ~RWMutexImpl();
- /// 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();
- /// @}
- /// @name Methods
- /// @{
- public:
+ /// 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 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 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 reader mode.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally release the lock in reader mode.
- bool reader_release();
+ /// 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();
- /// 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:
+ //@}
+ /// @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 {
- RWMutexImpl impl;
- unsigned readers = 0;
- unsigned writers = 0;
+/// 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:
- explicit SmartRWMutex() = default;
- SmartRWMutex(const SmartRWMutex<mt_only> & original) = delete;
- SmartRWMutex<mt_only> &operator=(const SmartRWMutex<mt_only> &) = delete;
+public:
+ bool lock_shared() {
+ if (!mt_only || llvm_is_multithreaded()) {
+ impl.lock_shared();
+ return true;
+ }
- 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;
+ }
- // 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;
+ }
- 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;
+ }
- // 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;
+ }
- 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;
+ }
- // 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;
+ }
- 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;
+ }
+};
- // 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;
- 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;
- /// 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();
+ }
- explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
- mutex.lock_shared();
- }
+ ~SmartScopedReader() { mutex.unlock_shared(); }
+};
+#endif
+typedef SmartScopedReader<false> ScopedReader;
- ~SmartScopedReader() {
- mutex.unlock_shared();
- }
- };
+/// 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;
- typedef SmartScopedReader<false> ScopedReader;
+ explicit SmartScopedWriter(SmartRWMutex<mt_only> &m) : mutex(m) {
+ mutex.lock();
+ }
- /// 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;
+ ~SmartScopedWriter() { mutex.unlock(); }
+};
+#endif
+typedef SmartScopedWriter<false> ScopedWriter;
} // end namespace sys
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/Support/Regex.h b/linux-x64/clang/include/llvm/Support/Regex.h
index 2d19b10..ae4b951 100644
--- a/linux-x64/clang/include/llvm/Support/Regex.h
+++ b/linux-x64/clang/include/llvm/Support/Regex.h
@@ -16,6 +16,7 @@
#ifndef LLVM_SUPPORT_REGEX_H
#define LLVM_SUPPORT_REGEX_H
+#include "llvm/ADT/BitmaskEnum.h"
#include <string>
struct llvm_regex;
@@ -26,25 +27,31 @@
class Regex {
public:
- enum {
- NoFlags=0,
+ enum RegexFlags : unsigned {
+ NoFlags = 0,
/// Compile for matching that ignores upper/lower case distinctions.
- IgnoreCase=1,
+ IgnoreCase = 1,
/// Compile for newline-sensitive matching. With this flag '[^' bracket
/// expressions and '.' never match newline. A ^ anchor matches the
/// null string after any newline in the string in addition to its normal
/// function, and the $ anchor matches the null string before any
/// newline in the string in addition to its normal function.
- Newline=2,
+ Newline = 2,
/// By default, the POSIX extended regular expression (ERE) syntax is
/// assumed. Pass this flag to turn on basic regular expressions (BRE)
/// instead.
- BasicRegex=4
+ BasicRegex = 4,
+
+ LLVM_MARK_AS_BITMASK_ENUM(BasicRegex)
};
Regex();
/// Compiles the given regular expression \p Regex.
- Regex(StringRef Regex, unsigned Flags = NoFlags);
+ ///
+ /// \param Regex - referenced string is no longer needed after this
+ /// constructor does finish. Only its compiled form is kept stored.
+ Regex(StringRef Regex, RegexFlags Flags = NoFlags);
+ Regex(StringRef Regex, unsigned Flags);
Regex(const Regex &) = delete;
Regex &operator=(Regex regex) {
std::swap(preg, regex.preg);
@@ -54,9 +61,10 @@
Regex(Regex &®ex);
~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 +77,12 @@
/// 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 +93,9 @@
///
/// \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/linux-x64/clang/include/llvm/Support/Registry.h b/linux-x64/clang/include/llvm/Support/Registry.h
index 4d8aa5f..5bb6a25 100644
--- a/linux-x64/clang/include/llvm/Support/Registry.h
+++ b/linux-x64/clang/include/llvm/Support/Registry.h
@@ -115,7 +115,7 @@
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/linux-x64/clang/include/llvm/Support/SHA1.h b/linux-x64/clang/include/llvm/Support/SHA1.h
index 87fe94b..efd8513 100644
--- a/linux-x64/clang/include/llvm/Support/SHA1.h
+++ b/linux-x64/clang/include/llvm/Support/SHA1.h
@@ -15,8 +15,6 @@
#ifndef LLVM_SUPPORT_SHA1_H
#define LLVM_SUPPORT_SHA1_H
-#include "llvm/ADT/ArrayRef.h"
-
#include <array>
#include <cstdint>
@@ -36,10 +34,7 @@
void update(ArrayRef<uint8_t> Data);
/// Digest more data.
- void update(StringRef Str) {
- update(ArrayRef<uint8_t>((uint8_t *)const_cast<char *>(Str.data()),
- Str.size()));
- }
+ void update(StringRef Str);
/// Return a reference to the current raw 160-bits SHA1 for the digested data
/// since the last call to init(). This call will add data to the internal
diff --git a/linux-x64/clang/include/llvm/Support/ScalableSize.h b/linux-x64/clang/include/llvm/Support/ScalableSize.h
deleted file mode 100644
index 96bf043..0000000
--- a/linux-x64/clang/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/linux-x64/clang/include/llvm/Support/ScaledNumber.h b/linux-x64/clang/include/llvm/Support/ScaledNumber.h
index 552da34..a5261e4 100644
--- a/linux-x64/clang/include/llvm/Support/ScaledNumber.h
+++ b/linux-x64/clang/include/llvm/Support/ScaledNumber.h
@@ -418,7 +418,7 @@
class raw_ostream;
class ScaledNumberBase {
public:
- static const int DefaultPrecision = 10;
+ static constexpr int DefaultPrecision = 10;
static void dump(uint64_t D, int16_t E, int Width);
static raw_ostream &print(raw_ostream &OS, uint64_t D, int16_t E, int Width,
@@ -499,7 +499,7 @@
private:
typedef std::numeric_limits<DigitsType> DigitsLimits;
- static const int Width = sizeof(DigitsType) * 8;
+ static constexpr int Width = sizeof(DigitsType) * 8;
static_assert(Width <= 64, "invalid integer width for digits");
private:
diff --git a/linux-x64/clang/include/llvm/Support/Signals.h b/linux-x64/clang/include/llvm/Support/Signals.h
index 9f2cb85..44f5a75 100644
--- a/linux-x64/clang/include/llvm/Support/Signals.h
+++ b/linux-x64/clang/include/llvm/Support/Signals.h
@@ -50,7 +50,9 @@
void DisableSystemDialogsOnCrash();
/// Print the stack trace using the given \c raw_ostream object.
- void PrintStackTrace(raw_ostream &OS);
+ /// \param Depth refers to the number of stackframes to print. If not
+ /// specified, the entire frame is printed.
+ void PrintStackTrace(raw_ostream &OS, int Depth = 0);
// Run all registered signal handlers.
void RunSignalHandlers();
@@ -65,13 +67,58 @@
/// This function registers a function to be called when the user "interrupts"
/// the program (typically by pressing ctrl-c). When the user interrupts the
/// program, the specified interrupt function is called instead of the program
- /// being killed, and the interrupt function automatically disabled. Note
- /// that interrupt functions are not allowed to call any non-reentrant
+ /// being killed, and the interrupt function automatically disabled.
+ ///
+ /// Note that interrupt functions are not allowed to call any non-reentrant
/// functions. An null interrupt function pointer disables the current
/// installed function. Note also that the handler may be executed on a
/// different thread on some platforms.
- /// Register a function to be called when ctrl-c is pressed.
void SetInterruptFunction(void (*IF)());
+
+ /// Registers a function to be called when an "info" signal is delivered to
+ /// the process.
+ ///
+ /// On POSIX systems, this will be SIGUSR1; on systems that have it, SIGINFO
+ /// will also be used (typically ctrl-t).
+ ///
+ /// Note that signal handlers are not allowed to call any non-reentrant
+ /// functions. An null function pointer disables the current installed
+ /// 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 in a "one-shot" manner when a pipe
+ /// signal is delivered to the process (i.e., on a failed write to a pipe).
+ /// After the pipe signal is handled once, the handler is unregistered.
+ ///
+ /// The LLVM signal handling code will not install any handler for the pipe
+ /// signal unless one is provided with this API (see \ref
+ /// DefaultOneShotPipeSignalHandler). This handler must be provided before
+ /// any other LLVM signal handlers are installed: the \ref InitLLVM
+ /// constructor has a flag that can simplify this setup.
+ ///
+ /// Note that the handler is not allowed to call any non-reentrant
+ /// functions. A null handler pointer disables the current installed
+ /// function. Note also that the handler may be executed on a
+ /// different thread on some platforms.
+ ///
+ /// This is a no-op on Windows.
+ void SetOneShotPipeSignalFunction(void (*Handler)());
+
+ /// On Unix systems, this function exits with an "IO error" exit code.
+ /// This is a no-op on Windows.
+ void DefaultOneShotPipeSignalHandler();
+
+ /// This function does the following:
+ /// - clean up any temporary files registered with RemoveFileOnSignal()
+ /// - dump the callstack from the exception context
+ /// - call any relevant interrupt/signal handlers
+ /// - create a core/mini dump of the exception context whenever possible
+ /// Context is a system-specific failure context: it is the signal type on
+ /// Unix; the ExceptionContext on Windows.
+ void CleanupOnSignal(uintptr_t Context);
+
+ void unregisterHandlers();
} // End sys namespace
} // End llvm namespace
diff --git a/linux-x64/clang/include/llvm/Support/Signposts.h b/linux-x64/clang/include/llvm/Support/Signposts.h
index b5a8c3d..8036b1f 100644
--- a/linux-x64/clang/include/llvm/Support/Signposts.h
+++ b/linux-x64/clang/include/llvm/Support/Signposts.h
@@ -17,9 +17,10 @@
#ifndef LLVM_SUPPORT_SIGNPOSTS_H
#define LLVM_SUPPORT_SIGNPOSTS_H
+#include "llvm/ADT/StringRef.h"
+
namespace llvm {
class SignpostEmitterImpl;
-class Timer;
/// Manages the emission of signposts into the recording method supported by
/// the OS.
@@ -32,10 +33,10 @@
bool isEnabled() const;
- /// Begin a signposted interval for the given timer.
- void startTimerInterval(Timer *T);
- /// End a signposted interval for the given timer.
- void endTimerInterval(Timer *T);
+ /// Begin a signposted interval for a given object.
+ void startInterval(const void *O, StringRef Name);
+ /// End a signposted interval for a given object.
+ void endInterval(const void *O, StringRef Name);
};
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/Support/SmallVectorMemoryBuffer.h b/linux-x64/clang/include/llvm/Support/SmallVectorMemoryBuffer.h
index b63b58e..62900b7 100644
--- a/linux-x64/clang/include/llvm/Support/SmallVectorMemoryBuffer.h
+++ b/linux-x64/clang/include/llvm/Support/SmallVectorMemoryBuffer.h
@@ -44,7 +44,7 @@
/// Construct a named SmallVectorMemoryBuffer from the given
/// SmallVector r-value and StringRef.
SmallVectorMemoryBuffer(SmallVectorImpl<char> &&SV, StringRef Name)
- : SV(std::move(SV)), BufferName(Name) {
+ : SV(std::move(SV)), BufferName(std::string(Name)) {
init(this->SV.begin(), this->SV.end(), false);
}
diff --git a/linux-x64/clang/include/llvm/Support/SourceMgr.h b/linux-x64/clang/include/llvm/Support/SourceMgr.h
index 7b081d3..28716b4 100644
--- a/linux-x64/clang/include/llvm/Support/SourceMgr.h
+++ b/linux-x64/clang/include/llvm/Support/SourceMgr.h
@@ -15,19 +15,9 @@
#ifndef LLVM_SUPPORT_SOURCEMGR_H
#define LLVM_SUPPORT_SOURCEMGR_H
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SMLoc.h"
-#include <algorithm>
-#include <cassert>
-#include <memory>
-#include <string>
-#include <utility>
#include <vector>
namespace llvm {
@@ -57,29 +47,29 @@
/// The memory buffer for the file.
std::unique_ptr<MemoryBuffer> Buffer;
- /// Helper type for OffsetCache below: since we're storing many offsets
- /// into relatively small files (often smaller than 2^8 or 2^16 bytes),
- /// we select the offset vector element type dynamically based on the
- /// size of Buffer.
- using VariableSizeOffsets = PointerUnion4<std::vector<uint8_t> *,
- std::vector<uint16_t> *,
- std::vector<uint32_t> *,
- std::vector<uint64_t> *>;
-
/// Vector of offsets into Buffer at which there are line-endings
/// (lazily populated). Once populated, the '\n' that marks the end of
/// line number N from [1..] is at Buffer[OffsetCache[N-1]]. Since
/// these offsets are in sorted (ascending) order, they can be
/// binary-searched for the first one after any given offset (eg. an
/// offset corresponding to a particular SMLoc).
- mutable VariableSizeOffsets OffsetCache;
+ ///
+ /// Since we're storing offsets into relatively small files (often smaller
+ /// than 2^8 or 2^16 bytes), we select the offset vector element type
+ /// dynamically based on the size of Buffer.
+ mutable void *OffsetCache = nullptr;
- /// Populate \c OffsetCache and look up a given \p Ptr in it, assuming
- /// it points somewhere into \c Buffer. The static type parameter \p T
- /// must be an unsigned integer type from uint{8,16,32,64}_t large
- /// enough to store offsets inside \c Buffer.
- template<typename T>
+ /// Look up a given \p Ptr in in the buffer, determining which line it came
+ /// from.
unsigned getLineNumber(const char *Ptr) const;
+ template <typename T>
+ unsigned getLineNumberSpecialized(const char *Ptr) const;
+
+ /// Return a pointer to the first character of the specified line number or
+ /// null if the line number is invalid.
+ const char *getPointerForLineNumber(unsigned LineNo) const;
+ template <typename T>
+ const char *getPointerForLineNumberSpecialized(unsigned LineNo) const;
/// This is the location of the parent include, or null if at the top level.
SMLoc IncludeLoc;
@@ -106,6 +96,8 @@
SourceMgr() = default;
SourceMgr(const SourceMgr &) = delete;
SourceMgr &operator=(const SourceMgr &) = delete;
+ SourceMgr(SourceMgr &&) = default;
+ SourceMgr &operator=(SourceMgr &&) = default;
~SourceMgr() = default;
void setIncludeDirs(const std::vector<std::string> &Dirs) {
@@ -132,9 +124,7 @@
return Buffers[i - 1].Buffer.get();
}
- unsigned getNumBuffers() const {
- return Buffers.size();
- }
+ unsigned getNumBuffers() const { return Buffers.size(); }
unsigned getMainFileID() const {
assert(getNumBuffers());
@@ -182,20 +172,29 @@
std::pair<unsigned, unsigned> getLineAndColumn(SMLoc Loc,
unsigned BufferID = 0) const;
+ /// Get a string with the \p SMLoc filename and line number
+ /// formatted in the standard style.
+ std::string getFormattedLocationNoOffset(SMLoc Loc,
+ bool IncludePath = false) const;
+
+ /// Given a line and column number in a mapped buffer, turn it into an SMLoc.
+ /// This will return a null SMLoc if the line/column location is invalid.
+ SMLoc FindLocForLineAndColumn(unsigned BufferID, unsigned LineNo,
+ unsigned ColNo);
+
/// Emit a message about the specified location with the specified string.
///
/// \param ShowColors Display colored messages if output is a terminal and
/// the default error handler is used.
- void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind,
- const Twine &Msg,
- ArrayRef<SMRange> Ranges = None,
- ArrayRef<SMFixIt> FixIts = None,
+ void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg,
+ ArrayRef<SMRange> Ranges = {},
+ ArrayRef<SMFixIt> FixIts = {},
bool ShowColors = true) const;
/// Emits a diagnostic to llvm::errs().
void PrintMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
- ArrayRef<SMRange> Ranges = None,
- ArrayRef<SMFixIt> FixIts = None,
+ ArrayRef<SMRange> Ranges = {},
+ ArrayRef<SMFixIt> FixIts = {},
bool ShowColors = true) const;
/// Emits a manually-constructed diagnostic to the given output stream.
@@ -211,8 +210,8 @@
/// \param Msg If non-null, the kind of message (e.g., "error") which is
/// prefixed to the message.
SMDiagnostic GetMessage(SMLoc Loc, DiagKind Kind, const Twine &Msg,
- ArrayRef<SMRange> Ranges = None,
- ArrayRef<SMFixIt> FixIts = None) const;
+ ArrayRef<SMRange> Ranges = {},
+ ArrayRef<SMFixIt> FixIts = {}) const;
/// Prints the names of included files and the line of the file they were
/// included from. A diagnostic handler can use this before printing its
@@ -230,17 +229,10 @@
std::string Text;
public:
- // FIXME: Twine.str() is not very efficient.
- SMFixIt(SMLoc Loc, const Twine &Insertion)
- : Range(Loc, Loc), Text(Insertion.str()) {
- assert(Loc.isValid());
- }
+ SMFixIt(SMRange R, const Twine &Replacement);
- // FIXME: Twine.str() is not very efficient.
- SMFixIt(SMRange R, const Twine &Replacement)
- : Range(R), Text(Replacement.str()) {
- assert(R.isValid());
- }
+ SMFixIt(SMLoc Loc, const Twine &Replacement)
+ : SMFixIt(SMRange(Loc, Loc), Replacement) {}
StringRef getText() const { return Text; }
SMRange getRange() const { return Range; }
@@ -272,14 +264,13 @@
SMDiagnostic() = default;
// Diagnostic with no location (e.g. file not found, command line arg error).
SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg)
- : Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {}
+ : Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {}
// Diagnostic with a location.
- SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN,
- int Line, int Col, SourceMgr::DiagKind Kind,
- StringRef Msg, StringRef LineStr,
- ArrayRef<std::pair<unsigned,unsigned>> Ranges,
- ArrayRef<SMFixIt> FixIts = None);
+ SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, int Line, int Col,
+ SourceMgr::DiagKind Kind, StringRef Msg, StringRef LineStr,
+ ArrayRef<std::pair<unsigned, unsigned>> Ranges,
+ ArrayRef<SMFixIt> FixIts = {});
const SourceMgr *getSourceMgr() const { return SM; }
SMLoc getLoc() const { return Loc; }
@@ -291,13 +282,9 @@
StringRef getLineContents() const { return LineContents; }
ArrayRef<std::pair<unsigned, unsigned>> getRanges() const { return Ranges; }
- void addFixIt(const SMFixIt &Hint) {
- FixIts.push_back(Hint);
- }
+ void addFixIt(const SMFixIt &Hint) { FixIts.push_back(Hint); }
- ArrayRef<SMFixIt> getFixIts() const {
- return FixIts;
- }
+ ArrayRef<SMFixIt> getFixIts() const { return FixIts; }
void print(const char *ProgName, raw_ostream &S, bool ShowColors = true,
bool ShowKindLabel = true) const;
diff --git a/linux-x64/clang/include/llvm/Support/SpecialCaseList.h b/linux-x64/clang/include/llvm/Support/SpecialCaseList.h
index b740026..d022a8f 100644
--- a/linux-x64/clang/include/llvm/Support/SpecialCaseList.h
+++ b/linux-x64/clang/include/llvm/Support/SpecialCaseList.h
@@ -7,8 +7,8 @@
//
// This is a utility class used to parse user-provided text files with
// "special case lists" for code sanitizers. Such files are used to
-// define an "ABI list" for DataFlowSanitizer and blacklists for sanitizers
-// like AddressSanitizer or UndefinedBehaviorSanitizer.
+// define an "ABI list" for DataFlowSanitizer and allow/exclusion lists for
+// sanitizers like AddressSanitizer or UndefinedBehaviorSanitizer.
//
// Empty lines and lines starting with "#" are ignored. Sections are defined
// using a '[section_name]' header and can be used to specify sanitizers the
@@ -19,18 +19,18 @@
// prefix:wildcard_expression[=category]
// If category is not specified, it is assumed to be empty string.
// Definitions of "prefix" and "category" are sanitizer-specific. For example,
-// sanitizer blacklists support prefixes "src", "fun" and "global".
+// sanitizer exclusion support prefixes "src", "fun" and "global".
// Wildcard expressions define, respectively, source files, functions or
// globals which shouldn't be instrumented.
// Examples of categories:
// "functional": used in DFSan to list functions with pure functional
// semantics.
-// "init": used in ASan blacklist to disable initialization-order bugs
+// "init": used in ASan exclusion list to disable initialization-order bugs
// detection for certain globals or source files.
// Full special case list file example:
// ---
// [address]
-// # Blacklisted items:
+// # Excluded items:
// fun:*_ZN4base6subtle*
// global:*global_with_bad_access_or_initialization*
// global:*global_with_initialization_issues*=init
@@ -52,23 +52,27 @@
#define LLVM_SUPPORT_SPECIALCASELIST_H
#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/TrigramIndex.h"
+#include <memory>
#include <string>
#include <vector>
namespace llvm {
class MemoryBuffer;
-class Regex;
class StringRef;
+namespace vfs {
+class FileSystem;
+}
+
class SpecialCaseList {
public:
/// Parses the special case list entries from files. On failure, returns
/// 0 and writes an error message to string.
static std::unique_ptr<SpecialCaseList>
- create(const std::vector<std::string> &Paths, std::string &Error);
+ create(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &FS,
+ std::string &Error);
/// Parses the special case list from a memory buffer. On failure, returns
/// 0 and writes an error message to string.
static std::unique_ptr<SpecialCaseList> create(const MemoryBuffer *MB,
@@ -76,7 +80,7 @@
/// Parses the special case list entries from files. On failure, reports a
/// fatal error.
static std::unique_ptr<SpecialCaseList>
- createOrDie(const std::vector<std::string> &Paths);
+ createOrDie(const std::vector<std::string> &Paths, llvm::vfs::FileSystem &FS);
~SpecialCaseList();
@@ -94,7 +98,7 @@
/// @Prefix:<E>=@Category
/// \endcode
/// where @Query satisfies wildcard expression <E> in a given @Section.
- /// Returns zero if there is no blacklist entry corresponding to this
+ /// Returns zero if there is no exclusion entry corresponding to this
/// expression.
unsigned inSectionBlame(StringRef Section, StringRef Prefix, StringRef Query,
StringRef Category = StringRef()) const;
@@ -103,7 +107,7 @@
// Implementations of the create*() functions that can also be used by derived
// classes.
bool createInternal(const std::vector<std::string> &Paths,
- std::string &Error);
+ vfs::FileSystem &VFS, std::string &Error);
bool createInternal(const MemoryBuffer *MB, std::string &Error);
SpecialCaseList() = default;
diff --git a/linux-x64/clang/include/llvm/Support/StringPool.h b/linux-x64/clang/include/llvm/Support/StringPool.h
deleted file mode 100644
index a4f4591..0000000
--- a/linux-x64/clang/include/llvm/Support/StringPool.h
+++ /dev/null
@@ -1,139 +0,0 @@
-//===- StringPool.h - Interned string pool ----------------------*- 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 declares an interned string pool, which helps reduce the cost of
-// strings by using the same storage for identical strings.
-//
-// To intern a string:
-//
-// StringPool Pool;
-// PooledStringPtr Str = Pool.intern("wakka wakka");
-//
-// To use the value of an interned string, use operator bool and operator*:
-//
-// if (Str)
-// cerr << "the string is" << *Str << "\n";
-//
-// Pooled strings are immutable, but you can change a PooledStringPtr to point
-// to another instance. So that interned strings can eventually be freed,
-// strings in the string pool are reference-counted (automatically).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_STRINGPOOL_H
-#define LLVM_SUPPORT_STRINGPOOL_H
-
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include <cassert>
-
-namespace llvm {
-
- class PooledStringPtr;
-
- /// StringPool - An interned string pool. Use the intern method to add a
- /// string. Strings are removed automatically as PooledStringPtrs are
- /// destroyed.
- class StringPool {
- /// PooledString - This is the value of an entry in the pool's interning
- /// table.
- struct PooledString {
- StringPool *Pool = nullptr; ///< So the string can remove itself.
- unsigned Refcount = 0; ///< Number of referencing PooledStringPtrs.
-
- public:
- PooledString() = default;
- };
-
- friend class PooledStringPtr;
-
- using table_t = StringMap<PooledString>;
- using entry_t = StringMapEntry<PooledString>;
- table_t InternTable;
-
- public:
- StringPool();
- ~StringPool();
-
- /// intern - Adds a string to the pool and returns a reference-counted
- /// pointer to it. No additional memory is allocated if the string already
- /// exists in the pool.
- PooledStringPtr intern(StringRef Str);
-
- /// empty - Checks whether the pool is empty. Returns true if so.
- ///
- inline bool empty() const { return InternTable.empty(); }
- };
-
- /// PooledStringPtr - A pointer to an interned string. Use operator bool to
- /// test whether the pointer is valid, and operator * to get the string if so.
- /// This is a lightweight value class with storage requirements equivalent to
- /// a single pointer, but it does have reference-counting overhead when
- /// copied.
- class PooledStringPtr {
- using entry_t = StringPool::entry_t;
-
- entry_t *S = nullptr;
-
- public:
- PooledStringPtr() = default;
-
- explicit PooledStringPtr(entry_t *E) : S(E) {
- if (S) ++S->getValue().Refcount;
- }
-
- PooledStringPtr(const PooledStringPtr &That) : S(That.S) {
- if (S) ++S->getValue().Refcount;
- }
-
- PooledStringPtr &operator=(const PooledStringPtr &That) {
- if (S != That.S) {
- clear();
- S = That.S;
- if (S) ++S->getValue().Refcount;
- }
- return *this;
- }
-
- void clear() {
- if (!S)
- return;
- if (--S->getValue().Refcount == 0) {
- S->getValue().Pool->InternTable.remove(S);
- S->Destroy();
- }
- S = nullptr;
- }
-
- ~PooledStringPtr() { clear(); }
-
- inline const char *begin() const {
- assert(*this && "Attempt to dereference empty PooledStringPtr!");
- return S->getKeyData();
- }
-
- inline const char *end() const {
- assert(*this && "Attempt to dereference empty PooledStringPtr!");
- return S->getKeyData() + S->getKeyLength();
- }
-
- inline unsigned size() const {
- assert(*this && "Attempt to dereference empty PooledStringPtr!");
- return S->getKeyLength();
- }
-
- inline const char *operator*() const { return begin(); }
- inline explicit operator bool() const { return S != nullptr; }
-
- inline bool operator==(const PooledStringPtr &That) const { return S == That.S; }
- inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; }
- };
-
-} // end namespace llvm
-
-#endif // LLVM_SUPPORT_STRINGPOOL_H
diff --git a/linux-x64/clang/include/llvm/Support/SuffixTree.h b/linux-x64/clang/include/llvm/Support/SuffixTree.h
new file mode 100644
index 0000000..352fba5
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/SuffixTree.h
@@ -0,0 +1,350 @@
+//===- llvm/ADT/SuffixTree.h - Tree for substrings --------------*- 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 the Suffix Tree class and Suffix Tree Node struct.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_SUPPORT_SUFFIXTREE_H
+#define LLVM_SUPPORT_SUFFIXTREE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Allocator.h"
+#include <vector>
+
+namespace llvm {
+
+/// Represents an undefined index in the suffix tree.
+const unsigned EmptyIdx = -1;
+
+/// A node in a suffix tree which represents a substring or suffix.
+///
+/// Each node has either no children or at least two children, with the root
+/// being a exception in the empty tree.
+///
+/// Children are represented as a map between unsigned integers and nodes. If
+/// a node N has a child M on unsigned integer k, then the mapping represented
+/// by N is a proper prefix of the mapping represented by M. Note that this,
+/// although similar to a trie is somewhat different: each node stores a full
+/// substring of the full mapping rather than a single character state.
+///
+/// Each internal node contains a pointer to the internal node representing
+/// the same string, but with the first character chopped off. This is stored
+/// in \p Link. Each leaf node stores the start index of its respective
+/// suffix in \p SuffixIdx.
+struct SuffixTreeNode {
+
+ /// The children of this node.
+ ///
+ /// A child existing on an unsigned integer implies that from the mapping
+ /// represented by the current node, there is a way to reach another
+ /// mapping by tacking that character on the end of the current string.
+ llvm::DenseMap<unsigned, SuffixTreeNode *> Children;
+
+ /// The start index of this node's substring in the main string.
+ unsigned StartIdx = EmptyIdx;
+
+ /// The end index of this node's substring in the main string.
+ ///
+ /// Every leaf node must have its \p EndIdx incremented at the end of every
+ /// step in the construction algorithm. To avoid having to update O(N)
+ /// nodes individually at the end of every step, the end index is stored
+ /// as a pointer.
+ unsigned *EndIdx = nullptr;
+
+ /// For leaves, the start index of the suffix represented by this node.
+ ///
+ /// For all other nodes, this is ignored.
+ unsigned SuffixIdx = EmptyIdx;
+
+ /// For internal nodes, a pointer to the internal node representing
+ /// the same sequence with the first character chopped off.
+ ///
+ /// This acts as a shortcut in Ukkonen's algorithm. One of the things that
+ /// Ukkonen's algorithm does to achieve linear-time construction is
+ /// keep track of which node the next insert should be at. This makes each
+ /// insert O(1), and there are a total of O(N) inserts. The suffix link
+ /// helps with inserting children of internal nodes.
+ ///
+ /// Say we add a child to an internal node with associated mapping S. The
+ /// next insertion must be at the node representing S - its first character.
+ /// This is given by the way that we iteratively build the tree in Ukkonen's
+ /// algorithm. The main idea is to look at the suffixes of each prefix in the
+ /// string, starting with the longest suffix of the prefix, and ending with
+ /// the shortest. Therefore, if we keep pointers between such nodes, we can
+ /// move to the next insertion point in O(1) time. If we don't, then we'd
+ /// have to query from the root, which takes O(N) time. This would make the
+ /// construction algorithm O(N^2) rather than O(N).
+ SuffixTreeNode *Link = nullptr;
+
+ /// The length of the string formed by concatenating the edge labels from the
+ /// root to this node.
+ unsigned ConcatLen = 0;
+
+ /// Returns true if this node is a leaf.
+ bool isLeaf() const { return SuffixIdx != EmptyIdx; }
+
+ /// Returns true if this node is the root of its owning \p SuffixTree.
+ bool isRoot() const { return StartIdx == EmptyIdx; }
+
+ /// Return the number of elements in the substring associated with this node.
+ size_t size() const {
+
+ // Is it the root? If so, it's the empty string so return 0.
+ if (isRoot())
+ return 0;
+
+ assert(*EndIdx != EmptyIdx && "EndIdx is undefined!");
+
+ // Size = the number of elements in the string.
+ // For example, [0 1 2 3] has length 4, not 3. 3-0 = 3, so we have 3-0+1.
+ return *EndIdx - StartIdx + 1;
+ }
+
+ SuffixTreeNode(unsigned StartIdx, unsigned *EndIdx, SuffixTreeNode *Link)
+ : StartIdx(StartIdx), EndIdx(EndIdx), Link(Link) {}
+
+ SuffixTreeNode() {}
+};
+
+/// A data structure for fast substring queries.
+///
+/// Suffix trees represent the suffixes of their input strings in their leaves.
+/// A suffix tree is a type of compressed trie structure where each node
+/// represents an entire substring rather than a single character. Each leaf
+/// of the tree is a suffix.
+///
+/// A suffix tree can be seen as a type of state machine where each state is a
+/// substring of the full string. The tree is structured so that, for a string
+/// of length N, there are exactly N leaves in the tree. This structure allows
+/// us to quickly find repeated substrings of the input string.
+///
+/// In this implementation, a "string" is a vector of unsigned integers.
+/// These integers may result from hashing some data type. A suffix tree can
+/// contain 1 or many strings, which can then be queried as one large string.
+///
+/// The suffix tree is implemented using Ukkonen's algorithm for linear-time
+/// suffix tree construction. Ukkonen's algorithm is explained in more detail
+/// in the paper by Esko Ukkonen "On-line construction of suffix trees. The
+/// paper is available at
+///
+/// https://www.cs.helsinki.fi/u/ukkonen/SuffixT1withFigs.pdf
+class SuffixTree {
+public:
+ /// Each element is an integer representing an instruction in the module.
+ llvm::ArrayRef<unsigned> Str;
+
+ /// A repeated substring in the tree.
+ struct RepeatedSubstring {
+ /// The length of the string.
+ unsigned Length;
+
+ /// The start indices of each occurrence.
+ std::vector<unsigned> StartIndices;
+ };
+
+private:
+ /// Maintains each node in the tree.
+ llvm::SpecificBumpPtrAllocator<SuffixTreeNode> NodeAllocator;
+
+ /// The root of the suffix tree.
+ ///
+ /// The root represents the empty string. It is maintained by the
+ /// \p NodeAllocator like every other node in the tree.
+ SuffixTreeNode *Root = nullptr;
+
+ /// Maintains the end indices of the internal nodes in the tree.
+ ///
+ /// Each internal node is guaranteed to never have its end index change
+ /// during the construction algorithm; however, leaves must be updated at
+ /// every step. Therefore, we need to store leaf end indices by reference
+ /// to avoid updating O(N) leaves at every step of construction. Thus,
+ /// every internal node must be allocated its own end index.
+ llvm::BumpPtrAllocator InternalEndIdxAllocator;
+
+ /// The end index of each leaf in the tree.
+ unsigned LeafEndIdx = -1;
+
+ /// Helper struct which keeps track of the next insertion point in
+ /// Ukkonen's algorithm.
+ struct ActiveState {
+ /// The next node to insert at.
+ SuffixTreeNode *Node = nullptr;
+
+ /// The index of the first character in the substring currently being added.
+ unsigned Idx = EmptyIdx;
+
+ /// The length of the substring we have to add at the current step.
+ unsigned Len = 0;
+ };
+
+ /// The point the next insertion will take place at in the
+ /// construction algorithm.
+ ActiveState Active;
+
+ /// Allocate a leaf node and add it to the tree.
+ ///
+ /// \param Parent The parent of this node.
+ /// \param StartIdx The start index of this node's associated string.
+ /// \param Edge The label on the edge leaving \p Parent to this node.
+ ///
+ /// \returns A pointer to the allocated leaf node.
+ SuffixTreeNode *insertLeaf(SuffixTreeNode &Parent, unsigned StartIdx,
+ unsigned Edge);
+
+ /// Allocate an internal node and add it to the tree.
+ ///
+ /// \param Parent The parent of this node. Only null when allocating the root.
+ /// \param StartIdx The start index of this node's associated string.
+ /// \param EndIdx The end index of this node's associated string.
+ /// \param Edge The label on the edge leaving \p Parent to this node.
+ ///
+ /// \returns A pointer to the allocated internal node.
+ SuffixTreeNode *insertInternalNode(SuffixTreeNode *Parent, unsigned StartIdx,
+ unsigned EndIdx, unsigned Edge);
+
+ /// Set the suffix indices of the leaves to the start indices of their
+ /// respective suffixes.
+ void setSuffixIndices();
+
+ /// Construct the suffix tree for the prefix of the input ending at
+ /// \p EndIdx.
+ ///
+ /// Used to construct the full suffix tree iteratively. At the end of each
+ /// step, the constructed suffix tree is either a valid suffix tree, or a
+ /// suffix tree with implicit suffixes. At the end of the final step, the
+ /// suffix tree is a valid tree.
+ ///
+ /// \param EndIdx The end index of the current prefix in the main string.
+ /// \param SuffixesToAdd The number of suffixes that must be added
+ /// to complete the suffix tree at the current phase.
+ ///
+ /// \returns The number of suffixes that have not been added at the end of
+ /// this step.
+ unsigned extend(unsigned EndIdx, unsigned SuffixesToAdd);
+
+public:
+ /// Construct a suffix tree from a sequence of unsigned integers.
+ ///
+ /// \param Str The string to construct the suffix tree for.
+ SuffixTree(const std::vector<unsigned> &Str);
+
+ /// Iterator for finding all repeated substrings in the suffix tree.
+ struct RepeatedSubstringIterator {
+ private:
+ /// The current node we're visiting.
+ SuffixTreeNode *N = nullptr;
+
+ /// The repeated substring associated with this node.
+ RepeatedSubstring RS;
+
+ /// The nodes left to visit.
+ std::vector<SuffixTreeNode *> ToVisit;
+
+ /// The minimum length of a repeated substring to find.
+ /// Since we're outlining, we want at least two instructions in the range.
+ /// FIXME: This may not be true for targets like X86 which support many
+ /// instruction lengths.
+ const unsigned MinLength = 2;
+
+ /// Move the iterator to the next repeated substring.
+ void advance() {
+ // Clear the current state. If we're at the end of the range, then this
+ // is the state we want to be in.
+ RS = RepeatedSubstring();
+ N = nullptr;
+
+ // Each leaf node represents a repeat of a string.
+ std::vector<SuffixTreeNode *> LeafChildren;
+
+ // Continue visiting nodes until we find one which repeats more than once.
+ while (!ToVisit.empty()) {
+ SuffixTreeNode *Curr = ToVisit.back();
+ ToVisit.pop_back();
+ LeafChildren.clear();
+
+ // Keep track of the length of the string associated with the node. If
+ // it's too short, we'll quit.
+ unsigned Length = Curr->ConcatLen;
+
+ // Iterate over each child, saving internal nodes for visiting, and
+ // leaf nodes in LeafChildren. Internal nodes represent individual
+ // strings, which may repeat.
+ for (auto &ChildPair : Curr->Children) {
+ // Save all of this node's children for processing.
+ if (!ChildPair.second->isLeaf())
+ ToVisit.push_back(ChildPair.second);
+
+ // It's not an internal node, so it must be a leaf. If we have a
+ // long enough string, then save the leaf children.
+ else if (Length >= MinLength)
+ LeafChildren.push_back(ChildPair.second);
+ }
+
+ // The root never represents a repeated substring. If we're looking at
+ // that, then skip it.
+ if (Curr->isRoot())
+ continue;
+
+ // Do we have any repeated substrings?
+ if (LeafChildren.size() >= 2) {
+ // Yes. Update the state to reflect this, and then bail out.
+ N = Curr;
+ RS.Length = Length;
+ for (SuffixTreeNode *Leaf : LeafChildren)
+ RS.StartIndices.push_back(Leaf->SuffixIdx);
+ break;
+ }
+ }
+
+ // At this point, either NewRS is an empty RepeatedSubstring, or it was
+ // set in the above loop. Similarly, N is either nullptr, or the node
+ // associated with NewRS.
+ }
+
+ public:
+ /// Return the current repeated substring.
+ RepeatedSubstring &operator*() { return RS; }
+
+ RepeatedSubstringIterator &operator++() {
+ advance();
+ return *this;
+ }
+
+ RepeatedSubstringIterator operator++(int I) {
+ RepeatedSubstringIterator It(*this);
+ advance();
+ return It;
+ }
+
+ bool operator==(const RepeatedSubstringIterator &Other) const {
+ return N == Other.N;
+ }
+ bool operator!=(const RepeatedSubstringIterator &Other) const {
+ return !(*this == Other);
+ }
+
+ RepeatedSubstringIterator(SuffixTreeNode *N) : N(N) {
+ // Do we have a non-null node?
+ if (N) {
+ // Yes. At the first step, we need to visit all of N's children.
+ // Note: This means that we visit N last.
+ ToVisit.push_back(N);
+ advance();
+ }
+ }
+ };
+
+ typedef RepeatedSubstringIterator iterator;
+ iterator begin() { return iterator(Root); }
+ iterator end() { return iterator(nullptr); }
+};
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_SUFFIXTREE_H
diff --git a/linux-x64/clang/include/llvm/Support/SwapByteOrder.h b/linux-x64/clang/include/llvm/Support/SwapByteOrder.h
index 06a447a..e8612ba 100644
--- a/linux-x64/clang/include/llvm/Support/SwapByteOrder.h
+++ b/linux-x64/clang/include/llvm/Support/SwapByteOrder.h
@@ -14,20 +14,43 @@
#ifndef LLVM_SUPPORT_SWAPBYTEORDER_H
#define LLVM_SUPPORT_SWAPBYTEORDER_H
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
#include <cstddef>
+#include <cstdint>
#include <type_traits>
#if defined(_MSC_VER) && !defined(_DEBUG)
#include <stdlib.h>
#endif
-namespace llvm {
-namespace sys {
+#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \
+ defined(__Fuchsia__) || defined(__EMSCRIPTEN__)
+#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
+#elif defined(__MVS__)
+#define BIG_ENDIAN 4321
+#define LITTLE_ENDIAN 1234
+#define BYTE_ORDER BIG_ENDIAN
+#else
+#if !defined(BYTE_ORDER) && !defined(_WIN32)
+#include <machine/endian.h>
+#endif
+#endif
-/// SwapByteOrder_16 - This function returns a byte-swapped representation of
+namespace llvm {
+
+/// ByteSwap_16 - This function returns a byte-swapped representation of
/// the 16-bit argument.
-inline uint16_t SwapByteOrder_16(uint16_t value) {
+inline uint16_t ByteSwap_16(uint16_t value) {
#if defined(_MSC_VER) && !defined(_DEBUG)
// The DLL version of the runtime lacks these functions (bug!?), but in a
// release build they're replaced with BSWAP instructions anyway.
@@ -39,10 +62,9 @@
#endif
}
-/// SwapByteOrder_32 - This function returns a byte-swapped representation of
-/// the 32-bit argument.
-inline uint32_t SwapByteOrder_32(uint32_t value) {
-#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC))
+/// This function returns a byte-swapped representation of the 32-bit argument.
+inline uint32_t ByteSwap_32(uint32_t value) {
+#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
return __builtin_bswap32(value);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_ulong(value);
@@ -55,45 +77,55 @@
#endif
}
-/// SwapByteOrder_64 - This function returns a byte-swapped representation of
-/// the 64-bit argument.
-inline uint64_t SwapByteOrder_64(uint64_t value) {
-#if defined(__llvm__) || (LLVM_GNUC_PREREQ(4, 3, 0) && !defined(__ICC))
+/// This function returns a byte-swapped representation of the 64-bit argument.
+inline uint64_t ByteSwap_64(uint64_t value) {
+#if defined(__llvm__) || (defined(__GNUC__) && !defined(__ICC))
return __builtin_bswap64(value);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_uint64(value);
#else
- uint64_t Hi = SwapByteOrder_32(uint32_t(value));
- uint32_t Lo = SwapByteOrder_32(uint32_t(value >> 32));
+ uint64_t Hi = ByteSwap_32(uint32_t(value));
+ uint32_t Lo = ByteSwap_32(uint32_t(value >> 32));
return (Hi << 32) | Lo;
#endif
}
+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;
+
inline unsigned char getSwappedBytes(unsigned char C) { return C; }
inline signed char getSwappedBytes(signed char C) { return C; }
inline char getSwappedBytes(char C) { return C; }
-inline unsigned short getSwappedBytes(unsigned short C) { return SwapByteOrder_16(C); }
-inline signed short getSwappedBytes( signed short C) { return SwapByteOrder_16(C); }
+inline unsigned short getSwappedBytes(unsigned short C) { return ByteSwap_16(C); }
+inline signed short getSwappedBytes( signed short C) { return ByteSwap_16(C); }
-inline unsigned int getSwappedBytes(unsigned int C) { return SwapByteOrder_32(C); }
-inline signed int getSwappedBytes( signed int C) { return SwapByteOrder_32(C); }
+inline unsigned int getSwappedBytes(unsigned int C) { return ByteSwap_32(C); }
+inline signed int getSwappedBytes( signed int C) { return ByteSwap_32(C); }
-#if __LONG_MAX__ == __INT_MAX__
-inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_32(C); }
-inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_32(C); }
-#elif __LONG_MAX__ == __LONG_LONG_MAX__
-inline unsigned long getSwappedBytes(unsigned long C) { return SwapByteOrder_64(C); }
-inline signed long getSwappedBytes( signed long C) { return SwapByteOrder_64(C); }
-#else
-#error "Unknown long size!"
-#endif
+inline unsigned long getSwappedBytes(unsigned long C) {
+ // Handle LLP64 and LP64 platforms.
+ return sizeof(long) == sizeof(int) ? ByteSwap_32((uint32_t)C)
+ : ByteSwap_64((uint64_t)C);
+}
+inline signed long getSwappedBytes(signed long C) {
+ // Handle LLP64 and LP64 platforms.
+ return sizeof(long) == sizeof(int) ? ByteSwap_32((uint32_t)C)
+ : ByteSwap_64((uint64_t)C);
+}
inline unsigned long long getSwappedBytes(unsigned long long C) {
- return SwapByteOrder_64(C);
+ return ByteSwap_64(C);
}
inline signed long long getSwappedBytes(signed long long C) {
- return SwapByteOrder_64(C);
+ return ByteSwap_64(C);
}
inline float getSwappedBytes(float C) {
@@ -102,7 +134,7 @@
float f;
} in, out;
in.f = C;
- out.i = SwapByteOrder_32(in.i);
+ out.i = ByteSwap_32(in.i);
return out.f;
}
@@ -112,15 +144,14 @@
double d;
} in, out;
in.d = C;
- out.i = SwapByteOrder_64(in.i);
+ out.i = ByteSwap_64(in.i);
return out.d;
}
template <typename T>
-inline typename std::enable_if<std::is_enum<T>::value, T>::type
-getSwappedBytes(T C) {
+inline std::enable_if_t<std::is_enum<T>::value, T> getSwappedBytes(T C) {
return static_cast<T>(
- getSwappedBytes(static_cast<typename std::underlying_type<T>::type>(C)));
+ getSwappedBytes(static_cast<std::underlying_type_t<T>>(C)));
}
template<typename T>
diff --git a/linux-x64/clang/include/llvm/Support/SymbolRemappingReader.h b/linux-x64/clang/include/llvm/Support/SymbolRemappingReader.h
index 2b9ab57..820cf9e 100644
--- a/linux-x64/clang/include/llvm/Support/SymbolRemappingReader.h
+++ b/linux-x64/clang/include/llvm/Support/SymbolRemappingReader.h
@@ -68,7 +68,7 @@
class SymbolRemappingParseError : public ErrorInfo<SymbolRemappingParseError> {
public:
- SymbolRemappingParseError(StringRef File, int64_t Line, Twine Message)
+ SymbolRemappingParseError(StringRef File, int64_t Line, const Twine &Message)
: File(File), Line(Line), Message(Message.str()) {}
void log(llvm::raw_ostream &OS) const override {
diff --git a/linux-x64/clang/include/llvm/Support/SystemUtils.h b/linux-x64/clang/include/llvm/Support/SystemUtils.h
index 77deddb..786bea3 100644
--- a/linux-x64/clang/include/llvm/Support/SystemUtils.h
+++ b/linux-x64/clang/include/llvm/Support/SystemUtils.h
@@ -15,17 +15,16 @@
#define LLVM_SUPPORT_SYSTEMUTILS_H
namespace llvm {
- class raw_ostream;
+class raw_ostream;
/// Determine if the raw_ostream provided is connected to a terminal. If so,
/// generate a warning message to errs() advising against display of bitcode
/// and return true. Otherwise just return false.
/// Check for output written to a console
bool CheckBitcodeOutputToConsole(
- raw_ostream &stream_to_check, ///< The stream to be checked
- bool print_warning = true ///< Control whether warnings are printed
+ raw_ostream &stream_to_check ///< The stream to be checked
);
-} // End llvm namespace
+} // namespace llvm
#endif
diff --git a/linux-x64/clang/include/llvm/Support/TargetOpcodes.def b/linux-x64/clang/include/llvm/Support/TargetOpcodes.def
index fa02463..a63d404 100644
--- a/linux-x64/clang/include/llvm/Support/TargetOpcodes.def
+++ b/linux-x64/clang/include/llvm/Support/TargetOpcodes.def
@@ -77,6 +77,10 @@
/// DBG_VALUE - a mapping of the llvm.dbg.value intrinsic
HANDLE_TARGET_OPCODE(DBG_VALUE)
+/// DBG_INSTR_REF - A mapping of llvm.dbg.value referring to the instruction
+/// that defines the value, rather than a virtual register.
+HANDLE_TARGET_OPCODE(DBG_INSTR_REF)
+
/// DBG_LABEL - a mapping of the llvm.dbg.label intrinsic
HANDLE_TARGET_OPCODE(DBG_LABEL)
@@ -106,6 +110,9 @@
HANDLE_TARGET_OPCODE(LIFETIME_START)
HANDLE_TARGET_OPCODE(LIFETIME_END)
+/// Pseudo probe
+HANDLE_TARGET_OPCODE(PSEUDO_PROBE)
+
/// A Stackmap instruction captures the location of live variables at its
/// position in the instruction stream. It is followed by a shadow of bytes
/// that must lie within the function and not contain another stackmap.
@@ -127,6 +134,12 @@
/// additionally expand this pseudo after register allocation.
HANDLE_TARGET_OPCODE(LOAD_STACK_GUARD)
+/// These are used to support call sites that must have the stack adjusted
+/// before the call (e.g. to initialize an argument passed by value).
+/// See llvm.call.preallocated.{setup,arg} in the LangRef for more details.
+HANDLE_TARGET_OPCODE(PREALLOCATED_SETUP)
+HANDLE_TARGET_OPCODE(PREALLOCATED_ARG)
+
/// Call instruction with associated vm state for deoptimization and list
/// of live pointers for relocation by the garbage collector. It is
/// intended to support garbage collection with fully precise relocating
@@ -279,12 +292,24 @@
/// COPY is the relevant instruction.
HANDLE_TARGET_OPCODE(G_BITCAST)
+/// Generic freeze.
+HANDLE_TARGET_OPCODE(G_FREEZE)
+
/// INTRINSIC trunc intrinsic.
HANDLE_TARGET_OPCODE(G_INTRINSIC_TRUNC)
/// INTRINSIC round intrinsic.
HANDLE_TARGET_OPCODE(G_INTRINSIC_ROUND)
+/// INTRINSIC round to integer intrinsic.
+HANDLE_TARGET_OPCODE(G_INTRINSIC_LRINT)
+
+/// INTRINSIC roundeven intrinsic.
+HANDLE_TARGET_OPCODE(G_INTRINSIC_ROUNDEVEN)
+
+/// INTRINSIC readcyclecounter
+HANDLE_TARGET_OPCODE(G_READCYCLECOUNTER)
+
/// Generic load (including anyext load)
HANDLE_TARGET_OPCODE(G_LOAD)
@@ -294,9 +319,21 @@
/// 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 +352,8 @@
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 +393,7 @@
// Generic sign extend
HANDLE_TARGET_OPCODE(G_SEXT)
+HANDLE_TARGET_OPCODE(G_SEXT_INREG)
// Generic zero extend
HANDLE_TARGET_OPCODE(G_ZEXT)
@@ -367,6 +407,12 @@
// Generic arithmetic right-shift
HANDLE_TARGET_OPCODE(G_ASHR)
+// Generic funnel left shift
+HANDLE_TARGET_OPCODE(G_FSHL)
+
+// Generic funnel right shift
+HANDLE_TARGET_OPCODE(G_FSHR)
+
/// Generic integer-base comparison, also applicable to vectors of integers.
HANDLE_TARGET_OPCODE(G_ICMP)
@@ -424,6 +470,48 @@
// the high half of the result.
HANDLE_TARGET_OPCODE(G_SMULH)
+/// Generic saturating unsigned addition.
+HANDLE_TARGET_OPCODE(G_UADDSAT)
+
+/// Generic saturating signed addition.
+HANDLE_TARGET_OPCODE(G_SADDSAT)
+
+/// Generic saturating unsigned subtraction.
+HANDLE_TARGET_OPCODE(G_USUBSAT)
+
+/// Generic saturating signed subtraction.
+HANDLE_TARGET_OPCODE(G_SSUBSAT)
+
+/// Generic saturating unsigned left shift.
+HANDLE_TARGET_OPCODE(G_USHLSAT)
+
+/// Generic saturating signed left shift.
+HANDLE_TARGET_OPCODE(G_SSHLSAT)
+
+// Perform signed fixed point multiplication
+HANDLE_TARGET_OPCODE(G_SMULFIX)
+
+// Perform unsigned fixed point multiplication
+HANDLE_TARGET_OPCODE(G_UMULFIX)
+
+// Perform signed, saturating fixed point multiplication
+HANDLE_TARGET_OPCODE(G_SMULFIXSAT)
+
+// Perform unsigned, saturating fixed point multiplication
+HANDLE_TARGET_OPCODE(G_UMULFIXSAT)
+
+// Perform signed fixed point division
+HANDLE_TARGET_OPCODE(G_SDIVFIX)
+
+// Perform unsigned fixed point division
+HANDLE_TARGET_OPCODE(G_UDIVFIX)
+
+// Perform signed, saturating fixed point division
+HANDLE_TARGET_OPCODE(G_SDIVFIXSAT)
+
+// Perform unsigned, saturating fixed point division
+HANDLE_TARGET_OPCODE(G_UDIVFIXSAT)
+
/// Generic FP addition.
HANDLE_TARGET_OPCODE(G_FADD)
@@ -436,6 +524,9 @@
/// 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)
@@ -445,6 +536,9 @@
/// Generic FP exponentiation.
HANDLE_TARGET_OPCODE(G_FPOW)
+/// Generic FP exponentiation, with an integer exponent.
+HANDLE_TARGET_OPCODE(G_FPOWI)
+
/// Generic base-e exponential of a value.
HANDLE_TARGET_OPCODE(G_FEXP)
@@ -493,12 +587,23 @@
/// Generic FP canonicalize value.
HANDLE_TARGET_OPCODE(G_FCANONICALIZE)
-/// Generic pointer offset
-HANDLE_TARGET_OPCODE(G_GEP)
+/// FP min/max matching libm's fmin/fmax
+HANDLE_TARGET_OPCODE(G_FMINNUM)
+HANDLE_TARGET_OPCODE(G_FMAXNUM)
-/// Clear the specified number of low bits in a pointer. This rounds the value
-/// *down* to the given alignment.
-HANDLE_TARGET_OPCODE(G_PTR_MASK)
+/// FP min/max matching IEEE-754 2008's minnum/maxnum semantics.
+HANDLE_TARGET_OPCODE(G_FMINNUM_IEEE)
+HANDLE_TARGET_OPCODE(G_FMAXNUM_IEEE)
+
+/// FP min/max matching IEEE-754 2018 draft semantics.
+HANDLE_TARGET_OPCODE(G_FMINIMUM)
+HANDLE_TARGET_OPCODE(G_FMAXIMUM)
+
+/// Generic pointer offset
+HANDLE_TARGET_OPCODE(G_PTR_ADD)
+
+/// Clear the specified bits in a pointer.
+HANDLE_TARGET_OPCODE(G_PTRMASK)
/// Generic signed integer minimum.
HANDLE_TARGET_OPCODE(G_SMIN)
@@ -512,6 +617,9 @@
/// Generic unsigned integer maximum.
HANDLE_TARGET_OPCODE(G_UMAX)
+/// Generic integer absolute value.
+HANDLE_TARGET_OPCODE(G_ABS)
+
/// Generic BRANCH instruction. This is an unconditional branch.
HANDLE_TARGET_OPCODE(G_BR)
@@ -545,6 +653,9 @@
/// Generic byte swap.
HANDLE_TARGET_OPCODE(G_BSWAP)
+/// Generic bit reverse.
+HANDLE_TARGET_OPCODE(G_BITREVERSE)
+
/// Floating point ceil.
HANDLE_TARGET_OPCODE(G_FCEIL)
@@ -575,12 +686,54 @@
/// Generic jump table address
HANDLE_TARGET_OPCODE(G_JUMP_TABLE)
-// TODO: Add more generic opcodes as we move along.
+/// Generic dynamic stack allocation.
+HANDLE_TARGET_OPCODE(G_DYN_STACKALLOC)
+
+/// Strict floating point instructions.
+HANDLE_TARGET_OPCODE(G_STRICT_FADD)
+HANDLE_TARGET_OPCODE(G_STRICT_FSUB)
+HANDLE_TARGET_OPCODE(G_STRICT_FMUL)
+HANDLE_TARGET_OPCODE(G_STRICT_FDIV)
+HANDLE_TARGET_OPCODE(G_STRICT_FREM)
+HANDLE_TARGET_OPCODE(G_STRICT_FMA)
+HANDLE_TARGET_OPCODE(G_STRICT_FSQRT)
+
+/// read_register intrinsic
+HANDLE_TARGET_OPCODE(G_READ_REGISTER)
+
+/// write_register intrinsic
+HANDLE_TARGET_OPCODE(G_WRITE_REGISTER)
+
+/// llvm.memcpy intrinsic
+HANDLE_TARGET_OPCODE(G_MEMCPY)
+
+/// llvm.memmove intrinsic
+HANDLE_TARGET_OPCODE(G_MEMMOVE)
+
+/// llvm.memset intrinsic
+HANDLE_TARGET_OPCODE(G_MEMSET)
+
+/// Vector reductions
+HANDLE_TARGET_OPCODE(G_VECREDUCE_SEQ_FADD)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_SEQ_FMUL)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_FADD)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_FMUL)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_FMAX)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_FMIN)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_ADD)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_MUL)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_AND)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_OR)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_XOR)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_SMAX)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_SMIN)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_UMAX)
+HANDLE_TARGET_OPCODE(G_VECREDUCE_UMIN)
/// 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_VECREDUCE_UMIN)
/// 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/linux-x64/clang/include/llvm/Support/TargetParser.h b/linux-x64/clang/include/llvm/Support/TargetParser.h
index a7e1a75..450e713 100644
--- a/linux-x64/clang/include/llvm/Support/TargetParser.h
+++ b/linux-x64/clang/include/llvm/Support/TargetParser.h
@@ -25,55 +25,12 @@
class StringRef;
// Target specific information in their own namespaces.
-// (ARM/AArch64 are declared in ARM/AArch64TargetParser.h)
+// (ARM/AArch64/X86 are declared in ARM/AArch64/X86TargetParser.h)
// These should be generated from TableGen because the information is already
// there, and there is where new information about targets will be added.
// FIXME: To TableGen this we need to make some table generated files available
// even if the back-end is not compiled with LLVM, plus we need to create a new
// back-end to TableGen to create these clean tables.
-namespace X86 {
-
-// This should be kept in sync with libcc/compiler-rt as its included by clang
-// as a proxy for what's in libgcc/compiler-rt.
-enum ProcessorVendors : unsigned {
- VENDOR_DUMMY,
-#define X86_VENDOR(ENUM, STRING) \
- ENUM,
-#include "llvm/Support/X86TargetParser.def"
- VENDOR_OTHER
-};
-
-// This should be kept in sync with libcc/compiler-rt as its included by clang
-// as a proxy for what's in libgcc/compiler-rt.
-enum ProcessorTypes : unsigned {
- CPU_TYPE_DUMMY,
-#define X86_CPU_TYPE(ARCHNAME, ENUM) \
- ENUM,
-#include "llvm/Support/X86TargetParser.def"
- CPU_TYPE_MAX
-};
-
-// This should be kept in sync with libcc/compiler-rt as its included by clang
-// as a proxy for what's in libgcc/compiler-rt.
-enum ProcessorSubtypes : unsigned {
- CPU_SUBTYPE_DUMMY,
-#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \
- ENUM,
-#include "llvm/Support/X86TargetParser.def"
- CPU_SUBTYPE_MAX
-};
-
-// This should be kept in sync with libcc/compiler-rt as it should be used
-// by clang as a proxy for what's in libgcc/compiler-rt.
-enum ProcessorFeatures {
-#define X86_FEATURE(VAL, ENUM) \
- ENUM = VAL,
-#include "llvm/Support/X86TargetParser.def"
-
-};
-
-} // namespace X86
-
namespace AMDGPU {
/// GPU kinds supported by the AMDGPU target.
@@ -105,17 +62,20 @@
// AMDGCN-based processors.
GK_GFX600 = 32,
GK_GFX601 = 33,
+ GK_GFX602 = 34,
GK_GFX700 = 40,
GK_GFX701 = 41,
GK_GFX702 = 42,
GK_GFX703 = 43,
GK_GFX704 = 44,
+ GK_GFX705 = 45,
GK_GFX801 = 50,
GK_GFX802 = 51,
GK_GFX803 = 52,
- GK_GFX810 = 53,
+ GK_GFX805 = 53,
+ GK_GFX810 = 54,
GK_GFX900 = 60,
GK_GFX902 = 61,
@@ -123,13 +83,18 @@
GK_GFX906 = 63,
GK_GFX908 = 64,
GK_GFX909 = 65,
+ GK_GFX90C = 66,
GK_GFX1010 = 71,
GK_GFX1011 = 72,
GK_GFX1012 = 73,
+ GK_GFX1030 = 75,
+ GK_GFX1031 = 76,
+ GK_GFX1032 = 77,
+ GK_GFX1033 = 78,
GK_AMDGCN_FIRST = GK_GFX600,
- GK_AMDGCN_LAST = GK_GFX1012,
+ GK_AMDGCN_LAST = GK_GFX1033,
};
/// Instruction set architecture version.
@@ -151,12 +116,21 @@
// Common features.
FEATURE_FAST_FMA_F32 = 1 << 4,
- FEATURE_FAST_DENORMAL_F32 = 1 << 5
+ FEATURE_FAST_DENORMAL_F32 = 1 << 5,
+
+ // Wavefront 32 is available.
+ FEATURE_WAVE32 = 1 << 6,
+
+ // Xnack is available.
+ FEATURE_XNACK = 1 << 7,
+
+ // Sram-ecc is available.
+ FEATURE_SRAMECC = 1 << 8,
};
StringRef getArchNameAMDGCN(GPUKind AK);
StringRef getArchNameR600(GPUKind AK);
-StringRef getCanonicalArchName(StringRef Arch);
+StringRef getCanonicalArchName(const Triple &T, StringRef Arch);
GPUKind parseArchAMDGCN(StringRef CPU);
GPUKind parseArchR600(StringRef CPU);
unsigned getArchAttrAMDGCN(GPUKind AK);
@@ -169,6 +143,36 @@
} // namespace AMDGPU
+namespace RISCV {
+
+enum CPUKind : unsigned {
+#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH) CK_##ENUM,
+#include "RISCVTargetParser.def"
+};
+
+enum FeatureKind : unsigned {
+ FK_INVALID = 0,
+ FK_NONE = 1,
+ FK_STDEXTM = 1 << 2,
+ FK_STDEXTA = 1 << 3,
+ FK_STDEXTF = 1 << 4,
+ FK_STDEXTD = 1 << 5,
+ FK_STDEXTC = 1 << 6,
+ FK_64BIT = 1 << 7,
+};
+
+bool checkCPUKind(CPUKind Kind, bool IsRV64);
+bool checkTuneCPUKind(CPUKind Kind, bool IsRV64);
+CPUKind parseCPUKind(StringRef CPU);
+CPUKind parseTuneCPUKind(StringRef CPU, bool IsRV64);
+StringRef getMArchFromMcpu(StringRef CPU);
+void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
+void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
+bool getCPUFeaturesExceptStdExt(CPUKind Kind, std::vector<StringRef> &Features);
+StringRef resolveTuneCPUAlias(StringRef TuneCPU, bool IsRV64);
+
+} // namespace RISCV
+
} // namespace llvm
#endif
diff --git a/linux-x64/clang/include/llvm/Support/TargetRegistry.h b/linux-x64/clang/include/llvm/Support/TargetRegistry.h
index bf75650..2c65eb6 100644
--- a/linux-x64/clang/include/llvm/Support/TargetRegistry.h
+++ b/linux-x64/clang/include/llvm/Support/TargetRegistry.h
@@ -128,7 +128,8 @@
using ArchMatchFnTy = bool (*)(Triple::ArchType Arch);
using MCAsmInfoCtorFnTy = MCAsmInfo *(*)(const MCRegisterInfo &MRI,
- const Triple &TT);
+ const Triple &TT,
+ const MCTargetOptions &Options);
using MCInstrInfoCtorFnTy = MCInstrInfo *(*)();
using MCInstrAnalysisCtorFnTy = MCInstrAnalysis *(*)(const MCInstrInfo *Info);
using MCRegInfoCtorFnTy = MCRegisterInfo *(*)(const Triple &TT);
@@ -335,11 +336,11 @@
/// feature set; it should always be provided. Generally this should be
/// either the target triple from the module, or the target triple of the
/// host if that does not exist.
- MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI,
- StringRef TheTriple) const {
+ MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI, StringRef TheTriple,
+ const MCTargetOptions &Options) const {
if (!MCAsmInfoCtorFn)
return nullptr;
- return MCAsmInfoCtorFn(MRI, Triple(TheTriple));
+ return MCAsmInfoCtorFn(MRI, Triple(TheTriple), Options);
}
/// createMCInstrInfo - Create a MCInstrInfo implementation.
@@ -473,7 +474,7 @@
const MCSubtargetInfo &STI, bool RelaxAll,
bool IncrementalLinkerCompatible,
bool DWARFMustBeAtTheEnd) const {
- MCStreamer *S;
+ MCStreamer *S = nullptr;
switch (T.getObjectFormat()) {
case Triple::UnknownObjectFormat:
llvm_unreachable("Unknown object format");
@@ -509,9 +510,11 @@
S = createWasmStreamer(Ctx, std::move(TAB), std::move(OW),
std::move(Emitter), RelaxAll);
break;
+ case Triple::GOFF:
+ report_fatal_error("GOFF MCObjectStreamer not implemented yet");
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)
@@ -948,9 +951,9 @@
}
private:
- static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/,
- const Triple &TT) {
- return new MCAsmInfoImpl(TT);
+ static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/, const Triple &TT,
+ const MCTargetOptions &Options) {
+ return new MCAsmInfoImpl(TT, Options);
}
};
diff --git a/linux-x64/clang/include/llvm/Support/TaskQueue.h b/linux-x64/clang/include/llvm/Support/TaskQueue.h
index df2ffde..6901a55 100644
--- a/linux-x64/clang/include/llvm/Support/TaskQueue.h
+++ b/linux-x64/clang/include/llvm/Support/TaskQueue.h
@@ -38,7 +38,7 @@
// type-specialized domain (before type erasure) and then erase this into a
// std::function.
template <typename Callable> struct Task {
- using ResultTy = typename std::result_of<Callable()>::type;
+ using ResultTy = std::result_of_t<Callable()>;
explicit Task(Callable C, TaskQueue &Parent)
: C(std::move(C)), P(std::make_shared<std::promise<ResultTy>>()),
Parent(&Parent) {}
@@ -78,13 +78,13 @@
/// used to wait for the task (and all previous tasks that have not yet
/// completed) to finish.
template <typename Callable>
- std::future<typename std::result_of<Callable()>::type> async(Callable &&C) {
+ std::future<std::result_of_t<Callable()>> async(Callable &&C) {
#if !LLVM_ENABLE_THREADS
static_assert(false,
"TaskQueue requires building with LLVM_ENABLE_THREADS!");
#endif
Task<Callable> T{std::move(C), *this};
- using ResultTy = typename std::result_of<Callable()>::type;
+ using ResultTy = std::result_of_t<Callable()>;
std::future<ResultTy> F = T.P->get_future();
{
std::lock_guard<std::mutex> Lock(QueueLock);
@@ -98,7 +98,7 @@
IsTaskInFlight = true;
}
}
- return std::move(F);
+ return F;
}
private:
diff --git a/linux-x64/clang/include/llvm/Support/ThreadPool.h b/linux-x64/clang/include/llvm/Support/ThreadPool.h
index 4bcbaa3..528fb32 100644
--- a/linux-x64/clang/include/llvm/Support/ThreadPool.h
+++ b/linux-x64/clang/include/llvm/Support/ThreadPool.h
@@ -14,6 +14,7 @@
#define LLVM_SUPPORT_THREAD_POOL_H
#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Threading.h"
#include "llvm/Support/thread.h"
#include <future>
@@ -38,12 +39,11 @@
using TaskTy = std::function<void()>;
using PackagedTaskTy = std::packaged_task<void()>;
- /// Construct a pool with the number of threads found by
- /// hardware_concurrency().
- ThreadPool();
-
- /// Construct a pool of \p ThreadCount threads
- ThreadPool(unsigned ThreadCount);
+ /// Construct a pool using the hardware strategy \p S for mapping hardware
+ /// execution resources (threads, cores, CPUs)
+ /// Defaults to using the maximum execution resources in the system, but
+ /// accounting for the affinity mask.
+ ThreadPool(ThreadPoolStrategy S = hardware_concurrency());
/// Blocking destructor: the pool will wait for all the threads to complete.
~ThreadPool();
@@ -68,7 +68,11 @@
/// It is an error to try to add new tasks while blocking on this call.
void wait();
+ unsigned getThreadCount() const { return ThreadCount; }
+
private:
+ bool workCompletedUnlocked() { return !ActiveThreads && Tasks.empty(); }
+
/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
std::shared_future<void> asyncImpl(TaskTy F);
@@ -83,17 +87,18 @@
std::mutex QueueLock;
std::condition_variable QueueCondition;
- /// Locking and signaling for job completion
- std::mutex CompletionLock;
+ /// Signaling for job completion
std::condition_variable CompletionCondition;
/// Keep track of the number of thread actually busy
- std::atomic<unsigned> ActiveThreads;
+ unsigned ActiveThreads = 0;
#if LLVM_ENABLE_THREADS // avoids warning for unused variable
/// Signal for the destruction of the pool, asking thread to exit.
- bool EnableFlag;
+ bool EnableFlag = true;
#endif
+
+ unsigned ThreadCount;
};
}
diff --git a/linux-x64/clang/include/llvm/Support/Threading.h b/linux-x64/clang/include/llvm/Support/Threading.h
index 46d413d..46cf825 100644
--- a/linux-x64/clang/include/llvm/Support/Threading.h
+++ b/linux-x64/clang/include/llvm/Support/Threading.h
@@ -14,6 +14,8 @@
#ifndef LLVM_SUPPORT_THREADING_H
#define LLVM_SUPPORT_THREADING_H
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
#include "llvm/Support/Compiler.h"
@@ -52,9 +54,8 @@
/// false otherwise.
bool llvm_is_multithreaded();
-/// llvm_execute_on_thread - Execute the given \p UserFn on a separate
-/// thread, passing it the provided \p UserData and waits for thread
-/// completion.
+/// Execute the given \p UserFn on a separate thread, passing it the provided \p
+/// UserData and waits for thread completion.
///
/// This function does not guarantee that the code will actually be executed
/// on a separate thread or honoring the requested stack size, but tries to do
@@ -62,10 +63,26 @@
///
/// \param UserFn - The callback to execute.
/// \param UserData - An argument to pass to the callback function.
-/// \param RequestedStackSize - If non-zero, a requested size (in bytes) for
-/// the thread stack.
-void llvm_execute_on_thread(void (*UserFn)(void *), void *UserData,
- unsigned RequestedStackSize = 0);
+/// \param StackSizeInBytes - A requested size (in bytes) for the thread stack
+/// (or None for default)
+void llvm_execute_on_thread(
+ void (*UserFn)(void *), void *UserData,
+ llvm::Optional<unsigned> StackSizeInBytes = llvm::None);
+
+/// Schedule the given \p Func for execution on a separate thread, then return
+/// to the caller immediately. Roughly equivalent to
+/// `std::thread(Func).detach()`, except it allows requesting a specific stack
+/// size, if supported for the platform.
+///
+/// This function would report a fatal error if it can't execute the code
+/// on a separate thread.
+///
+/// \param Func - The callback to execute.
+/// \param StackSizeInBytes - A requested size (in bytes) for the thread stack
+/// (or None for default)
+void llvm_execute_on_thread_async(
+ llvm::unique_function<void()> Func,
+ llvm::Optional<unsigned> StackSizeInBytes = llvm::None);
#if LLVM_THREADING_USE_STD_CALL_ONCE
@@ -127,20 +144,91 @@
#endif
}
- /// Get the amount of currency to use for tasks requiring significant
- /// memory or other resources. Currently based on physical cores, if
- /// available for the host system, otherwise falls back to
- /// thread::hardware_concurrency().
- /// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF
- unsigned heavyweight_hardware_concurrency();
+ /// This tells how a thread pool will be used
+ class ThreadPoolStrategy {
+ public:
+ // The default value (0) means all available threads should be used,
+ // taking the affinity mask into account. If set, this value only represents
+ // a suggested high bound, the runtime might choose a lower value (not
+ // higher).
+ unsigned ThreadsRequested = 0;
- /// Get the number of threads that the current program can execute
- /// concurrently. On some systems std::thread::hardware_concurrency() returns
- /// the total number of cores, without taking affinity into consideration.
- /// Returns 1 when LLVM is configured with LLVM_ENABLE_THREADS=OFF.
- /// Fallback to std::thread::hardware_concurrency() if sched_getaffinity is
- /// not available.
- unsigned hardware_concurrency();
+ // If SMT is active, use hyper threads. If false, there will be only one
+ // std::thread per core.
+ bool UseHyperThreads = true;
+
+ // If set, will constrain 'ThreadsRequested' to the number of hardware
+ // threads, or hardware cores.
+ bool Limit = false;
+
+ /// Retrieves the max available threads for the current strategy. This
+ /// accounts for affinity masks and takes advantage of all CPU sockets.
+ unsigned compute_thread_count() const;
+
+ /// Assign the current thread to an ideal hardware CPU or NUMA node. In a
+ /// multi-socket system, this ensures threads are assigned to all CPU
+ /// sockets. \p ThreadPoolNum represents a number bounded by [0,
+ /// compute_thread_count()).
+ void apply_thread_strategy(unsigned ThreadPoolNum) const;
+
+ /// Finds the CPU socket where a thread should go. Returns 'None' if the
+ /// thread shall remain on the actual CPU socket.
+ Optional<unsigned> compute_cpu_socket(unsigned ThreadPoolNum) const;
+ };
+
+ /// Build a strategy from a number of threads as a string provided in \p Num.
+ /// When Num is above the max number of threads specified by the \p Default
+ /// strategy, we attempt to equally allocate the threads on all CPU sockets.
+ /// "0" or an empty string will return the \p Default strategy.
+ /// "all" for using all hardware threads.
+ Optional<ThreadPoolStrategy>
+ get_threadpool_strategy(StringRef Num, ThreadPoolStrategy Default = {});
+
+ /// Returns a thread strategy for tasks requiring significant memory or other
+ /// resources. To be used for workloads where hardware_concurrency() proves to
+ /// be less efficient. Avoid this strategy if doing lots of I/O. Currently
+ /// based on physical cores, if available for the host system, otherwise falls
+ /// back to hardware_concurrency(). Returns 1 when LLVM is configured with
+ /// LLVM_ENABLE_THREADS = OFF.
+ inline ThreadPoolStrategy
+ heavyweight_hardware_concurrency(unsigned ThreadCount = 0) {
+ ThreadPoolStrategy S;
+ S.UseHyperThreads = false;
+ S.ThreadsRequested = ThreadCount;
+ return S;
+ }
+
+ /// Like heavyweight_hardware_concurrency() above, but builds a strategy
+ /// based on the rules described for get_threadpool_strategy().
+ /// If \p Num is invalid, returns a default strategy where one thread per
+ /// hardware core is used.
+ inline ThreadPoolStrategy heavyweight_hardware_concurrency(StringRef Num) {
+ Optional<ThreadPoolStrategy> S =
+ get_threadpool_strategy(Num, heavyweight_hardware_concurrency());
+ if (S)
+ return *S;
+ return heavyweight_hardware_concurrency();
+ }
+
+ /// Returns a default thread strategy where all available hardware resources
+ /// are to be used, except for those initially excluded by an affinity mask.
+ /// This function takes affinity into consideration. Returns 1 when LLVM is
+ /// configured with LLVM_ENABLE_THREADS=OFF.
+ inline ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount = 0) {
+ ThreadPoolStrategy S;
+ S.ThreadsRequested = ThreadCount;
+ return S;
+ }
+
+ /// Returns an optimal thread strategy to execute specified amount of tasks.
+ /// This strategy should prevent us from creating too many threads if we
+ /// occasionaly have an unexpectedly small amount of tasks.
+ inline ThreadPoolStrategy optimal_concurrency(unsigned TaskCount = 0) {
+ ThreadPoolStrategy S;
+ S.Limit = true;
+ S.ThreadsRequested = TaskCount;
+ return S;
+ }
/// Return the current thread id, as used in various OS system calls.
/// Note that not all platforms guarantee that the value returned will be
@@ -168,6 +256,14 @@
/// the operation succeeded or failed is returned.
void get_thread_name(SmallVectorImpl<char> &Name);
+ /// Returns a mask that represents on which hardware thread, core, CPU, NUMA
+ /// group, the calling thread can be executed. On Windows, threads cannot
+ /// cross CPU sockets boundaries.
+ llvm::BitVector get_thread_affinity_mask();
+
+ /// Returns how many physical CPUs or NUMA groups the system has.
+ unsigned get_cpus();
+
enum class ThreadPriority {
Background = 0,
Default = 1,
diff --git a/linux-x64/clang/include/llvm/Support/TimeProfiler.h b/linux-x64/clang/include/llvm/Support/TimeProfiler.h
index 72b6f71..b6f8a64 100644
--- a/linux-x64/clang/include/llvm/Support/TimeProfiler.h
+++ b/linux-x64/clang/include/llvm/Support/TimeProfiler.h
@@ -9,31 +9,44 @@
#ifndef LLVM_SUPPORT_TIME_PROFILER_H
#define LLVM_SUPPORT_TIME_PROFILER_H
+#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
struct TimeTraceProfiler;
-extern TimeTraceProfiler *TimeTraceProfilerInstance;
+TimeTraceProfiler *getTimeTraceProfilerInstance();
/// Initialize the time trace profiler.
/// This sets up the global \p TimeTraceProfilerInstance
/// variable to be the profiler instance.
-void timeTraceProfilerInitialize();
+void timeTraceProfilerInitialize(unsigned TimeTraceGranularity,
+ StringRef ProcName);
/// Cleanup the time trace profiler, if it was initialized.
void timeTraceProfilerCleanup();
+/// Finish a time trace profiler running on a worker thread.
+void timeTraceProfilerFinishThread();
+
/// Is the time trace profiler enabled, i.e. initialized?
inline bool timeTraceProfilerEnabled() {
- return TimeTraceProfilerInstance != nullptr;
+ return getTimeTraceProfilerInstance() != nullptr;
}
-/// Write profiling data to output file.
+/// Write profiling data to output stream.
/// Data produced is JSON, in Chrome "Trace Event" format, see
/// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
void timeTraceProfilerWrite(raw_pwrite_stream &OS);
+/// Write profiling data to a file.
+/// The function will write to \p PreferredFileName if provided, if not
+/// then will write to \p FallbackFileName appending .time-trace.
+/// Returns a StringError indicating a failure if the function is
+/// unable to open the file for writing.
+Error timeTraceProfilerWrite(StringRef PreferredFileName,
+ StringRef FallbackFileName);
+
/// Manually begin a time section, with the given \p Name and \p Detail.
/// Profiler copies the string data, so the pointers can be given into
/// temporaries. Time sections can be hierarchical; every Begin must have a
@@ -57,16 +70,20 @@
TimeTraceScope(TimeTraceScope &&) = delete;
TimeTraceScope &operator=(TimeTraceScope &&) = delete;
+ TimeTraceScope(StringRef Name) {
+ if (getTimeTraceProfilerInstance() != nullptr)
+ timeTraceProfilerBegin(Name, StringRef(""));
+ }
TimeTraceScope(StringRef Name, StringRef Detail) {
- if (TimeTraceProfilerInstance != nullptr)
+ if (getTimeTraceProfilerInstance() != nullptr)
timeTraceProfilerBegin(Name, Detail);
}
TimeTraceScope(StringRef Name, llvm::function_ref<std::string()> Detail) {
- if (TimeTraceProfilerInstance != nullptr)
+ if (getTimeTraceProfilerInstance() != nullptr)
timeTraceProfilerBegin(Name, Detail);
}
~TimeTraceScope() {
- if (TimeTraceProfilerInstance != nullptr)
+ if (getTimeTraceProfilerInstance() != nullptr)
timeTraceProfilerEnd();
}
};
diff --git a/linux-x64/clang/include/llvm/Support/Timer.h b/linux-x64/clang/include/llvm/Support/Timer.h
index 76c9bc7..045ac44 100644
--- a/linux-x64/clang/include/llvm/Support/Timer.h
+++ b/linux-x64/clang/include/llvm/Support/Timer.h
@@ -78,18 +78,18 @@
TimeRecord StartTime; ///< The time startTimer() was last called.
std::string Name; ///< The name of this time variable.
std::string Description; ///< Description of this time variable.
- bool Running; ///< Is the timer currently running?
- bool Triggered; ///< Has the timer ever been triggered?
+ bool Running = false; ///< Is the timer currently running?
+ bool Triggered = false; ///< Has the timer ever been triggered?
TimerGroup *TG = nullptr; ///< The TimerGroup this Timer is in.
- Timer **Prev; ///< Pointer to \p Next of previous timer in group.
- Timer *Next; ///< Next timer in the group.
+ Timer **Prev = nullptr; ///< Pointer to \p Next of previous timer in group.
+ Timer *Next = nullptr; ///< Next timer in the group.
public:
- explicit Timer(StringRef Name, StringRef Description) {
- init(Name, Description);
+ explicit Timer(StringRef TimerName, StringRef TimerDescription) {
+ init(TimerName, TimerDescription);
}
- Timer(StringRef Name, StringRef Description, TimerGroup &tg) {
- init(Name, Description, tg);
+ Timer(StringRef TimerName, StringRef TimerDescription, TimerGroup &tg) {
+ init(TimerName, TimerDescription, tg);
}
Timer(const Timer &RHS) {
assert(!RHS.TG && "Can only copy uninitialized timers");
@@ -102,8 +102,8 @@
/// Create an uninitialized timer, client must use 'init'.
explicit Timer() {}
- void init(StringRef Name, StringRef Description);
- void init(StringRef Name, StringRef Description, TimerGroup &tg);
+ void init(StringRef TimerName, StringRef TimerDescription);
+ void init(StringRef TimerName, StringRef TimerDescription, TimerGroup &tg);
const std::string &getName() const { return Name; }
const std::string &getDescription() const { return Description; }
@@ -174,6 +174,7 @@
std::string Description;
PrintRecord(const PrintRecord &Other) = default;
+ PrintRecord &operator=(const PrintRecord &Other) = default;
PrintRecord(const TimeRecord &Time, const std::string &Name,
const std::string &Description)
: Time(Time), Name(Name), Description(Description) {}
@@ -229,6 +230,11 @@
/// used by the Statistic code to influence the construction and destruction
/// order of the global timer lists.
static void ConstructTimerLists();
+
+ /// This makes the default group unmanaged, and lets the user manage the
+ /// group's lifetime.
+ static std::unique_ptr<TimerGroup> aquireDefaultGroup();
+
private:
friend class Timer;
friend void PrintStatisticsJSON(raw_ostream &OS);
diff --git a/linux-x64/clang/include/llvm/Support/ToolOutputFile.h b/linux-x64/clang/include/llvm/Support/ToolOutputFile.h
index a99e327..cf01b9e 100644
--- a/linux-x64/clang/include/llvm/Support/ToolOutputFile.h
+++ b/linux-x64/clang/include/llvm/Support/ToolOutputFile.h
@@ -13,6 +13,7 @@
#ifndef LLVM_SUPPORT_TOOLOUTPUTFILE_H
#define LLVM_SUPPORT_TOOLOUTPUTFILE_H
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
@@ -38,8 +39,12 @@
~CleanupInstaller();
} Installer;
- /// The contained stream. This is intentionally declared after Installer.
- raw_fd_ostream OS;
+ /// Storage for the stream, if we're owning our own stream. This is
+ /// intentionally declared after Installer.
+ Optional<raw_fd_ostream> OSHolder;
+
+ /// The actual stream to use.
+ raw_fd_ostream *OS;
public:
/// This constructor's arguments are passed to raw_fd_ostream's
@@ -50,7 +55,7 @@
ToolOutputFile(StringRef Filename, int FD);
/// Return the contained raw_fd_ostream.
- raw_fd_ostream &os() { return OS; }
+ raw_fd_ostream &os() { return *OS; }
/// Indicate that the tool's job wrt this output file has been successful and
/// the file should not be deleted.
diff --git a/linux-x64/clang/include/llvm/Support/TrailingObjects.h b/linux-x64/clang/include/llvm/Support/TrailingObjects.h
index 8cf4f7a..0d9c450 100644
--- a/linux-x64/clang/include/llvm/Support/TrailingObjects.h
+++ b/linux-x64/clang/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 @@
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 @@
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 @@
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 @@
// 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.
@@ -332,8 +326,8 @@
/// used in the class; they are supplied here redundantly only so
/// that it's clear what the counts are counting in callers.
template <typename... Tys>
- static constexpr typename std::enable_if<
- std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t>::type
+ static constexpr std::enable_if_t<
+ std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t>
additionalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType<
TrailingTys, size_t>::type... Counts) {
return ParentType::additionalSizeToAllocImpl(0, Counts...);
@@ -344,8 +338,8 @@
/// additionalSizeToAlloc, except it *does* include the size of the base
/// object.
template <typename... Tys>
- static constexpr typename std::enable_if<
- std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t>::type
+ static constexpr std::enable_if_t<
+ std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t>
totalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType<
TrailingTys, size_t>::type... Counts) {
return sizeof(BaseTy) + ParentType::additionalSizeToAllocImpl(0, Counts...);
@@ -369,7 +363,9 @@
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/linux-x64/clang/include/llvm/Support/TrigramIndex.h b/linux-x64/clang/include/llvm/Support/TrigramIndex.h
index 9351c2d..360ab94 100644
--- a/linux-x64/clang/include/llvm/Support/TrigramIndex.h
+++ b/linux-x64/clang/include/llvm/Support/TrigramIndex.h
@@ -27,8 +27,7 @@
#define LLVM_SUPPORT_TRIGRAMINDEX_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
-
+#include "llvm/ADT/StringRef.h"
#include <string>
#include <unordered_map>
#include <vector>
diff --git a/linux-x64/clang/include/llvm/Support/TypeSize.h b/linux-x64/clang/include/llvm/Support/TypeSize.h
new file mode 100644
index 0000000..d277aff
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/TypeSize.h
@@ -0,0 +1,531 @@
+//===- 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 "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/WithColor.h"
+
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <cstdint>
+#include <type_traits>
+
+namespace llvm {
+
+template <typename LeafTy> struct LinearPolyBaseTypeTraits {};
+
+//===----------------------------------------------------------------------===//
+// LinearPolyBase - a base class for linear polynomials with multiple
+// dimensions. This can e.g. be used to describe offsets that are have both a
+// fixed and scalable component.
+//===----------------------------------------------------------------------===//
+
+/// LinearPolyBase describes a linear polynomial:
+/// c0 * scale0 + c1 * scale1 + ... + cK * scaleK
+/// where the scale is implicit, so only the coefficients are encoded.
+template <typename LeafTy>
+class LinearPolyBase {
+public:
+ using ScalarTy = typename LinearPolyBaseTypeTraits<LeafTy>::ScalarTy;
+ static constexpr auto Dimensions = LinearPolyBaseTypeTraits<LeafTy>::Dimensions;
+ static_assert(Dimensions != std::numeric_limits<unsigned>::max(),
+ "Dimensions out of range");
+
+private:
+ std::array<ScalarTy, Dimensions> Coefficients;
+
+protected:
+ LinearPolyBase(ArrayRef<ScalarTy> Values) {
+ std::copy(Values.begin(), Values.end(), Coefficients.begin());
+ }
+
+public:
+ friend LeafTy &operator+=(LeafTy &LHS, const LeafTy &RHS) {
+ for (unsigned I=0; I<Dimensions; ++I)
+ LHS.Coefficients[I] += RHS.Coefficients[I];
+ return LHS;
+ }
+
+ friend LeafTy &operator-=(LeafTy &LHS, const LeafTy &RHS) {
+ for (unsigned I=0; I<Dimensions; ++I)
+ LHS.Coefficients[I] -= RHS.Coefficients[I];
+ return LHS;
+ }
+
+ friend LeafTy &operator*=(LeafTy &LHS, ScalarTy RHS) {
+ for (auto &C : LHS.Coefficients)
+ C *= RHS;
+ return LHS;
+ }
+
+ friend LeafTy operator+(const LeafTy &LHS, const LeafTy &RHS) {
+ LeafTy Copy = LHS;
+ return Copy += RHS;
+ }
+
+ friend LeafTy operator-(const LeafTy &LHS, const LeafTy &RHS) {
+ LeafTy Copy = LHS;
+ return Copy -= RHS;
+ }
+
+ friend LeafTy operator*(const LeafTy &LHS, ScalarTy RHS) {
+ LeafTy Copy = LHS;
+ return Copy *= RHS;
+ }
+
+ template <typename U = ScalarTy>
+ friend typename std::enable_if_t<std::is_signed<U>::value, LeafTy>
+ operator-(const LeafTy &LHS) {
+ LeafTy Copy = LHS;
+ return Copy *= -1;
+ }
+
+ bool operator==(const LinearPolyBase &RHS) const {
+ return std::equal(Coefficients.begin(), Coefficients.end(),
+ RHS.Coefficients.begin());
+ }
+
+ bool operator!=(const LinearPolyBase &RHS) const {
+ return !(*this == RHS);
+ }
+
+ bool isZero() const {
+ return all_of(Coefficients, [](const ScalarTy &C) { return C == 0; });
+ }
+ bool isNonZero() const { return !isZero(); }
+ explicit operator bool() const { return isNonZero(); }
+
+ ScalarTy getValue(unsigned Dim) const { return Coefficients[Dim]; }
+};
+
+//===----------------------------------------------------------------------===//
+// StackOffset - Represent an offset with named fixed and scalable components.
+//===----------------------------------------------------------------------===//
+
+class StackOffset;
+template <> struct LinearPolyBaseTypeTraits<StackOffset> {
+ using ScalarTy = int64_t;
+ static constexpr unsigned Dimensions = 2;
+};
+
+/// StackOffset is a class to represent an offset with 2 dimensions,
+/// named fixed and scalable, respectively. This class allows a value for both
+/// dimensions to depict e.g. "8 bytes and 16 scalable bytes", which is needed
+/// to represent stack offsets.
+class StackOffset : public LinearPolyBase<StackOffset> {
+protected:
+ StackOffset(ScalarTy Fixed, ScalarTy Scalable)
+ : LinearPolyBase<StackOffset>({Fixed, Scalable}) {}
+
+public:
+ StackOffset() : StackOffset({0, 0}) {}
+ StackOffset(const LinearPolyBase<StackOffset> &Other)
+ : LinearPolyBase<StackOffset>(Other) {}
+ static StackOffset getFixed(ScalarTy Fixed) { return {Fixed, 0}; }
+ static StackOffset getScalable(ScalarTy Scalable) { return {0, Scalable}; }
+ static StackOffset get(ScalarTy Fixed, ScalarTy Scalable) {
+ return {Fixed, Scalable};
+ }
+
+ ScalarTy getFixed() const { return this->getValue(0); }
+ ScalarTy getScalable() const { return this->getValue(1); }
+};
+
+//===----------------------------------------------------------------------===//
+// UnivariateLinearPolyBase - a base class for linear polynomials with multiple
+// dimensions, but where only one dimension can be set at any time.
+// This can e.g. be used to describe sizes that are either fixed or scalable.
+//===----------------------------------------------------------------------===//
+
+/// UnivariateLinearPolyBase is a base class for ElementCount and TypeSize.
+/// Like LinearPolyBase it tries to represent a linear polynomial
+/// where only one dimension can be set at any time, e.g.
+/// 0 * scale0 + 0 * scale1 + ... + cJ * scaleJ + ... + 0 * scaleK
+/// The dimension that is set is the univariate dimension.
+template <typename LeafTy>
+class UnivariateLinearPolyBase {
+public:
+ using ScalarTy = typename LinearPolyBaseTypeTraits<LeafTy>::ScalarTy;
+ static constexpr auto Dimensions = LinearPolyBaseTypeTraits<LeafTy>::Dimensions;
+ static_assert(Dimensions != std::numeric_limits<unsigned>::max(),
+ "Dimensions out of range");
+
+protected:
+ ScalarTy Value; // The value at the univeriate dimension.
+ unsigned UnivariateDim; // The univeriate dimension.
+
+ UnivariateLinearPolyBase(ScalarTy Val, unsigned UnivariateDim)
+ : Value(Val), UnivariateDim(UnivariateDim) {
+ assert(UnivariateDim < Dimensions && "Dimension out of range");
+ }
+
+ friend LeafTy &operator+=(LeafTy &LHS, const LeafTy &RHS) {
+ assert(LHS.UnivariateDim == RHS.UnivariateDim && "Invalid dimensions");
+ LHS.Value += RHS.Value;
+ return LHS;
+ }
+
+ friend LeafTy &operator-=(LeafTy &LHS, const LeafTy &RHS) {
+ assert(LHS.UnivariateDim == RHS.UnivariateDim && "Invalid dimensions");
+ LHS.Value -= RHS.Value;
+ return LHS;
+ }
+
+ friend LeafTy &operator*=(LeafTy &LHS, ScalarTy RHS) {
+ LHS.Value *= RHS;
+ return LHS;
+ }
+
+ friend LeafTy operator+(const LeafTy &LHS, const LeafTy &RHS) {
+ LeafTy Copy = LHS;
+ return Copy += RHS;
+ }
+
+ friend LeafTy operator-(const LeafTy &LHS, const LeafTy &RHS) {
+ LeafTy Copy = LHS;
+ return Copy -= RHS;
+ }
+
+ friend LeafTy operator*(const LeafTy &LHS, ScalarTy RHS) {
+ LeafTy Copy = LHS;
+ return Copy *= RHS;
+ }
+
+ template <typename U = ScalarTy>
+ friend typename std::enable_if<std::is_signed<U>::value, LeafTy>::type
+ operator-(const LeafTy &LHS) {
+ LeafTy Copy = LHS;
+ return Copy *= -1;
+ }
+
+public:
+ bool operator==(const UnivariateLinearPolyBase &RHS) const {
+ return Value == RHS.Value && UnivariateDim == RHS.UnivariateDim;
+ }
+
+ bool operator!=(const UnivariateLinearPolyBase &RHS) const {
+ return !(*this == RHS);
+ }
+
+ bool isZero() const { return !Value; }
+ bool isNonZero() const { return !isZero(); }
+ explicit operator bool() const { return isNonZero(); }
+ ScalarTy getValue() const { return Value; }
+ ScalarTy getValue(unsigned Dim) const {
+ return Dim == UnivariateDim ? Value : 0;
+ }
+
+ /// Add \p RHS to the value at the univariate dimension.
+ LeafTy getWithIncrement(ScalarTy RHS) {
+ return static_cast<LeafTy>(
+ UnivariateLinearPolyBase(Value + RHS, UnivariateDim));
+ }
+
+ /// Subtract \p RHS from the value at the univariate dimension.
+ LeafTy getWithDecrement(ScalarTy RHS) {
+ return static_cast<LeafTy>(
+ UnivariateLinearPolyBase(Value - RHS, UnivariateDim));
+ }
+};
+
+
+//===----------------------------------------------------------------------===//
+// LinearPolySize - base class for fixed- or scalable sizes.
+// ^ ^
+// | |
+// | +----- ElementCount - Leaf class to represent an element count
+// | (vscale x unsigned)
+// |
+// +-------- TypeSize - Leaf class to represent a type size
+// (vscale x uint64_t)
+//===----------------------------------------------------------------------===//
+
+/// LinearPolySize is a base class to represent sizes. It is either
+/// fixed-sized or it is scalable-sized, but it cannot be both.
+template <typename LeafTy>
+class LinearPolySize : public UnivariateLinearPolyBase<LeafTy> {
+ // Make the parent class a friend, so that it can access the protected
+ // conversion/copy-constructor for UnivariatePolyBase<LeafTy> ->
+ // LinearPolySize<LeafTy>.
+ friend class UnivariateLinearPolyBase<LeafTy>;
+
+public:
+ using ScalarTy = typename UnivariateLinearPolyBase<LeafTy>::ScalarTy;
+ enum Dims : unsigned { FixedDim = 0, ScalableDim = 1 };
+
+protected:
+ LinearPolySize(ScalarTy MinVal, Dims D)
+ : UnivariateLinearPolyBase<LeafTy>(MinVal, D) {}
+
+ LinearPolySize(const UnivariateLinearPolyBase<LeafTy> &V)
+ : UnivariateLinearPolyBase<LeafTy>(V) {}
+
+public:
+
+ static LeafTy getFixed(ScalarTy MinVal) {
+ return static_cast<LeafTy>(LinearPolySize(MinVal, FixedDim));
+ }
+ static LeafTy getScalable(ScalarTy MinVal) {
+ return static_cast<LeafTy>(LinearPolySize(MinVal, ScalableDim));
+ }
+ static LeafTy get(ScalarTy MinVal, bool Scalable) {
+ return static_cast<LeafTy>(
+ LinearPolySize(MinVal, Scalable ? ScalableDim : FixedDim));
+ }
+ static LeafTy getNull() { return get(0, false); }
+
+ /// Returns the minimum value this size can represent.
+ ScalarTy getKnownMinValue() const { return this->getValue(); }
+ /// Returns whether the size is scaled by a runtime quantity (vscale).
+ bool isScalable() const { return this->UnivariateDim == ScalableDim; }
+ /// A return value of true indicates we know at compile time that the number
+ /// of elements (vscale * Min) is definitely even. However, returning false
+ /// does not guarantee that the total number of elements is odd.
+ bool isKnownEven() const { return (getKnownMinValue() & 0x1) == 0; }
+ /// This function tells the caller whether the element count is known at
+ /// compile time to be a multiple of the scalar value RHS.
+ bool isKnownMultipleOf(ScalarTy RHS) const {
+ return getKnownMinValue() % RHS == 0;
+ }
+
+ // Return the minimum value with the assumption that the count is exact.
+ // Use in places where a scalable count doesn't make sense (e.g. non-vector
+ // types, or vectors in backends which don't support scalable vectors).
+ ScalarTy getFixedValue() const {
+ assert(!isScalable() &&
+ "Request for a fixed element count on a scalable object");
+ return getKnownMinValue();
+ }
+
+ // For some 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.
+ //
+ // All the functions below make use of the fact vscale is always >= 1, which
+ // means that <vscale x 4 x i32> is guaranteed to be >= <4 x i32>, etc.
+
+ static bool isKnownLT(const LinearPolySize &LHS, const LinearPolySize &RHS) {
+ if (!LHS.isScalable() || RHS.isScalable())
+ return LHS.getKnownMinValue() < RHS.getKnownMinValue();
+ return false;
+ }
+
+ static bool isKnownGT(const LinearPolySize &LHS, const LinearPolySize &RHS) {
+ if (LHS.isScalable() || !RHS.isScalable())
+ return LHS.getKnownMinValue() > RHS.getKnownMinValue();
+ return false;
+ }
+
+ static bool isKnownLE(const LinearPolySize &LHS, const LinearPolySize &RHS) {
+ if (!LHS.isScalable() || RHS.isScalable())
+ return LHS.getKnownMinValue() <= RHS.getKnownMinValue();
+ return false;
+ }
+
+ static bool isKnownGE(const LinearPolySize &LHS, const LinearPolySize &RHS) {
+ if (LHS.isScalable() || !RHS.isScalable())
+ return LHS.getKnownMinValue() >= RHS.getKnownMinValue();
+ return false;
+ }
+
+ /// We do not provide the '/' operator here because division for polynomial
+ /// types does not work in the same way as for normal integer types. We can
+ /// only divide the minimum value (or coefficient) by RHS, which is not the
+ /// same as
+ /// (Min * Vscale) / RHS
+ /// The caller is recommended to use this function in combination with
+ /// isKnownMultipleOf(RHS), which lets the caller know if it's possible to
+ /// perform a lossless divide by RHS.
+ LeafTy divideCoefficientBy(ScalarTy RHS) const {
+ return static_cast<LeafTy>(
+ LinearPolySize::get(getKnownMinValue() / RHS, isScalable()));
+ }
+
+ LeafTy coefficientNextPowerOf2() const {
+ return static_cast<LeafTy>(LinearPolySize::get(
+ static_cast<ScalarTy>(llvm::NextPowerOf2(getKnownMinValue())),
+ isScalable()));
+ }
+
+ /// Printing function.
+ void print(raw_ostream &OS) const {
+ if (isScalable())
+ OS << "vscale x ";
+ OS << getKnownMinValue();
+ }
+};
+
+class ElementCount;
+template <> struct LinearPolyBaseTypeTraits<ElementCount> {
+ using ScalarTy = unsigned;
+ static constexpr unsigned Dimensions = 2;
+};
+
+class ElementCount : public LinearPolySize<ElementCount> {
+public:
+
+ ElementCount(const LinearPolySize<ElementCount> &V) : LinearPolySize(V) {}
+
+ /// Counting predicates.
+ ///
+ ///@{ Number of elements..
+ /// Exactly one element.
+ bool isScalar() const { return !isScalable() && getKnownMinValue() == 1; }
+ /// One or more elements.
+ bool isVector() const {
+ return (isScalable() && getKnownMinValue() != 0) || getKnownMinValue() > 1;
+ }
+ ///@}
+};
+
+// This class is used to represent the size of types. If the type is of fixed
+class TypeSize;
+template <> struct LinearPolyBaseTypeTraits<TypeSize> {
+ using ScalarTy = uint64_t;
+ static constexpr unsigned Dimensions = 2;
+};
+
+// TODO: Most functionality in this class will gradually be phased out
+// so it will resemble LinearPolySize as much as possible.
+//
+// TypeSize 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 : public LinearPolySize<TypeSize> {
+public:
+ TypeSize(const LinearPolySize<TypeSize> &V) : LinearPolySize(V) {}
+ TypeSize(ScalarTy MinVal, bool IsScalable)
+ : LinearPolySize(LinearPolySize::get(MinVal, IsScalable)) {}
+
+ static TypeSize Fixed(ScalarTy MinVal) { return TypeSize(MinVal, false); }
+ static TypeSize Scalable(ScalarTy MinVal) { return TypeSize(MinVal, true); }
+
+ ScalarTy getFixedSize() const { return getFixedValue(); }
+ ScalarTy getKnownMinSize() const { return getKnownMinValue(); }
+
+ // All code for this class below this point is needed because of the
+ // temporary implicit conversion to uint64_t. The operator overloads are
+ // needed because otherwise the conversion of the parent class
+ // UnivariateLinearPolyBase -> TypeSize is ambiguous.
+ // TODO: Remove the implicit conversion.
+
+ // Casts to a uint64_t if this is a fixed-width size.
+ //
+ // This interface is deprecated and will be removed in a future version
+ // of LLVM in favour of upgrading uses that rely on this implicit conversion
+ // to uint64_t. Calls to functions that return a TypeSize should use the
+ // proper interfaces to TypeSize.
+ // In practice this is mostly calls to MVT/EVT::getSizeInBits().
+ //
+ // To determine how to upgrade the code:
+ //
+ // if (<algorithm works for both scalable and fixed-width vectors>)
+ // use getKnownMinValue()
+ // else if (<algorithm works only for fixed-width vectors>) {
+ // if <algorithm can be adapted for both scalable and fixed-width vectors>
+ // update the algorithm and use getKnownMinValue()
+ // else
+ // bail out early for scalable vectors and use getFixedValue()
+ // }
+ operator ScalarTy() const {
+#ifdef STRICT_FIXED_SIZE_VECTORS
+ return getFixedValue();
+#else
+ if (isScalable())
+ WithColor::warning() << "Compiler has made implicit assumption that "
+ "TypeSize is not scalable. This may or may not "
+ "lead to broken code.\n";
+ return getKnownMinValue();
+#endif
+ }
+
+ // Additional operators needed to avoid ambiguous parses
+ // because of the implicit conversion hack.
+ friend TypeSize operator*(const TypeSize &LHS, const int RHS) {
+ return LHS * (ScalarTy)RHS;
+ }
+ friend TypeSize operator*(const TypeSize &LHS, const unsigned RHS) {
+ return LHS * (ScalarTy)RHS;
+ }
+ friend TypeSize operator*(const TypeSize &LHS, const int64_t RHS) {
+ return LHS * (ScalarTy)RHS;
+ }
+ friend TypeSize operator*(const int LHS, const TypeSize &RHS) {
+ return RHS * LHS;
+ }
+ friend TypeSize operator*(const unsigned LHS, const TypeSize &RHS) {
+ return RHS * LHS;
+ }
+ friend TypeSize operator*(const int64_t LHS, const TypeSize &RHS) {
+ return RHS * LHS;
+ }
+ friend TypeSize operator*(const uint64_t LHS, const TypeSize &RHS) {
+ return RHS * LHS;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Utilities
+//===----------------------------------------------------------------------===//
+
+/// 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.getKnownMinValue() + Align - 1) / Align * Align,
+ Size.isScalable()};
+}
+
+/// Stream operator function for `LinearPolySize`.
+template <typename LeafTy>
+inline raw_ostream &operator<<(raw_ostream &OS,
+ const LinearPolySize<LeafTy> &PS) {
+ PS.print(OS);
+ return OS;
+}
+
+template <typename T> struct DenseMapInfo;
+template <> struct DenseMapInfo<ElementCount> {
+ static inline ElementCount getEmptyKey() {
+ return ElementCount::getScalable(~0U);
+ }
+ static inline ElementCount getTombstoneKey() {
+ return ElementCount::getFixed(~0U - 1);
+ }
+ static unsigned getHashValue(const ElementCount &EltCnt) {
+ unsigned HashVal = EltCnt.getKnownMinValue() * 37U;
+ if (EltCnt.isScalable())
+ return (HashVal - 1U);
+
+ return HashVal;
+ }
+
+ static bool isEqual(const ElementCount &LHS, const ElementCount &RHS) {
+ return LHS == RHS;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_TypeSize_H
diff --git a/linux-x64/clang/include/llvm/Support/UnicodeCharRanges.h b/linux-x64/clang/include/llvm/Support/UnicodeCharRanges.h
index 4b59f8a..73d3603 100644
--- a/linux-x64/clang/include/llvm/Support/UnicodeCharRanges.h
+++ b/linux-x64/clang/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/linux-x64/clang/include/llvm/Support/UniqueLock.h b/linux-x64/clang/include/llvm/Support/UniqueLock.h
deleted file mode 100644
index 0a887ad..0000000
--- a/linux-x64/clang/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/linux-x64/clang/include/llvm/Support/VCSRevision.h b/linux-x64/clang/include/llvm/Support/VCSRevision.h
index 3ad6886..3fe7a5f 100644
--- a/linux-x64/clang/include/llvm/Support/VCSRevision.h
+++ b/linux-x64/clang/include/llvm/Support/VCSRevision.h
@@ -1,2 +1,2 @@
-#define LLVM_REVISION "e0caee08e5f09b374a27a676d04978c81fcb1928"
-#define LLVM_REPOSITORY "/buildbot/tmp/tmpyQwgD_"
+#define LLVM_REVISION "c935d99d7cf2016289302412d708641d52d2f7ee"
+#define LLVM_REPOSITORY "/buildbot/src/android/llvm-toolchain/out/llvm-project/llvm"
diff --git a/linux-x64/clang/include/llvm/Support/VersionTuple.h b/linux-x64/clang/include/llvm/Support/VersionTuple.h
index 14736d6..6f3711f 100644
--- a/linux-x64/clang/include/llvm/Support/VersionTuple.h
+++ b/linux-x64/clang/include/llvm/Support/VersionTuple.h
@@ -14,13 +14,14 @@
#ifndef LLVM_SUPPORT_VERSIONTUPLE_H
#define LLVM_SUPPORT_VERSIONTUPLE_H
+#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
#include <string>
#include <tuple>
namespace llvm {
+class raw_ostream;
+class StringRef;
/// Represents a version number in the form major[.minor[.subminor[.build]]].
class VersionTuple {
@@ -87,6 +88,13 @@
return Build;
}
+ /// Return a version tuple that contains only the first 3 version components.
+ VersionTuple withoutBuild() const {
+ if (HasBuild)
+ return VersionTuple(Major, Minor, Subminor);
+ return *this;
+ }
+
/// Determine if two version numbers are equivalent. If not
/// provided, minor and subminor version numbers are considered to be zero.
friend bool operator==(const VersionTuple &X, const VersionTuple &Y) {
@@ -137,6 +145,10 @@
return !(X < Y);
}
+ friend llvm::hash_code hash_value(const VersionTuple &VT) {
+ return llvm::hash_combine(VT.Major, VT.Minor, VT.Subminor, VT.Build);
+ }
+
/// Retrieve a string representation of the version number.
std::string getAsString() const;
diff --git a/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h b/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h
index 31c9e85..d483fc3 100644
--- a/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h
+++ b/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h
@@ -19,7 +19,6 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
@@ -35,9 +34,14 @@
#include <utility>
#include <vector>
+// ANDROID x86_64 defined the FS macro
+#undef FS
+
namespace llvm {
class MemoryBuffer;
+class MemoryBufferRef;
+class Twine;
namespace vfs {
@@ -126,7 +130,7 @@
/// Only information available on most platforms is included.
class directory_entry {
std::string Path;
- llvm::sys::fs::file_type Type;
+ llvm::sys::fs::file_type Type = llvm::sys::fs::file_type::type_unknown;
public:
directory_entry() = default;
@@ -293,7 +297,7 @@
/// \param Path A path that is modified to be an absolute path.
/// \returns success if \a path has been made absolute, otherwise a
/// platform-specific error_code.
- std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
+ virtual std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const;
};
/// Gets an \p vfs::FileSystem for the 'real' file system, as seen by
@@ -463,7 +467,8 @@
/// false if the file or directory already exists in the file system with
/// different contents.
bool addFileNoOwn(const Twine &Path, time_t ModificationTime,
- llvm::MemoryBuffer *Buffer, Optional<uint32_t> User = None,
+ const llvm::MemoryBufferRef &Buffer,
+ Optional<uint32_t> User = None,
Optional<uint32_t> Group = None,
Optional<llvm::sys::fs::file_type> Type = None,
Optional<llvm::sys::fs::perms> Perms = None);
@@ -498,7 +503,7 @@
/// Gets a \p FileSystem for a virtual file system described in YAML
/// format.
-IntrusiveRefCntPtr<FileSystem>
+std::unique_ptr<FileSystem>
getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer,
llvm::SourceMgr::DiagHandlerTy DiagHandler,
StringRef YAMLFilePath, void *DiagContext = nullptr,
@@ -506,10 +511,12 @@
struct YAMLVFSEntry {
template <typename T1, typename T2>
- YAMLVFSEntry(T1 &&VPath, T2 &&RPath)
- : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)) {}
+ YAMLVFSEntry(T1 &&VPath, T2 &&RPath, bool IsDirectory = false)
+ : VPath(std::forward<T1>(VPath)), RPath(std::forward<T2>(RPath)),
+ IsDirectory(IsDirectory) {}
std::string VPath;
std::string RPath;
+ bool IsDirectory = false;
};
class VFSFromYamlDirIterImpl;
@@ -532,7 +539,7 @@
/// \endverbatim
///
/// All configuration options are optional.
-/// 'case-sensitive': <boolean, default=true>
+/// 'case-sensitive': <boolean, default=(true for Posix, false for Windows)>
/// 'use-external-names': <boolean, default=true>
/// 'overlay-relative': <boolean, default=false>
/// 'fallthrough': <boolean, default=true>
@@ -647,9 +654,30 @@
friend class VFSFromYamlDirIterImpl;
friend class RedirectingFileSystemParser;
+ bool shouldUseExternalFS() const {
+ return ExternalFSValidWD && IsFallthrough;
+ }
+
+ // In a RedirectingFileSystem, keys can be specified in Posix or Windows
+ // style (or even a mixture of both), so this comparison helper allows
+ // slashes (representing a root) to match backslashes (and vice versa). Note
+ // that, other than the root, path components should not contain slashes or
+ // backslashes.
+ bool pathComponentMatches(llvm::StringRef lhs, llvm::StringRef rhs) const {
+ if ((CaseSensitive ? lhs.equals(rhs) : lhs.equals_lower(rhs)))
+ return true;
+ return (lhs == "/" && rhs == "\\") || (lhs == "\\" && rhs == "/");
+ }
+
/// 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;
@@ -664,7 +692,12 @@
/// Whether to perform case-sensitive comparisons.
///
/// Currently, case-insensitive matching only works correctly with ASCII.
- bool CaseSensitive = true;
+ bool CaseSensitive =
+#ifdef _WIN32
+ false;
+#else
+ true;
+#endif
/// IsRelativeOverlay marks whether a ExternalContentsPrefixDir path must
/// be prefixed in every 'external-contents' when reading from YAML files.
@@ -679,18 +712,7 @@
bool IsFallthrough = true;
/// @}
- /// Virtual file paths and external files could be canonicalized without "..",
- /// "." and "./" in their paths. FIXME: some unittests currently fail on
- /// win32 when using remove_dots and remove_leading_dotslash on paths.
- bool UseCanonicalizedPaths =
-#ifdef _WIN32
- false;
-#else
- 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.
@@ -707,11 +729,16 @@
/// Parses \p Buffer, which is expected to be in YAML format and
/// returns a virtual file system representing its contents.
- static RedirectingFileSystem *
+ static std::unique_ptr<RedirectingFileSystem>
create(std::unique_ptr<MemoryBuffer> Buffer,
SourceMgr::DiagHandlerTy DiagHandler, StringRef YAMLFilePath,
void *DiagContext, IntrusiveRefCntPtr<FileSystem> ExternalFS);
+ /// Redirect each of the remapped files from first to second.
+ static std::unique_ptr<RedirectingFileSystem>
+ create(ArrayRef<std::pair<std::string, std::string>> RemappedFiles,
+ bool UseExternalNames, FileSystem &ExternalFS);
+
ErrorOr<Status> status(const Twine &Path) override;
ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override;
@@ -724,15 +751,22 @@
std::error_code isLocal(const Twine &Path, bool &Result) override;
+ std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const override;
+
directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override;
void setExternalContentsPrefixDir(StringRef PrefixDir);
StringRef getExternalContentsPrefixDir() const;
+ void setFallthrough(bool Fallthrough);
+
+ std::vector<llvm::StringRef> getRoots() 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
};
@@ -753,10 +787,13 @@
Optional<bool> UseExternalNames;
std::string OverlayDir;
+ void addEntry(StringRef VirtualPath, StringRef RealPath, bool IsDirectory);
+
public:
YAMLVFSWriter() = default;
void addFileMapping(StringRef VirtualPath, StringRef RealPath);
+ void addDirectoryMapping(StringRef VirtualPath, StringRef RealPath);
void setCaseSensitivity(bool CaseSensitive) {
IsCaseSensitive = CaseSensitive;
diff --git a/linux-x64/clang/include/llvm/Support/Win64EH.h b/linux-x64/clang/include/llvm/Support/Win64EH.h
index bdd23b4..9359fcb 100644
--- a/linux-x64/clang/include/llvm/Support/Win64EH.h
+++ b/linux-x64/clang/include/llvm/Support/Win64EH.h
@@ -30,18 +30,22 @@
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
// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
UOP_AllocMedium,
+ UOP_SaveR19R20X,
UOP_SaveFPLRX,
UOP_SaveFPLR,
UOP_SaveReg,
UOP_SaveRegX,
UOP_SaveRegP,
UOP_SaveRegPX,
+ UOP_SaveLRPair,
UOP_SaveFReg,
UOP_SaveFRegX,
UOP_SaveFRegP,
@@ -49,7 +53,11 @@
UOP_SetFP,
UOP_AddFP,
UOP_Nop,
- UOP_End
+ UOP_End,
+ UOP_SaveNext,
+ UOP_TrapFrame,
+ UOP_Context,
+ UOP_ClearUnwoundToCall
};
/// UnwindCode - This union describes a single operation in a function prolog,
diff --git a/linux-x64/clang/include/llvm/Support/Windows/WindowsSupport.h b/linux-x64/clang/include/llvm/Support/Windows/WindowsSupport.h
new file mode 100644
index 0000000..bd5a90c
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/Windows/WindowsSupport.h
@@ -0,0 +1,249 @@
+//===- WindowsSupport.h - Common Windows Include File -----------*- 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 things specific to Windows implementations. In addition to
+// providing some helpers for working with win32 APIs, this header wraps
+// <windows.h> with some portability macros. Always include WindowsSupport.h
+// instead of including <windows.h> directly.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//=== is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H
+#define LLVM_SUPPORT_WINDOWSSUPPORT_H
+
+// mingw-w64 tends to define it as 0x0502 in its headers.
+#undef _WIN32_WINNT
+#undef _WIN32_IE
+
+// Require at least Windows 7 API.
+#define _WIN32_WINNT 0x0601
+#define _WIN32_IE 0x0800 // MinGW at it again. FIXME: verify if still needed.
+#define WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Config/config.h" // Get build system configuration settings
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Chrono.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/VersionTuple.h"
+#include <cassert>
+#include <string>
+#include <system_error>
+#include <windows.h>
+
+// Must be included after windows.h
+#include <wincrypt.h>
+
+namespace llvm {
+
+/// Determines if the program is running on Windows 8 or newer. This
+/// reimplements one of the helpers in the Windows 8.1 SDK, which are intended
+/// to supercede raw calls to GetVersionEx. Old SDKs, Cygwin, and MinGW don't
+/// yet have VersionHelpers.h, so we have our own helper.
+bool RunningWindows8OrGreater();
+
+/// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
+/// RtlGetVersion or GetVersionEx under the hood depending on what is available.
+/// GetVersionEx is deprecated, but this API exposes the build number which can
+/// be useful for working around certain kernel bugs.
+llvm::VersionTuple GetWindowsOSVersion();
+
+bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix);
+
+// Include GetLastError() in a fatal error message.
+LLVM_ATTRIBUTE_NORETURN inline void ReportLastErrorFatal(const char *Msg) {
+ std::string ErrMsg;
+ MakeErrMsg(&ErrMsg, Msg);
+ llvm::report_fatal_error(ErrMsg);
+}
+
+template <typename HandleTraits>
+class ScopedHandle {
+ typedef typename HandleTraits::handle_type handle_type;
+ handle_type Handle;
+
+ ScopedHandle(const ScopedHandle &other) = delete;
+ void operator=(const ScopedHandle &other) = delete;
+public:
+ ScopedHandle()
+ : Handle(HandleTraits::GetInvalid()) {}
+
+ explicit ScopedHandle(handle_type h)
+ : Handle(h) {}
+
+ ~ScopedHandle() {
+ if (HandleTraits::IsValid(Handle))
+ HandleTraits::Close(Handle);
+ }
+
+ handle_type take() {
+ handle_type t = Handle;
+ Handle = HandleTraits::GetInvalid();
+ return t;
+ }
+
+ ScopedHandle &operator=(handle_type h) {
+ if (HandleTraits::IsValid(Handle))
+ HandleTraits::Close(Handle);
+ Handle = h;
+ return *this;
+ }
+
+ // True if Handle is valid.
+ explicit operator bool() const {
+ return HandleTraits::IsValid(Handle) ? true : false;
+ }
+
+ operator handle_type() const {
+ return Handle;
+ }
+};
+
+struct CommonHandleTraits {
+ typedef HANDLE handle_type;
+
+ static handle_type GetInvalid() {
+ return INVALID_HANDLE_VALUE;
+ }
+
+ static void Close(handle_type h) {
+ ::CloseHandle(h);
+ }
+
+ static bool IsValid(handle_type h) {
+ return h != GetInvalid();
+ }
+};
+
+struct JobHandleTraits : CommonHandleTraits {
+ static handle_type GetInvalid() {
+ return NULL;
+ }
+};
+
+struct CryptContextTraits : CommonHandleTraits {
+ typedef HCRYPTPROV handle_type;
+
+ static handle_type GetInvalid() {
+ return 0;
+ }
+
+ static void Close(handle_type h) {
+ ::CryptReleaseContext(h, 0);
+ }
+
+ static bool IsValid(handle_type h) {
+ return h != GetInvalid();
+ }
+};
+
+struct RegTraits : CommonHandleTraits {
+ typedef HKEY handle_type;
+
+ static handle_type GetInvalid() {
+ return NULL;
+ }
+
+ static void Close(handle_type h) {
+ ::RegCloseKey(h);
+ }
+
+ static bool IsValid(handle_type h) {
+ return h != GetInvalid();
+ }
+};
+
+struct FindHandleTraits : CommonHandleTraits {
+ static void Close(handle_type h) {
+ ::FindClose(h);
+ }
+};
+
+struct FileHandleTraits : CommonHandleTraits {};
+
+typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
+typedef ScopedHandle<FileHandleTraits> ScopedFileHandle;
+typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
+typedef ScopedHandle<RegTraits> ScopedRegHandle;
+typedef ScopedHandle<FindHandleTraits> ScopedFindHandle;
+typedef ScopedHandle<JobHandleTraits> ScopedJobHandle;
+
+template <class T>
+class SmallVectorImpl;
+
+template <class T>
+typename SmallVectorImpl<T>::const_pointer
+c_str(SmallVectorImpl<T> &str) {
+ str.push_back(0);
+ str.pop_back();
+ return str.data();
+}
+
+namespace sys {
+
+inline std::chrono::nanoseconds toDuration(FILETIME Time) {
+ ULARGE_INTEGER TimeInteger;
+ TimeInteger.LowPart = Time.dwLowDateTime;
+ TimeInteger.HighPart = Time.dwHighDateTime;
+
+ // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
+ return std::chrono::nanoseconds(100 * TimeInteger.QuadPart);
+}
+
+inline TimePoint<> toTimePoint(FILETIME Time) {
+ ULARGE_INTEGER TimeInteger;
+ TimeInteger.LowPart = Time.dwLowDateTime;
+ TimeInteger.HighPart = Time.dwHighDateTime;
+
+ // Adjust for different epoch
+ TimeInteger.QuadPart -= 11644473600ll * 10000000;
+
+ // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
+ return TimePoint<>(std::chrono::nanoseconds(100 * TimeInteger.QuadPart));
+}
+
+inline FILETIME toFILETIME(TimePoint<> TP) {
+ ULARGE_INTEGER TimeInteger;
+ TimeInteger.QuadPart = TP.time_since_epoch().count() / 100;
+ TimeInteger.QuadPart += 11644473600ll * 10000000;
+
+ FILETIME Time;
+ Time.dwLowDateTime = TimeInteger.LowPart;
+ Time.dwHighDateTime = TimeInteger.HighPart;
+ return Time;
+}
+
+namespace windows {
+// Returns command line arguments. Unlike arguments given to main(),
+// this function guarantees that the returned arguments are encoded in
+// UTF-8 regardless of the current code page setting.
+std::error_code GetCommandLineArguments(SmallVectorImpl<const char *> &Args,
+ BumpPtrAllocator &Alloc);
+
+/// Convert UTF-8 path to a suitable UTF-16 path for use with the Win32 Unicode
+/// File API.
+std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16,
+ size_t MaxPathLen = MAX_PATH);
+
+} // end namespace windows
+} // end namespace sys
+} // end namespace llvm.
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/WithColor.h b/linux-x64/clang/include/llvm/Support/WithColor.h
index f4e1075..eea4a72 100644
--- a/linux-x64/clang/include/llvm/Support/WithColor.h
+++ b/linux-x64/clang/include/llvm/Support/WithColor.h
@@ -9,14 +9,18 @@
#ifndef LLVM_SUPPORT_WITHCOLOR_H
#define LLVM_SUPPORT_WITHCOLOR_H
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
namespace llvm {
-extern cl::OptionCategory ColorCategory;
+class Error;
+class StringRef;
-class raw_ostream;
+namespace cl {
+class OptionCategory;
+}
+
+extern cl::OptionCategory ColorCategory;
// Symbolic names for various syntax elements.
enum class HighlightColor {
@@ -32,31 +36,43 @@
Remark
};
+enum class ColorMode {
+ /// Determine whether to use color based on the command line argument and the
+ /// raw_ostream.
+ Auto,
+ /// Enable colors. Because raw_ostream is the one implementing colors, this
+ /// has no effect if the stream does not support colors or has colors
+ /// disabled.
+ Enable,
+ /// Disable colors.
+ Disable,
+};
+
/// An RAII object that temporarily switches an output stream to a specific
/// color.
class WithColor {
raw_ostream &OS;
- bool DisableColors;
+ ColorMode Mode;
public:
/// To be used like this: WithColor(OS, HighlightColor::String) << "text";
/// @param OS The output stream
/// @param S Symbolic name for syntax element to color
- /// @param DisableColors Whether to ignore color changes regardless of -color
- /// and support in OS
- WithColor(raw_ostream &OS, HighlightColor S, bool DisableColors = false);
+ /// @param Mode Enable, disable or compute whether to use colors.
+ WithColor(raw_ostream &OS, HighlightColor S,
+ ColorMode Mode = ColorMode::Auto);
/// To be used like this: WithColor(OS, raw_ostream::Black) << "text";
/// @param OS The output stream
/// @param Color ANSI color to use, the special SAVEDCOLOR can be used to
/// change only the bold attribute, and keep colors untouched
/// @param Bold Bold/brighter text, default false
/// @param BG If true, change the background, default: change foreground
- /// @param DisableColors Whether to ignore color changes regardless of -color
- /// and support in OS
+ /// @param Mode Enable, disable or compute whether to use colors.
WithColor(raw_ostream &OS,
raw_ostream::Colors Color = raw_ostream::SAVEDCOLOR,
- bool Bold = false, bool BG = false, bool DisableColors = false)
- : OS(OS), DisableColors(DisableColors) {
+ bool Bold = false, bool BG = false,
+ ColorMode Mode = ColorMode::Auto)
+ : OS(OS), Mode(Mode) {
changeColor(Color, Bold, BG);
}
~WithColor();
@@ -108,6 +124,14 @@
/// Reset the colors to terminal defaults. Call this when you are done
/// outputting colored text, or before program exit.
WithColor &resetColor();
+
+ /// Implement default handling for Error.
+ /// Print "error: " to stderr.
+ static void defaultErrorHandler(Error Err);
+
+ /// Implement default handling for Warning.
+ /// Print "warning: " to stderr.
+ static void defaultWarningHandler(Error Warning);
};
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/Support/X86DisassemblerDecoderCommon.h b/linux-x64/clang/include/llvm/Support/X86DisassemblerDecoderCommon.h
index baf842b..5697ff9 100644
--- a/linux-x64/clang/include/llvm/Support/X86DisassemblerDecoderCommon.h
+++ b/linux-x64/clang/include/llvm/Support/X86DisassemblerDecoderCommon.h
@@ -361,6 +361,7 @@
ENUM_ENTRY(ENCODING_RM_CD16,"R/M operand with CDisp scaling of 16") \
ENUM_ENTRY(ENCODING_RM_CD32,"R/M operand with CDisp scaling of 32") \
ENUM_ENTRY(ENCODING_RM_CD64,"R/M operand with CDisp scaling of 64") \
+ ENUM_ENTRY(ENCODING_SIB, "Force SIB operand in ModR/M byte.") \
ENUM_ENTRY(ENCODING_VSIB, "VSIB operand in ModR/M byte.") \
ENUM_ENTRY(ENCODING_VSIB_CD2, "VSIB operand with CDisp scaling of 2") \
ENUM_ENTRY(ENCODING_VSIB_CD4, "VSIB operand with CDisp scaling of 4") \
@@ -374,7 +375,7 @@
ENUM_ENTRY(ENCODING_IW, "2-byte") \
ENUM_ENTRY(ENCODING_ID, "4-byte") \
ENUM_ENTRY(ENCODING_IO, "8-byte") \
- ENUM_ENTRY(ENCODING_RB, "(AL..DIL, R8L..R15L) Register code added to " \
+ ENUM_ENTRY(ENCODING_RB, "(AL..DIL, R8B..R15B) Register code added to " \
"the opcode byte") \
ENUM_ENTRY(ENCODING_RW, "(AX..DI, R8W..R15W)") \
ENUM_ENTRY(ENCODING_RD, "(EAX..EDI, R8D..R15D)") \
@@ -411,6 +412,7 @@
ENUM_ENTRY(TYPE_IMM, "immediate operand") \
ENUM_ENTRY(TYPE_UIMM8, "1-byte unsigned immediate operand") \
ENUM_ENTRY(TYPE_M, "Memory operand") \
+ ENUM_ENTRY(TYPE_MSIB, "Memory operand force sib encoding") \
ENUM_ENTRY(TYPE_MVSIBX, "Memory operand using XMM index") \
ENUM_ENTRY(TYPE_MVSIBY, "Memory operand using YMM index") \
ENUM_ENTRY(TYPE_MVSIBZ, "Memory operand using ZMM index") \
@@ -424,6 +426,7 @@
ENUM_ENTRY(TYPE_ZMM, "64-byte") \
ENUM_ENTRY(TYPE_VK, "mask register") \
ENUM_ENTRY(TYPE_VK_PAIR, "mask register pair") \
+ ENUM_ENTRY(TYPE_TMM, "tile") \
ENUM_ENTRY(TYPE_SEGMENTREG, "Segment register operand") \
ENUM_ENTRY(TYPE_DEBUGREG, "Debug register operand") \
ENUM_ENTRY(TYPE_CONTROLREG, "Control register operand") \
diff --git a/linux-x64/clang/include/llvm/Support/X86TargetParser.def b/linux-x64/clang/include/llvm/Support/X86TargetParser.def
index 1749be3..ec19ce4 100644
--- a/linux-x64/clang/include/llvm/Support/X86TargetParser.def
+++ b/linux-x64/clang/include/llvm/Support/X86TargetParser.def
@@ -19,153 +19,185 @@
X86_VENDOR(VENDOR_AMD, "amd")
#undef X86_VENDOR
-// This macro is used to implement CPU types that have an alias. As of now
-// there is only ever one alias.
-#ifndef X86_CPU_TYPE_COMPAT_WITH_ALIAS
-#define X86_CPU_TYPE_COMPAT_WITH_ALIAS(ARCHNAME, ENUM, STR, ALIAS) X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR)
-#endif
-
// This macro is used for cpu types present in compiler-rt/libgcc.
-#ifndef X86_CPU_TYPE_COMPAT
-#define X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR) X86_CPU_TYPE(ARCHNAME, ENUM)
+#ifndef X86_CPU_TYPE
+#define X86_CPU_TYPE(ENUM, STR)
#endif
-#ifndef X86_CPU_TYPE
-#define X86_CPU_TYPE(ARCHNAME, ENUM)
+#ifndef X86_CPU_TYPE_ALIAS
+#define X86_CPU_TYPE_ALIAS(ENUM, STR)
#endif
-// The first part of this list must match what is implemented in libgcc and
-// compilert-rt. Clang uses this to know how to implement __builtin_cpu_is.
-X86_CPU_TYPE_COMPAT_WITH_ALIAS("bonnell", INTEL_BONNELL, "bonnell", "atom")
-X86_CPU_TYPE_COMPAT ("core2", INTEL_CORE2, "core2")
-X86_CPU_TYPE_COMPAT ("nehalem", INTEL_COREI7, "corei7")
-X86_CPU_TYPE_COMPAT_WITH_ALIAS("amdfam10", AMDFAM10H, "amdfam10h", "amdfam10")
-X86_CPU_TYPE_COMPAT_WITH_ALIAS("bdver1", AMDFAM15H, "amdfam15h", "amdfam15")
-X86_CPU_TYPE_COMPAT_WITH_ALIAS("silvermont", INTEL_SILVERMONT, "silvermont", "slm")
-X86_CPU_TYPE_COMPAT ("knl", INTEL_KNL, "knl")
-X86_CPU_TYPE_COMPAT ("btver1", AMD_BTVER1, "btver1")
-X86_CPU_TYPE_COMPAT ("btver2", AMD_BTVER2, "btver2")
-X86_CPU_TYPE_COMPAT ("znver1", AMDFAM17H, "amdfam17h")
-X86_CPU_TYPE_COMPAT ("knm", INTEL_KNM, "knm")
-X86_CPU_TYPE_COMPAT ("goldmont", INTEL_GOLDMONT, "goldmont")
-X86_CPU_TYPE_COMPAT ("goldmont-plus", INTEL_GOLDMONT_PLUS, "goldmont-plus")
-X86_CPU_TYPE_COMPAT ("tremont", INTEL_TREMONT, "tremont")
-// Entries below this are not in libgcc/compiler-rt.
-X86_CPU_TYPE ("i386", INTEL_i386)
-X86_CPU_TYPE ("i486", INTEL_i486)
-X86_CPU_TYPE ("pentium", INTEL_PENTIUM)
-X86_CPU_TYPE ("pentium-mmx", INTEL_PENTIUM_MMX)
-X86_CPU_TYPE ("pentiumpro", INTEL_PENTIUM_PRO)
-X86_CPU_TYPE ("pentium2", INTEL_PENTIUM_II)
-X86_CPU_TYPE ("pentium3", INTEL_PENTIUM_III)
-X86_CPU_TYPE ("pentium4", INTEL_PENTIUM_IV)
-X86_CPU_TYPE ("pentium-m", INTEL_PENTIUM_M)
-X86_CPU_TYPE ("yonah", INTEL_CORE_DUO)
-X86_CPU_TYPE ("nocona", INTEL_NOCONA)
-X86_CPU_TYPE ("prescott", INTEL_PRESCOTT)
-X86_CPU_TYPE ("i486", AMD_i486)
-X86_CPU_TYPE ("pentium", AMDPENTIUM)
-X86_CPU_TYPE ("athlon", AMD_ATHLON)
-X86_CPU_TYPE ("athlon-xp", AMD_ATHLON_XP)
-X86_CPU_TYPE ("k8", AMD_K8)
-X86_CPU_TYPE ("k8-sse3", AMD_K8SSE3)
-#undef X86_CPU_TYPE_COMPAT_WITH_ALIAS
-#undef X86_CPU_TYPE_COMPAT
+
+// This list must match what is implemented in libgcc and compilert-rt. Clang
+// uses this to know how to implement __builtin_cpu_is.
+X86_CPU_TYPE(INTEL_BONNELL, "bonnell")
+X86_CPU_TYPE(INTEL_CORE2, "core2")
+X86_CPU_TYPE(INTEL_COREI7, "corei7")
+X86_CPU_TYPE(AMDFAM10H, "amdfam10h")
+X86_CPU_TYPE(AMDFAM15H, "amdfam15h")
+X86_CPU_TYPE(INTEL_SILVERMONT, "silvermont")
+X86_CPU_TYPE(INTEL_KNL, "knl")
+X86_CPU_TYPE(AMD_BTVER1, "btver1")
+X86_CPU_TYPE(AMD_BTVER2, "btver2")
+X86_CPU_TYPE(AMDFAM17H, "amdfam17h")
+X86_CPU_TYPE(INTEL_KNM, "knm")
+X86_CPU_TYPE(INTEL_GOLDMONT, "goldmont")
+X86_CPU_TYPE(INTEL_GOLDMONT_PLUS, "goldmont-plus")
+X86_CPU_TYPE(INTEL_TREMONT, "tremont")
+X86_CPU_TYPE(AMDFAM19H, "amdfam19h")
+
+// Alternate names supported by __builtin_cpu_is and target multiversioning.
+X86_CPU_TYPE_ALIAS(INTEL_BONNELL, "atom")
+X86_CPU_TYPE_ALIAS(AMDFAM10H, "amdfam10")
+X86_CPU_TYPE_ALIAS(AMDFAM15H, "amdfam15")
+X86_CPU_TYPE_ALIAS(INTEL_SILVERMONT, "slm")
+
+#undef X86_CPU_TYPE_ALIAS
#undef X86_CPU_TYPE
// This macro is used for cpu subtypes present in compiler-rt/libgcc.
-#ifndef X86_CPU_SUBTYPE_COMPAT
-#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) X86_CPU_SUBTYPE(ARCHNAME, ENUM)
-#endif
-
#ifndef X86_CPU_SUBTYPE
-#define X86_CPU_SUBTYPE(ARCHNAME, ENUM)
+#define X86_CPU_SUBTYPE(ENUM, STR)
#endif
-// The first part of this list must match what is implemented in libgcc and
-// compilert-rt. Clang uses this to know how to implement __builtin_cpu_is.
-X86_CPU_SUBTYPE_COMPAT("nehalem", INTEL_COREI7_NEHALEM, "nehalem")
-X86_CPU_SUBTYPE_COMPAT("westmere", INTEL_COREI7_WESTMERE, "westmere")
-X86_CPU_SUBTYPE_COMPAT("sandybridge", INTEL_COREI7_SANDYBRIDGE, "sandybridge")
-X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_BARCELONA, "barcelona")
-X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_SHANGHAI, "shanghai")
-X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_ISTANBUL, "istanbul")
-X86_CPU_SUBTYPE_COMPAT("bdver1", AMDFAM15H_BDVER1, "bdver1")
-X86_CPU_SUBTYPE_COMPAT("bdver2", AMDFAM15H_BDVER2, "bdver2")
-X86_CPU_SUBTYPE_COMPAT("bdver3", AMDFAM15H_BDVER3, "bdver3")
-X86_CPU_SUBTYPE_COMPAT("bdver4", AMDFAM15H_BDVER4, "bdver4")
-X86_CPU_SUBTYPE_COMPAT("znver1", AMDFAM17H_ZNVER1, "znver1")
-X86_CPU_SUBTYPE_COMPAT("ivybridge", INTEL_COREI7_IVYBRIDGE, "ivybridge")
-X86_CPU_SUBTYPE_COMPAT("haswell", INTEL_COREI7_HASWELL, "haswell")
-X86_CPU_SUBTYPE_COMPAT("broadwell", INTEL_COREI7_BROADWELL, "broadwell")
-X86_CPU_SUBTYPE_COMPAT("skylake", INTEL_COREI7_SKYLAKE, "skylake")
-X86_CPU_SUBTYPE_COMPAT("skylake-avx512", INTEL_COREI7_SKYLAKE_AVX512, "skylake-avx512")
-X86_CPU_SUBTYPE_COMPAT("cannonlake", INTEL_COREI7_CANNONLAKE, "cannonlake")
-X86_CPU_SUBTYPE_COMPAT("icelake-client", INTEL_COREI7_ICELAKE_CLIENT, "icelake-client")
-X86_CPU_SUBTYPE_COMPAT("icelake-server", INTEL_COREI7_ICELAKE_SERVER, "icelake-server")
-X86_CPU_SUBTYPE_COMPAT("znver2", AMDFAM17H_ZNVER2, "znver2")
-X86_CPU_SUBTYPE_COMPAT("cascadelake", INTEL_COREI7_CASCADELAKE, "cascadelake")
-// Entries below this are not in libgcc/compiler-rt.
-X86_CPU_SUBTYPE ("core2", INTEL_CORE2_65)
-X86_CPU_SUBTYPE ("penryn", INTEL_CORE2_45)
-X86_CPU_SUBTYPE ("k6", AMDPENTIUM_K6)
-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)
-#undef X86_CPU_SUBTYPE_COMPAT
+// This list must match what is implemented in libgcc and compilert-rt. Clang
+// uses this to know how to implement __builtin_cpu_is.
+X86_CPU_SUBTYPE(INTEL_COREI7_NEHALEM, "nehalem")
+X86_CPU_SUBTYPE(INTEL_COREI7_WESTMERE, "westmere")
+X86_CPU_SUBTYPE(INTEL_COREI7_SANDYBRIDGE, "sandybridge")
+X86_CPU_SUBTYPE(AMDFAM10H_BARCELONA, "barcelona")
+X86_CPU_SUBTYPE(AMDFAM10H_SHANGHAI, "shanghai")
+X86_CPU_SUBTYPE(AMDFAM10H_ISTANBUL, "istanbul")
+X86_CPU_SUBTYPE(AMDFAM15H_BDVER1, "bdver1")
+X86_CPU_SUBTYPE(AMDFAM15H_BDVER2, "bdver2")
+X86_CPU_SUBTYPE(AMDFAM15H_BDVER3, "bdver3")
+X86_CPU_SUBTYPE(AMDFAM15H_BDVER4, "bdver4")
+X86_CPU_SUBTYPE(AMDFAM17H_ZNVER1, "znver1")
+X86_CPU_SUBTYPE(INTEL_COREI7_IVYBRIDGE, "ivybridge")
+X86_CPU_SUBTYPE(INTEL_COREI7_HASWELL, "haswell")
+X86_CPU_SUBTYPE(INTEL_COREI7_BROADWELL, "broadwell")
+X86_CPU_SUBTYPE(INTEL_COREI7_SKYLAKE, "skylake")
+X86_CPU_SUBTYPE(INTEL_COREI7_SKYLAKE_AVX512, "skylake-avx512")
+X86_CPU_SUBTYPE(INTEL_COREI7_CANNONLAKE, "cannonlake")
+X86_CPU_SUBTYPE(INTEL_COREI7_ICELAKE_CLIENT, "icelake-client")
+X86_CPU_SUBTYPE(INTEL_COREI7_ICELAKE_SERVER, "icelake-server")
+X86_CPU_SUBTYPE(AMDFAM17H_ZNVER2, "znver2")
+X86_CPU_SUBTYPE(INTEL_COREI7_CASCADELAKE, "cascadelake")
+X86_CPU_SUBTYPE(INTEL_COREI7_TIGERLAKE, "tigerlake")
+X86_CPU_SUBTYPE(INTEL_COREI7_COOPERLAKE, "cooperlake")
+X86_CPU_SUBTYPE(INTEL_COREI7_SAPPHIRERAPIDS, "sapphirerapids")
+X86_CPU_SUBTYPE(INTEL_COREI7_ALDERLAKE, "alderlake")
+X86_CPU_SUBTYPE(AMDFAM19H_ZNVER3, "znver3")
#undef X86_CPU_SUBTYPE
// This macro is used for cpu types present in compiler-rt/libgcc.
#ifndef X86_FEATURE_COMPAT
-#define X86_FEATURE_COMPAT(VAL, ENUM, STR) X86_FEATURE(VAL, ENUM)
+#define X86_FEATURE_COMPAT(ENUM, STR) X86_FEATURE(ENUM, STR)
#endif
#ifndef X86_FEATURE
-#define X86_FEATURE(VAL, ENUM)
+#define X86_FEATURE(ENUM, STR)
#endif
-X86_FEATURE_COMPAT( 0, FEATURE_CMOV, "cmov")
-X86_FEATURE_COMPAT( 1, FEATURE_MMX, "mmx")
-X86_FEATURE_COMPAT( 2, FEATURE_POPCNT, "popcnt")
-X86_FEATURE_COMPAT( 3, FEATURE_SSE, "sse")
-X86_FEATURE_COMPAT( 4, FEATURE_SSE2, "sse2")
-X86_FEATURE_COMPAT( 5, FEATURE_SSE3, "sse3")
-X86_FEATURE_COMPAT( 6, FEATURE_SSSE3, "ssse3")
-X86_FEATURE_COMPAT( 7, FEATURE_SSE4_1, "sse4.1")
-X86_FEATURE_COMPAT( 8, FEATURE_SSE4_2, "sse4.2")
-X86_FEATURE_COMPAT( 9, FEATURE_AVX, "avx")
-X86_FEATURE_COMPAT(10, FEATURE_AVX2, "avx2")
-X86_FEATURE_COMPAT(11, FEATURE_SSE4_A, "sse4a")
-X86_FEATURE_COMPAT(12, FEATURE_FMA4, "fma4")
-X86_FEATURE_COMPAT(13, FEATURE_XOP, "xop")
-X86_FEATURE_COMPAT(14, FEATURE_FMA, "fma")
-X86_FEATURE_COMPAT(15, FEATURE_AVX512F, "avx512f")
-X86_FEATURE_COMPAT(16, FEATURE_BMI, "bmi")
-X86_FEATURE_COMPAT(17, FEATURE_BMI2, "bmi2")
-X86_FEATURE_COMPAT(18, FEATURE_AES, "aes")
-X86_FEATURE_COMPAT(19, FEATURE_PCLMUL, "pclmul")
-X86_FEATURE_COMPAT(20, FEATURE_AVX512VL, "avx512vl")
-X86_FEATURE_COMPAT(21, FEATURE_AVX512BW, "avx512bw")
-X86_FEATURE_COMPAT(22, FEATURE_AVX512DQ, "avx512dq")
-X86_FEATURE_COMPAT(23, FEATURE_AVX512CD, "avx512cd")
-X86_FEATURE_COMPAT(24, FEATURE_AVX512ER, "avx512er")
-X86_FEATURE_COMPAT(25, FEATURE_AVX512PF, "avx512pf")
-X86_FEATURE_COMPAT(26, FEATURE_AVX512VBMI, "avx512vbmi")
-X86_FEATURE_COMPAT(27, FEATURE_AVX512IFMA, "avx512ifma")
-X86_FEATURE_COMPAT(28, FEATURE_AVX5124VNNIW, "avx5124vnniw")
-X86_FEATURE_COMPAT(29, FEATURE_AVX5124FMAPS, "avx5124fmaps")
-X86_FEATURE_COMPAT(30, FEATURE_AVX512VPOPCNTDQ, "avx512vpopcntdq")
-X86_FEATURE_COMPAT(31, FEATURE_AVX512VBMI2, "avx512vbmi2")
-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(CMOV, "cmov")
+X86_FEATURE_COMPAT(MMX, "mmx")
+X86_FEATURE_COMPAT(POPCNT, "popcnt")
+X86_FEATURE_COMPAT(SSE, "sse")
+X86_FEATURE_COMPAT(SSE2, "sse2")
+X86_FEATURE_COMPAT(SSE3, "sse3")
+X86_FEATURE_COMPAT(SSSE3, "ssse3")
+X86_FEATURE_COMPAT(SSE4_1, "sse4.1")
+X86_FEATURE_COMPAT(SSE4_2, "sse4.2")
+X86_FEATURE_COMPAT(AVX, "avx")
+X86_FEATURE_COMPAT(AVX2, "avx2")
+X86_FEATURE_COMPAT(SSE4_A, "sse4a")
+X86_FEATURE_COMPAT(FMA4, "fma4")
+X86_FEATURE_COMPAT(XOP, "xop")
+X86_FEATURE_COMPAT(FMA, "fma")
+X86_FEATURE_COMPAT(AVX512F, "avx512f")
+X86_FEATURE_COMPAT(BMI, "bmi")
+X86_FEATURE_COMPAT(BMI2, "bmi2")
+X86_FEATURE_COMPAT(AES, "aes")
+X86_FEATURE_COMPAT(PCLMUL, "pclmul")
+X86_FEATURE_COMPAT(AVX512VL, "avx512vl")
+X86_FEATURE_COMPAT(AVX512BW, "avx512bw")
+X86_FEATURE_COMPAT(AVX512DQ, "avx512dq")
+X86_FEATURE_COMPAT(AVX512CD, "avx512cd")
+X86_FEATURE_COMPAT(AVX512ER, "avx512er")
+X86_FEATURE_COMPAT(AVX512PF, "avx512pf")
+X86_FEATURE_COMPAT(AVX512VBMI, "avx512vbmi")
+X86_FEATURE_COMPAT(AVX512IFMA, "avx512ifma")
+X86_FEATURE_COMPAT(AVX5124VNNIW, "avx5124vnniw")
+X86_FEATURE_COMPAT(AVX5124FMAPS, "avx5124fmaps")
+X86_FEATURE_COMPAT(AVX512VPOPCNTDQ, "avx512vpopcntdq")
+X86_FEATURE_COMPAT(AVX512VBMI2, "avx512vbmi2")
+X86_FEATURE_COMPAT(GFNI, "gfni")
+X86_FEATURE_COMPAT(VPCLMULQDQ, "vpclmulqdq")
+X86_FEATURE_COMPAT(AVX512VNNI, "avx512vnni")
+X86_FEATURE_COMPAT(AVX512BITALG, "avx512bitalg")
+X86_FEATURE_COMPAT(AVX512BF16, "avx512bf16")
+X86_FEATURE_COMPAT(AVX512VP2INTERSECT, "avx512vp2intersect")
// 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 (3DNOW, "3dnow")
+X86_FEATURE (3DNOWA, "3dnowa")
+X86_FEATURE (64BIT, "64bit")
+X86_FEATURE (ADX, "adx")
+X86_FEATURE (AMX_BF16, "amx-bf16")
+X86_FEATURE (AMX_INT8, "amx-int8")
+X86_FEATURE (AMX_TILE, "amx-tile")
+X86_FEATURE (CLDEMOTE, "cldemote")
+X86_FEATURE (CLFLUSHOPT, "clflushopt")
+X86_FEATURE (CLWB, "clwb")
+X86_FEATURE (CLZERO, "clzero")
+X86_FEATURE (CMPXCHG16B, "cx16")
+X86_FEATURE (CMPXCHG8B, "cx8")
+X86_FEATURE (ENQCMD, "enqcmd")
+X86_FEATURE (F16C, "f16c")
+X86_FEATURE (FSGSBASE, "fsgsbase")
+X86_FEATURE (FXSR, "fxsr")
+X86_FEATURE (INVPCID, "invpcid")
+X86_FEATURE (KL, "kl")
+X86_FEATURE (WIDEKL, "widekl")
+X86_FEATURE (LWP, "lwp")
+X86_FEATURE (LZCNT, "lzcnt")
+X86_FEATURE (MOVBE, "movbe")
+X86_FEATURE (MOVDIR64B, "movdir64b")
+X86_FEATURE (MOVDIRI, "movdiri")
+X86_FEATURE (MWAITX, "mwaitx")
+X86_FEATURE (PCONFIG, "pconfig")
+X86_FEATURE (PKU, "pku")
+X86_FEATURE (PREFETCHWT1, "prefetchwt1")
+X86_FEATURE (PRFCHW, "prfchw")
+X86_FEATURE (PTWRITE, "ptwrite")
+X86_FEATURE (RDPID, "rdpid")
+X86_FEATURE (RDRND, "rdrnd")
+X86_FEATURE (RDSEED, "rdseed")
+X86_FEATURE (RTM, "rtm")
+X86_FEATURE (SAHF, "sahf")
+X86_FEATURE (SERIALIZE, "serialize")
+X86_FEATURE (SGX, "sgx")
+X86_FEATURE (SHA, "sha")
+X86_FEATURE (SHSTK, "shstk")
+X86_FEATURE (TBM, "tbm")
+X86_FEATURE (TSXLDTRK, "tsxldtrk")
+X86_FEATURE (UINTR, "uintr")
+X86_FEATURE (VAES, "vaes")
+X86_FEATURE (VZEROUPPER, "vzeroupper")
+X86_FEATURE (WAITPKG, "waitpkg")
+X86_FEATURE (WBNOINVD, "wbnoinvd")
+X86_FEATURE (X87, "x87")
+X86_FEATURE (XSAVE, "xsave")
+X86_FEATURE (XSAVEC, "xsavec")
+X86_FEATURE (XSAVEOPT, "xsaveopt")
+X86_FEATURE (XSAVES, "xsaves")
+X86_FEATURE (HRESET, "hreset")
+X86_FEATURE (AVXVNNI, "avxvnni")
+// These features aren't really CPU features, but the frontend can set them.
+X86_FEATURE (RETPOLINE_EXTERNAL_THUNK, "retpoline-external-thunk")
+X86_FEATURE (RETPOLINE_INDIRECT_BRANCHES, "retpoline-indirect-branches")
+X86_FEATURE (RETPOLINE_INDIRECT_CALLS, "retpoline-indirect-calls")
+X86_FEATURE (LVI_CFI, "lvi-cfi")
+X86_FEATURE (LVI_LOAD_HARDENING, "lvi-load-hardening")
#undef X86_FEATURE_COMPAT
#undef X86_FEATURE
diff --git a/linux-x64/clang/include/llvm/Support/X86TargetParser.h b/linux-x64/clang/include/llvm/Support/X86TargetParser.h
new file mode 100644
index 0000000..2d50830
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/X86TargetParser.h
@@ -0,0 +1,159 @@
+//===-- X86TargetParser - Parser for X86 features ---------------*- 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 implements a target parser to recognise X86 hardware features.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_X86TARGETPARSERCOMMON_H
+#define LLVM_SUPPORT_X86TARGETPARSERCOMMON_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace llvm {
+class StringRef;
+
+namespace X86 {
+
+// This should be kept in sync with libcc/compiler-rt as its included by clang
+// as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorVendors : unsigned {
+ VENDOR_DUMMY,
+#define X86_VENDOR(ENUM, STRING) \
+ ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ VENDOR_OTHER
+};
+
+// This should be kept in sync with libcc/compiler-rt as its included by clang
+// as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorTypes : unsigned {
+ CPU_TYPE_DUMMY,
+#define X86_CPU_TYPE(ENUM, STRING) \
+ ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ CPU_TYPE_MAX
+};
+
+// This should be kept in sync with libcc/compiler-rt as its included by clang
+// as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorSubtypes : unsigned {
+ CPU_SUBTYPE_DUMMY,
+#define X86_CPU_SUBTYPE(ENUM, STRING) \
+ ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ CPU_SUBTYPE_MAX
+};
+
+// This should be kept in sync with libcc/compiler-rt as it should be used
+// by clang as a proxy for what's in libgcc/compiler-rt.
+enum ProcessorFeatures {
+#define X86_FEATURE(ENUM, STRING) FEATURE_##ENUM,
+#include "llvm/Support/X86TargetParser.def"
+ CPU_FEATURE_MAX
+};
+
+enum CPUKind {
+ CK_None,
+ CK_i386,
+ CK_i486,
+ CK_WinChipC6,
+ CK_WinChip2,
+ CK_C3,
+ CK_i586,
+ CK_Pentium,
+ CK_PentiumMMX,
+ CK_PentiumPro,
+ CK_i686,
+ CK_Pentium2,
+ CK_Pentium3,
+ CK_PentiumM,
+ CK_C3_2,
+ CK_Yonah,
+ CK_Pentium4,
+ CK_Prescott,
+ CK_Nocona,
+ CK_Core2,
+ CK_Penryn,
+ CK_Bonnell,
+ CK_Silvermont,
+ CK_Goldmont,
+ CK_GoldmontPlus,
+ CK_Tremont,
+ CK_Nehalem,
+ CK_Westmere,
+ CK_SandyBridge,
+ CK_IvyBridge,
+ CK_Haswell,
+ CK_Broadwell,
+ CK_SkylakeClient,
+ CK_SkylakeServer,
+ CK_Cascadelake,
+ CK_Cooperlake,
+ CK_Cannonlake,
+ CK_IcelakeClient,
+ CK_IcelakeServer,
+ CK_Tigerlake,
+ CK_SapphireRapids,
+ CK_Alderlake,
+ CK_KNL,
+ CK_KNM,
+ CK_Lakemont,
+ CK_K6,
+ CK_K6_2,
+ CK_K6_3,
+ CK_Athlon,
+ CK_AthlonXP,
+ CK_K8,
+ CK_K8SSE3,
+ CK_AMDFAM10,
+ CK_BTVER1,
+ CK_BTVER2,
+ CK_BDVER1,
+ CK_BDVER2,
+ CK_BDVER3,
+ CK_BDVER4,
+ CK_ZNVER1,
+ CK_ZNVER2,
+ CK_ZNVER3,
+ CK_x86_64,
+ CK_x86_64_v2,
+ CK_x86_64_v3,
+ CK_x86_64_v4,
+ CK_Geode,
+};
+
+/// Parse \p CPU string into a CPUKind. Will only accept 64-bit capable CPUs if
+/// \p Only64Bit is true.
+CPUKind parseArchX86(StringRef CPU, bool Only64Bit = false);
+CPUKind parseTuneCPU(StringRef CPU, bool Only64Bit = false);
+
+/// Provide a list of valid CPU names. If \p Only64Bit is true, the list will
+/// only contain 64-bit capable CPUs.
+void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values,
+ bool Only64Bit = false);
+/// Provide a list of valid -mtune names.
+void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values,
+ bool Only64Bit = false);
+
+/// Get the key feature prioritizing target multiversioning.
+ProcessorFeatures getKeyFeature(CPUKind Kind);
+
+/// Fill in the features that \p CPU supports into \p Features.
+void getFeaturesForCPU(StringRef CPU, SmallVectorImpl<StringRef> &Features);
+
+/// Set or clear entries in \p Features that are implied to be enabled/disabled
+/// by the provided \p Feature.
+void updateImpliedFeatures(StringRef Feature, bool Enabled,
+ StringMap<bool> &Features);
+
+} // namespace X86
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/YAMLParser.h b/linux-x64/clang/include/llvm/Support/YAMLParser.h
index 3570119..759e11a 100644
--- a/linux-x64/clang/include/llvm/Support/YAMLParser.h
+++ b/linux-x64/clang/include/llvm/Support/YAMLParser.h
@@ -40,6 +40,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/SourceMgr.h"
#include <cassert>
#include <cstddef>
#include <iterator>
@@ -51,7 +52,6 @@
namespace llvm {
class MemoryBufferRef;
-class SourceMgr;
class raw_ostream;
class Twine;
@@ -78,6 +78,9 @@
/// escaped, but emitted verbatim.
std::string escape(StringRef Input, bool EscapePrintable = true);
+/// Parse \p S as a bool according to https://yaml.org/type/bool.html.
+llvm::Optional<bool> parseBool(StringRef S);
+
/// This class represents a YAML stream potentially containing multiple
/// documents.
class Stream {
@@ -100,7 +103,10 @@
return !failed();
}
- void printError(Node *N, const Twine &Msg);
+ void printError(Node *N, const Twine &Msg,
+ SourceMgr::DiagKind Kind = SourceMgr::DK_Error);
+ void printError(const SMRange &Range, const Twine &Msg,
+ SourceMgr::DiagKind Kind = SourceMgr::DK_Error);
private:
friend class Document;
@@ -139,7 +145,7 @@
void operator delete(void *Ptr, BumpPtrAllocator &Alloc,
size_t Size) noexcept {
- Alloc.Deallocate(Ptr, Size);
+ Alloc.Deallocate(Ptr, Size, 0);
}
void operator delete(void *) noexcept = delete;
@@ -222,7 +228,7 @@
/// Gets the value of this node as a StringRef.
///
- /// \param Storage is used to store the content of the returned StringRef iff
+ /// \param Storage is used to store the content of the returned StringRef if
/// it requires any modification from how it appeared in the source.
/// This happens with escaped characters and multi-line literals.
StringRef getValue(SmallVectorImpl<char> &Storage) const;
@@ -509,7 +515,6 @@
: Node(NK_Alias, D, StringRef(), StringRef()), Name(Val) {}
StringRef getName() const { return Name; }
- Node *getTarget();
static bool classof(const Node *N) { return N->getType() == NK_Alias; }
diff --git a/linux-x64/clang/include/llvm/Support/YAMLTraits.h b/linux-x64/clang/include/llvm/Support/YAMLTraits.h
index 2185cd7..bdd27dd 100644
--- a/linux-x64/clang/include/llvm/Support/YAMLTraits.h
+++ b/linux-x64/clang/include/llvm/Support/YAMLTraits.h
@@ -19,7 +19,9 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Regex.h"
+#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/YAMLParser.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
@@ -61,7 +63,7 @@
// Must provide:
// static void mapping(IO &io, T &fields);
// Optionally may provide:
- // static StringRef validate(IO &io, T &fields);
+ // static std::string validate(IO &io, T &fields);
//
// The optional flow flag will cause generated YAML to use a flow mapping
// (e.g. { a: 0, b: 1 }):
@@ -83,7 +85,7 @@
// Must provide:
// static void mapping(IO &io, T &fields, Context &Ctx);
// Optionally may provide:
- // static StringRef validate(IO &io, T &fields, Context &Ctx);
+ // static std::string validate(IO &io, T &fields, Context &Ctx);
//
// The optional flow flag will cause generated YAML to use a flow mapping
// (e.g. { a: 0, b: 1 }):
@@ -421,7 +423,7 @@
// Test if MappingContextTraits<T>::validate() is defined on type T.
template <class T, class Context> struct has_MappingValidateTraits {
- using Signature_validate = StringRef (*)(class IO &, T &, Context &);
+ using Signature_validate = std::string (*)(class IO &, T &, Context &);
template <typename U>
static char test(SameType<Signature_validate, &U::validate>*);
@@ -435,7 +437,7 @@
// Test if MappingTraits<T>::validate() is defined on type T.
template <class T> struct has_MappingValidateTraits<T, EmptyContext> {
- using Signature_validate = StringRef (*)(class IO &, T &);
+ using Signature_validate = std::string (*)(class IO &, T &);
template <typename U>
static char test(SameType<Signature_validate, &U::validate> *);
@@ -637,6 +639,7 @@
}
inline bool isBool(StringRef S) {
+ // FIXME: using parseBool is causing multiple tests to fail.
return S.equals("true") || S.equals("True") || S.equals("TRUE") ||
S.equals("false") || S.equals("False") || S.equals("FALSE");
}
@@ -649,23 +652,25 @@
inline QuotingType needsQuotes(StringRef S) {
if (S.empty())
return QuotingType::Single;
- if (isspace(S.front()) || isspace(S.back()))
- return QuotingType::Single;
+
+ QuotingType MaxQuotingNeeded = QuotingType::None;
+ if (isSpace(static_cast<unsigned char>(S.front())) ||
+ isSpace(static_cast<unsigned char>(S.back())))
+ MaxQuotingNeeded = QuotingType::Single;
if (isNull(S))
- return QuotingType::Single;
+ MaxQuotingNeeded = QuotingType::Single;
if (isBool(S))
- return QuotingType::Single;
+ MaxQuotingNeeded = QuotingType::Single;
if (isNumeric(S))
- return QuotingType::Single;
+ MaxQuotingNeeded = QuotingType::Single;
// 7.3.3 Plain Style
// Plain scalars must not begin with most indicators, as this would cause
// ambiguity with other YAML constructs.
static constexpr char Indicators[] = R"(-?:\,[]{}#&*!|>'"%@`)";
if (S.find_first_of(Indicators) == 0)
- return QuotingType::Single;
+ MaxQuotingNeeded = QuotingType::Single;
- QuotingType MaxQuotingNeeded = QuotingType::None;
for (unsigned char C : S) {
// Alphanum is safe.
if (isAlnum(C))
@@ -683,11 +688,11 @@
case 0x9:
continue;
// LF(0xA) and CR(0xD) may delimit values and so require at least single
- // quotes.
+ // quotes. LLVM YAML parser cannot handle single quoted multiline so use
+ // double quoting to produce valid YAML.
case 0xA:
case 0xD:
- MaxQuotingNeeded = QuotingType::Single;
- continue;
+ return QuotingType::Double;
// DEL (0x7F) are excluded from the allowed character range.
case 0x7F:
return QuotingType::Double;
@@ -748,7 +753,7 @@
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;
@@ -787,6 +792,7 @@
virtual NodeKind getNodeKind() = 0;
virtual void setError(const Twine &) = 0;
+ virtual void setAllowUnknownKeys(bool Allow);
template <typename T>
void enumCase(T &Val, const char* Str, const T ConstVal) {
@@ -842,7 +848,7 @@
Val = Val | ConstVal;
}
- void *getContext();
+ void *getContext() const;
void setContext(void *);
template <typename T> void mapRequired(const char *Key, T &Val) {
@@ -867,7 +873,7 @@
}
template <typename T, typename Context>
- typename std::enable_if<has_SequenceTraits<T>::value, void>::type
+ std::enable_if_t<has_SequenceTraits<T>::value, void>
mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
// omit key/value instead of outputting empty sequence
if (this->canElideEmptySequence() && !(Val.begin() != Val.end()))
@@ -882,7 +888,7 @@
}
template <typename T, typename Context>
- typename std::enable_if<!has_SequenceTraits<T>::value, void>::type
+ std::enable_if_t<!has_SequenceTraits<T>::value, void>
mapOptionalWithContext(const char *Key, T &Val, Context &Ctx) {
this->processKey(Key, Val, false, Ctx);
}
@@ -900,24 +906,7 @@
template <typename T, typename Context>
void processKeyWithDefault(const char *Key, Optional<T> &Val,
const Optional<T> &DefaultValue, bool Required,
- Context &Ctx) {
- assert(DefaultValue.hasValue() == false &&
- "Optional<T> shouldn't have a value!");
- void *SaveInfo;
- bool UseDefault = true;
- const bool sameAsDefault = outputting() && !Val.hasValue();
- if (!outputting() && !Val.hasValue())
- Val = T();
- if (Val.hasValue() &&
- this->preflightKey(Key, Required, sameAsDefault, UseDefault,
- SaveInfo)) {
- yamlize(*this, Val.getValue(), Required, Ctx);
- this->postflightKey(SaveInfo);
- } else {
- if (UseDefault)
- Val = DefaultValue;
- }
- }
+ Context &Ctx);
template <typename T, typename Context>
void processKeyWithDefault(const char *Key, T &Val, const T &DefaultValue,
@@ -964,7 +953,7 @@
} // end namespace detail
template <typename T>
-typename std::enable_if<has_ScalarEnumerationTraits<T>::value, void>::type
+std::enable_if_t<has_ScalarEnumerationTraits<T>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
io.beginEnumScalar();
ScalarEnumerationTraits<T>::enumeration(io, Val);
@@ -972,7 +961,7 @@
}
template <typename T>
-typename std::enable_if<has_ScalarBitSetTraits<T>::value, void>::type
+std::enable_if_t<has_ScalarBitSetTraits<T>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
bool DoClear;
if ( io.beginBitSetScalar(DoClear) ) {
@@ -984,8 +973,8 @@
}
template <typename T>
-typename std::enable_if<has_ScalarTraits<T>::value, void>::type
-yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
+std::enable_if_t<has_ScalarTraits<T>::value, void> yamlize(IO &io, T &Val, bool,
+ EmptyContext &Ctx) {
if ( io.outputting() ) {
std::string Storage;
raw_string_ostream Buffer(Storage);
@@ -1004,7 +993,7 @@
}
template <typename T>
-typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type
+std::enable_if_t<has_BlockScalarTraits<T>::value, void>
yamlize(IO &YamlIO, T &Val, bool, EmptyContext &Ctx) {
if (YamlIO.outputting()) {
std::string Storage;
@@ -1023,7 +1012,7 @@
}
template <typename T>
-typename std::enable_if<has_TaggedScalarTraits<T>::value, void>::type
+std::enable_if_t<has_TaggedScalarTraits<T>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
if (io.outputting()) {
std::string ScalarStorage, TagStorage;
@@ -1048,14 +1037,14 @@
}
template <typename T, typename Context>
-typename std::enable_if<validatedMappingTraits<T, Context>::value, void>::type
+std::enable_if_t<validatedMappingTraits<T, Context>::value, void>
yamlize(IO &io, T &Val, bool, Context &Ctx) {
if (has_FlowTraits<MappingTraits<T>>::value)
io.beginFlowMapping();
else
io.beginMapping();
if (io.outputting()) {
- StringRef Err = MappingTraits<T>::validate(io, Val);
+ std::string Err = MappingTraits<T>::validate(io, Val);
if (!Err.empty()) {
errs() << Err << "\n";
assert(Err.empty() && "invalid struct trying to be written as yaml");
@@ -1063,7 +1052,7 @@
}
detail::doMapping(io, Val, Ctx);
if (!io.outputting()) {
- StringRef Err = MappingTraits<T>::validate(io, Val);
+ std::string Err = MappingTraits<T>::validate(io, Val);
if (!Err.empty())
io.setError(Err);
}
@@ -1074,7 +1063,7 @@
}
template <typename T, typename Context>
-typename std::enable_if<unvalidatedMappingTraits<T, Context>::value, void>::type
+std::enable_if_t<unvalidatedMappingTraits<T, Context>::value, void>
yamlize(IO &io, T &Val, bool, Context &Ctx) {
if (has_FlowTraits<MappingTraits<T>>::value) {
io.beginFlowMapping();
@@ -1088,7 +1077,7 @@
}
template <typename T>
-typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type
+std::enable_if_t<has_CustomMappingTraits<T>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
if ( io.outputting() ) {
io.beginMapping();
@@ -1103,7 +1092,7 @@
}
template <typename T>
-typename std::enable_if<has_PolymorphicTraits<T>::value, void>::type
+std::enable_if_t<has_PolymorphicTraits<T>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
switch (io.outputting() ? PolymorphicTraits<T>::getKind(Val)
: io.getNodeKind()) {
@@ -1117,13 +1106,13 @@
}
template <typename T>
-typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type
+std::enable_if_t<missingTraits<T, EmptyContext>::value, void>
yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) {
char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
}
template <typename T, typename Context>
-typename std::enable_if<has_SequenceTraits<T>::value, void>::type
+std::enable_if_t<has_SequenceTraits<T>::value, void>
yamlize(IO &io, T &Seq, bool, Context &Ctx) {
if ( has_FlowTraits< SequenceTraits<T>>::value ) {
unsigned incnt = io.beginFlowSequence();
@@ -1246,10 +1235,9 @@
// type. This way endian aware types are supported whenever the traits are
// defined for the underlying type.
template <typename value_type, support::endianness endian, size_t alignment>
-struct ScalarTraits<
- support::detail::packed_endian_specific_integral<value_type, endian,
- alignment>,
- typename std::enable_if<has_ScalarTraits<value_type>::value>::type> {
+struct ScalarTraits<support::detail::packed_endian_specific_integral<
+ value_type, endian, alignment>,
+ std::enable_if_t<has_ScalarTraits<value_type>::value>> {
using endian_type =
support::detail::packed_endian_specific_integral<value_type, endian,
alignment>;
@@ -1274,8 +1262,7 @@
struct ScalarEnumerationTraits<
support::detail::packed_endian_specific_integral<value_type, endian,
alignment>,
- typename std::enable_if<
- has_ScalarEnumerationTraits<value_type>::value>::type> {
+ std::enable_if_t<has_ScalarEnumerationTraits<value_type>::value>> {
using endian_type =
support::detail::packed_endian_specific_integral<value_type, endian,
alignment>;
@@ -1291,7 +1278,7 @@
struct ScalarBitSetTraits<
support::detail::packed_endian_specific_integral<value_type, endian,
alignment>,
- typename std::enable_if<has_ScalarBitSetTraits<value_type>::value>::type> {
+ std::enable_if_t<has_ScalarBitSetTraits<value_type>::value>> {
using endian_type =
support::detail::packed_endian_specific_integral<value_type, endian,
alignment>;
@@ -1402,7 +1389,7 @@
std::error_code error();
private:
- bool outputting() override;
+ bool outputting() const override;
bool mapTag(StringRef, bool) override;
void beginMapping() override;
void endMapping() override;
@@ -1487,9 +1474,10 @@
static bool classof(const MapHNode *) { return true; }
- using NameToNode = StringMap<std::unique_ptr<HNode>>;
+ using NameToNodeAndLoc =
+ StringMap<std::pair<std::unique_ptr<HNode>, SMRange>>;
- NameToNode Mapping;
+ NameToNodeAndLoc Mapping;
SmallVector<std::string, 6> ValidKeys;
};
@@ -1511,6 +1499,11 @@
std::unique_ptr<Input::HNode> createHNodes(Node *node);
void setError(HNode *hnode, const Twine &message);
void setError(Node *node, const Twine &message);
+ void setError(const SMRange &Range, const Twine &message);
+
+ void reportWarning(HNode *hnode, const Twine &message);
+ void reportWarning(Node *hnode, const Twine &message);
+ void reportWarning(const SMRange &Range, const Twine &message);
public:
// These are only used by operator>>. They could be private
@@ -1521,6 +1514,8 @@
/// Returns the current node that's being parsed by the YAML Parser.
const Node *getCurrentNode() const;
+ void setAllowUnknownKeys(bool Allow) override;
+
private:
SourceMgr SrcMgr; // must be before Strm
std::unique_ptr<llvm::yaml::Stream> Strm;
@@ -1530,7 +1525,8 @@
document_iterator DocIterator;
std::vector<bool> BitValuesUsed;
HNode *CurrentNode = nullptr;
- bool ScalarMatchFound;
+ bool ScalarMatchFound = false;
+ bool AllowUnknownKeys = false;
};
///
@@ -1549,7 +1545,7 @@
/// 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;
@@ -1620,10 +1616,47 @@
bool NeedBitValueComma = false;
bool NeedFlowSequenceComma = false;
bool EnumerationMatchFound = false;
- bool NeedsNewLine = false;
bool WriteDefaultValues = false;
+ StringRef Padding;
+ StringRef PaddingBeforeContainer;
};
+template <typename T, typename Context>
+void IO::processKeyWithDefault(const char *Key, Optional<T> &Val,
+ const Optional<T> &DefaultValue, bool Required,
+ Context &Ctx) {
+ assert(DefaultValue.hasValue() == false &&
+ "Optional<T> shouldn't have a value!");
+ void *SaveInfo;
+ bool UseDefault = true;
+ const bool sameAsDefault = outputting() && !Val.hasValue();
+ if (!outputting() && !Val.hasValue())
+ Val = T();
+ if (Val.hasValue() &&
+ this->preflightKey(Key, Required, sameAsDefault, UseDefault, SaveInfo)) {
+
+ // When reading an Optional<X> key from a YAML description, we allow the
+ // special "<none>" value, which can be used to specify that no value was
+ // requested, i.e. the DefaultValue will be assigned. The DefaultValue is
+ // usually None.
+ bool IsNone = false;
+ if (!outputting())
+ if (auto *Node = dyn_cast<ScalarNode>(((Input *)this)->getCurrentNode()))
+ // We use rtrim to ignore possible white spaces that might exist when a
+ // comment is present on the same line.
+ IsNone = Node->getRawValue().rtrim(' ') == "<none>";
+
+ if (IsNone)
+ Val = DefaultValue;
+ else
+ yamlize(*this, Val.getValue(), Required, Ctx);
+ this->postflightKey(SaveInfo);
+ } else {
+ if (UseDefault)
+ Val = DefaultValue;
+ }
+}
+
/// YAML I/O does conversion based on types. But often native data types
/// are just a typedef of built in intergral types (e.g. int). But the C++
/// type matching system sees through the typedef and all the typedefed types
@@ -1684,10 +1717,15 @@
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
};
+template <> struct ScalarTraits<VersionTuple> {
+ static void output(const VersionTuple &Value, void *, llvm::raw_ostream &Out);
+ static StringRef input(StringRef, void *, VersionTuple &);
+ static QuotingType mustQuote(StringRef) { return QuotingType::None; }
+};
+
// Define non-member operator>> so that Input can stream in a document list.
template <typename T>
-inline
-typename std::enable_if<has_DocumentListTraits<T>::value, Input &>::type
+inline std::enable_if_t<has_DocumentListTraits<T>::value, Input &>
operator>>(Input &yin, T &docList) {
int i = 0;
EmptyContext Ctx;
@@ -1703,8 +1741,7 @@
// Define non-member operator>> so that Input can stream in a map as a document.
template <typename T>
-inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
- Input &>::type
+inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Input &>
operator>>(Input &yin, T &docMap) {
EmptyContext Ctx;
yin.setCurrentDocument();
@@ -1715,8 +1752,7 @@
// Define non-member operator>> so that Input can stream in a sequence as
// a document.
template <typename T>
-inline
-typename std::enable_if<has_SequenceTraits<T>::value, Input &>::type
+inline std::enable_if_t<has_SequenceTraits<T>::value, Input &>
operator>>(Input &yin, T &docSeq) {
EmptyContext Ctx;
if (yin.setCurrentDocument())
@@ -1726,8 +1762,7 @@
// Define non-member operator>> so that Input can stream in a block scalar.
template <typename T>
-inline
-typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type
+inline std::enable_if_t<has_BlockScalarTraits<T>::value, Input &>
operator>>(Input &In, T &Val) {
EmptyContext Ctx;
if (In.setCurrentDocument())
@@ -1737,8 +1772,7 @@
// Define non-member operator>> so that Input can stream in a string map.
template <typename T>
-inline
-typename std::enable_if<has_CustomMappingTraits<T>::value, Input &>::type
+inline std::enable_if_t<has_CustomMappingTraits<T>::value, Input &>
operator>>(Input &In, T &Val) {
EmptyContext Ctx;
if (In.setCurrentDocument())
@@ -1748,7 +1782,7 @@
// Define non-member operator>> so that Input can stream in a polymorphic type.
template <typename T>
-inline typename std::enable_if<has_PolymorphicTraits<T>::value, Input &>::type
+inline std::enable_if_t<has_PolymorphicTraits<T>::value, Input &>
operator>>(Input &In, T &Val) {
EmptyContext Ctx;
if (In.setCurrentDocument())
@@ -1758,8 +1792,7 @@
// Provide better error message about types missing a trait specialization
template <typename T>
-inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
- Input &>::type
+inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Input &>
operator>>(Input &yin, T &docSeq) {
char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
return yin;
@@ -1767,8 +1800,7 @@
// Define non-member operator<< so that Output can stream out document list.
template <typename T>
-inline
-typename std::enable_if<has_DocumentListTraits<T>::value, Output &>::type
+inline std::enable_if_t<has_DocumentListTraits<T>::value, Output &>
operator<<(Output &yout, T &docList) {
EmptyContext Ctx;
yout.beginDocuments();
@@ -1786,8 +1818,7 @@
// Define non-member operator<< so that Output can stream out a map.
template <typename T>
-inline typename std::enable_if<has_MappingTraits<T, EmptyContext>::value,
- Output &>::type
+inline std::enable_if_t<has_MappingTraits<T, EmptyContext>::value, Output &>
operator<<(Output &yout, T &map) {
EmptyContext Ctx;
yout.beginDocuments();
@@ -1801,8 +1832,7 @@
// Define non-member operator<< so that Output can stream out a sequence.
template <typename T>
-inline
-typename std::enable_if<has_SequenceTraits<T>::value, Output &>::type
+inline std::enable_if_t<has_SequenceTraits<T>::value, Output &>
operator<<(Output &yout, T &seq) {
EmptyContext Ctx;
yout.beginDocuments();
@@ -1816,8 +1846,7 @@
// Define non-member operator<< so that Output can stream out a block scalar.
template <typename T>
-inline
-typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type
+inline std::enable_if_t<has_BlockScalarTraits<T>::value, Output &>
operator<<(Output &Out, T &Val) {
EmptyContext Ctx;
Out.beginDocuments();
@@ -1831,8 +1860,7 @@
// Define non-member operator<< so that Output can stream out a string map.
template <typename T>
-inline
-typename std::enable_if<has_CustomMappingTraits<T>::value, Output &>::type
+inline std::enable_if_t<has_CustomMappingTraits<T>::value, Output &>
operator<<(Output &Out, T &Val) {
EmptyContext Ctx;
Out.beginDocuments();
@@ -1847,7 +1875,7 @@
// Define non-member operator<< so that Output can stream out a polymorphic
// type.
template <typename T>
-inline typename std::enable_if<has_PolymorphicTraits<T>::value, Output &>::type
+inline std::enable_if_t<has_PolymorphicTraits<T>::value, Output &>
operator<<(Output &Out, T &Val) {
EmptyContext Ctx;
Out.beginDocuments();
@@ -1864,8 +1892,7 @@
// Provide better error message about types missing a trait specialization
template <typename T>
-inline typename std::enable_if<missingTraits<T, EmptyContext>::value,
- Output &>::type
+inline std::enable_if_t<missingTraits<T, EmptyContext>::value, Output &>
operator<<(Output &yout, T &seq) {
char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)];
return yout;
@@ -1896,25 +1923,25 @@
// If T has SequenceElementTraits, then vector<T> and SmallVector<T, N> have
// SequenceTraits that do the obvious thing.
template <typename T>
-struct SequenceTraits<std::vector<T>,
- typename std::enable_if<CheckIsBool<
- SequenceElementTraits<T>::flow>::value>::type>
+struct SequenceTraits<
+ std::vector<T>,
+ std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
: SequenceTraitsImpl<std::vector<T>, SequenceElementTraits<T>::flow> {};
template <typename T, unsigned N>
-struct SequenceTraits<SmallVector<T, N>,
- typename std::enable_if<CheckIsBool<
- SequenceElementTraits<T>::flow>::value>::type>
+struct SequenceTraits<
+ SmallVector<T, N>,
+ std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
: SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
template <typename T>
-struct SequenceTraits<SmallVectorImpl<T>,
- typename std::enable_if<CheckIsBool<
- SequenceElementTraits<T>::flow>::value>::type>
+struct SequenceTraits<
+ SmallVectorImpl<T>,
+ std::enable_if_t<CheckIsBool<SequenceElementTraits<T>::flow>::value>>
: SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
// Sequences of fundamental types use flow formatting.
template <typename T>
-struct SequenceElementTraits<
- T, typename std::enable_if<std::is_fundamental<T>::value>::type> {
+struct SequenceElementTraits<T,
+ std::enable_if_t<std::is_fundamental<T>::value>> {
static const bool flow = true;
};
@@ -1934,7 +1961,7 @@
using map_type = std::map<std::string, T>;
static void inputOne(IO &io, StringRef key, map_type &v) {
- io.mapRequired(key.str().c_str(), v[key]);
+ io.mapRequired(key.str().c_str(), v[std::string(key)]);
}
static void output(IO &io, map_type &v) {
@@ -2033,4 +2060,9 @@
} \
}
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex32)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex16)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex8)
+
#endif // LLVM_SUPPORT_YAMLTRAITS_H
diff --git a/linux-x64/clang/include/llvm/Support/circular_raw_ostream.h b/linux-x64/clang/include/llvm/Support/circular_raw_ostream.h
index 4ecdb17..d2f01ea 100644
--- a/linux-x64/clang/include/llvm/Support/circular_raw_ostream.h
+++ b/linux-x64/clang/include/llvm/Support/circular_raw_ostream.h
@@ -27,12 +27,12 @@
/// stream and is responsible for cleanup, memory management
/// issues, etc.
///
- static const bool TAKE_OWNERSHIP = true;
+ static constexpr bool TAKE_OWNERSHIP = true;
/// REFERENCE_ONLY - Tell this stream it should not manage the
/// held stream.
///
- static const bool REFERENCE_ONLY = false;
+ static constexpr bool REFERENCE_ONLY = false;
private:
/// TheStream - The real stream we output to. We set it to be
@@ -122,6 +122,10 @@
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/linux-x64/clang/include/llvm/Support/raw_ostream.h b/linux-x64/clang/include/llvm/Support/raw_ostream.h
index 48bb623..bd15f97 100644
--- a/linux-x64/clang/include/llvm/Support/raw_ostream.h
+++ b/linux-x64/clang/include/llvm/Support/raw_ostream.h
@@ -15,12 +15,15 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DataTypes.h"
#include <cassert>
+#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include <system_error>
+#include <type_traits>
namespace llvm {
@@ -29,12 +32,14 @@
class FormattedString;
class FormattedNumber;
class FormattedBytes;
+template <class T> class LLVM_NODISCARD Expected;
namespace sys {
namespace fs {
enum FileAccess : unsigned;
enum OpenFlags : unsigned;
enum CreationDisposition : unsigned;
+class FileLocker;
} // end namespace fs
} // end namespace sys
@@ -43,7 +48,16 @@
/// buffered disciplines etc. It is a simple buffer that outputs
/// a chunk at a time.
class raw_ostream {
+public:
+ // Class kinds to support LLVM-style RTTI.
+ enum class OStreamKind {
+ OK_OStream,
+ OK_FDStream,
+ };
+
private:
+ OStreamKind Kind;
+
/// The buffer is handled in such a way that the buffer is
/// uninitialized, unbuffered, or out of space when OutBufCur >=
/// OutBufEnd. Thus a single comparison suffices to determine if we
@@ -63,8 +77,13 @@
/// for a \see write_impl() call to handle the data which has been put into
/// this buffer.
char *OutBufStart, *OutBufEnd, *OutBufCur;
+ bool ColorEnabled = false;
- enum BufferKind {
+ /// Optional stream this stream is tied to. If this stream is written to, the
+ /// tied-to stream will be flushed first.
+ raw_ostream *TiedStream = nullptr;
+
+ enum class BufferKind {
Unbuffered = 0,
InternalBuffer,
ExternalBuffer
@@ -72,7 +91,7 @@
public:
// color order matches ANSI escape sequence, don't change
- enum Colors {
+ enum class Colors {
BLACK = 0,
RED,
GREEN,
@@ -81,11 +100,25 @@
MAGENTA,
CYAN,
WHITE,
- SAVEDCOLOR
+ SAVEDCOLOR,
+ RESET,
};
- explicit raw_ostream(bool unbuffered = false)
- : BufferMode(unbuffered ? Unbuffered : InternalBuffer) {
+ static constexpr Colors BLACK = Colors::BLACK;
+ static constexpr Colors RED = Colors::RED;
+ static constexpr Colors GREEN = Colors::GREEN;
+ static constexpr Colors YELLOW = Colors::YELLOW;
+ static constexpr Colors BLUE = Colors::BLUE;
+ static constexpr Colors MAGENTA = Colors::MAGENTA;
+ static constexpr Colors CYAN = Colors::CYAN;
+ static constexpr Colors WHITE = Colors::WHITE;
+ static constexpr Colors SAVEDCOLOR = Colors::SAVEDCOLOR;
+ static constexpr Colors RESET = Colors::RESET;
+
+ explicit raw_ostream(bool unbuffered = false,
+ OStreamKind K = OStreamKind::OK_OStream)
+ : Kind(K), BufferMode(unbuffered ? BufferKind::Unbuffered
+ : BufferKind::InternalBuffer) {
// Start out ready to flush.
OutBufStart = OutBufEnd = OutBufCur = nullptr;
}
@@ -98,6 +131,8 @@
/// tell - Return the current offset with the file.
uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); }
+ OStreamKind get_kind() const { return Kind; }
+
//===--------------------------------------------------------------------===//
// Configuration Interface
//===--------------------------------------------------------------------===//
@@ -109,13 +144,13 @@
/// Set the stream to be buffered, using the specified buffer size.
void SetBufferSize(size_t Size) {
flush();
- SetBufferAndMode(new char[Size], Size, InternalBuffer);
+ SetBufferAndMode(new char[Size], Size, BufferKind::InternalBuffer);
}
size_t GetBufferSize() const {
// If we're supposed to be buffered but haven't actually gotten around
// to allocating the buffer yet, return the value that would be used.
- if (BufferMode != Unbuffered && OutBufStart == nullptr)
+ if (BufferMode != BufferKind::Unbuffered && OutBufStart == nullptr)
return preferred_buffer_size();
// Otherwise just return the size of the allocated buffer.
@@ -127,7 +162,7 @@
/// when the stream is being set to unbuffered.
void SetUnbuffered() {
flush();
- SetBufferAndMode(nullptr, 0, Unbuffered);
+ SetBufferAndMode(nullptr, 0, BufferKind::Unbuffered);
}
size_t GetNumBytesInBuffer() const {
@@ -214,6 +249,9 @@
/// 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);
@@ -253,21 +291,15 @@
/// @param Bold bold/brighter text, default false
/// @param BG if true change the background, default: change foreground
/// @returns itself so it can be used within << invocations
- virtual raw_ostream &changeColor(enum Colors Color,
- bool Bold = false,
- bool BG = false) {
- (void)Color;
- (void)Bold;
- (void)BG;
- return *this;
- }
+ virtual raw_ostream &changeColor(enum Colors Color, bool Bold = false,
+ bool BG = false);
/// Resets the colors to terminal defaults. Call this when you are done
/// outputting colored text, or before program exit.
- virtual raw_ostream &resetColor() { return *this; }
+ virtual raw_ostream &resetColor();
/// Reverses the foreground and background colors.
- virtual raw_ostream &reverseColor() { return *this; }
+ virtual raw_ostream &reverseColor();
/// This function determines if this stream is connected to a "tty" or
/// "console" window. That is, the output would be displayed to the user
@@ -275,8 +307,17 @@
virtual bool is_displayed() const { return false; }
/// This function determines if this stream is displayed and supports colors.
+ /// The result is unaffected by calls to enable_color().
virtual bool has_colors() const { return is_displayed(); }
+ // Enable or disable colors. Once enable_colors(false) is called,
+ // changeColor() has no effect until enable_colors(true) is called.
+ virtual void enable_colors(bool enable) { ColorEnabled = enable; }
+
+ /// Tie this stream to the specified stream. Replaces any existing tied-to
+ /// stream. Specifying a nullptr unties the stream.
+ void tie(raw_ostream *TieTo) { TiedStream = TieTo; }
+
//===--------------------------------------------------------------------===//
// Subclass Interface
//===--------------------------------------------------------------------===//
@@ -306,7 +347,7 @@
/// use only by subclasses which can arrange for the output to go directly
/// into the desired output buffer, instead of being copied on each flush.
void SetBuffer(char *BufferStart, size_t Size) {
- SetBufferAndMode(BufferStart, Size, ExternalBuffer);
+ SetBufferAndMode(BufferStart, Size, BufferKind::ExternalBuffer);
}
/// Return an efficient buffer size for the underlying output mechanism.
@@ -331,9 +372,27 @@
/// unused bytes in the buffer.
void copy_to_buffer(const char *Ptr, size_t Size);
+ /// Compute whether colors should be used and do the necessary work such as
+ /// flushing. The result is affected by calls to enable_color().
+ bool prepare_colors();
+
+ /// Flush the tied-to stream (if present) and then write the required data.
+ void flush_tied_then_write(const char *Ptr, size_t Size);
+
virtual void anchor();
};
+/// Call the appropriate insertion operator, given an rvalue reference to a
+/// raw_ostream object and return a stream of the same type as the argument.
+template <typename OStream, typename T>
+std::enable_if_t<!std::is_reference<OStream>::value &&
+ std::is_base_of<raw_ostream, OStream>::value,
+ OStream &&>
+operator<<(OStream &&OS, const T &Value) {
+ OS << Value;
+ return std::move(OS);
+}
+
/// An abstract base class for streams implementations that also support a
/// pwrite operation. This is useful for code that can mostly stream out data,
/// but needs to patch in a header that needs to know the output size.
@@ -342,8 +401,9 @@
void anchor() override;
public:
- explicit raw_pwrite_stream(bool Unbuffered = false)
- : raw_ostream(Unbuffered) {}
+ explicit raw_pwrite_stream(bool Unbuffered = false,
+ OStreamKind K = OStreamKind::OK_OStream)
+ : raw_ostream(Unbuffered, K) {}
void pwrite(const char *Ptr, size_t Size, uint64_t Offset) {
#ifndef NDEBUG
uint64_t Pos = tell();
@@ -365,8 +425,8 @@
class raw_fd_ostream : public raw_pwrite_stream {
int FD;
bool ShouldClose;
-
- bool SupportsSeeking;
+ bool SupportsSeeking = false;
+ mutable Optional<bool> HasColors;
#ifdef _WIN32
/// True if this fd refers to a Windows console device. Mintty and other
@@ -376,7 +436,7 @@
std::error_code EC;
- uint64_t pos;
+ uint64_t pos = 0;
/// See raw_ostream::write_impl.
void write_impl(const char *Ptr, size_t Size) override;
@@ -390,10 +450,17 @@
/// Determine an efficient buffer size.
size_t preferred_buffer_size() const override;
+ void anchor() override;
+
+protected:
/// Set the flag indicating that an output error has been encountered.
void error_detected(std::error_code EC) { this->EC = EC; }
- void anchor() override;
+ /// Return the file descriptor.
+ int get_fd() const { return FD; }
+
+ // Update the file position by increasing \p Delta.
+ void inc_pos(uint64_t Delta) { pos += Delta; }
public:
/// Open the specified file for writing. If an error occurs, information
@@ -418,7 +485,8 @@
/// FD is the file descriptor that this writes to. If ShouldClose is true,
/// this closes the file when the stream is destroyed. If FD is for stdout or
/// stderr, it will not be closed.
- raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false);
+ raw_fd_ostream(int fd, bool shouldClose, bool unbuffered = false,
+ OStreamKind K = OStreamKind::OK_OStream);
~raw_fd_ostream() override;
@@ -426,18 +494,12 @@
/// fsync.
void close();
- bool supportsSeeking() { return SupportsSeeking; }
+ bool supportsSeeking() const { return SupportsSeeking; }
/// Flushes the stream and repositions the underlying file descriptor position
/// to the offset specified from the beginning of the file.
uint64_t seek(uint64_t off);
- raw_ostream &changeColor(enum Colors colors, bool bold=false,
- bool bg=false) override;
- raw_ostream &resetColor() override;
-
- raw_ostream &reverseColor() override;
-
bool is_displayed() const override;
bool has_colors() const override;
@@ -460,20 +522,83 @@
/// - from The Zen of Python, by Tim Peters
///
void clear_error() { EC = std::error_code(); }
+
+ /// Locks the underlying file.
+ ///
+ /// @returns RAII object that releases the lock upon leaving the scope, if the
+ /// locking was successful. Otherwise returns corresponding
+ /// error code.
+ ///
+ /// The function blocks the current thread until the lock become available or
+ /// error occurs.
+ ///
+ /// Possible use of this function may be as follows:
+ ///
+ /// @code{.cpp}
+ /// if (auto L = stream.lock()) {
+ /// // ... do action that require file to be locked.
+ /// } else {
+ /// handleAllErrors(std::move(L.takeError()), [&](ErrorInfoBase &EIB) {
+ /// // ... handle lock error.
+ /// });
+ /// }
+ /// @endcode
+ LLVM_NODISCARD Expected<sys::fs::FileLocker> lock();
+
+ /// Tries to lock the underlying file within the specified period.
+ ///
+ /// @returns RAII object that releases the lock upon leaving the scope, if the
+ /// locking was successful. Otherwise returns corresponding
+ /// error code.
+ ///
+ /// It is used as @ref lock.
+ LLVM_NODISCARD
+ Expected<sys::fs::FileLocker> tryLockFor(std::chrono::milliseconds Timeout);
};
-/// This returns a reference to a raw_ostream for standard output. Use it like:
-/// outs() << "foo" << "bar";
-raw_ostream &outs();
+/// This returns a reference to a raw_fd_ostream for standard output. Use it
+/// like: outs() << "foo" << "bar";
+raw_fd_ostream &outs();
-/// This returns a reference to a raw_ostream for standard error. Use it like:
-/// errs() << "foo" << "bar";
-raw_ostream &errs();
+/// This returns a reference to a raw_ostream for standard error.
+/// Use it like: errs() << "foo" << "bar";
+/// By default, the stream is tied to stdout to ensure stdout is flushed before
+/// stderr is written, to ensure the error messages are written in their
+/// expected place.
+raw_fd_ostream &errs();
/// This returns a reference to a raw_ostream which simply discards output.
raw_ostream &nulls();
//===----------------------------------------------------------------------===//
+// File Streams
+//===----------------------------------------------------------------------===//
+
+/// A raw_ostream of a file for reading/writing/seeking.
+///
+class raw_fd_stream : public raw_fd_ostream {
+public:
+ /// Open the specified file for reading/writing/seeking. If an error occurs,
+ /// information about the error is put into EC, and the stream should be
+ /// immediately destroyed.
+ raw_fd_stream(StringRef Filename, std::error_code &EC);
+
+ /// This reads the \p Size bytes into a buffer pointed by \p Ptr.
+ ///
+ /// \param Ptr The start of the buffer to hold data to be read.
+ ///
+ /// \param Size The number of bytes to be read.
+ ///
+ /// On success, the number of bytes read is returned, and the file position is
+ /// advanced by this number. On error, -1 is returned, use error() to get the
+ /// error code.
+ ssize_t read(char *Ptr, size_t Size);
+
+ /// Check if \p OS is a pointer of type raw_fd_stream*.
+ static bool classof(const raw_ostream *OS);
+};
+
+//===----------------------------------------------------------------------===//
// Output Stream Adaptors
//===----------------------------------------------------------------------===//
@@ -490,7 +615,9 @@
uint64_t current_pos() const override { return OS.size(); }
public:
- explicit raw_string_ostream(std::string &O) : OS(O) {}
+ explicit raw_string_ostream(std::string &O) : OS(O) {
+ SetUnbuffered();
+ }
~raw_string_ostream() override;
/// Flushes the stream contents to the target string and returns the string's
@@ -531,7 +658,7 @@
void flush() = delete;
/// Return a StringRef for the vector contents.
- StringRef str() { return StringRef(OS.data(), OS.size()); }
+ StringRef str() const { return StringRef(OS.data(), OS.size()); }
};
/// A raw_ostream that discards all output.
diff --git a/linux-x64/clang/include/llvm/Support/type_traits.h b/linux-x64/clang/include/llvm/Support/type_traits.h
index c8c6a76..7b7d5d9 100644
--- a/linux-x64/clang/include/llvm/Support/type_traits.h
+++ b/linux-x64/clang/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 {
@@ -33,7 +28,7 @@
/// Also note that enum classes aren't implicitly convertible to integral types,
/// the value may therefore need to be explicitly converted before being used.
template <typename T> class is_integral_or_enum {
- using UnderlyingT = typename std::remove_reference<T>::type;
+ using UnderlyingT = std::remove_reference_t<T>;
public:
static const bool value =
@@ -50,7 +45,7 @@
template <typename T>
struct add_lvalue_reference_if_not_pointer<
- T, typename std::enable_if<std::is_pointer<T>::value>::type> {
+ T, std::enable_if_t<std::is_pointer<T>::value>> {
using type = T;
};
@@ -60,9 +55,8 @@
struct add_const_past_pointer { using type = const T; };
template <typename T>
-struct add_const_past_pointer<
- T, typename std::enable_if<std::is_pointer<T>::value>::type> {
- using type = const typename std::remove_pointer<T>::type *;
+struct add_const_past_pointer<T, std::enable_if_t<std::is_pointer<T>::value>> {
+ using type = const std::remove_pointer_t<T> *;
};
template <typename T, typename Enable = void>
@@ -70,8 +64,8 @@
using type = const T &;
};
template <typename T>
-struct const_pointer_or_const_ref<
- T, typename std::enable_if<std::is_pointer<T>::value>::type> {
+struct const_pointer_or_const_ref<T,
+ std::enable_if_t<std::is_pointer<T>::value>> {
using type = typename add_const_past_pointer<T>::type;
};
@@ -194,17 +188,4 @@
} // 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