Update prebuilt Clang to r365631c1 from Android.
The version we had was segfaulting.
Bug: 132420445
Change-Id: Icb45a6fe0b4e2166f7895e669df1157cec9fb4e0
diff --git a/linux-x64/clang/include/llvm/Support/AArch64TargetParser.def b/linux-x64/clang/include/llvm/Support/AArch64TargetParser.def
index d8c69c2..e152f38 100644
--- a/linux-x64/clang/include/llvm/Support/AArch64TargetParser.def
+++ b/linux-x64/clang/include/llvm/Support/AArch64TargetParser.def
@@ -50,78 +50,92 @@
#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("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("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")
#undef AARCH64_ARCH_EXT_NAME
#ifndef AARCH64_CPU_NAME
#define AARCH64_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)
#endif
AARCH64_CPU_NAME("cortex-a35", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC))
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("cortex-a53", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, true,
- (AArch64::AEK_CRC))
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("cortex-a55", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC))
AARCH64_CPU_NAME("cortex-a57", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC))
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("cortex-a72", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC))
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("cortex-a73", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC))
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("cortex-a75", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC))
+AARCH64_CPU_NAME("cortex-a76", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | AArch64::AEK_RCPC |
+ AArch64::AEK_SSBS))
+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("cyclone", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_NONE))
+ (AArch64::AEK_NONE))
AARCH64_CPU_NAME("exynos-m1", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC))
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("exynos-m2", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC))
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("exynos-m3", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC))
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("exynos-m4", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_FP16 | AArch64::AEK_DOTPROD))
+ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16))
+AARCH64_CPU_NAME("exynos-m5", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (AArch64::AEK_DOTPROD | AArch64::AEK_FP16))
AARCH64_CPU_NAME("falkor", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC | AArch64::AEK_RDM))
+ (AArch64::AEK_CRC | AArch64::AEK_RDM))
AARCH64_CPU_NAME("saphira", ARMV8_3A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_PROFILE))
+ (AArch64::AEK_PROFILE))
AARCH64_CPU_NAME("kryo", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC))
+ (AArch64::AEK_CRC))
AARCH64_CPU_NAME("thunderx2t99", ARMV8_1A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_NONE))
+ (AArch64::AEK_NONE))
AARCH64_CPU_NAME("thunderx", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
+ (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
AARCH64_CPU_NAME("thunderxt88", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
+ (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
AARCH64_CPU_NAME("thunderxt81", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
+ (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
AARCH64_CPU_NAME("thunderxt83", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
+ (AArch64::AEK_CRC | AArch64::AEK_PROFILE))
AARCH64_CPU_NAME("tsv110", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
- (AArch64::AEK_PROFILE | AArch64::AEK_FP16 | AArch64::AEK_FP16FML |
- AArch64::AEK_DOTPROD))
+ (AArch64::AEK_DOTPROD |
+ AArch64::AEK_FP16 | AArch64::AEK_FP16FML |
+ AArch64::AEK_PROFILE))
// 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 faf1c5c..965d385 100644
--- a/linux-x64/clang/include/llvm/Support/AArch64TargetParser.h
+++ b/linux-x64/clang/include/llvm/Support/AArch64TargetParser.h
@@ -49,6 +49,11 @@
AEK_SSBS = 1 << 20,
AEK_SB = 1 << 21,
AEK_PREDRES = 1 << 22,
+ AEK_SVE2 = 1 << 23,
+ AEK_SVE2AES = 1 << 24,
+ AEK_SVE2SM4 = 1 << 25,
+ AEK_SVE2SHA3 = 1 << 26,
+ AEK_BITPERM = 1 << 27,
};
enum class ArchKind {
diff --git a/linux-x64/clang/include/llvm/Support/AMDGPUMetadata.h b/linux-x64/clang/include/llvm/Support/AMDGPUMetadata.h
index f43be51..f7f1ec4 100644
--- a/linux-x64/clang/include/llvm/Support/AMDGPUMetadata.h
+++ b/linux-x64/clang/include/llvm/Support/AMDGPUMetadata.h
@@ -74,6 +74,7 @@
HiddenPrintfBuffer = 11,
HiddenDefaultQueue = 12,
HiddenCompletionAction = 13,
+ HiddenMultiGridSyncArg = 14,
Unknown = 0xff
};
@@ -156,6 +157,8 @@
constexpr char TypeName[] = "TypeName";
/// Key for Kernel::Arg::Metadata::mSize.
constexpr char Size[] = "Size";
+/// Key for Kernel::Arg::Metadata::mOffset.
+constexpr char Offset[] = "Offset";
/// Key for Kernel::Arg::Metadata::mAlign.
constexpr char Align[] = "Align";
/// Key for Kernel::Arg::Metadata::mValueKind.
@@ -188,6 +191,8 @@
std::string mTypeName = std::string();
/// Size in bytes. Required.
uint32_t mSize = 0;
+ /// Offset in bytes. Required for code object v3, unused for code object v2.
+ uint32_t mOffset = 0;
/// Alignment in bytes. Required.
uint32_t mAlign = 0;
/// Value kind. Required.
@@ -452,11 +457,30 @@
//===----------------------------------------------------------------------===//
namespace PALMD {
-/// PAL metadata assembler directive.
+/// PAL metadata (old linear format) assembler directive.
constexpr char AssemblerDirective[] = ".amd_amdgpu_pal_metadata";
+/// PAL metadata (new MsgPack format) beginning assembler directive.
+constexpr char AssemblerDirectiveBegin[] = ".amdgpu_pal_metadata";
+
+/// PAL metadata (new MsgPack format) ending assembler directive.
+constexpr char AssemblerDirectiveEnd[] = ".end_amdgpu_pal_metadata";
+
/// PAL metadata keys.
enum Key : uint32_t {
+ R_2E12_COMPUTE_PGM_RSRC1 = 0x2e12,
+ R_2D4A_SPI_SHADER_PGM_RSRC1_LS = 0x2d4a,
+ R_2D0A_SPI_SHADER_PGM_RSRC1_HS = 0x2d0a,
+ R_2CCA_SPI_SHADER_PGM_RSRC1_ES = 0x2cca,
+ R_2C8A_SPI_SHADER_PGM_RSRC1_GS = 0x2c8a,
+ R_2C4A_SPI_SHADER_PGM_RSRC1_VS = 0x2c4a,
+ R_2C0A_SPI_SHADER_PGM_RSRC1_PS = 0x2c0a,
+ R_2E00_COMPUTE_DISPATCH_INITIATOR = 0x2e00,
+ R_A1B3_SPI_PS_INPUT_ENA = 0xa1b3,
+ R_A1B4_SPI_PS_INPUT_ADDR = 0xa1b4,
+ R_A1B6_SPI_PS_IN_CONTROL = 0xa1b6,
+ R_A2D5_VGT_SHADER_STAGES_EN = 0xa2d5,
+
LS_NUM_USED_VGPRS = 0x10000021,
HS_NUM_USED_VGPRS = 0x10000022,
ES_NUM_USED_VGPRS = 0x10000023,
@@ -482,12 +506,6 @@
CS_SCRATCH_SIZE = 0x1000004a
};
-/// PAL metadata represented as a vector.
-typedef std::vector<uint32_t> Metadata;
-
-/// Converts \p PALMetadata to \p String.
-std::error_code toString(const Metadata &PALMetadata, std::string &String);
-
} // end namespace PALMD
} // end namespace AMDGPU
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/Support/AMDHSAKernelDescriptor.h b/linux-x64/clang/include/llvm/Support/AMDHSAKernelDescriptor.h
index dca1a31..d1c2147 100644
--- a/linux-x64/clang/include/llvm/Support/AMDHSAKernelDescriptor.h
+++ b/linux-x64/clang/include/llvm/Support/AMDHSAKernelDescriptor.h
@@ -88,8 +88,11 @@
COMPUTE_PGM_RSRC1(ENABLE_IEEE_MODE, 23, 1),
COMPUTE_PGM_RSRC1(BULKY, 24, 1),
COMPUTE_PGM_RSRC1(CDBG_USER, 25, 1),
- COMPUTE_PGM_RSRC1(FP16_OVFL, 26, 1), // GFX9+
- COMPUTE_PGM_RSRC1(RESERVED0, 27, 5),
+ COMPUTE_PGM_RSRC1(FP16_OVFL, 26, 1), // GFX9+
+ COMPUTE_PGM_RSRC1(RESERVED0, 27, 2),
+ COMPUTE_PGM_RSRC1(WGP_MODE, 29, 1), // GFX10+
+ COMPUTE_PGM_RSRC1(MEM_ORDERED, 30, 1), // GFX10+
+ COMPUTE_PGM_RSRC1(FWD_PROGRESS, 31, 1), // GFX10+
};
#undef COMPUTE_PGM_RSRC1
@@ -119,6 +122,15 @@
};
#undef COMPUTE_PGM_RSRC2
+// Compute program resource register 3. Must match hardware definition.
+#define COMPUTE_PGM_RSRC3(NAME, SHIFT, WIDTH) \
+ AMDHSA_BITS_ENUM_ENTRY(COMPUTE_PGM_RSRC3_ ## NAME, SHIFT, WIDTH)
+enum : int32_t {
+ COMPUTE_PGM_RSRC3(SHARED_VGPR_COUNT, 0, 4), // GFX10+
+ COMPUTE_PGM_RSRC3(RESERVED0, 4, 28),
+};
+#undef COMPUTE_PGM_RSRC3
+
// Kernel code properties. Must be kept backwards compatible.
#define KERNEL_CODE_PROPERTY(NAME, SHIFT, WIDTH) \
AMDHSA_BITS_ENUM_ENTRY(KERNEL_CODE_PROPERTY_ ## NAME, SHIFT, WIDTH)
@@ -130,7 +142,9 @@
KERNEL_CODE_PROPERTY(ENABLE_SGPR_DISPATCH_ID, 4, 1),
KERNEL_CODE_PROPERTY(ENABLE_SGPR_FLAT_SCRATCH_INIT, 5, 1),
KERNEL_CODE_PROPERTY(ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, 6, 1),
- KERNEL_CODE_PROPERTY(RESERVED0, 7, 9),
+ KERNEL_CODE_PROPERTY(RESERVED0, 7, 3),
+ KERNEL_CODE_PROPERTY(ENABLE_WAVEFRONT_SIZE32, 10, 1), // GFX10+
+ KERNEL_CODE_PROPERTY(RESERVED1, 11, 5),
};
#undef KERNEL_CODE_PROPERTY
@@ -140,7 +154,8 @@
uint32_t private_segment_fixed_size;
uint8_t reserved0[8];
int64_t kernel_code_entry_byte_offset;
- uint8_t reserved1[24];
+ uint8_t reserved1[20];
+ uint32_t compute_pgm_rsrc3; // GFX10+
uint32_t compute_pgm_rsrc1;
uint32_t compute_pgm_rsrc2;
uint16_t kernel_code_properties;
@@ -166,6 +181,9 @@
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(
diff --git a/linux-x64/clang/include/llvm/Support/ARMAttributeParser.h b/linux-x64/clang/include/llvm/Support/ARMAttributeParser.h
index c7aeaf9..f6c39ab 100644
--- a/linux-x64/clang/include/llvm/Support/ARMAttributeParser.h
+++ b/linux-x64/clang/include/llvm/Support/ARMAttributeParser.h
@@ -53,6 +53,8 @@
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,
diff --git a/linux-x64/clang/include/llvm/Support/ARMBuildAttributes.h b/linux-x64/clang/include/llvm/Support/ARMBuildAttributes.h
index 1299c0b..90481ea 100644
--- a/linux-x64/clang/include/llvm/Support/ARMBuildAttributes.h
+++ b/linux-x64/clang/include/llvm/Support/ARMBuildAttributes.h
@@ -67,6 +67,7 @@
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,
@@ -110,6 +111,7 @@
v8_R = 15, // e.g. Cortex R52
v8_M_Base= 16, // v8_M_Base AArch32
v8_M_Main= 17, // v8_M_Main AArch32
+ v8_1_M_Main=21, // v8_1_M_Main AArch32
};
enum CPUArchProfile { // (=7), uleb128
@@ -151,6 +153,10 @@
AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted
AllowNeonARMv8_1a = 4,// ARM v8.1-A SIMD was permitted (RDMA)
+ // Tag_MVE_arch, (=48), uleb128
+ AllowMVEInteger = 1, // integer-only MVE was permitted
+ AllowMVEIntegerAndFloat = 2, // both integer and floating point MVE were permitted
+
// Tag_ABI_PCS_R9_use, (=14), uleb128
R9IsGPR = 0, // R9 used as v6 (just another callee-saved register)
R9IsSB = 1, // R9 used as a global static base rgister
diff --git a/linux-x64/clang/include/llvm/Support/ARMTargetParser.def b/linux-x64/clang/include/llvm/Support/ARMTargetParser.def
index 35f8333..593480f 100644
--- a/linux-x64/clang/include/llvm/Support/ARMTargetParser.def
+++ b/linux-x64/clang/include/llvm/Support/ARMTargetParser.def
@@ -31,6 +31,8 @@
ARM_FPU("fpv5-d16", FK_FPV5_D16, FPUVersion::VFPV5, NeonSupportLevel::None, FPURestriction::D16)
ARM_FPU("fpv5-sp-d16", FK_FPV5_SP_D16, FPUVersion::VFPV5, NeonSupportLevel::None, FPURestriction::SP_D16)
ARM_FPU("fp-armv8", FK_FP_ARMV8, FPUVersion::VFPV5, NeonSupportLevel::None, FPURestriction::None)
+ARM_FPU("fp-armv8-fullfp16-d16", FK_FP_ARMV8_FULLFP16_D16, FPUVersion::VFPV5_FULLFP16, NeonSupportLevel::None, FPURestriction::D16)
+ARM_FPU("fp-armv8-fullfp16-sp-d16", FK_FP_ARMV8_FULLFP16_SP_D16, FPUVersion::VFPV5_FULLFP16, NeonSupportLevel::None, FPURestriction::SP_D16)
ARM_FPU("neon", FK_NEON, FPUVersion::VFPV3, NeonSupportLevel::Neon, FPURestriction::None)
ARM_FPU("neon-fp16", FK_NEON_FP16, FPUVersion::VFPV3_FP16, NeonSupportLevel::Neon, FPURestriction::None)
ARM_FPU("neon-vfpv4", FK_NEON_VFPV4, FPUVersion::VFPV4, NeonSupportLevel::Neon, FPURestriction::None)
@@ -118,6 +120,8 @@
ARMBuildAttrs::CPUArch::v8_M_Base, FK_NONE, ARM::AEK_HWDIVTHUMB)
ARM_ARCH("armv8-m.main", ARMV8MMainline, "8-M.Mainline", "v8m.main",
ARMBuildAttrs::CPUArch::v8_M_Main, FK_FPV5_D16, ARM::AEK_HWDIVTHUMB)
+ARM_ARCH("armv8.1-m.main", ARMV8_1MMainline, "8.1-M.Mainline", "v8.1m.main",
+ ARMBuildAttrs::CPUArch::v8_1_M_Main, FK_FP_ARMV8_FULLFP16_SP_D16, ARM::AEK_HWDIVTHUMB | ARM::AEK_RAS | ARM::AEK_LOB)
// Non-standard Arch names.
ARM_ARCH("iwmmxt", IWMMXT, "iwmmxt", "", ARMBuildAttrs::CPUArch::v5TE,
FK_NONE, ARM::AEK_NONE)
@@ -144,6 +148,8 @@
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("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)
@@ -158,6 +164,7 @@
ARM_ARCH_EXT_NAME("xscale", ARM::AEK_XSCALE, nullptr, nullptr)
ARM_ARCH_EXT_NAME("fp16fml", ARM::AEK_FP16FML, "+fp16fml", "-fp16fml")
ARM_ARCH_EXT_NAME("sb", ARM::AEK_SB, "+sb", "-sb")
+ARM_ARCH_EXT_NAME("lob", ARM::AEK_LOB, "+lob", "-lob")
#undef ARM_ARCH_EXT_NAME
#ifndef ARM_HW_DIV_NAME
@@ -251,6 +258,7 @@
ARM_CPU_NAME("cortex-m7", ARMV7EM, FK_FPV5_D16, false, ARM::AEK_NONE)
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-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)
@@ -261,12 +269,18 @@
ARM_CPU_NAME("cortex-a73", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
ARM_CPU_NAME("cortex-a75", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
(ARM::AEK_FP16 | ARM::AEK_DOTPROD))
+ARM_CPU_NAME("cortex-a76", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
+ARM_CPU_NAME("cortex-a76ae", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
ARM_CPU_NAME("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))
+ARM_CPU_NAME("exynos-m5", ARMV8_2A, FK_CRYPTO_NEON_FP_ARMV8, false,
+ (ARM::AEK_FP16 | ARM::AEK_DOTPROD))
ARM_CPU_NAME("kryo", ARMV8A, FK_CRYPTO_NEON_FP_ARMV8, false, ARM::AEK_CRC)
// Non-standard Arch names.
ARM_CPU_NAME("iwmmxt", IWMMXT, FK_NONE, true, ARM::AEK_NONE)
diff --git a/linux-x64/clang/include/llvm/Support/ARMTargetParser.h b/linux-x64/clang/include/llvm/Support/ARMTargetParser.h
index edd47ef..4b9070d 100644
--- a/linux-x64/clang/include/llvm/Support/ARMTargetParser.h
+++ b/linux-x64/clang/include/llvm/Support/ARMTargetParser.h
@@ -45,6 +45,13 @@
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,
// Unsupported extensions.
AEK_OS = 0x8000000,
AEK_IWMMXT = 0x10000000,
@@ -126,7 +133,8 @@
VFPV3,
VFPV3_FP16,
VFPV4,
- VFPV5
+ VFPV5,
+ VFPV5_FULLFP16,
};
// An FPU name restricts the FPU in one of three ways:
@@ -233,6 +241,8 @@
StringRef getSubArch(ArchKind AK);
StringRef getArchExtName(unsigned ArchExtKind);
StringRef getArchExtFeature(StringRef ArchExt);
+bool appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK, StringRef ArchExt,
+ std::vector<StringRef> &Features);
StringRef getHWDivName(unsigned HWDivKind);
// Information by Name
diff --git a/linux-x64/clang/include/llvm/Support/ARMWinEH.h b/linux-x64/clang/include/llvm/Support/ARMWinEH.h
index b1b821b..857a0d3 100644
--- a/linux-x64/clang/include/llvm/Support/ARMWinEH.h
+++ b/linux-x64/clang/include/llvm/Support/ARMWinEH.h
@@ -382,7 +382,7 @@
return ((Data[0] & 0x00400000) >> 22);
}
- uint8_t EpilogueCount() const {
+ uint16_t EpilogueCount() const {
if (HeaderWords(*this) == 1) {
if (isAArch64)
return (Data[0] & 0x07C00000) >> 22;
diff --git a/linux-x64/clang/include/llvm/Support/BinaryStreamReader.h b/linux-x64/clang/include/llvm/Support/BinaryStreamReader.h
index 32e5728..d8fddde 100644
--- a/linux-x64/clang/include/llvm/Support/BinaryStreamReader.h
+++ b/linux-x64/clang/include/llvm/Support/BinaryStreamReader.h
@@ -96,6 +96,18 @@
return Error::success();
}
+ /// Read an unsigned LEB128 encoded value.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ Error readULEB128(uint64_t &Dest);
+
+ /// Read a signed LEB128 encoded value.
+ ///
+ /// \returns a success error code if the data was successfully read, otherwise
+ /// returns an appropriate error code.
+ Error readSLEB128(int64_t &Dest);
+
/// Read a null terminated string from \p Dest. Whether a copy occurs depends
/// on the implementation of the underlying stream. Updates the stream's
/// offset to point after the newly read data.
diff --git a/linux-x64/clang/include/llvm/Support/BinaryStreamWriter.h b/linux-x64/clang/include/llvm/Support/BinaryStreamWriter.h
index ae019c8..86d2389 100644
--- a/linux-x64/clang/include/llvm/Support/BinaryStreamWriter.h
+++ b/linux-x64/clang/include/llvm/Support/BinaryStreamWriter.h
@@ -79,6 +79,20 @@
return writeInteger<U>(static_cast<U>(Num));
}
+ /// Write the unsigned integer Value to the underlying stream using ULEB128
+ /// encoding.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ Error writeULEB128(uint64_t Value);
+
+ /// Write the unsigned integer Value to the underlying stream using ULEB128
+ /// encoding.
+ ///
+ /// \returns a success error code if the data was successfully written,
+ /// otherwise returns an appropriate error code.
+ Error writeSLEB128(int64_t Value);
+
/// Write the string \p Str to the underlying stream followed by a null
/// terminator. On success, updates the offset so that subsequent writes
/// occur at the next unwritten position. \p Str need not be null terminated
diff --git a/linux-x64/clang/include/llvm/Support/BranchProbability.h b/linux-x64/clang/include/llvm/Support/BranchProbability.h
index dd0aba0..cd9d369 100644
--- a/linux-x64/clang/include/llvm/Support/BranchProbability.h
+++ b/linux-x64/clang/include/llvm/Support/BranchProbability.h
@@ -118,6 +118,13 @@
return *this;
}
+ BranchProbability &operator/=(BranchProbability RHS) {
+ assert(N != UnknownN && RHS.N != UnknownN &&
+ "Unknown probability cannot participate in arithmetics.");
+ N = (static_cast<uint64_t>(N) * D + RHS.N / 2) / RHS.N;
+ return *this;
+ }
+
BranchProbability &operator/=(uint32_t RHS) {
assert(N != UnknownN &&
"Unknown probability cannot participate in arithmetics.");
@@ -128,27 +135,38 @@
BranchProbability operator+(BranchProbability RHS) const {
BranchProbability Prob(*this);
- return Prob += RHS;
+ Prob += RHS;
+ return Prob;
}
BranchProbability operator-(BranchProbability RHS) const {
BranchProbability Prob(*this);
- return Prob -= RHS;
+ Prob -= RHS;
+ return Prob;
}
BranchProbability operator*(BranchProbability RHS) const {
BranchProbability Prob(*this);
- return Prob *= RHS;
+ Prob *= RHS;
+ return Prob;
}
BranchProbability operator*(uint32_t RHS) const {
BranchProbability Prob(*this);
- return Prob *= RHS;
+ Prob *= RHS;
+ return Prob;
+ }
+
+ BranchProbability operator/(BranchProbability RHS) const {
+ BranchProbability Prob(*this);
+ Prob /= RHS;
+ return Prob;
}
BranchProbability operator/(uint32_t RHS) const {
BranchProbability Prob(*this);
- return Prob /= RHS;
+ Prob /= RHS;
+ return Prob;
}
bool operator==(BranchProbability RHS) const { return N == RHS.N; }
diff --git a/linux-x64/clang/include/llvm/Support/CRC.h b/linux-x64/clang/include/llvm/Support/CRC.h
new file mode 100644
index 0000000..6ea8e3e
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/CRC.h
@@ -0,0 +1,25 @@
+//===-- llvm/Support/CRC.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 basic functions for calculating Cyclic Redundancy Check
+// or CRC.
+//
+//===----------------------------------------------------------------------===//
+
+#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);
+} // end namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/Casting.h b/linux-x64/clang/include/llvm/Support/Casting.h
index cddee36..46bdedb 100644
--- a/linux-x64/clang/include/llvm/Support/Casting.h
+++ b/linux-x64/clang/include/llvm/Support/Casting.h
@@ -143,6 +143,16 @@
typename simplify_type<const Y>::SimpleType>::doit(Val);
}
+// isa_and_nonnull<X> - Functionally identical to isa, except that a null value
+// is accepted.
+//
+template <class X, class Y>
+LLVM_NODISCARD inline bool isa_and_nonnull(const Y &Val) {
+ if (!Val)
+ return false;
+ return isa<X>(Val);
+}
+
//===----------------------------------------------------------------------===//
// cast<x> Support Templates
//===----------------------------------------------------------------------===//
diff --git a/linux-x64/clang/include/llvm/Support/CheckedArithmetic.h b/linux-x64/clang/include/llvm/Support/CheckedArithmetic.h
index 8f7fbde..8a50e3d 100644
--- a/linux-x64/clang/include/llvm/Support/CheckedArithmetic.h
+++ b/linux-x64/clang/include/llvm/Support/CheckedArithmetic.h
@@ -49,6 +49,15 @@
return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov);
}
+/// Subtract two signed integers \p LHS and \p RHS.
+/// \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
+checkedSub(T LHS, T RHS) {
+ return checkedOp(LHS, RHS, &llvm::APInt::ssub_ov);
+}
+
/// Multiply two signed integers \p LHS and \p RHS.
/// \return Optional of product if no signed overflow occurred,
/// \c None otherwise.
diff --git a/linux-x64/clang/include/llvm/Support/CodeGen.h b/linux-x64/clang/include/llvm/Support/CodeGen.h
index 3175b29..a3f423e 100644
--- a/linux-x64/clang/include/llvm/Support/CodeGen.h
+++ b/linux-x64/clang/include/llvm/Support/CodeGen.h
@@ -18,13 +18,14 @@
// Relocation model types.
namespace Reloc {
- enum Model { Static, PIC_, DynamicNoPIC, ROPI, RWPI, ROPI_RWPI };
+ // Cannot be named PIC due to collision with -DPIC
+ enum Model { Static, PIC_, DynamicNoPIC, ROPI, RWPI, ROPI_RWPI };
}
// Code model types.
namespace CodeModel {
// Sync changes with CodeGenCWrappers.h.
- enum Model { Tiny, Small, Kernel, Medium, Large };
+ enum Model { Tiny, Small, Kernel, Medium, Large };
}
namespace PICLevel {
diff --git a/linux-x64/clang/include/llvm/Support/CommandLine.h b/linux-x64/clang/include/llvm/Support/CommandLine.h
index a78020f..3cc2c3c 100644
--- a/linux-x64/clang/include/llvm/Support/CommandLine.h
+++ b/linux-x64/clang/include/llvm/Support/CommandLine.h
@@ -66,7 +66,8 @@
bool ParseCommandLineOptions(int argc, const char *const *argv,
StringRef Overview = "",
raw_ostream *Errs = nullptr,
- const char *EnvVar = nullptr);
+ const char *EnvVar = nullptr,
+ bool LongOptionsUseDoubleDash = false);
//===----------------------------------------------------------------------===//
// ParseEnvironmentOptions - Environment variable option processing alternate
@@ -158,23 +159,27 @@
// AlwaysPrefix - Only allow the behavior enabled by the Prefix flag and reject
// the Option=Value form.
//
-// Grouping - With this option enabled, multiple letter options are allowed to
-// bunch together with only a single hyphen for the whole group. This allows
-// emulation of the behavior that ls uses for example: ls -la === ls -l -a
-//
enum FormattingFlags {
NormalFormatting = 0x00, // Nothing special
Positional = 0x01, // Is a positional argument, no '-' required
Prefix = 0x02, // Can this option directly prefix its value?
- AlwaysPrefix = 0x03, // Can this option only directly prefix its value?
- Grouping = 0x04 // Can this option group with other options?
+ AlwaysPrefix = 0x03 // Can this option only directly prefix its value?
};
enum MiscFlags { // Miscellaneous flags to adjust argument
CommaSeparated = 0x01, // Should this cl::list split between commas?
PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args?
- Sink = 0x04 // Should this cl::list eat all unknown options?
+ Sink = 0x04, // Should this cl::list eat all unknown options?
+
+ // Grouping - Can this option group with other options?
+ // If this is enabled, multiple letter options are allowed to bunch together
+ // with only a single hyphen for the whole group. This allows emulation
+ // of the behavior that ls uses for example: ls -la === ls -l -a
+ Grouping = 0x08,
+
+ // Default option
+ DefaultOption = 0x10
};
//===----------------------------------------------------------------------===//
@@ -260,26 +265,27 @@
// Out of line virtual function to provide home for the class.
virtual void anchor();
- int NumOccurrences = 0; // The number of times specified
+ uint16_t NumOccurrences; // The number of times specified
// Occurrences, HiddenFlag, and Formatting are all enum types but to avoid
// problems with signed enums in bitfields.
- unsigned Occurrences : 3; // enum NumOccurrencesFlag
+ uint16_t Occurrences : 3; // enum NumOccurrencesFlag
// not using the enum type for 'Value' because zero is an implementation
// detail representing the non-value
- unsigned Value : 2;
- unsigned HiddenFlag : 2; // enum OptionHidden
- unsigned Formatting : 3; // enum FormattingFlags
- unsigned Misc : 3;
- unsigned Position = 0; // Position of last occurrence of the option
- unsigned AdditionalVals = 0; // Greater than 0 for multi-valued option.
+ uint16_t Value : 2;
+ uint16_t HiddenFlag : 2; // enum OptionHidden
+ uint16_t Formatting : 2; // enum FormattingFlags
+ uint16_t Misc : 5;
+ uint16_t FullyInitialized : 1; // Has addArgument been called?
+ uint16_t Position; // Position of last occurrence of the option
+ uint16_t AdditionalVals; // Greater than 0 for multi-valued option.
public:
StringRef ArgStr; // The argument string itself (ex: "help", "o")
StringRef HelpStr; // The descriptive text message for -help
StringRef ValueStr; // String describing what the value of this option is
- OptionCategory *Category; // The Category this option belongs to
- SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to.
- bool FullyInitialized = false; // Has addArgument been called?
+ SmallVector<OptionCategory *, 1>
+ Categories; // The Categories this option belongs to
+ SmallPtrSet<SubCommand *, 1> Subs; // The subcommands this option belongs to.
inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
return (enum NumOccurrencesFlag)Occurrences;
@@ -305,6 +311,7 @@
bool hasArgStr() const { return !ArgStr.empty(); }
bool isPositional() const { return getFormattingFlag() == cl::Positional; }
bool isSink() const { return getMiscFlags() & cl::Sink; }
+ bool isDefaultOption() const { return getMiscFlags() & cl::DefaultOption; }
bool isConsumeAfter() const {
return getNumOccurrencesFlag() == cl::ConsumeAfter;
@@ -328,14 +335,17 @@
void setFormattingFlag(enum FormattingFlags V) { Formatting = V; }
void setMiscFlag(enum MiscFlags M) { Misc |= M; }
void setPosition(unsigned pos) { Position = pos; }
- void setCategory(OptionCategory &C) { Category = &C; }
+ void addCategory(OptionCategory &C);
void addSubCommand(SubCommand &S) { Subs.insert(&S); }
protected:
explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
enum OptionHidden Hidden)
- : Occurrences(OccurrencesFlag), Value(0), HiddenFlag(Hidden),
- Formatting(NormalFormatting), Misc(0), Category(&GeneralCategory) {}
+ : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0),
+ HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0),
+ FullyInitialized(false), Position(0), AdditionalVals(0) {
+ Categories.push_back(&GeneralCategory);
+ }
inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
@@ -381,7 +391,7 @@
}
inline int getNumOccurrences() const { return NumOccurrences; }
- inline void reset() { NumOccurrences = 0; }
+ void reset();
};
//===----------------------------------------------------------------------===//
@@ -446,7 +456,7 @@
cat(OptionCategory &c) : Category(c) {}
- template <class Opt> void apply(Opt &O) const { O.setCategory(Category); }
+ template <class Opt> void apply(Opt &O) const { O.addCategory(Category); }
};
// sub - Specify the subcommand that this option belongs to.
@@ -822,6 +832,8 @@
public:
basic_parser_impl(Option &) {}
+ virtual ~basic_parser_impl() {}
+
enum ValueExpected getValueExpectedFlagDefault() const {
return ValueRequired;
}
@@ -849,8 +861,6 @@
virtual void anchor();
protected:
- ~basic_parser_impl() = default;
-
// A helper for basic_parser::printOptionDiff.
void printOptionName(const Option &O, size_t GlobalWidth) const;
};
@@ -864,15 +874,12 @@
using OptVal = OptionValue<DataType>;
basic_parser(Option &O) : basic_parser_impl(O) {}
-
-protected:
- ~basic_parser() = default;
};
//--------------------------------------------------
// parser<bool>
//
-template <> class parser<bool> final : public basic_parser<bool> {
+template <> class parser<bool> : public basic_parser<bool> {
public:
parser(Option &O) : basic_parser(O) {}
@@ -899,8 +906,7 @@
//--------------------------------------------------
// parser<boolOrDefault>
-template <>
-class parser<boolOrDefault> final : public basic_parser<boolOrDefault> {
+template <> class parser<boolOrDefault> : public basic_parser<boolOrDefault> {
public:
parser(Option &O) : basic_parser(O) {}
@@ -926,7 +932,7 @@
//--------------------------------------------------
// parser<int>
//
-template <> class parser<int> final : public basic_parser<int> {
+template <> class parser<int> : public basic_parser<int> {
public:
parser(Option &O) : basic_parser(O) {}
@@ -948,7 +954,7 @@
//--------------------------------------------------
// parser<unsigned>
//
-template <> class parser<unsigned> final : public basic_parser<unsigned> {
+template <> class parser<unsigned> : public basic_parser<unsigned> {
public:
parser(Option &O) : basic_parser(O) {}
@@ -968,11 +974,33 @@
extern template class basic_parser<unsigned>;
//--------------------------------------------------
+// parser<unsigned long>
+//
+template <>
+class parser<unsigned long> final : public basic_parser<unsigned long> {
+public:
+ parser(Option &O) : basic_parser(O) {}
+
+ // parse - Return true on error.
+ bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned long &Val);
+
+ // getValueName - Overload in subclass to provide a better default value.
+ StringRef getValueName() const override { return "ulong"; }
+
+ void printOptionDiff(const Option &O, unsigned 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<unsigned long>;
+
+//--------------------------------------------------
// parser<unsigned long long>
//
template <>
-class parser<unsigned long long> final
- : public basic_parser<unsigned long long> {
+class parser<unsigned long long> : public basic_parser<unsigned long long> {
public:
parser(Option &O) : basic_parser(O) {}
@@ -981,7 +1009,7 @@
unsigned long long &Val);
// getValueName - Overload in subclass to provide a better default value.
- StringRef getValueName() const override { return "uint"; }
+ StringRef getValueName() const override { return "ulong"; }
void printOptionDiff(const Option &O, unsigned long long V, OptVal Default,
size_t GlobalWidth) const;
@@ -995,7 +1023,7 @@
//--------------------------------------------------
// parser<double>
//
-template <> class parser<double> final : public basic_parser<double> {
+template <> class parser<double> : public basic_parser<double> {
public:
parser(Option &O) : basic_parser(O) {}
@@ -1017,7 +1045,7 @@
//--------------------------------------------------
// parser<float>
//
-template <> class parser<float> final : public basic_parser<float> {
+template <> class parser<float> : public basic_parser<float> {
public:
parser(Option &O) : basic_parser(O) {}
@@ -1039,7 +1067,7 @@
//--------------------------------------------------
// parser<std::string>
//
-template <> class parser<std::string> final : public basic_parser<std::string> {
+template <> class parser<std::string> : public basic_parser<std::string> {
public:
parser(Option &O) : basic_parser(O) {}
@@ -1064,7 +1092,7 @@
//--------------------------------------------------
// parser<char>
//
-template <> class parser<char> final : public basic_parser<char> {
+template <> class parser<char> : public basic_parser<char> {
public:
parser(Option &O) : basic_parser(O) {}
@@ -1177,7 +1205,11 @@
};
template <> struct applicator<MiscFlags> {
- static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); }
+ static void opt(MiscFlags MF, Option &O) {
+ assert((MF != Grouping || O.ArgStr.size() == 1) &&
+ "cl::Grouping can only apply to single charater Options.");
+ O.setMiscFlag(MF);
+ }
};
// apply method - Apply modifiers to an option in a type safe way.
@@ -1397,6 +1429,8 @@
public:
list_storage() = default;
+ void clear() {}
+
bool setLocation(Option &O, StorageClass &L) {
if (Location)
return O.error("cl::location(x) specified more than once!");
@@ -1448,6 +1482,10 @@
reference operator[](size_type pos) { return Storage[pos]; }
const_reference operator[](size_type pos) const { return Storage[pos]; }
+ void clear() {
+ Storage.clear();
+ }
+
iterator erase(const_iterator pos) { return Storage.erase(pos); }
iterator erase(const_iterator first, const_iterator last) {
return Storage.erase(first, last);
@@ -1525,7 +1563,10 @@
void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override {
}
- void setDefault() override {}
+ void setDefault() override {
+ Positions.clear();
+ list_storage<DataType, StorageClass>::clear();
+ }
void done() {
addArgument();
@@ -1731,7 +1772,10 @@
error("cl::alias must have argument name specified!");
if (!AliasFor)
error("cl::alias must have an cl::aliasopt(option) specified!");
+ if (!Subs.empty())
+ error("cl::alias must not have cl::sub(), aliased option's cl::sub() will be used!");
Subs = AliasFor->Subs;
+ Categories = AliasFor->Categories;
addArgument();
}
diff --git a/linux-x64/clang/include/llvm/Support/Compiler.h b/linux-x64/clang/include/llvm/Support/Compiler.h
index a81488a..3f4f465 100644
--- a/linux-x64/clang/include/llvm/Support/Compiler.h
+++ b/linux-x64/clang/include/llvm/Support/Compiler.h
@@ -254,6 +254,15 @@
#define LLVM_FALLTHROUGH
#endif
+/// LLVM_REQUIRE_CONSTANT_INITIALIZATION - Apply this to globals to ensure that
+/// they are constant initialized.
+#if __has_cpp_attribute(clang::require_constant_initialization)
+#define LLVM_REQUIRE_CONSTANT_INITIALIZATION \
+ [[clang::require_constant_initialization]]
+#else
+#define LLVM_REQUIRE_CONSTANT_INITIALIZATION
+#endif
+
/// LLVM_EXTENSION - Support compilers where we have a keyword to suppress
/// pedantic diagnostics.
#ifdef __GNUC__
diff --git a/linux-x64/clang/include/llvm/Support/Endian.h b/linux-x64/clang/include/llvm/Support/Endian.h
index a0632bb..d8be944 100644
--- a/linux-x64/clang/include/llvm/Support/Endian.h
+++ b/linux-x64/clang/include/llvm/Support/Endian.h
@@ -203,10 +203,14 @@
namespace detail {
-template<typename value_type,
- endianness endian,
- std::size_t alignment>
+template<typename ValueType,
+ endianness Endian,
+ std::size_t Alignment>
struct packed_endian_specific_integral {
+ using value_type = ValueType;
+ static constexpr endianness endian = Endian;
+ static constexpr std::size_t alignment = Alignment;
+
packed_endian_specific_integral() = default;
explicit packed_endian_specific_integral(value_type val) { *this = val; }
@@ -334,6 +338,17 @@
using unaligned_int64_t =
detail::packed_endian_specific_integral<int64_t, native, unaligned>;
+template <typename T>
+using little_t = detail::packed_endian_specific_integral<T, little, unaligned>;
+template <typename T>
+using big_t = detail::packed_endian_specific_integral<T, big, unaligned>;
+
+template <typename T>
+using aligned_little_t =
+ detail::packed_endian_specific_integral<T, little, aligned>;
+template <typename T>
+using aligned_big_t = detail::packed_endian_specific_integral<T, big, aligned>;
+
namespace endian {
template <typename T> inline T read(const void *P, endianness E) {
diff --git a/linux-x64/clang/include/llvm/Support/Error.h b/linux-x64/clang/include/llvm/Support/Error.h
index 23a48ed..299fce7 100644
--- a/linux-x64/clang/include/llvm/Support/Error.h
+++ b/linux-x64/clang/include/llvm/Support/Error.h
@@ -1160,8 +1160,8 @@
/// Create formatted StringError object.
template <typename... Ts>
-Error createStringError(std::error_code EC, char const *Fmt,
- const Ts &... Vals) {
+inline Error createStringError(std::error_code EC, char const *Fmt,
+ const Ts &... Vals) {
std::string Buffer;
raw_string_ostream Stream(Buffer);
Stream << format(Fmt, Vals...);
@@ -1170,6 +1170,12 @@
Error createStringError(std::error_code EC, char const *Msg);
+template <typename... Ts>
+inline Error createStringError(std::errc EC, char const *Fmt,
+ const Ts &... Vals) {
+ return createStringError(std::make_error_code(EC), Fmt, Vals...);
+}
+
/// This class wraps a filename and another Error.
///
/// In some cases, an error needs to live along a 'source' name, in order to
@@ -1177,11 +1183,14 @@
class FileError final : public ErrorInfo<FileError> {
friend Error createFileError(const Twine &, Error);
+ friend Error createFileError(const Twine &, size_t, Error);
public:
void log(raw_ostream &OS) const override {
assert(Err && !FileName.empty() && "Trying to log after takeError().");
OS << "'" << FileName << "': ";
+ if (Line.hasValue())
+ OS << "line " << Line.getValue() << ": ";
Err->log(OS);
}
@@ -1193,26 +1202,36 @@
static char ID;
private:
- FileError(const Twine &F, std::unique_ptr<ErrorInfoBase> E) {
+ FileError(const Twine &F, Optional<size_t> LineNum,
+ std::unique_ptr<ErrorInfoBase> E) {
assert(E && "Cannot create FileError from Error success value.");
assert(!F.isTriviallyEmpty() &&
"The file name provided to FileError must not be empty.");
FileName = F.str();
Err = std::move(E);
+ Line = std::move(LineNum);
}
- static Error build(const Twine &F, Error E) {
- return Error(std::unique_ptr<FileError>(new FileError(F, E.takePayload())));
+ static Error build(const Twine &F, Optional<size_t> Line, Error E) {
+ return Error(
+ std::unique_ptr<FileError>(new FileError(F, Line, E.takePayload())));
}
std::string FileName;
+ Optional<size_t> Line;
std::unique_ptr<ErrorInfoBase> Err;
};
/// Concatenate a source file path and/or name with an Error. The resulting
/// Error is unchecked.
inline Error createFileError(const Twine &F, Error E) {
- return FileError::build(F, std::move(E));
+ return FileError::build(F, Optional<size_t>(), std::move(E));
+}
+
+/// Concatenate a source file path and/or name with line number and an Error.
+/// The resulting Error is unchecked.
+inline Error createFileError(const Twine &F, size_t Line, Error E) {
+ return FileError::build(F, Optional<size_t>(Line), std::move(E));
}
/// Concatenate a source file path and/or name with a std::error_code
@@ -1221,6 +1240,12 @@
return createFileError(F, errorCodeToError(EC));
}
+/// Concatenate a source file path and/or name with line number and
+/// std::error_code to form an Error object.
+inline Error createFileError(const Twine &F, size_t Line, std::error_code EC) {
+ return createFileError(F, Line, errorCodeToError(EC));
+}
+
Error createFileError(const Twine &F, ErrorSuccess) = delete;
/// Helper for check-and-exit error handling.
diff --git a/linux-x64/clang/include/llvm/Support/FileCheck.h b/linux-x64/clang/include/llvm/Support/FileCheck.h
index 01e9362..b3a8433 100644
--- a/linux-x64/clang/include/llvm/Support/FileCheck.h
+++ b/linux-x64/clang/include/llvm/Support/FileCheck.h
@@ -36,9 +36,174 @@
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.
+// Pattern handling code.
//===----------------------------------------------------------------------===//
namespace Check {
@@ -77,12 +242,142 @@
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;
@@ -94,43 +389,132 @@
/// a fixed string to match.
std::string RegExStr;
- /// Entries in this vector map to uses of a variable in the pattern, e.g.
- /// "foo[[bar]]baz". In this case, the RegExStr will contain "foobaz" and
- /// we'll get an entry in this vector that tells us to insert the value of
- /// bar at offset 3.
- std::vector<std::pair<StringRef, unsigned>> VariableUses;
+ /// 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 definitions of variables to their parenthesized capture numbers.
+ /// 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", VariableDefs will map "bar" to
- /// 1.
+ /// 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;
- /// Contains the number of line this pattern is in.
- unsigned LineNumber;
+ /// 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:
- explicit FileCheckPattern(Check::FileCheckType Ty)
- : CheckTy(Ty) {}
+ FileCheckPattern(Check::FileCheckType Ty, FileCheckPatternContext *Context,
+ size_t Line)
+ : Context(Context), CheckTy(Ty), LineNumber(Line) {}
- /// Returns the location in source code.
+ /// \returns the location in source code.
SMLoc getLoc() const { return PatternLoc; }
- bool ParsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
- unsigned LineNumber, const FileCheckRequest &Req);
- size_t Match(StringRef Buffer, size_t &MatchLen,
- StringMap<StringRef> &VariableTable) const;
- void PrintVariableUses(const SourceMgr &SM, StringRef Buffer,
- const StringMap<StringRef> &VariableTable,
- SMRange MatchRange = None) const;
- void PrintFuzzyMatch(const SourceMgr &SM, StringRef Buffer,
- const StringMap<StringRef> &VariableTable,
+ /// \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 !(VariableUses.empty() && VariableDefs.empty());
+ return !(Substitutions.empty() && VariableDefs.empty());
}
Check::FileCheckType getCheckTy() const { return CheckTy; }
@@ -140,11 +524,28 @@
private:
bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
void AddBackrefToRegEx(unsigned BackrefNum);
- unsigned
- ComputeMatchDistance(StringRef Buffer,
- const StringMap<StringRef> &VariableTable) const;
- bool EvaluateExpression(StringRef Expr, std::string &Value) const;
+ /// 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;
};
//===----------------------------------------------------------------------===//
@@ -222,20 +623,27 @@
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, StringMap<StringRef> &VariableTable,
- FileCheckRequest &Req, std::vector<FileCheckDiag> *Diags) const;
+ 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,
- StringMap<StringRef> &VariableTable,
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,
- StringMap<StringRef> &VariableTable,
const FileCheckRequest &Req,
std::vector<FileCheckDiag> *Diags) const;
};
@@ -244,6 +652,7 @@
/// use information from the request.
class FileCheck {
FileCheckRequest Req;
+ FileCheckPatternContext PatternContext;
public:
FileCheck(FileCheckRequest Req) : Req(Req) {}
@@ -255,24 +664,27 @@
// library.
Regex buildCheckPrefixRegex();
- /// Read the check file, which specifies the sequence of expected strings.
+ /// 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.
///
- /// The strings are added to the CheckStrings vector. Returns true in case of
- /// an error, false otherwise.
+ /// 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();
- /// Canonicalize whitespaces in the file. Line endings are replaced with
+ /// Canonicalizes whitespaces in the file. Line endings are replaced with
/// UNIX-style '\n'.
StringRef CanonicalizeFile(MemoryBuffer &MB,
SmallVectorImpl<char> &OutputBuffer);
- /// Check the input to FileCheck provided in the \p Buffer against the \p
- /// CheckStrings read from the check file.
+ /// 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.
+ /// \returns false if the input fails to satisfy the checks.
bool CheckInput(SourceMgr &SM, StringRef Buffer,
ArrayRef<FileCheckString> CheckStrings,
std::vector<FileCheckDiag> *Diags = nullptr);
diff --git a/linux-x64/clang/include/llvm/Support/FileSystem.h b/linux-x64/clang/include/llvm/Support/FileSystem.h
index 156250f..3f2c939 100644
--- a/linux-x64/clang/include/llvm/Support/FileSystem.h
+++ b/linux-x64/clang/include/llvm/Support/FileSystem.h
@@ -648,16 +648,32 @@
/// A version for when a file descriptor is already available.
std::error_code status(int FD, file_status &Result);
+#ifdef _WIN32
+/// A version for when a file descriptor is already available.
+std::error_code status(file_t FD, file_status &Result);
+#endif
+
+/// Get file creation mode mask of the process.
+///
+/// @returns Mask reported by umask(2)
+/// @note There is no umask on Windows. This function returns 0 always
+/// on Windows. This function does not return an error_code because
+/// umask(2) never fails. It is not thread safe.
+unsigned getUmask();
+
/// Set file permissions.
///
/// @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);
+std::error_code setPermissions(const Twine &Path, perms Permissions,
+ bool RespectUmask = false);
/// Get file permissions.
///
@@ -764,11 +780,32 @@
OF_UpdateAtime = 16,
};
+/// Create a potentially unique file name but does not create it.
+///
+/// Generates a unique path suitable for a temporary file but does not
+/// open or create the file. The name is based on \a Model with '%'
+/// replaced by a random char in [0-9a-f]. If \a MakeAbsolute is true
+/// then the system's temp directory is prepended first. If \a MakeAbsolute
+/// is false the current directory will be used instead.
+///
+/// This function does not check if the file exists. If you want to be sure
+/// that the file does not yet exist, you should use use enough '%' characters
+/// in your model to ensure this. Each '%' gives 4-bits of entropy so you can
+/// use 32 of them to get 128 bits of entropy.
+///
+/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s
+///
+/// @param Model Name to base unique path off of.
+/// @param ResultPath Set to the file's path.
+/// @param MakeAbsolute Whether to use the system temp directory.
+void createUniquePath(const Twine &Model, SmallVectorImpl<char> &ResultPath,
+ bool MakeAbsolute);
+
/// Create a uniquely named file.
///
/// Generates a unique path suitable for a temporary file and then opens it as a
-/// file. The name is based on \a model with '%' replaced by a random char in
-/// [0-9a-f]. If \a model is not an absolute path, the temporary file will be
+/// file. The name is based on \a Model with '%' replaced by a random char in
+/// [0-9a-f]. If \a Model is not an absolute path, the temporary file will be
/// created in the current directory.
///
/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s
@@ -931,6 +968,51 @@
FileAccess Access, OpenFlags Flags,
unsigned Mode = 0666);
+/// Converts from a Posix file descriptor number to a native file handle.
+/// On Windows, this retreives the underlying handle. On non-Windows, this is a
+/// no-op.
+file_t convertFDToNativeFile(int FD);
+
+#ifndef _WIN32
+inline file_t convertFDToNativeFile(int FD) { return FD; }
+#endif
+
+/// Return an open handle to standard in. On Unix, this is typically FD 0.
+/// Returns kInvalidFile when the stream is closed.
+file_t getStdinHandle();
+
+/// Return an open handle to standard out. On Unix, this is typically FD 1.
+/// Returns kInvalidFile when the stream is closed.
+file_t getStdoutHandle();
+
+/// Return an open handle to standard error. On Unix, this is typically FD 2.
+/// 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.
+///
+/// @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);
+
+/// 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.
+///
+/// @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);
+
/// @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
/// is created.
@@ -1050,11 +1132,15 @@
SmallVectorImpl<char> *RealPath = nullptr);
/// @brief Close the file object. This should be used instead of ::close for
-/// portability.
+/// portability. On error, the caller should assume the file is closed, as is
+/// the case for Process::SafelyCloseFileDescriptor
///
/// @param F On input, this is the file to close. On output, the file is
/// set to kInvalidFile.
-void closeFile(file_t &F);
+///
+/// @returns An error code if closing the file failed. Typically, an error here
+/// means that the filesystem may have failed to perform some buffered writes.
+std::error_code closeFile(file_t &F);
std::error_code getUniqueID(const Twine Path, UniqueID &Result);
@@ -1084,21 +1170,19 @@
size_t Size;
void *Mapping;
#ifdef _WIN32
- void *FileHandle;
+ sys::fs::file_t FileHandle;
#endif
mapmode Mode;
- std::error_code init(int FD, uint64_t Offset, mapmode Mode);
+ std::error_code init(sys::fs::file_t FD, uint64_t Offset, mapmode Mode);
public:
mapped_file_region() = delete;
mapped_file_region(mapped_file_region&) = delete;
mapped_file_region &operator =(mapped_file_region&) = delete;
- /// \param fd An open file descriptor to map. mapped_file_region takes
- /// ownership if closefd is true. It must have been opended in the correct
- /// mode.
- mapped_file_region(int fd, mapmode mode, size_t length, uint64_t offset,
+ /// \param fd An open file descriptor to map. Does not take ownership of fd.
+ mapped_file_region(sys::fs::file_t fd, mapmode mode, size_t length, uint64_t offset,
std::error_code &ec);
~mapped_file_region();
diff --git a/linux-x64/clang/include/llvm/Support/GenericDomTree.h b/linux-x64/clang/include/llvm/Support/GenericDomTree.h
index 53a613e..9962080 100644
--- a/linux-x64/clang/include/llvm/Support/GenericDomTree.h
+++ b/linux-x64/clang/include/llvm/Support/GenericDomTree.h
@@ -669,14 +669,12 @@
// The postdom tree can have a null root if there are no returns.
if (getRootNode()) PrintDomTree<NodeT>(getRootNode(), O, 1);
- if (IsPostDominator) {
- O << "Roots: ";
- for (const NodePtr Block : Roots) {
- Block->printAsOperand(O, false);
- O << " ";
- }
- O << "\n";
+ O << "Roots: ";
+ for (const NodePtr Block : Roots) {
+ Block->printAsOperand(O, false);
+ O << " ";
}
+ O << "\n";
}
public:
diff --git a/linux-x64/clang/include/llvm/Support/GenericDomTreeConstruction.h b/linux-x64/clang/include/llvm/Support/GenericDomTreeConstruction.h
index 69cc721..ccceba8 100644
--- a/linux-x64/clang/include/llvm/Support/GenericDomTreeConstruction.h
+++ b/linux-x64/clang/include/llvm/Support/GenericDomTreeConstruction.h
@@ -15,9 +15,12 @@
/// Loukas Georgiadis, Princeton University, November 2005, pp. 21-23:
/// ftp://ftp.cs.princeton.edu/reports/2005/737.pdf
///
-/// This implements the O(n*log(n)) versions of EVAL and LINK, because it turns
-/// out that the theoretically slower O(n*log(n)) implementation is actually
-/// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs.
+/// Semi-NCA algorithm runs in O(n^2) worst-case time but usually slightly
+/// faster than Simple Lengauer-Tarjan in practice.
+///
+/// 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.
///
/// The file uses the Depth Based Search algorithm to perform incremental
/// updates (insertion and deletions). The implemented algorithm is based on
@@ -254,42 +257,47 @@
return LastNum;
}
- NodePtr eval(NodePtr VIn, unsigned LastLinked) {
- auto &VInInfo = NodeToInfo[VIn];
- if (VInInfo.DFSNum < LastLinked)
- return VIn;
+ // V is a predecessor of W. eval() returns V if V < W, otherwise the minimum
+ // of sdom(U), where U > W and there is a virtual forest path from U to V. The
+ // virtual forest consists of linked edges of processed vertices.
+ //
+ // We can follow Parent pointers (virtual forest edges) to determine the
+ // ancestor U with minimum sdom(U). But it is slow and thus we employ the path
+ // compression technique to speed up to O(m*log(n)). Theoretically the virtual
+ // forest can be organized as balanced trees to achieve almost linear
+ // O(m*alpha(m,n)) running time. But it requires two auxiliary arrays (Size
+ // and Child) and is unlikely to be faster than the simple implementation.
+ //
+ // For each vertex V, its Label points to the vertex with the minimal sdom(U)
+ // (Semi) in its path from V (included) to NodeToInfo[V].Parent (excluded).
+ NodePtr eval(NodePtr V, unsigned LastLinked,
+ SmallVectorImpl<InfoRec *> &Stack) {
+ InfoRec *VInfo = &NodeToInfo[V];
+ if (VInfo->Parent < LastLinked)
+ return VInfo->Label;
- SmallVector<NodePtr, 32> Work;
- SmallPtrSet<NodePtr, 32> Visited;
+ // Store ancestors except the last (root of a virtual tree) into a stack.
+ assert(Stack.empty());
+ do {
+ Stack.push_back(VInfo);
+ VInfo = &NodeToInfo[NumToNode[VInfo->Parent]];
+ } while (VInfo->Parent >= LastLinked);
- if (VInInfo.Parent >= LastLinked)
- Work.push_back(VIn);
-
- while (!Work.empty()) {
- NodePtr V = Work.back();
- auto &VInfo = NodeToInfo[V];
- NodePtr VAncestor = NumToNode[VInfo.Parent];
-
- // Process Ancestor first
- if (Visited.insert(VAncestor).second && VInfo.Parent >= LastLinked) {
- Work.push_back(VAncestor);
- continue;
- }
- Work.pop_back();
-
- // Update VInfo based on Ancestor info
- if (VInfo.Parent < LastLinked)
- continue;
-
- auto &VAInfo = NodeToInfo[VAncestor];
- NodePtr VAncestorLabel = VAInfo.Label;
- NodePtr VLabel = VInfo.Label;
- if (NodeToInfo[VAncestorLabel].Semi < NodeToInfo[VLabel].Semi)
- VInfo.Label = VAncestorLabel;
- VInfo.Parent = VAInfo.Parent;
- }
-
- return VInInfo.Label;
+ // Path compression. Point each vertex's Parent to the root and update its
+ // Label if any of its ancestors (PInfo->Label) has a smaller Semi.
+ const InfoRec *PInfo = VInfo;
+ const InfoRec *PLabelInfo = &NodeToInfo[PInfo->Label];
+ do {
+ VInfo = Stack.pop_back_val();
+ VInfo->Parent = PInfo->Parent;
+ const InfoRec *VLabelInfo = &NodeToInfo[VInfo->Label];
+ if (PLabelInfo->Semi < VLabelInfo->Semi)
+ VInfo->Label = PInfo->Label;
+ else
+ PLabelInfo = VLabelInfo;
+ PInfo = VInfo;
+ } while (!Stack.empty());
+ return VInfo->Label;
}
// This function requires DFS to be run before calling it.
@@ -303,6 +311,7 @@
}
// Step #1: Calculate the semidominators of all vertices.
+ SmallVector<InfoRec *, 32> EvalStack;
for (unsigned i = NextDFSNum - 1; i >= 2; --i) {
NodePtr W = NumToNode[i];
auto &WInfo = NodeToInfo[W];
@@ -318,7 +327,7 @@
if (TN && TN->getLevel() < MinLevel)
continue;
- unsigned SemiU = NodeToInfo[eval(N, i + 1)].Semi;
+ unsigned SemiU = NodeToInfo[eval(N, i + 1, EvalStack)].Semi;
if (SemiU < WInfo.Semi) WInfo.Semi = SemiU;
}
}
@@ -619,21 +628,22 @@
// Helper struct used during edge insertions.
struct InsertionInfo {
- using BucketElementTy = std::pair<unsigned, TreeNodePtr>;
- struct DecreasingLevel {
- bool operator()(const BucketElementTy &First,
- const BucketElementTy &Second) const {
- return First.first > Second.first;
+ struct Compare {
+ bool operator()(TreeNodePtr LHS, TreeNodePtr RHS) const {
+ return LHS->getLevel() < RHS->getLevel();
}
};
- std::priority_queue<BucketElementTy, SmallVector<BucketElementTy, 8>,
- DecreasingLevel>
- Bucket; // Queue of tree nodes sorted by level in descending order.
- SmallDenseSet<TreeNodePtr, 8> Affected;
- SmallDenseMap<TreeNodePtr, unsigned, 8> Visited;
- SmallVector<TreeNodePtr, 8> AffectedQueue;
- SmallVector<TreeNodePtr, 8> VisitedNotAffectedQueue;
+ // Bucket queue of tree nodes ordered by descending level. For simplicity,
+ // we use a priority_queue here.
+ std::priority_queue<TreeNodePtr, SmallVector<TreeNodePtr, 8>,
+ Compare>
+ Bucket;
+ SmallDenseSet<TreeNodePtr, 8> Visited;
+ SmallVector<TreeNodePtr, 8> Affected;
+#ifndef NDEBUG
+ SmallVector<TreeNodePtr, 8> VisitedUnaffected;
+#endif
};
static void InsertEdge(DomTreeT &DT, const BatchUpdatePtr BUI,
@@ -688,6 +698,17 @@
return true;
}
+ static bool isPermutation(const SmallVectorImpl<NodePtr> &A,
+ const SmallVectorImpl<NodePtr> &B) {
+ if (A.size() != B.size())
+ return false;
+ SmallPtrSet<NodePtr, 4> Set(A.begin(), A.end());
+ for (NodePtr N : B)
+ if (Set.count(N) == 0)
+ return false;
+ return true;
+ }
+
// Updates the set of roots after insertion or deletion. This ensures that
// roots are the same when after a series of updates and when the tree would
// be built from scratch.
@@ -701,9 +722,8 @@
return;
// Recalculate the set of roots.
- auto Roots = FindRoots(DT, BUI);
- if (DT.Roots.size() != Roots.size() ||
- !std::is_permutation(DT.Roots.begin(), DT.Roots.end(), Roots.begin())) {
+ RootsT Roots = FindRoots(DT, BUI);
+ if (!isPermutation(DT.Roots, Roots)) {
// The roots chosen in the CFG have changed. This is because the
// incremental algorithm does not really know or use the set of roots and
// can make a different (implicit) decision about which node within an
@@ -714,7 +734,6 @@
// 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.
CalculateFromScratch(DT, BUI);
- return;
}
}
@@ -736,130 +755,115 @@
assert(NCD);
LLVM_DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n");
- const TreeNodePtr ToIDom = To->getIDom();
+ const unsigned NCDLevel = NCD->getLevel();
- // Nothing affected -- NCA property holds.
- // (Based on the lemma 2.5 from the second paper.)
- if (NCD == To || NCD == ToIDom) return;
+ // 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)
+ //
+ // 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).
- // Identify and collect affected nodes.
+ // To is in the path, so depth(NCD)+1 < depth(v) <= depth(To). Nothing
+ // affected if this does not hold.
+ if (NCDLevel + 1 >= To->getLevel())
+ return;
+
InsertionInfo II;
- LLVM_DEBUG(dbgs() << "Marking " << BlockNamePrinter(To)
- << " as affected\n");
- II.Affected.insert(To);
- const unsigned ToLevel = To->getLevel();
- LLVM_DEBUG(dbgs() << "Putting " << BlockNamePrinter(To)
- << " into a Bucket\n");
- II.Bucket.push({ToLevel, To});
+ SmallVector<TreeNodePtr, 8> UnaffectedOnCurrentLevel;
+ II.Bucket.push(To);
+ II.Visited.insert(To);
while (!II.Bucket.empty()) {
- const TreeNodePtr CurrentNode = II.Bucket.top().second;
- const unsigned CurrentLevel = CurrentNode->getLevel();
+ TreeNodePtr TN = II.Bucket.top();
II.Bucket.pop();
- LLVM_DEBUG(dbgs() << "\tAdding to Visited and AffectedQueue: "
- << BlockNamePrinter(CurrentNode) << "\n");
+ II.Affected.push_back(TN);
- II.Visited.insert({CurrentNode, CurrentLevel});
- II.AffectedQueue.push_back(CurrentNode);
+ const unsigned CurrentLevel = TN->getLevel();
+ LLVM_DEBUG(dbgs() << "Mark " << BlockNamePrinter(TN) <<
+ "as affected, CurrentLevel " << CurrentLevel << "\n");
- // Discover and collect affected successors of the current node.
- VisitInsertion(DT, BUI, CurrentNode, CurrentLevel, NCD, II);
+ assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!");
+
+ while (true) {
+ // Unlike regular Dijkstra, we have an inner loop to expand more
+ // vertices. The first iteration is for the (affected) vertex popped
+ // from II.Bucket and the rest are for vertices in
+ // UnaffectedOnCurrentLevel, which may eventually expand to affected
+ // vertices.
+ //
+ // 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)) {
+ const TreeNodePtr SuccTN = DT.getNode(Succ);
+ assert(SuccTN &&
+ "Unreachable successor found at reachable insertion");
+ const unsigned SuccLevel = SuccTN->getLevel();
+
+ LLVM_DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ)
+ << ", level = " << SuccLevel << "\n");
+
+ // There is an optimal path from `To` to Succ with the minimum depth
+ // being min(CurrentLevel, SuccLevel).
+ //
+ // If depth(NCD)+1 < depth(Succ) is not satisfied, Succ is unaffected
+ // and no affected vertex may be reached by a path passing through it.
+ // Stop here. Also, Succ may be visited by other predecessors but the
+ // first visit has the optimal path. Stop if Succ has been visited.
+ if (SuccLevel <= NCDLevel + 1 || !II.Visited.insert(SuccTN).second)
+ continue;
+
+ if (SuccLevel > CurrentLevel) {
+ // Succ is unaffected but it may (transitively) expand to affected
+ // vertices. Store it in UnaffectedOnCurrentLevel.
+ LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected "
+ << BlockNamePrinter(Succ) << "\n");
+ UnaffectedOnCurrentLevel.push_back(SuccTN);
+#ifndef NDEBUG
+ II.VisitedUnaffected.push_back(SuccTN);
+#endif
+ } else {
+ // The condition is satisfied (Succ is affected). Add Succ to the
+ // bucket queue.
+ LLVM_DEBUG(dbgs() << "\t\tAdd " << BlockNamePrinter(Succ)
+ << " to a Bucket\n");
+ II.Bucket.push(SuccTN);
+ }
+ }
+
+ if (UnaffectedOnCurrentLevel.empty())
+ break;
+ TN = UnaffectedOnCurrentLevel.pop_back_val();
+ LLVM_DEBUG(dbgs() << " Next: " << BlockNamePrinter(TN) << "\n");
+ }
}
// Finish by updating immediate dominators and levels.
UpdateInsertion(DT, BUI, NCD, II);
}
- // Visits an affected node and collect its affected successors.
- static void VisitInsertion(DomTreeT &DT, const BatchUpdatePtr BUI,
- const TreeNodePtr TN, const unsigned RootLevel,
- const TreeNodePtr NCD, InsertionInfo &II) {
- const unsigned NCDLevel = NCD->getLevel();
- LLVM_DEBUG(dbgs() << "Visiting " << BlockNamePrinter(TN) << ", RootLevel "
- << RootLevel << "\n");
-
- SmallVector<TreeNodePtr, 8> Stack = {TN};
- assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!");
-
- SmallPtrSet<TreeNodePtr, 8> Processed;
-
- do {
- TreeNodePtr Next = Stack.pop_back_val();
- LLVM_DEBUG(dbgs() << " Next: " << BlockNamePrinter(Next) << "\n");
-
- for (const NodePtr Succ :
- ChildrenGetter<IsPostDom>::Get(Next->getBlock(), BUI)) {
- const TreeNodePtr SuccTN = DT.getNode(Succ);
- assert(SuccTN && "Unreachable successor found at reachable insertion");
- const unsigned SuccLevel = SuccTN->getLevel();
-
- LLVM_DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ)
- << ", level = " << SuccLevel << "\n");
-
- // Do not process the same node multiple times.
- if (Processed.count(Next) > 0)
- continue;
-
- // Succ dominated by subtree From -- not affected.
- // (Based on the lemma 2.5 from the second paper.)
- if (SuccLevel > RootLevel) {
- LLVM_DEBUG(dbgs() << "\t\tDominated by subtree From\n");
- if (II.Visited.count(SuccTN) != 0) {
- LLVM_DEBUG(dbgs() << "\t\t\talready visited at level "
- << II.Visited[SuccTN] << "\n\t\t\tcurrent level "
- << RootLevel << ")\n");
-
- // A node can be necessary to visit again if we see it again at
- // a lower level than before.
- if (II.Visited[SuccTN] >= RootLevel)
- continue;
- }
-
- LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected "
- << BlockNamePrinter(Succ) << "\n");
- II.Visited.insert({SuccTN, RootLevel});
- II.VisitedNotAffectedQueue.push_back(SuccTN);
- Stack.push_back(SuccTN);
- } else if ((SuccLevel > NCDLevel + 1) &&
- II.Affected.count(SuccTN) == 0) {
- LLVM_DEBUG(dbgs() << "\t\tMarking affected and adding "
- << BlockNamePrinter(Succ) << " to a Bucket\n");
- II.Affected.insert(SuccTN);
- II.Bucket.push({SuccLevel, SuccTN});
- }
- }
-
- Processed.insert(Next);
- } while (!Stack.empty());
- }
-
// Updates immediate dominators and levels after insertion.
static void UpdateInsertion(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr NCD, InsertionInfo &II) {
LLVM_DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n");
- for (const TreeNodePtr TN : II.AffectedQueue) {
+ for (const TreeNodePtr TN : II.Affected) {
LLVM_DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN)
<< ") = " << BlockNamePrinter(NCD) << "\n");
TN->setIDom(NCD);
}
- UpdateLevelsAfterInsertion(II);
+#ifndef NDEBUG
+ for (const TreeNodePtr TN : II.VisitedUnaffected)
+ assert(TN->getLevel() == TN->getIDom()->getLevel() + 1 &&
+ "TN should have been updated by an affected ancestor");
+#endif
+
if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI);
}
- static void UpdateLevelsAfterInsertion(InsertionInfo &II) {
- LLVM_DEBUG(
- dbgs() << "Updating levels for visited but not affected nodes\n");
-
- for (const TreeNodePtr TN : II.VisitedNotAffectedQueue) {
- LLVM_DEBUG(dbgs() << "\tlevel(" << BlockNamePrinter(TN) << ") = ("
- << BlockNamePrinter(TN->getIDom()) << ") "
- << TN->getIDom()->getLevel() << " + 1\n");
- TN->UpdateLevel();
- }
- }
-
// Handles insertion to previously unreachable nodes.
static void InsertUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI,
const TreeNodePtr From, const NodePtr To) {
@@ -1181,6 +1185,10 @@
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)) {
@@ -1189,6 +1197,7 @@
dbgs() << "\n";
});
LLVM_DEBUG(dbgs() << "\n");
+#endif
// Recalculate the DominatorTree when the number of updates
// exceeds a threshold, which usually makes direct updating slower than
@@ -1214,8 +1223,13 @@
static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI) {
assert(!BUI.Updates.empty() && "No updates to apply!");
UpdateT CurrentUpdate = BUI.Updates.pop_back_val();
+#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() << "Applying update: ");
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
@@ -1269,9 +1283,7 @@
}
RootsT ComputedRoots = FindRoots(DT, nullptr);
- if (DT.Roots.size() != ComputedRoots.size() ||
- !std::is_permutation(DT.Roots.begin(), DT.Roots.end(),
- ComputedRoots.begin())) {
+ if (!isPermutation(DT.Roots, ComputedRoots)) {
errs() << "Tree has different roots than freshly computed ones!\n";
errs() << "\tPDT roots: ";
for (const NodePtr N : DT.Roots) errs() << BlockNamePrinter(N) << ", ";
diff --git a/linux-x64/clang/include/llvm/Support/GenericIteratedDominanceFrontier.h b/linux-x64/clang/include/llvm/Support/GenericIteratedDominanceFrontier.h
new file mode 100644
index 0000000..fcd2133
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/GenericIteratedDominanceFrontier.h
@@ -0,0 +1,210 @@
+//===- IteratedDominanceFrontier.h - Calculate IDF --------------*- 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
+/// Compute iterated dominance frontiers using a linear time algorithm.
+///
+/// The algorithm used here is based on:
+///
+/// Sreedhar and Gao. A linear time algorithm for placing phi-nodes.
+/// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of
+/// Programming Languages
+/// POPL '95. ACM, New York, NY, 62-73.
+///
+/// It has been modified to not explicitly use the DJ graph data structure and
+/// to directly compute pruned SSA using per-variable liveness information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_GENERIC_IDF_H
+#define LLVM_SUPPORT_GENERIC_IDF_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/GenericDomTree.h"
+#include <queue>
+
+namespace llvm {
+
+namespace IDFCalculatorDetail {
+
+/// Generic utility class used for getting the children of a basic block.
+/// May be specialized if, for example, one wouldn't like to return nullpointer
+/// successors.
+template <class NodeTy, bool IsPostDom> struct ChildrenGetterTy {
+ using NodeRef = typename GraphTraits<NodeTy>::NodeRef;
+ using ChildrenTy = SmallVector<NodeRef, 8>;
+
+ ChildrenTy get(const NodeRef &N);
+};
+
+} // end of namespace IDFCalculatorDetail
+
+/// Determine the iterated dominance frontier, given a set of defining
+/// blocks, and optionally, a set of live-in blocks.
+///
+/// In turn, the results can be used to place phi nodes.
+///
+/// This algorithm is a linear time computation of Iterated Dominance Frontiers,
+/// pruned using the live-in set.
+/// By default, liveness is not used to prune the IDF computation.
+/// The template parameters should be of a CFG block type.
+template <class NodeTy, bool IsPostDom> class IDFCalculatorBase {
+public:
+ using OrderedNodeTy =
+ typename std::conditional<IsPostDom, Inverse<NodeTy *>, NodeTy *>::type;
+ using ChildrenGetterTy =
+ IDFCalculatorDetail::ChildrenGetterTy<NodeTy, IsPostDom>;
+
+ IDFCalculatorBase(DominatorTreeBase<NodeTy, IsPostDom> &DT) : DT(DT) {}
+
+ IDFCalculatorBase(DominatorTreeBase<NodeTy, IsPostDom> &DT,
+ const ChildrenGetterTy &C)
+ : DT(DT), ChildrenGetter(C) {}
+
+ /// Give the IDF calculator the set of blocks in which the value is
+ /// defined. This is equivalent to the set of starting blocks it should be
+ /// calculating the IDF for (though later gets pruned based on liveness).
+ ///
+ /// Note: This set *must* live for the entire lifetime of the IDF calculator.
+ void setDefiningBlocks(const SmallPtrSetImpl<NodeTy *> &Blocks) {
+ DefBlocks = &Blocks;
+ }
+
+ /// Give the IDF calculator the set of blocks in which the value is
+ /// live on entry to the block. This is used to prune the IDF calculation to
+ /// not include blocks where any phi insertion would be dead.
+ ///
+ /// Note: This set *must* live for the entire lifetime of the IDF calculator.
+ void setLiveInBlocks(const SmallPtrSetImpl<NodeTy *> &Blocks) {
+ LiveInBlocks = &Blocks;
+ useLiveIn = true;
+ }
+
+ /// Reset the live-in block set to be empty, and tell the IDF
+ /// calculator to not use liveness anymore.
+ void resetLiveInBlocks() {
+ LiveInBlocks = nullptr;
+ useLiveIn = false;
+ }
+
+ /// Calculate iterated dominance frontiers
+ ///
+ /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in
+ /// the file-level comment. It performs DF->IDF pruning using the live-in
+ /// set, to avoid computing the IDF for blocks where an inserted PHI node
+ /// would be dead.
+ void calculate(SmallVectorImpl<NodeTy *> &IDFBlocks);
+
+private:
+ DominatorTreeBase<NodeTy, IsPostDom> &DT;
+ ChildrenGetterTy ChildrenGetter;
+ bool useLiveIn = false;
+ const SmallPtrSetImpl<NodeTy *> *LiveInBlocks;
+ const SmallPtrSetImpl<NodeTy *> *DefBlocks;
+};
+
+//===----------------------------------------------------------------------===//
+// Implementation.
+//===----------------------------------------------------------------------===//
+
+namespace IDFCalculatorDetail {
+
+template <class NodeTy, bool IsPostDom>
+typename ChildrenGetterTy<NodeTy, IsPostDom>::ChildrenTy
+ChildrenGetterTy<NodeTy, IsPostDom>::get(
+ const ChildrenGetterTy<NodeTy, IsPostDom>::NodeRef &N) {
+ using OrderedNodeTy =
+ typename IDFCalculatorBase<NodeTy, IsPostDom>::OrderedNodeTy;
+
+ auto Children = children<OrderedNodeTy>(N);
+ return {Children.begin(), Children.end()};
+}
+
+} // end of namespace IDFCalculatorDetail
+
+template <class NodeTy, bool IsPostDom>
+void IDFCalculatorBase<NodeTy, IsPostDom>::calculate(
+ SmallVectorImpl<NodeTy *> &PHIBlocks) {
+ // 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
+ // deterministic way.
+ using DomTreeNodePair =
+ std::pair<DomTreeNodeBase<NodeTy> *, std::pair<unsigned, unsigned>>;
+ using IDFPriorityQueue =
+ std::priority_queue<DomTreeNodePair, SmallVector<DomTreeNodePair, 32>,
+ less_second>;
+
+ IDFPriorityQueue PQ;
+
+ 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;
+
+ while (!PQ.empty()) {
+ DomTreeNodePair RootPair = PQ.top();
+ PQ.pop();
+ DomTreeNodeBase<NodeTy> *Root = RootPair.first;
+ unsigned RootLevel = RootPair.second.first;
+
+ // Walk all dominator tree children of Root, inspecting their CFG edges with
+ // targets elsewhere on the dominator tree. Only targets whose level is at
+ // most Root's level are added to the iterated dominance frontier of the
+ // definition set.
+
+ Worklist.clear();
+ Worklist.push_back(Root);
+ VisitedWorklist.insert(Root);
+
+ while (!Worklist.empty()) {
+ DomTreeNodeBase<NodeTy> *Node = Worklist.pop_back_val();
+ NodeTy *BB = Node->getBlock();
+ // Succ is the successor in the direction we are calculating IDF, so it is
+ // successor for IDF, and predecessor for Reverse IDF.
+ auto DoWork = [&](NodeTy *Succ) {
+ DomTreeNodeBase<NodeTy> *SuccNode = DT.getNode(Succ);
+
+ const unsigned SuccLevel = SuccNode->getLevel();
+ if (SuccLevel > RootLevel)
+ return;
+
+ if (!VisitedPQ.insert(SuccNode).second)
+ return;
+
+ NodeTy *SuccBB = SuccNode->getBlock();
+ if (useLiveIn && !LiveInBlocks->count(SuccBB))
+ return;
+
+ PHIBlocks.emplace_back(SuccBB);
+ if (!DefBlocks->count(SuccBB))
+ PQ.push(std::make_pair(
+ SuccNode, std::make_pair(SuccLevel, SuccNode->getDFSNumIn())));
+ };
+
+ for (auto Succ : ChildrenGetter.get(BB))
+ DoWork(Succ);
+
+ for (auto DomChild : *Node) {
+ if (VisitedWorklist.insert(DomChild).second)
+ Worklist.push_back(DomChild);
+ }
+ }
+ }
+}
+
+} // end of namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/JSON.h b/linux-x64/clang/include/llvm/Support/JSON.h
index e3cb950..0ca4109 100644
--- a/linux-x64/clang/include/llvm/Support/JSON.h
+++ b/linux-x64/clang/include/llvm/Support/JSON.h
@@ -21,6 +21,9 @@
/// - a convention and helpers for mapping between json::Value and user-defined
/// types. See fromJSON(), ObjectMapper, and the class comment on Value.
///
+/// - an output API json::OStream which can emit JSON without materializing
+/// all structures as json::Value.
+///
/// Typically, JSON data would be read from an external source, parsed into
/// a Value, and then converted into some native data structure before doing
/// real work on it. (And vice versa when writing).
@@ -36,7 +39,7 @@
///
/// - LLVM bitstream is a space- and CPU- efficient binary format. Typically it
/// encodes LLVM IR ("bitcode"), but it can be a container for other data.
-/// Low-level reader/writer libraries are in Bitcode/Bitstream*.h
+/// Low-level reader/writer libraries are in Bitstream/Bitstream*.h
///
//===---------------------------------------------------------------------===//
@@ -95,7 +98,7 @@
using iterator = Storage::iterator;
using const_iterator = Storage::const_iterator;
- explicit Object() = default;
+ Object() = default;
// KV is a trivial key-value struct for list-initialization.
// (using std::pair forces extra copies).
struct KV;
@@ -156,7 +159,7 @@
using iterator = std::vector<Value>::iterator;
using const_iterator = std::vector<Value>::const_iterator;
- explicit Array() = default;
+ Array() = default;
explicit Array(std::initializer_list<Value> Elements);
template <typename Collection> explicit Array(const Collection &C) {
for (const auto &V : C)
@@ -179,6 +182,7 @@
bool empty() const { return V.empty(); }
size_t size() const { return V.size(); }
+ void reserve(size_t S) { V.reserve(S); }
void clear() { V.clear(); }
void push_back(const Value &E) { V.push_back(E); }
@@ -309,8 +313,8 @@
create<std::string>(std::move(V));
}
Value(const llvm::SmallVectorImpl<char> &V)
- : Value(std::string(V.begin(), V.end())){};
- Value(const llvm::formatv_object_base &V) : Value(V.str()){};
+ : Value(std::string(V.begin(), V.end())) {}
+ Value(const llvm::formatv_object_base &V) : Value(V.str()) {}
// Strings: types with reference semantics. Must be valid UTF-8.
Value(StringRef V) : Type(T_StringRef) {
create<llvm::StringRef>(V);
@@ -436,11 +440,6 @@
return LLVM_LIKELY(Type == T_Array) ? &as<json::Array>() : nullptr;
}
- /// Serializes this Value to JSON, writing it to the provided stream.
- /// The formatting is compact (no extra whitespace) and deterministic.
- /// For pretty-printing, use the formatv() format_provider below.
- friend llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Value &);
-
private:
void destroy();
void copyFrom(const Value &M);
@@ -461,9 +460,7 @@
return *static_cast<T *>(Storage);
}
- template <typename Indenter>
- void print(llvm::raw_ostream &, const Indenter &) const;
- friend struct llvm::format_provider<llvm::json::Value>;
+ friend class OStream;
enum ValueType : char {
T_Null,
@@ -485,7 +482,6 @@
bool operator==(const Value &, const Value &);
inline bool operator!=(const Value &L, const Value &R) { return !(L == R); }
-llvm::raw_ostream &operator<<(llvm::raw_ostream &, const Value &);
/// ObjectKey is a used to capture keys in Object. Like Value but:
/// - only strings are allowed
@@ -698,6 +694,154 @@
return llvm::inconvertibleErrorCode();
}
};
+
+/// 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.
+///
+/// Only one "top-level" object can be written to a stream.
+/// Simplest usage involves passing lambdas (Blocks) to fill in containers:
+///
+/// json::OStream J(OS);
+/// J.array([&]{
+/// for (const Event &E : Events)
+/// J.object([&] {
+/// J.attribute("timestamp", int64_t(E.Time));
+/// J.attributeArray("participants", [&] {
+/// for (const Participant &P : E.Participants)
+/// J.string(P.toString());
+/// });
+/// });
+/// });
+///
+/// This would produce JSON like:
+///
+/// [
+/// {
+/// "timestamp": 19287398741,
+/// "participants": [
+/// "King Kong",
+/// "Miley Cyrus",
+/// "Cleopatra"
+/// ]
+/// },
+/// ...
+/// ]
+///
+/// The lower level begin/end methods (arrayBegin()) are more flexible but
+/// care must be taken to pair them correctly:
+///
+/// json::OStream J(OS);
+// J.arrayBegin();
+/// for (const Event &E : Events) {
+/// J.objectBegin();
+/// J.attribute("timestamp", int64_t(E.Time));
+/// J.attributeBegin("participants");
+/// for (const Participant &P : E.Participants)
+/// J.value(P.toString());
+/// J.attributeEnd();
+/// J.objectEnd();
+/// }
+/// J.arrayEnd();
+///
+/// If the call sequence isn't valid JSON, asserts will fire in debug mode.
+/// This can be mismatched begin()/end() pairs, trying to emit attributes inside
+/// an array, and so on.
+/// With asserts disabled, this is undefined behavior.
+class OStream {
+ public:
+ using Block = llvm::function_ref<void()>;
+ // If IndentSize is nonzero, output is pretty-printed.
+ explicit OStream(llvm::raw_ostream &OS, unsigned IndentSize = 0)
+ : OS(OS), IndentSize(IndentSize) {
+ Stack.emplace_back();
+ }
+ ~OStream() {
+ assert(Stack.size() == 1 && "Unmatched begin()/end()");
+ assert(Stack.back().Ctx == Singleton);
+ assert(Stack.back().HasValue && "Did not write top-level value");
+ }
+
+ /// Flushes the underlying ostream. OStream does not buffer internally.
+ void flush() { OS.flush(); }
+
+ // High level functions to output a value.
+ // Valid at top-level (exactly once), in an attribute value (exactly once),
+ // or in an array (any number of times).
+
+ /// Emit a self-contained value (number, string, vector<string> etc).
+ void value(const Value &V);
+ /// Emit an array whose elements are emitted in the provided Block.
+ void array(Block Contents) {
+ arrayBegin();
+ Contents();
+ arrayEnd();
+ }
+ /// Emit an object whose elements are emitted in the provided Block.
+ void object(Block Contents) {
+ objectBegin();
+ Contents();
+ objectEnd();
+ }
+
+ // High level functions to output object attributes.
+ // Valid only within an object (any number of times).
+
+ /// Emit an attribute whose value is self-contained (number, vector<int> etc).
+ void attribute(llvm::StringRef Key, const Value& Contents) {
+ attributeImpl(Key, [&] { value(Contents); });
+ }
+ /// Emit an attribute whose value is an array with elements from the Block.
+ void attributeArray(llvm::StringRef Key, Block Contents) {
+ attributeImpl(Key, [&] { array(Contents); });
+ }
+ /// Emit an attribute whose value is an object with attributes from the Block.
+ void attributeObject(llvm::StringRef Key, Block Contents) {
+ attributeImpl(Key, [&] { object(Contents); });
+ }
+
+ // Low-level begin/end functions to output arrays, objects, and attributes.
+ // Must be correctly paired. Allowed contexts are as above.
+
+ void arrayBegin();
+ void arrayEnd();
+ void objectBegin();
+ void objectEnd();
+ void attributeBegin(llvm::StringRef Key);
+ void attributeEnd();
+
+ private:
+ void attributeImpl(llvm::StringRef Key, Block Contents) {
+ attributeBegin(Key);
+ Contents();
+ attributeEnd();
+ }
+
+ void valueBegin();
+ void newline();
+
+ enum Context {
+ Singleton, // Top level, or object attribute.
+ Array,
+ Object,
+ };
+ struct State {
+ Context Ctx = Singleton;
+ bool HasValue = false;
+ };
+ llvm::SmallVector<State, 16> Stack; // Never empty.
+ llvm::raw_ostream &OS;
+ unsigned IndentSize;
+ unsigned Indent = 0;
+};
+
+/// Serializes this Value to JSON, writing it to the provided stream.
+/// The formatting is compact (no extra whitespace) and deterministic.
+/// For pretty-printing, use the formatv() format_provider below.
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Value &V) {
+ OStream(OS).value(V);
+ return OS;
+}
} // namespace json
/// Allow printing json::Value with formatv().
diff --git a/linux-x64/clang/include/llvm/Support/KnownBits.h b/linux-x64/clang/include/llvm/Support/KnownBits.h
index 8983a06..07fd94e 100644
--- a/linux-x64/clang/include/llvm/Support/KnownBits.h
+++ b/linux-x64/clang/include/llvm/Support/KnownBits.h
@@ -109,25 +109,36 @@
/// Truncate the underlying known Zero and One bits. This is equivalent
/// to truncating the value we're tracking.
- KnownBits trunc(unsigned BitWidth) {
+ KnownBits trunc(unsigned BitWidth) const {
return KnownBits(Zero.trunc(BitWidth), One.trunc(BitWidth));
}
- /// Zero extends the underlying known Zero and One bits. This is equivalent
- /// to zero extending the value we're tracking.
- KnownBits zext(unsigned BitWidth) {
- return KnownBits(Zero.zext(BitWidth), One.zext(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 {
+ unsigned OldBitWidth = getBitWidth();
+ APInt NewZero = Zero.zext(BitWidth);
+ if (ExtendedBitsAreKnownZero)
+ 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.
- KnownBits sext(unsigned BitWidth) {
+ KnownBits sext(unsigned BitWidth) const {
return KnownBits(Zero.sext(BitWidth), One.sext(BitWidth));
}
- /// Zero extends or truncates the underlying known Zero and One bits. This is
- /// equivalent to zero extending or truncating the value we're tracking.
- KnownBits zextOrTrunc(unsigned 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 {
+ if (BitWidth > getBitWidth())
+ return zext(BitWidth, ExtendedBitsAreKnownZero);
return KnownBits(Zero.zextOrTrunc(BitWidth), One.zextOrTrunc(BitWidth));
}
@@ -191,6 +202,10 @@
return getBitWidth() - Zero.countPopulation();
}
+ /// 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);
+
/// Compute known bits resulting from adding LHS and RHS.
static KnownBits computeForAddSub(bool Add, bool NSW, const KnownBits &LHS,
KnownBits RHS);
diff --git a/linux-x64/clang/include/llvm/Support/LEB128.h b/linux-x64/clang/include/llvm/Support/LEB128.h
index eb43c85..a02b83c 100644
--- a/linux-x64/clang/include/llvm/Support/LEB128.h
+++ b/linux-x64/clang/include/llvm/Support/LEB128.h
@@ -165,6 +165,8 @@
int64_t Value = 0;
unsigned Shift = 0;
uint8_t Byte;
+ if (error)
+ *error = nullptr;
do {
if (end && p == end) {
if (error)
@@ -174,11 +176,11 @@
return 0;
}
Byte = *p++;
- Value |= (int64_t(Byte & 0x7f) << Shift);
+ Value |= (uint64_t(Byte & 0x7f) << Shift);
Shift += 7;
} while (Byte >= 128);
- // Sign extend negative numbers.
- if (Byte & 0x40)
+ // Sign extend negative numbers if needed.
+ if (Shift < 64 && (Byte & 0x40))
Value |= (-1ULL) << Shift;
if (n)
*n = (unsigned)(p - orig_p);
diff --git a/linux-x64/clang/include/llvm/Support/LowLevelTypeImpl.h b/linux-x64/clang/include/llvm/Support/LowLevelTypeImpl.h
index efe5c51..0e02b6e 100644
--- a/linux-x64/clang/include/llvm/Support/LowLevelTypeImpl.h
+++ b/linux-x64/clang/include/llvm/Support/LowLevelTypeImpl.h
@@ -111,6 +111,12 @@
return getScalarSizeInBits() * getNumElements();
}
+ /// Returns the total size of the type in bytes, i.e. number of whole bytes
+ /// needed to represent the size in bits. Must only be called on sized types.
+ unsigned getSizeInBytes() const {
+ return (getSizeInBits() + 7) / 8;
+ }
+
LLT getScalarType() const {
return isVector() ? getElementType() : *this;
}
diff --git a/linux-x64/clang/include/llvm/Support/MachineValueType.h b/linux-x64/clang/include/llvm/Support/MachineValueType.h
index 7651b28..a9b130f 100644
--- a/linux-x64/clang/include/llvm/Support/MachineValueType.h
+++ b/linux-x64/clang/include/llvm/Support/MachineValueType.h
@@ -86,58 +86,65 @@
v64i16 = 39, // 64 x i16
v128i16 = 40, //128 x i16
- v1i32 = 41, // 1 x i32
- v2i32 = 42, // 2 x i32
- v4i32 = 43, // 4 x i32
- v8i32 = 44, // 8 x i32
- v16i32 = 45, // 16 x i32
- v32i32 = 46, // 32 x i32
- v64i32 = 47, // 64 x i32
+ v1i32 = 41, // 1 x i32
+ v2i32 = 42, // 2 x i32
+ v3i32 = 43, // 3 x i32
+ v4i32 = 44, // 4 x i32
+ v5i32 = 45, // 5 x i32
+ v8i32 = 46, // 8 x i32
+ v16i32 = 47, // 16 x i32
+ v32i32 = 48, // 32 x i32
+ v64i32 = 49, // 64 x i32
+ v128i32 = 50, // 128 x i32
+ v256i32 = 51, // 256 x i32
+ v512i32 = 52, // 512 x i32
+ v1024i32 = 53, // 1024 x i32
+ v2048i32 = 54, // 2048 x i32
- v1i64 = 48, // 1 x i64
- v2i64 = 49, // 2 x i64
- v4i64 = 50, // 4 x i64
- v8i64 = 51, // 8 x i64
- v16i64 = 52, // 16 x i64
- v32i64 = 53, // 32 x i64
+ v1i64 = 55, // 1 x i64
+ v2i64 = 56, // 2 x i64
+ v4i64 = 57, // 4 x i64
+ v8i64 = 58, // 8 x i64
+ v16i64 = 59, // 16 x i64
+ v32i64 = 60, // 32 x i64
- v1i128 = 54, // 1 x i128
+ v1i128 = 61, // 1 x i128
// Scalable integer types
- nxv1i1 = 55, // n x 1 x i1
- nxv2i1 = 56, // n x 2 x i1
- nxv4i1 = 57, // n x 4 x i1
- nxv8i1 = 58, // n x 8 x i1
- nxv16i1 = 59, // n x 16 x i1
- nxv32i1 = 60, // n x 32 x i1
+ nxv1i1 = 62, // n x 1 x i1
+ nxv2i1 = 63, // n x 2 x i1
+ nxv4i1 = 64, // n x 4 x i1
+ nxv8i1 = 65, // n x 8 x i1
+ nxv16i1 = 66, // n x 16 x i1
+ nxv32i1 = 67, // n x 32 x i1
- nxv1i8 = 61, // n x 1 x i8
- nxv2i8 = 62, // n x 2 x i8
- nxv4i8 = 63, // n x 4 x i8
- nxv8i8 = 64, // n x 8 x i8
- nxv16i8 = 65, // n x 16 x i8
- nxv32i8 = 66, // n x 32 x i8
+ nxv1i8 = 68, // n x 1 x i8
+ nxv2i8 = 69, // n x 2 x i8
+ nxv4i8 = 70, // n x 4 x i8
+ nxv8i8 = 71, // n x 8 x i8
+ nxv16i8 = 72, // n x 16 x i8
+ nxv32i8 = 73, // n x 32 x i8
- nxv1i16 = 67, // n x 1 x i16
- nxv2i16 = 68, // n x 2 x i16
- nxv4i16 = 69, // n x 4 x i16
- nxv8i16 = 70, // n x 8 x i16
- nxv16i16 = 71, // n x 16 x i16
- nxv32i16 = 72, // n x 32 x i16
+ nxv1i16 = 74, // n x 1 x i16
+ nxv2i16 = 75, // n x 2 x i16
+ nxv4i16 = 76, // n x 4 x i16
+ nxv8i16 = 77, // n x 8 x i16
+ nxv16i16 = 78, // n x 16 x i16
+ nxv32i16 = 79, // n x 32 x i16
- nxv1i32 = 73, // n x 1 x i32
- nxv2i32 = 74, // n x 2 x i32
- nxv4i32 = 75, // n x 4 x i32
- nxv8i32 = 76, // n x 8 x i32
- nxv16i32 = 77, // n x 16 x i32
- nxv32i32 = 78, // n x 32 x i32
+ nxv1i32 = 80, // n x 1 x i32
+ nxv2i32 = 81, // n x 2 x i32
+ nxv4i32 = 82, // n x 4 x i32
+ nxv8i32 = 83, // n x 8 x i32
+ nxv16i32 = 84, // n x 16 x i32
+ nxv32i32 = 85, // n x 32 x i32
- nxv1i64 = 79, // n x 1 x i64
- nxv2i64 = 80, // n x 2 x i64
- nxv4i64 = 81, // n x 4 x i64
- nxv8i64 = 82, // n x 8 x i64
- nxv16i64 = 83, // n x 16 x i64
- nxv32i64 = 84, // n x 32 x i64
+ nxv1i64 = 86, // n x 1 x i64
+ nxv2i64 = 87, // n x 2 x i64
+ nxv4i64 = 88, // n x 4 x i64
+ nxv8i64 = 89, // n x 8 x i64
+ nxv16i64 = 90, // n x 16 x i64
+ nxv32i64 = 91, // n x 32 x i64
FIRST_INTEGER_VECTOR_VALUETYPE = v1i1,
LAST_INTEGER_VECTOR_VALUETYPE = nxv32i64,
@@ -145,31 +152,40 @@
FIRST_INTEGER_SCALABLE_VALUETYPE = nxv1i1,
LAST_INTEGER_SCALABLE_VALUETYPE = nxv32i64,
- v2f16 = 85, // 2 x f16
- v4f16 = 86, // 4 x f16
- v8f16 = 87, // 8 x f16
- v1f32 = 88, // 1 x f32
- v2f32 = 89, // 2 x f32
- v4f32 = 90, // 4 x f32
- v8f32 = 91, // 8 x f32
- v16f32 = 92, // 16 x f32
- v1f64 = 93, // 1 x f64
- v2f64 = 94, // 2 x f64
- v4f64 = 95, // 4 x f64
- v8f64 = 96, // 8 x f64
+ v2f16 = 92, // 2 x f16
+ v4f16 = 93, // 4 x f16
+ v8f16 = 94, // 8 x f16
+ v1f32 = 95, // 1 x f32
+ v2f32 = 96, // 2 x f32
+ v3f32 = 97, // 3 x f32
+ v4f32 = 98, // 4 x f32
+ v5f32 = 99, // 5 x f32
+ v8f32 = 100, // 8 x f32
+ v16f32 = 101, // 16 x f32
+ v32f32 = 102, // 32 x f32
+ v64f32 = 103, // 64 x f32
+ v128f32 = 104, // 128 x f32
+ v256f32 = 105, // 256 x f32
+ v512f32 = 106, // 512 x f32
+ v1024f32 = 107, // 1024 x f32
+ v2048f32 = 108, // 2048 x f32
+ v1f64 = 109, // 1 x f64
+ v2f64 = 110, // 2 x f64
+ v4f64 = 111, // 4 x f64
+ v8f64 = 112, // 8 x f64
- nxv2f16 = 97, // n x 2 x f16
- nxv4f16 = 98, // n x 4 x f16
- nxv8f16 = 99, // n x 8 x f16
- nxv1f32 = 100, // n x 1 x f32
- nxv2f32 = 101, // n x 2 x f32
- nxv4f32 = 102, // n x 4 x f32
- nxv8f32 = 103, // n x 8 x f32
- nxv16f32 = 104, // n x 16 x f32
- nxv1f64 = 105, // n x 1 x f64
- nxv2f64 = 106, // n x 2 x f64
- nxv4f64 = 107, // n x 4 x f64
- nxv8f64 = 108, // n x 8 x f64
+ nxv2f16 = 113, // n x 2 x f16
+ nxv4f16 = 114, // n x 4 x f16
+ nxv8f16 = 115, // n x 8 x f16
+ nxv1f32 = 116, // n x 1 x f32
+ nxv2f32 = 117, // n x 2 x f32
+ nxv4f32 = 118, // n x 4 x f32
+ nxv8f32 = 119, // n x 8 x f32
+ nxv16f32 = 120, // n x 16 x f32
+ nxv1f64 = 121, // n x 1 x f64
+ nxv2f64 = 122, // n x 2 x f64
+ nxv4f64 = 123, // n x 4 x f64
+ nxv8f64 = 124, // n x 8 x f64
FIRST_FP_VECTOR_VALUETYPE = v2f16,
LAST_FP_VECTOR_VALUETYPE = nxv8f64,
@@ -180,25 +196,25 @@
FIRST_VECTOR_VALUETYPE = v1i1,
LAST_VECTOR_VALUETYPE = nxv8f64,
- x86mmx = 109, // This is an X86 MMX value
+ x86mmx = 125, // This is an X86 MMX value
- Glue = 110, // This glues nodes together during pre-RA sched
+ Glue = 126, // This glues nodes together during pre-RA sched
- isVoid = 111, // This has no value
+ isVoid = 127, // This has no value
- Untyped = 112, // This value takes a register, but has
+ Untyped = 128, // This value takes a register, but has
// unspecified type. The register class
// will be determined by the opcode.
- ExceptRef = 113, // WebAssembly's except_ref type
+ ExceptRef = 129, // WebAssembly's except_ref type
FIRST_VALUETYPE = 1, // This is always the beginning of the list.
- LAST_VALUETYPE = 114, // This always remains at the end of the list.
+ LAST_VALUETYPE = 130, // 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 = 128,
+ MAX_ALLOWED_VALUETYPE = 160,
// A value of type llvm::TokenTy
token = 248,
@@ -463,11 +479,18 @@
case nxv32i16: return i16;
case v1i32:
case v2i32:
+ case v3i32:
case v4i32:
+ case v5i32:
case v8i32:
case v16i32:
case v32i32:
case v64i32:
+ case v128i32:
+ case v256i32:
+ case v512i32:
+ case v1024i32:
+ case v2048i32:
case nxv1i32:
case nxv2i32:
case nxv4i32:
@@ -495,9 +518,18 @@
case nxv8f16: return f16;
case v1f32:
case v2f32:
+ case v3f32:
case v4f32:
+ case v5f32:
case v8f32:
case v16f32:
+ case v32f32:
+ case v64f32:
+ case v128f32:
+ case v256f32:
+ case v512f32:
+ case v1024f32:
+ case v2048f32:
case nxv1f32:
case nxv2f32:
case nxv4f32:
@@ -518,21 +550,33 @@
switch (SimpleTy) {
default:
llvm_unreachable("Not a vector MVT!");
- case v1024i1: return 1024;
- case v512i1: return 512;
- case v256i8: return 256;
+ case v2048i32:
+ case v2048f32: return 2048;
+ case v1024i1:
+ case v1024i32:
+ case v1024f32: return 1024;
+ case v512i1:
+ case v512i32:
+ case v512f32: return 512;
+ case v256i8:
+ case v256i32:
+ case v256f32: return 256;
case v128i1:
case v128i8:
- case v128i16: return 128;
+ case v128i16:
+ case v128i32:
+ case v128f32: return 128;
case v64i1:
case v64i8:
case v64i16:
- case v64i32: return 64;
+ case v64i32:
+ case v64f32: return 64;
case v32i1:
case v32i8:
case v32i16:
case v32i32:
case v32i64:
+ case v32f32:
case nxv32i1:
case nxv32i8:
case nxv32i16:
@@ -566,6 +610,8 @@
case nxv8f16:
case nxv8f32:
case nxv8f64: return 8;
+ case v5i32:
+ case v5f32: return 5;
case v4i1:
case v4i8:
case v4i16:
@@ -582,6 +628,8 @@
case nxv4f16:
case nxv4f32:
case nxv4f64: return 4;
+ case v3i32:
+ case v3f32: return 3;
case v2i1:
case v2i8:
case v2i16:
@@ -692,6 +740,8 @@
case nxv2f32:
case nxv1f64: return 64;
case f80 : return 80;
+ case v3i32:
+ case v3f32: return 96;
case f128:
case ppcf128:
case i128:
@@ -711,6 +761,8 @@
case nxv8f16:
case nxv4f32:
case nxv2f64: return 128;
+ case v5i32:
+ case v5f32: return 160;
case v32i8:
case v16i16:
case v8i32:
@@ -740,13 +792,25 @@
case v64i16:
case v32i32:
case v16i64:
+ case v32f32:
case nxv32i32:
case nxv16i64: return 1024;
case v256i8:
case v128i16:
case v64i32:
case v32i64:
+ case v64f32:
case nxv32i64: return 2048;
+ case v128i32:
+ case v128f32: return 4096;
+ case v256i32:
+ case v256f32: return 8192;
+ case v512i32:
+ case v512f32: return 16384;
+ case v1024i32:
+ case v1024f32: return 32768;
+ case v2048i32:
+ case v2048f32: return 65536;
case ExceptRef: return 0; // opaque type
}
}
@@ -861,13 +925,20 @@
if (NumElements == 128) return MVT::v128i16;
break;
case MVT::i32:
- if (NumElements == 1) return MVT::v1i32;
- if (NumElements == 2) return MVT::v2i32;
- if (NumElements == 4) return MVT::v4i32;
- if (NumElements == 8) return MVT::v8i32;
- if (NumElements == 16) return MVT::v16i32;
- if (NumElements == 32) return MVT::v32i32;
- if (NumElements == 64) return MVT::v64i32;
+ if (NumElements == 1) return MVT::v1i32;
+ if (NumElements == 2) return MVT::v2i32;
+ if (NumElements == 3) return MVT::v3i32;
+ if (NumElements == 4) return MVT::v4i32;
+ if (NumElements == 5) return MVT::v5i32;
+ if (NumElements == 8) return MVT::v8i32;
+ if (NumElements == 16) return MVT::v16i32;
+ if (NumElements == 32) return MVT::v32i32;
+ if (NumElements == 64) return MVT::v64i32;
+ if (NumElements == 128) return MVT::v128i32;
+ if (NumElements == 256) return MVT::v256i32;
+ if (NumElements == 512) return MVT::v512i32;
+ if (NumElements == 1024) return MVT::v1024i32;
+ if (NumElements == 2048) return MVT::v2048i32;
break;
case MVT::i64:
if (NumElements == 1) return MVT::v1i64;
@@ -886,11 +957,20 @@
if (NumElements == 8) return MVT::v8f16;
break;
case MVT::f32:
- if (NumElements == 1) return MVT::v1f32;
- if (NumElements == 2) return MVT::v2f32;
- if (NumElements == 4) return MVT::v4f32;
- if (NumElements == 8) return MVT::v8f32;
- if (NumElements == 16) return MVT::v16f32;
+ if (NumElements == 1) return MVT::v1f32;
+ if (NumElements == 2) return MVT::v2f32;
+ if (NumElements == 3) return MVT::v3f32;
+ if (NumElements == 4) return MVT::v4f32;
+ if (NumElements == 5) return MVT::v5f32;
+ if (NumElements == 8) return MVT::v8f32;
+ if (NumElements == 16) return MVT::v16f32;
+ if (NumElements == 32) return MVT::v32f32;
+ if (NumElements == 64) return MVT::v64f32;
+ if (NumElements == 128) return MVT::v128f32;
+ if (NumElements == 256) return MVT::v256f32;
+ if (NumElements == 512) return MVT::v512f32;
+ if (NumElements == 1024) return MVT::v1024f32;
+ if (NumElements == 2048) return MVT::v2048f32;
break;
case MVT::f64:
if (NumElements == 1) return MVT::v1f64;
diff --git a/linux-x64/clang/include/llvm/Support/ManagedStatic.h b/linux-x64/clang/include/llvm/Support/ManagedStatic.h
index 441f24e..e65bb05 100644
--- a/linux-x64/clang/include/llvm/Support/ManagedStatic.h
+++ b/linux-x64/clang/include/llvm/Support/ManagedStatic.h
@@ -32,18 +32,41 @@
static void call(void *Ptr) { delete[](T *)Ptr; }
};
+// ManagedStatic must be initialized to zero, and it must *not* have a dynamic
+// initializer because managed statics are often created while running other
+// dynamic initializers. In standard C++11, the best way to accomplish this is
+// with a constexpr default constructor. However, different versions of the
+// Visual C++ compiler have had bugs where, even though the constructor may be
+// 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__)
+#define LLVM_USE_CONSTEXPR_CTOR
+#endif
+
/// ManagedStaticBase - Common base class for ManagedStatic instances.
class ManagedStaticBase {
protected:
+#ifdef LLVM_USE_CONSTEXPR_CTOR
+ mutable std::atomic<void *> Ptr{};
+ mutable void (*DeleterFn)(void *) = nullptr;
+ mutable const ManagedStaticBase *Next = nullptr;
+#else
// This should only be used as a static variable, which guarantees that this
// will be zero initialized.
mutable std::atomic<void *> Ptr;
- mutable void (*DeleterFn)(void*);
+ mutable void (*DeleterFn)(void *);
mutable const ManagedStaticBase *Next;
+#endif
void RegisterManagedStatic(void *(*creator)(), void (*deleter)(void*)) const;
public:
+#ifdef LLVM_USE_CONSTEXPR_CTOR
+ constexpr ManagedStaticBase() = default;
+#endif
+
/// isConstructed - Return true if this object has not been created yet.
bool isConstructed() const { return Ptr != nullptr; }
diff --git a/linux-x64/clang/include/llvm/Support/MathExtras.h b/linux-x64/clang/include/llvm/Support/MathExtras.h
index e902a72..85d5a5a 100644
--- a/linux-x64/clang/include/llvm/Support/MathExtras.h
+++ b/linux-x64/clang/include/llvm/Support/MathExtras.h
@@ -51,14 +51,14 @@
namespace detail {
template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
- static std::size_t count(T Val, ZeroBehavior) {
+ static unsigned count(T Val, ZeroBehavior) {
if (!Val)
return std::numeric_limits<T>::digits;
if (Val & 0x1)
return 0;
// Bisection method.
- std::size_t ZeroBits = 0;
+ unsigned ZeroBits = 0;
T Shift = std::numeric_limits<T>::digits >> 1;
T Mask = std::numeric_limits<T>::max() >> Shift;
while (Shift) {
@@ -75,7 +75,7 @@
#if __GNUC__ >= 4 || defined(_MSC_VER)
template <typename T> struct TrailingZerosCounter<T, 4> {
- static std::size_t count(T Val, ZeroBehavior ZB) {
+ static unsigned count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 32;
@@ -91,7 +91,7 @@
#if !defined(_MSC_VER) || defined(_M_X64)
template <typename T> struct TrailingZerosCounter<T, 8> {
- static std::size_t count(T Val, ZeroBehavior ZB) {
+ static unsigned count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 64;
@@ -116,7 +116,7 @@
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
/// valid arguments.
template <typename T>
-std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
+unsigned countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
"Only unsigned integral types are allowed.");
@@ -125,12 +125,12 @@
namespace detail {
template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
- static std::size_t count(T Val, ZeroBehavior) {
+ static unsigned count(T Val, ZeroBehavior) {
if (!Val)
return std::numeric_limits<T>::digits;
// Bisection method.
- std::size_t ZeroBits = 0;
+ unsigned ZeroBits = 0;
for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
T Tmp = Val >> Shift;
if (Tmp)
@@ -144,7 +144,7 @@
#if __GNUC__ >= 4 || defined(_MSC_VER)
template <typename T> struct LeadingZerosCounter<T, 4> {
- static std::size_t count(T Val, ZeroBehavior ZB) {
+ static unsigned count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 32;
@@ -160,7 +160,7 @@
#if !defined(_MSC_VER) || defined(_M_X64)
template <typename T> struct LeadingZerosCounter<T, 8> {
- static std::size_t count(T Val, ZeroBehavior ZB) {
+ static unsigned count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 64;
@@ -185,7 +185,7 @@
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
/// valid arguments.
template <typename T>
-std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
+unsigned countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
"Only unsigned integral types are allowed.");
@@ -458,7 +458,7 @@
/// \param ZB the behavior on an input of all ones. Only ZB_Width and
/// ZB_Undefined are valid arguments.
template <typename T>
-std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
+unsigned countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
"Only unsigned integral types are allowed.");
@@ -474,7 +474,7 @@
/// \param ZB the behavior on an input of all ones. Only ZB_Width and
/// ZB_Undefined are valid arguments.
template <typename T>
-std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
+unsigned countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
"Only unsigned integral types are allowed.");
diff --git a/linux-x64/clang/include/llvm/Support/MemAlloc.h b/linux-x64/clang/include/llvm/Support/MemAlloc.h
index ed076ff..0e58691 100644
--- a/linux-x64/clang/include/llvm/Support/MemAlloc.h
+++ b/linux-x64/clang/include/llvm/Support/MemAlloc.h
@@ -24,23 +24,41 @@
LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_malloc(size_t Sz) {
void *Result = std::malloc(Sz);
- if (Result == nullptr)
+ if (Result == nullptr) {
+ // It is implementation-defined whether allocation occurs if the space
+ // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+ // non-zero, if the space requested was zero.
+ if (Sz == 0)
+ return safe_malloc(1);
report_bad_alloc_error("Allocation failed");
+ }
return Result;
}
LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_calloc(size_t Count,
size_t Sz) {
void *Result = std::calloc(Count, Sz);
- if (Result == nullptr)
+ if (Result == nullptr) {
+ // It is implementation-defined whether allocation occurs if the space
+ // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+ // non-zero, if the space requested was zero.
+ if (Count == 0 || Sz == 0)
+ return safe_malloc(1);
report_bad_alloc_error("Allocation failed");
+ }
return Result;
}
LLVM_ATTRIBUTE_RETURNS_NONNULL inline void *safe_realloc(void *Ptr, size_t Sz) {
void *Result = std::realloc(Ptr, Sz);
- if (Result == nullptr)
+ if (Result == nullptr) {
+ // It is implementation-defined whether allocation occurs if the space
+ // requested is zero (ISO/IEC 9899:2018 7.22.3). Retry, requesting
+ // non-zero, if the space requested was zero.
+ if (Sz == 0)
+ return safe_malloc(1);
report_bad_alloc_error("Allocation failed");
+ }
return Result;
}
diff --git a/linux-x64/clang/include/llvm/Support/Memory.h b/linux-x64/clang/include/llvm/Support/Memory.h
index 2f4cafe..6f22dd7 100644
--- a/linux-x64/clang/include/llvm/Support/Memory.h
+++ b/linux-x64/clang/include/llvm/Support/Memory.h
@@ -18,6 +18,10 @@
#include <system_error>
namespace llvm {
+
+// Forward declare raw_ostream: it is used for debug dumping below.
+class raw_ostream;
+
namespace sys {
/// This class encapsulates the notion of a memory block which has an address
@@ -27,14 +31,18 @@
/// Memory block abstraction.
class MemoryBlock {
public:
- MemoryBlock() : Address(nullptr), Size(0) { }
- MemoryBlock(void *addr, size_t size) : Address(addr), Size(size) { }
+ MemoryBlock() : Address(nullptr), AllocatedSize(0) {}
+ MemoryBlock(void *addr, size_t allocatedSize)
+ : Address(addr), AllocatedSize(allocatedSize) {}
void *base() const { return Address; }
- size_t size() const { return Size; }
-
+ /// The size as it was allocated. This is always greater or equal to the
+ /// size that was originally requested.
+ size_t allocatedSize() const { return AllocatedSize; }
+
private:
void *Address; ///< Address of first byte of memory area
- size_t Size; ///< Size, in bytes of the memory area
+ size_t AllocatedSize; ///< Size, in bytes of the memory area
+ unsigned Flags = 0;
friend class Memory;
};
@@ -45,9 +53,11 @@
class Memory {
public:
enum ProtectionFlags {
- MF_READ = 0x1000000,
+ MF_READ = 0x1000000,
MF_WRITE = 0x2000000,
- MF_EXEC = 0x4000000
+ MF_EXEC = 0x4000000,
+ MF_RWE_MASK = 0x7000000,
+ MF_HUGE_HINT = 0x0000001
};
/// This method allocates a block of memory that is suitable for loading
@@ -132,13 +142,22 @@
Memory::releaseMappedMemory(M);
}
void *base() const { return M.base(); }
- size_t size() const { return M.size(); }
+ /// The size as it was allocated. This is always greater or equal to the
+ /// size that was originally requested.
+ size_t allocatedSize() const { return M.allocatedSize(); }
MemoryBlock getMemoryBlock() const { return M; }
private:
MemoryBlock M;
};
-}
-}
+#ifndef NDEBUG
+ /// Debugging output for Memory::ProtectionFlags.
+ raw_ostream &operator<<(raw_ostream &OS, const Memory::ProtectionFlags &PF);
+
+ /// Debugging output for MemoryBlock.
+ raw_ostream &operator<<(raw_ostream &OS, const MemoryBlock &MB);
+#endif // ifndef NDEBUG
+ } // end namespace sys
+ } // end namespace llvm
#endif
diff --git a/linux-x64/clang/include/llvm/Support/MemoryBuffer.h b/linux-x64/clang/include/llvm/Support/MemoryBuffer.h
index 4405269..b5196cd 100644
--- a/linux-x64/clang/include/llvm/Support/MemoryBuffer.h
+++ b/linux-x64/clang/include/llvm/Support/MemoryBuffer.h
@@ -90,7 +90,7 @@
/// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize.
/// Since this is in the middle of a file, the buffer is not null terminated.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
- getOpenFileSlice(int FD, const Twine &Filename, uint64_t MapSize,
+ getOpenFileSlice(sys::fs::file_t FD, const Twine &Filename, uint64_t MapSize,
int64_t Offset, bool IsVolatile = false);
/// Given an already-open file descriptor, read the file and return a
@@ -100,7 +100,7 @@
/// can change outside the user's control, e.g. when libclang tries to parse
/// while the user is editing/updating the file or if the file is on an NFS.
static ErrorOr<std::unique_ptr<MemoryBuffer>>
- getOpenFile(int FD, const Twine &Filename, uint64_t FileSize,
+ getOpenFile(sys::fs::file_t FD, const Twine &Filename, uint64_t FileSize,
bool RequiresNullTerminator = true, bool IsVolatile = false);
/// Open the specified memory range as a MemoryBuffer. Note that InputData
@@ -264,7 +264,7 @@
public:
MemoryBufferRef() = default;
- MemoryBufferRef(MemoryBuffer& Buffer)
+ MemoryBufferRef(const MemoryBuffer& Buffer)
: Buffer(Buffer.getBuffer()), Identifier(Buffer.getBufferIdentifier()) {}
MemoryBufferRef(StringRef Buffer, StringRef Identifier)
: Buffer(Buffer), Identifier(Identifier) {}
diff --git a/linux-x64/clang/include/llvm/Support/Parallel.h b/linux-x64/clang/include/llvm/Support/Parallel.h
index 9843b95..eab9b49 100644
--- a/linux-x64/clang/include/llvm/Support/Parallel.h
+++ b/linux-x64/clang/include/llvm/Support/Parallel.h
@@ -73,8 +73,12 @@
class TaskGroup {
Latch L;
+ bool Parallel;
public:
+ TaskGroup();
+ ~TaskGroup();
+
void spawn(std::function<void()> f);
void sync() const { L.sync(); }
diff --git a/linux-x64/clang/include/llvm/Support/Process.h b/linux-x64/clang/include/llvm/Support/Process.h
index 9a70304..67e3791 100644
--- a/linux-x64/clang/include/llvm/Support/Process.h
+++ b/linux-x64/clang/include/llvm/Support/Process.h
@@ -28,6 +28,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Chrono.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Error.h"
#include <system_error>
namespace llvm {
@@ -41,7 +42,25 @@
/// current executing process.
class Process {
public:
- static unsigned getPageSize();
+ /// 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
+ /// safely discarded by calling consumeError, and an estimated page size
+ /// substituted instead.
+ static Expected<unsigned> getPageSize();
+
+ /// Get the process's estimated page size.
+ /// This function always succeeds, but if the underlying syscall to determine
+ /// the page size fails then this will silently return an estimated page size.
+ /// The estimated page size is guaranteed to be a power of 2.
+ static unsigned getPageSizeEstimate() {
+ if (auto PageSize = getPageSize())
+ return *PageSize;
+ else {
+ consumeError(PageSize.takeError());
+ return 4096;
+ }
+ }
/// Return process memory usage.
/// This static function will return the total amount of memory allocated
diff --git a/linux-x64/clang/include/llvm/Support/SMTAPI.h b/linux-x64/clang/include/llvm/Support/SMTAPI.h
new file mode 100644
index 0000000..24dcd12
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/SMTAPI.h
@@ -0,0 +1,447 @@
+//===- SMTAPI.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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a SMT generic Solver API, which will be the base class
+// for every SMT solver specific class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SMTAPI_H
+#define LLVM_SUPPORT_SMTAPI_H
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+
+namespace llvm {
+
+/// Generic base class for SMT sorts
+class SMTSort {
+public:
+ SMTSort() = default;
+ virtual ~SMTSort() = default;
+
+ /// Returns true if the sort is a bitvector, calls isBitvectorSortImpl().
+ virtual bool isBitvectorSort() const { return isBitvectorSortImpl(); }
+
+ /// Returns true if the sort is a floating-point, calls isFloatSortImpl().
+ virtual bool isFloatSort() const { return isFloatSortImpl(); }
+
+ /// Returns true if the sort is a boolean, calls isBooleanSortImpl().
+ virtual bool isBooleanSort() const { return isBooleanSortImpl(); }
+
+ /// Returns the bitvector size, fails if the sort is not a bitvector
+ /// Calls getBitvectorSortSizeImpl().
+ virtual unsigned getBitvectorSortSize() const {
+ assert(isBitvectorSort() && "Not a bitvector sort!");
+ unsigned Size = getBitvectorSortSizeImpl();
+ assert(Size && "Size is zero!");
+ return Size;
+ };
+
+ /// Returns the floating-point size, fails if the sort is not a floating-point
+ /// Calls getFloatSortSizeImpl().
+ virtual unsigned getFloatSortSize() const {
+ assert(isFloatSort() && "Not a floating-point sort!");
+ unsigned Size = getFloatSortSizeImpl();
+ assert(Size && "Size is zero!");
+ return Size;
+ };
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
+
+ bool operator<(const SMTSort &Other) const {
+ llvm::FoldingSetNodeID ID1, ID2;
+ Profile(ID1);
+ Other.Profile(ID2);
+ return ID1 < ID2;
+ }
+
+ friend bool operator==(SMTSort const &LHS, SMTSort const &RHS) {
+ return LHS.equal_to(RHS);
+ }
+
+ virtual void print(raw_ostream &OS) const = 0;
+
+ LLVM_DUMP_METHOD void dump() const;
+
+protected:
+ /// Query the SMT solver and returns true if two sorts are equal (same kind
+ /// and bit width). This does not check if the two sorts are the same objects.
+ virtual bool equal_to(SMTSort const &other) const = 0;
+
+ /// Query the SMT solver and checks if a sort is bitvector.
+ virtual bool isBitvectorSortImpl() const = 0;
+
+ /// Query the SMT solver and checks if a sort is floating-point.
+ virtual bool isFloatSortImpl() const = 0;
+
+ /// Query the SMT solver and checks if a sort is boolean.
+ virtual bool isBooleanSortImpl() const = 0;
+
+ /// Query the SMT solver and returns the sort bit width.
+ virtual unsigned getBitvectorSortSizeImpl() const = 0;
+
+ /// Query the SMT solver and returns the sort bit width.
+ virtual unsigned getFloatSortSizeImpl() const = 0;
+};
+
+/// Shared pointer for SMTSorts, used by SMTSolver API.
+using SMTSortRef = const SMTSort *;
+
+/// Generic base class for SMT exprs
+class SMTExpr {
+public:
+ SMTExpr() = default;
+ virtual ~SMTExpr() = default;
+
+ bool operator<(const SMTExpr &Other) const {
+ llvm::FoldingSetNodeID ID1, ID2;
+ Profile(ID1);
+ Other.Profile(ID2);
+ return ID1 < ID2;
+ }
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
+
+ friend bool operator==(SMTExpr const &LHS, SMTExpr const &RHS) {
+ return LHS.equal_to(RHS);
+ }
+
+ virtual void print(raw_ostream &OS) const = 0;
+
+ LLVM_DUMP_METHOD void dump() const;
+
+protected:
+ /// Query the SMT solver and returns true if two sorts are equal (same kind
+ /// and bit width). This does not check if the two sorts are the same objects.
+ virtual bool equal_to(SMTExpr const &other) const = 0;
+};
+
+/// Shared pointer for SMTExprs, used by SMTSolver API.
+using SMTExprRef = const SMTExpr *;
+
+/// Generic base class for SMT Solvers
+///
+/// This class is responsible for wrapping all sorts and expression generation,
+/// through the mk* methods. It also provides methods to create SMT expressions
+/// straight from clang's AST, through the from* methods.
+class SMTSolver {
+public:
+ SMTSolver() = default;
+ virtual ~SMTSolver() = default;
+
+ LLVM_DUMP_METHOD void dump() const;
+
+ // Returns an appropriate floating-point sort for the given bitwidth.
+ SMTSortRef getFloatSort(unsigned BitWidth) {
+ switch (BitWidth) {
+ case 16:
+ return getFloat16Sort();
+ case 32:
+ return getFloat32Sort();
+ case 64:
+ return getFloat64Sort();
+ case 128:
+ return getFloat128Sort();
+ default:;
+ }
+ llvm_unreachable("Unsupported floating-point bitwidth!");
+ }
+
+ // Returns a boolean sort.
+ virtual SMTSortRef getBoolSort() = 0;
+
+ // Returns an appropriate bitvector sort for the given bitwidth.
+ virtual SMTSortRef getBitvectorSort(const unsigned BitWidth) = 0;
+
+ // Returns a floating-point sort of width 16
+ virtual SMTSortRef getFloat16Sort() = 0;
+
+ // Returns a floating-point sort of width 32
+ virtual SMTSortRef getFloat32Sort() = 0;
+
+ // Returns a floating-point sort of width 64
+ virtual SMTSortRef getFloat64Sort() = 0;
+
+ // Returns a floating-point sort of width 128
+ virtual SMTSortRef getFloat128Sort() = 0;
+
+ // Returns an appropriate sort for the given AST.
+ virtual SMTSortRef getSort(const SMTExprRef &AST) = 0;
+
+ /// Given a constraint, adds it to the solver
+ virtual void addConstraint(const SMTExprRef &Exp) const = 0;
+
+ /// Creates a bitvector addition operation
+ virtual SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector subtraction operation
+ virtual SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector multiplication operation
+ virtual SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed modulus operation
+ virtual SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned modulus operation
+ virtual SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed division operation
+ virtual SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned division operation
+ virtual SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector logical shift left operation
+ virtual SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector arithmetic shift right operation
+ virtual SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector logical shift right operation
+ virtual SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector negation operation
+ virtual SMTExprRef mkBVNeg(const SMTExprRef &Exp) = 0;
+
+ /// Creates a bitvector not operation
+ virtual SMTExprRef mkBVNot(const SMTExprRef &Exp) = 0;
+
+ /// Creates a bitvector xor operation
+ virtual SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector or operation
+ virtual SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector and operation
+ virtual SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned less-than operation
+ virtual SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed less-than operation
+ virtual SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned greater-than operation
+ virtual SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed greater-than operation
+ virtual SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned less-equal-than operation
+ virtual SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed less-equal-than operation
+ virtual SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector unsigned greater-equal-than operation
+ virtual SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a bitvector signed greater-equal-than operation
+ virtual SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a boolean not operation
+ virtual SMTExprRef mkNot(const SMTExprRef &Exp) = 0;
+
+ /// Creates a boolean equality operation
+ virtual SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a boolean and operation
+ virtual SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a boolean or operation
+ virtual SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a boolean ite operation
+ virtual SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T,
+ const SMTExprRef &F) = 0;
+
+ /// Creates a bitvector sign extension operation
+ virtual SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) = 0;
+
+ /// Creates a bitvector zero extension operation
+ virtual SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) = 0;
+
+ /// Creates a bitvector extract operation
+ virtual SMTExprRef mkBVExtract(unsigned High, unsigned Low,
+ const SMTExprRef &Exp) = 0;
+
+ /// Creates a bitvector concat operation
+ virtual SMTExprRef mkBVConcat(const SMTExprRef &LHS,
+ const SMTExprRef &RHS) = 0;
+
+ /// Creates a predicate that checks for overflow in a bitvector addition
+ /// operation
+ virtual SMTExprRef mkBVAddNoOverflow(const SMTExprRef &LHS,
+ const SMTExprRef &RHS,
+ bool isSigned) = 0;
+
+ /// Creates a predicate that checks for underflow in a signed bitvector
+ /// addition operation
+ virtual SMTExprRef mkBVAddNoUnderflow(const SMTExprRef &LHS,
+ const SMTExprRef &RHS) = 0;
+
+ /// Creates a predicate that checks for overflow in a signed bitvector
+ /// subtraction operation
+ virtual SMTExprRef mkBVSubNoOverflow(const SMTExprRef &LHS,
+ const SMTExprRef &RHS) = 0;
+
+ /// Creates a predicate that checks for underflow in a bitvector subtraction
+ /// operation
+ virtual SMTExprRef mkBVSubNoUnderflow(const SMTExprRef &LHS,
+ const SMTExprRef &RHS,
+ bool isSigned) = 0;
+
+ /// Creates a predicate that checks for overflow in a signed bitvector
+ /// division/modulus operation
+ virtual SMTExprRef mkBVSDivNoOverflow(const SMTExprRef &LHS,
+ const SMTExprRef &RHS) = 0;
+
+ /// Creates a predicate that checks for overflow in a bitvector negation
+ /// operation
+ virtual SMTExprRef mkBVNegNoOverflow(const SMTExprRef &Exp) = 0;
+
+ /// Creates a predicate that checks for overflow in a bitvector multiplication
+ /// operation
+ virtual SMTExprRef mkBVMulNoOverflow(const SMTExprRef &LHS,
+ const SMTExprRef &RHS,
+ bool isSigned) = 0;
+
+ /// Creates a predicate that checks for underflow in a signed bitvector
+ /// multiplication operation
+ virtual SMTExprRef mkBVMulNoUnderflow(const SMTExprRef &LHS,
+ const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point negation operation
+ virtual SMTExprRef mkFPNeg(const SMTExprRef &Exp) = 0;
+
+ /// Creates a floating-point isInfinite operation
+ virtual SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) = 0;
+
+ /// Creates a floating-point isNaN operation
+ virtual SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) = 0;
+
+ /// Creates a floating-point isNormal operation
+ virtual SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) = 0;
+
+ /// Creates a floating-point isZero operation
+ virtual SMTExprRef mkFPIsZero(const SMTExprRef &Exp) = 0;
+
+ /// Creates a floating-point multiplication operation
+ virtual SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point division operation
+ virtual SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point remainder operation
+ virtual SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point addition operation
+ virtual SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point subtraction operation
+ virtual SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point less-than operation
+ virtual SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point greater-than operation
+ virtual SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point less-than-or-equal operation
+ virtual SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point greater-than-or-equal operation
+ virtual SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point equality operation
+ virtual SMTExprRef mkFPEqual(const SMTExprRef &LHS,
+ const SMTExprRef &RHS) = 0;
+
+ /// Creates a floating-point conversion from floatint-point to floating-point
+ /// operation
+ virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0;
+
+ /// Creates a floating-point conversion from signed bitvector to
+ /// floatint-point operation
+ virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From,
+ const SMTSortRef &To) = 0;
+
+ /// Creates a floating-point conversion from unsigned bitvector to
+ /// floatint-point operation
+ virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From,
+ const SMTSortRef &To) = 0;
+
+ /// Creates a floating-point conversion from floatint-point to signed
+ /// bitvector operation
+ virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, unsigned ToWidth) = 0;
+
+ /// Creates a floating-point conversion from floatint-point to unsigned
+ /// bitvector operation
+ virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, unsigned ToWidth) = 0;
+
+ /// Creates a new symbol, given a name and a sort
+ virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0;
+
+ // Returns an appropriate floating-point rounding mode.
+ virtual SMTExprRef getFloatRoundingMode() = 0;
+
+ // If the a model is available, returns the value of a given bitvector symbol
+ virtual llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth,
+ bool isUnsigned) = 0;
+
+ // If the a model is available, returns the value of a given boolean symbol
+ virtual bool getBoolean(const SMTExprRef &Exp) = 0;
+
+ /// Constructs an SMTExprRef from a boolean.
+ virtual SMTExprRef mkBoolean(const bool b) = 0;
+
+ /// Constructs an SMTExprRef from a finite APFloat.
+ virtual SMTExprRef mkFloat(const llvm::APFloat Float) = 0;
+
+ /// Constructs an SMTExprRef from an APSInt and its bit width
+ virtual SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) = 0;
+
+ /// Given an expression, extract the value of this operand in the model.
+ virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) = 0;
+
+ /// Given an expression extract the value of this operand in the model.
+ virtual bool getInterpretation(const SMTExprRef &Exp,
+ llvm::APFloat &Float) = 0;
+
+ /// Check if the constraints are satisfiable
+ virtual Optional<bool> check() const = 0;
+
+ /// Push the current solver state
+ virtual void push() = 0;
+
+ /// Pop the previous solver state
+ virtual void pop(unsigned NumStates = 1) = 0;
+
+ /// Reset the solver and remove all constraints.
+ virtual void reset() = 0;
+
+ /// Checks if the solver supports floating-points.
+ virtual bool isFPSupported() = 0;
+
+ virtual void print(raw_ostream &OS) const = 0;
+};
+
+/// Shared pointer for SMTSolvers.
+using SMTSolverRef = std::shared_ptr<SMTSolver>;
+
+/// Convenience method to create and Z3Solver object
+SMTSolverRef CreateZ3Solver();
+
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/ScalableSize.h b/linux-x64/clang/include/llvm/Support/ScalableSize.h
new file mode 100644
index 0000000..96bf043
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/ScalableSize.h
@@ -0,0 +1,43 @@
+//===- 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/ScopedPrinter.h b/linux-x64/clang/include/llvm/Support/ScopedPrinter.h
index 1699655..88daedc 100644
--- a/linux-x64/clang/include/llvm/Support/ScopedPrinter.h
+++ b/linux-x64/clang/include/llvm/Support/ScopedPrinter.h
@@ -1,4 +1,4 @@
-//===-- ScopedPrinter.h ---------------------------------------------------===//
+//===-- ScopedPrinter.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.
diff --git a/linux-x64/clang/include/llvm/Support/Signposts.h b/linux-x64/clang/include/llvm/Support/Signposts.h
new file mode 100644
index 0000000..b5a8c3d
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/Signposts.h
@@ -0,0 +1,43 @@
+//===-- llvm/Support/Signposts.h - Interval debug annotations ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file Some OS's provide profilers that allow applications to provide custom
+/// annotations to the profiler. For example, on Xcode 10 and later 'signposts'
+/// can be emitted by the application and these will be rendered to the Points
+/// of Interest track on the instruments timeline.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_SIGNPOSTS_H
+#define LLVM_SUPPORT_SIGNPOSTS_H
+
+namespace llvm {
+class SignpostEmitterImpl;
+class Timer;
+
+/// Manages the emission of signposts into the recording method supported by
+/// the OS.
+class SignpostEmitter {
+ SignpostEmitterImpl *Impl;
+
+public:
+ SignpostEmitter();
+ ~SignpostEmitter();
+
+ 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);
+};
+
+} // end namespace llvm
+
+#endif // ifndef LLVM_SUPPORT_SIGNPOSTS_H
diff --git a/linux-x64/clang/include/llvm/Support/SwapByteOrder.h b/linux-x64/clang/include/llvm/Support/SwapByteOrder.h
index f58b4d9..06a447a 100644
--- a/linux-x64/clang/include/llvm/Support/SwapByteOrder.h
+++ b/linux-x64/clang/include/llvm/Support/SwapByteOrder.h
@@ -17,6 +17,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataTypes.h"
#include <cstddef>
+#include <type_traits>
#if defined(_MSC_VER) && !defined(_DEBUG)
#include <stdlib.h>
#endif
@@ -115,6 +116,13 @@
return out.d;
}
+template <typename T>
+inline typename std::enable_if<std::is_enum<T>::value, T>::type
+getSwappedBytes(T C) {
+ return static_cast<T>(
+ getSwappedBytes(static_cast<typename std::underlying_type<T>::type>(C)));
+}
+
template<typename T>
inline void swapByteOrder(T &Value) {
Value = getSwappedBytes(Value);
diff --git a/linux-x64/clang/include/llvm/Support/TargetOpcodes.def b/linux-x64/clang/include/llvm/Support/TargetOpcodes.def
index 6612274..fa02463 100644
--- a/linux-x64/clang/include/llvm/Support/TargetOpcodes.def
+++ b/linux-x64/clang/include/llvm/Support/TargetOpcodes.def
@@ -316,6 +316,9 @@
HANDLE_TARGET_OPCODE(G_ATOMICRMW_UMAX)
HANDLE_TARGET_OPCODE(G_ATOMICRMW_UMIN)
+// Generic atomic fence
+HANDLE_TARGET_OPCODE(G_FENCE)
+
/// Generic conditional branch instruction.
HANDLE_TARGET_OPCODE(G_BRCOND)
@@ -481,6 +484,12 @@
/// Generic FP absolute value.
HANDLE_TARGET_OPCODE(G_FABS)
+/// FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This does
+/// not require that X and Y have the same type, just that they are both
+/// floating point. X and the result must have the same type. FCOPYSIGN(f32,
+/// f64) is allowed.
+HANDLE_TARGET_OPCODE(G_FCOPYSIGN)
+
/// Generic FP canonicalize value.
HANDLE_TARGET_OPCODE(G_FCANONICALIZE)
@@ -491,9 +500,24 @@
/// *down* to the given alignment.
HANDLE_TARGET_OPCODE(G_PTR_MASK)
+/// Generic signed integer minimum.
+HANDLE_TARGET_OPCODE(G_SMIN)
+
+/// Generic signed integer maximum.
+HANDLE_TARGET_OPCODE(G_SMAX)
+
+/// Generic unsigned integer maximum.
+HANDLE_TARGET_OPCODE(G_UMIN)
+
+/// Generic unsigned integer maximum.
+HANDLE_TARGET_OPCODE(G_UMAX)
+
/// Generic BRANCH instruction. This is an unconditional branch.
HANDLE_TARGET_OPCODE(G_BR)
+/// Generic branch to jump table entry.
+HANDLE_TARGET_OPCODE(G_BRJT)
+
/// Generic insertelement.
HANDLE_TARGET_OPCODE(G_INSERT_VECTOR_ELT)
@@ -536,18 +560,27 @@
/// Floating point floor.
HANDLE_TARGET_OPCODE(G_FFLOOR)
+/// Floating point round to next integer.
+HANDLE_TARGET_OPCODE(G_FRINT)
+
+/// Floating point round to nearest integer.
+HANDLE_TARGET_OPCODE(G_FNEARBYINT)
+
/// Generic AddressSpaceCast.
HANDLE_TARGET_OPCODE(G_ADDRSPACE_CAST)
/// Generic block address
HANDLE_TARGET_OPCODE(G_BLOCK_ADDR)
+/// Generic jump table address
+HANDLE_TARGET_OPCODE(G_JUMP_TABLE)
+
// TODO: Add more generic opcodes as we move along.
/// Marker for the end of the generic opcode.
/// This is used to check if an opcode is in the range of the
/// generic opcodes.
-HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_BLOCK_ADDR)
+HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_JUMP_TABLE)
/// 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 7efd022..a7e1a75 100644
--- a/linux-x64/clang/include/llvm/Support/TargetParser.h
+++ b/linux-x64/clang/include/llvm/Support/TargetParser.h
@@ -121,10 +121,15 @@
GK_GFX902 = 61,
GK_GFX904 = 62,
GK_GFX906 = 63,
+ GK_GFX908 = 64,
GK_GFX909 = 65,
+ GK_GFX1010 = 71,
+ GK_GFX1011 = 72,
+ GK_GFX1012 = 73,
+
GK_AMDGCN_FIRST = GK_GFX600,
- GK_AMDGCN_LAST = GK_GFX909,
+ GK_AMDGCN_LAST = GK_GFX1012,
};
/// Instruction set architecture version.
diff --git a/linux-x64/clang/include/llvm/Support/TargetRegistry.h b/linux-x64/clang/include/llvm/Support/TargetRegistry.h
index 5854d57..bf75650 100644
--- a/linux-x64/clang/include/llvm/Support/TargetRegistry.h
+++ b/linux-x64/clang/include/llvm/Support/TargetRegistry.h
@@ -100,6 +100,11 @@
std::unique_ptr<MCObjectWriter> &&OW,
std::unique_ptr<MCCodeEmitter> &&CE,
bool RelaxAll);
+MCStreamer *createXCOFFStreamer(MCContext &Ctx,
+ std::unique_ptr<MCAsmBackend> &&TAB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&CE,
+ bool RelaxAll);
MCRelocationInfo *createMCRelocationInfo(const Triple &TT, MCContext &Ctx);
@@ -470,7 +475,7 @@
bool DWARFMustBeAtTheEnd) const {
MCStreamer *S;
switch (T.getObjectFormat()) {
- default:
+ case Triple::UnknownObjectFormat:
llvm_unreachable("Unknown object format");
case Triple::COFF:
assert(T.isOSWindows() && "only Windows COFF is supported");
@@ -504,6 +509,10 @@
S = createWasmStreamer(Ctx, std::move(TAB), std::move(OW),
std::move(Emitter), RelaxAll);
break;
+ case Triple::XCOFF:
+ S = createXCOFFStreamer(Ctx, std::move(TAB), std::move(OW),
+ std::move(Emitter), RelaxAll);
+ break;
}
if (ObjectTargetStreamerCtorFn)
ObjectTargetStreamerCtorFn(*S, STI);
diff --git a/linux-x64/clang/include/llvm/Support/Threading.h b/linux-x64/clang/include/llvm/Support/Threading.h
index 23b115f..46d413d 100644
--- a/linux-x64/clang/include/llvm/Support/Threading.h
+++ b/linux-x64/clang/include/llvm/Support/Threading.h
@@ -32,6 +32,9 @@
// implementations like libstdc++ are known to have problems on NetBSD,
// OpenBSD and PowerPC.
#define LLVM_THREADING_USE_STD_CALL_ONCE 1
+#elif defined(LLVM_ON_UNIX) && \
+ ((defined(__ppc__) || defined(__PPC__)) && defined(__LITTLE_ENDIAN__))
+#define LLVM_THREADING_USE_STD_CALL_ONCE 1
#else
#define LLVM_THREADING_USE_STD_CALL_ONCE 0
#endif
@@ -164,6 +167,19 @@
/// purposes, and as with setting a thread's name no indication of whether
/// the operation succeeded or failed is returned.
void get_thread_name(SmallVectorImpl<char> &Name);
+
+ enum class ThreadPriority {
+ Background = 0,
+ Default = 1,
+ };
+ /// If priority is Background tries to lower current threads priority such
+ /// that it does not affect foreground tasks significantly. Can be used for
+ /// long-running, latency-insensitive tasks to make sure cpu is not hogged by
+ /// this task.
+ /// If the priority is default tries to restore current threads priority to
+ /// default scheduling priority.
+ enum class SetThreadPriorityResult { FAILURE, SUCCESS };
+ SetThreadPriorityResult set_thread_priority(ThreadPriority Priority);
}
#endif
diff --git a/linux-x64/clang/include/llvm/Support/TimeProfiler.h b/linux-x64/clang/include/llvm/Support/TimeProfiler.h
new file mode 100644
index 0000000..72b6f71
--- /dev/null
+++ b/linux-x64/clang/include/llvm/Support/TimeProfiler.h
@@ -0,0 +1,76 @@
+//===- llvm/Support/TimeProfiler.h - Hierarchical Time Profiler -*- 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_TIME_PROFILER_H
+#define LLVM_SUPPORT_TIME_PROFILER_H
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+struct TimeTraceProfiler;
+extern TimeTraceProfiler *TimeTraceProfilerInstance;
+
+/// Initialize the time trace profiler.
+/// This sets up the global \p TimeTraceProfilerInstance
+/// variable to be the profiler instance.
+void timeTraceProfilerInitialize();
+
+/// Cleanup the time trace profiler, if it was initialized.
+void timeTraceProfilerCleanup();
+
+/// Is the time trace profiler enabled, i.e. initialized?
+inline bool timeTraceProfilerEnabled() {
+ return TimeTraceProfilerInstance != nullptr;
+}
+
+/// Write profiling data to output file.
+/// 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);
+
+/// 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
+/// matching End pair but they can nest.
+void timeTraceProfilerBegin(StringRef Name, StringRef Detail);
+void timeTraceProfilerBegin(StringRef Name,
+ llvm::function_ref<std::string()> Detail);
+
+/// Manually end the last time section.
+void timeTraceProfilerEnd();
+
+/// The TimeTraceScope is a helper class to call the begin and end functions
+/// of the time trace profiler. When the object is constructed, it begins
+/// the section; and when it is destroyed, it stops it. If the time profiler
+/// is not initialized, the overhead is a single branch.
+struct TimeTraceScope {
+
+ TimeTraceScope() = delete;
+ TimeTraceScope(const TimeTraceScope &) = delete;
+ TimeTraceScope &operator=(const TimeTraceScope &) = delete;
+ TimeTraceScope(TimeTraceScope &&) = delete;
+ TimeTraceScope &operator=(TimeTraceScope &&) = delete;
+
+ TimeTraceScope(StringRef Name, StringRef Detail) {
+ if (TimeTraceProfilerInstance != nullptr)
+ timeTraceProfilerBegin(Name, Detail);
+ }
+ TimeTraceScope(StringRef Name, llvm::function_ref<std::string()> Detail) {
+ if (TimeTraceProfilerInstance != nullptr)
+ timeTraceProfilerBegin(Name, Detail);
+ }
+ ~TimeTraceScope() {
+ if (TimeTraceProfilerInstance != nullptr)
+ timeTraceProfilerEnd();
+ }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/Support/Timer.h b/linux-x64/clang/include/llvm/Support/Timer.h
index 09f7422..76c9bc7 100644
--- a/linux-x64/clang/include/llvm/Support/Timer.h
+++ b/linux-x64/clang/include/llvm/Support/Timer.h
@@ -205,8 +205,9 @@
Description.assign(NewDescription.begin(), NewDescription.end());
}
- /// Print any started timers in this group.
- void print(raw_ostream &OS);
+ /// Print any started timers in this group, optionally resetting timers after
+ /// printing them.
+ void print(raw_ostream &OS, bool ResetAfterPrint = false);
/// Clear all timers in this group.
void clear();
@@ -233,7 +234,7 @@
friend void PrintStatisticsJSON(raw_ostream &OS);
void addTimer(Timer &T);
void removeTimer(Timer &T);
- void prepareToPrintList();
+ void prepareToPrintList(bool reset_time = false);
void PrintQueuedTimers(raw_ostream &OS);
void printJSONValue(raw_ostream &OS, const PrintRecord &R,
const char *suffix, double Value);
diff --git a/linux-x64/clang/include/llvm/Support/VCSRevision.h b/linux-x64/clang/include/llvm/Support/VCSRevision.h
index a6a8b9c..3ad6886 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 "60cf23e54e46c807513f7a36d0a7b777920b5881"
-#define LLVM_REPOSITORY "/buildbot/tmp/tmpCdFZ_W"
+#define LLVM_REVISION "e0caee08e5f09b374a27a676d04978c81fcb1928"
+#define LLVM_REPOSITORY "/buildbot/tmp/tmpyQwgD_"
diff --git a/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h b/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h
index 7b7c9f8..31c9e85 100644
--- a/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h
+++ b/linux-x64/clang/include/llvm/Support/VirtualFileSystem.h
@@ -58,15 +58,15 @@
Status() = default;
Status(const llvm::sys::fs::file_status &Status);
- Status(StringRef Name, llvm::sys::fs::UniqueID UID,
+ Status(const Twine &Name, llvm::sys::fs::UniqueID UID,
llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group,
uint64_t Size, llvm::sys::fs::file_type Type,
llvm::sys::fs::perms Perms);
/// Get a copy of a Status with a different name.
- static Status copyWithNewName(const Status &In, StringRef NewName);
+ static Status copyWithNewName(const Status &In, const Twine &NewName);
static Status copyWithNewName(const llvm::sys::fs::file_status &In,
- StringRef NewName);
+ const Twine &NewName);
/// Returns the name that should be used for this file or directory.
StringRef getName() const { return Name; }
@@ -298,8 +298,16 @@
/// Gets an \p vfs::FileSystem for the 'real' file system, as seen by
/// the operating system.
+/// The working directory is linked to the process's working directory.
+/// (This is usually thread-hostile).
IntrusiveRefCntPtr<FileSystem> getRealFileSystem();
+/// Create an \p vfs::FileSystem for the 'real' file system, as seen by
+/// the operating system.
+/// It has its own working directory, independent of (but initially equal to)
+/// that of the process.
+std::unique_ptr<FileSystem> createPhysicalFileSystem();
+
/// A file system that allows overlaying one \p AbstractFileSystem on top
/// of another.
///
@@ -335,15 +343,24 @@
using iterator = FileSystemList::reverse_iterator;
using const_iterator = FileSystemList::const_reverse_iterator;
+ using reverse_iterator = FileSystemList::iterator;
+ using const_reverse_iterator = FileSystemList::const_iterator;
/// Get an iterator pointing to the most recently added file system.
iterator overlays_begin() { return FSList.rbegin(); }
const_iterator overlays_begin() const { return FSList.rbegin(); }
- /// Get an iterator pointing one-past the least recently added file
- /// system.
+ /// Get an iterator pointing one-past the least recently added file system.
iterator overlays_end() { return FSList.rend(); }
const_iterator overlays_end() const { return FSList.rend(); }
+
+ /// Get an iterator pointing to the least recently added file system.
+ reverse_iterator overlays_rbegin() { return FSList.begin(); }
+ const_reverse_iterator overlays_rbegin() const { return FSList.begin(); }
+
+ /// Get an iterator pointing one-past the most recently added file system.
+ reverse_iterator overlays_rend() { return FSList.end(); }
+ const_reverse_iterator overlays_rend() const { return FSList.end(); }
};
/// By default, this delegates all calls to the underlying file system. This
diff --git a/linux-x64/clang/include/llvm/Support/X86DisassemblerDecoderCommon.h b/linux-x64/clang/include/llvm/Support/X86DisassemblerDecoderCommon.h
index 83c8671..baf842b 100644
--- a/linux-x64/clang/include/llvm/Support/X86DisassemblerDecoderCommon.h
+++ b/linux-x64/clang/include/llvm/Support/X86DisassemblerDecoderCommon.h
@@ -46,29 +46,23 @@
// Attributes of an instruction that must be known before the opcode can be
// processed correctly. Most of these indicate the presence of particular
// prefixes, but ATTR_64BIT is simply an attribute of the decoding context.
-#define ATTRIBUTE_BITS \
- ENUM_ENTRY(ATTR_NONE, 0x00) \
- ENUM_ENTRY(ATTR_64BIT, (0x1 << 0)) \
- ENUM_ENTRY(ATTR_XS, (0x1 << 1)) \
- ENUM_ENTRY(ATTR_XD, (0x1 << 2)) \
- ENUM_ENTRY(ATTR_REXW, (0x1 << 3)) \
- ENUM_ENTRY(ATTR_OPSIZE, (0x1 << 4)) \
- ENUM_ENTRY(ATTR_ADSIZE, (0x1 << 5)) \
- ENUM_ENTRY(ATTR_VEX, (0x1 << 6)) \
- ENUM_ENTRY(ATTR_VEXL, (0x1 << 7)) \
- ENUM_ENTRY(ATTR_EVEX, (0x1 << 8)) \
- ENUM_ENTRY(ATTR_EVEXL, (0x1 << 9)) \
- ENUM_ENTRY(ATTR_EVEXL2, (0x1 << 10)) \
- ENUM_ENTRY(ATTR_EVEXK, (0x1 << 11)) \
- ENUM_ENTRY(ATTR_EVEXKZ, (0x1 << 12)) \
- ENUM_ENTRY(ATTR_EVEXB, (0x1 << 13))
-
-#define ENUM_ENTRY(n, v) n = v,
enum attributeBits {
- ATTRIBUTE_BITS
- ATTR_max
+ ATTR_NONE = 0x00,
+ ATTR_64BIT = 0x1 << 0,
+ ATTR_XS = 0x1 << 1,
+ ATTR_XD = 0x1 << 2,
+ ATTR_REXW = 0x1 << 3,
+ ATTR_OPSIZE = 0x1 << 4,
+ ATTR_ADSIZE = 0x1 << 5,
+ ATTR_VEX = 0x1 << 6,
+ ATTR_VEXL = 0x1 << 7,
+ ATTR_EVEX = 0x1 << 8,
+ ATTR_EVEXL2 = 0x1 << 9,
+ ATTR_EVEXK = 0x1 << 10,
+ ATTR_EVEXKZ = 0x1 << 11,
+ ATTR_EVEXB = 0x1 << 12,
+ ATTR_max = 0x1 << 13,
};
-#undef ENUM_ENTRY
// Combinations of the above attributes that are relevant to instruction
// decode. Although other combinations are possible, they can be reduced to
@@ -393,6 +387,7 @@
ENUM_ENTRY(ENCODING_IRC, "Immediate for static rounding control") \
ENUM_ENTRY(ENCODING_Rv, "Register code of operand size added to the " \
"opcode byte") \
+ ENUM_ENTRY(ENCODING_CC, "Condition code encoded in opcode") \
ENUM_ENTRY(ENCODING_DUP, "Duplicate of another operand; ID is encoded " \
"in type") \
ENUM_ENTRY(ENCODING_SI, "Source index; encoded in OpSize/Adsize prefix") \
@@ -414,9 +409,6 @@
ENUM_ENTRY(TYPE_R32, "4-byte") \
ENUM_ENTRY(TYPE_R64, "8-byte") \
ENUM_ENTRY(TYPE_IMM, "immediate operand") \
- ENUM_ENTRY(TYPE_IMM3, "1-byte immediate operand between 0 and 7") \
- ENUM_ENTRY(TYPE_IMM5, "1-byte immediate operand between 0 and 31") \
- ENUM_ENTRY(TYPE_AVX512ICC, "1-byte immediate operand for AVX512 icmp") \
ENUM_ENTRY(TYPE_UIMM8, "1-byte unsigned immediate operand") \
ENUM_ENTRY(TYPE_M, "Memory operand") \
ENUM_ENTRY(TYPE_MVSIBX, "Memory operand using XMM index") \
@@ -431,6 +423,7 @@
ENUM_ENTRY(TYPE_YMM, "32-byte") \
ENUM_ENTRY(TYPE_ZMM, "64-byte") \
ENUM_ENTRY(TYPE_VK, "mask register") \
+ ENUM_ENTRY(TYPE_VK_PAIR, "mask register pair") \
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 fb82228..1749be3 100644
--- a/linux-x64/clang/include/llvm/Support/X86TargetParser.def
+++ b/linux-x64/clang/include/llvm/Support/X86TargetParser.def
@@ -33,6 +33,8 @@
#ifndef X86_CPU_TYPE
#define X86_CPU_TYPE(ARCHNAME, ENUM)
#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")
@@ -79,6 +81,8 @@
#define X86_CPU_SUBTYPE(ARCHNAME, ENUM)
#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")
@@ -98,14 +102,16 @@
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 ("cascadelake", INTEL_COREI7_CASCADELAKE)
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
#undef X86_CPU_SUBTYPE
@@ -160,5 +166,6 @@
X86_FEATURE (66, FEATURE_EM64T)
X86_FEATURE (67, FEATURE_CLFLUSHOPT)
X86_FEATURE (68, FEATURE_SHA)
+X86_FEATURE (69, FEATURE_AVX512BF16)
#undef X86_FEATURE_COMPAT
#undef X86_FEATURE
diff --git a/linux-x64/clang/include/llvm/Support/YAMLTraits.h b/linux-x64/clang/include/llvm/Support/YAMLTraits.h
index e991f3b..2185cd7 100644
--- a/linux-x64/clang/include/llvm/Support/YAMLTraits.h
+++ b/linux-x64/clang/include/llvm/Support/YAMLTraits.h
@@ -101,8 +101,7 @@
/// io.enumCase(value, "green", cGreen);
/// }
/// };
-template<typename T>
-struct ScalarEnumerationTraits {
+template <typename T, typename Enable = void> struct ScalarEnumerationTraits {
// Must provide:
// static void enumeration(IO &io, T &value);
};
@@ -118,8 +117,7 @@
/// io.bitSetCase(value, "round", flagRound);
/// }
/// };
-template<typename T>
-struct ScalarBitSetTraits {
+template <typename T, typename Enable = void> struct ScalarBitSetTraits {
// Must provide:
// static void bitset(IO &io, T &value);
};
@@ -145,8 +143,7 @@
/// }
/// static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
/// };
-template<typename T>
-struct ScalarTraits {
+template <typename T, typename Enable = void> struct ScalarTraits {
// Must provide:
//
// Function to write the value as a string:
@@ -863,8 +860,8 @@
mapOptionalWithContext(Key, Val, Ctx);
}
- template <typename T>
- void mapOptional(const char *Key, T &Val, const T &Default) {
+ template <typename T, typename DefaultT>
+ void mapOptional(const char *Key, T &Val, const DefaultT &Default) {
EmptyContext Ctx;
mapOptionalWithContext(Key, Val, Default, Ctx);
}
@@ -890,10 +887,13 @@
this->processKey(Key, Val, false, Ctx);
}
- template <typename T, typename Context>
- void mapOptionalWithContext(const char *Key, T &Val, const T &Default,
+ template <typename T, typename Context, typename DefaultT>
+ void mapOptionalWithContext(const char *Key, T &Val, const DefaultT &Default,
Context &Ctx) {
- this->processKeyWithDefault(Key, Val, Default, false, Ctx);
+ static_assert(std::is_convertible<DefaultT, T>::value,
+ "Default type must be implicitly convertible to value type!");
+ this->processKeyWithDefault(Key, Val, static_cast<const T &>(Default),
+ false, Ctx);
}
private:
@@ -977,7 +977,7 @@
bool DoClear;
if ( io.beginBitSetScalar(DoClear) ) {
if ( DoClear )
- Val = static_cast<T>(0);
+ Val = T();
ScalarBitSetTraits<T>::bitset(io, Val);
io.endBitSetScalar();
}
@@ -1242,12 +1242,14 @@
static QuotingType mustQuote(StringRef) { return QuotingType::None; }
};
-// For endian types, we just use the existing ScalarTraits for the underlying
-// type. This way endian aware types are supported whenever a ScalarTraits
-// is defined for the underlying type.
+// For endian types, we use existing scalar Traits class for the underlying
+// 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>> {
+struct ScalarTraits<
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>,
+ typename std::enable_if<has_ScalarTraits<value_type>::value>::type> {
using endian_type =
support::detail::packed_endian_specific_integral<value_type, endian,
alignment>;
@@ -1268,6 +1270,38 @@
}
};
+template <typename value_type, support::endianness endian, size_t alignment>
+struct ScalarEnumerationTraits<
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>,
+ typename std::enable_if<
+ has_ScalarEnumerationTraits<value_type>::value>::type> {
+ using endian_type =
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>;
+
+ static void enumeration(IO &io, endian_type &E) {
+ value_type V = E;
+ ScalarEnumerationTraits<value_type>::enumeration(io, V);
+ E = V;
+ }
+};
+
+template <typename value_type, support::endianness endian, size_t alignment>
+struct ScalarBitSetTraits<
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>,
+ typename std::enable_if<has_ScalarBitSetTraits<value_type>::value>::type> {
+ using endian_type =
+ support::detail::packed_endian_specific_integral<value_type, endian,
+ alignment>;
+ static void bitset(IO &io, endian_type &E) {
+ value_type V = E;
+ ScalarBitSetTraits<value_type>::bitset(io, V);
+ E = V;
+ }
+};
+
// Utility for use within MappingTraits<>::mapping() method
// to [de]normalize an object for use with YAML conversion.
template <typename TNorm, typename TFinal>
@@ -1871,6 +1905,11 @@
typename std::enable_if<CheckIsBool<
SequenceElementTraits<T>::flow>::value>::type>
: SequenceTraitsImpl<SmallVector<T, N>, SequenceElementTraits<T>::flow> {};
+template <typename T>
+struct SequenceTraits<SmallVectorImpl<T>,
+ typename std::enable_if<CheckIsBool<
+ SequenceElementTraits<T>::flow>::value>::type>
+ : SequenceTraitsImpl<SmallVectorImpl<T>, SequenceElementTraits<T>::flow> {};
// Sequences of fundamental types use flow formatting.
template <typename T>
diff --git a/linux-x64/clang/include/llvm/Support/raw_ostream.h b/linux-x64/clang/include/llvm/Support/raw_ostream.h
index 1eb13c7..48bb623 100644
--- a/linux-x64/clang/include/llvm/Support/raw_ostream.h
+++ b/linux-x64/clang/include/llvm/Support/raw_ostream.h
@@ -345,7 +345,7 @@
explicit raw_pwrite_stream(bool Unbuffered = false)
: raw_ostream(Unbuffered) {}
void pwrite(const char *Ptr, size_t Size, uint64_t Offset) {
-#ifndef NDBEBUG
+#ifndef NDEBUG
uint64_t Pos = tell();
// /dev/null always reports a pos of 0, so we cannot perform this check
// in that case.